mss_comblk.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /*******************************************************************************
  2. * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
  3. *
  4. * SmartFusion2 COMBLK access functions.
  5. *
  6. * SVN $Revision: 8345 $
  7. * SVN $Date: 2016-03-23 11:53:04 +0530 (Wed, 23 Mar 2016) $
  8. */
  9. #include "mss_comblk.h"
  10. #include "../../CMSIS/mss_assert.h"
  11. /*==============================================================================
  12. *
  13. */
  14. /*------------------------------------------------------------------------------
  15. * Control register bit masks.
  16. */
  17. #define CR_FLUSHOUT_MASK 0x01u
  18. #define CR_FLUSHIN_MASK 0x02u
  19. #define CR_SIZETX_MASK 0x04u
  20. #define CR_ENABLE_MASK 0x10u
  21. #define CR_LOOPBACK_MASK 0x20u
  22. /*------------------------------------------------------------------------------
  23. * Status and interrupt enable registers bit masks.
  24. */
  25. #define TXTOKAY_MASK 0x01u
  26. #define RCVOKAY_MASK 0x02u
  27. #define TXOVERFLOW_MASK 0x04u
  28. #define RXUNDERFLOW_MASK 0x08u
  29. /*------------------------------------------------------------------------------
  30. * DATA8 register bit masks.
  31. */
  32. #define DATA8_COMMAND_MASK 0x8000u
  33. /*------------------------------------------------------------------------------
  34. * COMBLK driver states.
  35. */
  36. #define COMBLK_IDLE 0u
  37. #define COMBLK_TX_CMD 1u
  38. #define COMBLK_TX_DATA 2u
  39. #define COMBLK_WAIT_RESPONSE 3u
  40. #define COMBLK_RX_RESPONSE 4u
  41. #define COMBLK_TX_PAGED_DATA 5u
  42. #define POR_DIGEST_ERROR_OPCODE 0xF1u
  43. /*==============================================================================
  44. * COMBLK interrupt service routine.
  45. */
  46. void ComBlk_IRQHandler(void);
  47. /*==============================================================================
  48. * Local functions.
  49. */
  50. static void abort_current_cmd(void);
  51. static void send_cmd_opcode(uint8_t opcode);
  52. static uint32_t fill_tx_fifo(const uint8_t * p_cmd, uint32_t cmd_size);
  53. static void handle_tx_okay_irq(void);
  54. static void handle_rx_okay_irq(void);
  55. static void complete_request(uint16_t response_length);
  56. static void process_sys_ctrl_command(uint8_t cmd_opcode);
  57. /*==============================================================================
  58. * Global variables:
  59. */
  60. static volatile uint8_t g_comblk_cmd_opcode = 0u;
  61. static const uint8_t * g_comblk_p_cmd = 0u;
  62. static volatile uint16_t g_comblk_cmd_size = 0u;
  63. static const uint8_t * g_comblk_p_data = 0u;
  64. static volatile uint32_t g_comblk_data_size = 0u;
  65. static uint8_t * g_comblk_p_response = 0u;
  66. static uint16_t g_comblk_response_size = 0u;
  67. static volatile uint16_t g_comblk_response_idx = 0u;
  68. static comblk_completion_handler_t g_comblk_completion_handler = 0;
  69. static uint32_t (*g_comblk_page_handler)(uint8_t const ** pp_next_page) = 0;
  70. static volatile uint8_t g_request_in_progress = 0u;
  71. static uint8_t g_comblk_state = COMBLK_IDLE;
  72. static volatile comblk_async_event_handler_t g_async_event_handler = 0;
  73. /*==============================================================================
  74. *
  75. */
  76. void MSS_COMBLK_init
  77. (
  78. comblk_async_event_handler_t async_event_handler,
  79. uint8_t* p_response
  80. )
  81. {
  82. /*
  83. * Disable and clear previous interrupts.
  84. */
  85. NVIC_DisableIRQ(ComBlk_IRQn);
  86. COMBLK->INT_ENABLE = 0u;
  87. NVIC_ClearPendingIRQ(ComBlk_IRQn);
  88. g_async_event_handler = async_event_handler;
  89. /*
  90. * Initialize COMBLK driver state variables:
  91. */
  92. g_request_in_progress = 0u;
  93. g_comblk_cmd_opcode = 0u;
  94. g_comblk_p_cmd = 0u;
  95. g_comblk_cmd_size = 0u;
  96. g_comblk_p_data = 0u;
  97. g_comblk_data_size = 0u;
  98. g_comblk_p_response = p_response;
  99. g_comblk_response_size = 0u;
  100. g_comblk_response_idx = 0u;
  101. g_comblk_completion_handler = 0;
  102. g_comblk_state = COMBLK_IDLE;
  103. /*
  104. * Disable loopback before enabling the MSS COMM_BLK to ensure that any
  105. * codes waiting in the TX FIFO of the System Controller’s COMM_BLK are
  106. * not lost.
  107. */
  108. COMBLK->CONTROL &= ~CR_LOOPBACK_MASK;
  109. COMBLK->CONTROL |= CR_ENABLE_MASK;
  110. /*--------------------------------------------------------------------------
  111. * Enable receive interrupt to receive asynchronous events from the system
  112. * controller.
  113. */
  114. COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
  115. COMBLK->INT_ENABLE |= RCVOKAY_MASK;
  116. NVIC_EnableIRQ(ComBlk_IRQn);
  117. }
  118. /*==============================================================================
  119. *
  120. */
  121. void MSS_COMBLK_send_cmd_with_ptr
  122. (
  123. uint8_t cmd_opcode,
  124. uint32_t cmd_params_ptr,
  125. uint8_t * p_response,
  126. uint16_t response_size,
  127. comblk_completion_handler_t completion_handler
  128. )
  129. {
  130. uint32_t tx_okay;
  131. /*--------------------------------------------------------------------------
  132. * Disable and clear previous interrupts.
  133. */
  134. NVIC_DisableIRQ(ComBlk_IRQn);
  135. COMBLK->INT_ENABLE = 0u;
  136. NVIC_ClearPendingIRQ(ComBlk_IRQn);
  137. /*--------------------------------------------------------------------------
  138. * Abort current command if any.
  139. */
  140. abort_current_cmd();
  141. /*--------------------------------------------------------------------------
  142. * Initialize COMBLK driver state variables.
  143. */
  144. g_request_in_progress = 1u;
  145. g_comblk_cmd_opcode = cmd_opcode;
  146. g_comblk_p_cmd = 0u;
  147. g_comblk_cmd_size = 0u;
  148. g_comblk_p_data = 0u;
  149. g_comblk_data_size = 0u;
  150. g_comblk_p_response = p_response;
  151. g_comblk_response_size = response_size;
  152. g_comblk_response_idx = 0u;
  153. g_comblk_page_handler = 0u;
  154. g_comblk_completion_handler = completion_handler;
  155. /*--------------------------------------------------------------------------
  156. * Send command opcode as a single byte write to the Tx FIFO.
  157. */
  158. send_cmd_opcode(g_comblk_cmd_opcode);
  159. /*--------------------------------------------------------------------------
  160. * Send the command parameters pointer to the Tx FIFO as a single 4 bytes
  161. * write to the Tx FIFO.
  162. */
  163. COMBLK->CONTROL |= CR_SIZETX_MASK;
  164. /* Wait for space to become available in Tx FIFO. */
  165. do {
  166. tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
  167. } while(0u == tx_okay);
  168. /* Send command opcode. */
  169. COMBLK->DATA32 = cmd_params_ptr;
  170. COMBLK->CONTROL &= ~CR_SIZETX_MASK;
  171. g_comblk_state = COMBLK_WAIT_RESPONSE;
  172. /*--------------------------------------------------------------------------
  173. * Enable interrupt.
  174. */
  175. COMBLK->INT_ENABLE |= RCVOKAY_MASK;
  176. NVIC_EnableIRQ(ComBlk_IRQn);
  177. }
  178. /*==============================================================================
  179. *
  180. */
  181. void MSS_COMBLK_send_cmd
  182. (
  183. const uint8_t * p_cmd,
  184. uint16_t cmd_size,
  185. const uint8_t * p_data,
  186. uint32_t data_size,
  187. uint8_t * p_response,
  188. uint16_t response_size,
  189. comblk_completion_handler_t completion_handler
  190. )
  191. {
  192. uint32_t size_sent;
  193. ASSERT(cmd_size > 0);
  194. /*
  195. * Disable and clear previous interrupts.
  196. */
  197. NVIC_DisableIRQ(ComBlk_IRQn);
  198. COMBLK->INT_ENABLE = 0u;
  199. NVIC_ClearPendingIRQ(ComBlk_IRQn);
  200. /*
  201. * Abort current command if any.
  202. */
  203. abort_current_cmd();
  204. /*
  205. * Initialize COMBLK driver state variables:
  206. */
  207. g_request_in_progress = 1u;
  208. g_comblk_cmd_opcode = p_cmd[0];
  209. g_comblk_p_cmd = p_cmd;
  210. g_comblk_cmd_size = cmd_size;
  211. g_comblk_p_data = p_data;
  212. g_comblk_data_size = data_size;
  213. g_comblk_p_response = p_response;
  214. g_comblk_response_size = response_size;
  215. g_comblk_response_idx = 0u;
  216. g_comblk_page_handler = 0u;
  217. g_comblk_completion_handler = completion_handler;
  218. COMBLK->INT_ENABLE |= RCVOKAY_MASK;
  219. /*
  220. * Fill FIFO with command.
  221. */
  222. send_cmd_opcode(g_comblk_cmd_opcode);
  223. size_sent = fill_tx_fifo(&p_cmd[1], cmd_size - 1u);
  224. ++size_sent; /* Adjust for opcode byte sent. */
  225. if(size_sent < cmd_size)
  226. {
  227. g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
  228. g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
  229. g_comblk_state = COMBLK_TX_CMD;
  230. }
  231. else
  232. {
  233. g_comblk_cmd_size = 0u;
  234. if(g_comblk_data_size > 0u)
  235. {
  236. g_comblk_state = COMBLK_TX_DATA;
  237. }
  238. else
  239. {
  240. g_comblk_state = COMBLK_WAIT_RESPONSE;
  241. }
  242. }
  243. /*
  244. * Enable interrupt.
  245. */
  246. NVIC_EnableIRQ(ComBlk_IRQn);
  247. }
  248. /*==============================================================================
  249. *
  250. */
  251. void MSS_COMBLK_send_paged_cmd
  252. (
  253. const uint8_t * p_cmd,
  254. uint16_t cmd_size,
  255. uint8_t * p_response,
  256. uint16_t response_size,
  257. comblk_page_handler_t page_read_handler,
  258. comblk_completion_handler_t completion_handler
  259. )
  260. {
  261. uint32_t size_sent;
  262. uint8_t irq_enable = 0u;
  263. ASSERT(cmd_size > 0u);
  264. /*
  265. * Disable and clear previous interrupts.
  266. */
  267. NVIC_DisableIRQ(ComBlk_IRQn);
  268. COMBLK->INT_ENABLE = 0u;
  269. NVIC_ClearPendingIRQ(ComBlk_IRQn);
  270. /*
  271. * Abort current command if any.
  272. */
  273. abort_current_cmd();
  274. /*
  275. * Initialize COMBLK driver state variables:
  276. */
  277. g_request_in_progress = 1u;
  278. g_comblk_cmd_opcode = p_cmd[0];
  279. g_comblk_p_cmd = p_cmd;
  280. g_comblk_cmd_size = cmd_size;
  281. g_comblk_p_data = 0;
  282. g_comblk_data_size = 0u;
  283. g_comblk_p_response = p_response;
  284. g_comblk_response_size = response_size;
  285. g_comblk_response_idx = 0u;
  286. g_comblk_page_handler = page_read_handler;
  287. g_comblk_completion_handler = completion_handler;
  288. /*
  289. * Fill FIFO with command.
  290. */
  291. send_cmd_opcode(g_comblk_cmd_opcode);
  292. size_sent = fill_tx_fifo(&p_cmd[1], cmd_size - 1u);
  293. ++size_sent; /* Adjust for opcode byte sent. */
  294. if(size_sent < cmd_size)
  295. {
  296. g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
  297. g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
  298. g_comblk_state = COMBLK_TX_CMD;
  299. irq_enable = TXTOKAY_MASK | RCVOKAY_MASK;
  300. }
  301. else
  302. {
  303. g_comblk_cmd_size = 0u;
  304. g_comblk_state = COMBLK_TX_PAGED_DATA;
  305. irq_enable = TXTOKAY_MASK | RCVOKAY_MASK;
  306. }
  307. /*
  308. * Enable interrupt.
  309. */
  310. COMBLK->INT_ENABLE |= irq_enable;
  311. NVIC_EnableIRQ(ComBlk_IRQn);
  312. }
  313. /*==============================================================================
  314. * COMBLK interrupt handler.
  315. */
  316. void ComBlk_IRQHandler(void)
  317. {
  318. uint8_t status;
  319. uint8_t tx_okay;
  320. uint8_t rcv_okay;
  321. status = (uint8_t)COMBLK->STATUS;
  322. /* Mask off interrupt that are not enabled.*/
  323. status &= COMBLK->INT_ENABLE;
  324. rcv_okay = status & RCVOKAY_MASK;
  325. if(rcv_okay)
  326. {
  327. handle_rx_okay_irq();
  328. }
  329. tx_okay = status & TXTOKAY_MASK;
  330. if(tx_okay)
  331. {
  332. handle_tx_okay_irq();
  333. }
  334. }
  335. /*==============================================================================
  336. *
  337. */
  338. static void handle_tx_okay_irq(void)
  339. {
  340. switch(g_comblk_state)
  341. {
  342. /*----------------------------------------------------------------------
  343. * The TX_OKAY interrupt should only be enabled for states COMBLK_TX_CMD
  344. * and COMBLK_TX_DATA.
  345. */
  346. case COMBLK_TX_CMD:
  347. if(g_comblk_cmd_size > 0u)
  348. {
  349. uint32_t size_sent;
  350. size_sent = fill_tx_fifo(g_comblk_p_cmd, g_comblk_cmd_size);
  351. if(size_sent < g_comblk_cmd_size)
  352. {
  353. g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
  354. g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
  355. }
  356. else
  357. {
  358. g_comblk_cmd_size = 0u;
  359. if(g_comblk_data_size > 0u)
  360. {
  361. g_comblk_state = COMBLK_TX_DATA;
  362. }
  363. else
  364. {
  365. g_comblk_state = COMBLK_WAIT_RESPONSE;
  366. }
  367. }
  368. }
  369. else
  370. {
  371. /*
  372. * This is an invalid situation indicating a bug in the driver
  373. * or corrupted memory.
  374. */
  375. ASSERT(0);
  376. abort_current_cmd();
  377. }
  378. break;
  379. case COMBLK_TX_DATA:
  380. if(g_comblk_data_size > 0u)
  381. {
  382. uint32_t size_sent;
  383. size_sent = fill_tx_fifo(g_comblk_p_data, g_comblk_data_size);
  384. if(size_sent < g_comblk_data_size)
  385. {
  386. g_comblk_data_size = g_comblk_data_size - size_sent;
  387. g_comblk_p_data = &g_comblk_p_data[size_sent];
  388. }
  389. else
  390. {
  391. COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
  392. g_comblk_state = COMBLK_WAIT_RESPONSE;
  393. }
  394. }
  395. else
  396. {
  397. /*
  398. * This is an invalid situation indicating a bug in the driver
  399. * or corrupted memory.
  400. */
  401. ASSERT(0);
  402. abort_current_cmd();
  403. }
  404. break;
  405. case COMBLK_TX_PAGED_DATA:
  406. /*
  407. * Read a page of data if required.
  408. */
  409. if(0u == g_comblk_data_size)
  410. {
  411. if(g_comblk_page_handler != 0)
  412. {
  413. g_comblk_data_size = g_comblk_page_handler(&g_comblk_p_data);
  414. if(0u == g_comblk_data_size)
  415. {
  416. COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
  417. g_comblk_state = COMBLK_WAIT_RESPONSE;
  418. }
  419. }
  420. else
  421. {
  422. ASSERT(0);
  423. abort_current_cmd();
  424. }
  425. }
  426. /*
  427. * Transmit the page data or move to COMBLK_WAIT_RESPONSE state if
  428. * no further page data could be obtained by the call to the page
  429. * handler above.
  430. */
  431. if(0u == g_comblk_data_size)
  432. {
  433. COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
  434. g_comblk_state = COMBLK_WAIT_RESPONSE;
  435. }
  436. else
  437. {
  438. uint32_t size_sent;
  439. size_sent = fill_tx_fifo(g_comblk_p_data, g_comblk_data_size);
  440. g_comblk_data_size = g_comblk_data_size - size_sent;
  441. g_comblk_p_data = &g_comblk_p_data[size_sent];
  442. }
  443. break;
  444. /*----------------------------------------------------------------------
  445. * The TX_OKAY interrupt should NOT be enabled for states COMBLK_IDLE,
  446. * COMBLK_WAIT_RESPONSE and COMBLK_RX_RESPONSE.
  447. */
  448. case COMBLK_IDLE:
  449. /* Fall through */
  450. case COMBLK_WAIT_RESPONSE:
  451. /* Fall through */
  452. case COMBLK_RX_RESPONSE:
  453. /* Fall through */
  454. default:
  455. COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
  456. complete_request(0u);
  457. g_comblk_state = COMBLK_IDLE;
  458. break;
  459. }
  460. }
  461. /*==============================================================================
  462. *
  463. */
  464. static void handle_rx_okay_irq(void)
  465. {
  466. uint16_t data16;
  467. uint16_t is_command;
  468. uint8_t data8;
  469. data16 = (uint16_t)COMBLK->DATA8;
  470. is_command = data16 & DATA8_COMMAND_MASK;
  471. data8 = (uint8_t)data16;
  472. switch(g_comblk_state)
  473. {
  474. /*----------------------------------------------------------------------
  475. * MSS_COMBLK_init() enables the RCV_OKAY interrupt for the COMBLK_IDLE
  476. * state to receive the asynchronous power-on-reset from the system
  477. * controller.
  478. */
  479. case COMBLK_IDLE:
  480. if(is_command)
  481. {
  482. if(data8 != POR_DIGEST_ERROR_OPCODE)
  483. {
  484. uint8_t rxed_opcode;
  485. rxed_opcode = data8;
  486. process_sys_ctrl_command(rxed_opcode);
  487. }
  488. else
  489. {
  490. g_comblk_response_idx = 0;
  491. g_comblk_p_response[g_comblk_response_idx] = data8;
  492. g_comblk_response_idx++;
  493. g_comblk_p_response[g_comblk_response_idx] = 0x00u;
  494. g_comblk_state = COMBLK_RX_RESPONSE;
  495. }
  496. }
  497. break;
  498. /*----------------------------------------------------------------------
  499. * The RCV_OKAY interrupt should only be enabled for states
  500. * COMBLK_WAIT_RESPONSE and COMBLK_RX_RESPONSE.
  501. */
  502. case COMBLK_WAIT_RESPONSE:
  503. if(is_command)
  504. {
  505. uint8_t rxed_opcode;
  506. rxed_opcode = data8;
  507. if(rxed_opcode == g_comblk_cmd_opcode)
  508. {
  509. g_comblk_response_idx = 0u;
  510. g_comblk_p_response[g_comblk_response_idx] = rxed_opcode;
  511. ++g_comblk_response_idx;
  512. g_comblk_state = COMBLK_RX_RESPONSE;
  513. }
  514. else
  515. {
  516. process_sys_ctrl_command(rxed_opcode);
  517. }
  518. }
  519. break;
  520. case COMBLK_RX_RESPONSE:
  521. if(is_command)
  522. {
  523. uint8_t rxed_opcode;
  524. rxed_opcode = data8;
  525. process_sys_ctrl_command(rxed_opcode);
  526. }
  527. else
  528. {
  529. if( g_comblk_p_response[g_comblk_response_idx-1] == POR_DIGEST_ERROR_OPCODE)
  530. {
  531. g_comblk_p_response[g_comblk_response_idx] = data8;
  532. process_sys_ctrl_command(g_comblk_p_response[g_comblk_response_idx-1]);
  533. g_comblk_state = COMBLK_IDLE;
  534. }
  535. else
  536. {
  537. if(g_comblk_response_idx < g_comblk_response_size)
  538. {
  539. uint8_t rxed_data;
  540. rxed_data = data8;
  541. g_comblk_p_response[g_comblk_response_idx] = rxed_data;
  542. ++g_comblk_response_idx;
  543. }
  544. if(g_comblk_response_idx == g_comblk_response_size)
  545. {
  546. complete_request(g_comblk_response_idx);
  547. g_comblk_state = COMBLK_IDLE;
  548. }
  549. }
  550. }
  551. break;
  552. /*----------------------------------------------------------------------
  553. * The RCV_OKAY interrupt should NOT be enabled for states
  554. * COMBLK_IDLE, COMBLK_TX_CMD and COMBLK_TX_DATA.
  555. */
  556. case COMBLK_TX_PAGED_DATA:
  557. /* This is needed because when there is an error, we need to terminate loading the data */
  558. if(!is_command)
  559. {
  560. g_comblk_p_response[1] = data8;
  561. complete_request(2u);
  562. g_comblk_state = COMBLK_IDLE;
  563. }
  564. else
  565. {
  566. uint8_t rxed_opcode;
  567. rxed_opcode = data8;
  568. process_sys_ctrl_command(rxed_opcode);
  569. }
  570. break;
  571. case COMBLK_TX_CMD:
  572. /* Fall through */
  573. case COMBLK_TX_DATA:
  574. /* Fall through */
  575. if(is_command)
  576. {
  577. uint8_t rxed_opcode;
  578. rxed_opcode = data8;
  579. process_sys_ctrl_command(rxed_opcode);
  580. }
  581. break;
  582. default:
  583. complete_request(0u);
  584. g_comblk_state = COMBLK_IDLE;
  585. break;
  586. }
  587. }
  588. /*==============================================================================
  589. *
  590. */
  591. static void complete_request
  592. (
  593. uint16_t response_length
  594. )
  595. {
  596. if(g_comblk_completion_handler != 0)
  597. {
  598. g_comblk_completion_handler(g_comblk_p_response, response_length);
  599. g_comblk_completion_handler = 0;
  600. g_request_in_progress = 0u;
  601. }
  602. }
  603. /*==============================================================================
  604. *
  605. */
  606. static void abort_current_cmd(void)
  607. {
  608. if(g_request_in_progress)
  609. {
  610. uint32_t flush_in_progress;
  611. /*
  612. * Call completion handler just in case we are in a multi threaded system
  613. * to avoid a task lockup.
  614. */
  615. complete_request(g_comblk_response_idx);
  616. /*
  617. * Flush the FIFOs
  618. */
  619. COMBLK->CONTROL |= CR_FLUSHOUT_MASK;
  620. do {
  621. flush_in_progress = COMBLK->CONTROL & CR_FLUSHOUT_MASK;
  622. } while(flush_in_progress);
  623. }
  624. }
  625. /*==============================================================================
  626. *
  627. */
  628. static void send_cmd_opcode
  629. (
  630. uint8_t opcode
  631. )
  632. {
  633. uint32_t tx_okay;
  634. /* Set transmit FIFO to transfer bytes. */
  635. COMBLK->CONTROL &= ~CR_SIZETX_MASK;
  636. /* Wait for space to become available in Tx FIFO. */
  637. do {
  638. tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
  639. } while(0u == tx_okay);
  640. /* Send command opcode. */
  641. COMBLK->FRAME_START8 = opcode;
  642. }
  643. /*==============================================================================
  644. *
  645. */
  646. static uint32_t fill_tx_fifo
  647. (
  648. const uint8_t * p_cmd,
  649. uint32_t cmd_size
  650. )
  651. {
  652. volatile uint32_t tx_okay;
  653. uint32_t size_sent;
  654. /* Set transmit FIFO to transfer bytes. */
  655. COMBLK->CONTROL &= ~CR_SIZETX_MASK;
  656. size_sent = 0u;
  657. tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
  658. while((tx_okay != 0u) && (size_sent < cmd_size))
  659. {
  660. COMBLK->DATA8 = p_cmd[size_sent];
  661. ++size_sent;
  662. tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
  663. }
  664. return size_sent;
  665. }
  666. /*==============================================================================
  667. *
  668. */
  669. static void process_sys_ctrl_command(uint8_t cmd_opcode)
  670. {
  671. if(g_async_event_handler != 0)
  672. {
  673. g_async_event_handler(cmd_opcode);
  674. }
  675. }