1 /***************************************************************************//**
2 * \file cybt_platform_freertos.c
3 *
4 * \brief
5 * Implementation for BT porting interface on FreeRTOS
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2019 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include <string.h>
26 #include "cy_ipc_bt.h"
27 #include "cybt_platform_trace.h"
28 #include "cyabs_rtos.h"
29 #include "cybt_platform_task.h"
30 #include "cybt_platform_interface.h"
31 #include "cybt_platform_internal.h"
32 #include "cybt_platform_config.h"
33 #include "cybt_platform_util.h"
34
35 /******************************************************************************
36 * Constants
37 ******************************************************************************/
38 #define NOT_IN_ISR (false)
39 #define IN_ISR (true)
40
41 /* MCU IPC interupt */
42 #define IPC1_INTERRUPT (btss_interrupt_btss_ipc_IRQn)
43 #define IPC1_PRIORITY (5u) /* IPC1 interrupt priority */
44
45 /* MCU IPC channel definition */
46 #define MCU_IPC_HCI_UL (0) /* For HCI MCU -> BLE */
47 #define MCU_IPC_HCI_DL (1) /* For HCI BLE -> MCU */
48 #define MCU_IPC_HPC_UL (2) /* For HPC MCU -> BLE */
49 #define MCU_IPC_HPC_DL (3) /* For HPC BLE -> MCU */
50
51 /* Interrupt Structure definition */
52 #define IPC_INTR_BLE (0)
53 #define IPC_INTR_MCU (1)
54
55 #define MAX_IPC_RETRIES (20)
56
57 #define RECORD_IPC_STATS
58
59 /*****************************************************************************
60 * Type Definitions
61 *****************************************************************************/
62 typedef struct
63 {
64 bool inited;
65 cy_semaphore_t boot_fully_up;
66 /* Context for MCU IPC */
67 cy_stc_ipc_bt_context_t ipc_context;
68 } hci_interface_t;
69
70 typedef uint16_t bt_task_event_t;
71
72 #ifdef RECORD_IPC_STATS
73 typedef struct {
74 uint32_t get_buf_fail_count; /* Number of get buffer requests that failed. This does not count number of retries performed for same request. */
75 uint32_t get_buf_max_retry_count; /* Maximum number of failed retries permormed for get buffer request. 0 <= MAX_IPC_RETRIES */
76 uint32_t write_fail_count; /* Number of write requests that failed. This does not count number of retries performed for same request. */
77 uint32_t write_max_retry_count; /* Maximum number of failed retries permormed for write request. 0 <= MAX_IPC_RETRIES */
78 }cybt_ipc_stats_t;
79 #endif
80
81 /******************************************************************************
82 * Callback Prototypes
83 ******************************************************************************/
84 cy_en_syspm_status_t cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t* callbackParams,
85 cy_en_syspm_callback_mode_t mode);
86
87 /******************************************************************************
88 * Variables Definitions
89 ******************************************************************************/
90 static hci_interface_t hci_cb;
91 static bt_task_event_t timer_msg = BT_EVT_TIMEOUT;
92 static bt_task_event_t hci_core_msg = BT_EVT_CORE_HCI;
93 static bt_task_event_t hci_boot_msg = BT_EVT_TASK_BOOT_COMPLETES;
94 static bt_task_event_t shutdown_msg = BT_EVT_TASK_SHUTDOWN;
95 static bt_task_event_t buffer_msg = BT_EVT_CORE_HCI_WRITE_BUF_AVAIL;
96 static bt_task_event_t reset_msg = BT_EVT_TASK_RESET_COMPLETE;
97
98 #ifdef RECORD_IPC_STATS
99 static cybt_ipc_stats_t ipc_stats;
100 #endif
101
102 static cy_stc_syspm_callback_params_t cybt_syspm_callback_param = { NULL, NULL };
103 static cy_stc_syspm_callback_t cybt_syspm_callback =
104 {
105 .callback = &cybt_platform_syspm_DeepSleepCallback,
106 .type = (cy_en_syspm_callback_type_t) CY_SYSPM_MODE_DEEPSLEEP_RAM,
107 .callbackParams = &cybt_syspm_callback_param,
108 .order = 253u,
109 };
110
111
112 /******************************************************************************
113 * Function Declarations
114 ******************************************************************************/
115 extern cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr);
116 extern void cybt_platform_exception_handler(cybt_exception_t error, uint8_t *info, uint32_t length);
117
118 /******************************************************************************
119 * Function Definitions
120 ******************************************************************************/
reset_btss(void)121 static void reset_btss(void)
122 {
123 HCIDRV_TRACE_DEBUG("BTSS Reset\n");
124
125 /* It will assert reset ( release group 3 IP ) */
126 (void)Cy_SysClk_PeriGroupSetSlaveCtl(3, CY_SYSCLK_PERI_GROUP_SL_CTL2, 0xFFFFFFFFU); /* Suppress a compiler warning about unused return value */
127
128 /* It will de-assert reset ( release group 3 IP ) */
129 (void)Cy_SysClk_PeriGroupSetSlaveCtl(3, CY_SYSCLK_PERI_GROUP_SL_CTL2, 0x0U); /* Suppress a compiler warning about unused return value */
130
131 HCIDRV_TRACE_DEBUG("BTSS Reset Complete\n");
132 }
133
134 BTSTACK_PORTING_SECTION_BEGIN
notify_rx_not_empty(uint32_t * msg)135 static void notify_rx_not_empty(uint32_t * msg)
136 {
137 cybt_platform_msg_to_bt_task(BT_EVT_CORE_HCI, IN_ISR);
138 return;
139 }
140 BTSTACK_PORTING_SECTION_END
141
notify_write_buffer_available(cy_en_btipc_buftype_t type)142 static void notify_write_buffer_available(cy_en_btipc_buftype_t type)
143 {
144 UNUSED_VARIABLE(type);
145 cybt_platform_msg_to_bt_task(BT_EVT_CORE_HCI_WRITE_BUF_AVAIL, IN_ISR);
146 return;
147 }
148
149 /* IPC IRQ Handler for MCU */
150 BTSTACK_PORTING_SECTION_BEGIN
ipc_irq_handler_mcu(void)151 static void ipc_irq_handler_mcu(void)
152 {
153 CONTROLLER_SLEEP(LOCK); // before Cy_BTIPC_IRQ_Handler
154 Cy_BTIPC_IRQ_Handler(&hci_cb.ipc_context);
155 CONTROLLER_SLEEP(UNLOCK); // after Cy_BTIPC_IRQ_Handler
156 }
157 BTSTACK_PORTING_SECTION_END
158
159 /* Release callback for MCU */
release_on_tx_done(void)160 static void release_on_tx_done(void)
161 {
162
163 }
164
165 #ifdef NOTIFY_IPC_PM
166 /* HPC Notify callback to MCU for power management */
notify_callback_mcu_pm(uint32_t * msg)167 static void notify_callback_mcu_pm(uint32_t * msg)
168 {
169 HCIDRV_TRACE_DEBUG("MCU: HPC Power Manager 0x%lx, 0x%lx\n",msg[0], msg[1]);
170 return;
171 }
172 #endif
173
174 /* HPC Notify callback to MCU for boot type in init process */
notify_callback_mcu_longmsg(uint32_t * msg)175 static void notify_callback_mcu_longmsg(uint32_t * msg)
176 {
177 /* Don't add any prints in ISR Context. It may lead to crash */
178 uint8_t bootType = *(((uint8_t*)msg)+2);
179 switch(bootType)
180 {
181 case CY_BT_IPC_BOOT_CONFIG_WAIT:
182 cybt_platform_msg_to_bt_task(BT_EVT_TASK_BOOT_COMPLETES, IN_ISR);
183 break;
184 case CY_BT_IPC_BOOT_FULLY_UP:
185 #ifdef FPGA_TEST_PLATFORM
186 /* On FPGA, controller does not send CY_BT_IPC_BOOT_CONFIG_WAIT and directly sends CY_BT_IPC_BOOT_FULLY_UP */
187 cybt_platform_msg_to_bt_task(BT_EVT_TASK_BOOT_COMPLETES, IN_ISR);
188 #else
189 cy_rtos_set_semaphore(&hci_cb.boot_fully_up, IN_ISR);
190 #endif /* FPGA_TEST_PLATFORM */
191 break;
192 default:
193 break;
194 }
195 return;
196 }
197
198 #ifdef NOTIFY_IPC_TRNG
199 /* HPC Notify callback to MCU for TRNG */
notify_callback_mcu_trng(uint32_t * msg)200 static void notify_callback_mcu_trng(uint32_t * msg)
201 {
202 HCIDRV_TRACE_DEBUG("MCU: HPC TRNG indication: 0x%lx, 0x%lx\n",msg[0], msg[1]);
203 return;
204 }
205 #endif
206
207 BTSTACK_PORTING_SECTION_BEGIN
ipc_hci_release_buffer(uint32_t * p_msg)208 static cybt_result_t ipc_hci_release_buffer(uint32_t *p_msg)
209 {
210 uint32_t time_out = 2000UL; //2ms
211 cy_en_btipcdrv_status_t ipc_status;
212
213 do
214 {
215 ipc_status = Cy_BTIPC_HCI_RelBuffer(&hci_cb.ipc_context, p_msg);
216
217 if(CY_BT_IPC_DRV_SUCCESS == ipc_status)
218 return CYBT_SUCCESS;
219
220 RELBUF_DELAY(); // default it will be dummy
221
222 time_out--;
223 } while (time_out > 0);
224
225 cybt_platform_exception_handler(CYBT_HCI_IPC_REL_BUFFER, (uint8_t *)&ipc_status, sizeof(ipc_status));
226
227 /* App wants to continue on error, we can proceed */
228 return CYBT_ERR_HCI_IPC_REL_BUFFER_FAILED;
229 }
230 BTSTACK_PORTING_SECTION_END
231
cybt_platform_hci_wait_for_boot_fully_up(bool is_from_isr)232 void cybt_platform_hci_wait_for_boot_fully_up(bool is_from_isr)
233 {
234 cy_rtos_get_semaphore(&hci_cb.boot_fully_up, CY_RTOS_NEVER_TIMEOUT, is_from_isr);
235 }
236
237 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_get_buffer(hci_packet_type_t pti,uint32_t size)238 uint8_t *cybt_platform_hci_get_buffer(hci_packet_type_t pti, uint32_t size)
239 {
240 static uint8_t short_msg[MAX_SHORT_MESG_LENGTH] = {0};
241 cy_en_btipcdrv_status_t ipc_status;
242 uint8_t *p_txbuffer = &short_msg[0];
243 cy_en_btipc_hcipti_t hci_pti = (cy_en_btipc_hcipti_t) pti;
244
245 /* Sleep lock to get and access shared buffer.
246 * It will be unlocked in cybt_platform_hci_write() */
247 CONTROLLER_SLEEP(LOCK); // before get_ipc_write_buffer and ipc_write
248
249 if ( (size > MAX_SHORT_MESG_LENGTH) || (hci_pti == CY_BT_IPC_HCI_ISO) || (hci_pti == CY_BT_IPC_HCI_ACL) )
250 {
251 int retries = 0;
252
253 do
254 {
255 ipc_status = Cy_BTIPC_HCI_GetWriteBufPtr(&hci_cb.ipc_context, hci_pti, (void**)&p_txbuffer, size);
256
257 if (CY_BT_IPC_DRV_SUCCESS != ipc_status)
258 {
259 /* adding a delay before retrying */
260 {
261 volatile int delay = 1000;
262 while(delay--);
263 }
264 //HCIDRV_TRACE_ERROR("MCU Error: IPC Get Buffer to BLE failed 0x%x!\n", ipc_status);
265 #ifdef RECORD_IPC_STATS
266 if (!retries)
267 ++ipc_stats.get_buf_fail_count;
268
269 if (retries > ipc_stats.get_buf_max_retry_count){
270 ipc_stats.get_buf_max_retry_count = retries;
271 }
272 #endif
273 }
274 else {
275 return (p_txbuffer);
276 }
277 }while(++retries < MAX_IPC_RETRIES);
278
279 /* Unlocking here since no buffer available */
280 CONTROLLER_SLEEP(UNLOCK); // if no ipc_write_buffer
281 return (NULL);
282 }
283 return (p_txbuffer);
284 }
285 BTSTACK_PORTING_SECTION_END
286
cybt_platform_hci_post_stack_init(void)287 void cybt_platform_hci_post_stack_init(void)
288 {
289 Cy_BTIPC_Buffer_RegisterCb(&hci_cb.ipc_context, notify_write_buffer_available);
290 }
291
292 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_msg_to_bt_task(const uint16_t msg,bool is_from_isr)293 cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr)
294 {
295 cybt_result_t result;
296 switch(msg)
297 {
298 case BT_EVT_TIMEOUT:
299 result = cybt_send_msg_to_bt_task(&timer_msg, is_from_isr);
300 break;
301 case BT_EVT_CORE_HCI:
302 result = cybt_send_msg_to_bt_task(&hci_core_msg, is_from_isr);
303 break;
304 case BT_EVT_TASK_BOOT_COMPLETES:
305 result = cybt_send_msg_to_bt_task(&hci_boot_msg, is_from_isr);
306 break;
307 case BT_EVT_TASK_SHUTDOWN:
308 result = cybt_send_msg_to_bt_task(&shutdown_msg, is_from_isr);
309 result = cybt_send_msg_to_bt_task(&reset_msg, is_from_isr);
310 break;
311 case BT_EVT_CORE_HCI_WRITE_BUF_AVAIL:
312 result = cybt_send_msg_to_bt_task(&buffer_msg, is_from_isr);
313 break;
314 default:
315 result = CYBT_ERR_BADARG;
316 break;
317 }
318 return (result);
319 }
320 BTSTACK_PORTING_SECTION_END
321
cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)322 cy_en_syspm_status_t cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t* callbackParams,
323 cy_en_syspm_callback_mode_t mode)
324 {
325 cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
326
327 CY_UNUSED_PARAMETER(callbackParams);
328
329 switch (mode)
330 {
331 case CY_SYSPM_CHECK_READY:
332 {
333 retVal = CY_SYSPM_SUCCESS;
334 break;
335 }
336
337 case CY_SYSPM_CHECK_FAIL:
338 {
339 retVal = CY_SYSPM_SUCCESS;
340 break;
341 }
342
343 case CY_SYSPM_BEFORE_TRANSITION:
344 {
345 retVal = CY_SYSPM_SUCCESS;
346 break;
347 }
348
349 case CY_SYSPM_AFTER_TRANSITION:
350 {
351 Cy_BTSS_PowerDep(true);
352 Cy_BTIPC_WarmInit(&hci_cb.ipc_context, (cy_stc_ipc_bt_config_t *) 0xFFFFFFFF);
353 Cy_BTSS_PowerDep(false);
354
355 retVal = CY_SYSPM_SUCCESS;
356 break;
357 }
358
359 default:
360 break;
361 }
362
363 return retVal;
364 }
365
cybt_platform_hci_open(void * p_arg)366 cybt_result_t cybt_platform_hci_open(void *p_arg)
367 {
368 cy_en_btipcdrv_status_t ipc_status;
369 uint32_t interruptState;
370
371 /* MCU IPC Config */
372 cy_stc_ipc_bt_config_t btIpcHciConfig_mcu = {
373 .ulChannelHCI = MCU_IPC_HCI_UL, /* HCI Uplink channel from MCU to BLE */
374 .dlChannelHCI = MCU_IPC_HCI_DL, /* HCI Downlink channel from BLE to MCU */
375 .ulChannelHPC = MCU_IPC_HPC_UL, /* HPC Uplink channel from MCU to BLE */
376 .dlChannelHPC = MCU_IPC_HPC_DL, /* HPC Downlink channel from BLE to MCU */
377
378 .intStuctureSelf = IPC_INTR_MCU, /* Interrupt Structure 1 is used for MCU */
379 .intStucturePeer = IPC_INTR_BLE, /* Interrupt Structure 0 is used for BLE */
380
381 .ipcIntConfig.intrSrc = IPC1_INTERRUPT,
382 .ipcIntConfig.intrPriority = IPC1_PRIORITY,
383
384 /* This handler will be removed later once simulations are done */
385 .irqHandlerPtr = ipc_irq_handler_mcu,
386 /* This callback will be removed later once simulations are done */
387 .internal_hpc_notify_cb = Cy_BTIPC_HPC_Notify,
388
389 .ulReleaseCallbackPtr = release_on_tx_done,
390 .bufCallbackPtr = NULL, // will register once host stack init is done
391 };
392
393 UNUSED_VARIABLE(p_arg);
394
395 if(true == hci_cb.inited)
396 {
397 return CYBT_SUCCESS;
398 }
399
400 /* host power domain: CY_PD_PDCM_MAIN (MAIN Power domain)
401 * destination power doamin: CY_PD_PDCM_BTSS (BTSS Power domain)
402 * cy_pd_pdcm_set_dependency() will create dependency settting of host on destination.
403 * which indirectly means host will not go into deep sleep until destination is running.*/
404 (void)cy_pd_pdcm_set_dependency(CY_PD_PDCM_MAIN, CY_PD_PDCM_BTSS); /* Suppress a compiler warning about unused return value */
405
406 memset(&hci_cb, 0, sizeof(hci_interface_t));
407
408 cy_rtos_init_semaphore(&hci_cb.boot_fully_up, 1, 0);
409
410 interruptState = Cy_SysLib_EnterCriticalSection();
411 reset_btss();
412
413 CONTROLLER_SLEEP(LOCK); // Cy_BTIPC_Init lock
414 ipc_status = Cy_BTIPC_Init(&hci_cb.ipc_context, &btIpcHciConfig_mcu);
415 CONTROLLER_SLEEP(UNLOCK); // Cy_BTIPC_Init unlock
416
417 if (ipc_status)
418 {
419 HCIDRV_TRACE_ERROR("MCU Error: IPC HCI Init failed !\n");
420 CY_ASSERT(0);
421 }
422
423 /* MCU Register HCI notify callback */
424 ipc_status = Cy_BTIPC_HCI_RegisterCb(&hci_cb.ipc_context, notify_rx_not_empty);
425 if (ipc_status)
426 {
427 HCIDRV_TRACE_ERROR("MCU Error: IPC HCI Notify Cb register failed 0x%x!\n", ipc_status);
428 CY_ASSERT(0);
429 }
430
431 /* MCU Register HPC callback for power management */
432 {
433 cy_stc_ipc_hcp_cb_t notifyCallbackParam[] = {
434 #ifdef NOTIFY_IPC_PM
435 {.hpcNotifyCallbackPtr = notify_callback_mcu_pm, .msgType = CY_BT_IPC_HPC_PM},
436 #endif
437 {.hpcNotifyCallbackPtr = notify_callback_mcu_longmsg, .msgType = CY_BT_IPC_HPC_LONG},
438 #ifdef NOTIFY_IPC_TRNG
439 {.hpcNotifyCallbackPtr = notify_callback_mcu_trng, .msgType = CY_BT_IPC_HPC_REQTRNG},
440 #endif
441 };
442
443 for (int i = 0; i < sizeof(notifyCallbackParam)/sizeof(notifyCallbackParam[0]); i++)
444 {
445 if(notifyCallbackParam[i].hpcNotifyCallbackPtr){
446 ipc_status = Cy_BTIPC_HPC_RegisterCb(&hci_cb.ipc_context, ¬ifyCallbackParam[i]);
447 if (ipc_status)
448 {
449 HCIDRV_TRACE_ERROR("MCU Error: IPC register %d failed 0x%x!\n", i, ipc_status);
450 CY_ASSERT(0);
451 }
452 }
453 }
454 }
455
456 Cy_SysLib_ExitCriticalSection(interruptState);
457
458 if (!Cy_SysPm_RegisterCallback(&cybt_syspm_callback))
459 {
460 HCIDRV_TRACE_ERROR("MCU Error: Syspm Callback registering failed 0x%x!\n", ipc_status);
461 CY_ASSERT(0);
462 }
463
464 hci_cb.inited = true;
465
466 HCIDRV_TRACE_DEBUG("hci_open(): Done");
467
468 return CYBT_SUCCESS;
469 }
470
471 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_write(hci_packet_type_t pti,uint8_t * p_data,uint32_t length)472 cybt_result_t cybt_platform_hci_write(hci_packet_type_t pti,
473 uint8_t *p_data,
474 uint32_t length
475 )
476 {
477 cybt_result_t status = CYBT_SUCCESS;
478 cy_en_btipcdrv_status_t ipc_status;
479 int retries = 0;
480
481 do
482 {
483 ipc_status = Cy_BTIPC_HCI_Write(&hci_cb.ipc_context, (cy_en_btipc_hcipti_t)pti, p_data, length);
484
485 if (ipc_status)
486 {
487 /* adding a delay before retrying */
488 {
489 volatile int delay = 1000;
490 while(delay--);
491 }
492
493 status = CYBT_ERR_HCI_WRITE_FAILED;
494
495 #ifdef RECORD_IPC_STATS
496 if (!retries)
497 ++ipc_stats.write_fail_count;
498
499 if (retries > ipc_stats.write_max_retry_count){
500 ipc_stats.write_max_retry_count = retries;
501 }
502 #endif
503 }else{
504 status = CYBT_SUCCESS;
505 break;
506 }
507 }while(++retries < MAX_IPC_RETRIES);
508
509 /* Sleep unlock which was already locked in cybt_platform_hci_get_buffer */
510 CONTROLLER_SLEEP(UNLOCK); // after get_ipc_write_buffer and ipc_write
511 return status;
512 }
513 BTSTACK_PORTING_SECTION_END
514
515 BTSTACK_PORTING_SECTION_BEGIN
cybt_platfrom_hci_get_rx_fifo_count(void)516 uint16_t cybt_platfrom_hci_get_rx_fifo_count(void)
517 {
518 if(!hci_cb.inited)
519 return 0;
520 return (Cy_BTIPC_HCI_FIFOCount(&hci_cb.ipc_context));
521 }
522 BTSTACK_PORTING_SECTION_END
523
524 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_read(void * event,hci_packet_type_t * pti,uint8_t * p_data,uint32_t * p_length)525 cybt_result_t cybt_platform_hci_read(void *event,
526 hci_packet_type_t *pti,
527 uint8_t *p_data,
528 uint32_t *p_length
529 )
530 {
531 cybt_result_t status = CYBT_SUCCESS;
532 uint8_t *ptr_rx_hci = NULL;
533 uint32_t *p_msg = NULL;
534
535 UNUSED_VARIABLE(event);
536
537 if(!(hci_cb.inited && pti && p_data && p_length))
538 {
539 HCIDRV_TRACE_ERROR("hci_read(): UART is NOT initialized");
540 return CYBT_ERR_HCI_NOT_INITIALIZE;
541 }
542
543 CONTROLLER_SLEEP(LOCK); // before ipc_read
544
545 /* cybt_platform_hci_read only be called when FIFO count is non-zero.
546 * And NULL check already handling in the beginning.
547 * Hence no need to check return values for below IPC API's */
548 Cy_BTIPC_HCI_FIFOGet(&hci_cb.ipc_context, &p_msg, 0);
549 Cy_BTIPC_HCI_getPTI ((cy_en_btipc_hcipti_t *)pti, p_length, p_msg);
550 Cy_BTIPC_HCI_GetReadBufPtr (&hci_cb.ipc_context, (void**)&ptr_rx_hci, (size_t*)p_length);
551
552 memcpy((uint8_t*)p_data, ptr_rx_hci, *p_length);
553 status = ipc_hci_release_buffer(p_msg);
554
555 CONTROLLER_SLEEP(UNLOCK); // after ipc_read
556
557 return status;
558 }
559 BTSTACK_PORTING_SECTION_END
560
cybt_platform_hci_close(void)561 cybt_result_t cybt_platform_hci_close(void)
562 {
563 cybt_result_t status = CYBT_SUCCESS;
564 if(false == hci_cb.inited)
565 {
566 HCIDRV_TRACE_ERROR("hci_close(): Not inited\n");
567 return CYBT_ERR_HCI_NOT_INITIALIZE;
568 }
569
570 if(CY_BT_IPC_DRV_SUCCESS != Cy_BTIPC_Deinit(&hci_cb.ipc_context))
571 {
572 HCIDRV_TRACE_ERROR("hci_close(): Cy_BTIPC_Deinit failed\n");
573 status = CYBT_ERR_HCI_IPC_DEINIT_FAILED;
574 }
575
576 if (!Cy_SysPm_UnregisterCallback(&cybt_syspm_callback))
577 {
578 HCIDRV_TRACE_ERROR("MCU Error: Syspm Callback Unregistering failed!\n");
579 CY_ASSERT(0);
580 }
581
582 memset(&hci_cb, 0, sizeof(hci_interface_t));
583
584 return status;
585 }
586
587 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_get_event_id(void * event)588 uint16_t cybt_platform_get_event_id(void *event)
589 {
590 bt_task_event_t *evt = (bt_task_event_t *)event;
591 return (*evt);
592 }
593 BTSTACK_PORTING_SECTION_END
594
cybt_platform_hci_set_baudrate(uint32_t baudrate)595 cybt_result_t cybt_platform_hci_set_baudrate(uint32_t baudrate)
596 {
597 /* This function is not applicable if HCI communication is using IPC instead UART
598 * Only reason to keeping this function is to maintain compatibility
599 */
600
601 UNUSED_VARIABLE(baudrate);
602 return CYBT_SUCCESS;
603 }
604
605 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_process_if_coredump(uint8_t * p_data,uint32_t length)606 bool cybt_platform_hci_process_if_coredump(uint8_t *p_data, uint32_t length)
607 {
608 if (0xF4FF != *((uint16_t *)&p_data[0]))
609 {
610 /* Packet raw data will be like this
611 * fff41b03107907020000001800000004000081f0d80020000000000000000000
612 * 0xFFF4 opcode, 0x1B DBFW dump event subcode, 0x03 dumpp type, 0x10 length, 0x79 check sum */
613 return false;
614 }
615
616 /* You may get multiple core dump packets don't assert here */
617 cybt_platform_exception_handler(CYBT_CONTROLLER_CORE_DUMP, p_data, length);
618 return true;
619 }
620 BTSTACK_PORTING_SECTION_END
621
622 #ifdef RECORD_IPC_STATS
cybt_platform_hci_get_ipc_stats(cybt_ipc_stats_t * p_stats)623 cybt_result_t cybt_platform_hci_get_ipc_stats(cybt_ipc_stats_t *p_stats)
624 {
625 p_stats->get_buf_fail_count = ipc_stats.get_buf_fail_count;
626 p_stats->get_buf_max_retry_count = ipc_stats.get_buf_max_retry_count;
627 p_stats->write_fail_count = ipc_stats.write_fail_count;
628 p_stats->write_max_retry_count = ipc_stats.write_max_retry_count;
629 return CYBT_SUCCESS;
630 }
631 #endif
632