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