From 56e86c626df3dbf74c1021210636a7c5d92a49ce Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 30 Oct 2018 16:31:29 +0100 Subject: move to cmake Signed-off-by: Dominik Sliwa --- drivers/src/fsl_uart_freertos.c | 332 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 drivers/src/fsl_uart_freertos.c (limited to 'drivers/src/fsl_uart_freertos.c') diff --git a/drivers/src/fsl_uart_freertos.c b/drivers/src/fsl_uart_freertos.c new file mode 100644 index 0000000..4d1da17 --- /dev/null +++ b/drivers/src/fsl_uart_freertos.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_uart_freertos.h" +#include +#include +#include + +static void UART_RTOS_Callback(UART_Type *base, uart_handle_t *state, status_t status, void *param) +{ + uart_rtos_handle_t *handle = (uart_rtos_handle_t *)param; + BaseType_t xHigherPriorityTaskWoken, xResult; + + xHigherPriorityTaskWoken = pdFALSE; + xResult = pdFAIL; + + if (status == kStatus_UART_RxIdle) + { + xResult = xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_COMPLETE, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_TxIdle) + { + xResult = xEventGroupSetBitsFromISR(handle->txEvent, RTOS_UART_COMPLETE, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_RxRingBufferOverrun) + { + xResult = xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_RING_BUFFER_OVERRUN, &xHigherPriorityTaskWoken); + } + else if (status == kStatus_UART_RxHardwareOverrun) + { + /* Clear Overrun flag (OR) in UART S1 register */ + UART_ClearStatusFlags(base, kUART_RxOverrunFlag); + xResult = + xEventGroupSetBitsFromISR(handle->rxEvent, RTOS_UART_HARDWARE_BUFFER_OVERRUN, &xHigherPriorityTaskWoken); + } + + if (xResult != pdFAIL) + { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Init + * Description : Initializes the UART instance for application + * + *END**************************************************************************/ +int UART_RTOS_Init(uart_rtos_handle_t *handle, uart_handle_t *t_handle, const uart_rtos_config_t *cfg) +{ + uart_config_t defcfg; + + if (NULL == handle) + { + return kStatus_InvalidArgument; + } + if (NULL == t_handle) + { + return kStatus_InvalidArgument; + } + if (NULL == cfg) + { + return kStatus_InvalidArgument; + } + if (NULL == cfg->base) + { + return kStatus_InvalidArgument; + } + if (0 == cfg->srcclk) + { + return kStatus_InvalidArgument; + } + if (0 == cfg->baudrate) + { + return kStatus_InvalidArgument; + } + + handle->base = cfg->base; + handle->t_state = t_handle; +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->txSemaphore = xSemaphoreCreateMutexStatic(&handle->txSemaphoreBuffer); +#else + handle->txSemaphore = xSemaphoreCreateMutex(); +#endif + if (NULL == handle->txSemaphore) + { + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->rxSemaphore = xSemaphoreCreateMutexStatic(&handle->rxSemaphoreBuffer); +#else + handle->rxSemaphore = xSemaphoreCreateMutex(); +#endif + if (NULL == handle->rxSemaphore) + { + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->txEvent = xEventGroupCreateStatic(&handle->txEventBuffer); +#else + handle->txEvent = xEventGroupCreate(); +#endif + if (NULL == handle->txEvent) + { + vSemaphoreDelete(handle->rxSemaphore); + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } +#if (configSUPPORT_STATIC_ALLOCATION == 1) + handle->rxEvent = xEventGroupCreateStatic(&handle->rxEventBuffer); +#else + handle->rxEvent = xEventGroupCreate(); +#endif + if (NULL == handle->rxEvent) + { + vEventGroupDelete(handle->txEvent); + vSemaphoreDelete(handle->rxSemaphore); + vSemaphoreDelete(handle->txSemaphore); + return kStatus_Fail; + } + UART_GetDefaultConfig(&defcfg); + + defcfg.baudRate_Bps = cfg->baudrate; + defcfg.parityMode = cfg->parity; +#if defined(FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT) && FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT + defcfg.stopBitCount = cfg->stopbits; +#endif + + UART_Init(handle->base, &defcfg, cfg->srcclk); + UART_TransferCreateHandle(handle->base, handle->t_state, UART_RTOS_Callback, handle); + UART_TransferStartRingBuffer(handle->base, handle->t_state, cfg->buffer, cfg->buffer_size); + + UART_EnableTx(handle->base, true); + UART_EnableRx(handle->base, true); + + return 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Deinit + * Description : Deinitializes the UART instance and frees resources + * + *END**************************************************************************/ +int UART_RTOS_Deinit(uart_rtos_handle_t *handle) +{ + UART_Deinit(handle->base); + + vEventGroupDelete(handle->txEvent); + vEventGroupDelete(handle->rxEvent); + + /* Give the semaphore. This is for functional safety */ + xSemaphoreGive(handle->txSemaphore); + xSemaphoreGive(handle->rxSemaphore); + + vSemaphoreDelete(handle->txSemaphore); + vSemaphoreDelete(handle->rxSemaphore); + + /* Invalidate the handle */ + handle->base = NULL; + handle->t_state = NULL; + + return 0; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Send + * Description : Initializes the UART instance for application + * + *END**************************************************************************/ +int UART_RTOS_Send(uart_rtos_handle_t *handle, const uint8_t *buffer, uint32_t length) +{ + EventBits_t ev; + int retval = kStatus_Success; + + if (NULL == handle->base) + { + /* Invalid handle. */ + return kStatus_Fail; + } + if (0 == length) + { + return 0; + } + if (NULL == buffer) + { + return kStatus_InvalidArgument; + } + + if (pdFALSE == xSemaphoreTake(handle->txSemaphore, 0)) + { + /* We could not take the semaphore, exit with 0 data received */ + return kStatus_Fail; + } + + handle->txTransfer.data = (uint8_t *)buffer; + handle->txTransfer.dataSize = (uint32_t)length; + + /* Non-blocking call */ + UART_TransferSendNonBlocking(handle->base, handle->t_state, &handle->txTransfer); + + ev = xEventGroupWaitBits(handle->txEvent, RTOS_UART_COMPLETE, pdTRUE, pdFALSE, portMAX_DELAY); + if (!(ev & RTOS_UART_COMPLETE)) + { + retval = kStatus_Fail; + } + + if (pdFALSE == xSemaphoreGive(handle->txSemaphore)) + { + /* We could not post the semaphore, exit with error */ + retval = kStatus_Fail; + } + + return retval; +} + +/*FUNCTION********************************************************************** + * + * Function Name : UART_RTOS_Recv + * Description : Receives chars for the application + * + *END**************************************************************************/ +int UART_RTOS_Receive(uart_rtos_handle_t *handle, uint8_t *buffer, uint32_t length, size_t *received) +{ + EventBits_t ev; + size_t n = 0; + int retval = kStatus_Fail; + size_t local_received = 0; + + if (NULL == handle->base) + { + /* Invalid handle. */ + return kStatus_Fail; + } + if (0 == length) + { + if (received != NULL) + { + *received = n; + } + return 0; + } + if (NULL == buffer) + { + return kStatus_InvalidArgument; + } + + /* New transfer can be performed only after current one is finished */ + if (pdFALSE == xSemaphoreTake(handle->rxSemaphore, portMAX_DELAY)) + { + /* We could not take the semaphore, exit with 0 data received */ + return kStatus_Fail; + } + + handle->rxTransfer.data = buffer; + handle->rxTransfer.dataSize = (uint32_t)length; + + /* Non-blocking call */ + UART_TransferReceiveNonBlocking(handle->base, handle->t_state, &handle->rxTransfer, &n); + + ev = xEventGroupWaitBits(handle->rxEvent, + RTOS_UART_COMPLETE | RTOS_UART_RING_BUFFER_OVERRUN | RTOS_UART_HARDWARE_BUFFER_OVERRUN, + pdTRUE, pdFALSE, portMAX_DELAY); + if (ev & RTOS_UART_HARDWARE_BUFFER_OVERRUN) + { + /* Stop data transfer to application buffer, ring buffer is still active */ + UART_TransferAbortReceive(handle->base, handle->t_state); + /* Prevent false indication of successful transfer in next call of UART_RTOS_Receive. + RTOS_UART_COMPLETE flag could be set meanwhile overrun is handled */ + xEventGroupClearBits(handle->rxEvent, RTOS_UART_COMPLETE); + retval = kStatus_UART_RxHardwareOverrun; + local_received = 0; + } + else if (ev & RTOS_UART_RING_BUFFER_OVERRUN) + { + /* Stop data transfer to application buffer, ring buffer is still active */ + UART_TransferAbortReceive(handle->base, handle->t_state); + /* Prevent false indication of successful transfer in next call of UART_RTOS_Receive. + RTOS_UART_COMPLETE flag could be set meanwhile overrun is handled */ + xEventGroupClearBits(handle->rxEvent, RTOS_UART_COMPLETE); + retval = kStatus_UART_RxRingBufferOverrun; + local_received = 0; + } + else if (ev & RTOS_UART_COMPLETE) + { + retval = kStatus_Success; + local_received = length; + } + + /* Prevent repetitive NULL check */ + if (received != NULL) + { + *received = local_received; + } + + /* Enable next transfer. Current one is finished */ + if (pdFALSE == xSemaphoreGive(handle->rxSemaphore)) + { + /* We could not post the semaphore, exit with error */ + retval = kStatus_Fail; + } + return retval; +} -- cgit v1.2.3