fsl_lpuart_freertos.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2019 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_lpuart_freertos.h"
  9. #include <FreeRTOS.h>
  10. #include <event_groups.h>
  11. #include <semphr.h>
  12. /* Component ID definition, used by tools. */
  13. #ifndef FSL_COMPONENT_ID
  14. #define FSL_COMPONENT_ID "platform.drivers.lpuart_freertos"
  15. #endif
  16. static void LPUART_RTOS_Callback(LPUART_Type *base, lpuart_handle_t *state, status_t status, void *param)
  17. {
  18. lpuart_rtos_handle_t *handle = (lpuart_rtos_handle_t *)param;
  19. BaseType_t xHigherPriorityTaskWoken, xResult;
  20. xHigherPriorityTaskWoken = pdFALSE;
  21. xResult = pdFAIL;
  22. if (status == kStatus_LPUART_RxIdle)
  23. {
  24. xResult = xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_LPUART_COMPLETE, &xHigherPriorityTaskWoken);
  25. }
  26. else if (status == kStatus_LPUART_TxIdle)
  27. {
  28. xResult = xEventGroupSetBitsFromISR(handle->txEvent, RTOS_LPUART_COMPLETE, &xHigherPriorityTaskWoken);
  29. }
  30. else if (status == kStatus_LPUART_RxRingBufferOverrun)
  31. {
  32. xResult =
  33. xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_LPUART_RING_BUFFER_OVERRUN, &xHigherPriorityTaskWoken);
  34. }
  35. else if (status == kStatus_LPUART_RxHardwareOverrun)
  36. {
  37. /* Clear Overrun flag (OR) in LPUART STAT register */
  38. (void)LPUART_ClearStatusFlags(base, (uint32_t)kLPUART_RxOverrunFlag);
  39. xResult =
  40. xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_LPUART_HARDWARE_BUFFER_OVERRUN, &xHigherPriorityTaskWoken);
  41. }
  42. else
  43. {
  44. xResult = pdFAIL;
  45. }
  46. if (xResult != pdFAIL)
  47. {
  48. portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  49. }
  50. }
  51. /*FUNCTION**********************************************************************
  52. *
  53. * Function Name : LPUART_RTOS_Init
  54. * Description : Initializes the LPUART instance for application
  55. *
  56. *END**************************************************************************/
  57. /*!
  58. * brief Initializes an LPUART instance for operation in RTOS.
  59. *
  60. * param handle The RTOS LPUART handle, the pointer to an allocated space for RTOS context.
  61. * param t_handle The pointer to an allocated space to store the transactional layer internal state.
  62. * param cfg The pointer to the parameters required to configure the LPUART after initialization.
  63. * return kStatus_Success, others failed
  64. */
  65. int LPUART_RTOS_Init(lpuart_rtos_handle_t *handle, lpuart_handle_t *t_handle, const lpuart_rtos_config_t *cfg)
  66. {
  67. status_t status;
  68. lpuart_config_t defcfg;
  69. if (NULL == handle)
  70. {
  71. return kStatus_InvalidArgument;
  72. }
  73. if (NULL == t_handle)
  74. {
  75. return kStatus_InvalidArgument;
  76. }
  77. if (NULL == cfg)
  78. {
  79. return kStatus_InvalidArgument;
  80. }
  81. if (NULL == cfg->base)
  82. {
  83. return kStatus_InvalidArgument;
  84. }
  85. if (0u == cfg->srcclk)
  86. {
  87. return kStatus_InvalidArgument;
  88. }
  89. if (0u == cfg->baudrate)
  90. {
  91. return kStatus_InvalidArgument;
  92. }
  93. handle->base = cfg->base;
  94. handle->t_state = t_handle;
  95. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  96. handle->txSemaphore = xSemaphoreCreateMutexStatic(&handle->txSemaphoreBuffer);
  97. #else
  98. handle->txSemaphore = xSemaphoreCreateMutex();
  99. #endif
  100. if (NULL == handle->txSemaphore)
  101. {
  102. return kStatus_Fail;
  103. }
  104. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  105. handle->rxSemaphore = xSemaphoreCreateMutexStatic(&handle->rxSemaphoreBuffer);
  106. #else
  107. handle->rxSemaphore = xSemaphoreCreateMutex();
  108. #endif
  109. if (NULL == handle->rxSemaphore)
  110. {
  111. vSemaphoreDelete(handle->txSemaphore);
  112. return kStatus_Fail;
  113. }
  114. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  115. handle->txEvent = xEventGroupCreateStatic(&handle->txEventBuffer);
  116. #else
  117. handle->txEvent = xEventGroupCreate();
  118. #endif
  119. if (NULL == handle->txEvent)
  120. {
  121. vSemaphoreDelete(handle->rxSemaphore);
  122. vSemaphoreDelete(handle->txSemaphore);
  123. return kStatus_Fail;
  124. }
  125. #if (configSUPPORT_STATIC_ALLOCATION == 1)
  126. handle->rxEvent = xEventGroupCreateStatic(&handle->rxEventBuffer);
  127. #else
  128. handle->rxEvent = xEventGroupCreate();
  129. #endif
  130. if (NULL == handle->rxEvent)
  131. {
  132. vEventGroupDelete(handle->txEvent);
  133. vSemaphoreDelete(handle->rxSemaphore);
  134. vSemaphoreDelete(handle->txSemaphore);
  135. return kStatus_Fail;
  136. }
  137. LPUART_GetDefaultConfig(&defcfg);
  138. defcfg.baudRate_Bps = cfg->baudrate;
  139. defcfg.parityMode = cfg->parity;
  140. defcfg.stopBitCount = cfg->stopbits;
  141. #if defined(FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT) && FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT
  142. defcfg.enableRxRTS = cfg->enableRxRTS;
  143. defcfg.enableTxCTS = cfg->enableTxCTS;
  144. defcfg.txCtsSource = cfg->txCtsSource;
  145. defcfg.txCtsConfig = cfg->txCtsConfig;
  146. #endif
  147. status = LPUART_Init(handle->base, &defcfg, cfg->srcclk);
  148. if (status != kStatus_Success)
  149. {
  150. vEventGroupDelete(handle->rxEvent);
  151. vEventGroupDelete(handle->txEvent);
  152. vSemaphoreDelete(handle->rxSemaphore);
  153. vSemaphoreDelete(handle->txSemaphore);
  154. return kStatus_Fail;
  155. }
  156. LPUART_TransferCreateHandle(handle->base, handle->t_state, LPUART_RTOS_Callback, handle);
  157. LPUART_TransferStartRingBuffer(handle->base, handle->t_state, cfg->buffer, cfg->buffer_size);
  158. LPUART_EnableTx(handle->base, true);
  159. LPUART_EnableRx(handle->base, true);
  160. return kStatus_Success;
  161. }
  162. /*FUNCTION**********************************************************************
  163. *
  164. * Function Name : LPUART_RTOS_Deinit
  165. * Description : Deinitializes the LPUART instance and frees resources
  166. *
  167. *END**************************************************************************/
  168. /*!
  169. * brief Deinitializes an LPUART instance for operation.
  170. *
  171. * This function deinitializes the LPUART module, sets all register value to the reset value,
  172. * and releases the resources.
  173. *
  174. * param handle The RTOS LPUART handle.
  175. */
  176. int LPUART_RTOS_Deinit(lpuart_rtos_handle_t *handle)
  177. {
  178. LPUART_Deinit(handle->base);
  179. vEventGroupDelete(handle->txEvent);
  180. vEventGroupDelete(handle->rxEvent);
  181. /* Give the semaphore. This is for functional safety */
  182. (void)xSemaphoreGive(handle->txSemaphore);
  183. (void)xSemaphoreGive(handle->rxSemaphore);
  184. vSemaphoreDelete(handle->txSemaphore);
  185. vSemaphoreDelete(handle->rxSemaphore);
  186. /* Invalidate the handle */
  187. handle->base = NULL;
  188. handle->t_state = NULL;
  189. return 0;
  190. }
  191. /*FUNCTION**********************************************************************
  192. *
  193. * Function Name : UART_RTOS_Send
  194. * Description : Initializes the UART instance for application
  195. *
  196. *END**************************************************************************/
  197. /*!
  198. * brief Sends data in the background.
  199. *
  200. * This function sends data. It is an synchronous API.
  201. * If the hardware buffer is full, the task is in the blocked state.
  202. *
  203. * param handle The RTOS LPUART handle.
  204. * param buffer The pointer to buffer to send.
  205. * param length The number of bytes to send.
  206. */
  207. int LPUART_RTOS_Send(lpuart_rtos_handle_t *handle, uint8_t *buffer, uint32_t length)
  208. {
  209. EventBits_t ev;
  210. int retval = kStatus_Success;
  211. status_t status;
  212. if (NULL == handle->base)
  213. {
  214. /* Invalid handle. */
  215. return kStatus_Fail;
  216. }
  217. if (0u == length)
  218. {
  219. return kStatus_Success;
  220. }
  221. if (NULL == buffer)
  222. {
  223. return kStatus_InvalidArgument;
  224. }
  225. if (pdFALSE == xSemaphoreTake(handle->txSemaphore, 0))
  226. {
  227. /* We could not take the semaphore, exit with 0 data received */
  228. return kStatus_Fail;
  229. }
  230. handle->txTransfer.data = (uint8_t *)buffer;
  231. handle->txTransfer.dataSize = (uint32_t)length;
  232. /* Non-blocking call */
  233. status = LPUART_TransferSendNonBlocking(handle->base, handle->t_state, &handle->txTransfer);
  234. if (status != kStatus_Success)
  235. {
  236. (void)xSemaphoreGive(handle->txSemaphore);
  237. return kStatus_Fail;
  238. }
  239. ev = xEventGroupWaitBits(handle->txEvent, RTOS_LPUART_COMPLETE, pdTRUE, pdFALSE, portMAX_DELAY);
  240. if ((ev & RTOS_LPUART_COMPLETE) == 0U)
  241. {
  242. retval = kStatus_Fail;
  243. }
  244. if (pdFALSE == xSemaphoreGive(handle->txSemaphore))
  245. {
  246. /* We could not post the semaphore, exit with error */
  247. retval = kStatus_Fail;
  248. }
  249. return retval;
  250. }
  251. /*FUNCTION**********************************************************************
  252. *
  253. * Function Name : LPUART_RTOS_Recv
  254. * Description : Receives chars for the application
  255. *
  256. *END**************************************************************************/
  257. /*!
  258. * brief Receives data.
  259. *
  260. * This function receives data from LPUART. It is an synchronous API. If any data is immediately available
  261. * it is returned immediately and the number of bytes received.
  262. *
  263. * param handle The RTOS LPUART handle.
  264. * param buffer The pointer to buffer where to write received data.
  265. * param length The number of bytes to receive.
  266. * param received The pointer to a variable of size_t where the number of received data is filled.
  267. */
  268. int LPUART_RTOS_Receive(lpuart_rtos_handle_t *handle, uint8_t *buffer, uint32_t length, size_t *received)
  269. {
  270. EventBits_t ev;
  271. size_t n = 0;
  272. int retval = kStatus_Fail;
  273. size_t local_received = 0;
  274. status_t status;
  275. if (NULL == handle->base)
  276. {
  277. /* Invalid handle. */
  278. return kStatus_Fail;
  279. }
  280. if (0u == length)
  281. {
  282. if (received != NULL)
  283. {
  284. *received = n;
  285. }
  286. return kStatus_Success;
  287. }
  288. if (NULL == buffer)
  289. {
  290. return kStatus_InvalidArgument;
  291. }
  292. /* New transfer can be performed only after current one is finished */
  293. if (pdFALSE == xSemaphoreTake(handle->rxSemaphore, portMAX_DELAY))
  294. {
  295. /* We could not take the semaphore, exit with 0 data received */
  296. return kStatus_Fail;
  297. }
  298. handle->rxTransfer.data = buffer;
  299. handle->rxTransfer.dataSize = (uint32_t)length;
  300. /* Non-blocking call */
  301. status = LPUART_TransferReceiveNonBlocking(handle->base, handle->t_state, &handle->rxTransfer, &n);
  302. if (status != kStatus_Success)
  303. {
  304. (void)xSemaphoreGive(handle->rxSemaphore);
  305. return kStatus_Fail;
  306. }
  307. ev = xEventGroupWaitBits(
  308. handle->rxEvent, RTOS_LPUART_COMPLETE | RTOS_LPUART_RING_BUFFER_OVERRUN | RTOS_LPUART_HARDWARE_BUFFER_OVERRUN,
  309. pdTRUE, pdFALSE, portMAX_DELAY);
  310. if ((ev & RTOS_LPUART_HARDWARE_BUFFER_OVERRUN) != 0U)
  311. {
  312. /* Stop data transfer to application buffer, ring buffer is still active */
  313. LPUART_TransferAbortReceive(handle->base, handle->t_state);
  314. /* Prevent false indication of successful transfer in next call of LPUART_RTOS_Receive.
  315. RTOS_LPUART_COMPLETE flag could be set meanwhile overrun is handled */
  316. (void)xEventGroupClearBits(handle->rxEvent, RTOS_LPUART_COMPLETE);
  317. retval = kStatus_LPUART_RxHardwareOverrun;
  318. local_received = 0;
  319. }
  320. else if ((ev & RTOS_LPUART_RING_BUFFER_OVERRUN) != 0U)
  321. {
  322. /* Stop data transfer to application buffer, ring buffer is still active */
  323. LPUART_TransferAbortReceive(handle->base, handle->t_state);
  324. /* Prevent false indication of successful transfer in next call of LPUART_RTOS_Receive.
  325. RTOS_LPUART_COMPLETE flag could be set meanwhile overrun is handled */
  326. (void)xEventGroupClearBits(handle->rxEvent, RTOS_LPUART_COMPLETE);
  327. retval = kStatus_LPUART_RxRingBufferOverrun;
  328. local_received = 0;
  329. }
  330. else if ((ev & RTOS_LPUART_COMPLETE) != 0U)
  331. {
  332. retval = kStatus_Success;
  333. local_received = length;
  334. }
  335. else
  336. {
  337. retval = kStatus_LPUART_Error;
  338. local_received = 0;
  339. }
  340. /* Prevent repetitive NULL check */
  341. if (received != NULL)
  342. {
  343. *received = local_received;
  344. }
  345. /* Enable next transfer. Current one is finished */
  346. if (pdFALSE == xSemaphoreGive(handle->rxSemaphore))
  347. {
  348. /* We could not post the semaphore, exit with error */
  349. retval = kStatus_Fail;
  350. }
  351. return retval;
  352. }