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