/** ******************************************************************************* * @file nimble_glue_spark.c * @create 2023-08-01 * @author Panchip BLE GROUP * @note * Copyright (c) 2022 Shanghai Panchip Microelectronics Co.,Ltd. * ******************************************************************************* */ #include #include "FreeRTOS.h" #include "task.h" #include "nimble_syscfg.h" #include "nimble/hci_common.h" #include "pan_ble.h" #include "comm_prf.h" #include "ble_config.h" #include "utility.h" #if CONFIG_LOW_SPEED_CLOCK_SRC == 0 || CONFIG_LOW_SPEED_CLOCK_SRC == 1 #include "soc_api.h" #endif #if CONFIG_OS_EN == 0 #error "user must enable OS...." #endif /**@brief enable ll thread. * !!!Note: user need to increase OS Heap size.!!! */ #define BLE_LL_THREAD_EN 0 #define BLE_LL_THREAD_STACK_SIZE 256 /* unit: in word */ #define BLE_LL_TRHEAD_PRIO 4 /** * @brief BLE host thread parameter config. */ #define BLE_HOST_THREAD_STACK_SIZE CONFIG_BLE_HOST_THREAD_STACK_SIZE #define BLE_HOST_THREAD_PRIO CONFIG_BLE_HOST_THREAD_PRIO /** * @brief BLE LL IRQ Priority Config. */ #ifndef CONFIG_BLE_LL_IRQ_PRIO #define CONFIG_BLE_LL_IRQ_PRIO 0 #endif /** * @brief BLE Event Handler IRQ Priority Config. */ #ifndef CONFIG_BLE_EVT_HANDLER_IRQ_PRIO #define CONFIG_BLE_EVT_HANDLER_IRQ_PRIO 1 #endif #if (configUSE_TICKLESS_IDLE == 1) extern void UpdateTickAndSch(void); #endif static TaskHandle_t host_task_h; static uint8_t ll_enable = false; #if BLE_LL_THREAD_EN SemaphoreHandle_t ll_semphr = NULL; #endif #define HCI_BUF_SIZE_ALIGN4(payload) MEM_ALIGNED4(4 + payload) #ifdef IP_107x #define PAN_BLE_CTLR_BUFFER_SIZE MEM_ALIGNED4(2148 + \ (HCI_BUF_SIZE_ALIGN4(MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE) << 3) + \ (HCI_BUF_SIZE_ALIGN4(65) << 3) + \ (500+256) * (CONFIG_BT_MAX_NUM_OF_CENTRAL + CONFIG_BT_MAX_NUM_OF_PERIPHERAL) + \ 80 * CONFIG_BLE_CONTROLLER_RESOLVELIST_NUM + \ 36 * (2 + CONFIG_BT_MAX_NUM_OF_CENTRAL + CONFIG_BT_MAX_NUM_OF_PERIPHERAL) \ ) #elif defined(IP_101x) #define PAN_BLE_CTLR_BUFFER_SIZE MEM_ALIGNED4(1024 + \ (HCI_BUF_SIZE_ALIGN4(251)*1) + \ (HCI_BUF_SIZE_ALIGN4(65) *1) + \ (500 + 256) * (CONFIG_BT_MAX_NUM_OF_CENTRAL + CONFIG_BT_MAX_NUM_OF_PERIPHERAL) + \ 80 * CONFIG_BLE_CONTROLLER_RESOLVELIST_NUM + \ 36 * (2 + CONFIG_BT_MAX_NUM_OF_CENTRAL + CONFIG_BT_MAX_NUM_OF_PERIPHERAL) \ ) #endif static uint32_t mem_buffer[PAN_BLE_CTLR_BUFFER_SIZE / 4]; static uint32_t mem_pos = 0; static void *mem_alloc(uint32_t size) { void *mem_ret = NULL; char *p_mem = (char *)mem_buffer; if (PAN_BLE_CTLR_BUFFER_SIZE - mem_pos >= size) { mem_ret = &p_mem[mem_pos]; mem_pos += size; } else { #if APP_LOG_EN printf("[E] BLE Heap buffer allocated Failed, need:%d B(%d)\n",size,PAN_BLE_CTLR_BUFFER_SIZE); #endif configASSERT(0); } #if APP_LOG_EN printf("[I] BLE Heap size:%d B, remain:%d B\n", PAN_BLE_CTLR_BUFFER_SIZE, PAN_BLE_CTLR_BUFFER_SIZE - mem_pos); #endif return mem_ret; } /**@brief BLE Configuration */ pan_ble_cfg ble_cfg = { .sleep_clock_source = CONFIG_LOW_SPEED_CLOCK_SRC, .sleep_clock_accuracy = CONFIG_BT_CTLR_SCA, .max_num_of_states = 0, /* unused param */ .tx_power = CONFIG_BT_CTLR_TX_POWER_DFT, .pf_mem_init = mem_alloc, .link_layer_debug = ((CONFIG_IO_TIMING_TRACK && CONFIG_BT_CTLR_LINK_LAYER_DEBUG) ? true:false), .agc_cfg_mode = 0, /* BLE Controller Configuration Parameter. */ #if CONFIG_PM .pmEnable = true, #endif .mstMargin = CONFIG_BLE_CONTROLLER_MASTER_LINK_MARGIN, .wlNum = CONFIG_BLE_CONTROLLER_WIHTELIST_NUM, .rlNum = CONFIG_BLE_CONTROLLER_RESOLVELIST_NUM, .maxMst = CONFIG_BT_MAX_NUM_OF_CENTRAL, .maxSlv = CONFIG_BT_MAX_NUM_OF_PERIPHERAL, .maxAclLen = MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE, .numRxBufs = CONFIG_BLE_CONTROLLER_RF_RX_BUF_NUM, .numTxBufs = CONFIG_BLE_CONTROLLER_RF_TX_BUF_NUM, .numMoreData = CONFIG_BLE_CONTROLLER_MORE_DATA_NUM, .llEncTime = CONFIG_BLE_CONTROLLER_LL_ENC_TIME, }; #if BLE_LL_THREAD_EN void pan_ble_ll_thread_entry(void *p) { while(1) { xSemaphoreTake(ll_semphr, pdMS_TO_TICKS(0xFFFFFFFF)); P22 = 1; pan_ble_handle(); P22=0; } } void ble_ll_thread_create(void) { ll_semphr = xSemaphoreCreateBinary();//xSemaphoreCreateCounting(10, 1); if(ll_semphr == NULL){ #if APP_LOG_EN printf("[E] create ll semphr failed\r\n"); #endif assert(0); } xTaskCreate(pan_ble_ll_thread_entry, "ll", BLE_LL_THREAD_STACK_SIZE, NULL, BLE_LL_TRHEAD_PRIO, NULL); } #endif CONFIG_RAM_CODE int ll_semphr_cback(void) { #if BLE_LL_THREAD_EN if(ll_semphr) { if(IN_ISR()){ BaseType_t pxHigherPriorityTaskWoken = 0; xSemaphoreGiveFromISR(ll_semphr, &pxHigherPriorityTaskWoken); } else{ xSemaphoreGive(ll_semphr); } } #else NVIC_EnableIRQ(BLE_EVENT_PROC_IRQn); NVIC_SetPendingIRQ(BLE_EVENT_PROC_IRQn); #endif return 0; } void on_reset(int reason) { #if APP_LOG_EN printf("[E] %s %d: ble stack error occurs. \r\n", __FILE__, __LINE__); #endif } void ll_init(void) { if(ll_enable){ return; } #if APP_LOG_EN printf("[I] Spark Controller Init Start.\r\n"); #endif /* register 32k clock measure function to controller. (RCL/XTL)*/ #if CONFIG_LOW_SPEED_CLOCK_SRC == 0 || CONFIG_LOW_SPEED_CLOCK_SRC == 1 pan_misc_register_32k_track_cb(clktrim_32k_clk_measure_start, clktrim_32k_clk_measure_value_get); #endif pan_ll_register_hostcopy_cb(host_copydata); pan_ll_register_semphr_cback(ll_semphr_cback); pan_ble_hci_init(ble_hci_evt_ll_to_host_cbk, ble_hci_acl_ll_to_host_cbk); pan_ble_init(&ble_cfg); ll_enable = true; #if APP_LOG_EN printf("[I] Spark Controller Init OK.\r\n"); #endif } void pan_ble_stack_init(ble_stack_pre_init_cb_t ble_stack_pre_init_cb, ble_stack_enabled_cb_t *ble_stack_enabled_cb) { #if APP_LOG_EN printf("[I] ble stack init start...\r\n"); #endif /* Spack controller initialization. */ ll_init(); #ifdef IP_101x extern void *panchip_mem_init(void); if (panchip_mem_init() == NULL){ #if APP_LOG_EN printf("[E] %s %d pan101 allocate memory failed from ll data ram\r\n", __FILE__, __LINE__); #endif assert(0); } #endif /* nimble initialization. */ nimble_port_init(); /* BLE Pre init */ if(ble_stack_pre_init_cb){ ble_stack_pre_init_cb(); } /* Register BLE stack enabled call-back. */ ble_hs_cfg.reset_cb = on_reset; ble_hs_cfg.sync_cb = ble_stack_enabled_cb; /* SMP initialization. */ #if MYNEWT_VAL_BLE_SM_SC || MYNEWT_VAL_BLE_SM_LEGACY ble_hs_cfg.store_status_cb = ble_store_util_status_rr; // use for SMP /* pair info store initialization. */ extern void ble_store_config_init(void); ble_store_config_init(); #endif /* LL IRQ initialization. */ NVIC_EnableIRQ(LL_IRQn); NVIC_SetPriority(LL_IRQn, CONFIG_BLE_LL_IRQ_PRIO); //defult: highest /* Create LL Thread */ #if BLE_LL_THREAD_EN ble_ll_thread_create(); #else NVIC_EnableIRQ(BLE_EVENT_PROC_IRQn); NVIC_SetPriority(BLE_EVENT_PROC_IRQn, CONFIG_BLE_EVT_HANDLER_IRQ_PRIO);//defult: high #endif #if APP_LOG_EN printf("[I] ble host init ok -> ble thread start...\r\n"); #endif /* BLE Host Thread Create. */ pan_ble_thread_create(); } static void pan_ble_thread_entry(void *parameter) { nimble_port_run(); } /** * @brief : create ble stack thread * @param : none. * @return: none. */ void pan_ble_thread_create(void) { xTaskCreate(pan_ble_thread_entry, "host", BLE_HOST_THREAD_STACK_SIZE, NULL, BLE_HOST_THREAD_PRIO, &host_task_h); } /** * @brief: ble stack execute entry. * !!!Note: user need place this API to a thread. * @param : none. * @return: none. */ void pan_ble_stack_start(void) { struct ble_npl_event *ev; //while (1) { ev = ble_npl_eventq_get(nimble_port_get_dflt_eventq(), BLE_NPL_TIME_FOREVER); ble_npl_event_run(ev); //} } void vApplicationUserHook(void) { if(ll_enable){ pan_update_stimer(); } } /** * @brief RF IRQ entry */ CONFIG_RAM_CODE void LL_IRQHandler(void) { PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_LL_IRQ, 1); #ifdef PRF_BLE_DUAL_MODE if (panchip_prf_ble_handler()) { return; } #endif pan_ble_irq(); PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_LL_IRQ, 0); } #if !BLE_LL_THREAD_EN /** * @brief BLE controller event handler */ CONFIG_RAM_CODE void BLE_EVENT_PROC_IRQ(void) { PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_BLE_EVNT_IRQ, 1); pan_ble_handle(); #if (configUSE_TICKLESS_IDLE == 1) UpdateTickAndSch(); #endif PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_BLE_EVNT_IRQ, 0); } #endif int host_copydata(void *from, void *dst, uint16_t len) { struct os_mbuf *om = from; return os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), dst); } void ble_hci_evt_ll_to_host_cbk(uint8_t *p_evt, uint16_t evt_len) { void *buf; if (p_evt[2] == BLE_HCI_LE_SUBEV_ADV_RPT) { buf = ble_transport_alloc_evt(1); } else { buf = ble_transport_alloc_evt(0); } if (buf) { memcpy(buf, p_evt, evt_len); ble_transport_to_hs_evt(buf); } else{ #if APP_LOG_EN printf("[E] %s %d: Host transport alloc HCI Evt buffer failed\n", __FILE__, __LINE__); #endif } } void ble_hci_acl_ll_to_host_cbk(uint8_t *p_acl, uint16_t acl_len) { int ret; struct os_mbuf *om; om = ble_transport_alloc_acl_from_ll(); if (om) { ret = os_mbuf_append(om, p_acl, acl_len); if (ret) { os_mbuf_free_chain(om); } else { ble_transport_to_hs_acl(om); } } else{ #if APP_LOG_EN printf("[E] %s %d: Host transport alloc HCI ACL buffer failed\n", __FILE__, __LINE__); #endif } } int ble_transport_to_ll_acl_impl(struct os_mbuf *om) { int rc = 0; rc = pan_ble_hci_acl_nimble_handle((void *)om, OS_MBUF_PKTLEN(om)); os_mbuf_free_chain(om); return (rc != 0) ? BLE_ERR_MEM_CAPACITY : 0; } int ble_transport_to_ll_cmd_impl(void *buf) { int rc; struct ble_hci_cmd *cmd = buf; rc = pan_ble_hci_cmd_handle(buf, sizeof(struct ble_hci_cmd) + cmd->length, 0, 0); ble_transport_free(cmd); return (rc != 0) ? BLE_ERR_MEM_CAPACITY : 0; } void assert_failed(uint8_t exp, uint32_t errCode, char *fileName, int line) { if(exp == 0){ #if APP_LOG_EN printf("[E]File: %s Line: %d Error:0x%08x\r\n", fileName, line, errCode); #endif while(1) {} } } void pan_misc_set_ll_rx_time_enable(uint8_t en) { pan_svc_interface(SVC_LL_ENABLE_RX_TIME, &en); }