/* * Copyright (c) 2013-2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Driver_USART.h" #include "cmsis_driver_config.h" #include "RTE_Device.h" #ifndef ARG_UNUSED #define ARG_UNUSED(arg) (void)arg #endif /* Driver version */ #define ARM_USART_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 2) /* Driver Version */ static const ARM_DRIVER_VERSION DriverVersion = { ARM_USART_API_VERSION, ARM_USART_DRV_VERSION }; /* Driver Capabilities */ static const ARM_USART_CAPABILITIES DriverCapabilities = { 1, /* supports UART (Asynchronous) mode */ 0, /* supports Synchronous Master mode */ 0, /* supports Synchronous Slave mode */ 0, /* supports UART Single-wire mode */ 0, /* supports UART IrDA mode */ 0, /* supports UART Smart Card mode */ 0, /* Smart Card Clock generator available */ 0, /* RTS Flow Control available */ 0, /* CTS Flow Control available */ 0, /* Transmit completed event: \ref ARM_USARTx_EVENT_TX_COMPLETE */ 0, /* Signal receive character timeout event: * \ref ARM_USARTx_EVENT_RX_TIMEOUT */ 0, /* RTS Line: 0=not available, 1=available */ 0, /* CTS Line: 0=not available, 1=available */ 0, /* DTR Line: 0=not available, 1=available */ 0, /* DSR Line: 0=not available, 1=available */ 0, /* DCD Line: 0=not available, 1=available */ 0, /* RI Line: 0=not available, 1=available */ 0, /* Signal CTS change event: \ref ARM_USARTx_EVENT_CTS */ 0, /* Signal DSR change event: \ref ARM_USARTx_EVENT_DSR */ 0, /* Signal DCD change event: \ref ARM_USARTx_EVENT_DCD */ 0, /* Signal RI change event: \ref ARM_USARTx_EVENT_RI */ 0 /* Reserved */ }; static ARM_DRIVER_VERSION ARM_USART_GetVersion(void) { return DriverVersion; } static ARM_USART_CAPABILITIES ARM_USART_GetCapabilities(void) { return DriverCapabilities; } typedef struct { struct uart_pl011_dev_t* dev; /* UART device structure */ uint32_t tx_nbr_bytes; /* Number of bytes transfered */ uint32_t rx_nbr_bytes; /* Number of bytes received */ ARM_USART_SignalEvent_t cb_event; /* Callback function for events */ } UARTx_Resources; static int32_t ARM_USARTx_Initialize(UARTx_Resources* uart_dev) { /* Initializes generic UART driver */ uart_pl011_init(uart_dev->dev, PeripheralClock); uart_pl011_enable(uart_dev->dev); return ARM_DRIVER_OK; } static int32_t ARM_USARTx_Uninitialize(UARTx_Resources* uart_dev) { /* Disables and uninitializes generic UART driver */ uart_pl011_uninit(uart_dev->dev); return ARM_DRIVER_OK; } static int32_t ARM_USARTx_PowerControl(UARTx_Resources* uart_dev, ARM_POWER_STATE state) { ARG_UNUSED(uart_dev); switch (state) { case ARM_POWER_OFF: case ARM_POWER_LOW: return ARM_DRIVER_ERROR_UNSUPPORTED; case ARM_POWER_FULL: /* Nothing to be done */ return ARM_DRIVER_OK; default: return ARM_DRIVER_ERROR_PARAMETER; } } static int32_t ARM_USARTx_Send(UARTx_Resources* uart_dev, const void *data, uint32_t num) { const uint8_t* p_data = (const uint8_t*)data; if ((data == NULL) || (num == 0U)) { /* Invalid parameters */ return ARM_DRIVER_ERROR_PARAMETER; } /* Resets previous TX counter */ uart_dev->tx_nbr_bytes = 0; while(uart_dev->tx_nbr_bytes != num) { /* Waits until UART is ready to transmit */ while(!uart_pl011_is_writable(uart_dev->dev)) {}; /* As UART is ready to transmit at this point, the write function can * not return any transmit error */ (void)uart_pl011_write(uart_dev->dev, *p_data); uart_dev->tx_nbr_bytes++; p_data++; } if (uart_dev->cb_event != NULL) { uart_dev->cb_event(ARM_USART_EVENT_SEND_COMPLETE); } /* Waits until character is transmited */ while (!uart_pl011_is_writable(uart_dev->dev)){}; return ARM_DRIVER_OK; } static int32_t ARM_USARTx_Receive(UARTx_Resources* uart_dev, void *data, uint32_t num) { uint8_t* p_data = (uint8_t*)data; if ((data == NULL) || (num == 0U)) { // Invalid parameters return ARM_DRIVER_ERROR_PARAMETER; } /* Resets previous RX counter */ uart_dev->rx_nbr_bytes = 0; while(uart_dev->rx_nbr_bytes != num) { /* Waits until one character is received */ while (!uart_pl011_is_readable(uart_dev->dev)){}; /* As UART has received one byte, the read can not * return any receive error at this point */ (void)uart_pl011_read(uart_dev->dev, p_data); uart_dev->rx_nbr_bytes++; p_data++; } if (uart_dev->cb_event != NULL) { uart_dev->cb_event(ARM_USART_EVENT_RECEIVE_COMPLETE); } return ARM_DRIVER_OK; } static uint32_t ARM_USARTx_GetTxCount(UARTx_Resources* uart_dev) { return uart_dev->tx_nbr_bytes; } static uint32_t ARM_USARTx_GetRxCount(UARTx_Resources* uart_dev) { return uart_dev->rx_nbr_bytes; } static int32_t ARM_USARTx_Control(UARTx_Resources* uart_dev, uint32_t control, uint32_t arg) { switch (control & ARM_USART_CONTROL_Msk) { #ifdef UART_TX_RX_CONTROL_ENABLED case ARM_USART_CONTROL_TX: if (arg == 0) { uart_pl011_disable_transmit(uart_dev->dev); } else if (arg == 1) { uart_pl011_enable_transmit(uart_dev->dev); } else { return ARM_DRIVER_ERROR_PARAMETER; } break; case ARM_USART_CONTROL_RX: if (arg == 0) { uart_pl011_disable_receive(uart_dev->dev); } else if (arg == 1) { uart_pl011_enable_receive(uart_dev->dev); } else { return ARM_DRIVER_ERROR_PARAMETER; } break; #endif case ARM_USART_MODE_ASYNCHRONOUS: if(uart_pl011_set_baudrate(uart_dev->dev, arg) != UART_PL011_ERR_NONE) { return ARM_USART_ERROR_BAUDRATE; } break; /* Unsupported command */ default: return ARM_DRIVER_ERROR_UNSUPPORTED; } /* UART Data bits */ if(control & ARM_USART_DATA_BITS_Msk) { /* Data bit is not configurable */ return ARM_DRIVER_ERROR_UNSUPPORTED; } /* UART Parity */ if(control & ARM_USART_PARITY_Msk) { /* Parity is not configurable */ return ARM_USART_ERROR_PARITY; } /* USART Stop bits */ if(control & ARM_USART_STOP_BITS_Msk) { /* Stop bit is not configurable */ return ARM_USART_ERROR_STOP_BITS; } return ARM_DRIVER_OK; } #if (RTE_USART0) /* USART0 Driver wrapper functions */ static UARTx_Resources USART0_DEV = { .dev = &UART0_DEV, .tx_nbr_bytes = 0, .rx_nbr_bytes = 0, .cb_event = NULL, }; static int32_t ARM_USART0_Initialize(ARM_USART_SignalEvent_t cb_event) { USART0_DEV.cb_event = cb_event; return ARM_USARTx_Initialize(&USART0_DEV); } static int32_t ARM_USART0_Uninitialize(void) { return ARM_USARTx_Uninitialize(&USART0_DEV); } static int32_t ARM_USART0_PowerControl(ARM_POWER_STATE state) { return ARM_USARTx_PowerControl(&USART0_DEV, state); } static int32_t ARM_USART0_Send(const void *data, uint32_t num) { return ARM_USARTx_Send(&USART0_DEV, data, num); } static int32_t ARM_USART0_Receive(void *data, uint32_t num) { return ARM_USARTx_Receive(&USART0_DEV, data, num); } static int32_t ARM_USART0_Transfer(const void *data_out, void *data_in, uint32_t num) { ARG_UNUSED(data_out); ARG_UNUSED(data_in); ARG_UNUSED(num); return ARM_DRIVER_ERROR_UNSUPPORTED; } static uint32_t ARM_USART0_GetTxCount(void) { return ARM_USARTx_GetTxCount(&USART0_DEV); } static uint32_t ARM_USART0_GetRxCount(void) { return ARM_USARTx_GetRxCount(&USART0_DEV); } static int32_t ARM_USART0_Control(uint32_t control, uint32_t arg) { return ARM_USARTx_Control(&USART0_DEV, control, arg); } static ARM_USART_STATUS ARM_USART0_GetStatus(void) { ARM_USART_STATUS status = {0, 0, 0, 0, 0, 0, 0, 0}; return status; } static int32_t ARM_USART0_SetModemControl(ARM_USART_MODEM_CONTROL control) { ARG_UNUSED(control); return ARM_DRIVER_ERROR_UNSUPPORTED; } static ARM_USART_MODEM_STATUS ARM_USART0_GetModemStatus(void) { ARM_USART_MODEM_STATUS modem_status = {0, 0, 0, 0, 0}; return modem_status; } extern ARM_DRIVER_USART Driver_USART0; ARM_DRIVER_USART Driver_USART0 = { ARM_USART_GetVersion, ARM_USART_GetCapabilities, ARM_USART0_Initialize, ARM_USART0_Uninitialize, ARM_USART0_PowerControl, ARM_USART0_Send, ARM_USART0_Receive, ARM_USART0_Transfer, ARM_USART0_GetTxCount, ARM_USART0_GetRxCount, ARM_USART0_Control, ARM_USART0_GetStatus, ARM_USART0_SetModemControl, ARM_USART0_GetModemStatus }; #endif /* RTE_USART0 */