cybt_debug_uart.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. #include "cybt_platform_config.h"
  2. #ifdef ENABLE_DEBUG_UART
  3. #include "cyhal_uart.h"
  4. #include "cyabs_rtos.h"
  5. #include "cybsp_types.h"
  6. #include "cybt_platform_task.h"
  7. #include "cybt_debug_uart.h"
  8. #include "cybt_platform_interface.h"
  9. #include "wiced_memory.h"
  10. #define HCI_WICED_PKT 0x19
  11. #define BT_TASK_NAME_DEBUG_UART_TX "CYBT_DEBUG_UART_TX_Task"
  12. #define BT_TASK_NAME_DEBUG_UART_RX "CYBT_DEBUG_UART_RX_Task"
  13. #define DEBUG_UART_TX_TASK_STACK_SIZE (0x1800)
  14. #define DEBUG_UART_RX_TASK_STACK_SIZE (0x1800)
  15. #define DEBUG_UART_TX_TASK_QUEUE_COUNT (20)
  16. #define DEBUG_UART_TX_QUEUE_ITEM_SIZE (sizeof(void *))
  17. #define DEBUG_UART_TX_TASK_QUEUE cybt_debug_uart_tx_queue
  18. #define DEBUG_UART_TX_TASK_PRIORITY (CY_RTOS_PRIORITY_ABOVENORMAL)
  19. #define DEBUG_UART_RX_TASK_PRIORITY (CY_RTOS_PRIORITY_ABOVENORMAL)
  20. #define WICED_HDR_SZ 5
  21. #define MAX_TRACE_DATA_LEN 1000
  22. #define MAX_RX_DATA_LEN 1000
  23. #define DEBUG_UART_MEMORY_SIZE (MAX_TRACE_DATA_LEN * 6)
  24. #define HCI_CONTROL_GROUP_DEVICE 0x00
  25. #define HCI_CONTROL_EVENT_WICED_TRACE ( ( HCI_CONTROL_GROUP_DEVICE << 8 ) | 0x02 ) /* WICED trace packet */
  26. #define HCI_CONTROL_EVENT_HCI_TRACE ( ( HCI_CONTROL_GROUP_DEVICE << 8 ) | 0x03 ) /* Bluetooth protocol trace */
  27. #define INVALID_TYPE 0xFF
  28. wiced_bt_heap_t *debug_task_heap = NULL;
  29. enum
  30. {
  31. HEADER_PHASE = 0,
  32. DATA_PHASE
  33. };
  34. typedef struct
  35. {
  36. bool inited;
  37. cyhal_uart_t hal_obj;
  38. cy_semaphore_t tx_complete;
  39. cy_semaphore_t rx_complete;
  40. cy_semaphore_t tx_ready;
  41. cy_mutex_t tx_atomic;
  42. bool rx_done;
  43. cybt_debug_uart_data_handler_t rx_cb;
  44. } debug_uart_cb_t;
  45. typedef struct
  46. {
  47. int opcode;
  48. uint16_t length;
  49. uint16_t type;
  50. uint8_t *data;
  51. }trace_data_t;
  52. debug_uart_cb_t cy_trans_uart;
  53. cy_queue_t cybt_debug_uart_tx_queue;
  54. cy_thread_t cybt_debug_uart_tx_task;
  55. cy_thread_t cybt_debug_uart_rx_task;
  56. /*
  57. * Global variable declarations
  58. */
  59. static uint8_t wiced_rx_cmd[MAX_RX_DATA_LEN+WICED_HDR_SZ]; //RX command pool.
  60. volatile uint32_t phase=HEADER_PHASE,data_counter=0;
  61. cybt_result_t cybt_trans_write (uint8_t type, uint16_t opcode, uint16_t data_size, uint8_t *p_data);
  62. static cybt_result_t cybt_handle_received_tx_data(uint16_t type, uint16_t op,uint16_t length, uint8_t* p_data);
  63. uint32_t cybt_get_read_request_len(void)
  64. {
  65. if (phase == DATA_PHASE)
  66. return data_counter;
  67. return WICED_HDR_SZ;
  68. }
  69. static void *cybt_platform_debug_task_mempool_alloc(uint32_t req_size)
  70. {
  71. void *p_mem_block;
  72. if(NULL == debug_task_heap)
  73. {
  74. return NULL;
  75. }
  76. cybt_platform_disable_irq();
  77. p_mem_block = (void *) wiced_bt_get_buffer_from_heap(debug_task_heap, req_size);
  78. cybt_platform_enable_irq();
  79. return p_mem_block;
  80. }
  81. static void cybt_platform_debug_task_mempool_free(void *p_mem_block)
  82. {
  83. if(NULL == debug_task_heap)
  84. {
  85. return;
  86. }
  87. cybt_platform_disable_irq();
  88. wiced_bt_free_buffer((wiced_bt_buffer_t *) p_mem_block);
  89. cybt_platform_enable_irq();
  90. }
  91. static cybt_result_t cybt_handle_received_tx_data(uint16_t type, uint16_t opcode,uint16_t length, uint8_t* p_data)
  92. {
  93. trace_data_t *data = NULL;
  94. cy_rslt_t result = CYBT_ERR_GENERIC;
  95. size_t count = 0;
  96. if (!debug_task_heap || (length > MAX_TRACE_DATA_LEN) )
  97. return CYBT_ERR_GENERIC;
  98. result = cy_rtos_get_semaphore(&cy_trans_uart.tx_ready, CY_RTOS_NEVER_TIMEOUT, false);
  99. if(CY_RSLT_SUCCESS != result)
  100. {
  101. return CYBT_ERR_GENERIC;
  102. }
  103. result = cy_rtos_count_queue(&DEBUG_UART_TX_TASK_QUEUE, &count);
  104. if ( (result != CY_RSLT_SUCCESS) || (count == DEBUG_UART_TX_TASK_QUEUE_COUNT))
  105. {
  106. cy_rtos_set_semaphore(&cy_trans_uart.tx_ready, false);
  107. return CYBT_ERR_QUEUE_FULL;
  108. }
  109. data = cybt_platform_debug_task_mempool_alloc(sizeof(trace_data_t) + length + 3);
  110. if (data == NULL)
  111. {
  112. cy_rtos_set_semaphore(&cy_trans_uart.tx_ready, false);
  113. return CYBT_ERR_OUT_OF_MEMORY;
  114. }
  115. data->opcode = opcode;
  116. data->length = length;
  117. data->type = type;
  118. data->data = (uint8_t *)(data + 1);
  119. memcpy(data->data, p_data, length);
  120. result = cy_rtos_put_queue(&DEBUG_UART_TX_TASK_QUEUE, (void *) &data, 0, false);
  121. if(CY_RSLT_SUCCESS != result)
  122. {
  123. cybt_platform_debug_task_mempool_free((void *)data);
  124. }
  125. cy_rtos_set_semaphore(&cy_trans_uart.tx_ready, false);
  126. return CYBT_SUCCESS;
  127. }
  128. static void cybt_debug_rx_task(void *arg)
  129. {
  130. cy_rslt_t result;
  131. volatile uint32_t numAvailable;
  132. volatile size_t expectedlength = 0;
  133. volatile uint32_t data_index = 0;
  134. while(1)
  135. {
  136. result = cy_rtos_get_semaphore(&cy_trans_uart.rx_complete, CY_RTOS_NEVER_TIMEOUT, false);
  137. if (result != CY_RSLT_SUCCESS)
  138. {
  139. continue;
  140. }
  141. numAvailable = 0;
  142. expectedlength = cybt_get_read_request_len();
  143. if (!cy_trans_uart.rx_done)
  144. {
  145. numAvailable = cyhal_uart_readable(&cy_trans_uart.hal_obj);
  146. if (numAvailable >= expectedlength)
  147. {
  148. cyhal_uart_read(&cy_trans_uart.hal_obj, wiced_rx_cmd + data_index, (size_t *)&expectedlength);
  149. numAvailable -= expectedlength;
  150. }
  151. else
  152. {
  153. cyhal_uart_enable_event(&cy_trans_uart.hal_obj, CYHAL_UART_IRQ_RX_DONE, CYHAL_ISR_PRIORITY_DEFAULT, true);
  154. cyhal_uart_read_async(&cy_trans_uart.hal_obj, wiced_rx_cmd + data_index, expectedlength);
  155. continue;
  156. }
  157. }
  158. switch(phase)
  159. {
  160. case HEADER_PHASE:
  161. if(wiced_rx_cmd[0] != HCI_WICED_PKT)
  162. {
  163. data_index=0x0;
  164. break;
  165. }
  166. data_counter = ( wiced_rx_cmd[3] | (uint32_t)(wiced_rx_cmd[4])<<8);
  167. data_index += WICED_HDR_SZ;
  168. phase = DATA_PHASE;
  169. break;
  170. case DATA_PHASE:
  171. data_counter -= expectedlength;
  172. data_index += expectedlength;
  173. break;
  174. }
  175. if(data_counter==0 && (cy_trans_uart.rx_cb != NULL))
  176. {
  177. phase = HEADER_PHASE;
  178. cy_trans_uart.rx_cb(wiced_rx_cmd+1, data_index-1);
  179. data_index = 0;
  180. }
  181. cy_trans_uart.rx_done = false;
  182. if (numAvailable)
  183. {
  184. // re-enter the loop if data is available
  185. cy_rtos_set_semaphore(&cy_trans_uart.rx_complete, true);
  186. continue;
  187. }
  188. cyhal_uart_enable_event(&cy_trans_uart.hal_obj, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, true);
  189. }
  190. }
  191. static void cybt_debug_tx_task(void *arg)
  192. {
  193. cy_rslt_t result;
  194. trace_data_t *data = NULL;
  195. while(1)
  196. {
  197. data = NULL;
  198. result = cy_rtos_get_queue(&DEBUG_UART_TX_TASK_QUEUE,
  199. (void *)&data,
  200. CY_RTOS_NEVER_TIMEOUT,
  201. false
  202. );
  203. if(CY_RSLT_SUCCESS != result || NULL == data)
  204. {
  205. continue;
  206. }
  207. cybt_trans_write(data->type,data->opcode, (uint32_t)data->length, data->data);
  208. cybt_platform_debug_task_mempool_free(data);
  209. }
  210. }
  211. cybt_result_t cybt_init_debug_trans_task(void)
  212. {
  213. cy_rslt_t result;
  214. void *p_heap_mem = NULL;
  215. result = cy_rtos_init_queue(&DEBUG_UART_TX_TASK_QUEUE,
  216. DEBUG_UART_TX_TASK_QUEUE_COUNT,
  217. DEBUG_UART_TX_QUEUE_ITEM_SIZE
  218. );
  219. if (result != CY_RSLT_SUCCESS)
  220. return CYBT_ERR_INIT_QUEUE_FAILED;
  221. result = cy_rtos_create_thread(&cybt_debug_uart_tx_task,
  222. cybt_debug_tx_task,
  223. BT_TASK_NAME_DEBUG_UART_TX,
  224. NULL,
  225. DEBUG_UART_TX_TASK_STACK_SIZE,
  226. DEBUG_UART_TX_TASK_PRIORITY,
  227. (cy_thread_arg_t) NULL
  228. );
  229. if (result != CY_RSLT_SUCCESS)
  230. return CYBT_ERR_CREATE_TASK_FAILED;
  231. result = cy_rtos_create_thread(&cybt_debug_uart_rx_task,
  232. cybt_debug_rx_task,
  233. BT_TASK_NAME_DEBUG_UART_RX,
  234. NULL,
  235. DEBUG_UART_RX_TASK_STACK_SIZE,
  236. DEBUG_UART_RX_TASK_PRIORITY,
  237. (cy_thread_arg_t) NULL
  238. );
  239. if (result != CY_RSLT_SUCCESS)
  240. return CYBT_ERR_CREATE_TASK_FAILED;
  241. p_heap_mem = (wiced_bt_heap_t *)cybt_platform_malloc(DEBUG_UART_MEMORY_SIZE);
  242. if (p_heap_mem == NULL)
  243. return CYBT_ERR_OUT_OF_MEMORY;
  244. debug_task_heap = wiced_bt_create_heap("CYBT_DEBUG_TASK_POOL",
  245. p_heap_mem,
  246. DEBUG_UART_MEMORY_SIZE,
  247. NULL,
  248. FALSE
  249. );
  250. return CYBT_SUCCESS;
  251. }
  252. static void cybt_uart_tx_irq(void)
  253. {
  254. cy_rtos_set_semaphore(&cy_trans_uart.tx_complete, true);
  255. }
  256. static void cybt_uart_irq_handler_(void *handler_arg, cyhal_uart_event_t event)
  257. {
  258. switch(event)
  259. {
  260. case CYHAL_UART_IRQ_RX_NOT_EMPTY:
  261. cyhal_uart_enable_event(&cy_trans_uart.hal_obj, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, false);
  262. cy_rtos_set_semaphore(&cy_trans_uart.rx_complete, true);
  263. break;
  264. case CYHAL_UART_IRQ_RX_DONE:
  265. cyhal_uart_enable_event(&cy_trans_uart.hal_obj, CYHAL_UART_IRQ_RX_DONE, CYHAL_ISR_PRIORITY_DEFAULT, false);
  266. cy_rtos_set_semaphore(&cy_trans_uart.rx_complete, true);
  267. cy_trans_uart.rx_done = true;
  268. break;
  269. case CYHAL_UART_IRQ_TX_DONE:
  270. cybt_uart_tx_irq();
  271. break;
  272. default:
  273. break;
  274. }
  275. }
  276. cybt_result_t cybt_debug_uart_init(cybt_debug_uart_config_t *config, cybt_debug_uart_data_handler_t p_data_handler)
  277. {
  278. const cyhal_uart_cfg_t uart_config =
  279. {
  280. .data_bits = 8,
  281. .stop_bits = 1,
  282. .parity = CYHAL_UART_PARITY_NONE,
  283. .rx_buffer = NULL,
  284. .rx_buffer_size = 0,
  285. };
  286. uint16_t enable_irq_event = (CYHAL_UART_IRQ_TX_DONE
  287. | CYHAL_UART_IRQ_RX_NOT_EMPTY
  288. );
  289. if (!config)
  290. {
  291. return CYBT_ERR_BADARG;
  292. }
  293. memset(&cy_trans_uart, 0, sizeof(debug_uart_cb_t));
  294. #if (CYHAL_API_VERSION >= 2)
  295. cy_rslt_t result = cyhal_uart_init(&cy_trans_uart.hal_obj,
  296. config->uart_tx_pin,
  297. config->uart_rx_pin,
  298. config->uart_cts_pin,
  299. config->uart_rts_pin,
  300. NULL,
  301. &uart_config
  302. );
  303. #else
  304. cy_rslt_t result = cyhal_uart_init(&cy_trans_uart.hal_obj, config->uart_tx_pin, config->uart_rx_pin, NULL, &uart_config);
  305. #endif
  306. if (result == CY_RSLT_SUCCESS)
  307. {
  308. result = cyhal_uart_set_baud(&cy_trans_uart.hal_obj, config->baud_rate, NULL);
  309. if (result == CY_RSLT_SUCCESS)
  310. {
  311. if (config->flow_control)
  312. {
  313. #if (CYHAL_API_VERSION >= 2)
  314. result = cyhal_uart_enable_flow_control(&cy_trans_uart.hal_obj, true, true);
  315. #else
  316. result = cyhal_uart_set_flow_control(&cy_trans_uart.hal_obj, config->uart_cts_pin, config->uart_rts_pin);
  317. #endif
  318. }
  319. if (result == CY_RSLT_SUCCESS)
  320. {
  321. cy_rtos_init_semaphore(&cy_trans_uart.tx_complete,
  322. 1,
  323. 0
  324. );
  325. cy_rtos_init_semaphore(&cy_trans_uart.rx_complete,
  326. 1,
  327. 0
  328. );
  329. cy_rtos_init_semaphore(&cy_trans_uart.tx_ready,
  330. 1,
  331. 1
  332. );
  333. cy_rtos_init_mutex(&cy_trans_uart.tx_atomic);
  334. cyhal_uart_register_callback(&cy_trans_uart.hal_obj,
  335. cybt_uart_irq_handler_,
  336. NULL
  337. );
  338. cyhal_uart_enable_event(&cy_trans_uart.hal_obj,
  339. (cyhal_uart_event_t)enable_irq_event,
  340. CYHAL_ISR_PRIORITY_DEFAULT,
  341. true
  342. );
  343. cy_trans_uart.inited = true;
  344. cy_trans_uart.rx_done = false;
  345. cy_trans_uart.rx_cb = p_data_handler;
  346. cybt_init_debug_trans_task();
  347. return CYBT_SUCCESS;
  348. }
  349. }
  350. }
  351. return CYBT_ERR_HCI_INIT_FAILED;
  352. }
  353. cybt_result_t cybt_debug_uart_send_trace(uint16_t length, uint8_t* p_data)
  354. {
  355. return cybt_handle_received_tx_data(INVALID_TYPE, HCI_CONTROL_EVENT_WICED_TRACE, length, p_data);
  356. }
  357. cybt_result_t cybt_debug_uart_send_data (uint16_t opcode, uint16_t data_size, uint8_t *p_data)
  358. {
  359. return cybt_trans_write(INVALID_TYPE,(uint16_t)opcode, data_size, p_data);
  360. }
  361. cybt_result_t cybt_debug_uart_send_hci_trace (uint8_t type, uint16_t data_size, uint8_t *p_data)
  362. {
  363. return cybt_handle_received_tx_data((uint16_t)type, HCI_CONTROL_EVENT_HCI_TRACE, data_size, p_data);
  364. }
  365. cybt_result_t cybt_trans_write (uint8_t type, uint16_t op, uint16_t data_size, uint8_t *p_data)
  366. {
  367. cybt_result_t result = CYBT_ERR_GENERIC;
  368. cy_rslt_t status = CY_RSLT_SUCCESS;
  369. uint8_t data[1000];
  370. size_t index = 0;
  371. uint8_t opcode = (uint8_t)(op&0xff);
  372. uint8_t group_code = (uint8_t)((op >> 8)&0xff);
  373. if (cy_trans_uart.inited == false)
  374. return CYBT_ERR_GENERIC;
  375. status = cy_rtos_get_mutex(&cy_trans_uart.tx_atomic, CY_RTOS_NEVER_TIMEOUT);
  376. if(CY_RSLT_SUCCESS != status)
  377. {
  378. return result;
  379. }
  380. data[index++] = HCI_WICED_PKT;
  381. if ( (type != 0xFF) || ((group_code == 0x00) && (opcode == 0x03)) )
  382. {
  383. uint16_t new_size = (data_size+1);
  384. data[index++] = 0x03;
  385. data[index++] = 0x00;
  386. data[index++] = (uint8_t)(new_size&0xff);
  387. data[index++] = (uint8_t)((new_size >> 8)&0xff);
  388. data[index++] = type;
  389. }
  390. else
  391. {
  392. data[index++] = opcode;
  393. data[index++] = group_code;
  394. data[index++] = (uint8_t)(data_size&0xff);
  395. data[index++] = (uint8_t)((data_size >> 8)&0xff);
  396. }
  397. memcpy(&data[index], p_data, data_size);
  398. index += data_size;
  399. status = cyhal_uart_write_async(&cy_trans_uart.hal_obj,
  400. (void *) data,
  401. (size_t) index
  402. );
  403. if(CY_RSLT_SUCCESS == status)
  404. {
  405. cy_rtos_get_semaphore(&cy_trans_uart.tx_complete, CY_RTOS_NEVER_TIMEOUT, false);
  406. result = CYBT_SUCCESS;
  407. }
  408. cy_rtos_set_mutex(&cy_trans_uart.tx_atomic);
  409. return result;
  410. }
  411. int _write(int fd, const char* ptr, int len)
  412. {
  413. if ( cybt_debug_uart_send_trace(len,(uint8_t* )ptr) == CYBT_SUCCESS)
  414. {
  415. return len;
  416. }
  417. return 0;
  418. }
  419. #endif // ENABLE_DEBUG_UART