X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FDemo%2FT-HEAD_CB2201_CDK%2Fcsi%2Fcsi_driver%2Fcsky%2Fcommon%2Fusart%2Fdw_usart.c;fp=FreeRTOS%2FDemo%2FT-HEAD_CB2201_CDK%2Fcsi%2Fcsi_driver%2Fcsky%2Fcommon%2Fusart%2Fdw_usart.c;h=2b9e47c759f7a63607bef8527c4cae158735d897;hb=eb22b4ef7e59311b4e0439de0b3cf7356915a4d7;hp=0000000000000000000000000000000000000000;hpb=7305db088a93adde8fff02fef82674f7c094153a;p=freertos diff --git a/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/usart/dw_usart.c b/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/usart/dw_usart.c new file mode 100644 index 000000000..2b9e47c75 --- /dev/null +++ b/FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/usart/dw_usart.c @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved. + * + * 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. + */ + +/****************************************************************************** + * @file dw_usart.c + * @brief CSI Source File for usart Driver + * @version V1.0 + * @date 02. June 2017 + ******************************************************************************/ +#include +#include "csi_core.h" +#include "drv_usart.h" +#include "dw_usart.h" +#include "soc.h" + +#define ERR_USART(errno) (CSI_DRV_ERRNO_USART_BASE | errno) + +/* + * setting config may be accessed when the USART is not + * busy(USR[0]=0) and the DLAB bit(LCR[7]) is set. + */ + +#define WAIT_USART_IDLE(addr)\ + do { \ + int32_t timecount = 0; \ + while ((addr->USR & USR_UART_BUSY) && (timecount < UART_BUSY_TIMEOUT)) {\ + timecount++;\ + }\ + if (timecount >= UART_BUSY_TIMEOUT) {\ + return ERR_USART(EDRV_TIMEOUT);\ + } \ + } while(0) + +#define USART_NULL_PARAM_CHK(para) \ + do { \ + if (para == NULL) { \ + return ERR_USART(EDRV_PARAMETER); \ + } \ + } while (0) + +typedef struct { + uint32_t base; +} dw_usart_priv_t; + +extern int32_t target_usart_init(pin_t tx, pin_t rx, uint32_t *base, uint32_t *irq); +extern int32_t target_usart_flowctrl_init(pin_t tx_flow, pin_t rx_flow, uint32_t flag); + +static dw_usart_priv_t usart_instance[CONFIG_USART_NUM]; + +static const usart_capabilities_t usart_capabilities = { + .asynchronous = 0, /* supports USART (Asynchronous) mode */ + .synchronous_master = 0, /* supports Synchronous Master mode */ + .synchronous_slave = 0, /* supports Synchronous Slave mode */ + .single_wire = 0, /* supports USART Single-wire mode */ + .event_tx_complete = 0, /* Transmit completed event */ + .event_rx_timeout = 0, /* Signal receive character timeout event */ +}; + +/** + \brief set the baut drate of usart. + \param[in] addr usart base to operate. + \param[in] baudrate baud rate + \param[in] apbfreq the frequency of the apb. + \return error code +*/ +int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baudrate, uint32_t apbfreq) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + +#ifdef CONFIG_CHIP_HOBBIT1_2 + uint8_t data[16]; + csi_usart_receive_query(handle, data, 16); +#endif + + WAIT_USART_IDLE(addr); + + /* baudrate=(seriak clock freq)/(16*divisor); algorithm :rounding*/ + uint32_t divisor = ((apbfreq * 10) / baudrate) >> 4; + + if ((divisor % 10) >= 5) { + divisor = (divisor / 10) + 1; + } else { + divisor = divisor / 10; + } + + addr->LCR |= LCR_SET_DLAB; + /* DLL and DLH is lower 8-bits and higher 8-bits of divisor.*/ + addr->DLL = divisor & 0xff; + addr->DLH = (divisor >> 8) & 0xff; + /* + * The DLAB must be cleared after the baudrate is setted + * to access other registers. + */ + addr->LCR &= (~LCR_SET_DLAB); + + return 0; +} + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] mode \ref usart_mode_e + \return error code +*/ +int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode) +{ + if (mode == USART_MODE_ASYNCHRONOUS) { + return 0; + } + + return ERR_USART(EDRV_USART_MODE); +} + +/** + \brief config usart parity. + \param[in] handle usart handle to operate. + \param[in] parity \ref usart_parity_e + \return error code +*/ +int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + WAIT_USART_IDLE(addr); + + switch (parity) { + case USART_PARITY_NONE: + /*CLear the PEN bit(LCR[3]) to disable parity.*/ + addr->LCR &= (~LCR_PARITY_ENABLE); + break; + + case USART_PARITY_ODD: + /* Set PEN and clear EPS(LCR[4]) to set the ODD parity. */ + addr->LCR |= LCR_PARITY_ENABLE; + addr->LCR &= LCR_PARITY_ODD; + break; + + case USART_PARITY_EVEN: + /* Set PEN and EPS(LCR[4]) to set the EVEN parity.*/ + addr->LCR |= LCR_PARITY_ENABLE; + addr->LCR |= LCR_PARITY_EVEN; + break; + + default: + return ERR_USART(EDRV_USART_PARITY); + } + + return 0; +} + +/** + \brief config usart stop bit number. + \param[in] handle usart handle to operate. + \param[in] stopbits \ref usart_stop_bits_e + \return error code +*/ +int32_t dw_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + WAIT_USART_IDLE(addr); + + switch (stopbit) { + case USART_STOP_BITS_1: + /* Clear the STOP bit to set 1 stop bit*/ + addr->LCR &= LCR_STOP_BIT1; + break; + + case USART_STOP_BITS_2: + /* + * If the STOP bit is set "1",we'd gotten 1.5 stop + * bits when DLS(LCR[1:0]) is zero, else 2 stop bits. + */ + addr->LCR |= LCR_STOP_BIT2; + break; + + default: + return ERR_USART(EDRV_USART_STOP_BITS); + } + + return 0; +} + +/** + \brief config usart data length. + \param[in] handle usart handle to operate. + \param[in] databits \ref usart_data_bits_e + \return error code +*/ +int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + +#ifdef CONFIG_CHIP_HOBBIT1_2 + uint8_t data[16]; + csi_usart_receive_query(handle, data, 16); +#endif + + WAIT_USART_IDLE(addr); + /* The word size decides by the DLS bits(LCR[1:0]), and the + * corresponding relationship between them is: + * DLS word size + * 00 -- 5 bits + * 01 -- 6 bits + * 10 -- 7 bits + * 11 -- 8 bits + */ + + switch (databits) { + case USART_DATA_BITS_5: + addr->LCR &= LCR_WORD_SIZE_5; + break; + + case USART_DATA_BITS_6: + addr->LCR &= 0xfd; + addr->LCR |= LCR_WORD_SIZE_6; + break; + + case USART_DATA_BITS_7: + addr->LCR &= 0xfe; + addr->LCR |= LCR_WORD_SIZE_7; + break; + + case USART_DATA_BITS_8: + addr->LCR |= LCR_WORD_SIZE_8; + break; + + default: + return ERR_USART(EDRV_USART_DATA_BITS); + } + + return 0; +} + +/** + \brief get character in query mode. + \param[in] handle usart handle to operate. + \param[in] the pointer to the received character if return 0. + \return error code +*/ +int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch) +{ + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + while (!(addr->LSR & LSR_DATA_READY)); + + *ch = addr->RBR; + + return 0; +} + +/** + \brief transmit character in query mode. + \param[in] handle usart handle to operate. + \param[in] ch the input character + \return error code +*/ +int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch) +{ + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + while ((!(addr->LSR & DW_LSR_TRANS_EMPTY))); + + addr->THR = ch; + + return 0; +} + +/** + \brief the interrupt service function. + \param[in] index of usart instance. +*/ +void dw_usart_irqhandler(int32_t idx) +{ + (void)idx; +} + +/** + \brief Get driver capabilities. + \param[in] handle usart handle to operate. + \return \ref usart_capabilities_t +*/ +usart_capabilities_t csi_usart_get_capabilities(usart_handle_t handle) +{ + return usart_capabilities; +} + +/** + \brief Initialize USART Interface. 1. Initializes the resources needed for the USART interface 2.registers event callback function + \param[in] usart pin of tx + \param[in] usart pin of rx + \param[in] cb_event Pointer to \ref usart_event_cb_t + \return return usart handle if success +*/ +usart_handle_t csi_usart_initialize(pin_t tx, pin_t rx, usart_event_cb_t cb_event, void *cb_arg) +{ + uint32_t base = 0u; + uint32_t irq = 0u; + int32_t idx = target_usart_init(tx, rx, &base, &irq); + + if (idx < 0 || idx >= CONFIG_USART_NUM) { + return NULL; + } + + dw_usart_priv_t *usart_priv = &usart_instance[idx]; + usart_priv->base = base; + + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + /* FIFO enable */ + addr->FCR = DW_FCR_FIFOE | DW_FCR_RT_FIFO_HALF; + + return usart_priv; +} + +/** + \brief De-initialize UART Interface. stops operation and releases the software resources used by the interface + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_uninitialize(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + return 0; +} + +/** + \brief config usart mode. + \param[in] handle usart handle to operate. + \param[in] sysclk configured system clock. + \param[in] baud baud rate + \param[in] mode \ref usart_mode_e + \param[in] parity \ref usart_parity_e + \param[in] stopbits \ref usart_stop_bits_e + \param[in] bits \ref usart_data_bits_e + \return error code +*/ +int32_t csi_usart_config(usart_handle_t handle, + uint32_t sysclk, + uint32_t baud, + usart_mode_e mode, + usart_parity_e parity, + usart_stop_bits_e stopbits, + usart_data_bits_e bits) +{ + int32_t ret; + + /* control the data_bit of the usart*/ + ret = csi_usart_config_baudrate(handle, baud, sysclk); + + if (ret < 0) { + return ret; + } + + /* control mode of the usart*/ + ret = csi_usart_config_mode(handle, mode); + + if (ret < 0) { + return ret; + } + + /* control the parity of the usart*/ + ret = csi_usart_config_parity(handle, parity); + + if (ret < 0) { + return ret; + } + + /* control the stopbit of the usart*/ + ret = dw_usart_config_stopbits(handle, stopbits); + + if (ret < 0) { + return ret; + } + + ret = csi_usart_config_databits(handle, bits); + + if (ret < 0) { + return ret; + } + + return 0; +} + +/** + \brief config usart default tx value. used in syn mode + \param[in] handle usart handle to operate. + \param[in] value default tx value + \return error code +*/ +int32_t csi_usart_set_default_tx_value(usart_handle_t handle, uint32_t value) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Start sending data to UART transmitter,(received data is ignored). + The function is non-blocking,UART_EVENT_TRANSFER_COMPLETE is signaled when transfer completes. + csi_usart_get_status can indicates if transmission is still in progress or pending + \param[in] handle usart handle to operate. + \param[in] data Pointer to buffer with data to send to UART transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits, + \param[in] num Number of data items to send + \return error code +*/ +int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + USART_NULL_PARAM_CHK(data); + + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Abort Send data to UART transmitter + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_send(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Start receiving data from UART receiver.transmits the default value as specified by csi_usart_set_default_tx_value + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \return error code +*/ +int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num) +{ + return ERR_USART(EDRV_UNSUPPORTED); + +} + +/** + \brief query data from UART receiver FIFO. + \param[in] handle usart handle to operate. + \param[out] data Pointer to buffer for data to receive from UART receiver + \param[in] num Number of data items to receive + \return receive fifo data num +*/ +int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num) +{ + return ERR_USART(EDRV_UNSUPPORTED); + +} + +/** + \brief Abort Receive data from UART receiver + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_receive(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Start sending/receiving data to/from UART transmitter/receiver. + \param[in] handle usart handle to operate. + \param[in] data_out Pointer to buffer with data to send to USART transmitter + \param[out] data_in Pointer to buffer for data to receive from USART receiver + \param[in] num Number of data items to transfer + \return error code +*/ +int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief abort sending/receiving data to/from USART transmitter/receiver. + \param[in] handle usart handle to operate. + \return error code +*/ +int32_t csi_usart_abort_transfer(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Get USART status. + \param[in] handle usart handle to operate. + \return USART status \ref usart_status_t +*/ +usart_status_t csi_usart_get_status(usart_handle_t handle) +{ + usart_status_t status = {0}; + return status; +} + +/** + \brief control the transmit. + \param[in] handle usart handle to operate. + \param[in] 1 - enable the transmitter. 0 - disable the transmitter + \return error code +*/ +int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return 0; +} + +/** + \brief control the receive. + \param[in] handle usart handle to operate. + \param[in] 1 - enable the receiver. 0 - disable the receiver + \return error code +*/ +int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return 0; +} + +/** + \brief control the break. + \param[in] handle usart handle to operate. + \param[in] 1- Enable continuous Break transmission,0 - disable continuous Break transmission + \return error code +*/ +int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable) +{ + USART_NULL_PARAM_CHK(handle); + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief flush receive/send data. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_flush_type_e. + \return error code +*/ +int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type) +{ + USART_NULL_PARAM_CHK(handle); + + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + if (type == USART_FLUSH_WRITE) { + addr->FCR |= DW_FCR_XFIFOR; + + while (addr->FCR & DW_FCR_XFIFOR); + } else if (type == USART_FLUSH_READ) { + addr->FCR |= DW_FCR_RFIFOR; + + while (addr->FCR & DW_FCR_RFIFOR); + } else { + return ERR_USART(EDRV_PARAMETER); + } + + return 0; +} + +/** + \brief control interrupt on/off. + \param[in] handle usart handle to operate. + \param[in] type \ref usart_intr_type_e. + \param[in] flag 0-OFF, 1-ON. + \return error code +*/ +int32_t csi_usart_interrupt_on_off(usart_handle_t handle, usart_intr_type_e type, int flag) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Get usart send data count. + \param[in] handle usart handle to operate. + \return number of data bytes transferred +*/ +uint32_t csi_usart_get_tx_count(usart_handle_t handle) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief Get usart receive data count. + \param[in] handle usart handle to operate. + \return number of data bytes transferred +*/ +uint32_t csi_usart_get_rx_count(usart_handle_t handle) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief control usart power. + \param[in] handle usart handle to operate. + \param[in] state power state.\ref csi_power_stat_e. + \return error code +*/ +int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief config usart flow control type. + \param[in] handle usart handle to operate. + \param[in] flowctrl_type flow control type.\ref usart_flowctrl_type_e. + \param[in] tx_flow The TX flow pin name + \param[in] rx_flow The RX flow pin name + \return error code +*/ +int32_t csi_usart_config_flowctrl(usart_handle_t handle, + usart_flowctrl_type_e flowctrl_type, + pin_t tx_flow, pin_t rx_flow) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + int32_t ret; + + switch (flowctrl_type) { + case USART_FLOWCTRL_CTS: + return ERR_USART(EDRV_UNSUPPORTED); + + case USART_FLOWCTRL_RTS: + return ERR_USART(EDRV_UNSUPPORTED); + + case USART_FLOWCTRL_CTS_RTS: + ret = target_usart_flowctrl_init(tx_flow, rx_flow, 1); + + if (ret < 0) { + return ERR_USART(EDRV_PARAMETER); + } + + WAIT_USART_IDLE(addr); + addr->MCR |= DW_MCR_AFCE | DW_MCR_RTS; + break; + + case USART_FLOWCTRL_NONE: + ret = target_usart_flowctrl_init(tx_flow, rx_flow, 0); + + if (ret < 0) { + return ERR_USART(EDRV_PARAMETER); + } + + WAIT_USART_IDLE(addr); + addr->MCR = 0; + break; + + default: + return ERR_USART(EDRV_UNSUPPORTED); + } + + return 0; +} + +/** + \brief usart modem control. + \param[in] handle usart handle to operate. + \param[in] modem_ctrl modem control action.\ref usart_modem_ctrl_e. + \return error code +*/ +int32_t csi_usart_modem_ctrl(usart_handle_t handle, usart_modem_ctrl_e modem_ctrl) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief get usart modem status. + \param[in] handle usart handle to operate. + \param[in] modem_ctrl modem control action.\ref usart_modem_ctrl_e. + \return modem status.\ref usart_modem_stat_t. +*/ +usart_modem_stat_t csi_usart_get_modem_stat(usart_handle_t handle) +{ + usart_modem_stat_t modem_stat = {0}; + return modem_stat; +} + +/** + \brief config usart clock Polarity and Phase. + \param[in] handle usart handle to operate. + \param[in] cpol Clock Polarity.\ref usart_cpol_e. + \param[in] cpha Clock Phase.\ref usart_cpha_e. + \return error code +*/ +int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief config usart guard time. + \param[in] handle usart handle to operate. + \param[in] num_of_bits guard time in number of bit periods. + \return error code +*/ +int32_t csi_usart_config_guard_time(usart_handle_t handle, uint32_t num_of_bits) +{ + return ERR_USART(EDRV_UNSUPPORTED); +} + +/** + \brief check if usart is readable(data received). + \param[in] handle usart handle to operate. + \return 1 - a character can be read, 0 if nothing to read ,negative for error code +*/ +int32_t csi_usart_readable(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + if (addr->LSR & LSR_DATA_READY) { + return 1; + } else { + return 0; + } +} + +/** + \brief check if usart is writable(free for data sending). + \param[in] handle usart handle to operate. + \return 1 - a character can be written, 0 - cannot be written ,negative for error code +*/ +int32_t csi_usart_writable(usart_handle_t handle) +{ + USART_NULL_PARAM_CHK(handle); + dw_usart_priv_t *usart_priv = handle; + dw_usart_reg_t *addr = (dw_usart_reg_t *)(usart_priv->base); + + if (addr->LSR & DW_LSR_TRANS_EMPTY) { + return 1; + } else { + return 0; + } +}