From abc7beac7024d7685aa6a3166459dfa3f013857c Mon Sep 17 00:00:00 2001 From: Zhao Wei Liang Date: Tue, 18 Mar 2025 16:04:40 +0800 Subject: [PATCH] fix(ble): fixed hci assertion issue when uart interference occurs (cherry picked from commit 84f0b39e4d076d7c7eae708a804342a57285b1f2) Co-authored-by: zwl --- .../transport/driver/common/hci_driver_h4.c | 125 +++++++++++++----- .../transport/driver/common/hci_driver_mem.c | 9 +- .../transport/driver/common/hci_driver_util.c | 13 +- .../transport/driver/uart/hci_driver_uart.c | 3 +- .../driver/uart/hci_driver_uart_dma.c | 4 +- .../transport/include/common/hci_driver_h4.h | 15 ++- .../transport/include/common/hci_driver_mem.h | 2 +- .../include/common/hci_driver_util.h | 7 +- 8 files changed, 138 insertions(+), 40 deletions(-) diff --git a/components/bt/porting/transport/driver/common/hci_driver_h4.c b/components/bt/porting/transport/driver/common/hci_driver_h4.c index c31b71164e..2911289cef 100644 --- a/components/bt/porting/transport/driver/common/hci_driver_h4.c +++ b/components/bt/porting/transport/driver/common/hci_driver_h4.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,9 @@ #include #include #include +#include "esp_hci_driver.h" #include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -62,9 +64,11 @@ hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type) case HCI_H4_ISO: rxs->min_len = 4; break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) case HCI_H4_EVT: rxs->min_len = 2; break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) default: /* !TODO: Sync loss. Need to wait for reset. */ return -1; @@ -76,7 +80,7 @@ hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type) static int hci_h4_ib_consume(struct hci_h4_input_buffer *ib, uint16_t len) { - assert(ib->len >= len); + HCI_TRANS_ASSERT((ib->len >= len), ib->len, len); ib->buf += len; ib->len -= len; @@ -113,7 +117,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) switch (h4sm->pkt_type) { case HCI_H4_CMD: - assert(h4sm->allocs && h4sm->allocs->cmd); + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0); h4sm->buf = h4sm->allocs->cmd(); if (!h4sm->buf) { return -1; @@ -124,7 +128,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) break; case HCI_H4_ACL: - assert(h4sm->allocs && h4sm->allocs->acl); + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->acl, 0, 0); h4sm->om = h4sm->allocs->acl(); if (!h4sm->om) { return -1; @@ -145,7 +149,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) } } - assert(h4sm->allocs && h4sm->allocs->evt); + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->evt, 0, 0); /* We can drop legacy advertising events if there's no free buffer in * discardable pool. @@ -167,7 +171,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) break; #endif // !CONFIG_BT_CONTROLLER_ENABLED case HCI_H4_ISO: - assert(h4sm->allocs && h4sm->allocs->iso); + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->iso, 0, 0); h4sm->om = h4sm->allocs->iso(); if (!h4sm->om) { return -1; @@ -177,8 +181,7 @@ hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) h4sm->exp_len = (get_le16(&h4sm->hdr[2]) & 0x7fff) + 4; break; default: - assert(0); - break; + return -2; } return 0; @@ -193,19 +196,18 @@ hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm, int rc; len = min(ib->len, h4sm->exp_len - h4sm->len); - - switch (h4sm->pkt_type) { case HCI_H4_CMD: +#if (!CONFIG_BT_CONTROLLER_ENABLED) case HCI_H4_EVT: +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) if (h4sm->buf) { memcpy(&h4sm->buf[h4sm->len], ib->buf, len); } break; case HCI_H4_ACL: case HCI_H4_ISO: - assert(h4sm->om); - + HCI_TRANS_ASSERT(h4sm->om, h4sm->pkt_type, len); mbuf_len = OS_MBUF_PKTLEN(h4sm->om); rc = os_mbuf_append(h4sm->om, ib->buf, len); if (rc) { @@ -215,13 +217,11 @@ hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm, len = OS_MBUF_PKTLEN(h4sm->om) - mbuf_len; h4sm->len += len; hci_h4_ib_consume(ib, len); - return -1; } break; default: - assert(0); - break; + return -2; } h4sm->len += len; @@ -240,51 +240,110 @@ hci_h4_sm_completed(struct hci_h4_sm *h4sm) #if CONFIG_BT_CONTROLLER_ENABLED case HCI_H4_CMD: if (h4sm->buf) { - assert(h4sm->frame_cb); + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); - assert(rc == 0); + HCI_TRANS_ASSERT(rc == 0, rc, 0); h4sm->buf = NULL; } break; case HCI_H4_ACL: case HCI_H4_ISO: if (h4sm->om) { - assert(h4sm->frame_cb); + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); - assert(rc == 0); + HCI_TRANS_ASSERT(rc == 0, rc, 0); h4sm->om = NULL; } break; #else case HCI_H4_CMD: - case HCI_H4_EVT: if (h4sm->buf) { - assert(h4sm->frame_cb); + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); if (rc != 0) { - ble_transport_free(h4sm->buf); + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->cmd, rc, (uint32_t)h4sm->frees); + h4sm->frees->cmd(h4sm->buf); + } + h4sm->buf = NULL; + } + break; + case HCI_H4_EVT: + if (h4sm->buf) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->evt, rc, (uint32_t)h4sm->frees); + h4sm->frees->evt(h4sm->buf); } h4sm->buf = NULL; } break; case HCI_H4_ACL: - case HCI_H4_ISO: if (h4sm->om) { - assert(h4sm->frame_cb); + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); if (rc != 0) { - os_mbuf_free_chain(h4sm->om); + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->acl, rc, (uint32_t)h4sm->frees); + h4sm->frees->acl(h4sm->om); + } + h4sm->om = NULL; + } + break; + case HCI_H4_ISO: + if (h4sm->om) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->iso, rc, (uint32_t)h4sm->frees); + h4sm->frees->iso(h4sm->om); } h4sm->om = NULL; } break; #endif // CONFIG_BT_CONTROLLER_ENABLED default: - assert(0); + HCI_TRANS_ASSERT(0, h4sm->pkt_type, 0); break; } } +static int +hci_h4_sm_free_buf(struct hci_h4_sm *h4sm) +{ + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + if (h4sm->buf) { + h4sm->frees->cmd(h4sm->buf); + h4sm->buf = NULL; + } + break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: + if (h4sm->buf) { + h4sm->frees->evt(h4sm->buf); + h4sm->buf = NULL; + } + break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_ACL: + if (h4sm->om) { + h4sm->frees->acl(h4sm->om); + h4sm->om = NULL; + } + break; + case HCI_H4_ISO: + if (h4sm->om) { + h4sm->frees->iso(h4sm->om); + h4sm->om = NULL; + } + break; + default: + break; + } + + return 0; +} + int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) { @@ -307,18 +366,18 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) /* no break */ case HCI_H4_SM_W4_HEADER: rc = hci_h4_sm_w4_header(h4sm, &ib); - assert(rc >= 0); if (rc) { break; } + h4sm->state = HCI_H4_SM_W4_PAYLOAD; /* no break */ case HCI_H4_SM_W4_PAYLOAD: rc = hci_h4_sm_w4_payload(h4sm, &ib); - assert(rc >= 0); if (rc) { break; } + h4sm->state = HCI_H4_SM_COMPLETED; /* no break */ case HCI_H4_SM_COMPLETED: @@ -330,6 +389,11 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) } } + if (rc < 0) { + hci_h4_sm_free_buf(h4sm); + h4sm->state = HCI_H4_SM_W4_PKT_TYPE; + return -1; + } /* Calculate consumed bytes * * Note: we should always consume some bytes unless there is an oom error. @@ -339,7 +403,7 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) */ len = len - ib.len; if (len == 0) { - assert(rc < 0); + HCI_TRANS_ASSERT((rc < 0), rc, ib.len); return -1; } @@ -347,10 +411,11 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) } void -hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, +hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, const struct hci_h4_frees *frees, hci_h4_frame_cb *frame_cb) { memset(h4sm, 0, sizeof(*h4sm)); h4sm->allocs = allocs; + h4sm->frees = frees; h4sm->frame_cb = frame_cb; } diff --git a/components/bt/porting/transport/driver/common/hci_driver_mem.c b/components/bt/porting/transport/driver/common/hci_driver_mem.c index acfdf793f6..3505fa627d 100644 --- a/components/bt/porting/transport/driver/common/hci_driver_mem.c +++ b/components/bt/porting/transport/driver/common/hci_driver_mem.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -53,3 +53,10 @@ const struct hci_h4_allocators s_hci_driver_mem_alloc = { .acl = hci_driver_mem_acl_alloc, .iso = hci_driver_mem_iso_alloc, }; + +const struct hci_h4_frees s_hci_driver_mem_free = { + .cmd = r_ble_hci_trans_buf_free, + .evt = r_ble_hci_trans_buf_free, + .acl = os_mbuf_free_chain, + .iso = os_mbuf_free_chain, +}; diff --git a/components/bt/porting/transport/driver/common/hci_driver_util.c b/components/bt/porting/transport/driver/common/hci_driver_util.c index 30fe8d13c4..3c3a49cd78 100644 --- a/components/bt/porting/transport/driver/common/hci_driver_util.c +++ b/components/bt/porting/transport/driver/common/hci_driver_util.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -96,7 +96,7 @@ hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint hci_driver_util_tx_entry_t *tx_entry; tx_entry = os_memblock_get(s_hci_driver_util_env.tx_entry_pool); - assert(tx_entry != NULL); + HCI_TRANS_ASSERT((tx_entry != NULL), 0, 0); tx_entry->data_type = type; tx_entry->data = data; tx_entry->length = len; @@ -149,7 +149,7 @@ hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_ *tx_data = &tx_entry->data[s_hci_driver_util_env.cur_tx_off]; } } else { - assert(0); + HCI_TRANS_ASSERT(0, tx_entry->data_type, data_len); } /* If this is the last frame, inform the invoker not to call this API until the current data * has been completely sent. @@ -223,3 +223,10 @@ hci_driver_util_deinit(void) memset(&s_hci_driver_util_env, 0, sizeof(hci_driver_util_env_t)); } + + +void +hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) +{ + ESP_LOGE(TAG, "hci driver assert: line %d in function %s, param: 0x%x, 0x%x", ln, fn, param1, param2); +} diff --git a/components/bt/porting/transport/driver/uart/hci_driver_uart.c b/components/bt/porting/transport/driver/uart/hci_driver_uart.c index 636cf49749..5ab4938f19 100644 --- a/components/bt/porting/transport/driver/uart/hci_driver_uart.c +++ b/components/bt/porting/transport/driver/uart/hci_driver_uart.c @@ -111,6 +111,7 @@ hci_driver_uart_rx_task(void *p) ESP_LOG_BUFFER_HEXDUMP(TAG, data, read_len, ESP_LOG_DEBUG); ret = hci_h4_sm_rx(s_hci_driver_uart_env.h4_sm, data, read_len); if (ret < 0) { + ESP_LOGE(TAG, "parse rx data error! sm_state:%d\n", s_hci_driver_uart_env.h4_sm->state); r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); } } @@ -175,7 +176,7 @@ hci_driver_uart_init(hci_driver_forward_fn *cb) memset(&s_hci_driver_uart_env, 0, sizeof(hci_driver_uart_env_t)); s_hci_driver_uart_env.h4_sm = &s_hci_driver_uart_h4_sm; - hci_h4_sm_init(s_hci_driver_uart_env.h4_sm, &s_hci_driver_mem_alloc, hci_driver_uart_h4_frame_cb); + hci_h4_sm_init(s_hci_driver_uart_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_h4_frame_cb); rc = hci_driver_util_init(); if (rc) { diff --git a/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c b/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c index 1a12317e91..242ce0f916 100644 --- a/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c +++ b/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -609,7 +609,7 @@ hci_driver_uart_dma_init(hci_driver_forward_fn *cb) memset(&s_hci_driver_uart_dma_env, 0, sizeof(hci_driver_uart_dma_env_t)); s_hci_driver_uart_dma_env.h4_sm = &s_hci_driver_uart_h4_sm; - hci_h4_sm_init(s_hci_driver_uart_dma_env.h4_sm, &s_hci_driver_mem_alloc, hci_driver_uart_dma_h4_frame_cb); + hci_h4_sm_init(s_hci_driver_uart_dma_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_dma_h4_frame_cb); rc = hci_driver_util_init(); if (rc) { diff --git a/components/bt/porting/transport/include/common/hci_driver_h4.h b/components/bt/porting/transport/include/common/hci_driver_h4.h index 32d2dd8ba6..4c8424c7cc 100644 --- a/components/bt/porting/transport/include/common/hci_driver_h4.h +++ b/components/bt/porting/transport/include/common/hci_driver_h4.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,17 @@ struct hci_h4_allocators { extern const struct hci_h4_allocators hci_h4_allocs_from_ll; extern const struct hci_h4_allocators hci_h4_allocs_from_hs; +typedef void (hci_h4_free_cmd)(uint8_t *buf); +typedef void (hci_h4_free_evt)(uint8_t *buf); +typedef int (hci_h4_free_acl)(struct os_mbuf *om); +typedef int (hci_h4_free_iso)(struct os_mbuf *om); +struct hci_h4_frees { + hci_h4_free_cmd *cmd; + hci_h4_free_acl *acl; + hci_h4_free_evt *evt; + hci_h4_free_iso *iso; +}; + typedef int (hci_h4_frame_cb)(uint8_t pkt_type, void *data); struct hci_h4_sm { @@ -63,11 +74,13 @@ struct hci_h4_sm { }; const struct hci_h4_allocators *allocs; + const struct hci_h4_frees *frees; hci_h4_frame_cb *frame_cb; }; void hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, + const struct hci_h4_frees *frees, hci_h4_frame_cb *frame_cb); int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); diff --git a/components/bt/porting/transport/include/common/hci_driver_mem.h b/components/bt/porting/transport/include/common/hci_driver_mem.h index 769b18369e..8a2180e5d6 100644 --- a/components/bt/porting/transport/include/common/hci_driver_mem.h +++ b/components/bt/porting/transport/include/common/hci_driver_mem.h @@ -21,5 +21,5 @@ struct os_mbuf *hci_driver_mem_iso_alloc(void); struct os_mbuf *hci_driver_mem_iso_len_alloc(uint32_t len); extern const struct hci_h4_allocators s_hci_driver_mem_alloc; - +extern const struct hci_h4_frees s_hci_driver_mem_free; #endif // _H_HCI_DRIVER_MEM_ diff --git a/components/bt/porting/transport/include/common/hci_driver_util.h b/components/bt/porting/transport/include/common/hci_driver_util.h index 05b7abd502..2e186e11fc 100644 --- a/components/bt/porting/transport/include/common/hci_driver_util.h +++ b/components/bt/porting/transport/include/common/hci_driver_util.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,4 +15,9 @@ void hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint32_t hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_frame); +void hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); +#define HCI_TRANS_ASSERT(cond, p1, p2) \ + if (!(cond)) { \ + hci_driver_util_assert_check(__LINE__, __func__, p1, p2); \ + } #endif // _H_HCI_DRIVER_UTIL_