diff --git a/extmod/nimble/bsp/bsp.h b/extmod/nimble/bsp/bsp.h new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/extmod/nimble/bsp/bsp.h @@ -0,0 +1 @@ +// empty diff --git a/extmod/nimble/hal/hal_gpio.h b/extmod/nimble/hal/hal_gpio.h new file mode 100644 index 0000000000..8b1a393741 --- /dev/null +++ b/extmod/nimble/hal/hal_gpio.h @@ -0,0 +1 @@ +// empty diff --git a/extmod/nimble/hal/hal_uart.h b/extmod/nimble/hal/hal_uart.h new file mode 100644 index 0000000000..294dfb50dd --- /dev/null +++ b/extmod/nimble/hal/hal_uart.h @@ -0,0 +1,18 @@ +#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H +#define MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H + +#include + +#define SYSINIT_PANIC_ASSERT_MSG(cond, msg) + +#define HAL_UART_PARITY_NONE (0) + +typedef int (*hal_uart_tx_cb_t)(void *arg); +typedef int (*hal_uart_rx_cb_t)(void *arg, uint8_t data); + +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); +int hal_uart_close(uint32_t port); + +#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk new file mode 100644 index 0000000000..274fcdb9f3 --- /dev/null +++ b/extmod/nimble/nimble.mk @@ -0,0 +1,96 @@ +# Makefile directives for Apache mynewt nimble BLE component + +ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1) + +NIMBLE_LIB_DIR = lib/mynewt-nimble +NIMBLE_EXTMOD_DIR = extmod/nimble + +SRC_LIB += $(addprefix $(NIMBLE_LIB_DIR)/, \ + $(addprefix ext/tinycrypt/src/, \ + aes_encrypt.c \ + cmac_mode.c \ + ecc.c \ + ecc_dh.c \ + utils.c \ + ) \ + nimble/host/services/gap/src/ble_svc_gap.c \ + nimble/host/services/gatt/src/ble_svc_gatt.c \ + $(addprefix nimble/host/src/, \ + ble_att.c \ + ble_att_clt.c \ + ble_att_cmd.c \ + ble_att_svr.c \ + ble_eddystone.c \ + ble_gap.c \ + ble_gattc.c \ + ble_gatts.c \ + ble_hs_adv.c \ + ble_hs_atomic.c \ + ble_hs.c \ + ble_hs_cfg.c \ + ble_hs_conn.c \ + ble_hs_dbg.c \ + ble_hs_flow.c \ + ble_hs_hci.c \ + ble_hs_hci_cmd.c \ + ble_hs_hci_evt.c \ + ble_hs_hci_util.c \ + ble_hs_id.c \ + ble_hs_log.c \ + ble_hs_mbuf.c \ + ble_hs_misc.c \ + ble_hs_mqueue.c \ + ble_hs_pvcy.c \ + ble_hs_startup.c \ + ble_hs_stop.c \ + ble_ibeacon.c \ + ble_l2cap.c \ + ble_l2cap_coc.c \ + ble_l2cap_sig.c \ + ble_l2cap_sig_cmd.c \ + ble_monitor.c \ + ble_sm_alg.c \ + ble_sm.c \ + ble_sm_cmd.c \ + ble_sm_lgcy.c \ + ble_sm_sc.c \ + ble_store.c \ + ble_store_util.c \ + ble_uuid.c \ + ) \ + nimble/host/store/ram/src/ble_store_ram.c \ + nimble/host/util/src/addr.c \ + nimble/transport/uart/src/ble_hci_uart.c \ + $(addprefix porting/nimble/src/, \ + endian.c \ + mem.c \ + nimble_port.c \ + os_mbuf.c \ + os_mempool.c \ + os_msys_init.c \ + ) \ + ) + +EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \ + nimble/misc.c \ + nimble/npl_os.c \ + nimble/hci_uart.c \ + ) + +CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1 + +INC += -I$(TOP)/$(NIMBLE_EXTMOD_DIR) +INC += -I$(TOP)/$(NIMBLE_LIB_DIR) +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/ext/tinycrypt/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gap/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gatt/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/store/ram/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/util/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/transport/uart/include +INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/porting/nimble/include + +$(BUILD)/$(NIMBLE_LIB_DIR)/%.o: CFLAGS += -Wno-maybe-uninitialized -Wno-pointer-arith -Wno-unused-but-set-variable -Wno-format + +endif diff --git a/extmod/nimble/nimble/hci_uart.c b/extmod/nimble/nimble/hci_uart.c new file mode 100644 index 0000000000..801291def4 --- /dev/null +++ b/extmod/nimble/nimble/hci_uart.c @@ -0,0 +1,122 @@ +/* + * 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 "pin_static_af.h" +#include "nimble/ble.h" +#include "hal/hal_uart.h" +#include "hci_uart.h" + +#if MICROPY_BLUETOOTH_NIMBLE + +/******************************************************************************/ +// Bindings Uart to Nimble +uint8_t bt_hci_cmd_buf[4 + 256]; + +static hal_uart_tx_cb_t hal_uart_tx_cb; +static void *hal_uart_tx_arg; +static hal_uart_rx_cb_t hal_uart_rx_cb; +static void *hal_uart_rx_arg; + +static uint32_t bt_sleep_ticks; + +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) { + hal_uart_tx_cb = tx_cb; + hal_uart_tx_arg = tx_arg; + hal_uart_rx_cb = rx_cb; + hal_uart_rx_arg = rx_arg; + return 0; // success +} + +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(); +} + +void hal_uart_start_tx(uint32_t port) { + size_t len = 0; + for (;;) { + int data = hal_uart_tx_cb(hal_uart_tx_arg); + if (data == -1) { + break; + } + bt_hci_cmd_buf[len++] = data; + } + + #if 0 + printf("[% 8d] BTUTX: %02x", mp_hal_ticks_ms(), hci_cmd_buf[0]); + for (int i = 1; i < len; ++i) { + printf(":%02x", hci_cmd_buf[i]); + } + printf("\n"); + #endif + + bt_sleep_ticks = mp_hal_ticks_ms(); + + #ifdef pyb_pin_BT_DEV_WAKE + 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 + mp_hal_delay_ms(5); // can't go lower than this + } + #endif + + nimble_hci_uart_tx_strn((void*)bt_hci_cmd_buf, len); +} + +int hal_uart_close(uint32_t port) { + return 0; // success +} + +void nimble_uart_process(void) { + int host_wake = 0; + #ifdef pyb_pin_BT_HOST_WAKE + host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE); + #endif + /* + // 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; + } + */ + while (nimble_hci_uart_rx_any()) { + uint8_t data = nimble_hci_uart_rx_char(); + //printf("UART RX: %02x\n", data); + hal_uart_rx_cb(hal_uart_rx_arg, data); + } + 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 // MICROPY_BLUETOOTH_NIMBLE diff --git a/extmod/nimble/nimble/hci_uart.h b/extmod/nimble/nimble/hci_uart.h new file mode 100644 index 0000000000..e184210830 --- /dev/null +++ b/extmod/nimble/nimble/hci_uart.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 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. + */ +#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H +#define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H + +// To be implemented by the port. + +int nimble_hci_uart_configure(uint32_t port); + +// 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); + +mp_uint_t nimble_hci_uart_rx_any(); +int nimble_hci_uart_rx_char(); +void nimble_hci_uart_tx_strn(const char *str, uint len); + +#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_HCI_UART_H diff --git a/extmod/nimble/nimble/misc.c b/extmod/nimble/nimble/misc.c new file mode 100644 index 0000000000..0e7d8a42a8 --- /dev/null +++ b/extmod/nimble/nimble/misc.c @@ -0,0 +1,44 @@ +/* + * 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" + +#if MICROPY_BLUETOOTH_NIMBLE + +/******************************************************************************/ +// Misc functions needed by Nimble + +#include + +int nimble_sprintf(char *str, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int ret = vsnprintf(str, 65535, fmt, ap); + va_end(ap); + return ret; +} + +#endif diff --git a/extmod/nimble/nimble/nimble_npl_os.h b/extmod/nimble/nimble/nimble_npl_os.h new file mode 100644 index 0000000000..3d886fedb5 --- /dev/null +++ b/extmod/nimble/nimble/nimble_npl_os.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H +#define MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H + +#include + +#define BLE_NPL_OS_ALIGNMENT (4) +#define BLE_NPL_TIME_FOREVER (0xffffffff) + +typedef uint32_t ble_npl_time_t; +typedef int32_t ble_npl_stime_t; + +struct ble_npl_event { + ble_npl_event_fn *fn; + void *arg; + struct ble_npl_event *prev; + struct ble_npl_event *next; +}; + +struct ble_npl_eventq { + struct ble_npl_event *head; + struct ble_npl_eventq *nextq; +}; + +struct ble_npl_callout { + bool active; + uint32_t ticks; + struct ble_npl_eventq *evq; + struct ble_npl_event ev; + struct ble_npl_callout *nextc; +}; + +struct ble_npl_mutex { + volatile uint8_t locked; +}; + +struct ble_npl_sem { + volatile uint16_t count; +}; + +#endif // MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H diff --git a/extmod/nimble/nimble/npl_os.c b/extmod/nimble/nimble/npl_os.c new file mode 100644 index 0000000000..0f852c8780 --- /dev/null +++ b/extmod/nimble/nimble/npl_os.c @@ -0,0 +1,307 @@ +/* + * 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 +#include "py/mphal.h" +#include "nimble/nimble_npl.h" + +#define DEBUG_OS_printf(...) //printf(__VA_ARGS__) +#define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) +#define DEBUG_MUTEX_printf(...) //printf(__VA_ARGS__) +#define DEBUG_SEM_printf(...) //printf(__VA_ARGS__) +#define DEBUG_CALLOUT_printf(...) //printf(__VA_ARGS__) +#define DEBUG_TIME_printf(...) //printf(__VA_ARGS__) +#define DEBUG_CRIT_printf(...) //printf(__VA_ARGS__) + +bool ble_npl_os_started(void) { + DEBUG_OS_printf("ble_npl_os_started\n"); + return true; +} + +void *ble_npl_get_current_task_id(void) { + DEBUG_OS_printf("ble_npl_get_current_task_id\n"); + return NULL; +} + +/******************************************************************************/ +// EVENTQ + +struct ble_npl_eventq *global_eventq = NULL; + +void os_eventq_run_all(void) { + for (struct ble_npl_eventq *evq = global_eventq; evq != NULL; evq = evq->nextq) { + while (evq->head != NULL) { + struct ble_npl_event *ev = evq->head; + evq->head = ev->next; + if (ev->next) { + ev->next->prev = NULL; + ev->next = NULL; + } + ev->prev = NULL; + DEBUG_EVENT_printf("event_run(%p)\n", ev); + ev->fn(ev); + DEBUG_EVENT_printf("event_run(%p) done\n", ev); + } + } +} + +void ble_npl_eventq_init(struct ble_npl_eventq *evq) { + DEBUG_EVENT_printf("ble_npl_eventq_init(%p)\n", evq); + evq->head = NULL; + struct ble_npl_eventq **evq2; + for (evq2 = &global_eventq; *evq2 != NULL; evq2 = &(*evq2)->nextq) { + } + *evq2 = evq; + evq->nextq = NULL; +} + +void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { + DEBUG_EVENT_printf("ble_npl_eventq_put(%p, %p (%p, %p))\n", evq, ev, ev->fn, ev->arg); + ev->next = NULL; + if (evq->head == NULL) { + evq->head = ev; + ev->prev = NULL; + } else { + struct ble_npl_event *ev2 = evq->head; + while (true) { + if (ev2 == ev) { + DEBUG_EVENT_printf(" --> already in queue\n"); + return; + } + if (ev2->next == NULL) { + break; + } + DEBUG_EVENT_printf(" --> %p\n", ev2->next); + ev2 = ev2->next; + } + ev2->next = ev; + ev->prev = ev2; + } +} + +void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) { + DEBUG_EVENT_printf("ble_npl_event_init(%p, %p, %p)\n", ev, fn, arg); + ev->fn = fn; + ev->arg = arg; + ev->next = NULL; +} + +void *ble_npl_event_get_arg(struct ble_npl_event *ev) { + DEBUG_EVENT_printf("ble_npl_event_get_arg(%p) -> %p\n", ev, ev->arg); + return ev->arg; +} + +void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) { + DEBUG_EVENT_printf("ble_npl_event_set_arg(%p, %p)\n", ev, arg); + ev->arg = arg; +} + +/******************************************************************************/ +// MUTEX + +ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu) { + DEBUG_MUTEX_printf("ble_npl_mutex_init(%p)\n", mu); + mu->locked = 0; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) { + DEBUG_MUTEX_printf("ble_npl_mutex_pend(%p, %u) locked=%u\n", mu, (uint)timeout, (uint)mu->locked); + mu->locked = 1; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu) { + DEBUG_MUTEX_printf("ble_npl_mutex_release(%p) locked=%u\n", mu, (uint)mu->locked); + mu->locked = 0; + return BLE_NPL_OK; +} + +/******************************************************************************/ +// SEM + +ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { + DEBUG_SEM_printf("ble_npl_sem_init(%p, %u)\n", sem, (uint)tokens); + sem->count = tokens; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { + DEBUG_SEM_printf("ble_npl_sem_pend(%p, %u) count=%u\n", sem, (uint)timeout, (uint)sem->count); + 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(); + if (sem->count != 0) { + break; + } + __WFI(); + } + if (sem->count == 0) { + printf("timeout\n"); + return BLE_NPL_TIMEOUT; + } + DEBUG_SEM_printf("got response in %u ms\n", (int)(mp_hal_ticks_ms() - t0)); + } + sem->count -= 1; + return BLE_NPL_OK; +} + +ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem) { + DEBUG_SEM_printf("ble_npl_sem_release(%p)\n", sem); + sem->count += 1; + return BLE_NPL_OK; +} + +uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem) { + DEBUG_SEM_printf("ble_npl_sem_get_count(%p)\n", sem); + return sem->count; +} + +/******************************************************************************/ +// CALLOUT + +static struct ble_npl_callout *global_callout = NULL; + +void os_callout_process(void) { + uint32_t tnow = mp_hal_ticks_ms(); + for (struct ble_npl_callout *c = global_callout; c != NULL; c = c->nextc) { + if (!c->active) { + continue; + } + if ((int32_t)(tnow - c->ticks) >= 0) { + DEBUG_CALLOUT_printf("callout_run(%p) tnow=%u ticks=%u evq=%p\n", c, (uint)tnow, (uint)c->ticks, c->evq); + c->active = false; + if (c->evq) { + ble_npl_eventq_put(c->evq, &c->ev); + } else { + c->ev.fn(&c->ev); + } + DEBUG_CALLOUT_printf("callout_run(%p) done\n", c); + } + } +} + +void ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, ble_npl_event_fn *ev_cb, void *ev_arg) { + DEBUG_CALLOUT_printf("ble_npl_callout_init(%p, %p, %p, %p)\n", c, evq, ev_cb, ev_arg); + c->active = false; + c->ticks = 0; + c->evq = evq; + ble_npl_event_init(&c->ev, ev_cb, ev_arg); + + struct ble_npl_callout **c2; + for (c2 = &global_callout; *c2 != NULL; c2 = &(*c2)->nextc) { + if (c == *c2) { + // callout already in linked list so don't link it in again + return; + } + } + *c2 = c; + c->nextc = NULL; +} + +ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) { + DEBUG_CALLOUT_printf("ble_npl_callout_reset(%p, %u) tnow=%u\n", c, (uint)ticks, (uint)mp_hal_ticks_ms()); + c->active = true; + c->ticks = ble_npl_time_get() + ticks; + return BLE_NPL_OK; +} + +void ble_npl_callout_stop(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_stop(%p)\n", c); + c->active = false; +} + +bool ble_npl_callout_is_active(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_is_active(%p)\n", c); + return c->active; +} + +ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_get_ticks(%p)\n", c); + return c->ticks; +} + +ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *c, ble_npl_time_t now) { + DEBUG_CALLOUT_printf("ble_npl_callout_remaining_ticks(%p, %u)\n", c, (uint)now); + if (c->ticks > now) { + return c->ticks - now; + } else { + return 0; + } +} + +void *ble_npl_callout_get_arg(struct ble_npl_callout *c) { + DEBUG_CALLOUT_printf("ble_npl_callout_get_arg(%p)\n", c); + return ble_npl_event_get_arg(&c->ev); +} + +void ble_npl_callout_set_arg(struct ble_npl_callout *c, void *arg) { + DEBUG_CALLOUT_printf("ble_npl_callout_set_arg(%p, %p)\n", c, arg); + ble_npl_event_set_arg(&c->ev, arg); +} + +/******************************************************************************/ +// TIME + +uint32_t ble_npl_time_get(void) { + DEBUG_TIME_printf("ble_npl_time_get -> %u\n", (uint)mp_hal_ticks_ms()); + return mp_hal_ticks_ms(); +} + +ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) { + DEBUG_TIME_printf("ble_npl_time_ms_to_ticks(%u)\n", (uint)ms); + *out_ticks = ms; + return BLE_NPL_OK; +} + +ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms) { + DEBUG_TIME_printf("ble_npl_time_ms_to_ticks32(%u)\n", (uint)ms); + return ms; +} + +uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) { + DEBUG_TIME_printf("ble_npl_time_ticks_to_ms32(%u)\n", (uint)ticks); + return ticks; +} + +void ble_npl_time_delay(ble_npl_time_t ticks) { + mp_hal_delay_ms(ticks + 1); +} + +/******************************************************************************/ +// CRITICAL + +uint32_t ble_npl_hw_enter_critical(void) { + DEBUG_CRIT_printf("ble_npl_hw_enter_critical()\n"); + return raise_irq_pri(15); +} + +void ble_npl_hw_exit_critical(uint32_t ctx) { + DEBUG_CRIT_printf("ble_npl_hw_exit_critical(%u)\n", (uint)ctx); + restore_irq_pri(ctx); +} diff --git a/extmod/nimble/syscfg/syscfg.h b/extmod/nimble/syscfg/syscfg.h new file mode 100644 index 0000000000..0d3acf9a76 --- /dev/null +++ b/extmod/nimble/syscfg/syscfg.h @@ -0,0 +1,160 @@ +#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H +#define MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H + +#include "py/mphal.h" +#include "uart.h" + +void *nimble_malloc(size_t size); +void nimble_free(void *ptr); +void *nimble_realloc(void *ptr, size_t size); + +#define malloc(size) nimble_malloc(size) +#define free(ptr) nimble_free(ptr) +#define realloc(ptr, size) nimble_realloc(ptr, size) + +int nimble_sprintf(char *str, const char *fmt, ...); +#define sprintf(str, fmt, ...) nimble_sprintf(str, fmt, __VA_ARGS__) + +#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x + +#define MYNEWT_VAL_LOG_LEVEL (255) + +/*** compiler/arm-none-eabi-m4 */ +#define MYNEWT_VAL_HARDFLOAT (1) + +/*** kernel/os */ +#define MYNEWT_VAL_FLOAT_USER (0) +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) +#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) +#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) +#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) +#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) +#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) +#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0) +#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4) +#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024) +#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127) +#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0) +#define MYNEWT_VAL_OS_MEMPOOL_POISON (0) + +/*** nimble */ +#define MYNEWT_VAL_BLE_EXT_ADV (0) +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1) +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) +#define MYNEWT_VAL_BLE_WHITELIST (1) + +/*** nimble/host */ +#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256) +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1) +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000) +#define MYNEWT_VAL_BLE_ATT_SVR_READ (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) +#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1) +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) +#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_INDICATE (1) +#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) +#define MYNEWT_VAL_BLE_GATT_NOTIFY (1) +#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8) +#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000) +#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4) +#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#define MYNEWT_VAL_BLE_HOST (1) +#define MYNEWT_VAL_BLE_HS_DEBUG (0) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) +#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0) +#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1) +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0) +#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) +#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) +#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) +#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) +#define MYNEWT_VAL_BLE_MONITOR_RTT (0) +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor") +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) +#define MYNEWT_VAL_BLE_MONITOR_UART (0) +#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) +#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) +#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") +#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) +#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) +#define MYNEWT_VAL_BLE_SM_KEYPRESS (0) +#define MYNEWT_VAL_BLE_SM_LEGACY (1) +#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) +#define MYNEWT_VAL_BLE_SM_MITM (0) +#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_SC (1) +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) + +/*** nimble/host/services/gap */ +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0) +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("pybd") +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31) +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) + +/* Overridden by targets/porting-nimble (defined by nimble/transport) */ +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0) +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) + +/*** nimble/transport/uart */ +#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (12) +#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255) +#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12) +#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70) +#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8) +#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8) + +/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ +#define MYNEWT_VAL_BLE_HCI_UART_BAUD (MICROPY_HW_BLE_UART_BAUDRATE) +#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8) +#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (1) +#define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE) +#define MYNEWT_VAL_BLE_HCI_UART_PORT (MICROPY_HW_BLE_UART_ID) +#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1) + +#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H