123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956 |
- /* ------------------------------------------
- * Copyright (c) 2016, Synopsys, Inc. All rights reserved.
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1) Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2) 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.
- * 3) Neither the name of the Synopsys, Inc., 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.
- *
- * \version 2016.05
- * \date 2014-06-20
- * \author Huaqi Fang(Huaqi.Fang@synopsys.com)
- --------------------------------------------- */
- /**
- * \defgroup DEVICE_DW_UART Designware UART Driver
- * \ingroup DEVICE_DW
- * \brief Designware UART Driver Implementation
- */
- /**
- * \file
- * \ingroup DEVICE_DW_UART
- * \brief DesignWare UART driver implementation based on device hal layer definition (\ref dev_uart.h)
- */
- #include <string.h>
- #include "inc/embARC_toolchain.h"
- #include "inc/embARC_error.h"
- #include "inc/arc/arc_exception.h"
- #include "device/designware/uart/dw_uart_hal.h"
- #include "device/designware/uart/dw_uart.h"
- /**
- * \name DesignWare UART Driver Macros
- * \brief DesignWare UART driver macros used in uart driver
- * @{
- */
- /** check expressions used in DesignWare UART driver implementation */
- #define DW_UART_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
- #ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
- /** valid check of uart info object */
- #define VALID_CHK_UART_INFO_OBJECT(uartinfo_obj_ptr) { \
- DW_UART_CHECK_EXP((uartinfo_obj_ptr)!=NULL, E_OBJ); \
- DW_UART_CHECK_EXP(((uartinfo_obj_ptr)->uart_ctrl)!=NULL, E_OBJ); \
- }
- #endif
- /** convert DesignWare baudrate to divisor */
- #define DW_UART_BAUD2DIV(perifreq, baud) ((perifreq) / ((baud)*16))
- /**
- * \name DesignWare UART Interrupt Callback Routine Select Marcos
- * \brief DesignWare UART interrupt callback routines select macros definitions
- * @{
- */
- #define DW_UART_RDY_SND (1U) /*!< ready to send callback */
- #define DW_UART_RDY_RCV (2U) /*!< ready to receive callback */
- /** @} */
- /** @} */
- /**
- * \defgroup DEVICE_DW_UART_STATIC DesignWare UART Driver Static Functions
- * \ingroup DEVICE_DW_UART
- * \brief Static or inline functions, variables for DesignWare UART handle uart operations,
- * only used in this file
- * @{
- */
- const uint8_t dw_uart_databits[] = { \
- DW_UART_LCR_WORD_LEN5, DW_UART_LCR_WORD_LEN6, \
- DW_UART_LCR_WORD_LEN7, DW_UART_LCR_WORD_LEN8};
- const uint8_t dw_uart_parity[] = {
- DW_UART_LCR_PARITY_NONE, DW_UART_LCR_PARITY_ODD,
- DW_UART_LCR_PARITY_EVEN, DW_UART_LCR_PARITY_MASK,
- DW_UART_LCR_PARITY_SPACE
- };
- const uint8_t dw_uart_stopbits[] = {
- DW_UART_LCR_1_STOP_BIT, DW_UART_LCR_1D5_STOP_BIT,
- DW_UART_LCR_2_STOP_BIT
- };
- /** test whether uart is ready to send, 1 ready, 0 not ready */
- Inline int32_t dw_uart_putready(DW_UART_REG *uart_reg_ptr)
- {
- return ((uart_reg_ptr->USR & DW_UART_USR_TFNF) != 0);
- }
- /** test whether uart is ready to receive, 1 ready, 0 not ready */
- Inline int32_t dw_uart_getready(DW_UART_REG *uart_reg_ptr)
- {
- return ((uart_reg_ptr->USR & DW_UART_USR_RFNE) != 0);
- }
- /** write char to uart send fifo */
- Inline void dw_uart_putchar(DW_UART_REG *uart_reg_ptr, char chr)
- {
- uart_reg_ptr->DATA = chr;
- }
- /** read data from uart receive fifo, return data received */
- Inline int32_t dw_uart_getchar(DW_UART_REG *uart_reg_ptr)
- {
- return (int32_t)uart_reg_ptr->DATA;
- }
- /**
- * \brief send char by uart when available,
- * mostly used in interrupt method, non-blocked function
- * \param[in] uart_reg_ptr uart register structure pointer
- * \param[in] chr char to be sent
- * \retval 0 send successfully
- * \retval -1 not ready to send data
- */
- Inline int32_t dw_uart_snd_chr(DW_UART_REG *uart_reg_ptr, char chr)
- {
- if (dw_uart_putready(uart_reg_ptr)) {
- dw_uart_putchar(uart_reg_ptr, chr);
- return 0;
- }
- return -1;
- }
- /**
- * \brief receive one char from uart,
- * mostly used in interrupt routine, non-blocked function
- * \param[in] uart_reg_ptr uart register structure pointer
- * \return data received by the uart
- */
- Inline int32_t dw_uart_rcv_chr(DW_UART_REG *uart_reg_ptr)
- {
- return dw_uart_getchar(uart_reg_ptr);
- }
- /**
- * \brief send char by uart in poll method, blocked function
- * \param[in] uart_reg_ptr uart register structure pointer
- * \param[in] chr char to be sent
- */
- Inline void dw_uart_psnd_chr(DW_UART_REG *uart_reg_ptr, char chr)
- {
- /** wait until uart is ready to send */
- while (!dw_uart_putready(uart_reg_ptr)); /* blocked */
- /** send char */
- dw_uart_putchar(uart_reg_ptr, chr);
- }
- /**
- * \brief receive one char from uart in poll method, blocked function
- * \param[in] uart_reg_ptr uart register structure pointer
- * \return data received by the uart
- */
- Inline int32_t dw_uart_prcv_chr(DW_UART_REG *uart_reg_ptr)
- {
- /** wait until uart is ready to receive */
- while (!dw_uart_getready(uart_reg_ptr)); /* blocked */
- /** receive data */
- return dw_uart_getchar(uart_reg_ptr);
- }
- /** Get TX FIFO Length */
- Inline uint32_t dw_uart_get_txfifo_len(DW_UART_REG *uart_reg_ptr)
- {
- uint32_t txfifolen;
- uint32_t uart_cpr;
- uart_cpr = uart_reg_ptr->CPR;
- if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
- txfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
- } else {
- txfifolen = 0;
- }
- return txfifolen;
- }
- /** Get RX FIFO Length */
- Inline uint32_t dw_uart_get_rxfifo_len(DW_UART_REG *uart_reg_ptr)
- {
- uint32_t rxfifolen;
- uint32_t uart_cpr;
- uart_cpr = uart_reg_ptr->CPR;
- if (uart_cpr & DW_UART_CPR_FIFO_STAT) {
- rxfifolen = ((uart_cpr & DW_UART_CPR_FIFO_MODE) >> DW_UART_CPR_FIFO_MODE_OFS) << 4;
- } else {
- rxfifolen = 0;
- }
- return rxfifolen;
- }
- /**
- * \brief set designware uart DPS value
- * \param uart_reg_ptr uart register structure
- * \param dps data bits/parity bit/stop bits parameter
- * \retval 0 Set ok
- * \retval !0 Set failed
- */
- static int32_t dw_uart_set_dps(DW_UART_REG *uart_reg_ptr, UART_DPS_FORMAT *dps)
- {
- uint32_t dps_value = 0;
- if (dps == NULL) return -1;
- /* data bits check */
- if ((dps->databits < 5) || (dps->databits > 8)) return -1;
- /* stop bits check */
- if (dps->stopbits > UART_STPBITS_TWO) return -1;
- /* parity bit type check */
- if (dps->parity > UART_PARITY_SPACE) return -1;
- dps_value |= (uint32_t)dw_uart_databits[dps->databits-5];
- dps_value |= (uint32_t)dw_uart_stopbits[dps->stopbits];
- dps_value |= (uint32_t)dw_uart_parity[dps->parity];
- /* clear dps bits */
- uart_reg_ptr->LCR &= (~DW_UART_LCR_DPS_MASK);
- /* set dps bits */
- uart_reg_ptr->LCR |= dps_value;
- return 0;
- }
- /**
- * \brief set designware uart baudrate
- * \param uart_reg_ptr uart register structure
- * \param baud_divisor uart baudrate divisor
- */
- static void dw_uart_set_baud(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor)
- {
- /* enable uart baudrate update */
- uart_reg_ptr->LCR |= DW_UART_LCR_DLAB;
- /**
- * setting uart baudrate registers
- */
- uart_reg_ptr->DATA = baud_divisor & 0xff; /*!< DLL */
- uart_reg_ptr->IER = (baud_divisor>>8) & 0xff; /*!< DLH */
- /** disable DLAB */
- uart_reg_ptr->LCR &= ~(DW_UART_LCR_DLAB);
- }
- /**
- * \brief Do uart software reset
- * \param uart_reg_ptr uart register structure
- */
- Inline void dw_uart_software_reset(DW_UART_REG *uart_reg_ptr)
- {
- uart_reg_ptr->SRR = DW_UART_SRR_UR|DW_UART_SRR_RFR|DW_UART_SRR_XFR;
- while(uart_reg_ptr->USR & DW_UART_USR_BUSY); /* wait until software reset completed */
- }
- /**
- * \brief set designware uart baudrate
- * \param uart_reg_ptr uart register structure
- * \param hwfc uart hardware flow control type
- * \note Need to set corresponding pin functions
- */
- static void dw_uart_set_hwfc(DW_UART_REG *uart_reg_ptr, UART_HW_FLOW_CONTROL hwfc)
- {
- if (hwfc == UART_FC_NONE) {
- uart_reg_ptr->MCR &= ~(DW_UART_MCR_AFCE|DW_UART_MCR_RTS);
- }
- if ((hwfc == UART_FC_RTS) || (hwfc == UART_FC_BOTH)) {
- uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE|DW_UART_MCR_RTS);
- }
- if ((hwfc == UART_FC_CTS) || (hwfc == UART_FC_BOTH)) {
- uart_reg_ptr->MCR |= (DW_UART_MCR_AFCE);
- }
- }
- Inline void dw_uart_set_break(DW_UART_REG *uart_reg_ptr)
- {
- uart_reg_ptr->LCR |= DW_UART_LCR_BREAK;
- }
- Inline void dw_uart_clr_break(DW_UART_REG *uart_reg_ptr)
- {
- uart_reg_ptr->LCR &= ~DW_UART_LCR_BREAK;
- }
- /**
- * \brief init designware uart with selected baud
- * \param[in] uart_reg_ptr uart register structure pointer
- * \param[in] baud_divisor baudrate divisor
- */
- static void dw_uart_init(DW_UART_REG *uart_reg_ptr, uint32_t baud_divisor, UART_DPS_FORMAT *dps, UART_HW_FLOW_CONTROL hwfc)
- {
- dw_uart_software_reset(uart_reg_ptr);
- dw_uart_set_hwfc(uart_reg_ptr, hwfc);
- dw_uart_set_dps(uart_reg_ptr, dps);
- dw_uart_set_baud(uart_reg_ptr, baud_divisor);
- uart_reg_ptr->IIR = 0x1; /** enable uart fifo (FCR IIR is the same) */
- uart_reg_ptr->IER = 0x0; /** disable all uart interrupt */
- }
- /**
- * \brief set designware uart baudrate
- * \param uart_info_ptr uart information structure pointer
- */
- static void dw_uart_flush_output(DEV_UART_INFO *uart_info_ptr)
- {
- uint32_t i;
- char *p_charbuf;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- if (uart_info_ptr->tx_buf.buf != NULL) {
- p_charbuf = (char *)(uart_info_ptr->tx_buf.buf);
- for (i = uart_info_ptr->tx_buf.ofs; i < uart_info_ptr->tx_buf.len; i ++) {
- dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i]);
- }
- /* clear transmit buffer */
- uart_info_ptr->tx_buf.buf = NULL;
- uart_info_ptr->tx_buf.len = 0;
- uart_info_ptr->tx_buf.ofs = 0;
- }
- /* wait until transmit fifo is empty */
- while ((uart_reg_ptr->USR & DW_UART_USR_TFE) == 0);
- while (uart_reg_ptr->USR & DW_UART_USR_BUSY);
- }
- /**
- * \brief disable designware uart send or receive interrupt
- * \param[in] DEV_UART_INFO *uart_info_ptr
- * \param[in] cbrtn control code of callback routine of send or receive
- */
- static void dw_uart_dis_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- switch (cbrtn) {
- case DW_UART_RDY_SND:
- uart_reg_ptr->IER &= ~DW_UART_IER_XMIT_EMPTY;
- uart_ctrl_ptr->int_status &= ~DW_UART_TXINT_ENABLE;
- break;
- case DW_UART_RDY_RCV:
- uart_reg_ptr->IER &= ~DW_UART_IER_DATA_AVAIL;
- uart_ctrl_ptr->int_status &= ~DW_UART_RXINT_ENABLE;
- break;
- default:
- break;
- }
- if (uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) {
- if ((uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) == 0) {
- int_disable(uart_ctrl_ptr->intno);
- uart_ctrl_ptr->int_status &= ~DW_UART_GINT_ENABLE;
- }
- }
- }
- /**
- * \brief enable DesignWare UART send or receive interrupt
- * \param[in] DEV_UART_INFO *uart_info_ptr
- * \param[in] cbrtn control code of callback routine of send or receive
- */
- static void dw_uart_ena_cbr(DEV_UART_INFO *uart_info_ptr, uint32_t cbrtn)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- switch (cbrtn) {
- case DW_UART_RDY_SND:
- uart_ctrl_ptr->int_status |= DW_UART_TXINT_ENABLE;
- uart_reg_ptr->IER |= DW_UART_IER_XMIT_EMPTY;
- break;
- case DW_UART_RDY_RCV:
- uart_ctrl_ptr->int_status |= DW_UART_RXINT_ENABLE;
- uart_reg_ptr->IER |= DW_UART_IER_DATA_AVAIL;
- break;
- default:
- break;
- }
- if ((uart_ctrl_ptr->int_status & DW_UART_GINT_ENABLE) == 0) {
- if (uart_ctrl_ptr->int_status & (DW_UART_RXINT_ENABLE|DW_UART_TXINT_ENABLE)) {
- uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE;
- int_enable(uart_ctrl_ptr->intno);
- }
- }
- }
- /**
- * \brief enable designware uart interrupt
- * \param uart_info_ptr uart information structure pointer
- */
- static void dw_uart_enable_interrupt(DEV_UART_INFO *uart_info_ptr)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler);
- uart_ctrl_ptr->int_status |= DW_UART_GINT_ENABLE;
- int_enable(uart_ctrl_ptr->intno); /** enable uart interrupt */
- }
- /**
- * \brief disable designware uart interrupt
- * \param uart_info_ptr uart information structure pointer
- */
- static void dw_uart_disable_interrupt(DEV_UART_INFO *uart_info_ptr)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- /** disable uart send&receive interrupt after disable uart interrupt */
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
- /* disable uart interrupt */
- int_disable(uart_ctrl_ptr->intno);
- uart_ctrl_ptr->int_status &= ~(DW_UART_GINT_ENABLE|DW_UART_TXINT_ENABLE|DW_UART_RXINT_ENABLE);
- }
- /** enable designware uart */
- static void dw_uart_enable_device(DEV_UART_INFO *uart_info_ptr)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
- dw_uart_set_baud(uart_reg_ptr, uart_info_ptr->baudrate);
- uart_info_ptr->status |= DEV_ENABLED;
- }
- }
- /** disable designware uart */
- static void dw_uart_disable_device(DEV_UART_INFO *uart_info_ptr)
- {
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- if ((uart_info_ptr->status & DEV_ENABLED) == DEV_ENABLED) {
- dw_uart_set_baud(uart_reg_ptr, 0);
- uart_info_ptr->status &= ~DEV_ENABLED;
- }
- }
- /** abort current interrupt transmit transfer */
- static void dw_uart_abort_tx(DEV_UART *uart_obj)
- {
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- if (uart_ctrl_ptr->int_status & DW_UART_TXINT_ENABLE) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
- uart_info_ptr->status |= DEV_IN_TX_ABRT;
- if (uart_info_ptr->uart_cbs.tx_cb != NULL) {
- uart_info_ptr->uart_cbs.tx_cb(uart_obj);
- }
- uart_info_ptr->status &= ~(DEV_IN_TX_ABRT);
- }
- }
- /** abort current interrupt receive transfer */
- static void dw_uart_abort_rx(DEV_UART *uart_obj)
- {
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- if (uart_ctrl_ptr->int_status & DW_UART_RXINT_ENABLE) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
- uart_info_ptr->status |= DEV_IN_RX_ABRT;
- if (uart_info_ptr->uart_cbs.rx_cb != NULL) {
- uart_info_ptr->uart_cbs.rx_cb(uart_obj);
- }
- uart_info_ptr->status &= ~(DEV_IN_RX_ABRT);
- }
- }
- /** Get available transmit fifo count */
- static int32_t dw_uart_get_txavail(DW_UART_CTRL *uart_ctrl_ptr)
- {
- int32_t tx_avail = 0;
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
- if (uart_ctrl_ptr->tx_fifo_len <= 1) {
- if (dw_uart_putready(uart_reg_ptr) == 1) {
- tx_avail = 1;
- } else {
- tx_avail = 0;
- }
- } else {
- tx_avail = uart_ctrl_ptr->tx_fifo_len - uart_reg_ptr->TFL;
- }
- return tx_avail;
- }
- /** Get available receive fifo count */
- static int32_t dw_uart_get_rxavail(DW_UART_CTRL *uart_ctrl_ptr)
- {
- int32_t rx_avail = 0;
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG *)(uart_ctrl_ptr->dw_uart_regbase);
- if (uart_ctrl_ptr->rx_fifo_len <= 1) {
- if (dw_uart_getready(uart_reg_ptr) == 1) {
- rx_avail = 1;
- } else {
- rx_avail = 0;
- }
- } else {
- rx_avail = uart_reg_ptr->RFL;
- }
- return rx_avail;
- }
- /** @} end of group DEVICE_DW_UART_STATIC */
- /**
- * \brief open a designware uart device
- * \param[in] uart_obj uart object structure pointer
- * \param[in] baud baudrate to initialized
- * \retval E_OK Open successfully without any issues
- * \retval E_OPNED If device was opened before with different baudrate, then return E_OPNED
- * \retval E_OBJ Device object is not valid
- * \retval E_PAR Parameter is not valid
- * \retval E_NOSPT Open settings are not supported
- */
- int32_t dw_uart_open (DEV_UART *uart_obj, uint32_t baud)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- DW_UART_CHECK_EXP(baud>0, E_PAR);
- /* END OF ERROR CHECK */
- uart_info_ptr->opn_cnt ++;
- if (uart_info_ptr->opn_cnt > 1) { /* opened before */
- if (baud == uart_info_ptr->baudrate) { /* baudrate is the same */
- return E_OK;
- } else { /* open with different baudrate */
- return E_OPNED;
- }
- }
- int32_t baud_divisor = 0;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- /* Get FIFO Length */
- uart_ctrl_ptr->tx_fifo_len = dw_uart_get_txfifo_len(uart_reg_ptr);
- uart_ctrl_ptr->rx_fifo_len = dw_uart_get_rxfifo_len(uart_reg_ptr);
- /** init uart */
- uart_info_ptr->baudrate = baud;
- baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, baud);
- uart_info_ptr->dps_format = dps_format_default;
- uart_info_ptr->hwfc = hwfc_default;
- dw_uart_init(uart_reg_ptr, baud_divisor, &(uart_info_ptr->dps_format), uart_info_ptr->hwfc);
- uart_info_ptr->status = DEV_ENABLED;
- uart_info_ptr->extra = NULL;
- /**
- * uart interrupt related init
- */
- dw_uart_disable_interrupt(uart_info_ptr);
- /** install uart interrupt into system */
- int_handler_install(uart_ctrl_ptr->intno, uart_ctrl_ptr->dw_uart_int_handler);
- memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
- memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
- memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
- error_exit:
- return ercd;
- }
- /**
- * \brief close a DesignWare UART device
- * \param[in] uart_obj uart object structure pointer
- * \retval E_OK Open successfully without any issues
- * \retval E_OPNED Device is still opened, the device opn_cnt decreased by 1
- * \retval E_OBJ Device object is not valid
- */
- int32_t dw_uart_close (DEV_UART *uart_obj)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_OK);
- /* END OF ERROR CHECK */
- uart_info_ptr->opn_cnt --;
- if (uart_info_ptr->opn_cnt == 0) {
- dw_uart_disable_interrupt(uart_info_ptr);
- dw_uart_abort_tx(uart_obj);
- dw_uart_abort_rx(uart_obj);
- dw_uart_flush_output(uart_info_ptr);
- memset(&(uart_info_ptr->tx_buf), 0, sizeof(DEV_BUFFER));
- memset(&(uart_info_ptr->rx_buf), 0, sizeof(DEV_BUFFER));
- memset(&(uart_info_ptr->uart_cbs), 0, sizeof(DEV_UART_CBS));
- dw_uart_disable_device(uart_info_ptr);
- uart_info_ptr->status = 0;
- uart_info_ptr->extra = NULL;
- } else {
- ercd = E_OPNED;
- }
- error_exit:
- return ercd;
- }
- /**
- * \brief control uart by ctrl command
- * \param[in] uart_obj uart object structure pointer
- * \param[in] ctrl_cmd control command code to do specific uart work
- * \param[in,out] param parameters used to control uart or return something
- * \retval E_OK Control device successfully
- * \retval E_CLSED Device is not opened
- * \retval E_DIS Device is disabled
- * \retval E_OBJ Device object is not valid or not exists
- * \retval E_PAR Parameter is not valid for current control command
- * \retval E_SYS Control device failed, due to hardware issues
- * \retval E_CTX Control device failed, due to different reasons like in transfer state
- * \retval E_NOSPT Control command is not supported or not valid
- */
- int32_t dw_uart_control (DEV_UART *uart_obj, uint32_t ctrl_cmd, void *param)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
- /* END OF ERROR CHECK */
- uint32_t val32; /** to receive unsigned int value */
- int32_t baud_divisor = 0;
- DEV_BUFFER *devbuf;
- UART_DPS_FORMAT *dps_ptr;
- UART_HW_FLOW_CONTROL hwfc_local;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- /* check whether current device is disabled */
- if ((uart_info_ptr->status & DEV_ENABLED) == 0) {
- /** When device is disabled,
- * only UART_CMD_ENA_DEV, UART_CMD_DIS_DEV, UART_CMD_GET_STATUS
- * are available, other commands will return E_SYS
- */
- if ((ctrl_cmd != UART_CMD_ENA_DEV) && \
- (ctrl_cmd != UART_CMD_DIS_DEV) && \
- (ctrl_cmd != UART_CMD_GET_STATUS) ) {
- return E_SYS;
- }
- }
- switch (ctrl_cmd) {
- case UART_CMD_SET_BAUD:
- val32 = (uint32_t)param;
- DW_UART_CHECK_EXP(val32>0, E_PAR);
- if (val32 != uart_info_ptr->baudrate) {
- baud_divisor = DW_UART_BAUD2DIV(uart_ctrl_ptr->dw_apb_bus_freq, val32);
- dw_uart_set_baud(uart_reg_ptr, baud_divisor);
- uart_info_ptr->baudrate = val32;
- }
- break;
- case UART_CMD_GET_STATUS:
- DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- *((int32_t *)param) = uart_info_ptr->status;
- break;
- case UART_CMD_ENA_DEV:
- dw_uart_enable_device(uart_info_ptr);
- break;
- case UART_CMD_DIS_DEV:
- dw_uart_disable_device(uart_info_ptr);
- break;
- case UART_CMD_FLUSH_OUTPUT:
- dw_uart_flush_output(uart_info_ptr);
- break;
- case UART_CMD_GET_RXAVAIL:
- DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- *((int32_t *)param) = dw_uart_get_rxavail(uart_ctrl_ptr);
- break;
- case UART_CMD_GET_TXAVAIL:
- DW_UART_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- *((int32_t *)param) = dw_uart_get_txavail(uart_ctrl_ptr);
- break;
- case UART_CMD_BREAK_SET:
- dw_uart_set_break(uart_reg_ptr);
- break;
- case UART_CMD_BREAK_CLR:
- dw_uart_clr_break(uart_reg_ptr);
- break;
- case UART_CMD_SET_DPS_FORMAT:
- DW_UART_CHECK_EXP(param!=NULL, E_PAR);
- dps_ptr = (UART_DPS_FORMAT *)param;
- if (dw_uart_set_dps(uart_reg_ptr, dps_ptr) == 0) {
- uart_info_ptr->dps_format = *dps_ptr;
- } else {
- ercd = E_PAR;
- }
- break;
- case UART_CMD_SET_HWFC:
- hwfc_local = (UART_HW_FLOW_CONTROL)param;
- DW_UART_CHECK_EXP(((hwfc_local>=UART_FC_NONE) && (hwfc_local<=UART_FC_BOTH)), E_PAR);
- dw_uart_set_hwfc(uart_reg_ptr, hwfc_local);
- uart_info_ptr->hwfc = hwfc_local;
- break;
- case UART_CMD_SET_TXCB:
- DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
- uart_info_ptr->uart_cbs.tx_cb = param;
- break;
- case UART_CMD_SET_RXCB:
- DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
- uart_info_ptr->uart_cbs.rx_cb = param;
- break;
- case UART_CMD_SET_ERRCB:
- DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
- uart_info_ptr->uart_cbs.err_cb = param;
- break;
- case UART_CMD_ABORT_TX:
- dw_uart_abort_tx(uart_obj);
- break;
- case UART_CMD_ABORT_RX:
- dw_uart_abort_rx(uart_obj);
- break;
- case UART_CMD_SET_TXINT:
- val32 = (uint32_t)param;
- if (val32 == 0) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
- } else {
- dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_SND);
- }
- break;
- case UART_CMD_SET_RXINT:
- val32 = (uint32_t)param;
- if (val32 == 0) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
- } else {
- dw_uart_ena_cbr(uart_info_ptr, DW_UART_RDY_RCV);
- }
- break;
- case UART_CMD_SET_TXINT_BUF:
- DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
- if (param != NULL) {
- devbuf = (DEV_BUFFER *)param;
- uart_info_ptr->tx_buf = *devbuf;
- uart_info_ptr->tx_buf.ofs = 0;
- } else {
- uart_info_ptr->tx_buf.buf = NULL;
- uart_info_ptr->tx_buf.len = 0;
- uart_info_ptr->tx_buf.ofs = 0;
- }
- break;
- case UART_CMD_SET_RXINT_BUF:
- DW_UART_CHECK_EXP(CHECK_ALIGN_4BYTES(param), E_PAR);
- if (param != NULL) {
- devbuf = (DEV_BUFFER *)param;
- uart_info_ptr->rx_buf = *devbuf;
- uart_info_ptr->rx_buf.ofs = 0;
- } else {
- uart_info_ptr->rx_buf.buf = NULL;
- uart_info_ptr->rx_buf.len = 0;
- uart_info_ptr->rx_buf.ofs = 0;
- }
- break;
- default:
- ercd = E_NOSPT;
- break;
- }
- error_exit:
- return ercd;
- }
- /**
- * \brief send data through DesignWare UART
- * \param[in] uart_obj uart object structure pointer
- * \param[in] data data that need to send (data must be char type)
- * \param[in] len data length need to send
- * \retval >0 Byte count that was successfully sent for poll method
- * \retval E_OBJ Device object is not valid or not exists
- * \retval E_PAR Parameter is not valid for current control command
- * \retval E_SYS Can't write data to hardware due to hardware issues
- */
- int32_t dw_uart_write (DEV_UART *uart_obj, const void *data, uint32_t len)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
- DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
- DW_UART_CHECK_EXP(data!=NULL, E_PAR);
- DW_UART_CHECK_EXP(len>0, E_PAR);
- /* END OF ERROR CHECK */
- int32_t i = 0;
- const char *p_charbuf = (const char *)data;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- while (i < len) {
- dw_uart_psnd_chr(uart_reg_ptr, p_charbuf[i++]);
- }
- ercd = i;
- error_exit:
- return ercd;
- }
- /**
- * \brief read data through DesignWare UART
- * \param[in] uart_obj uart object structure pointer
- * \param[out] data data that need to read (data must be char type)
- * \param[in] len data count need to read
- * \retval >0 Byte count that was successfully sent for poll method
- * \retval E_OBJ Device object is not valid or not exists
- * \retval E_PAR Parameter is not valid for current control command
- * \retval E_SYS Can't receive data from hardware due to hardware issues, such as device is disabled
- */
- int32_t dw_uart_read (DEV_UART *uart_obj, void *data, uint32_t len)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- DW_UART_CHECK_EXP(uart_info_ptr->opn_cnt > 0, E_CLSED);
- DW_UART_CHECK_EXP(uart_info_ptr->status & DEV_ENABLED, E_SYS);
- DW_UART_CHECK_EXP(data!=NULL, E_PAR);
- DW_UART_CHECK_EXP(len>0, E_PAR);
- /* END OF ERROR CHECK */
- int32_t i = 0;
- char *p_charbuf = (char *)data;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- while (i < len) {
- p_charbuf[i++] = dw_uart_prcv_chr(uart_reg_ptr);
- }
- ercd = i;
- error_exit:
- return ercd;
- }
- /**
- * \brief DesignWare UART interrupt processing routine
- * \param[in] uart_obj uart object structure pointer
- * \param[in] ptr extra information
- */
- void dw_uart_isr (DEV_UART *uart_obj, void *ptr)
- {
- int32_t ercd = E_OK;
- DEV_UART_INFO *uart_info_ptr = &(uart_obj->uart_info);
- /* START ERROR CHECK */
- VALID_CHK_UART_INFO_OBJECT(uart_info_ptr);
- /* END OF ERROR CHECK */
- uint32_t uart_int_status; /** uart interrupt status */
- volatile uint32_t temp; /** read error status to clear interrupt */
- DEV_BUFFER *buf_ptr;
- char *p_charbuf;
- DW_UART_CTRL *uart_ctrl_ptr = (DW_UART_CTRL_PTR)(uart_info_ptr->uart_ctrl);
- DW_UART_REG *uart_reg_ptr = (DW_UART_REG_PTR)(uart_ctrl_ptr->dw_uart_regbase);
- /** get uart interrupt status */
- uart_int_status = (uart_reg_ptr->IIR) & DW_UART_IIR_INT_ID_MASK;
- switch (uart_int_status) {
- case DW_UART_IIR_MDM_STATUS:
- temp = (volatile uint32_t)(uart_reg_ptr->MSR);
- break;
- case DW_UART_IIR_LINE_STATUS:
- if (uart_info_ptr->uart_cbs.err_cb) {
- uart_info_ptr->uart_cbs.err_cb(uart_info_ptr);
- }
- temp = (volatile uint32_t)(uart_reg_ptr->LSR);
- break;
- case DW_UART_IIR_XMIT_EMPTY:
- buf_ptr = &(uart_info_ptr->tx_buf);
- p_charbuf = (char *)buf_ptr->buf;
- if (p_charbuf != NULL) {
- while (dw_uart_putready(uart_reg_ptr)) {
- dw_uart_putchar(uart_reg_ptr, p_charbuf[buf_ptr->ofs]);
- buf_ptr->ofs ++;
- if (buf_ptr->ofs >= buf_ptr->len) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_SND);
- if (uart_info_ptr->uart_cbs.tx_cb) {
- uart_info_ptr->uart_cbs.tx_cb(uart_obj);
- }
- /* clear the send buffer pointer */
- memset(buf_ptr, 0, sizeof(DEV_BUFFER));
- break;
- }
- }
- } else {
- if (uart_info_ptr->uart_cbs.tx_cb) {
- uart_info_ptr->uart_cbs.tx_cb(uart_obj);
- }
- }
- break;
- case DW_UART_IIR_RX_TIMEOUT:
- temp = dw_uart_getchar(uart_reg_ptr);
- break;
- case DW_UART_IIR_DATA_AVAIL:
- buf_ptr = &(uart_info_ptr->rx_buf);
- p_charbuf = (char *)buf_ptr->buf;
- if (p_charbuf != NULL) {
- while (dw_uart_getready(uart_reg_ptr)) {
- p_charbuf[buf_ptr->ofs] = (char)dw_uart_getchar(uart_reg_ptr);
- buf_ptr->ofs ++;
- if (buf_ptr->ofs >= buf_ptr->len) {
- dw_uart_dis_cbr(uart_info_ptr, DW_UART_RDY_RCV);
- if (uart_info_ptr->uart_cbs.rx_cb) {
- uart_info_ptr->uart_cbs.rx_cb(uart_obj);
- }
- /* clear the send buffer pointer */
- memset(buf_ptr, 0, sizeof(DEV_BUFFER));
- break;
- }
- }
- } else {
- if (uart_info_ptr->uart_cbs.rx_cb) {
- uart_info_ptr->uart_cbs.rx_cb(uart_obj);
- }
- }
- break;
- default:
- temp = (volatile uint32_t)(uart_reg_ptr->USR);
- break;
- }
- error_exit:
- return;
- }
|