stm32: Refactor bluetooth stack/hci/driver bindings.
This makes a cleaner separation between the: driver, HCI UART and BT stack. Also updated the naming to be more consistent (mp_bluetooth_hci_*). Work done in collaboration with Jim Mussared aka @jimmo.
This commit is contained in:
parent
c44d52f33e
commit
894c550c86
@ -3,7 +3,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Damien P. George
|
||||
* Copyright (c) 2019-2020 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -31,8 +31,7 @@
|
||||
#include "py/mphal.h"
|
||||
#include "pin_static_af.h"
|
||||
#include "uart.h"
|
||||
#include "cywbt.h"
|
||||
#include "nimble/hci_uart.h"
|
||||
#include "extmod/modbluetooth_hci.h"
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
|
||||
@ -42,7 +41,7 @@ extern const char fw_4343WA1_7_45_98_50_start;
|
||||
/******************************************************************************/
|
||||
// CYW BT HCI low-level driver
|
||||
|
||||
static void cywbt_wait_cts_low(void) {
|
||||
STATIC void cywbt_wait_cts_low(void) {
|
||||
mp_hal_pin_config(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
|
||||
for (int i = 0; i < 200; ++i) {
|
||||
if (mp_hal_pin_read(pyb_pin_BT_CTS) == 0) {
|
||||
@ -53,13 +52,13 @@ static void cywbt_wait_cts_low(void) {
|
||||
mp_hal_pin_config_alt_static(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_USART6_CTS);
|
||||
}
|
||||
|
||||
static int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
|
||||
uart_tx_strn(&bt_hci_uart_obj, (void*)buf, len);
|
||||
STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
|
||||
uart_tx_strn(&mp_bluetooth_hci_uart_obj, (void*)buf, len);
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
while (!uart_rx_any(&bt_hci_uart_obj)) {
|
||||
while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
buf[i] = uart_rx_char(&bt_hci_uart_obj);
|
||||
buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
|
||||
}
|
||||
|
||||
// expect a comand complete event (event 0x0e)
|
||||
@ -76,17 +75,17 @@ static int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
|
||||
|
||||
int sz = buf[2] - 3;
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
while (!uart_rx_any(&bt_hci_uart_obj)) {
|
||||
while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
buf[i] = uart_rx_char(&bt_hci_uart_obj);
|
||||
buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
|
||||
uint8_t *buf = bt_hci_cmd_buf;
|
||||
STATIC int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
|
||||
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
|
||||
buf[0] = 0x01;
|
||||
buf[1] = ocf;
|
||||
buf[2] = ogf << 2 | ocf >> 8;
|
||||
@ -97,19 +96,19 @@ static int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *para
|
||||
return cywbt_hci_cmd_raw(4 + param_len, buf);
|
||||
}
|
||||
|
||||
static void put_le16(uint8_t *buf, uint16_t val) {
|
||||
STATIC void put_le16(uint8_t *buf, uint16_t val) {
|
||||
buf[0] = val;
|
||||
buf[1] = val >> 8;
|
||||
}
|
||||
|
||||
static void put_le32(uint8_t *buf, uint32_t val) {
|
||||
STATIC void put_le32(uint8_t *buf, uint32_t val) {
|
||||
buf[0] = val;
|
||||
buf[1] = val >> 8;
|
||||
buf[2] = val >> 16;
|
||||
buf[3] = val >> 24;
|
||||
}
|
||||
|
||||
static int cywbt_set_baudrate(uint32_t baudrate) {
|
||||
STATIC int cywbt_set_baudrate(uint32_t baudrate) {
|
||||
uint8_t buf[6];
|
||||
put_le16(buf, 0);
|
||||
put_le32(buf + 2, baudrate);
|
||||
@ -117,12 +116,12 @@ static int cywbt_set_baudrate(uint32_t baudrate) {
|
||||
}
|
||||
|
||||
// download firmware
|
||||
static int cywbt_download_firmware(const uint8_t *firmware) {
|
||||
STATIC int cywbt_download_firmware(const uint8_t *firmware) {
|
||||
cywbt_hci_cmd(0x3f, 0x2e, 0, NULL);
|
||||
|
||||
bool last_packet = false;
|
||||
while (!last_packet) {
|
||||
uint8_t *buf = bt_hci_cmd_buf;
|
||||
uint8_t *buf = mp_bluetooth_hci_cmd_buf;
|
||||
memcpy(buf + 1, firmware, 3);
|
||||
firmware += 3;
|
||||
last_packet = buf[1] == 0x4e;
|
||||
@ -149,15 +148,15 @@ static int cywbt_download_firmware(const uint8_t *firmware) {
|
||||
cywbt_wait_cts_low();
|
||||
mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external)
|
||||
|
||||
nimble_hci_uart_set_baudrate(115200);
|
||||
mp_bluetooth_hci_uart_set_baudrate(115200);
|
||||
cywbt_set_baudrate(3000000);
|
||||
nimble_hci_uart_set_baudrate(3000000);
|
||||
mp_bluetooth_hci_uart_set_baudrate(3000000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cywbt_init(void) {
|
||||
// This is called from Nimble via hal_uart_config which will have already initialized the UART.
|
||||
int mp_bluetooth_hci_controller_init(void) {
|
||||
// This is called immediately after the UART is initialised during stack initialisation.
|
||||
|
||||
mp_hal_pin_output(pyb_pin_BT_REG_ON);
|
||||
mp_hal_pin_low(pyb_pin_BT_REG_ON);
|
||||
@ -172,11 +171,11 @@ int cywbt_init(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cywbt_activate(void) {
|
||||
int mp_bluetooth_hci_controller_activate(void) {
|
||||
uint8_t buf[256];
|
||||
|
||||
mp_hal_pin_low(pyb_pin_BT_REG_ON);
|
||||
nimble_hci_uart_set_baudrate(115200);
|
||||
mp_bluetooth_hci_uart_set_baudrate(115200);
|
||||
mp_hal_delay_ms(100);
|
||||
mp_hal_pin_high(pyb_pin_BT_REG_ON);
|
||||
cywbt_wait_cts_low();
|
||||
@ -186,7 +185,7 @@ int cywbt_activate(void) {
|
||||
|
||||
// Change baudrate
|
||||
cywbt_set_baudrate(3000000);
|
||||
nimble_hci_uart_set_baudrate(3000000);
|
||||
mp_bluetooth_hci_uart_set_baudrate(3000000);
|
||||
|
||||
cywbt_download_firmware((const uint8_t*)CYWBT_FW_ADDR);
|
||||
|
||||
@ -220,4 +219,57 @@ int cywbt_activate(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_controller_deactivate(void) {
|
||||
mp_hal_pin_low(pyb_pin_BT_REG_ON);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
STATIC uint32_t bt_sleep_ticks;
|
||||
#endif
|
||||
|
||||
int mp_bluetooth_hci_controller_sleep_maybe(void) {
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) {
|
||||
if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) {
|
||||
mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mp_bluetooth_hci_controller_woken(void) {
|
||||
#ifdef pyb_pin_BT_HOST_WAKE
|
||||
bool host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE);
|
||||
/*
|
||||
// this is just for info/tracing purposes
|
||||
static bool last_host_wake = false;
|
||||
if (host_wake != last_host_wake) {
|
||||
printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake);
|
||||
last_host_wake = host_wake;
|
||||
}
|
||||
*/
|
||||
return host_wake;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_controller_wakeup(void) {
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
bt_sleep_ticks = mp_hal_ticks_ms();
|
||||
|
||||
if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) {
|
||||
mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up
|
||||
// Use delay_us rather than delay_ms to prevent running the scheduler (which
|
||||
// might result in more BLE operations).
|
||||
mp_hal_delay_us(5000); // can't go lower than this
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -23,13 +23,33 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H
|
||||
#define MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H
|
||||
|
||||
extern uint8_t bt_hci_cmd_buf[4 + 256];
|
||||
extern pyb_uart_obj_t bt_hci_uart_obj;
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
|
||||
|
||||
int cywbt_init(void);
|
||||
int cywbt_activate(void);
|
||||
#include "uart.h"
|
||||
|
||||
#endif // MICROPY_INCLUDED_DRIVERS_CYW43_CYWBT_H
|
||||
// Optionally can be implemented by the driver.
|
||||
int mp_bluetooth_hci_controller_init(void);
|
||||
int mp_bluetooth_hci_controller_activate(void);
|
||||
int mp_bluetooth_hci_controller_deactivate(void);
|
||||
|
||||
// Tell the controller to go to sleep (e.g. on RX if we don't think we're expecting anything more).
|
||||
int mp_bluetooth_hci_controller_sleep_maybe(void);
|
||||
// True if the controller woke us up.
|
||||
bool mp_bluetooth_hci_controller_woken(void);
|
||||
// Wake up the controller (e.g. we're about to TX).
|
||||
int mp_bluetooth_hci_controller_wakeup(void);
|
||||
|
||||
// Storage and bindings that need to be implemented by the port.
|
||||
// These are used by the stack bindings (e.g. nimble/hal_uart.c)
|
||||
// as well as potentially the driver (e.g. cywbt.c).
|
||||
extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
|
||||
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
|
||||
|
||||
int mp_bluetooth_hci_uart_init(uint32_t port);
|
||||
int mp_bluetooth_hci_uart_activate(void);
|
||||
int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate);
|
||||
int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MODBLUETOOTH_HCI_H
|
@ -28,14 +28,11 @@
|
||||
#include "py/mphal.h"
|
||||
#include "pin_static_af.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "hal/hal_uart.h"
|
||||
#include "hci_uart.h"
|
||||
#include "extmod/nimble/hal/hal_uart.h"
|
||||
#include "extmod/modbluetooth_hci.h"
|
||||
#include "extmod/nimble/nimble/nimble_hci_uart.h"
|
||||
|
||||
#if MICROPY_BLUETOOTH_NIMBLE
|
||||
|
||||
/******************************************************************************/
|
||||
// Bindings Uart to Nimble
|
||||
uint8_t bt_hci_cmd_buf[4 + 256];
|
||||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
|
||||
static hal_uart_tx_cb_t hal_uart_tx_cb;
|
||||
static void *hal_uart_tx_arg;
|
||||
@ -51,9 +48,9 @@ int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_u
|
||||
}
|
||||
|
||||
int hal_uart_config(uint32_t port, uint32_t baudrate, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow) {
|
||||
nimble_hci_uart_configure(port);
|
||||
nimble_hci_uart_set_baudrate(baudrate);
|
||||
return nimble_hci_uart_activate();
|
||||
mp_bluetooth_hci_uart_init(port);
|
||||
mp_bluetooth_hci_uart_set_baudrate(baudrate);
|
||||
return mp_bluetooth_hci_uart_activate();
|
||||
}
|
||||
|
||||
void hal_uart_start_tx(uint32_t port) {
|
||||
@ -63,7 +60,7 @@ void hal_uart_start_tx(uint32_t port) {
|
||||
if (data == -1) {
|
||||
break;
|
||||
}
|
||||
bt_hci_cmd_buf[len++] = data;
|
||||
mp_bluetooth_hci_cmd_buf[len++] = data;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -74,15 +71,15 @@ void hal_uart_start_tx(uint32_t port) {
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
nimble_hci_uart_tx_strn((void*)bt_hci_cmd_buf, len);
|
||||
mp_bluetooth_nimble_hci_uart_tx_strn((void*)mp_bluetooth_hci_cmd_buf, len);
|
||||
}
|
||||
|
||||
int hal_uart_close(uint32_t port) {
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
void nimble_uart_process(void) {
|
||||
nimble_hci_uart_rx(hal_uart_rx_cb, hal_uart_rx_arg);
|
||||
void mp_bluetooth_nimble_hci_uart_process(void) {
|
||||
mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb, hal_uart_rx_arg);
|
||||
}
|
||||
|
||||
#endif // MICROPY_BLUETOOTH_NIMBLE
|
||||
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
@ -10,6 +10,7 @@
|
||||
typedef int (*hal_uart_tx_cb_t)(void *arg);
|
||||
typedef int (*hal_uart_rx_cb_t)(void *arg, uint8_t data);
|
||||
|
||||
// Called by NimBLE, implemented in hal_uart.c.
|
||||
int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg);
|
||||
int hal_uart_config(uint32_t port, uint32_t baud, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow);
|
||||
void hal_uart_start_tx(uint32_t port);
|
||||
|
@ -84,7 +84,7 @@ SRC_LIB += $(addprefix $(NIMBLE_LIB_DIR)/, \
|
||||
|
||||
EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
|
||||
nimble/npl_os.c \
|
||||
nimble/hci_uart.c \
|
||||
hal/hal_uart.c \
|
||||
)
|
||||
|
||||
INC += -I$(TOP)/$(NIMBLE_EXTMOD_DIR)
|
||||
|
@ -23,21 +23,18 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
|
||||
|
||||
// Extensions to extmod/modbluetooth_hci.h specific to NimBLE.
|
||||
|
||||
#include "extmod/nimble/hal/hal_uart.h"
|
||||
|
||||
// To be implemented by the port.
|
||||
// Helpers called from ports.
|
||||
void mp_bluetooth_nimble_hci_uart_process(void);
|
||||
|
||||
int nimble_hci_uart_configure(uint32_t port);
|
||||
// Must be provided by the port.
|
||||
void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg);
|
||||
void mp_bluetooth_nimble_hci_uart_tx_strn(const char *str, uint len);
|
||||
|
||||
// This will default to MICROPY_HW_BLE_UART_BAUDRATE, but can be updated later.
|
||||
int nimble_hci_uart_set_baudrate(uint32_t baudrate);
|
||||
|
||||
int nimble_hci_uart_activate(void);
|
||||
|
||||
void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg);
|
||||
void nimble_hci_uart_tx_strn(const char *str, uint len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
|
@ -29,6 +29,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_npl.h"
|
||||
#include "nimble/nimble_hci_uart.h"
|
||||
|
||||
#define DEBUG_OS_printf(...) //printf(__VA_ARGS__)
|
||||
#define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__)
|
||||
@ -234,8 +235,7 @@ ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout
|
||||
if (sem->count == 0) {
|
||||
uint32_t t0 = mp_hal_ticks_ms();
|
||||
while (sem->count == 0 && mp_hal_ticks_ms() - t0 < timeout) {
|
||||
extern void nimble_uart_process(void);
|
||||
nimble_uart_process();
|
||||
mp_bluetooth_nimble_hci_uart_process();
|
||||
if (sem->count != 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -460,10 +460,11 @@ endif
|
||||
|
||||
ifeq ($(MICROPY_PY_BLUETOOTH),1)
|
||||
|
||||
SRC_C += modbluetooth_hci.c
|
||||
|
||||
ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
|
||||
include $(TOP)/extmod/nimble/nimble.mk
|
||||
SRC_C += nimble.c
|
||||
SRC_C += nimble_hci_uart.c
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_PY_NETWORK_CYW43),1)
|
||||
|
@ -49,7 +49,7 @@
|
||||
#include "drivers/cyw43/cyw43.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_BLUETOOTH_NIMBLE
|
||||
#if MICROPY_PY_BLUETOOTH
|
||||
#include "extmod/modbluetooth.h"
|
||||
#endif
|
||||
|
||||
@ -539,9 +539,9 @@ void stm32_main(uint32_t reset_mode) {
|
||||
#endif
|
||||
systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper);
|
||||
#endif
|
||||
#if MICROPY_BLUETOOTH_NIMBLE
|
||||
extern void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms);
|
||||
systick_enable_dispatch(SYSTICK_DISPATCH_NIMBLE, mod_bluetooth_nimble_poll_wrapper);
|
||||
#if MICROPY_PY_BLUETOOTH
|
||||
extern void mp_bluetooth_hci_poll_wrapper(uint32_t ticks_ms);
|
||||
systick_enable_dispatch(SYSTICK_DISPATCH_BLUETOOTH_HCI, mp_bluetooth_hci_poll_wrapper);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
|
158
ports/stm32/modbluetooth_hci.c
Normal file
158
ports/stm32/modbluetooth_hci.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2020 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/modbluetooth_hci.h"
|
||||
#include "systick.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH
|
||||
|
||||
uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
|
||||
|
||||
// Must be provided by the stack bindings.
|
||||
extern void mp_bluetooth_hci_poll(void);
|
||||
|
||||
// Hook for pendsv poller to run this periodically every 128ms
|
||||
#define BLUETOOTH_HCI_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0)
|
||||
|
||||
// Called periodically (systick) or directly (e.g. uart irq).
|
||||
void mp_bluetooth_hci_poll_wrapper(uint32_t ticks_ms) {
|
||||
if (ticks_ms == 0 || BLUETOOTH_HCI_TICK(ticks_ms)) {
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_BLUETOOTH_HCI, mp_bluetooth_hci_poll);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(STM32WB)
|
||||
|
||||
/******************************************************************************/
|
||||
// HCI over IPCC
|
||||
|
||||
#include "rfcore.h"
|
||||
|
||||
int mp_bluetooth_hci_controller_deactivate(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_controller_sleep_maybe(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mp_bluetooth_hci_controller_woken(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_controller_wakeup(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_init(uint32_t port) {
|
||||
(void)port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_activate(void) {
|
||||
rfcore_ble_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) {
|
||||
(void)baudrate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
|
||||
MICROPY_PY_BLUETOOTH_ENTER
|
||||
rfcore_ble_hci_cmd(len, (const uint8_t *)buf);
|
||||
MICROPY_PY_BLUETOOTH_EXIT
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/******************************************************************************/
|
||||
// HCI over UART
|
||||
|
||||
#include "pendsv.h"
|
||||
#include "uart.h"
|
||||
|
||||
pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
|
||||
|
||||
static uint8_t hci_uart_rxbuf[512];
|
||||
|
||||
mp_obj_t mp_uart_interrupt(mp_obj_t self_in) {
|
||||
// New HCI data, schedule mp_bluetooth_hci_poll to make the stack handle it.
|
||||
mp_bluetooth_hci_poll_wrapper(0);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_uart_interrupt_obj, mp_uart_interrupt);
|
||||
|
||||
int mp_bluetooth_hci_uart_init(uint32_t port) {
|
||||
// bits (8), stop (1), parity (none) and flow (rts/cts) are assumed to match MYNEWT_VAL_BLE_HCI_UART_ constants in syscfg.h.
|
||||
mp_bluetooth_hci_uart_obj.base.type = &pyb_uart_type;
|
||||
mp_bluetooth_hci_uart_obj.uart_id = port;
|
||||
mp_bluetooth_hci_uart_obj.is_static = true;
|
||||
mp_bluetooth_hci_uart_obj.timeout = 2;
|
||||
mp_bluetooth_hci_uart_obj.timeout_char = 2;
|
||||
MP_STATE_PORT(pyb_uart_obj_all)[mp_bluetooth_hci_uart_obj.uart_id - 1] = &mp_bluetooth_hci_uart_obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) {
|
||||
uart_init(&mp_bluetooth_hci_uart_obj, baudrate, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, UART_HWCONTROL_RTS | UART_HWCONTROL_CTS);
|
||||
uart_set_rxbuf(&mp_bluetooth_hci_uart_obj, sizeof(hci_uart_rxbuf), hci_uart_rxbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_activate(void) {
|
||||
// Interrupt on RX chunk received (idle)
|
||||
// Trigger stack poll when this happens
|
||||
mp_obj_t uart_irq_fn = mp_load_attr(MP_OBJ_FROM_PTR(&mp_bluetooth_hci_uart_obj), MP_QSTR_irq);
|
||||
mp_obj_t uargs[] = {
|
||||
MP_OBJ_FROM_PTR(&mp_uart_interrupt_obj),
|
||||
MP_OBJ_NEW_SMALL_INT(UART_FLAG_IDLE),
|
||||
mp_const_true,
|
||||
};
|
||||
mp_call_function_n_kw(uart_irq_fn, 3, 0, uargs);
|
||||
|
||||
mp_bluetooth_hci_controller_init();
|
||||
mp_bluetooth_hci_controller_activate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
|
||||
mp_bluetooth_hci_controller_wakeup();
|
||||
uart_tx_strn(&mp_bluetooth_hci_uart_obj, (void *)buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // defined(STM32WB)
|
||||
|
||||
#endif // MICROPY_PY_BLUETOOTH
|
@ -4,6 +4,7 @@
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Jim Mussared
|
||||
* Copyright (c) 2020 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@ -30,37 +31,26 @@
|
||||
|
||||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
|
||||
#include "systick.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
#include "transport/uart/ble_hci_uart.h"
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
#include "extmod/modbluetooth_hci.h"
|
||||
#include "extmod/nimble/modbluetooth_nimble.h"
|
||||
#include "extmod/nimble/nimble/nimble_hci_uart.h"
|
||||
|
||||
extern void nimble_uart_process(void);
|
||||
extern void os_eventq_run_all(void);
|
||||
extern void os_callout_process(void);
|
||||
|
||||
// Hook for pendsv poller to run this periodically every 128ms
|
||||
#define NIMBLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0)
|
||||
|
||||
void nimble_poll(void) {
|
||||
void mp_bluetooth_hci_poll(void) {
|
||||
if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
nimble_uart_process();
|
||||
mp_bluetooth_nimble_hci_uart_process();
|
||||
os_callout_process();
|
||||
os_eventq_run_all();
|
||||
}
|
||||
|
||||
void mod_bluetooth_nimble_poll_wrapper(uint32_t ticks_ms) {
|
||||
if (NIMBLE_TICK(ticks_ms)) {
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_bluetooth_nimble_port_preinit(void) {
|
||||
MP_STATE_PORT(bluetooth_nimble_memory) = NULL;
|
||||
ble_hci_uart_init();
|
||||
@ -70,13 +60,46 @@ void mp_bluetooth_nimble_port_postinit(void) {
|
||||
}
|
||||
|
||||
void mp_bluetooth_nimble_port_deinit(void) {
|
||||
#ifdef pyb_pin_BT_REG_ON
|
||||
mp_hal_pin_low(pyb_pin_BT_REG_ON);
|
||||
#endif
|
||||
mp_bluetooth_hci_controller_deactivate();
|
||||
}
|
||||
|
||||
void mp_bluetooth_nimble_port_start(void) {
|
||||
ble_hs_start();
|
||||
}
|
||||
|
||||
#if defined(STM32WB)
|
||||
|
||||
#include "rfcore.h"
|
||||
|
||||
void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
|
||||
// Protect in case it's called from ble_npl_sem_pend at thread-level
|
||||
MICROPY_PY_LWIP_ENTER
|
||||
rfcore_ble_check_msg(rx_cb, rx_arg);
|
||||
MICROPY_PY_LWIP_EXIT
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
|
||||
bool host_wake = mp_bluetooth_hci_controller_woken();
|
||||
|
||||
while (uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
|
||||
uint8_t data = uart_rx_char(&mp_bluetooth_hci_uart_obj);
|
||||
//printf("UART RX: %02x\n", data);
|
||||
rx_cb(rx_arg, data);
|
||||
}
|
||||
|
||||
if (host_wake) {
|
||||
mp_bluetooth_hci_controller_sleep_maybe();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // defined(STM32WB)
|
||||
|
||||
void mp_bluetooth_nimble_hci_uart_tx_strn(const char *str, uint len) {
|
||||
mp_bluetooth_hci_uart_write((const uint8_t *)str, len);
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018-2019 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/nimble/nimble/hci_uart.h"
|
||||
|
||||
#if MICROPY_BLUETOOTH_NIMBLE
|
||||
|
||||
#if defined(STM32WB)
|
||||
|
||||
/******************************************************************************/
|
||||
// HCI over IPCC
|
||||
|
||||
#include "rfcore.h"
|
||||
|
||||
int nimble_hci_uart_configure(uint32_t port) {
|
||||
(void)port;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_hci_uart_set_baudrate(uint32_t baudrate) {
|
||||
(void)baudrate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_hci_uart_activate(void) {
|
||||
rfcore_ble_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
|
||||
// Protect in case it's called from ble_npl_sem_pend at thread-level
|
||||
MICROPY_PY_LWIP_ENTER
|
||||
rfcore_ble_check_msg(rx_cb, rx_arg);
|
||||
MICROPY_PY_LWIP_EXIT
|
||||
}
|
||||
|
||||
void nimble_hci_uart_tx_strn(const char *str, uint len) {
|
||||
MICROPY_PY_LWIP_ENTER
|
||||
rfcore_ble_hci_cmd(len, (const uint8_t *)str);
|
||||
MICROPY_PY_LWIP_EXIT
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/******************************************************************************/
|
||||
// HCI over UART
|
||||
|
||||
#include "pendsv.h"
|
||||
#include "uart.h"
|
||||
#include "drivers/cyw43/cywbt.h"
|
||||
|
||||
pyb_uart_obj_t bt_hci_uart_obj;
|
||||
static uint8_t hci_uart_rxbuf[512];
|
||||
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
static uint32_t bt_sleep_ticks;
|
||||
#endif
|
||||
|
||||
extern void nimble_poll(void);
|
||||
|
||||
mp_obj_t mp_uart_interrupt(mp_obj_t self_in) {
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_NIMBLE, nimble_poll);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_uart_interrupt_obj, mp_uart_interrupt);
|
||||
|
||||
int nimble_hci_uart_set_baudrate(uint32_t baudrate) {
|
||||
uart_init(&bt_hci_uart_obj, baudrate, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, UART_HWCONTROL_RTS | UART_HWCONTROL_CTS);
|
||||
uart_set_rxbuf(&bt_hci_uart_obj, sizeof(hci_uart_rxbuf), hci_uart_rxbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_hci_uart_configure(uint32_t port) {
|
||||
// bits (8), stop (1), parity (none) and flow (rts/cts) are assumed to match MYNEWT_VAL_BLE_HCI_UART_ constants in syscfg.h.
|
||||
bt_hci_uart_obj.base.type = &pyb_uart_type;
|
||||
bt_hci_uart_obj.uart_id = port;
|
||||
bt_hci_uart_obj.is_static = true;
|
||||
bt_hci_uart_obj.timeout = 2;
|
||||
bt_hci_uart_obj.timeout_char = 2;
|
||||
MP_STATE_PORT(pyb_uart_obj_all)[bt_hci_uart_obj.uart_id - 1] = &bt_hci_uart_obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nimble_hci_uart_activate(void) {
|
||||
// Interrupt on RX chunk received (idle)
|
||||
// Trigger nimble poll when this happens
|
||||
mp_obj_t uart_irq_fn = mp_load_attr(MP_OBJ_FROM_PTR(&bt_hci_uart_obj), MP_QSTR_irq);
|
||||
mp_obj_t uargs[] = {
|
||||
MP_OBJ_FROM_PTR(&mp_uart_interrupt_obj),
|
||||
MP_OBJ_NEW_SMALL_INT(UART_FLAG_IDLE),
|
||||
mp_const_true,
|
||||
};
|
||||
mp_call_function_n_kw(uart_irq_fn, 3, 0, uargs);
|
||||
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
cywbt_init();
|
||||
cywbt_activate();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg) {
|
||||
#ifdef pyb_pin_BT_HOST_WAKE
|
||||
int host_wake = 0;
|
||||
host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE);
|
||||
/*
|
||||
// this is just for info/tracing purposes
|
||||
static int last_host_wake = 0;
|
||||
if (host_wake != last_host_wake) {
|
||||
printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake);
|
||||
last_host_wake = host_wake;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
while (uart_rx_any(&bt_hci_uart_obj)) {
|
||||
uint8_t data = uart_rx_char(&bt_hci_uart_obj);
|
||||
//printf("UART RX: %02x\n", data);
|
||||
rx_cb(rx_arg, data);
|
||||
}
|
||||
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
if (host_wake == 1 && mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) {
|
||||
if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) {
|
||||
//printf("BT SLEEP\n");
|
||||
mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void nimble_hci_uart_tx_strn(const char *str, uint len) {
|
||||
#ifdef pyb_pin_BT_DEV_WAKE
|
||||
bt_sleep_ticks = mp_hal_ticks_ms();
|
||||
|
||||
if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) {
|
||||
//printf("BT WAKE for TX\n");
|
||||
mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up
|
||||
// Use delay_us rather than delay_ms to prevent running the scheduler (which
|
||||
// might result in more BLE operations).
|
||||
mp_hal_delay_us(5000); // can't go lower than this
|
||||
}
|
||||
#endif
|
||||
|
||||
uart_tx_strn(&bt_hci_uart_obj, str, len);
|
||||
}
|
||||
|
||||
#endif // defined(STM32WB)
|
||||
|
||||
#endif // MICROPY_BLUETOOTH_NIMBLE
|
@ -34,8 +34,8 @@ enum {
|
||||
PENDSV_DISPATCH_CYW43,
|
||||
#endif
|
||||
#endif
|
||||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
PENDSV_DISPATCH_NIMBLE,
|
||||
#if MICROPY_PY_BLUETOOTH
|
||||
PENDSV_DISPATCH_BLUETOOTH_HCI,
|
||||
#endif
|
||||
PENDSV_DISPATCH_MAX
|
||||
};
|
||||
|
@ -37,8 +37,8 @@ enum {
|
||||
#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP
|
||||
SYSTICK_DISPATCH_LWIP,
|
||||
#endif
|
||||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
|
||||
SYSTICK_DISPATCH_NIMBLE,
|
||||
#if MICROPY_PY_BLUETOOTH
|
||||
SYSTICK_DISPATCH_BLUETOOTH_HCI,
|
||||
#endif
|
||||
SYSTICK_DISPATCH_MAX
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user