diff --git a/nimble/host/mesh/src/crypto.c b/nimble/host/mesh/src/crypto.c index 1ead83c25..38c5bf514 100644 --- a/nimble/host/mesh/src/crypto.c +++ b/nimble/host/mesh/src/crypto.c @@ -37,8 +37,8 @@ #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg, - size_t sg_len, u8_t mac[16]) +int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg, + size_t sg_len, uint8_t mac[16]) { int rc = BLE_HS_EUNKNOWN; mbedtls_cipher_context_t ctx = {0}; @@ -79,8 +79,8 @@ exit: } #else -int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg, - size_t sg_len, u8_t mac[16]) +int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg, + size_t sg_len, uint8_t mac[16]) { struct tc_aes_key_sched_struct sched; struct tc_cmac_struct state; diff --git a/nimble/host/mesh/src/testing.c b/nimble/host/mesh/src/testing.c index 7ee11a137..112abe92f 100644 --- a/nimble/host/mesh/src/testing.c +++ b/nimble/host/mesh/src/testing.c @@ -115,14 +115,19 @@ int bt_test_mesh_rpl_clear(void) void bt_test_print_credentials(void) { + +#if MYNEWT_VAL(BLE_MESH_CDB) int i; struct bt_mesh_cdb_subnet *sub; struct bt_mesh_cdb_app_key *app_key; struct bt_mesh_subnet *subnet; +#endif console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index); console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16)); +#if MYNEWT_VAL(BLE_MESH_CDB) + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) { app_key = &bt_mesh_cdb.app_keys[i]; @@ -175,6 +180,7 @@ void bt_test_print_credentials(void) bt_hex(subnet->keys->msg.privacy, 16)); } } +#endif } int bt_test_shell_init(void) diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 125ae92a7..47c63cb47 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -124,7 +124,9 @@ struct ble_gap_connect_reattempt_ctxt { }; static struct ble_gap_connect_reattempt_ctxt ble_conn_reattempt[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; +#if !MYNEWT_VAL(BLE_EXT_ADV) static uint16_t reattempt_idx; +#endif static bool conn_cookie_enabled; #endif @@ -4042,7 +4044,7 @@ ble_gap_periodic_adv_stop(uint8_t instance) return rc; } -static void +void ble_gap_npl_sync_lost(struct ble_npl_event *ev) { struct ble_hs_periodic_sync *psync; diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c index 8f34d82db..c58d14f02 100644 --- a/nimble/host/src/ble_hs.c +++ b/nimble/host/src/ble_hs.c @@ -62,6 +62,14 @@ static int ble_hs_reset_reason; #define BLE_HS_SYNC_RETRY_TIMEOUT_MS 100 /* ms */ +extern void ble_hs_hci_deinit(void); +extern void ble_gap_deinit(void); +extern void ble_hs_stop_deinit(void); +extern void ble_mqueue_deinit(struct ble_mqueue *); +extern void ble_hs_flow_init(void); +extern void ble_hs_flow_deinit(void); +extern void ble_monitor_deinit(void); + static void *ble_hs_parent_task; /** @@ -441,6 +449,7 @@ ble_hs_timer_reset(uint32_t ticks) if (!ble_hs_is_enabled()) { ble_npl_callout_stop(&ble_hs_timer); + ble_npl_callout_deinit(&ble_hs_timer); } else { rc = ble_npl_callout_reset(&ble_hs_timer, ticks); BLE_HS_DBG_ASSERT_EVAL(rc == 0); @@ -465,6 +474,11 @@ ble_hs_timer_sched(int32_t ticks_from_now) ble_npl_callout_get_ticks(&ble_hs_timer))) < 0) { ble_hs_timer_reset(ticks_from_now); } + else if (ble_npl_callout_get_ticks(&ble_hs_timer) <= ble_npl_time_get()) { + /* Reset timer if currect time is later than expiration time. */ + BLE_HS_LOG(ERROR,"exp_time:%d.now:%d.ticks:%d.active:%d.Need reset.",ble_npl_callout_get_ticks(&ble_hs_timer),ble_npl_time_get(),ticks_from_now,ble_npl_callout_is_active(&ble_hs_timer)); + ble_hs_timer_reset(ticks_from_now); + } } void @@ -502,6 +516,9 @@ ble_hs_event_rx_hci_ev(struct ble_npl_event *ev) hci_ev = ble_npl_event_get_arg(ev); + /* Deinitialize hci npl event */ + ble_npl_event_deinit(ev); + rc = os_memblock_put(&ble_hs_hci_ev_pool, ev); BLE_HS_DBG_ASSERT_EVAL(rc == 0); @@ -794,6 +811,8 @@ ble_hs_init(void) ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start_stage1); #endif #endif + /* Initialize npl variables related to hs flow control */ + ble_hs_flow_init(); } /* Transport APIs for HS side */ @@ -839,5 +858,23 @@ ble_hs_deinit(void) ble_hs_flow_stop(); +#if NIMBLE_BLE_CONNECT + ble_npl_event_deinit(&ble_hs_ev_tx_notifications); +#endif + + ble_npl_event_deinit(&ble_hs_ev_reset); + + ble_npl_event_deinit(&ble_hs_ev_start_stage1); + + ble_npl_event_deinit(&ble_hs_ev_start_stage2); + + ble_mqueue_deinit(&ble_hs_rx_q); + + ble_hs_flow_deinit(); + ble_hs_stop_deinit(); + +#if BLE_MONITOR + ble_monitor_deinit(); +#endif } diff --git a/nimble/host/src/ble_hs_flow.c b/nimble/host/src/ble_hs_flow.c index 31ca69346..8b8430dae 100644 --- a/nimble/host/src/ble_hs_flow.c +++ b/nimble/host/src/ble_hs_flow.c @@ -235,7 +235,9 @@ ble_hs_flow_startup(void) }; int rc; - ble_npl_event_init(&ble_hs_flow_ev, ble_hs_flow_event_cb, NULL); + /* Remove previous event from queue, if any*/ + ble_npl_eventq_remove(ble_hs_evq_get(), &ble_hs_flow_ev); + #if MYNEWT_VAL(SELFTEST) ble_npl_callout_stop(&ble_hs_flow_timer); @@ -278,3 +280,22 @@ ble_hs_flow_stop(void) ble_npl_callout_deinit(&ble_hs_flow_timer); #endif } + +void +ble_hs_flow_init(void) +{ +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) + ble_npl_event_init(&ble_hs_flow_ev, ble_hs_flow_event_cb, NULL); + ble_npl_callout_init(&ble_hs_flow_timer, ble_hs_evq_get(), + ble_hs_flow_event_cb, NULL); +#endif //MYNEWT_VAL(BLE_HS_FLOW_CTRL) +} + +void +ble_hs_flow_deinit(void) +{ +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) + ble_npl_event_deinit(&ble_hs_flow_ev); + ble_npl_callout_deinit(&ble_hs_flow_timer); +#endif //MYNEWT_VAL(BLE_HS_FLOW_CTRL) +} diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c index 50bb55e6c..7eb1ad717 100644 --- a/nimble/host/src/ble_hs_hci.c +++ b/nimble/host/src/ble_hs_hci.c @@ -652,10 +652,13 @@ ble_hs_hci_init(void) BLE_HS_DBG_ASSERT_EVAL(rc == 0); } -void -ble_hs_hci_deinit(void) +void ble_hs_hci_deinit(void) { - ble_npl_mutex_deinit(&ble_hs_hci_mutex); + int rc; - ble_npl_sem_deinit(&ble_hs_hci_sem); + rc = ble_npl_mutex_deinit(&ble_hs_hci_mutex); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = ble_npl_sem_deinit(&ble_hs_hci_sem); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); } diff --git a/nimble/host/src/ble_hs_hci_cmd.c b/nimble/host/src/ble_hs_hci_cmd.c index 0b2a4f828..2decd6054 100644 --- a/nimble/host/src/ble_hs_hci_cmd.c +++ b/nimble/host/src/ble_hs_hci_cmd.c @@ -63,9 +63,11 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) cmd = ble_transport_alloc_cmd(); BLE_HS_DBG_ASSERT(cmd != NULL); +#if !(SOC_ESP_NIMBLE_CONTROLLER) /* Hack for avoiding memcpy while handling tx pkt to VHCI, * keep one byte for type field*/ buf++; +#endif put_le16(buf, opcode); buf[2] = len; if (len != 0) { @@ -77,7 +79,10 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) ble_hs_log_flat_buf(buf, len + BLE_HCI_CMD_HDR_LEN); BLE_HS_LOG(DEBUG, "\n"); #endif + +#if !(SOC_ESP_NIMBLE_CONTROLLER) buf--; +#endif rc = ble_hs_hci_cmd_transport((void *) buf); diff --git a/nimble/host/src/ble_hs_mqueue.c b/nimble/host/src/ble_hs_mqueue.c index 2e08efc14..99628c1fb 100644 --- a/nimble/host/src/ble_hs_mqueue.c +++ b/nimble/host/src/ble_hs_mqueue.c @@ -29,6 +29,12 @@ ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg) return (0); } +void +ble_mqueue_deinit(struct ble_mqueue *mq) +{ + ble_npl_event_deinit(&mq->ev); +} + struct os_mbuf * ble_mqueue_get(struct ble_mqueue *mq) { diff --git a/nimble/host/src/ble_hs_periodic_sync.c b/nimble/host/src/ble_hs_periodic_sync.c index dad535138..bfa52d689 100644 --- a/nimble/host/src/ble_hs_periodic_sync.c +++ b/nimble/host/src/ble_hs_periodic_sync.c @@ -43,6 +43,7 @@ ble_hs_periodic_sync_alloc(void) memset(psync, 0, sizeof(*psync)); } + ble_npl_event_init(&psync->lost_ev, ble_gap_npl_sync_lost, psync); return psync; } @@ -55,6 +56,7 @@ ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync) return; } + ble_npl_event_deinit(&psync->lost_ev); #if MYNEWT_VAL(BLE_HS_DEBUG) memset(psync, 0xff, sizeof *psync); #endif diff --git a/nimble/host/src/ble_hs_priv.h b/nimble/host/src/ble_hs_priv.h index 35920a480..27dc1fd8c 100644 --- a/nimble/host/src/ble_hs_priv.h +++ b/nimble/host/src/ble_hs_priv.h @@ -139,6 +139,8 @@ int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq); int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om); +void ble_gap_npl_sync_lost(struct ble_npl_event *ev); + #if MYNEWT_VAL(BLE_HS_DEBUG) #define BLE_HS_DBG_ASSERT(x) assert(x) #define BLE_HS_DBG_ASSERT_EVAL(x) assert(x) diff --git a/nimble/host/util/src/addr.c b/nimble/host/util/src/addr.c index 830ff0258..fe8bcad0e 100644 --- a/nimble/host/util/src/addr.c +++ b/nimble/host/util/src/addr.c @@ -21,6 +21,10 @@ #include "host/util/util.h" #include "../src/ble_hs_hci_priv.h" +#if SOC_ESP_NIMBLE_CONTROLLER +#include "esp_bt.h" +#endif + static int ble_hs_util_load_rand_addr(ble_addr_t *addr) { @@ -38,6 +42,14 @@ ble_hs_util_load_rand_addr(ble_addr_t *addr) } #endif +#if SOC_ESP_NIMBLE_CONTROLLER + int rc; + + rc = esp_ble_hw_get_static_addr(addr); + if (rc == 0) { + return 0; + } +#endif return BLE_HS_ENOADDR; } diff --git a/nimble/transport/socket/src/ble_hci_socket.c b/nimble/transport/socket/src/ble_hci_socket.c index 75a813dba..11232b010 100644 --- a/nimble/transport/socket/src/ble_hci_socket.c +++ b/nimble/transport/socket/src/ble_hci_socket.c @@ -775,6 +775,7 @@ ble_hci_sock_init_task(void) { ble_npl_eventq_init(&ble_hci_sock_state.evq); ble_npl_callout_stop(&ble_hci_sock_state.timer); + ble_npl_callout_deinit(&ble_hci_sock_state.timer); ble_npl_callout_init(&ble_hci_sock_state.timer, &ble_hci_sock_state.evq, ble_hci_sock_rx_ev, NULL); diff --git a/nimble/transport/src/monitor.c b/nimble/transport/src/monitor.c index b21dd9305..9b3a73470 100644 --- a/nimble/transport/src/monitor.c +++ b/nimble/transport/src/monitor.c @@ -347,6 +347,15 @@ ble_monitor_init(void) #endif } +void +ble_monitor_deinit(void) +{ +#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) + ble_npl_callout_deinit(&rtt_drops.tmo); +#endif + ble_npl_mutex_deinit(&lock); +} + int ble_monitor_send(uint16_t opcode, const void *data, size_t len) { diff --git a/porting/nimble/include/hal/hal_gpio.h b/porting/nimble/include/hal/hal_gpio.h new file mode 100644 index 000000000..0bc4db6cd --- /dev/null +++ b/porting/nimble/include/hal/hal_gpio.h @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALGpio HAL GPIO + * @{ + */ + +#ifndef H_HAL_GPIO_ +#define H_HAL_GPIO_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The "mode" of the gpio. The gpio is either an input, output, or it is + * "not connected" (the pin specified is not functioning as a gpio) + */ +enum hal_gpio_mode_e { + /** Not connected */ + HAL_GPIO_MODE_NC = -1, + /** Input */ + HAL_GPIO_MODE_IN = 0, + /** Output */ + HAL_GPIO_MODE_OUT = 1 +}; +typedef enum hal_gpio_mode_e hal_gpio_mode_t; + +/* + * The "pull" of the gpio. This is either an input or an output. + */ +enum hal_gpio_pull { + /** Pull-up/down not enabled */ + HAL_GPIO_PULL_NONE = 0, + /** Pull-up enabled */ + HAL_GPIO_PULL_UP = 1, + /** Pull-down enabled */ + HAL_GPIO_PULL_DOWN = 2 +}; +typedef enum hal_gpio_pull hal_gpio_pull_t; + +/* + * IRQ trigger type. + */ +enum hal_gpio_irq_trigger { + HAL_GPIO_TRIG_NONE = 0, + /** IRQ occurs on rising edge */ + HAL_GPIO_TRIG_RISING = 1, + /** IRQ occurs on falling edge */ + HAL_GPIO_TRIG_FALLING = 2, + /** IRQ occurs on either edge */ + HAL_GPIO_TRIG_BOTH = 3, + /** IRQ occurs when line is low */ + HAL_GPIO_TRIG_LOW = 4, + /** IRQ occurs when line is high */ + HAL_GPIO_TRIG_HIGH = 5 +}; +typedef enum hal_gpio_irq_trigger hal_gpio_irq_trig_t; + +/* Function proto for GPIO irq handler functions */ +typedef void (*hal_gpio_irq_handler_t)(void *arg); + +/** + * Initializes the specified pin as an input + * + * @param pin Pin number to set as input + * @param pull pull type + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_init_in(int pin, hal_gpio_pull_t pull); + +/** + * Initialize the specified pin as an output, setting the pin to the specified + * value. + * + * @param pin Pin number to set as output + * @param val Value to set pin + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_init_out(int pin, int val); + +/** + * Deinitialize the specified pin to revert the previous initialization + * + * @param pin Pin number to unset + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_deinit(int pin); + +/** + * Write a value (either high or low) to the specified pin. + * + * @param pin Pin to set + * @param val Value to set pin (0:low 1:high) + */ +void hal_gpio_write(int pin, int val); + +/** + * Reads the specified pin. + * + * @param pin Pin number to read + * + * @return int 0: low, 1: high + */ +int hal_gpio_read(int pin); + +/** + * Toggles the specified pin + * + * @param pin Pin number to toggle + * + * @return current gpio state int 0: low, 1: high + */ +int hal_gpio_toggle(int pin); + +/** + * Initialize a given pin to trigger a GPIO IRQ callback. + * + * @param pin The pin to trigger GPIO interrupt on + * @param handler The handler function to call + * @param arg The argument to provide to the IRQ handler + * @param trig The trigger mode (e.g. rising, falling) + * @param pull The mode of the pin (e.g. pullup, pulldown) + * + * @return 0 on success, non-zero error code on failure. + */ +int hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg, + hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull); + +/** + * Release a pin from being configured to trigger IRQ on state change. + * + * @param pin The pin to release + */ +void hal_gpio_irq_release(int pin); + +/** + * Enable IRQs on the passed pin + * + * @param pin The pin to enable IRQs on + */ +void hal_gpio_irq_enable(int pin); + +/** + * Disable IRQs on the passed pin + * + * @param pin The pin to disable IRQs on + */ +void hal_gpio_irq_disable(int pin); + + +#ifdef __cplusplus +} +#endif + +#endif /* H_HAL_GPIO_ */ + +/** + * @} HALGpio + * @} HAL + */ diff --git a/porting/nimble/include/hal/hal_os_tick.h b/porting/nimble/include/hal/hal_os_tick.h new file mode 100644 index 000000000..5a94e3f62 --- /dev/null +++ b/porting/nimble/include/hal/hal_os_tick.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALOsTick HAL OS Tick + * @{ + */ + +#ifndef H_HAL_OS_TICK_ +#define H_HAL_OS_TICK_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "os/os.h" + +typedef long os_time_t; + +void hal_rtc_intr_init(void); + +/** + * Set up the periodic timer to interrupt at a frequency of 'os_ticks_per_sec'. + * 'prio' is the cpu-specific priority of the periodic timer interrupt. + * + * @param os_ticks_per_sec Frequency of the OS tick timer + * @param prio Priority of the OS tick timer + */ +void bleonly_os_tick_init(uint32_t os_ticks_per_sec); + +/** + * Halt CPU for up to 'n' ticks. + * + * @param n The number of ticks to halt the CPU for + */ +void os_tick_idle(os_time_t n); + + +#ifdef __cplusplus +} +#endif + +#endif /* H_HAL_OS_TICK_ */ + +/** + * @} HALOsTick + * @} HAL + */ diff --git a/porting/nimble/include/hal/hal_system.h b/porting/nimble/include/hal/hal_system.h index fa0255a68..bf07da2ca 100644 --- a/porting/nimble/include/hal/hal_system.h +++ b/porting/nimble/include/hal/hal_system.h @@ -1,23 +1,9 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * SPDX-License-Identifier: Apache-2.0 */ - /** * @addtogroup HAL * @{ diff --git a/porting/nimble/include/hal/hal_uart.h b/porting/nimble/include/hal/hal_uart.h new file mode 100644 index 000000000..6864950b6 --- /dev/null +++ b/porting/nimble/include/hal/hal_uart.h @@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALUart HAL UART + * @{ + */ + +#ifndef H_HAL_UART_H_ +#define H_HAL_UART_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +/** + * Function prototype for UART driver to ask for more data to send. + * Returns -1 if no more data is available for TX. + * Driver must call this with interrupts disabled. + */ +typedef int (*hal_uart_tx_char)(void *arg); + +/** + * Function prototype for UART driver to report that transmission is + * complete. This should be called when transmission of last byte is + * finished. + * Driver must call this with interrupts disabled. + */ +typedef void (*hal_uart_tx_done)(void *arg); + +/** + * Function prototype for UART driver to report incoming byte of data. + * Returns -1 if data was dropped. + * Driver must call this with interrupts disabled. + */ +typedef int (*hal_uart_rx_char)(void *arg, uint8_t byte); + +/** + * Initializes given uart. Mapping of logical UART number to physical + * UART/GPIO pins is in BSP. + */ +int hal_uart_init_cbs(int uart, hal_uart_tx_char tx_func, + hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg); + +enum hal_uart_parity { + /** No Parity */ + HAL_UART_PARITY_NONE = 0, + /** Odd parity */ + HAL_UART_PARITY_ODD = 1, + /** Even parity */ + HAL_UART_PARITY_EVEN = 2 +}; + +enum hal_uart_flow_ctl { + /** No Flow Control */ + HAL_UART_FLOW_CTL_NONE = 0, + /** RTS/CTS */ + HAL_UART_FLOW_CTL_RTS_CTS = 1 +}; + +/** + * Initialize the HAL uart. + * + * @param uart The uart number to configure + * @param cfg Hardware specific uart configuration. This is passed from BSP + * directly to the MCU specific driver. + * + * @return 0 on success, non-zero error code on failure + */ +int hal_uart_init(int uart, void *cfg); + +/** + * Applies given configuration to UART. + * + * @param uart The UART number to configure + * @param speed The baudrate in bps to configure + * @param databits The number of databits to send per byte + * @param stopbits The number of stop bits to send + * @param parity The UART parity + * @param flow_ctl Flow control settings on the UART + * + * @return 0 on success, non-zero error code on failure + */ +int hal_uart_config(int uart, int32_t speed, uint8_t databits, uint8_t stopbits, + enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl); + +/** + * Close UART port. Can call hal_uart_config() with different settings after + * calling this. + * + * @param uart The UART number to close + */ +int hal_uart_close(int uart); + +/** + * More data queued for transmission. UART driver will start asking for that + * data. + * + * @param uart The UART number to start TX on + */ +void hal_uart_start_tx(int uart); + +/** + * Upper layers have consumed some data, and are now ready to receive more. + * This is meaningful after uart_rx_char callback has returned -1 telling + * that no more data can be accepted. + * + * @param uart The UART number to begin RX on + */ +void hal_uart_start_rx(int uart); + +/** + * This is type of write where UART has to block until character has been sent. + * Used when printing diag output from system crash. + * Must be called with interrupts disabled. + * + * @param uart The UART number to TX on + * @param byte The byte to TX on the UART + */ +void hal_uart_blocking_tx(int uart, uint8_t byte); + +#ifdef __cplusplus +} +#endif + + +#endif /* H_HAL_UART_H_ */ + + +/** + * @} HALUart + * @} HAL + */ diff --git a/porting/nimble/include/hal/hal_watchdog.h b/porting/nimble/include/hal/hal_watchdog.h new file mode 100644 index 000000000..d0658bf04 --- /dev/null +++ b/porting/nimble/include/hal/hal_watchdog.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALWatchdog HAL Watchdog + * @{ + */ + +#ifndef _HAL_WATCHDOG_H_ +#define _HAL_WATCHDOG_H_ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set a recurring watchdog timer to fire no sooner than in 'expire_secs' + * seconds. Watchdog should be tickled periodically with a frequency + * smaller than 'expire_secs'. Watchdog needs to be then started with + * a call to :c:func:`hal_watchdog_enable()`. + * + * @param expire_msecs Watchdog timer expiration time in msecs + * + * @return < 0 on failure; on success return the actual + * expiration time as positive value + */ +int hal_watchdog_init(uint32_t expire_msecs); + +/** + * Starts the watchdog. + */ +void hal_watchdog_enable(void); + +/** + * Tickles the watchdog. This needs to be done periodically, before + * the value configured in :c:func:`hal_watchdog_init()` expires. + */ +void hal_watchdog_tickle(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_WATCHDOG_H_ */ + +/** + * @} HALWatchdog + * @} HAL + */ diff --git a/porting/nimble/include/logcfg/logcfg.h b/porting/nimble/include/logcfg/logcfg.h index 1e009d3e4..f2f227c89 100644 --- a/porting/nimble/include/logcfg/logcfg.h +++ b/porting/nimble/include/logcfg/logcfg.h @@ -2,8 +2,8 @@ * This file was generated by Apache newt version: 1.11.0-dev */ -#ifndef H_MYNEWT_LOGCFG_ -#define H_MYNEWT_LOGCFG_ +#ifndef H_LOGCFG_ +#define H_LOGCFG_ #include "modlog/modlog.h" #include "log_common/log_common.h" @@ -130,6 +130,35 @@ #define BLE_MESH_TRANS_LOG_ERROR(...) MODLOG_ERROR(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__) + +#define BLE_MESH_RPL_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_RPL_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + +#define BLE_MESH_NET_KEYS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_INFO(...) MODLOG_INFO(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_WARN(...) MODLOG_WARN(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_ERROR(...) MODLOG_ERROR(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_CRITICAL(...) MODLOG_CRITICAL(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_DISABLED(...) MODLOG_DISABLED(23, __VA_ARGS__) + +#define BLE_MESH_PROV_DEVICE_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_INFO(...) MODLOG_INFO(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_WARN(...) MODLOG_WARN(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_ERROR(...) MODLOG_ERROR(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_CRITICAL(...) MODLOG_CRITICAL(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_DISABLED(...) MODLOG_DISABLED(24, __VA_ARGS__) + +#define BLE_MESH_HEARTBEAT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_INFO(...) MODLOG_INFO(25, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_WARN(...) MODLOG_WARN(25, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_ERROR(...) MODLOG_ERROR(25, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_CRITICAL(...) MODLOG_CRITICAL(25, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_DISABLED(...) MODLOG_DISABLED(25, __VA_ARGS__) + #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__) #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__) diff --git a/porting/nimble/include/mem/mem.h b/porting/nimble/include/mem/mem.h index 61994e8b9..bfe7cb392 100644 --- a/porting/nimble/include/mem/mem.h +++ b/porting/nimble/include/mem/mem.h @@ -27,6 +27,34 @@ extern "C" { struct os_mempool; struct os_mbuf_pool; + +#if SOC_ESP_NIMBLE_CONTROLLER +int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, + uint32_t block_size, char *name, void **out_buf); +#define mem_malloc_mempool r_mem_malloc_mempool + +int r_mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks, + uint32_t block_size, char *name, void **out_buf); +#define mem_malloc_mempool_ext r_mem_malloc_mempool_ext + + +int r_mem_malloc_mbuf_pool(struct os_mempool *mempool, + struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks, + uint32_t block_size, char *name, + void **out_buf); +#define mem_malloc_mbuf_pool r_mem_malloc_mbuf_pool + +int r_mem_malloc_mbufpkt_pool(struct os_mempool *mempool, + struct os_mbuf_pool *mbuf_pool, int num_blocks, + int block_size, char *name, + void **out_buf); +#define mem_malloc_mbufpkt_pool r_mem_malloc_mbufpkt_pool + +int r_mem_init_mbuf_pool(void *mem, struct os_mempool *mempool, + struct os_mbuf_pool *mbuf_pool, int num_blocks, + int block_size, const char *name); +#define mem_init_mbuf_pool r_mem_init_mbuf_pool +#else int mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, uint32_t block_size, char *name, void **out_buf); int mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks, @@ -43,6 +71,7 @@ int mem_malloc_mbufpkt_pool(struct os_mempool *mempool, int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool, struct os_mbuf_pool *mbuf_pool, int num_blocks, int block_size, const char *name); +#endif /** * Specifies a function used as a callback. Functions of this type allocate an @@ -58,11 +87,19 @@ int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool, */ typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg); + +#if SOC_ESP_NIMBLE_CONTROLLER +struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz, + mem_frag_alloc_fn *alloc_cb, void *cb_arg); +#define mem_split_frag r_mem_split_frag +void *r_mem_pullup_obj(struct os_mbuf **om, uint16_t len); +#define mem_pullup_obj r_mem_pullup_obj +#else struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz, mem_frag_alloc_fn *alloc_cb, void *cb_arg); void *mem_pullup_obj(struct os_mbuf **om, uint16_t len); - +#endif #ifdef __cplusplus } #endif diff --git a/porting/nimble/include/nimble/nimble_port.h b/porting/nimble/include/nimble/nimble_port.h index fe9592764..2efe13196 100644 --- a/porting/nimble/include/nimble/nimble_port.h +++ b/porting/nimble/include/nimble/nimble_port.h @@ -23,7 +23,12 @@ #include "nimble/nimble_npl.h" #define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) -#define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE + +#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE + +#if (CONFIG_IDF_TARGET_ESP32H2) +#define NIMBLE_LL_STACK_SIZE CONFIG_BT_NIMBLE_CONTROLLER_TASK_STACK_SIZE +#endif #ifdef __cplusplus extern "C" { diff --git a/porting/nimble/include/os/endian.h b/porting/nimble/include/os/endian.h index 5a7ede578..895463340 100644 --- a/porting/nimble/include/os/endian.h +++ b/porting/nimble/include/os/endian.h @@ -206,6 +206,63 @@ extern "C" { #endif +#if SOC_ESP_NIMBLE_CONTROLLER +void r_put_le16(void *buf, uint16_t x); +#define put_le16 r_put_le16 + +void r_put_le24(void *buf, uint32_t x); +#define put_le24 r_put_le24 + +void r_put_le32(void *buf, uint32_t x); +#define put_le32 r_put_le32 + +void r_put_le64(void *buf, uint64_t x); +#define put_le64 r_put_le64 + +uint16_t r_get_le16(const void *buf); +#define get_le16 r_get_le16 + +uint32_t r_get_le24(const void *buf); +#define get_le24 r_get_le24 + +uint32_t r_get_le32(const void *buf); +#define get_le32 r_get_le32 + +uint64_t r_get_le64(const void *buf); +#define get_le64 r_get_le64 + +void r_put_be16(void *buf, uint16_t x); +#define put_be16 r_put_be16 + +void r_put_be24(void *buf, uint32_t x); +#define put_be24 r_put_be24 + +void r_put_be32(void *buf, uint32_t x); +#define put_be32 r_put_be32 + +void r_put_be64(void *buf, uint64_t x); +#define put_be64 r_put_be64 + +uint16_t r_get_be16(const void *buf); +#define get_be16 r_get_be16 + +uint32_t r_get_be24(const void *buf); +#define get_be24 r_get_be24 + +uint32_t r_get_be32(const void *buf); +#define get_be32 r_get_be32 + +uint64_t r_get_be64(const void *buf); +#define get_be64 r_get_be64 + +void r_swap_in_place(void *buf, int len); +#define swap_in_place r_swap_in_place + +void r_swap_buf(uint8_t *dst, const uint8_t *src, int len); +#define swap_buf r_swap_buf + + +#else void put_le16(void *buf, uint16_t x); void put_le24(void *buf, uint32_t x); void put_le32(void *buf, uint32_t x); @@ -224,7 +281,7 @@ uint32_t get_be32(const void *buf); uint64_t get_be64(const void *buf); void swap_in_place(void *buf, int len); void swap_buf(uint8_t *dst, const uint8_t *src, int len); - +#endif #ifdef __cplusplus } #endif diff --git a/porting/nimble/include/os/os_cputime.h b/porting/nimble/include/os/os_cputime.h index 17ad87794..4e14bd8e2 100644 --- a/porting/nimble/include/os/os_cputime.h +++ b/porting/nimble/include/os/os_cputime.h @@ -55,6 +55,7 @@ extern "C" { MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192 || \ MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384 || \ MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768 || \ + MYNEWT_VAL(OS_CPUTIME_FREQ) == 32000 || \ MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536 || \ MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072 || \ MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144 || \ diff --git a/porting/nimble/include/os/os_mbuf.h b/porting/nimble/include/os/os_mbuf.h index 6c05b2a73..be9f5a387 100644 --- a/porting/nimble/include/os/os_mbuf.h +++ b/porting/nimble/include/os/os_mbuf.h @@ -238,6 +238,467 @@ _os_mbuf_trailingspace(struct os_mbuf *om) #define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om) +#if SOC_ESP_NIMBLE_CONTROLLER +/** + * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a + * particular task's event queue. Mqueues form a helper API around a common + * paradigm: wait on an event queue until at least one packet is available, + * then process a queue of packets. + * + * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA + * will be posted to the task's mbuf queue. + * + * @param mq The mqueue to initialize + * @param ev_cb The callback to associate with the mqeueue + * event. Typically, this callback pulls each + * packet off the mqueue and processes them. + * @param arg The argument to associate with the mqueue event. + * + * @return 0 on success, non-zero on failure. + */ +int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg); +#define os_mqueue_init r_os_mqueue_init + + +/** + * Remove and return a single mbuf from the mbuf queue. Does not block. + * + * @param mq The mbuf queue to pull an element off of. + * + * @return The next mbuf in the queue, or NULL if queue has no mbufs. + */ +struct os_mbuf *r_os_mqueue_get(struct os_mqueue *); +#define os_mqueue_get r_os_mqueue_get +/** + * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated + * with the mqueue gets posted to the specified eventq. + * + * @param mq The mbuf queue to append the mbuf to. + * @param evq The event queue to post an event to. + * @param m The mbuf to append to the mbuf queue. + * + * @return 0 on success, non-zero on failure. + */ +int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *); +#define os_mqueue_put r_os_mqueue_put + + +/** + * MSYS is a system level mbuf registry. Allows the system to share + * packet buffers amongst the various networking stacks that can be running + * simultaeneously. + * + * Mbuf pools are created in the system initialization code, and then when + * a mbuf is allocated out of msys, it will try and find the best fit based + * upon estimated mbuf size. + * + * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to + * allocate mbufs out of it. + * + * @param new_pool The pool to register with MSYS + * + * @return 0 on success, non-zero on failure + */ +int r_os_msys_register(struct os_mbuf_pool *); +#define os_msys_register r_os_msys_register + + +/** + * Allocate a mbuf from msys. Based upon the data size requested, + * os_msys_get() will choose the mbuf pool that has the best fit. + * + * @param dsize The estimated size of the data being stored in the mbuf + * @param leadingspace The amount of leadingspace to allocate in the mbuf + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace); +#define os_msys_get r_os_msys_get +/** + * De-registers all mbuf pools from msys. + */ +void r_os_msys_reset(void); +#define os_msys_reset r_os_msys_reset + + +/** + * Allocate a packet header structure from the MSYS pool. See + * os_msys_register() for a description of MSYS. + * + * @param dsize The estimated size of the data being stored in the mbuf + * @param user_hdr_len The length to allocate for the packet header structure + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len); +#define os_msys_get_pkthdr r_os_msys_get_pkthdr +/** + * Count the number of blocks in all the mbuf pools that are allocated. + * + * @return total number of blocks allocated in Msys + */ +int r_os_msys_count(void); +#define os_msys_count r_os_msys_count + + +/** + * Return the number of free blocks in Msys + * + * @return Number of free blocks available in Msys + */ +int r_os_msys_num_free(void); +#define os_msys_num_free r_os_msys_num_free + + +/** + * Initialize a pool of mbufs. + * + * @param omp The mbuf pool to initialize + * @param mp The memory pool that will hold this mbuf pool + * @param buf_len The length of the buffer itself. + * @param nbufs The number of buffers in the pool + * + * @return 0 on success, error code on failure. + */ +int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp, + uint16_t, uint16_t); +#define os_mbuf_pool_init r_os_mbuf_pool_init +/** + * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized + * prior to being returned. + * + * @param omp The mbuf pool to return the packet from + * @param leadingspace The amount of leadingspace to put before the data + * section by default. + * + * @return An initialized mbuf on success, and NULL on failure. + */ +struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t); +#define os_mbuf_get r_os_mbuf_get +/** + * Allocate a new packet header mbuf out of the os_mbuf_pool. + * + * @param omp The mbuf pool to allocate out of + * @param user_pkthdr_len The packet header length to reserve for the caller. + * + * @return A freshly allocated mbuf on success, NULL on failure. + */ +struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, + uint8_t pkthdr_len); +#define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr +/** + * Duplicate a chain of mbufs. Return the start of the duplicated chain. + * + * @param omp The mbuf pool to duplicate out of + * @param om The mbuf chain to duplicate + * + * @return A pointer to the new chain of mbufs + */ +struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m); +#define os_mbuf_dup r_os_mbuf_dup +/** + * Locates the specified absolute offset within an mbuf chain. The offset + * can be one past than the total length of the chain, but no greater. + * + * @param om The start of the mbuf chain to seek within. + * @param off The absolute address to find. + * @param out_off On success, this points to the relative offset + * within the returned mbuf. + * + * @return The mbuf containing the specified offset on + * success. + * NULL if the specified offset is out of bounds. + */ +struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off, + uint16_t *out_off); +#define os_mbuf_off r_os_mbuf_off + +/* + * Copy data from an mbuf chain starting "off" bytes from the beginning, + * continuing for "len" bytes, into the indicated buffer. + * + * @param m The mbuf chain to copy from + * @param off The offset into the mbuf chain to begin copying from + * @param len The length of the data to copy + * @param dst The destination buffer to copy into + * + * @return 0 on success; + * -1 if the mbuf does not contain enough data. + */ +int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst); +#define os_mbuf_copydata r_os_mbuf_copydata + + +/** + * @brief Calculates the length of an mbuf chain. + * + * Calculates the length of an mbuf chain. If the mbuf contains a packet + * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to + * this function. + * + * @param om The mbuf to measure. + * + * @return The length, in bytes, of the provided mbuf + * chain. + */ +uint16_t r_os_mbuf_len(const struct os_mbuf *om); +#define os_mbuf_len r_os_mbuf_len + + +/** + * Append data onto a mbuf + * + * @param om The mbuf to append the data onto + * @param data The data to append onto the mbuf + * @param len The length of the data to append + * + * @return 0 on success, and an error code on failure + */ +int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t); +#define os_mbuf_append r_os_mbuf_append + + +/** + * Reads data from one mbuf and appends it to another. On error, the specified + * data range may be partially appended. Neither mbuf is required to contain + * an mbuf packet header. + * + * @param dst The mbuf to append to. + * @param src The mbuf to copy data from. + * @param src_off The absolute offset within the source mbuf + * chain to read from. + * @param len The number of bytes to append. + * + * @return 0 on success; + * OS_EINVAL if the specified range extends beyond + * the end of the source mbuf chain. + */ +int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src, + uint16_t src_off, uint16_t len); +#define os_mbuf_appendfrom r_os_mbuf_appendfrom +/** + * Release a mbuf back to the pool + * + * @param omp The Mbuf pool to release back to + * @param om The Mbuf to release back to the pool + * + * @return 0 on success, -1 on failure + */ +int os_mbuf_free(struct os_mbuf *mb); +#define os_mbuf_free r_os_mbuf_free + + +/** + * Free a chain of mbufs + * + * @param omp The mbuf pool to free the chain of mbufs into + * @param om The starting mbuf of the chain to free back into the pool + * + * @return 0 on success, -1 on failure + */ +int r_os_mbuf_free_chain(struct os_mbuf *om); +#define os_mbuf_free_chain r_os_mbuf_free_chain + + +/** + * Adjust the length of a mbuf, trimming either from the head or the tail + * of the mbuf. + * + * @param mp The mbuf chain to adjust + * @param req_len The length to trim from the mbuf. If positive, trims + * from the head of the mbuf, if negative, trims from the + * tail of the mbuf. + */ +void r_os_mbuf_adj(struct os_mbuf *mp, int req_len); +#define os_mbuf_adj r_os_mbuf_adj + + + +/** + * Performs a memory compare of the specified region of an mbuf chain against a + * flat buffer. + * + * @param om The start of the mbuf chain to compare. + * @param off The offset within the mbuf chain to start the + * comparison. + * @param data The flat buffer to compare. + * @param len The length of the flat buffer. + * + * @return 0 if both memory regions are identical; + * A memcmp return code if there is a mismatch; + * INT_MAX if the mbuf is too short. + */ +int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len); +#define os_mbuf_cmpf r_os_mbuf_cmpf + + +/** + * Compares the contents of two mbuf chains. The ranges of the two chains to + * be compared are specified via the two offset parameters and the len + * parameter. Neither mbuf chain is required to contain a packet header. + * + * @param om1 The first mbuf chain to compare. + * @param offset1 The absolute offset within om1 at which to + * start the comparison. + * @param om2 The second mbuf chain to compare. + * @param offset2 The absolute offset within om2 at which to + * start the comparison. + * @param len The number of bytes to compare. + * + * @return 0 if both mbuf segments are identical; + * A memcmp() return code if the segment contents + * differ; + * INT_MAX if a specified range extends beyond the + * end of its corresponding mbuf chain. + */ +int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1, + const struct os_mbuf *om2, uint16_t offset2, + uint16_t len); +#define os_mbuf_cmpm r_os_mbuf_cmpm +/** + * Increases the length of an mbuf chain by adding data to the front. If there + * is insufficient room in the leading mbuf, additional mbufs are allocated and + * prepended as necessary. If this function fails to allocate an mbuf, the + * entire chain is freed. + * + * The specified mbuf chain does not need to contain a packet header. + * + * @param omp The mbuf pool to allocate from. + * @param om The head of the mbuf chain. + * @param len The number of bytes to prepend. + * + * @return The new head of the chain on success; + * NULL on failure. + */ +struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len); +#define os_mbuf_prepend r_os_mbuf_prepend +/** + * Prepends a chunk of empty data to the specified mbuf chain and ensures the + * chunk is contiguous. If either operation fails, the specified mbuf chain is + * freed and NULL is returned. + * + * @param om The mbuf chain to prepend to. + * @param len The number of bytes to prepend and pullup. + * + * @return The modified mbuf on success; + * NULL on failure (and the mbuf chain is freed). + */ +struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len); +#define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup +/** + * Copies the contents of a flat buffer into an mbuf chain, starting at the + * specified destination offset. If the mbuf is too small for the source data, + * it is extended as necessary. If the destination mbuf contains a packet + * header, the header length is updated. + * + * @param omp The mbuf pool to allocate from. + * @param om The mbuf chain to copy into. + * @param off The offset within the chain to copy to. + * @param src The source buffer to copy from. + * @param len The number of bytes to copy. + * + * @return 0 on success; nonzero on failure. + */ +int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len); +#define os_mbuf_copyinto r_os_mbuf_copyinto + + +/** + * Attaches a second mbuf chain onto the end of the first. If the first chain + * contains a packet header, the header's length is updated. If the second + * chain has a packet header, its header is cleared. + * + * @param first The mbuf chain being attached to. + * @param second The mbuf chain that gets attached. + */ +void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second); +#define os_mbuf_concat r_os_mbuf_concat + + + +/** + * Increases the length of an mbuf chain by the specified amount. If there is + * not sufficient room in the last buffer, a new buffer is allocated and + * appended to the chain. It is an error to request more data than can fit in + * a single buffer. + * + * @param omp + * @param om The head of the chain to extend. + * @param len The number of bytes to extend by. + * + * @return A pointer to the new data on success; + * NULL on failure. + */ +void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len); +#define os_mbuf_extend r_os_mbuf_extend +/** + * Rearrange a mbuf chain so that len bytes are contiguous, + * and in the data area of an mbuf (so that OS_MBUF_DATA() will + * work on a structure of size len.) Returns the resulting + * mbuf chain on success, free's it and returns NULL on failure. + * + * If there is room, it will add up to "max_protohdr - len" + * extra bytes to the contiguous region, in an attempt to avoid being + * called next time. + * + * @param omp The mbuf pool to take the mbufs out of + * @param om The mbuf chain to make contiguous + * @param len The number of bytes in the chain to make contiguous + * + * @return The contiguous mbuf chain on success, NULL on failure. + */ +struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len); +#define os_mbuf_pullup r_os_mbuf_pullup + +/** + * Removes and frees empty mbufs from the front of a chain. If the chain + * contains a packet header, it is preserved. + * + * @param om The mbuf chain to trim. + * + * @return The head of the trimmed mbuf chain. + */ +struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om); +#define os_mbuf_trim_front r_os_mbuf_trim_front +/** + * Increases the length of an mbuf chain by inserting a gap at the specified + * offset. The contents of the gap are indeterminate. If the mbuf chain + * contains a packet header, its total length is increased accordingly. + * + * This function never frees the provided mbuf chain. + * + * @param om The mbuf chain to widen. + * @param off The offset at which to insert the gap. + * @param len The size of the gap to insert. + * + * @return 0 on success; SYS_[...] error code on failure. + */ +int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len); +#define os_mbuf_widen r_os_mbuf_widen + + + +/** + * Creates a single chained mbuf from m1 and m2 utilizing all + * the available buffer space in all mbufs in the resulting + * chain. In other words, ensures there is no leading space in + * any mbuf in the resulting chain and trailing space only in + * the last mbuf in the chain. Mbufs from either chain may be + * freed if not needed. No mbufs are allocated. Note that mbufs + * from m2 are added to the end of m1. If m1 has a packet + * header, it is retained and length updated. If m2 has a packet + * header it is discarded. If m1 is NULL, NULL is returned and + * m2 is left untouched. + * + * @param m1 Pointer to first mbuf chain to pack + * @param m2 Pointer to second mbuf chain to pack + * + * @return struct os_mbuf* Pointer to resulting mbuf chain + */ +struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2); +#define os_mbuf_pack_chains r_os_mbuf_pack_chains + +#else /** * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a * particular task's event queue. Mqueues form a helper API around a common @@ -664,6 +1125,7 @@ int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len); */ struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2); +#endif #ifdef __cplusplus } #endif diff --git a/porting/nimble/include/os/os_mempool.h b/porting/nimble/include/os/os_mempool.h index f11df3a0d..8b2ef7b6d 100644 --- a/porting/nimble/include/os/os_mempool.h +++ b/porting/nimble/include/os/os_mempool.h @@ -170,6 +170,123 @@ typedef __uint128_t os_membuf_t; #define OS_MEMPOOL_BYTES(n,blksize) \ (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) +#if SOC_ESP_NIMBLE_CONTROLLER +/** + * Initialize a memory pool. + * + * @param mp Pointer to a pointer to a mempool + * @param blocks The number of blocks in the pool + * @param blocks_size The size of the block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); +#define os_mempool_init r_os_mempool_init +/** + * Initializes an extended memory pool. Extended attributes (e.g., callbacks) + * are not specified when this function is called; they are assigned manually + * after initialization. + * + * @param mpe The extended memory pool to initialize. + * @param blocks The number of blocks in the pool. + * @param block_size The size of each block, in bytes. + * @param membuf Pointer to memory to contain blocks. + * @param name Name of the pool. + * + * @return os_error_t + */ +os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, + uint32_t block_size, void *membuf, const char *name); +#define os_mempool_ext_init r_os_mempool_ext_init +/** + * Removes the specified mempool from the list of initialized mempools. + * + * @param mp The mempool to unregister. + * + * @return 0 on success; + * OS_INVALID_PARM if the mempool is not + * registered. + */ +os_error_t r_os_mempool_unregister(struct os_mempool *mp); +#define os_mempool_unregister r_os_mempool_unregister + + +/** + * Clears a memory pool. + * + * @param mp The mempool to clear. + * + * @return os_error_t + */ +os_error_t r_os_mempool_clear(struct os_mempool *mp); +#define os_mempool_clear r_os_mempool_clear + + +/** + * Performs an integrity check of the specified mempool. This function + * attempts to detect memory corruption in the specified memory pool. + * + * @param mp The mempool to check. + * + * @return true if the memory pool passes the integrity + * check; + * false if the memory pool is corrupt. + */ +bool r_os_mempool_is_sane(const struct os_mempool *mp); +#define os_mempool_is_sane r_os_mempool_is_sane + + +/** + * Checks if a memory block was allocated from the specified mempool. + * + * @param mp The mempool to check as parent. + * @param block_addr The memory block to check as child. + * + * @return 0 if the block does not belong to the mempool; + * 1 if the block does belong to the mempool. + */ +int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr); +#define os_memblock_from r_os_memblock_from + + +/** + * Get a memory block from a memory pool + * + * @param mp Pointer to the memory pool + * + * @return void* Pointer to block if available; NULL otherwise + */ +void *r_os_memblock_get(struct os_mempool *mp); +#define os_memblock_get r_os_memblock_get +/** + * Puts the memory block back into the pool, ignoring the put callback, if any. + * This function should only be called from a put callback to free a block + * without causing infinite recursion. + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); +#define os_memblock_put_from_cb r_os_memblock_put_from_cb + + +/** + * Puts the memory block back into the pool + * + * @param mp Pointer to memory pool + * @param block_addr Pointer to memory block + * + * @return os_error_t + */ +os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr); +#define os_memblock_put r_os_memblock_put + +#else /** * Initialize a memory pool. * @@ -282,6 +399,7 @@ os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); * @return os_error_t */ os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr); +#endif #ifdef __cplusplus } diff --git a/porting/nimble/include/syscfg/syscfg.h b/porting/nimble/include/syscfg/syscfg.h index 928254d5d..54506184d 100644 --- a/porting/nimble/include/syscfg/syscfg.h +++ b/porting/nimble/include/syscfg/syscfg.h @@ -2,8 +2,8 @@ * This file was generated by Apache newt version: 1.11.0-dev */ -#ifndef H_MYNEWT_SYSCFG_ -#define H_MYNEWT_SYSCFG_ +#ifndef H_SYSCFG_ +#define H_SYSCFG_ #ifdef ESP_PLATFORM #include "esp_nimble_cfg.h" diff --git a/porting/nimble/src/hal_uart.c b/porting/nimble/src/hal_uart.c new file mode 100644 index 000000000..226d5936a --- /dev/null +++ b/porting/nimble/src/hal_uart.c @@ -0,0 +1,397 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "freertos/FreeRTOS.h" +#include "os/os.h" +#include "hal/hal_uart.h" +#include "soc/soc.h" +#include "soc/system_reg.h" +#include "driver/gpio.h" +#include "esp_intr_alloc.h" +#include "riscv/interrupt.h" +#include "hal/uart_ll.h" +#include "freertos/semphr.h" + +struct hal_uart { + uint8_t u_open:1; + uint8_t u_rx_stall:1; + uint8_t u_tx_started:1; + uint8_t u_tx_buf; + hal_uart_rx_char u_rx_func; + hal_uart_tx_char u_tx_func; + hal_uart_tx_done u_tx_done; + SemaphoreHandle_t u_rx_sem; + void *u_func_arg; +}; +static struct hal_uart uart; + +#define UART_FIFO_LEN (128) + +uint8_t rxbuffer[256]; +static uint16_t rd_ptr = 0; +static uint16_t wr_ptr = 0; +#define BUFFER_MASK (0xff) + +static TaskHandle_t hci_uart_task_h; + +void uart_init(uint32_t baud); +void uart0_init(uint32_t baud); +void uart0_tout_isr(void); +void uart_tout_isr(void); +void +hal_uart_blocking_tx(int port, uint8_t data){ + +} +int hal_uart_init(int uart_no, void *cfg) +{ + // Uart_Init(uart_no, UART_CLK_FREQ_ROM); + return 0; +} + +void hal_uart_start_rx(int uart) +{ + ets_printf("rx support???\n"); +} +int hal_uart_init_cbs(int uart_no, hal_uart_tx_char tx_func, + hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg) +{ + struct hal_uart *u; + + u = &uart; + + if (u->u_open) { + return -1; + } + + u->u_rx_func = rx_func; + u->u_tx_func = tx_func; + u->u_tx_done = tx_done; + u->u_func_arg = arg; + return 0; +} + +int hal_uart_config(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, + enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl) +{ + struct hal_uart *u; + u = &uart; + + if (u->u_open) { + return -1; + } + if (uart_no) { + uart_init(speed); + } else { + uart0_init(speed); + } + u->u_open = 1; + return 0; +} + +static int +IRAM_ATTR_64MCPU hal_uart_tx_fill_buf(struct hal_uart *u, int uart_no) +{ + int data; + int i; + uart_dev_t *hw = &UART1; + if(!uart_no){ + hw = &UART0; + } + i = 0; + while(hw->status.txfifo_cnt < UART_FIFO_LEN){ + data = u->u_tx_func(u->u_func_arg); + if (data >= 0) { + hw->ahb_fifo.rw_byte = data; + i++; + }else{ + break; + } + } + return i; +} + +void hal_uart_start_tx(int uart_no) +{ + struct hal_uart *u; + os_sr_t sr; + uart_dev_t *hw = &UART1; + if(!uart_no){ + hw = &UART0; + } + u = &uart; + OS_ENTER_CRITICAL(sr); + if (u->u_tx_started == 0) { + u->u_tx_started = 1; + hw->int_ena.tx_done = 1; + hal_uart_tx_fill_buf(u,uart_no); + } + OS_EXIT_CRITICAL(sr); +} + +int hal_uart0_close(int uart_no) +{ + struct hal_uart *u; + u = &uart; + u->u_open = 0; + + REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST); + return 0; +} + +int hal_uart_close(int uart_no) +{ + struct hal_uart *u; + u = &uart; + u->u_open = 0; + + REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART1_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST); + return 0; +} + +IRAM_ATTR_64MCPU void uart0_tout_isr(void) +{ + struct hal_uart *u; + int rc; + uint32_t ch; + uart_dev_t *hw = &UART0; + + u = &uart; + uint32_t uart_int_st = hw->int_st.val; + //clear + hw->int_clr.val = uart_int_st; + if (uart_int_st&UART_TX_DONE_INT_ST_M) { + rc = hal_uart_tx_fill_buf(u,0); + if (rc == 0) { + if (u->u_tx_done) { + u->u_tx_done(u->u_func_arg); + } + u->u_tx_started = 0; + hw->int_ena.tx_done = 0; + } + } + + while (hw->status.rxfifo_cnt) { + int rd_len = hw->status.rxfifo_cnt; + for (int i = 0; i < rd_len; i++) { + ch = hw->ahb_fifo.rw_byte; + rc = u->u_rx_func(u->u_func_arg, ch); + if (rc < 0) { + u->u_rx_stall = 1; + } + } + + } +} + +IRAM_ATTR_64MCPU void uart_tout_isr(void) +{ + struct hal_uart *u; + int rc; + bool rx_update = false; + uart_dev_t *hw = &UART1; + u = &uart; + uint32_t uart_int_st = hw->int_st.val; + //clear + hw->int_clr.val = uart_int_st; + if (uart_int_st&UART_TX_DONE_INT_ST_M) { + rc = hal_uart_tx_fill_buf(u,1); + if (rc == 0) { + if (u->u_tx_done) { + u->u_tx_done(u->u_func_arg); + } + u->u_tx_started = 0; + hw->int_ena.tx_done = 0; + } + } + while (hw->status.rxfifo_cnt) { + rxbuffer[(wr_ptr++)&BUFFER_MASK] = hw->ahb_fifo.rw_byte; + rx_update = true; + } + if (rx_update) { + xSemaphoreGiveFromISR(u->u_rx_sem, 0); + } +} + +void +IRAM_ATTR uart_rx_task(void *arg){ + int rc; + struct hal_uart *u; + u = &uart; + while (1) { + xSemaphoreTake(u->u_rx_sem, portMAX_DELAY); + while (rd_ptr != wr_ptr){ + rc = u->u_rx_func(u->u_func_arg, rxbuffer[(rd_ptr++)&BUFFER_MASK]); + if (rc < 0) { + u->u_rx_stall = 1; + } + } + } +} + + +void uart0_init(uint32_t baud) +{ + REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST); + REG_CLR_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST); + REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M); + REG_SET_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M); + + const int sclk_div = 1; + uint32_t sclk_freq = 32000000; + uint32_t clk_div = ((sclk_freq) << 4) / baud; + uart_dev_t *hw = &UART0; + hw->clk_conf.sclk_en = 0; + hw->clk_conf.rx_sclk_en = 0; + hw->clk_conf.tx_sclk_en = 0; + + + hw->clk_conf.sclk_en = 1; + hw->clk_conf.rx_sclk_en = 1; + hw->clk_conf.tx_sclk_en = 1; + + hw->clk_div.div_int = clk_div >> 4; + hw->clk_div.div_frag = clk_div & 0xf; + hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255; + + hw->conf0.parity_en = 0; + + hw->conf0.irda_en = 0; + hw->rs485_conf.en = 0; + hw->rs485_conf.tx_rx_en = 0; + hw->rs485_conf.rx_busy_tx_en = 0; + + hw->conf0.bit_num = 3; + hw->conf0.stop_bit_num = 1; + + hw->conf1.rxfifo_full_thrhd = 80; + + hw->mem_conf.rx_tout_thrhd = 20; + hw->conf1.rx_tout_en = 1; + + hw->conf1.rx_flow_en = 0; + hw->conf0.tx_flow_en = 0; + + hw->conf0.rxfifo_rst = 1; + hw->conf0.rxfifo_rst = 0; + hw->conf0.txfifo_rst = 1; + hw->conf0.txfifo_rst = 0; + hw->int_ena.rxfifo_full = 1; + //enable rx fifo timeout interrupt + hw->int_ena.rxfifo_tout = 1; + + uint8_t tx_pin = 21, rx_pin = 20, ISR_ID = ETS_UART0_INUM; + + ets_isr_mask((1<clk_conf.sclk_en = 0; + hw->clk_conf.rx_sclk_en = 0; + hw->clk_conf.tx_sclk_en = 0; + + + hw->clk_conf.sclk_en = 1; + hw->clk_conf.rx_sclk_en = 1; + hw->clk_conf.tx_sclk_en = 1; + + hw->clk_div.div_int = clk_div >> 4; + hw->clk_div.div_frag = clk_div & 0xf; + hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255; + + hw->conf0.parity_en = 0; + + hw->conf0.irda_en = 0; + hw->rs485_conf.en = 0; + hw->rs485_conf.tx_rx_en = 0; + hw->rs485_conf.rx_busy_tx_en = 0; + + hw->conf0.bit_num = 3; + hw->conf0.stop_bit_num = 1; + + //set full threshold to (2/3)*FIFO_LEN + hw->conf1.rxfifo_full_thrhd = 80; + hw->mem_conf.rx_tout_thrhd = 20; + + hw->conf1.rx_tout_en = 1; + + hw->conf0.rxfifo_rst = 1; + hw->conf0.rxfifo_rst = 0; + hw->conf0.txfifo_rst = 1; + hw->conf0.txfifo_rst = 0; + hw->int_ena.rxfifo_full = 1; + //enable rx fifo timeout interrupt + hw->int_ena.rxfifo_tout = 1; + + u->u_rx_sem = xSemaphoreCreateBinary(); + + uint8_t TX_IO = 18, RX_IO = 19, ISR_ID = ETS_UART1_INUM; + ets_printf("set nimble port tx:%d, rx:%d.\n", TX_IO, RX_IO); + ets_printf("set baud:%d.\n", baud); + intr_handler_set(ISR_ID, (intr_handler_t)&uart_tout_isr, NULL); + intr_matrix_route(ETS_UART1_INTR_SOURCE, ISR_ID); + esprv_intc_int_enable(BIT(ISR_ID)); + esprv_intc_int_set_type(BIT(ISR_ID), INTR_TYPE_LEVEL); + esprv_intc_int_set_priority(ISR_ID, 1); + // TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure... + esp_intr_reserve(ISR_ID, xPortGetCoreID()); + + ESP_ERROR_CHECK(uart_set_pin(1, TX_IO, RX_IO, -1, -1)); + + //Enable hw flow control of UART1 for BQB test, which if not enabled, the tester takes quite long time to send a byte to DUT + //RX -> J52.IO0 + //CTS -> J52.IO1 + //TX -> J52.IO2 + //RTS -> J52.IO3 + +#ifndef CONFIG_WVT_TEST + uart_ll_set_hw_flow_ctrl(hw, UART_HW_FLOWCTRL_CTS_RTS, 110); +#endif + + xTaskCreate(uart_rx_task, "uart_rx", CONFIG_BT_NIMBLE_HCI_UART_TASK_STACK_SIZE, + NULL, 1, &hci_uart_task_h); +} diff --git a/porting/nimble/src/mem.c b/porting/nimble/src/mem.c index 738763cc3..d12e727c7 100644 --- a/porting/nimble/src/mem.c +++ b/porting/nimble/src/mem.c @@ -322,4 +322,5 @@ mem_pullup_obj(struct os_mbuf **om, uint16_t len) } return (*om)->om_data; -} \ No newline at end of file + +} diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index f53e2e41c..f09bf5926 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -22,14 +22,35 @@ #include "sysinit/sysinit.h" #include "host/ble_hs.h" #include "nimble/nimble_port.h" -#if NIMBLE_CFG_CONTROLLER -#include "controller/ble_ll.h" -#include "nimble/transport.h" -#endif +#include "nimble/nimble_port_freertos.h" #ifdef ESP_PLATFORM #include "esp_log.h" #endif +#include "soc/soc_caps.h" +#if SOC_ESP_NIMBLE_CONTROLLER +#if CONFIG_SW_COEXIST_ENABLE +#include "esp_coexist_internal.h" +#endif +#endif + +#ifdef CONFIG_BT_NIMBLE_CONTROL_USE_UART_HCI +#include "transport/uart/ble_hci_uart.h" +#else +#include "transport/ram/ble_hci_ram.h" +#endif +#include "nimble/ble_hci_trans.h" + +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_bt.h" + +extern void ble_hs_deinit(void); +#define NIMBLE_PORT_LOG_TAG "BLE_INIT" + +extern void os_msys_init(void); + static struct ble_npl_eventq g_eventq_dflt; static struct ble_hs_stop_listener stop_listener; static struct ble_npl_sem ble_hs_stop_sem; @@ -41,7 +62,24 @@ extern void os_mempool_module_init(void); void nimble_port_init(void) { +#if SOC_ESP_NIMBLE_CONTROLLER + struct esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if(esp_bt_controller_init(&config_opts) != 0) { + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller init failed\n"); + return; + } + /* Initialize the host */ + ble_hs_init(); + +#else //SOC_ESP_NIMBLE_CONTROLLER + + /* Initialize the function pointers for OS porting */ + npl_freertos_funcs_init(); + + npl_freertos_mempool_init(); + /* Initialize default event queue */ + ble_npl_eventq_init(&g_eventq_dflt); /* Initialize the global memory pool */ os_mempool_module_init(); @@ -63,24 +101,20 @@ nimble_port_init(void) void nimble_port_deinit(void) { - ble_npl_eventq_deinit(&g_eventq_dflt); +#if SOC_ESP_NIMBLE_CONTROLLER + ble_hs_deinit(); - ble_hs_deinit(); + esp_bt_controller_deinit(); + + /* Delete the host task */ + nimble_port_freertos_deinit(); +#else + ble_npl_eventq_deinit(&g_eventq_dflt); + + ble_hs_deinit(); +#endif } -void -nimble_port_run(void) -{ - struct ble_npl_event *ev; - - while (1) { - ev = ble_npl_eventq_get(&g_eventq_dflt, BLE_NPL_TIME_FOREVER); - ble_npl_event_run(ev); - if (ev == &ble_hs_ev_stop) { - break; - } - } -} /** * Called when the host stop procedure has completed. @@ -126,19 +160,23 @@ nimble_port_stop(void) return rc; } +void +IRAM_ATTR nimble_port_run(void) +{ + struct ble_npl_event *ev; + + while (1) { + ev = ble_npl_eventq_get(&g_eventq_dflt, BLE_NPL_TIME_FOREVER); + ble_npl_event_run(ev); + if (ev == &ble_hs_ev_stop) { + break; + } + + } +} struct ble_npl_eventq * -nimble_port_get_dflt_eventq(void) +IRAM_ATTR nimble_port_get_dflt_eventq(void) { return &g_eventq_dflt; } - -#if NIMBLE_CFG_CONTROLLER -void -nimble_port_ll_task_func(void *arg) -{ - extern void ble_ll_task(void *); - - ble_ll_task(arg); -} -#endif diff --git a/porting/nimble/src/os_mbuf.c b/porting/nimble/src/os_mbuf.c index f65907032..8832fd2d1 100644 --- a/porting/nimble/src/os_mbuf.c +++ b/porting/nimble/src/os_mbuf.c @@ -1250,4 +1250,4 @@ os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2) } return m1; -} \ No newline at end of file +} diff --git a/porting/nimble/src/os_msys_init.c b/porting/nimble/src/os_msys_init.c index 597d6ed5e..e4aaa3880 100644 --- a/porting/nimble/src/os_msys_init.c +++ b/porting/nimble/src/os_msys_init.c @@ -22,6 +22,7 @@ #include "mem/mem.h" #include "sysinit/sysinit.h" #include "esp_nimble_mem.h" +#include "esp_err.h" static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list = STAILQ_HEAD_INITIALIZER(g_msys_pool_list); @@ -68,7 +69,7 @@ static struct os_sanity_check os_msys_sc; * @return The msys pool's minimum safe buffer count. */ static int -os_msys_sanity_min_count(int idx) +IRAM_ATTR os_msys_sanity_min_count(int idx) { switch (idx) { case 0: @@ -78,13 +79,13 @@ os_msys_sanity_min_count(int idx) return MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT); default: - assert(0); - return 0; + BLE_LL_ASSERT(0); + return ESP_OK; } } static int -os_msys_sanity(struct os_sanity_check *sc, void *arg) +IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg) { const struct os_mbuf_pool *omp; int min_count; @@ -100,7 +101,7 @@ os_msys_sanity(struct os_sanity_check *sc, void *arg) idx++; } - return 0; + return ESP_OK; } #endif @@ -125,18 +126,18 @@ os_msys_buf_alloc(void) #if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0 os_msys_init_1_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE)); if (!os_msys_init_1_data) { - return -1; + return ESP_FAIL; } #endif #if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0 os_msys_init_2_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE)); if (!os_msys_init_2_data) { - return -1; + return ESP_FAIL; } #endif - return 0; + return ESP_OK; } void @@ -154,16 +155,14 @@ os_msys_buf_free(void) } -void -os_msys_init(void) +void os_msys_init(void) { +#if OS_MSYS_SANITY_ENABLED int rc; +#endif os_msys_reset(); - (void)os_msys_init_once; - (void)rc; - #if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0 os_msys_init_once(os_msys_init_1_data, &os_msys_init_1_mempool, diff --git a/porting/npl/freertos/include/nimble/nimble_npl_os.h b/porting/npl/freertos/include/nimble/nimble_npl_os.h index 16c9c7755..2480c3dd8 100644 --- a/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -33,40 +33,53 @@ extern "C" { #endif -#define BLE_NPL_OS_ALIGNMENT 4 +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof((array)[0])) +#endif -#define BLE_NPL_TIME_FOREVER portMAX_DELAY +extern int ets_printf(const char *fmt, ...); +#define BLE_LL_ASSERT(con) \ + do{ \ + if(!(con)) { \ + ets_printf("assertion:%s\n",#con); \ + ets_printf("line:%d,function:%s\n", __LINE__, __func__);\ + assert(0); \ + } \ + }while(0) + +#define BLE_NPL_OS_ALIGNMENT (4)/*ble_npl_get_os_alignment()*/ + +#define BLE_NPL_TIME_FOREVER ble_npl_get_time_forever() /* This should be compatible with TickType_t */ typedef uint32_t ble_npl_time_t; typedef int32_t ble_npl_stime_t; +struct ble_npl_event; +typedef void ble_npl_event_fn(struct ble_npl_event *ev); + struct ble_npl_event { - bool queued; +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER ble_npl_event_fn *fn; - void *arg; +#endif + void *event; }; struct ble_npl_eventq { - QueueHandle_t q; + void *eventq; }; struct ble_npl_callout { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_handle_t handle; -#else - TimerHandle_t handle; -#endif - struct ble_npl_eventq *evq; - struct ble_npl_event ev; + void *co; }; struct ble_npl_mutex { - SemaphoreHandle_t handle; + void *mutex; }; struct ble_npl_sem { - SemaphoreHandle_t handle; + void *sem; }; /* @@ -77,251 +90,303 @@ struct ble_npl_sem { */ #include "npl_freertos.h" +struct npl_funcs_t { + bool (*p_ble_npl_os_started)(void); + void *(*p_ble_npl_get_current_task_id)(void); + void (*p_ble_npl_eventq_init)(struct ble_npl_eventq *); + void (*p_ble_npl_eventq_deinit)(struct ble_npl_eventq *); + struct ble_npl_event * (*p_ble_npl_eventq_get)(struct ble_npl_eventq *, ble_npl_time_t); + void (*p_ble_npl_eventq_put)(struct ble_npl_eventq *, struct ble_npl_event *); + void (*p_ble_npl_eventq_remove)(struct ble_npl_eventq *, struct ble_npl_event *); + void (*p_ble_npl_event_run)(struct ble_npl_event *); + bool (*p_ble_npl_eventq_is_empty)(struct ble_npl_eventq *); + void (*p_ble_npl_event_init)(struct ble_npl_event *, ble_npl_event_fn *, void *); + void (*p_ble_npl_event_deinit)(struct ble_npl_event *); + void (*p_ble_npl_event_reset)(struct ble_npl_event *); + bool (*p_ble_npl_event_is_queued)(struct ble_npl_event *); + void * (*p_ble_npl_event_get_arg)(struct ble_npl_event *); + void (*p_ble_npl_event_set_arg)(struct ble_npl_event *, void *); + ble_npl_error_t (*p_ble_npl_mutex_init)(struct ble_npl_mutex *); + ble_npl_error_t (*p_ble_npl_mutex_deinit)(struct ble_npl_mutex *); + ble_npl_error_t (*p_ble_npl_mutex_pend)(struct ble_npl_mutex *, ble_npl_time_t); + ble_npl_error_t (*p_ble_npl_mutex_release)(struct ble_npl_mutex *); + ble_npl_error_t (*p_ble_npl_sem_init)(struct ble_npl_sem *, uint16_t); + ble_npl_error_t (*p_ble_npl_sem_deinit)(struct ble_npl_sem *); + ble_npl_error_t (*p_ble_npl_sem_pend)(struct ble_npl_sem *, ble_npl_time_t); + ble_npl_error_t (*p_ble_npl_sem_release)(struct ble_npl_sem *); + uint16_t (*p_ble_npl_sem_get_count)(struct ble_npl_sem *); + void (*p_ble_npl_callout_init)(struct ble_npl_callout *, struct ble_npl_eventq *, ble_npl_event_fn *, void *); + ble_npl_error_t (*p_ble_npl_callout_reset)(struct ble_npl_callout *, ble_npl_time_t); + void (*p_ble_npl_callout_stop)(struct ble_npl_callout *); + void (*p_ble_npl_callout_deinit)(struct ble_npl_callout *); + void (*p_ble_npl_callout_mem_reset)(struct ble_npl_callout *); + bool (*p_ble_npl_callout_is_active)(struct ble_npl_callout *); + ble_npl_time_t (*p_ble_npl_callout_get_ticks)(struct ble_npl_callout *); + uint32_t (*p_ble_npl_callout_remaining_ticks)(struct ble_npl_callout *, ble_npl_time_t); + void (*p_ble_npl_callout_set_arg)(struct ble_npl_callout *, void *); + uint32_t (*p_ble_npl_time_get)(void); + ble_npl_error_t (*p_ble_npl_time_ms_to_ticks)(uint32_t ms, ble_npl_time_t *); + ble_npl_error_t (*p_ble_npl_time_ticks_to_ms)(ble_npl_time_t, uint32_t *); + ble_npl_time_t (*p_ble_npl_time_ms_to_ticks32)(uint32_t); + uint32_t (*p_ble_npl_time_ticks_to_ms32)(ble_npl_time_t); + void (*p_ble_npl_time_delay)(ble_npl_time_t); + void (*p_ble_npl_hw_set_isr)(int, uint32_t); + uint32_t (*p_ble_npl_hw_enter_critical)(void); + void (*p_ble_npl_hw_exit_critical)(uint32_t); + uint32_t (*p_ble_npl_get_time_forever)(void); + uint8_t (*p_ble_npl_hw_is_in_critical)(void); +}; + +extern struct npl_funcs_t *npl_funcs; + static inline bool -ble_npl_os_started(void) +IRAM_ATTR ble_npl_os_started(void) { - return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; + return npl_funcs->p_ble_npl_os_started(); } static inline void * -ble_npl_get_current_task_id(void) +IRAM_ATTR ble_npl_get_current_task_id(void) { - return xTaskGetCurrentTaskHandle(); + return npl_funcs->p_ble_npl_get_current_task_id(); } static inline void -ble_npl_eventq_init(struct ble_npl_eventq *evq) +IRAM_ATTR ble_npl_eventq_init(struct ble_npl_eventq *evq) { - evq->q = xQueueCreate(32, sizeof(struct ble_npl_eventq *)); + return npl_funcs->p_ble_npl_eventq_init(evq); } static inline void -ble_npl_eventq_deinit(struct ble_npl_eventq *evq) +IRAM_ATTR ble_npl_eventq_deinit(struct ble_npl_eventq *evq) { - vQueueDelete(evq->q); + return npl_funcs->p_ble_npl_eventq_deinit(evq); } static inline struct ble_npl_event * -ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) +IRAM_ATTR ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) { - return npl_freertos_eventq_get(evq, tmo); + return npl_funcs->p_ble_npl_eventq_get(evq, tmo); } static inline void -ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) +IRAM_ATTR ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { - npl_freertos_eventq_put(evq, ev); + return npl_funcs->p_ble_npl_eventq_put(evq, ev); } static inline void -ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev) +IRAM_ATTR ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { - npl_freertos_eventq_remove(evq, ev); + return npl_funcs->p_ble_npl_eventq_remove(evq, ev); } static inline void -ble_npl_event_run(struct ble_npl_event *ev) +IRAM_ATTR ble_npl_event_run(struct ble_npl_event *ev) { - ev->fn(ev); + return npl_funcs->p_ble_npl_event_run(ev); } static inline bool -ble_npl_eventq_is_empty(struct ble_npl_eventq *evq) +IRAM_ATTR ble_npl_eventq_is_empty(struct ble_npl_eventq *evq) { - return xQueueIsQueueEmptyFromISR(evq->q); + return npl_funcs->p_ble_npl_eventq_is_empty(evq); } static inline void -ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, +IRAM_ATTR ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) { - memset(ev, 0, sizeof(*ev)); - ev->fn = fn; - ev->arg = arg; + return npl_funcs->p_ble_npl_event_init(ev, fn, arg); } static inline bool -ble_npl_event_is_queued(struct ble_npl_event *ev) +IRAM_ATTR ble_npl_event_is_queued(struct ble_npl_event *ev) { - return ev->queued; + return npl_funcs->p_ble_npl_event_is_queued(ev); } static inline void * -ble_npl_event_get_arg(struct ble_npl_event *ev) +IRAM_ATTR ble_npl_event_get_arg(struct ble_npl_event *ev) { - return ev->arg; + return npl_funcs->p_ble_npl_event_get_arg(ev); } static inline void -ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) +IRAM_ATTR ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) { - ev->arg = arg; + return npl_funcs->p_ble_npl_event_set_arg(ev, arg); } static inline ble_npl_error_t -ble_npl_mutex_init(struct ble_npl_mutex *mu) +IRAM_ATTR ble_npl_mutex_init(struct ble_npl_mutex *mu) { - return npl_freertos_mutex_init(mu); + return npl_funcs->p_ble_npl_mutex_init(mu); } static inline ble_npl_error_t -ble_npl_mutex_deinit(struct ble_npl_mutex *mu) +IRAM_ATTR ble_npl_mutex_deinit(struct ble_npl_mutex *mu) { - return npl_freertos_mutex_deinit(mu); + return npl_funcs->p_ble_npl_mutex_deinit(mu); } static inline ble_npl_error_t -ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) +IRAM_ATTR ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) { - return npl_freertos_mutex_pend(mu, timeout); + return npl_funcs->p_ble_npl_mutex_pend(mu, timeout); } static inline ble_npl_error_t -ble_npl_mutex_release(struct ble_npl_mutex *mu) +IRAM_ATTR ble_npl_mutex_release(struct ble_npl_mutex *mu) { - return npl_freertos_mutex_release(mu); + return npl_funcs->p_ble_npl_mutex_release(mu); } static inline ble_npl_error_t -ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) +IRAM_ATTR ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { - return npl_freertos_sem_init(sem, tokens); + return npl_funcs->p_ble_npl_sem_init(sem, tokens); } static inline ble_npl_error_t -ble_npl_sem_deinit(struct ble_npl_sem *sem) +IRAM_ATTR ble_npl_sem_deinit(struct ble_npl_sem *sem) { - return npl_freertos_sem_deinit(sem); + return npl_funcs->p_ble_npl_sem_deinit(sem); } static inline ble_npl_error_t -ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) +IRAM_ATTR ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { - return npl_freertos_sem_pend(sem, timeout); + return npl_funcs->p_ble_npl_sem_pend(sem, timeout); } static inline ble_npl_error_t -ble_npl_sem_release(struct ble_npl_sem *sem) +IRAM_ATTR ble_npl_sem_release(struct ble_npl_sem *sem) { - return npl_freertos_sem_release(sem); + return npl_funcs->p_ble_npl_sem_release(sem); } static inline uint16_t -ble_npl_sem_get_count(struct ble_npl_sem *sem) +IRAM_ATTR ble_npl_sem_get_count(struct ble_npl_sem *sem) { - return uxSemaphoreGetCount(sem->handle); + return npl_funcs->p_ble_npl_sem_get_count(sem); } static inline void -ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, +IRAM_ATTR ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, ble_npl_event_fn *ev_cb, void *ev_arg) { - npl_freertos_callout_init(co, evq, ev_cb, ev_arg); + return npl_funcs->p_ble_npl_callout_init(co, evq, ev_cb, ev_arg); } - static inline void -ble_npl_callout_deinit(struct ble_npl_callout *co) +IRAM_ATTR ble_npl_callout_deinit(struct ble_npl_callout *co) { - npl_freertos_callout_deinit(co); + return npl_funcs->p_ble_npl_callout_deinit(co); } static inline ble_npl_error_t -ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) +IRAM_ATTR ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) { - return npl_freertos_callout_reset(co, ticks); + return npl_funcs->p_ble_npl_callout_reset(co, ticks); } static inline void -ble_npl_callout_stop(struct ble_npl_callout *co) +IRAM_ATTR ble_npl_callout_stop(struct ble_npl_callout *co) { - npl_freertos_callout_stop(co); + return npl_funcs->p_ble_npl_callout_stop(co); } static inline bool -ble_npl_callout_is_active(struct ble_npl_callout *co) +IRAM_ATTR ble_npl_callout_is_active(struct ble_npl_callout *co) { - return npl_freertos_callout_is_active(co); + return npl_funcs->p_ble_npl_callout_is_active(co); } static inline ble_npl_time_t -ble_npl_callout_get_ticks(struct ble_npl_callout *co) +IRAM_ATTR ble_npl_callout_get_ticks(struct ble_npl_callout *co) { - return npl_freertos_callout_get_ticks(co); + return npl_funcs->p_ble_npl_callout_get_ticks(co); } -static inline uint32_t -ble_npl_callout_remaining_ticks(struct ble_npl_callout *co, +static inline ble_npl_time_t +IRAM_ATTR ble_npl_callout_remaining_ticks(struct ble_npl_callout *co, ble_npl_time_t time) { - return npl_freertos_callout_remaining_ticks(co, time); + return npl_funcs->p_ble_npl_callout_remaining_ticks(co, time); } static inline void -ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg) +IRAM_ATTR ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg) { - co->ev.arg = arg; -} - -static inline uint32_t -ble_npl_time_get(void) -{ - return xTaskGetTickCountFromISR(); -} - -static inline ble_npl_error_t -ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) -{ - return npl_freertos_time_ms_to_ticks(ms, out_ticks); -} - -static inline ble_npl_error_t -ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) -{ - return ble_npl_time_ticks_to_ms(ticks, out_ms); + return npl_funcs->p_ble_npl_callout_set_arg(co, arg); } static inline ble_npl_time_t -ble_npl_time_ms_to_ticks32(uint32_t ms) +IRAM_ATTR ble_npl_time_get(void) { - return ms * configTICK_RATE_HZ / 1000; + return npl_funcs->p_ble_npl_time_get(); +} + +static inline ble_npl_error_t +IRAM_ATTR ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) +{ + return npl_funcs->p_ble_npl_time_ms_to_ticks(ms, out_ticks); +} + +static inline ble_npl_error_t +IRAM_ATTR ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) +{ + return npl_funcs->p_ble_npl_time_ticks_to_ms(ticks, out_ms); +} + +static inline ble_npl_time_t +IRAM_ATTR ble_npl_time_ms_to_ticks32(uint32_t ms) +{ + return npl_funcs->p_ble_npl_time_ms_to_ticks32(ms); } static inline uint32_t -ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) +IRAM_ATTR ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) { - return ticks * 1000 / configTICK_RATE_HZ; + return npl_funcs->p_ble_npl_time_ticks_to_ms32(ticks); } static inline void -ble_npl_time_delay(ble_npl_time_t ticks) +IRAM_ATTR ble_npl_time_delay(ble_npl_time_t ticks) { - vTaskDelay(ticks); + return npl_funcs->p_ble_npl_time_delay(ticks); } #if NIMBLE_CFG_CONTROLLER static inline void -ble_npl_hw_set_isr(int irqn, uint32_t addr) +IRAM_ATTR ble_npl_hw_set_isr(int irqn, uint32_t addr) { - npl_freertos_hw_set_isr(irqn, addr); + return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr); } #endif -extern portMUX_TYPE ble_port_mutex; -//critical section static inline uint32_t -ble_npl_hw_enter_critical(void) +IRAM_ATTR ble_npl_hw_enter_critical(void) { - portENTER_CRITICAL(&ble_port_mutex); - return 0; + return npl_funcs->p_ble_npl_hw_enter_critical(); } static inline void -ble_npl_hw_exit_critical(uint32_t ctx) +IRAM_ATTR ble_npl_hw_exit_critical(uint32_t ctx) { - portEXIT_CRITICAL(&ble_port_mutex); - + return npl_funcs->p_ble_npl_hw_exit_critical(ctx); } +static inline bool IRAM_ATTR ble_npl_hw_is_in_critical(void) +{ + return npl_funcs->p_ble_npl_hw_is_in_critical(); +} + +#define ble_npl_get_time_forever (*npl_funcs->p_ble_npl_get_time_forever) +#define ble_npl_callout_mem_reset (*npl_funcs->p_ble_npl_callout_mem_reset) +#define ble_npl_event_deinit (*npl_funcs->p_ble_npl_event_deinit) +#define ble_npl_event_reset (*npl_funcs->p_ble_npl_event_reset) + #ifdef __cplusplus } #endif diff --git a/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/porting/npl/freertos/include/nimble/nimble_port_freertos.h index ddeefc71c..76253d5cd 100644 --- a/porting/npl/freertos/include/nimble/nimble_port_freertos.h +++ b/porting/npl/freertos/include/nimble/nimble_port_freertos.h @@ -28,7 +28,10 @@ extern "C" { void nimble_port_freertos_init(TaskFunction_t host_task_fn); void nimble_port_freertos_deinit(void); - +void npl_freertos_funcs_init(void); +void npl_freertos_funcs_deinit(void); +int npl_freertos_mempool_init(void); +struct npl_funcs_t * npl_freertos_funcs_get(void); #ifdef __cplusplus } #endif diff --git a/porting/npl/freertos/include/nimble/npl_freertos.h b/porting/npl/freertos/include/nimble/npl_freertos.h index c0c7f761a..acc3f6da1 100644 --- a/porting/npl/freertos/include/nimble/npl_freertos.h +++ b/porting/npl/freertos/include/nimble/npl_freertos.h @@ -24,6 +24,40 @@ extern "C" { #endif +typedef void ble_npl_event_fn(struct ble_npl_event *ev); + +struct ble_npl_event_freertos { + bool queued; + ble_npl_event_fn *fn; + void *arg; +}; + +struct ble_npl_eventq_freertos { + QueueHandle_t q; +}; + +struct ble_npl_callout_freertos { +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + esp_timer_handle_t handle; +#else + TimerHandle_t handle; +#endif + struct ble_npl_eventq *evq; + struct ble_npl_event ev; +}; + +struct ble_npl_mutex_freertos { + SemaphoreHandle_t handle; +}; + +struct ble_npl_sem_freertos { + SemaphoreHandle_t handle; +}; + +typedef void ble_npl_event_fn_freertos(struct ble_npl_event_freertos *ev); + +struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void); + struct ble_npl_event *npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo); diff --git a/porting/npl/freertos/src/nimble_port_freertos.c b/porting/npl/freertos/src/nimble_port_freertos.c index f0f80561f..aa33ed475 100644 --- a/porting/npl/freertos/src/nimble_port_freertos.c +++ b/porting/npl/freertos/src/nimble_port_freertos.c @@ -21,10 +21,8 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "nimble/nimble_port.h" +#include "esp_bt.h" -#if NIMBLE_CFG_CONTROLLER -static TaskHandle_t ll_task_h; -#endif static TaskHandle_t host_task_h; void @@ -37,16 +35,14 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * since it has compatible prototype. */ - xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, - NULL, configMAX_PRIORITIES - 1, &ll_task_h); + esp_bt_controller_enable(ESP_BT_MODE_BLE); #endif - /* * Create task where NimBLE host will run. It is not strictly necessary to * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ - xTaskCreatePinnedToCore(host_task_fn, "ble", NIMBLE_STACK_SIZE, + xTaskCreatePinnedToCore(host_task_fn, "ble", NIMBLE_HS_STACK_SIZE, NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); } @@ -56,4 +52,5 @@ nimble_port_freertos_deinit(void) if (host_task_h) { vTaskDelete(host_task_h); } + esp_bt_controller_disable(); } diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index 22b0f9863..f72af604e 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -20,81 +20,303 @@ #include #include #include +#include "syscfg/syscfg.h" #include "nimble/nimble_npl.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/task.h" +#include "freertos/timers.h" #include "freertos/portable.h" +#include "nimble/npl_freertos.h" + +#include "os/os_mempool.h" + #include "esp_log.h" +#include "soc/soc_caps.h" + portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED; +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER static const char *TAG = "Timer"; +#endif + +#define OS_MEM_ALLOC (1) + +#define BLE_HS_HCI_EVT_COUNT \ + (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + \ + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)) + +#define LL_NPL_BASE_EVENT_COUNT (11) +#define LL_SCAN_EXT_AUX_EVT_CNT (MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT)) +#define HCI_LL_NPL_EVENT_COUNT (1) +#define ADV_LL_NPL_EVENT_COUNT ((MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)+1)*3) +#define SCAN_LL_NPL_EVENT_COUNT (2) +#define RL_LL_NPL_EVENT_COUNT (1) +#define SYNC_LL_NPL_EVENT_COUNT (7) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +#define LL_CTRL_TO_HOST_FLOW_CTRL_EVT (1) +#else +#define LL_CTRL_TO_HOST_FLOW_CTRL_EVT (0) +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +#define LL_CFG_FEAT_LE_PING_EVT (1) +#else +#define LL_CFG_FEAT_LE_PING_EVT (0) +#endif + +#define CONN_MODULE_NPL_EVENT_COUNT (((LL_CFG_FEAT_LE_PING_EVT+2)*MYNEWT_VAL(BLE_MAX_CONNECTIONS))+LL_CTRL_TO_HOST_FLOW_CTRL_EVT) + +#define BLE_LL_EV_COUNT (LL_NPL_BASE_EVENT_COUNT + \ + LL_SCAN_EXT_AUX_EVT_CNT + \ + HCI_LL_NPL_EVENT_COUNT + \ + ADV_LL_NPL_EVENT_COUNT + \ + SCAN_LL_NPL_EVENT_COUNT + \ + RL_LL_NPL_EVENT_COUNT + \ + SYNC_LL_NPL_EVENT_COUNT + \ + CONN_MODULE_NPL_EVENT_COUNT) + +#define BLE_TOTAL_EV_COUNT (BLE_LL_EV_COUNT + BLE_HS_HCI_EVT_COUNT) + +#define BLE_TOTAL_EVQ_COUNT (10) + +#define BLE_TOTAL_CO_COUNT (20) + +#define BLE_TOTAL_SEM_COUNT (10) + +#define BLE_TOTAL_MUTEX_COUNT (10) + +#if SOC_ESP_NIMBLE_CONTROLLER + +struct os_mempool ble_freertos_ev_pool; +static os_membuf_t *ble_freertos_ev_buf = NULL; + +struct os_mempool ble_freertos_evq_pool; +static os_membuf_t *ble_freertos_evq_buf = NULL; + +struct os_mempool ble_freertos_co_pool; +static os_membuf_t *ble_freertos_co_buf = NULL; + +struct os_mempool ble_freertos_sem_pool; +static os_membuf_t *ble_freertos_sem_buf = NULL; + +struct os_mempool ble_freertos_mutex_pool; +static os_membuf_t *ble_freertos_mutex_buf = NULL; + +#else + +struct os_mempool ble_freertos_ev_pool; +static os_membuf_t ble_freertos_ev_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) +]; + +struct os_mempool ble_freertos_evq_pool; +static os_membuf_t ble_freertos_evq_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) +]; + +struct os_mempool ble_freertos_co_pool; +static os_membuf_t ble_freertos_co_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos)) +]; + +struct os_mempool ble_freertos_sem_pool; +static os_membuf_t ble_freertos_sem_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos)) +]; + +struct os_mempool ble_freertos_mutex_pool; +static os_membuf_t ble_freertos_mutex_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos)) +]; + +#endif + +bool +IRAM_ATTR npl_freertos_os_started(void) +{ + return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; +} + +void * +IRAM_ATTR npl_freertos_get_current_task_id(void) +{ + return xTaskGetCurrentTaskHandle(); +} + +void +IRAM_ATTR npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, + void *arg) +{ + struct ble_npl_event_freertos *event = NULL; +#if OS_MEM_ALLOC + if (!os_memblock_from(&ble_freertos_ev_pool,ev->event)) { + ev->event = os_memblock_get(&ble_freertos_ev_pool); + } +#else + if(!ev->event) { + ev->event = malloc(sizeof(struct ble_npl_event_freertos)); + } +#endif + event = (struct ble_npl_event_freertos *)ev->event; + BLE_LL_ASSERT(event); + + memset(event, 0, sizeof(*event)); + event->fn = fn; + event->arg = arg; +} + +void +IRAM_ATTR npl_freertos_event_deinit(struct ble_npl_event *ev) +{ + BLE_LL_ASSERT(ev->event); +#if OS_MEM_ALLOC + os_memblock_put(&ble_freertos_ev_pool,ev->event); +#else + free(ev->event); +#endif + ev->event = NULL; +} + +void +IRAM_ATTR npl_freertos_event_reset(struct ble_npl_event *ev) +{ + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + BLE_LL_ASSERT(event); + event->queued = 0; +} + +void +IRAM_ATTR npl_freertos_eventq_init(struct ble_npl_eventq *evq) +{ + struct ble_npl_eventq_freertos *eventq = NULL; +#if OS_MEM_ALLOC + if (!os_memblock_from(&ble_freertos_evq_pool,evq->eventq)) { + evq->eventq = os_memblock_get(&ble_freertos_evq_pool); + eventq = (struct ble_npl_eventq_freertos*)evq->eventq; + BLE_LL_ASSERT(eventq); + + memset(eventq, 0, sizeof(*eventq)); + eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *)); + BLE_LL_ASSERT(eventq->q); + } +#else + if(!evq->eventq) { + evq->eventq = malloc(sizeof(struct ble_npl_eventq_freertos)); + eventq = (struct ble_npl_eventq_freertos*)evq->eventq; + BLE_LL_ASSERT(eventq); + + memset(eventq, 0, sizeof(*eventq)); + eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *)); + BLE_LL_ASSERT(eventq->q); + } +#endif +} + +void +IRAM_ATTR npl_freertos_eventq_deinit(struct ble_npl_eventq *evq) +{ + struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; + + BLE_LL_ASSERT(eventq); + vQueueDelete(eventq->q); +#if OS_MEM_ALLOC + os_memblock_put(&ble_freertos_evq_pool,eventq); +#else + free((void *)eventq); +#endif + evq->eventq = NULL; +} + +void +IRAM_ATTR npl_freertos_callout_mem_reset(struct ble_npl_callout *co) +{ + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; + + BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout->handle); + + ble_npl_event_reset(&callout->ev); +} static inline bool -in_isr(void) +IRAM_ATTR in_isr(void) { /* XXX hw specific! */ return xPortInIsrContext() != 0; } struct ble_npl_event * -npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) +IRAM_ATTR npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) { struct ble_npl_event *ev = NULL; + struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; BaseType_t woken; BaseType_t ret; if (in_isr()) { - assert(tmo == 0); - ret = xQueueReceiveFromISR(evq->q, &ev, &woken); + BLE_LL_ASSERT(tmo == 0); + ret = xQueueReceiveFromISR(eventq->q, &ev, &woken); if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } } else { - ret = xQueueReceive(evq->q, &ev, tmo); + ret = xQueueReceive(eventq->q, &ev, tmo); } - assert(ret == pdPASS || ret == errQUEUE_EMPTY); + BLE_LL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY); if (ev) { - ev->queued = false; + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + if (event) { + event->queued = false; + } } return ev; } void -npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) +IRAM_ATTR npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) { BaseType_t woken; BaseType_t ret; + struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; - if (ev->queued) { + if (event->queued) { return; } - ev->queued = true; + event->queued = true; if (in_isr()) { - ret = xQueueSendToBackFromISR(evq->q, &ev, &woken); + ret = xQueueSendToBackFromISR(eventq->q, &ev, &woken); if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } } else { - ret = xQueueSendToBack(evq->q, &ev, portMAX_DELAY); + ret = xQueueSendToBack(eventq->q, &ev, portMAX_DELAY); } - assert(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); } void -npl_freertos_eventq_remove(struct ble_npl_eventq *evq, - struct ble_npl_event *ev) +IRAM_ATTR npl_freertos_eventq_remove(struct ble_npl_eventq *evq, + struct ble_npl_event *ev) { struct ble_npl_event *tmp_ev; BaseType_t ret; int i; int count; BaseType_t woken, woken2; + struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; - if (!ev->queued) { + if (!event->queued) { return; } @@ -108,18 +330,18 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, if (in_isr()) { woken = pdFALSE; - count = uxQueueMessagesWaitingFromISR(evq->q); + count = uxQueueMessagesWaitingFromISR(eventq->q); for (i = 0; i < count; i++) { - ret = xQueueReceiveFromISR(evq->q, &tmp_ev, &woken2); - assert(ret == pdPASS); + ret = xQueueReceiveFromISR(eventq->q, &tmp_ev, &woken2); + BLE_LL_ASSERT(ret == pdPASS); woken |= woken2; if (tmp_ev == ev) { continue; } - ret = xQueueSendToBackFromISR(evq->q, &tmp_ev, &woken2); - assert(ret == pdPASS); + ret = xQueueSendToBackFromISR(eventq->q, &tmp_ev, &woken2); + BLE_LL_ASSERT(ret == pdPASS); woken |= woken2; } @@ -130,86 +352,155 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&ble_npl_mut); - count = uxQueueMessagesWaiting(evq->q); + count = uxQueueMessagesWaiting(eventq->q); for (i = 0; i < count; i++) { - ret = xQueueReceive(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); + ret = xQueueReceive(eventq->q, &tmp_ev, 0); + BLE_LL_ASSERT(ret == pdPASS); if (tmp_ev == ev) { continue; } - ret = xQueueSendToBack(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); + ret = xQueueSendToBack(eventq->q, &tmp_ev, 0); + BLE_LL_ASSERT(ret == pdPASS); } portEXIT_CRITICAL(&ble_npl_mut); } - ev->queued = 0; + event->queued = 0; } ble_npl_error_t -npl_freertos_mutex_init(struct ble_npl_mutex *mu) +IRAM_ATTR npl_freertos_mutex_init(struct ble_npl_mutex *mu) { - if (!mu) { - return BLE_NPL_INVALID_PARAM; - } + struct ble_npl_mutex_freertos *mutex = NULL; +#if OS_MEM_ALLOC + if (!os_memblock_from(&ble_freertos_mutex_pool,mu->mutex)) { + mu->mutex = os_memblock_get(&ble_freertos_mutex_pool); + mutex = (struct ble_npl_mutex_freertos *)mu->mutex; - mu->handle = xSemaphoreCreateRecursiveMutex(); - assert(mu->handle); + if (!mutex) { + return BLE_NPL_INVALID_PARAM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateRecursiveMutex(); + BLE_LL_ASSERT(mutex->handle); + } +#else + if(!mu->mutex) { + mu->mutex = malloc(sizeof(struct ble_npl_mutex_freertos)); + mutex = (struct ble_npl_mutex_freertos *)mu->mutex; + + if (!mutex) { + return BLE_NPL_INVALID_PARAM; + } + + memset(mutex, 0, sizeof(*mutex)); + mutex->handle = xSemaphoreCreateRecursiveMutex(); + BLE_LL_ASSERT(mutex->handle); + } +#endif return BLE_NPL_OK; } ble_npl_error_t -npl_freertos_mutex_deinit(struct ble_npl_mutex *mu) +IRAM_ATTR npl_freertos_mutex_deinit(struct ble_npl_mutex *mu) { - if (!mu) { + struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex; + + if (!mutex) { return BLE_NPL_INVALID_PARAM; } - if (mu->handle) { - vSemaphoreDelete(mu->handle); - } + BLE_LL_ASSERT(mutex->handle); + vSemaphoreDelete(mutex->handle); + +#if OS_MEM_ALLOC + os_memblock_put(&ble_freertos_mutex_pool,mutex); +#else + free((void *)mutex); +#endif + mu->mutex = NULL; return BLE_NPL_OK; } +void +IRAM_ATTR npl_freertos_event_run(struct ble_npl_event *ev) +{ + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + event->fn(ev); +} + +bool +IRAM_ATTR npl_freertos_eventq_is_empty(struct ble_npl_eventq *evq) +{ + struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; + return xQueueIsQueueEmptyFromISR(eventq->q); +} + +bool +IRAM_ATTR npl_freertos_event_is_queued(struct ble_npl_event *ev) +{ + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + return event->queued; +} + +void * +IRAM_ATTR npl_freertos_event_get_arg(struct ble_npl_event *ev) +{ + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + return event->arg; +} + +void +IRAM_ATTR npl_freertos_event_set_arg(struct ble_npl_event *ev, void *arg) +{ + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; + event->arg = arg; +} + + ble_npl_error_t -npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) +IRAM_ATTR npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) { BaseType_t ret; + struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex; - if (!mu) { + if (!mutex) { return BLE_NPL_INVALID_PARAM; } - assert(mu->handle); + BLE_LL_ASSERT(mutex->handle); if (in_isr()) { ret = pdFAIL; - assert(0); + BLE_LL_ASSERT(0); } else { - ret = xSemaphoreTakeRecursive(mu->handle, timeout); + ret = xSemaphoreTakeRecursive(mutex->handle, timeout); } return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT; } ble_npl_error_t -npl_freertos_mutex_release(struct ble_npl_mutex *mu) +IRAM_ATTR npl_freertos_mutex_release(struct ble_npl_mutex *mu) { - if (!mu) { + struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex; + + if (!mutex) { return BLE_NPL_INVALID_PARAM; } - assert(mu->handle); + BLE_LL_ASSERT(mutex->handle); if (in_isr()) { - assert(0); + BLE_LL_ASSERT(0); } else { - if (xSemaphoreGiveRecursive(mu->handle) != pdPASS) { + if (xSemaphoreGiveRecursive(mutex->handle) != pdPASS) { return BLE_NPL_BAD_MUTEX; } } @@ -218,99 +509,131 @@ npl_freertos_mutex_release(struct ble_npl_mutex *mu) } ble_npl_error_t -npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) +IRAM_ATTR npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { - if (!sem) { - return BLE_NPL_INVALID_PARAM; - } + struct ble_npl_sem_freertos *semaphor = NULL; +#if OS_MEM_ALLOC + if (!os_memblock_from(&ble_freertos_sem_pool,sem->sem)) { + sem->sem = os_memblock_get(&ble_freertos_sem_pool); + semaphor = (struct ble_npl_sem_freertos *)sem->sem; - sem->handle = xSemaphoreCreateCounting(128, tokens); - assert(sem->handle); + if (!semaphor) { + return BLE_NPL_INVALID_PARAM; + } + + memset(semaphor, 0, sizeof(*semaphor)); + semaphor->handle = xSemaphoreCreateCounting(128, tokens); + BLE_LL_ASSERT(semaphor->handle); + } +#else + if(!sem->sem) { + sem->sem = malloc(sizeof(struct ble_npl_sem_freertos)); + semaphor = (struct ble_npl_sem_freertos *)sem->sem; + + if (!semaphor) { + return BLE_NPL_INVALID_PARAM; + } + + memset(semaphor, 0, sizeof(*semaphor)); + semaphor->handle = xSemaphoreCreateCounting(128, tokens); + BLE_LL_ASSERT(semaphor->handle); + } +#endif return BLE_NPL_OK; } ble_npl_error_t -npl_freertos_sem_deinit(struct ble_npl_sem *sem) +IRAM_ATTR npl_freertos_sem_deinit(struct ble_npl_sem *sem) { - if (!sem) { + struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem; + + if (!semaphor) { return BLE_NPL_INVALID_PARAM; } - if (sem->handle) { - vSemaphoreDelete(sem->handle); - } + BLE_LL_ASSERT(semaphor->handle); + vSemaphoreDelete(semaphor->handle); + +#if OS_MEM_ALLOC + os_memblock_put(&ble_freertos_sem_pool,semaphor); +#else + free((void *)semaphor); +#endif + sem->sem = NULL; return BLE_NPL_OK; } ble_npl_error_t -npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) +IRAM_ATTR npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { BaseType_t woken; BaseType_t ret; + struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem; - if (!sem) { + if (!semaphor) { return BLE_NPL_INVALID_PARAM; } - assert(sem->handle); + BLE_LL_ASSERT(semaphor->handle); if (in_isr()) { - assert(timeout == 0); - ret = xSemaphoreTakeFromISR(sem->handle, &woken); + BLE_LL_ASSERT(timeout == 0); + ret = xSemaphoreTakeFromISR(semaphor->handle, &woken); if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } } else { - ret = xSemaphoreTake(sem->handle, timeout); + ret = xSemaphoreTake(semaphor->handle, timeout); } return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT; } ble_npl_error_t -npl_freertos_sem_release(struct ble_npl_sem *sem) +IRAM_ATTR npl_freertos_sem_release(struct ble_npl_sem *sem) { BaseType_t ret; BaseType_t woken; + struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem; - if (!sem) { + if (!semaphor) { return BLE_NPL_INVALID_PARAM; } - assert(sem->handle); + BLE_LL_ASSERT(semaphor->handle); if (in_isr()) { - ret = xSemaphoreGiveFromISR(sem->handle, &woken); - + ret = xSemaphoreGiveFromISR(semaphor->handle, &woken); if( woken == pdTRUE ) { portYIELD_FROM_ISR(); } } else { - ret = xSemaphoreGive(sem->handle); + ret = xSemaphoreGive(semaphor->handle); } - assert(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); return BLE_NPL_OK; } - #if CONFIG_BT_NIMBLE_USE_ESP_TIMER static void -ble_npl_event_fn_wrapper(void *arg) +IRAM_ATTR ble_npl_event_fn_wrapper(void *arg) { - struct ble_npl_callout *co = (struct ble_npl_callout *)arg; + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)arg; + BLE_LL_ASSERT(callout); - if (co->evq) { - ble_npl_eventq_put(co->evq, &co->ev); + if (callout->evq) { + ble_npl_eventq_put(callout->evq, &callout->ev); } else { - co->ev.fn(&co->ev); + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event; + event->fn(&callout->ev); } } static -ble_npl_error_t esp_err_to_npl_error(esp_err_t err) +IRAM_ATTR ble_npl_error_t esp_err_to_npl_error(esp_err_t err) { switch(err) { case ESP_ERR_INVALID_ARG: @@ -322,75 +645,149 @@ ble_npl_error_t esp_err_to_npl_error(esp_err_t err) case ESP_OK: return BLE_NPL_OK; - default: + default: return BLE_NPL_ERROR; } } #else + static void -os_callout_timer_cb(TimerHandle_t timer) +IRAM_ATTR os_callout_timer_cb(TimerHandle_t timer) { - struct ble_npl_callout *co; + struct ble_npl_callout_freertos *callout; - co = pvTimerGetTimerID(timer); - assert(co); + callout = pvTimerGetTimerID(timer); + BLE_LL_ASSERT(callout); - if (co->evq) { - ble_npl_eventq_put(co->evq, &co->ev); + if (callout->evq) { + ble_npl_eventq_put(callout->evq, &callout->ev); } else { - co->ev.fn(&co->ev); + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event; + event->fn(&callout->ev); } } #endif void -npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg) +IRAM_ATTR npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, + ble_npl_event_fn *ev_cb, void *ev_arg) { + struct ble_npl_callout_freertos *callout = NULL; + +#if OS_MEM_ALLOC + if (!os_memblock_from(&ble_freertos_co_pool, co->co)) { + co->co = os_memblock_get(&ble_freertos_co_pool); + callout = (struct ble_npl_callout_freertos *)co->co; + BLE_LL_ASSERT(callout); + + memset(callout, 0, sizeof(*callout)); + #if CONFIG_BT_NIMBLE_USE_ESP_TIMER - co->ev.fn = ev_cb; - co->ev.arg = ev_arg; - co->evq = evq; + callout->ev.fn = ev_cb; + callout->ev.event = ev_arg; + callout->evq = evq; - esp_timer_create_args_t create_args = { - .callback = ble_npl_event_fn_wrapper, - .arg = co, - .name = "nimble_timer" - }; + esp_timer_create_args_t create_args = { + .callback = ble_npl_event_fn_wrapper, + .arg = callout, + .name = "nimble_timer" + }; + + ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle)); - ESP_ERROR_CHECK(esp_timer_create(&create_args, &co->handle)); #else - memset(co, 0, sizeof(*co)); - co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); - co->evq = evq; - ble_npl_event_init(&co->ev, ev_cb, ev_arg); + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); #endif + + BLE_LL_ASSERT(callout->handle); + } else { + callout = (struct ble_npl_callout_freertos *)co->co; + BLE_LL_ASSERT(callout); + } +#else + + if(!co->co) { + co->co = malloc(sizeof(struct ble_npl_callout_freertos)); + callout = (struct ble_npl_callout_freertos *)co->co; + BLE_LL_ASSERT(callout); + + memset(callout, 0, sizeof(*callout)); + +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + callout->ev.fn = ev_cb; + callout->ev.event = ev_arg; + callout->evq = evq; + + esp_timer_create_args_t create_args = { + .callback = ble_npl_event_fn_wrapper, + .arg = callout, + .name = "nimble_timer" + }; + + ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle)); +#else + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); +#endif + + BLE_LL_ASSERT(callout->handle); + } + else { + callout = (struct ble_npl_callout_freertos *)co->co; + BLE_LL_ASSERT(callout); + } +#endif + + callout->evq = evq; + ble_npl_event_init(&callout->ev, ev_cb, ev_arg); } void -npl_freertos_callout_deinit(struct ble_npl_callout *co) +IRAM_ATTR npl_freertos_callout_deinit(struct ble_npl_callout *co) { + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; + + BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout->handle); + #if CONFIG_BT_NIMBLE_USE_ESP_TIMER - if(esp_timer_stop(co->handle)) - ESP_LOGW(TAG, "Timer not stopped"); + if(esp_timer_stop(callout->handle)) + ESP_LOGW(TAG, "Timer not stopped"); + + if(esp_timer_delete(callout->handle)) + ESP_LOGW(TAG, "Timer not deleted"); - if(esp_timer_delete(co->handle)) - ESP_LOGW(TAG, "Timer not deleted"); #else - if (co->handle) { - xTimerDelete(co->handle, portMAX_DELAY); - } + + xTimerDelete(callout->handle, portMAX_DELAY); + ble_npl_event_deinit(&callout->ev); + +#if OS_MEM_ALLOC + os_memblock_put(&ble_freertos_co_pool,callout); +#else + free((void *)callout); #endif + +#endif + co->co = NULL; memset(co, 0, sizeof(struct ble_npl_callout)); } -ble_npl_error_t -npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) +uint16_t +IRAM_ATTR npl_freertos_sem_get_count(struct ble_npl_sem *sem) { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); + struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem; + return uxSemaphoreGetCount(semaphor->handle); +} - return esp_err_to_npl_error(esp_timer_start_once(co->handle, ticks*1000)); + +ble_npl_error_t +IRAM_ATTR npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) +{ + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER + esp_timer_stop(callout->handle); + + return esp_err_to_npl_error(esp_timer_start_once(callout->handle, ticks*1000)); #else BaseType_t woken1, woken2, woken3; @@ -398,19 +795,18 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) if (ticks == 0) { ticks = 1; } - if (in_isr()) { - xTimerStopFromISR(co->handle, &woken1); - xTimerChangePeriodFromISR(co->handle, ticks, &woken2); - xTimerResetFromISR(co->handle, &woken3); + xTimerStopFromISR(callout->handle, &woken1); + xTimerChangePeriodFromISR(callout->handle, ticks, &woken2); + xTimerResetFromISR(callout->handle, &woken3); if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) { portYIELD_FROM_ISR(); } } else { - xTimerStop(co->handle, portMAX_DELAY); - xTimerChangePeriod(co->handle, ticks, portMAX_DELAY); - xTimerReset(co->handle, portMAX_DELAY); + xTimerStop(callout->handle, portMAX_DELAY); + xTimerChangePeriod(callout->handle, ticks, portMAX_DELAY); + xTimerReset(callout->handle, portMAX_DELAY); } return BLE_NPL_OK; @@ -418,27 +814,29 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) } void -npl_freertos_callout_stop(struct ble_npl_callout *co) +IRAM_ATTR npl_freertos_callout_stop(struct ble_npl_callout *co) { + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; #if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); + esp_timer_stop(callout->handle); #else - xTimerStop(co->handle, portMAX_DELAY); + xTimerStop(callout->handle, portMAX_DELAY); #endif } bool -npl_freertos_callout_is_active(struct ble_npl_callout *co) +IRAM_ATTR npl_freertos_callout_is_active(struct ble_npl_callout *co) { + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; #if CONFIG_BT_NIMBLE_USE_ESP_TIMER - return esp_timer_is_active(co->handle); + return esp_timer_is_active(callout->handle); #else - return xTimerIsTimerActive(co->handle) == pdTRUE; + return xTimerIsTimerActive(callout->handle) == pdTRUE; #endif } ble_npl_time_t -npl_freertos_callout_get_ticks(struct ble_npl_callout *co) +IRAM_ATTR npl_freertos_callout_get_ticks(struct ble_npl_callout *co) { #if CONFIG_BT_NIMBLE_USE_ESP_TIMER /* Currently, esp_timer does not support an API which gets the expiry time for @@ -451,24 +849,27 @@ npl_freertos_callout_get_ticks(struct ble_npl_callout *co) return 0; #else - return xTimerGetExpiryTime(co->handle); + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; + return xTimerGetExpiryTime(callout->handle); #endif } ble_npl_time_t -npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, +IRAM_ATTR npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, ble_npl_time_t now) { ble_npl_time_t rt; uint32_t exp = 0; + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; + #if CONFIG_BT_NIMBLE_USE_ESP_TIMER #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) uint64_t expiry = 0; esp_err_t err; //Fetch expiry time in microseconds - err = esp_timer_get_expiry_time((esp_timer_handle_t)(co->handle), &expiry); + err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry); if (err != ESP_OK) { //Error. Could not fetch the expiry time return 0; @@ -482,7 +883,7 @@ npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, exp = 0; #endif //ESP_IDF_VERSION #else - exp = xTimerGetExpiryTime(co->handle); + exp = xTimerGetExpiryTime(callout->handle); #endif if (exp > now) { @@ -494,8 +895,22 @@ npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, return rt; } +void +IRAM_ATTR npl_freertos_callout_set_arg(struct ble_npl_callout *co, void *arg) +{ + struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; + struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event; + event->arg = arg; +} + +uint32_t +IRAM_ATTR npl_freertos_time_get(void) +{ + return xTaskGetTickCountFromISR(); +} + ble_npl_error_t -npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) +IRAM_ATTR npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) { uint64_t ticks; @@ -510,7 +925,7 @@ npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) } ble_npl_error_t -npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) +IRAM_ATTR npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) { uint64_t ms; @@ -523,3 +938,243 @@ npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) return 0; } + +ble_npl_time_t +IRAM_ATTR npl_freertos_time_ms_to_ticks32(uint32_t ms) +{ + return ms * configTICK_RATE_HZ / 1000; +} + +uint32_t +IRAM_ATTR npl_freertos_time_ticks_to_ms32(ble_npl_time_t ticks) +{ + return ticks * 1000 / configTICK_RATE_HZ; +} + +void +IRAM_ATTR npl_freertos_time_delay(ble_npl_time_t ticks) +{ + vTaskDelay(ticks); +} + +#if NIMBLE_CFG_CONTROLLER || CONFIG_NIMBLE_CONTROLLER_MODE +void +IRAM_ATTR npl_freertos_hw_set_isr(int irqn, uint32_t addr) +{ + //Do nothing +} +#endif + + +uint8_t hw_critical_state_status = 0; + +uint32_t +IRAM_ATTR npl_freertos_hw_enter_critical(void) +{ + ++hw_critical_state_status; + portENTER_CRITICAL(&ble_port_mutex); + return 0; +} + +uint8_t +IRAM_ATTR npl_freertos_hw_is_in_critical(void) +{ + return hw_critical_state_status; +} + +void +IRAM_ATTR npl_freertos_hw_exit_critical(uint32_t ctx) +{ + --hw_critical_state_status; + portEXIT_CRITICAL(&ble_port_mutex); + +} + +uint32_t +IRAM_ATTR npl_freertos_get_time_forever(void) +{ + return portMAX_DELAY; +} + +const struct npl_funcs_t npl_funcs_ro = { + .p_ble_npl_os_started = npl_freertos_os_started, + .p_ble_npl_get_current_task_id = npl_freertos_get_current_task_id, + .p_ble_npl_eventq_init = npl_freertos_eventq_init, + .p_ble_npl_eventq_deinit = npl_freertos_eventq_deinit, + .p_ble_npl_eventq_get = npl_freertos_eventq_get, + .p_ble_npl_eventq_put = npl_freertos_eventq_put, + .p_ble_npl_eventq_remove = npl_freertos_eventq_remove, + .p_ble_npl_event_run = npl_freertos_event_run, + .p_ble_npl_eventq_is_empty = npl_freertos_eventq_is_empty, + .p_ble_npl_event_init = npl_freertos_event_init, + .p_ble_npl_event_deinit = npl_freertos_event_deinit, + .p_ble_npl_event_reset = npl_freertos_event_reset, + .p_ble_npl_event_is_queued = npl_freertos_event_is_queued, + .p_ble_npl_event_get_arg = npl_freertos_event_get_arg, + .p_ble_npl_event_set_arg = npl_freertos_event_set_arg, + .p_ble_npl_mutex_init = npl_freertos_mutex_init, + .p_ble_npl_mutex_deinit = npl_freertos_mutex_deinit, + .p_ble_npl_mutex_pend = npl_freertos_mutex_pend, + .p_ble_npl_mutex_release = npl_freertos_mutex_release, + .p_ble_npl_sem_init = npl_freertos_sem_init, + .p_ble_npl_sem_deinit = npl_freertos_sem_deinit, + .p_ble_npl_sem_pend = npl_freertos_sem_pend, + .p_ble_npl_sem_release = npl_freertos_sem_release, + .p_ble_npl_sem_get_count = npl_freertos_sem_get_count, + .p_ble_npl_callout_init = npl_freertos_callout_init, + .p_ble_npl_callout_reset = npl_freertos_callout_reset, + .p_ble_npl_callout_stop = npl_freertos_callout_stop, + .p_ble_npl_callout_deinit = npl_freertos_callout_deinit, + .p_ble_npl_callout_mem_reset = npl_freertos_callout_mem_reset, + .p_ble_npl_callout_is_active = npl_freertos_callout_is_active, + .p_ble_npl_callout_get_ticks = npl_freertos_callout_get_ticks, + .p_ble_npl_callout_remaining_ticks = npl_freertos_callout_remaining_ticks, + .p_ble_npl_callout_set_arg = npl_freertos_callout_set_arg, + .p_ble_npl_time_get = npl_freertos_time_get, + .p_ble_npl_time_ms_to_ticks = npl_freertos_time_ms_to_ticks, + .p_ble_npl_time_ticks_to_ms = npl_freertos_time_ticks_to_ms, + .p_ble_npl_time_ms_to_ticks32 = npl_freertos_time_ms_to_ticks32, + .p_ble_npl_time_ticks_to_ms32 = npl_freertos_time_ticks_to_ms32, + .p_ble_npl_time_delay = npl_freertos_time_delay, +#if NIMBLE_CFG_CONTROLLER || CONFIG_NIMBLE_CONTROLLER_MODE + .p_ble_npl_hw_set_isr = npl_freertos_hw_set_isr, +#endif + .p_ble_npl_hw_enter_critical = npl_freertos_hw_enter_critical, + .p_ble_npl_hw_exit_critical = npl_freertos_hw_exit_critical, + .p_ble_npl_get_time_forever = npl_freertos_get_time_forever, + .p_ble_npl_hw_is_in_critical = npl_freertos_hw_is_in_critical +}; + +struct npl_funcs_t *npl_funcs = NULL; + +struct npl_funcs_t * npl_freertos_funcs_get(void) +{ + return npl_funcs; +} + +void npl_freertos_funcs_init(void) +{ + npl_funcs = (struct npl_funcs_t *)malloc(sizeof(struct npl_funcs_t)); + if(!npl_funcs) { + printf("npl funcs init failed\n"); + assert(0); + } + memcpy(npl_funcs, &npl_funcs_ro, sizeof(struct npl_funcs_t)); +} + +int npl_freertos_mempool_init(void) +{ + int rc = -1; + +#if SOC_ESP_NIMBLE_CONTROLLER + ble_freertos_ev_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t)); + if(!ble_freertos_ev_buf) { + goto _error; + } + ble_freertos_evq_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) * sizeof(os_membuf_t)); + if(!ble_freertos_evq_buf) { + goto _error; + } + ble_freertos_co_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos)) * sizeof(os_membuf_t)); + if(!ble_freertos_co_buf) { + goto _error; + } + ble_freertos_sem_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos)) * sizeof(os_membuf_t)); + if(!ble_freertos_sem_buf) { + goto _error; + } + ble_freertos_mutex_buf = malloc( OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos)) * sizeof(os_membuf_t)); + if(!ble_freertos_mutex_buf) { + goto _error; + } + +#endif + + rc = os_mempool_init(&ble_freertos_ev_pool, BLE_TOTAL_EV_COUNT, + sizeof (struct ble_npl_event_freertos), ble_freertos_ev_buf, + "ble_freertos_ev_pool"); + if(rc != 0) { + goto _error; + } + + rc = os_mempool_init(&ble_freertos_evq_pool, BLE_TOTAL_EVQ_COUNT, + sizeof (struct ble_npl_eventq_freertos), ble_freertos_evq_buf, + "ble_freertos_evq_pool"); + if(rc != 0) { + goto _error; + } + + rc = os_mempool_init(&ble_freertos_co_pool, BLE_TOTAL_CO_COUNT, + sizeof (struct ble_npl_callout_freertos), ble_freertos_co_buf, + "ble_freertos_co_pool"); + if(rc != 0) { + goto _error; + } + + rc = os_mempool_init(&ble_freertos_sem_pool, BLE_TOTAL_SEM_COUNT, + sizeof (struct ble_npl_sem_freertos), ble_freertos_sem_buf, + "ble_freertos_sem_pool"); + if(rc != 0) { + goto _error; + } + + rc = os_mempool_init(&ble_freertos_mutex_pool, BLE_TOTAL_MUTEX_COUNT, + sizeof (struct ble_npl_mutex_freertos), ble_freertos_mutex_buf, + "ble_freertos_mutex_pool"); + if(rc == 0) { + return rc; + } +_error: + +#if SOC_ESP_NIMBLE_CONTROLLER + if(ble_freertos_ev_buf) { + free(ble_freertos_ev_buf); + } + if(ble_freertos_evq_buf) { + free(ble_freertos_evq_buf); + } + if(ble_freertos_co_buf) { + free(ble_freertos_co_buf); + } + if(ble_freertos_sem_buf) { + free(ble_freertos_sem_buf); + } + if(ble_freertos_mutex_buf) { + free(ble_freertos_mutex_buf); + } + return -1; +#else + + BLE_LL_ASSERT(rc == 0); + return rc; +#endif +} + +void npl_freertos_mempool_deinit(void) +{ +#if SOC_ESP_NIMBLE_CONTROLLER + if(ble_freertos_ev_buf) { + free(ble_freertos_ev_buf); + } + if(ble_freertos_evq_buf) { + free(ble_freertos_evq_buf); + } + if(ble_freertos_co_buf) { + free(ble_freertos_co_buf); + } + if(ble_freertos_sem_buf) { + free(ble_freertos_sem_buf); + } + if(ble_freertos_mutex_buf) { + free(ble_freertos_mutex_buf); + } +#endif +} + +void npl_freertos_funcs_deinit(void) +{ + if (npl_funcs) { + free(npl_funcs); + } + npl_funcs = NULL; +}