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