3163 lines
110 KiB
C
3163 lines
110 KiB
C
/**
|
|
* @file sdrv_uart.c
|
|
* @brief sdrv uart driver source.
|
|
*
|
|
* @copyright Copyright (c) 2020 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <debug.h>
|
|
#include <string.h>
|
|
#include <types.h>
|
|
|
|
#include "sdrv_uart.h"
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
#include "armv7-r/cache.h"
|
|
#endif
|
|
#include "common.h"
|
|
#include "irq.h"
|
|
|
|
/**************************Static Functions Start******************************/
|
|
/**
|
|
* brief Srdv UART Initialization.
|
|
*
|
|
* This function brief initializes sdrv uart module with user-defined settings
|
|
*
|
|
* param [in] cfg sdrv uart config
|
|
* return The result of initializing uart module
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_init(const sdrv_uart_config_t *cfg);
|
|
|
|
/**
|
|
* brief Srdv UART set flow control mode.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* param [in] fcm_cfg The configurations of fcm
|
|
*/
|
|
static void sdrv_uart_set_fcm(sdrv_uart_regs_t *base,
|
|
sdrv_uart_fcm_config_t *fcm_cfg);
|
|
|
|
/**
|
|
* brief Srdv UART initializes interrupt register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt to disable.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static void sdrv_uart_intr_init(sdrv_uart_regs_t *base);
|
|
|
|
/**
|
|
* brief Srdv UART initializes interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static void sdrv_uart_intr_status_init(sdrv_uart_regs_t *base);
|
|
|
|
/**
|
|
* brief Srdv UART initializes rx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module rx interrupt.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_rx_intr_ctrl(sdrv_uart_t *ctrl, bool enable);
|
|
|
|
/**
|
|
* brief Srdv UART initializes tx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module tx interrupt.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_tx_intr_ctrl(sdrv_uart_t *ctrl, bool enable);
|
|
|
|
/**
|
|
* brief Srdv UART initializes rx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_rx_intrstatus_clear(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Srdv UART initializes tx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
*/
|
|
static void sdrv_uart_tx_intrstatus_clear(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Disable uart module.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static inline void sdrv_uart_disable(sdrv_uart_regs_t *base);
|
|
|
|
/**
|
|
* brief Sdrv uart baudrate round-off.
|
|
*
|
|
* param [in] dividend The clock frequency.
|
|
* param [in] divisor The value of baud.
|
|
* return The result of the baudrate after rounded off.
|
|
*/
|
|
static uint32_t sdrv_uart_baudrate_roundoff(uint32_t dividend,
|
|
uint32_t divisor);
|
|
|
|
/**
|
|
* brief Sdrv uart get char from rx fifo.
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] c The character to be received
|
|
* param [in] timeout The max times of query fifo empty register
|
|
* return The result of getting a character from rx fifo
|
|
*/
|
|
static inline bool sdrv_uart_getc(sdrv_uart_regs_t *base, uint8_t *c,
|
|
uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart put char in tx fifo.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* param [in] c The character to be transmitted
|
|
* param [in] timeout The max times of query fifo full register
|
|
* return The result of writting a character from tx fifo
|
|
*/
|
|
static inline bool sdrv_uart_putc(sdrv_uart_regs_t *base, uint8_t c,
|
|
uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart async read data from fifo
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] data Data buff
|
|
* param [in] size The size of data expected
|
|
* return The count of received characters
|
|
*/
|
|
static inline uint32_t sdrv_uart_read_async(sdrv_uart_regs_t *base,
|
|
uint8_t *data, uint32_t size);
|
|
/**
|
|
* brief Sdrv uart async write data to fifo
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] data Data buff
|
|
* param [in] size The size of data expected
|
|
* return The count of transmitted characters
|
|
*/
|
|
static inline uint32_t sdrv_uart_send_async(sdrv_uart_regs_t *base,
|
|
const uint8_t *data, uint32_t size);
|
|
|
|
/**
|
|
* brief Sdrv uart get the length of data in rx fifo.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* return The length of data in rx fifo
|
|
*/
|
|
static inline uint32_t sdrv_uart_get_rxfifolen(sdrv_uart_regs_t *base);
|
|
|
|
/**
|
|
* brief Sdrv uart module reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart module.
|
|
*/
|
|
static bool sdrv_uart_module_reset(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart clear tx fifo.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
*
|
|
* return The result of clearing tx fifo.
|
|
*/
|
|
static bool sdrv_uart_txfifo_clear(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart clear rx fifo.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
*
|
|
* return The result of clearing rx fifo.
|
|
*/
|
|
static bool sdrv_uart_rxfifo_clear(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart rx dma reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart dma rx.
|
|
*/
|
|
static bool sdrv_uart_rxdma_reset(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Sdrv uart tx dma reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart dma tx.
|
|
*/
|
|
static bool sdrv_uart_txdma_reset(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Waitting until sdrv uart tx io state changing to idle.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_txio_idle(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Waitting until sdrv uart rx io state changing to idle.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_rxio_idle(sdrv_uart_regs_t *base, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Waitting until auto baudrate detect completed or timeout.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_abr_ready(sdrv_uart_t *ctrl, uint32_t timeout);
|
|
|
|
/**
|
|
* brief Handle error interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_err_irq_handler(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Handle receive interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_rx_irq_handler(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Handle transmit interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_tx_irq_handler(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Handle auto baudrate detect interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_abr_irq_handler(sdrv_uart_t *ctrl);
|
|
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
/**
|
|
* brief Handle rx idle interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_rx_idle_irq_handler(sdrv_uart_t *ctrl);
|
|
|
|
/**
|
|
* brief Control uart rx dma interface.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] enable Enable or disable uart rx dma.
|
|
* param[in] timeout Timeout value.
|
|
*/
|
|
static bool sdrv_uart_dma_rx_ctrl(sdrv_uart_t *ctrl, bool enable,
|
|
uint32_t timeout);
|
|
|
|
/**
|
|
* brief Control uart tx dma interface.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] enable Enable or disable uart tx dma.
|
|
* param[in] timeout Timeout value.
|
|
*/
|
|
static bool sdrv_uart_dma_tx_ctrl(sdrv_uart_t *ctrl, bool enable,
|
|
uint32_t timeout);
|
|
|
|
/**
|
|
* brief UART receive data with dma single mode.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [out] xfer_config the configuration of the dma channel
|
|
* param [in] channel_id the number of dma channel
|
|
* param [in] xfer_type the type of the dma transfer
|
|
* param [in] xfer_mode the mode of the dma transfer
|
|
* param [in] burst_len the port burst length
|
|
* param [in] data receive data buffer
|
|
* param [in] size the size of receive data
|
|
*/
|
|
static void sdrv_uart_dma_config_creat(sdrv_uart_t *ctrl, sdrv_dma_t *dma_ctrl,
|
|
sdrv_dma_channel_config_t *xfer_config,
|
|
sdrv_dma_channel_id_e channel_id,
|
|
sdrv_dma_xfer_type_e xfer_type,
|
|
sdrv_dma_xfer_mode_e xfer_mode,
|
|
uint32_t burst_len, uint8_t *data,
|
|
uint32_t size);
|
|
|
|
/**
|
|
* brief Handle uart rx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_rx_realtime_handler(uint32_t status, uint32_t param,
|
|
void *context);
|
|
/**
|
|
* brief UART receive data with dma single mode.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [out] data receive data
|
|
* param [in] size the size of receive data
|
|
* param [in] rx_cb the callback function of receive
|
|
* param [in] rx_userparam the param of callback function
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [in] dma_channel sdrv dma channel controller entity
|
|
* param [in] channel_id The number of dma channel
|
|
* return The result of uart dma receive function
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart rx dma interface timeout.
|
|
* Status_Success : Starting the uart to receive with dma success.
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_dma_receive_single(
|
|
sdrv_uart_t *ctrl, uint8_t *data, uint32_t size, uart_callback_t rx_cb,
|
|
void *rx_userparam, sdrv_dma_t *dma_ctrl, sdrv_dma_channel_t *dma_channel,
|
|
sdrv_dma_channel_id_e channel_id);
|
|
|
|
/**
|
|
* brief UART transmit data with dma single mode.
|
|
*
|
|
* This function transmit data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User's data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [out] data transmit data
|
|
* param [in] size the size of transmit data
|
|
* param [in] tx_cb the callback function of transmit
|
|
* param [in] tx_userparam the param of callback function
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [in] dma_channel sdrv dma channel controller entity
|
|
* param [in] channel_id The number of dma channel
|
|
* return The result of uart dma transmit function
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart tx dma interface timeout.
|
|
* Status_Success : Starting the uart to transmit with dma success.
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_dma_transmit_single(
|
|
sdrv_uart_t *ctrl, const uint8_t *data, uint32_t size,
|
|
uart_callback_t tx_cb, void *tx_userparam, sdrv_dma_t *dma_ctrl,
|
|
sdrv_dma_channel_t *dma_channel, sdrv_dma_channel_id_e channel_id);
|
|
|
|
/**
|
|
* brief Handle uart rx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_rx_handler(uint32_t status, uint32_t param,
|
|
void *context);
|
|
|
|
/**
|
|
* brief Handle uart tx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_tx_handler(uint32_t status, uint32_t param,
|
|
void *context);
|
|
|
|
#endif
|
|
/**************************Static Functions End******************************/
|
|
|
|
/**
|
|
* @brief Sdrv UART controller initialization.
|
|
*
|
|
* This function initializes:
|
|
* 1) The uart module;
|
|
* 2) The uart controller entity.
|
|
*
|
|
* This function attach irq handler and transfer callback function.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller.
|
|
* @param [in] cfg sdrv uart configurations.
|
|
* @param [in] callback sdrv uart transfer callback function.
|
|
* @param [in] userData sdrv uart transfer callback function param.
|
|
* @return The result of initilalizing uart.
|
|
*/
|
|
sdrv_uart_error_status_e
|
|
sdrv_uart_controller_init(sdrv_uart_t *ctrl, const sdrv_uart_config_t *cfg,
|
|
uart_callback_t callback, void *userData)
|
|
{
|
|
ASSERT(cfg != NULL);
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT((cfg->baud > 0U) || (1U == cfg->abr_en));
|
|
ASSERT(cfg->clk_freq > 0U);
|
|
ASSERT(cfg->base > 0U);
|
|
|
|
/* Initializes uart module. */
|
|
sdrv_uart_error_status_e ret = sdrv_uart_init(cfg);
|
|
if (Status_Success != ret) {
|
|
return ret;
|
|
}
|
|
|
|
/* Initializes the controller. */
|
|
(void)memset(ctrl, 0, sizeof(sdrv_uart_t));
|
|
|
|
ctrl->base = cfg->base;
|
|
ctrl->irq = cfg->irq;
|
|
ctrl->clk_freq = cfg->clk_freq;
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
ctrl->rx_idle = cfg->rx_idle;
|
|
#endif
|
|
/* Set abr and tx/rx status */
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
|
|
/* Set auto baudrate state as Transfer_RxAbrBusy if uart need detect
|
|
* baudrate. */
|
|
if (cfg->abr_en) {
|
|
ctrl->abr_count = 0U;
|
|
ctrl->abr_state = Transfer_RxAbrBusy;
|
|
} else {
|
|
ctrl->baud = cfg->baud;
|
|
ctrl->abr_state = Transfer_RxAbrReady;
|
|
}
|
|
/* Set transfer callback function and user param */
|
|
ctrl->callback = callback;
|
|
ctrl->userData = userData;
|
|
/* Enable uart irq and attach handler */
|
|
if (ctrl->irq > 0U) {
|
|
|
|
ssdk_printf(SSDK_NOTICE, "uart3 irq\r\n");
|
|
irq_attach(ctrl->irq, sdrv_uart_irq_handler, ctrl);
|
|
irq_enable(ctrl->irq);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Srdv UART Deinitializes.
|
|
*
|
|
* This function deinitializes:
|
|
* 1) The uart controller entity
|
|
* 2) The uart module;
|
|
*
|
|
* This function dettach irq handler and transfer callback function.
|
|
*
|
|
* @param [in] ctrl sdrv uart ctrl
|
|
* @return The result of deinitilalizing uart.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_deinit(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Make sure pre operation was complete */
|
|
sdrv_uart_wait_txio_idle(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
sdrv_uart_wait_rxio_idle(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
|
|
/* Disable uart module */
|
|
sdrv_uart_disable(uart_base);
|
|
|
|
/* Disable uart irq and dettach handler */
|
|
if (ctrl->irq > 0U) {
|
|
irq_disable(ctrl->irq);
|
|
irq_detach(ctrl->irq);
|
|
}
|
|
|
|
/* Deinitializes the controller. */
|
|
(void)memset(ctrl, 0, sizeof(sdrv_uart_t));
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Configure uart baud rate.
|
|
*
|
|
*This function configures the uart module baud rate.
|
|
*This function is used to update the uart module baud rate.
|
|
*after the uart module is initialized by the sdrv_uart_controller_init.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] baud baud
|
|
* @return The result of setting baudrate.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_set_baudrate(sdrv_uart_t *ctrl,
|
|
uint32_t baud)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
if (0U == baud) {
|
|
return Status_Invalid_Param;
|
|
}
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Disable auto baudrate detect. */
|
|
uart_base->PCR0.ABREN = 0U;
|
|
uart_base->INTEN0.ABRPASS = 0U;
|
|
uart_base->INTEN0.ABRFAIL = 0U;
|
|
/* Set baud in controller and configurate baudrate in register. */
|
|
ctrl->baud = baud;
|
|
ctrl->abr_state = Transfer_RxAbrReady;
|
|
uart_base->PCR1.BAUDRATE =
|
|
sdrv_uart_baudrate_roundoff(ctrl->clk_freq, baud);
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Start auto baudrate detect.
|
|
*
|
|
*This function start auto baudrate detect.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] num The character number that abr expect to recv and match
|
|
* @return The result of starting abr.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_abr_start(sdrv_uart_t *ctrl,
|
|
sdrv_abr_max_e num)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)ctrl->base;
|
|
|
|
ctrl->abr_count = 0U;
|
|
ctrl->abr_state = Transfer_RxAbrBusy;
|
|
|
|
if (!sdrv_uart_module_reset(uart_base, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
return Status_Timeout;
|
|
}
|
|
|
|
uart_base->PCR0.ABRCTL0 = UART_ABR_PATTERN;
|
|
uart_base->PCR0.ABRCTL1 = num;
|
|
uart_base->INTEN0.ABRPASS = 1U;
|
|
uart_base->INTEN0.ABRFAIL = 1U;
|
|
|
|
uart_base->PCR0.ABREN = 1U;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the data in rx fifo.
|
|
*
|
|
* This function is used to get data in rx fifo.
|
|
* If user use sdrv_uart_start_realtime_receive function, this function is
|
|
* used in user's callback function to get rx fifo data.
|
|
* Users could call sdrv_uart_get_rxfifodata() to clear fifo.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] data the first address of user data buffer
|
|
* @param [in] maxlen the max length of user's data buffer
|
|
* @return the count of received byte
|
|
*/
|
|
uint32_t sdrv_uart_get_rxfifodata(sdrv_uart_t *ctrl, uint8_t *data,
|
|
uint32_t maxlen)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)ctrl->base;
|
|
/* Get the length of data in RX FIFO. */
|
|
uint32_t size = sdrv_uart_get_rxfifolen(uart_base);
|
|
/* Read data from RX FIFO.*/
|
|
size = (size <= maxlen) ? size : maxlen;
|
|
for (uint32_t i = 0U; i < size; ++i) {
|
|
sdrv_uart_getc(uart_base, &data[i], SDRV_UART_OPERATION_TIMEOUT);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
/**
|
|
* @brief Synchronous UART receive.
|
|
*
|
|
* This function receive RX data with a blocking method.
|
|
* This function will wait until data received successfully when times set
|
|
* as WaitForever.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [out] data receive data
|
|
* @param [in] size the size of receive data
|
|
* @param [in] received_bytes the size of data has been received
|
|
* @param [in] times the max times of query fifo empty register
|
|
* @return the result of transfer.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_sync_receive(sdrv_uart_t *ctrl,
|
|
uint8_t *data, uint32_t size,
|
|
uint32_t *received_bytes,
|
|
uint32_t times)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_uart_error_status_e ret = Status_Success;
|
|
uint32_t index = 0U;
|
|
|
|
if (Transfer_RxIdle != ctrl->rx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
ctrl->rx_state = Transfer_RxBusy;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_SYNC_MODE;
|
|
|
|
if (NULL != received_bytes)
|
|
*received_bytes = 0U;
|
|
/* Read data from RX FIFO. */
|
|
for (index = 0U; index < size; index++) {
|
|
/* Wait for receiving data until timeout. */
|
|
if ((!sdrv_uart_wait_abr_ready(ctrl, times)) ||
|
|
(!sdrv_uart_getc(uart_base, &data[index], times))) {
|
|
if (Transfer_RxAbrReady != ctrl->abr_state) {
|
|
ret = Status_Abr_Not_Ready;
|
|
break;
|
|
} else {
|
|
ret = Status_Timeout;
|
|
break;
|
|
}
|
|
}
|
|
if (NULL != received_bytes)
|
|
++(*received_bytes);
|
|
|
|
/* Transmission occurs error. */
|
|
if (SDRV_UART_INTR_RX_ERROR & sdrv_uart_intr_status_get(ctrl)) {
|
|
/* Check error type. */
|
|
if (SDRV_UART_INTR_RX_FOVF & sdrv_uart_intr_status_get(ctrl)) {
|
|
if ((index + 1U) != size) {
|
|
ret = Status_Rxfovf;
|
|
break;
|
|
}
|
|
}
|
|
if (SDRV_UART_INTR_PARITYERR &
|
|
sdrv_uart_intr_status_get(ctrl)) {
|
|
ret = Status_Parity_Err;
|
|
break;
|
|
}
|
|
#if (CONFIG_E3 || CONFIG_D3)
|
|
if (SDRV_UART_INTR_BAUDRATEERR &
|
|
sdrv_uart_intr_status_get(ctrl)) {
|
|
ret = Status_Baudrate_Err;
|
|
break;
|
|
}
|
|
#endif
|
|
#if CONFIG_E3L
|
|
if (IS_P0) {
|
|
if (SDRV_UART_INTR_BAUDRATEERR &
|
|
sdrv_uart_intr_status_get(ctrl)) {
|
|
ret = Status_Baudrate_Err;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
if (SDRV_UART_INTR_NOISERERR &
|
|
sdrv_uart_intr_status_get(ctrl)) {
|
|
ret = Status_Noise_Err;
|
|
break;
|
|
}
|
|
|
|
if (SDRV_UART_INTR_FRAMEERR & sdrv_uart_intr_status_get(ctrl)) {
|
|
ret = Status_Frame_Err;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Status_Success != ret) {
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
}
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Get empty status of tx fifo.
|
|
*
|
|
* This function is used to get empty status of tx fifo.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return the empty status of tx fifo
|
|
*/
|
|
bool sdrv_uart_txfifo_empty(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)ctrl->base;
|
|
|
|
return uart_base->FSR0.EMPTY > 0U;
|
|
}
|
|
|
|
/**
|
|
* @brief Synchronous UART transmit.
|
|
*
|
|
* This function transmit TX data with a blocking method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] data transmit data
|
|
* @param [in] size the size of transmit data
|
|
* @param [in] transmitted_bytes the size of data has been tansmitted
|
|
* @param [in] times the max times of query fifo full register
|
|
* @return the result of transfer
|
|
*/
|
|
sdrv_uart_error_status_e
|
|
sdrv_uart_sync_transmit(sdrv_uart_t *ctrl, const uint8_t *data, uint32_t size,
|
|
uint32_t *transmitted_bytes, uint32_t times)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
if (Transfer_TxIdle != ctrl->tx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
ctrl->tx_state = Transfer_TxBusy;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_SYNC_MODE;
|
|
|
|
if (NULL != transmitted_bytes)
|
|
*transmitted_bytes = 0U;
|
|
/* Wait for transmitting data untill timeout. */
|
|
for (uint32_t index = 0U; index < size; index++) {
|
|
if (!sdrv_uart_putc(uart_base, data[index], times)) {
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
return Status_Timeout;
|
|
}
|
|
if (NULL != transmitted_bytes)
|
|
++(*transmitted_bytes);
|
|
}
|
|
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Start UART realtime receive.
|
|
*
|
|
* This function start the feature of continuous receive RX data with a
|
|
* interrupt method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return the result of starting recv
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_start_realtime_receive(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
if (Transfer_RxIdle != ctrl->rx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
/* Update rx status and type. */
|
|
ctrl->rx_state = Transfer_RxBusy;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_REALTIME_MODE;
|
|
/* Clear RX Fifo */
|
|
if ((!sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT))) {
|
|
/* Update rx status and type. */
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_Timeout;
|
|
}
|
|
/* Enable rx related interrupt and clear interrupt status. */
|
|
sdrv_uart_rx_intrstatus_clear(ctrl);
|
|
sdrv_uart_rx_intr_ctrl(ctrl, true);
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Stop UART realtime receive.
|
|
*
|
|
* This function stop the feature of continuous receive RX data with a
|
|
* interrupt method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return The result of stopping realtime receive.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_stop_realtime_receive(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Clear RX Fifo */
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
|
|
/* Disable rx related interrupt. */
|
|
sdrv_uart_rx_intr_ctrl(ctrl, false);
|
|
sdrv_uart_rx_intrstatus_clear(ctrl);
|
|
/* Update rx status and type. */
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Asynchronous UART receive.
|
|
*
|
|
* This function receive RX data with an interrupt method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [out] data receive data
|
|
* @param [in] size the size of receive data
|
|
* @param [in] rx_cb the callback function of receive
|
|
* @param [in] rx_userparam the param of callback function
|
|
* @return the result of uart async receive function
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_async_receive(sdrv_uart_t *ctrl,
|
|
uint8_t *data, uint32_t size,
|
|
uart_callback_t rx_cb,
|
|
void *rx_userparam)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
|
|
if (Transfer_RxIdle != ctrl->rx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
/* Update rx status and type. */
|
|
ctrl->rx_state = Transfer_RxBusy;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_ASYNC_MODE;
|
|
/* Update rx frame information. */
|
|
ctrl->rx_ptr = data;
|
|
ctrl->rx_remain = size;
|
|
/* Update rx callback function. */
|
|
ctrl->rx_async_cb = rx_cb;
|
|
ctrl->rx_userparam = rx_userparam;
|
|
|
|
/* Enable rx related interrupt and clear interrupt status. */
|
|
sdrv_uart_rx_intr_ctrl(ctrl, true);
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Asynchronous UART receive abort.
|
|
*
|
|
* This function abort the transfer of receive RX data with an interrupt
|
|
* method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_async_receive_abort(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Clear RX Fifo */
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
/* Disable rx related interrupt. */
|
|
sdrv_uart_rx_intr_ctrl(ctrl, false);
|
|
sdrv_uart_rx_intrstatus_clear(ctrl);
|
|
/* Update rx status and type. */
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Asynchronous UART transmit.
|
|
*
|
|
* This function transmit TX data with an interrupt method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] data transmit data
|
|
* @param [in] size the size of transmit data
|
|
* @param [in] tx_cb the callback function of transmit
|
|
* @param [in] tx_userparam the param of callback function
|
|
* @return the result of uart async transmit function
|
|
*/
|
|
sdrv_uart_error_status_e
|
|
sdrv_uart_async_transmit(sdrv_uart_t *ctrl, const uint8_t *data, uint32_t size,
|
|
uart_callback_t tx_cb, void *tx_userparam)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
if (Transfer_TxIdle != ctrl->tx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
/* Update tx status and type. */
|
|
ctrl->tx_state = Transfer_TxBusy;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_ASYNC_MODE;
|
|
/* Update tx frame information. */
|
|
ctrl->tx_ptr = data;
|
|
ctrl->tx_remain = size;
|
|
/* Update tx callback function. */
|
|
ctrl->tx_async_cb = tx_cb;
|
|
ctrl->tx_userparam = tx_userparam;
|
|
/* Get transmitted bytes. */
|
|
uint32_t transmitted = sdrv_uart_send_async(uart_base, data, size);
|
|
if (transmitted > 0U) {
|
|
ctrl->tx_ptr += transmitted;
|
|
ctrl->tx_remain -= transmitted;
|
|
}
|
|
/* Enable tx related interrupt and clear interrupt status. */
|
|
sdrv_uart_tx_intr_ctrl(ctrl, true);
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Asynchronous UART transmit abort.
|
|
*
|
|
* This function abort the transfer of transmit TX data with an interrupt
|
|
* method.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return The result of aborting transmit.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_async_transmit_abort(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Clear tx fifo */
|
|
sdrv_uart_txfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
|
|
/* Disable tx related interrupt. */
|
|
sdrv_uart_tx_intr_ctrl(ctrl, false);
|
|
sdrv_uart_tx_intrstatus_clear(ctrl);
|
|
/* Update tx status and type. */
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
/**
|
|
* @brief UART receive data with dma.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
* This function can receive the fixed length data.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [out] data receive data
|
|
* @param [in] size the size of receive data
|
|
* @param [in] rx_cb the callback function of receive
|
|
* @param [in] rx_userparam the param of callback function
|
|
* @param [in] dma_ctrl sdrv dma controller entity
|
|
* @param [in] dma_channel sdrv dma channel controller entity
|
|
* @param [in] channel_id The number of dma channel
|
|
* @return The result of uart dma receive function
|
|
* Status_Busy : The uart receiver is busy.
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart rx dma interface timeout.
|
|
* Status_Success : Starting the uart to receive with dma success.
|
|
*/
|
|
sdrv_uart_error_status_e
|
|
sdrv_uart_dma_receive(sdrv_uart_t *ctrl, uint8_t *data, uint32_t size,
|
|
uart_callback_t rx_cb, void *rx_userparam,
|
|
sdrv_dma_t *dma_ctrl, sdrv_dma_channel_t *dma_channel,
|
|
sdrv_dma_channel_id_e channel_id)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
ASSERT(dma_ctrl != NULL);
|
|
ASSERT(dma_channel != NULL);
|
|
ASSERT(0 == (((uint32_t)data)) % CONFIG_ARCH_CACHE_LINE);
|
|
|
|
if (size > NUM_LINKLIST_ITEMS * DMA_BURST16_MAD_SIZE_MAX) {
|
|
return Status_Invalid_Param;
|
|
}
|
|
|
|
uint8_t *data_ptr = data;
|
|
uint32_t data_size = size;
|
|
uint32_t index = 0;
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_dma_channel_config_t xfer_config;
|
|
|
|
if (Transfer_RxIdle != ctrl->rx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
ctrl->rx_state = Transfer_RxBusy;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_DMA_ASYNC_MODE;
|
|
|
|
memset(&ctrl->rx_dma_linklist[0U], 0, sizeof(ctrl->rx_dma_linklist));
|
|
if (size >= CONFIG_ARCH_CACHE_LINE) {
|
|
/* Get the configuration of the dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_DEV2MEM,
|
|
SDRV_DMA_TRANSFER_MODE_LINKLIST, 16U, data, size);
|
|
|
|
/* Initialize receive linklist. */
|
|
while ((data_size / DMA_BURST16_MAD_SIZE_MAX) > 0U) {
|
|
/* Decrease size. */
|
|
data_size -= DMA_BURST16_MAD_SIZE_MAX;
|
|
/* set destination address */
|
|
xfer_config.dst_addr = (paddr_t)data_ptr;
|
|
/* Increase data pointer. */
|
|
data_ptr += DMA_BURST16_MAD_SIZE_MAX;
|
|
/* Set the next mad's linklist address. */
|
|
xfer_config.linklist_addr =
|
|
(paddr_t)&ctrl
|
|
->rx_dma_linklist[(index + 1) % NUM_LINKLIST_ITEMS];
|
|
/* Set transfer bytes */
|
|
xfer_config.xfer_bytes = DMA_BURST16_MAD_SIZE_MAX;
|
|
/* Set the mad's type. */
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_NORMAL_MAD;
|
|
if (0U == index) {
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_FIRST_MAD;
|
|
}
|
|
if (0U == data_size) {
|
|
xfer_config.linklist_addr = 0U;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
}
|
|
/* Initialize the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->rx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config);
|
|
/* Initialize dma channel. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
++index;
|
|
}
|
|
if (data_size > 0U) {
|
|
/* set destination address */
|
|
xfer_config.dst_addr = (paddr_t)data_ptr;
|
|
xfer_config.linklist_addr = 0U;
|
|
/* Set transfer bytes, should aligned with
|
|
* CONFIG_ARCH_CACHE_LINE.
|
|
*/
|
|
xfer_config.xfer_bytes =
|
|
data_size - (data_size % CONFIG_ARCH_CACHE_LINE);
|
|
/* Decrease size. */
|
|
data_size -= xfer_config.xfer_bytes;
|
|
/* Increase data pointer. */
|
|
data_ptr += xfer_config.xfer_bytes;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
/* Initialize the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->rx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config); /* init linklst */
|
|
/* Initialize dma channel. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Must invalidate rx linklist and dst_data cache */
|
|
arch_clean_cache_range((uint32_t)&ctrl->rx_dma_linklist[0U],
|
|
sizeof(ctrl->rx_dma_linklist));
|
|
arch_invalidate_cache_range((addr_t)data, size);
|
|
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 15U;
|
|
ctrl->rx_ptr = data_ptr;
|
|
ctrl->rx_remain = data_size;
|
|
ctrl->rx_async_cb = rx_cb;
|
|
|
|
} else {
|
|
/* Get configuration of the rx dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_DEV2MEM,
|
|
SDRV_DMA_TRANSFER_MODE_SINGLE, 1U, data, size);
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
/* Must invalidate dst_data cache */
|
|
arch_invalidate_cache_range((addr_t)data, size);
|
|
/* Increase data buffer pointer. */
|
|
data += size;
|
|
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 0U;
|
|
ctrl->rx_ptr = data;
|
|
ctrl->rx_remain = 0U;
|
|
ctrl->rx_async_cb = rx_cb;
|
|
}
|
|
/* Set interrupt callback */
|
|
dma_channel->irq_callback = sdrv_uart_dma_rx_handler;
|
|
dma_channel->irq_context = (void *)ctrl;
|
|
|
|
/* Update uart tranfer params. */
|
|
ctrl->dma_instance = dma_ctrl;
|
|
ctrl->rx_dmachannel = dma_channel;
|
|
ctrl->rx_userparam = rx_userparam;
|
|
ctrl->bytes_rxcarried = 0U;
|
|
|
|
/* Start dma channel. */
|
|
sdrv_dma_clear_channel_xfer_bytes(dma_channel);
|
|
sdrv_dma_start_channel_xfer(dma_channel);
|
|
|
|
/* Enable rx dma interface. */
|
|
if (!sdrv_uart_dma_rx_ctrl(ctrl, true, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_Timeout;
|
|
}
|
|
return Status_Success;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Abort the process of uart to receive data with dma.
|
|
*
|
|
* This function stop the dma channel and disable uart rx dma interface and
|
|
* clear tranfer status.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return The result of aborting receive.
|
|
* Status_Success : Abort the transfer success.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_dma_receive_abort(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(ctrl->rx_dmachannel != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Clear RX Fifo */
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
/* Disable rx dma interface. */
|
|
sdrv_uart_dma_rx_ctrl(ctrl, false, SDRV_UART_OPERATION_TIMEOUT);
|
|
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 0U;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
|
|
/* Disable rx dma channel. */
|
|
sdrv_dma_stop_channel_xfer(ctrl->rx_dmachannel);
|
|
/* Clear dma transfer byte register. */
|
|
sdrv_dma_clear_channel_xfer_bytes(ctrl->rx_dmachannel);
|
|
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief UART transmit data with dma.
|
|
*
|
|
* This function transmit data with dma linklist mode.
|
|
* User should initializes dma module before use this function.
|
|
* User's data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
* This function can receive the indefinite length data.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [out] data transmit data
|
|
* @param [in] size the size of transmit data
|
|
* @param [in] tx_cb the callback function of transmit
|
|
* @param [in] tx_userparam the param of callback function
|
|
* @param [in] dma_ctrl sdrv dma controller entity
|
|
* @param [in] dma_channel sdrv dma channel controller entity
|
|
* @param [in] channel_id The number of dma channel
|
|
* @return The result of uart dma transmit function
|
|
* Status_Busy : The uart transmitter is busy.
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart tx dma interface timeout.
|
|
* Status_Success : Starting the uart to transmit with dma success.
|
|
*/
|
|
sdrv_uart_error_status_e
|
|
sdrv_uart_dma_transmit(sdrv_uart_t *ctrl, const uint8_t *data, uint32_t size,
|
|
uart_callback_t tx_cb, void *tx_userparam,
|
|
sdrv_dma_t *dma_ctrl, sdrv_dma_channel_t *dma_channel,
|
|
sdrv_dma_channel_id_e channel_id)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
ASSERT(dma_ctrl != NULL);
|
|
ASSERT(dma_channel != NULL);
|
|
ASSERT(0 == (((uint32_t)data)) % CONFIG_ARCH_CACHE_LINE);
|
|
|
|
uint8_t *data_ptr = (uint8_t *)data;
|
|
uint32_t data_size = size;
|
|
uint32_t index = 0;
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_dma_channel_config_t xfer_config;
|
|
|
|
if (Transfer_TxIdle != ctrl->tx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
ctrl->tx_state = Transfer_TxBusy;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_DMA_ASYNC_MODE;
|
|
|
|
memset(&ctrl->tx_dma_linklist[0U], 0, sizeof(ctrl->tx_dma_linklist));
|
|
if (size >= CONFIG_ARCH_CACHE_LINE) {
|
|
/* Get configuration of the tx dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_MEM2DEV,
|
|
SDRV_DMA_TRANSFER_MODE_LINKLIST, 16U, data_ptr, size);
|
|
|
|
/* Initialize transmit linklist. */
|
|
while (((data_size / DMA_BURST16_MAD_SIZE_MAX) > 0U)) {
|
|
/* Decrease size. */
|
|
data_size -= DMA_BURST16_MAD_SIZE_MAX;
|
|
/* set source address */
|
|
xfer_config.src_addr = (paddr_t)data_ptr;
|
|
/* Increase data pointer. */
|
|
data_ptr += DMA_BURST16_MAD_SIZE_MAX;
|
|
/* Set the next mad's linklist address. */
|
|
xfer_config.linklist_addr =
|
|
(paddr_t)&ctrl
|
|
->tx_dma_linklist[(index + 1) % NUM_LINKLIST_ITEMS];
|
|
/* Set transfer bytes */
|
|
xfer_config.xfer_bytes = DMA_BURST16_MAD_SIZE_MAX;
|
|
/* Set linklist mad type. */
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_NORMAL_MAD;
|
|
if (0U == index) {
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_FIRST_MAD;
|
|
}
|
|
if (0U == data_size) {
|
|
xfer_config.linklist_addr = 0U;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
}
|
|
/* Configurate the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->tx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config); /* init linklst */
|
|
/* Initialize channal. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
++index;
|
|
}
|
|
if (data_size > 0U) {
|
|
/* Set source address */
|
|
xfer_config.src_addr = (paddr_t)data_ptr;
|
|
xfer_config.linklist_addr = 0U;
|
|
/* Set transfer bytes, should aligned with
|
|
* CONFIG_ARCH_CACHE_LINE.
|
|
*/
|
|
xfer_config.xfer_bytes =
|
|
data_size - (data_size % CONFIG_ARCH_CACHE_LINE);
|
|
/* Decrease size. */
|
|
data_size -= xfer_config.xfer_bytes;
|
|
/* Increase data pointer. */
|
|
data_ptr += xfer_config.xfer_bytes;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
/* Configurate the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->tx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config);
|
|
/* Initialize channal. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Must clean linklist and dst_data cache */
|
|
arch_clean_cache_range((uint32_t)&ctrl->tx_dma_linklist[0U],
|
|
sizeof(ctrl->tx_dma_linklist));
|
|
arch_clean_cache_range((addr_t)data, size);
|
|
|
|
/* Configurate Tx water level. */
|
|
uart_base->FCR0.WMLVL = 15U;
|
|
ctrl->tx_ptr = data_ptr;
|
|
ctrl->tx_remain = data_size;
|
|
} else {
|
|
/* Get configuration of the tx dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_MEM2DEV,
|
|
SDRV_DMA_TRANSFER_MODE_SINGLE, 1U, (uint8_t *)data, size);
|
|
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
|
|
/* Must clean dst_data cache */
|
|
arch_clean_cache_range((addr_t)data, size);
|
|
/* Increase data buffer pointer. */
|
|
data += size;
|
|
|
|
/* Configurate tx water level. */
|
|
uart_base->FCR0.WMLVL = 0U;
|
|
ctrl->tx_ptr = data;
|
|
ctrl->tx_remain = 0U;
|
|
}
|
|
/* Set interrupt callback */
|
|
dma_channel->irq_callback = sdrv_uart_dma_tx_handler;
|
|
dma_channel->irq_context = (void *)ctrl;
|
|
|
|
/* Update uart transfer params. */
|
|
ctrl->dma_instance = dma_ctrl;
|
|
ctrl->tx_dmachannel = dma_channel;
|
|
ctrl->tx_async_cb = tx_cb;
|
|
ctrl->tx_userparam = tx_userparam;
|
|
|
|
/* Start the channel. */
|
|
sdrv_dma_clear_channel_xfer_bytes(dma_channel);
|
|
sdrv_dma_start_channel_xfer(dma_channel);
|
|
|
|
/* Enable rx dma interface. */
|
|
if (!sdrv_uart_dma_tx_ctrl(ctrl, true, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_Timeout;
|
|
}
|
|
return Status_Success;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Abort the process of uart to transmit data with dma.
|
|
*
|
|
* This function stop the dma channel and disable uart tx dma interface and
|
|
* clear transfer status.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return The result of aborting transmit.
|
|
* Status_Timeout : Reset uart tx dma interface or clear tx fifo timeout
|
|
* Status_Success : Abort the transfer success.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_dma_transmit_abort(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(ctrl->tx_dmachannel != NULL);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* Clear TX Fifo */
|
|
sdrv_uart_txfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
/* Disable tx dma interface. */
|
|
sdrv_uart_dma_tx_ctrl(ctrl, false, SDRV_UART_OPERATION_TIMEOUT);
|
|
|
|
/* Configurate tx water level. */
|
|
uart_base->FCR0.WMLVL = 0U;
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
|
|
/* Disable tx dma channel. */
|
|
sdrv_dma_stop_channel_xfer(ctrl->tx_dmachannel);
|
|
sdrv_dma_clear_channel_xfer_bytes(ctrl->tx_dmachannel);
|
|
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief UART receive data with dma.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
* The size of the user's buffer should be larger than the size of the data
|
|
* that excepted received.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [out] data receive data
|
|
* @param [in] size the max size of data buffer
|
|
* @param [in] rx_cb the callback function of receive
|
|
* @param [in] rx_userparam the param of callback function
|
|
* @param [in] dma_ctrl sdrv dma controller entity
|
|
* @param [in] dma_channel sdrv dma channel controller entity
|
|
* @param [in] channel_id The number of dma channel
|
|
* @return The result of uart dma receive function
|
|
* Status_Busy : The uart receiver is busy.
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart rx dma interface timeout.
|
|
* Status_Success : Starting the uart to receive with dma success.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_dma_receive_start(
|
|
sdrv_uart_t *ctrl, uint8_t *data, uint32_t size, uart_callback_t rx_cb,
|
|
void *rx_userparam, sdrv_dma_t *dma_ctrl, sdrv_dma_channel_t *dma_channel,
|
|
sdrv_dma_channel_id_e channel_id)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
ASSERT(dma_ctrl != NULL);
|
|
ASSERT(dma_channel != NULL);
|
|
ASSERT(0 == (((uint32_t)data)) % CONFIG_ARCH_CACHE_LINE);
|
|
|
|
if (size > NUM_LINKLIST_ITEMS * DMA_BURST1_MAD_SIZE_MAX) {
|
|
return Status_Invalid_Param;
|
|
}
|
|
|
|
uint8_t *data_ptr = data;
|
|
uint32_t data_size = size;
|
|
uint32_t index = 0;
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_dma_channel_config_t xfer_config;
|
|
|
|
if (Transfer_RxIdle != ctrl->rx_state) {
|
|
return Status_Busy;
|
|
} else {
|
|
ctrl->rx_state = Transfer_RxBusy;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_DMA_REALTIME_MODE;
|
|
|
|
memset(&ctrl->rx_dma_linklist[0U], 0, sizeof(ctrl->rx_dma_linklist));
|
|
/* Get configuration of the rx dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_DEV2MEM,
|
|
SDRV_DMA_TRANSFER_MODE_LINKLIST, 1U, data, size);
|
|
|
|
/* Initialize receive linklist. */
|
|
while ((data_size / DMA_BURST1_MAD_SIZE_MAX) > 0U) {
|
|
/* Decrease size. */
|
|
data_size -= DMA_BURST1_MAD_SIZE_MAX;
|
|
/* set destination address */
|
|
xfer_config.dst_addr = (paddr_t)data_ptr;
|
|
/* Increase data pointer. */
|
|
data_ptr += DMA_BURST1_MAD_SIZE_MAX;
|
|
/* Set the next mad's linklist address. */
|
|
xfer_config.linklist_addr =
|
|
(paddr_t)&ctrl
|
|
->rx_dma_linklist[(index + 1) % NUM_LINKLIST_ITEMS];
|
|
/* Set transfer bytes */
|
|
xfer_config.xfer_bytes = DMA_BURST1_MAD_SIZE_MAX;
|
|
/* Set the mad's type. */
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_NORMAL_MAD;
|
|
if (0U == index) {
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_FIRST_MAD;
|
|
}
|
|
if (0U == data_size) {
|
|
xfer_config.linklist_addr = 0U;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
}
|
|
/* Initialize the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->rx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config);
|
|
/* Initialize dma channel. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
++index;
|
|
}
|
|
if (data_size > 0U) {
|
|
/* set destination address */
|
|
xfer_config.dst_addr = (paddr_t)data_ptr;
|
|
xfer_config.linklist_addr = 0U;
|
|
/* Set transfer bytes, should aligned with
|
|
* CONFIG_ARCH_CACHE_LINE.
|
|
*/
|
|
xfer_config.xfer_bytes = data_size;
|
|
/* Decrease size. */
|
|
data_size = 0U;
|
|
/* Increase data pointer. */
|
|
data_ptr += xfer_config.xfer_bytes;
|
|
xfer_config.linklist_mad_type = SDRV_DMA_LINKLIST_LAST_MAD;
|
|
/* Initialize the linklist of this mad. */
|
|
sdrv_dma_init_linklist_entry(
|
|
&ctrl->rx_dma_linklist[index % NUM_LINKLIST_ITEMS],
|
|
&xfer_config); /* init linklst */
|
|
/* Initialize dma channel. */
|
|
if (0U == index) {
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK !=
|
|
sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Must invalidate rx linklist and dst_data cache */
|
|
arch_clean_cache_range((uint32_t)&ctrl->rx_dma_linklist[0U],
|
|
sizeof(ctrl->rx_dma_linklist));
|
|
arch_invalidate_cache_range((addr_t)data, size);
|
|
|
|
/* Set interrupt callback */
|
|
dma_channel->irq_callback = sdrv_uart_dma_rx_realtime_handler;
|
|
dma_channel->irq_context = (void *)ctrl;
|
|
|
|
/* Update uart tranfer params. */
|
|
ctrl->dma_instance = dma_ctrl;
|
|
ctrl->rx_dmachannel = dma_channel;
|
|
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 0U;
|
|
ctrl->rx_ptr = data;
|
|
ctrl->rx_remain = size;
|
|
ctrl->rx_async_cb = rx_cb;
|
|
ctrl->rx_userparam = rx_userparam;
|
|
ctrl->bytes_rxcarried = 0U;
|
|
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
/* Enable rx dma interface. */
|
|
if (!sdrv_uart_dma_rx_ctrl(ctrl, true, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
return Status_Timeout;
|
|
}
|
|
|
|
sdrv_dma_clear_channel_xfer_bytes(dma_channel);
|
|
sdrv_dma_start_channel_xfer(dma_channel);
|
|
}
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the count of data carried by dma.
|
|
*
|
|
* This function only for dma mode.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return the count of received byte
|
|
*/
|
|
uint32_t sdrv_uart_dma_bytes_received(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
/* The number of the data carried by dma. */
|
|
return ctrl->bytes_rxcarried;
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
* @brief Enable/Disable Sdrv UART Interrupt.
|
|
*
|
|
* This function enable/disable sdrv uart interrupt with the provided mask.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] mask the interrupts to enable
|
|
* @param [in] value enable or disable
|
|
* @return The result of setting interrupt register.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_intr_ctrl(sdrv_uart_t *ctrl, uint32_t mask,
|
|
bool value)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t intr_ctrl = uart_base->INTEN0.v;
|
|
intr_ctrl = value ? (intr_ctrl | mask) : (intr_ctrl & (~mask));
|
|
|
|
uart_base->INTEN0.v = intr_ctrl;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Get Sdrv UART Interrupt enable/disable status.
|
|
*
|
|
* This function get sdrv uart interrupt enable/disable status with the
|
|
* provided mask.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return Sdrv UART Interrupt enable/disable status
|
|
*/
|
|
uint32_t sdrv_uart_intr_get(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
return uart_base->INTEN0.v;
|
|
}
|
|
|
|
/**
|
|
* @brief Get Sdrv UART Interrupt flag status.
|
|
*
|
|
* This function get Sdrv UART Interrupt flag status.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @return all sdrv UART Interrupt status
|
|
*/
|
|
uint32_t sdrv_uart_intr_status_get(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
return uart_base->INTR0.v;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear Sdrv UART Interrupt flag status.
|
|
*
|
|
* This function clear Sdrv UART Interrupt flag status with the provided
|
|
* mask.
|
|
*
|
|
* @param [in] ctrl sdrv uart controller
|
|
* @param [in] mask the interrupts status to clear
|
|
* @return The result of clearing interrupt status.
|
|
*/
|
|
sdrv_uart_error_status_e sdrv_uart_intr_status_clear(sdrv_uart_t *ctrl,
|
|
uint32_t mask)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uart_base->INTR0.v = mask;
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* @brief Sdrv UART default IRQ handle function.
|
|
*
|
|
* This function handles the sdrv uart transmit and receive
|
|
* and error IRQ request.
|
|
*
|
|
* @param [in] irq the irq number of uartx
|
|
* @param [in] ctrl sdrv uart controller
|
|
*/
|
|
int sdrv_uart_irq_handler(uint32_t irq, void *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
sdrv_uart_t *irq_ctrl = (sdrv_uart_t *)ctrl;
|
|
ASSERT(irq_ctrl->base > 0U);
|
|
|
|
/* Handle error interrupt during transfer. */
|
|
if ((SDRV_UART_INTR_RX_ERROR | SDRV_UART_INTR_TX_ERROR) &
|
|
sdrv_uart_intr_get(irq_ctrl)) {
|
|
if ((SDRV_UART_INTR_RX_ERROR | SDRV_UART_INTR_TX_ERROR) &
|
|
sdrv_uart_intr_status_get(irq_ctrl)) {
|
|
sdrv_uart_err_irq_handler(irq_ctrl);
|
|
}
|
|
}
|
|
|
|
/* Handle receive interrupt. */
|
|
if ((Transfer_RxAbrReady == irq_ctrl->abr_state) &&
|
|
(Transfer_RxBusy == irq_ctrl->rx_state)) {
|
|
if (SDRV_UART_INTR_RX_FWF & sdrv_uart_intr_get(irq_ctrl)) {
|
|
if (SDRV_UART_INTR_RX_FWF & sdrv_uart_intr_status_get(irq_ctrl)) {
|
|
sdrv_uart_rx_irq_handler(irq_ctrl);
|
|
}
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
/* Handle rx idle interrupt. */
|
|
if ((Transfer_RxAbrReady == irq_ctrl->abr_state) &&
|
|
(Transfer_RxBusy == irq_ctrl->rx_state)) {
|
|
if (SDRV_UART_INTR_RXIDLE & sdrv_uart_intr_get(irq_ctrl)) {
|
|
if (SDRV_UART_INTR_RXIDLE & sdrv_uart_intr_status_get(irq_ctrl)) {
|
|
sdrv_uart_rx_idle_irq_handler(irq_ctrl);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/* Handle transmit interrupt. */
|
|
if ((Transfer_TxBusy == irq_ctrl->tx_state)) {
|
|
if (SDRV_UART_INTR_TX_COMPLETED & sdrv_uart_intr_get(irq_ctrl)) {
|
|
if (SDRV_UART_INTR_TX_COMPLETED &
|
|
sdrv_uart_intr_status_get(irq_ctrl)) {
|
|
sdrv_uart_tx_irq_handler(irq_ctrl);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Handle auto baudrate detect interrupt. */
|
|
if (SDRV_UART_INTR_ABR & sdrv_uart_intr_get(irq_ctrl)) {
|
|
if (SDRV_UART_INTR_ABR & sdrv_uart_intr_status_get(irq_ctrl)) {
|
|
sdrv_uart_abr_irq_handler(irq_ctrl);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************Static Functions Start******************************/
|
|
/**
|
|
* brief Disable uart module.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static inline void sdrv_uart_disable(sdrv_uart_regs_t *base)
|
|
{
|
|
base->PCR0.TXEN = 0U;
|
|
base->PCR0.RXEN = 0U;
|
|
base->MCR0.MODEN = 0U;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART set flow control mode.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* param [in] fcm_cfg The configurations of fcm
|
|
*/
|
|
static void sdrv_uart_set_fcm(sdrv_uart_regs_t *base,
|
|
sdrv_uart_fcm_config_t *fcm_cfg)
|
|
{
|
|
ASSERT(fcm_cfg != NULL);
|
|
|
|
base->PCR0.FCM = fcm_cfg->fcm_type;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART Initialization.
|
|
*
|
|
* This function brief initializes sdrv uart module with user-defined
|
|
* settings
|
|
*
|
|
* param [in] cfg sdrv uart config
|
|
* return The result of initializing uart module
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_init(const sdrv_uart_config_t *cfg)
|
|
{
|
|
ASSERT(cfg != NULL);
|
|
ASSERT(cfg->base > 0U);
|
|
ASSERT((cfg->baud > 0U) || (1U == cfg->abr_en));
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(cfg->base);
|
|
|
|
/* Initializes sdrv uart module */
|
|
/* Disable uart module */
|
|
sdrv_uart_disable(uart_base);
|
|
|
|
/* Configurate uart as serial mode and full duplex. */
|
|
uart_base->MCR0.OPMOD = SDRV_UART_SERIAL_MODE;
|
|
uart_base->PCR0.TRANSFERMODE = SDRV_UART_FULL_DUPLEX;
|
|
|
|
/* Configurate sdrv uart flow control mode */
|
|
sdrv_uart_set_fcm(uart_base, (sdrv_uart_fcm_config_t *)&cfg->fcm);
|
|
|
|
/* Configurate uart data frame. */
|
|
uart_base->PCR0.DATABIT = cfg->data_bits;
|
|
uart_base->PCR0.STOPBIT = cfg->stop_bits;
|
|
uart_base->PCR0.PARITYBIT = cfg->parity;
|
|
|
|
/* Configurate uart fifo. */
|
|
uart_base->FCR0.WMLVL = cfg->txwmlvl;
|
|
uart_base->FCR1.WMLVL = cfg->rxwmlvl;
|
|
if ((!sdrv_uart_txfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT)) ||
|
|
(!sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT))) {
|
|
return Status_Timeout;
|
|
}
|
|
|
|
/* Initializes uart interrupt. */
|
|
sdrv_uart_intr_init(uart_base);
|
|
sdrv_uart_intr_status_init(uart_base);
|
|
|
|
/* Configurate uart dma interface. */
|
|
if (cfg->dma_en) {
|
|
if ((!sdrv_uart_txdma_reset(uart_base, SDRV_UART_OPERATION_TIMEOUT)) ||
|
|
(!sdrv_uart_rxdma_reset(uart_base, SDRV_UART_OPERATION_TIMEOUT))) {
|
|
return Status_Timeout;
|
|
}
|
|
uart_base->DMACR.TXDMAE = 1U;
|
|
uart_base->DMACR.RXDMAE = 1U;
|
|
} else {
|
|
uart_base->DMACR.TXDMAE = 0U;
|
|
uart_base->DMACR.RXDMAE = 0U;
|
|
}
|
|
|
|
/* Configurate filter. */
|
|
uart_base->PCR8.RXFILTCTL = 3U;
|
|
uart_base->PCR8.RXSYNCEN = 1U;
|
|
|
|
/* Reset uart module. */
|
|
if (!sdrv_uart_module_reset(uart_base, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
return Status_Timeout;
|
|
}
|
|
/* Enable TX line. */
|
|
uart_base->PCR0.TXEN = 1U;
|
|
/* Enable RX line. */
|
|
uart_base->PCR0.RXEN = 1U;
|
|
/* Enable uart module. */
|
|
uart_base->MCR0.MODEN = 1U;
|
|
|
|
/* Configurate auto baudrate detect. */
|
|
if (1U == cfg->abr_en) {
|
|
uart_base->PCR0.ABRCTL0 = UART_ABR_PATTERN;
|
|
uart_base->PCR0.ABRCTL1 = cfg->match_num;
|
|
uart_base->PCR1.BAUDRATE = 0U;
|
|
|
|
uart_base->INTEN0.ABRPASS = 1U;
|
|
uart_base->INTEN0.ABRFAIL = 1U;
|
|
|
|
uart_base->PCR0.ABREN = 1U;
|
|
} else {
|
|
uart_base->INTEN0.ABRPASS = 0U;
|
|
uart_base->INTEN0.ABRFAIL = 0U;
|
|
|
|
uart_base->PCR0.ABREN = 0U;
|
|
uart_base->PCR1.BAUDRATE =
|
|
sdrv_uart_baudrate_roundoff(cfg->clk_freq, cfg->baud);
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART initializes interrupt register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt to disable.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static void sdrv_uart_intr_init(sdrv_uart_regs_t *base) { base->INTEN0.v = 0; }
|
|
|
|
/**
|
|
* brief Srdv UART initializes interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
*/
|
|
static void sdrv_uart_intr_status_init(sdrv_uart_regs_t *base)
|
|
{
|
|
base->INTR0.v = 0xFFFFFFFFU;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART initializes rx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_rx_intr_ctrl(sdrv_uart_t *ctrl, bool enable)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t intr_ctrl = uart_base->INTEN0.v;
|
|
uint32_t mask = SDRV_UART_INTR_RX_ERROR;
|
|
|
|
#if CONFIG_E3L
|
|
if (IS_P1) {
|
|
mask = mask & (~SDRV_UART_INTR_BAUDRATEERR);
|
|
}
|
|
#endif
|
|
if ((SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) ||
|
|
(SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type)) {
|
|
mask = mask | SDRV_UART_INTR_RX_FWF;
|
|
}
|
|
|
|
intr_ctrl = enable ? (intr_ctrl | mask) : (intr_ctrl & (~mask));
|
|
uart_base->INTEN0.v = intr_ctrl;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART initializes tx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_tx_intr_ctrl(sdrv_uart_t *ctrl, bool enable)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t intr_ctrl = uart_base->INTEN0.v;
|
|
|
|
uint32_t mask = SDRV_UART_INTR_TX_ERROR;
|
|
if ((SDRV_TRANSFER_REALTIME_MODE == ctrl->txtransfer_type) ||
|
|
(SDRV_TRANSFER_ASYNC_MODE == ctrl->txtransfer_type)) {
|
|
mask = mask | SDRV_UART_INTR_TX_COMPLETED;
|
|
}
|
|
|
|
intr_ctrl = enable ? (intr_ctrl | mask) : (intr_ctrl & (~mask));
|
|
uart_base->INTEN0.v = intr_ctrl;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART initializes rx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] value enable or disable
|
|
*/
|
|
static void sdrv_uart_rx_intrstatus_clear(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t mask = SDRV_UART_INTR_RX_ERROR;
|
|
#if CONFIG_E3L
|
|
if (IS_P1) {
|
|
mask = mask & (~SDRV_UART_INTR_BAUDRATEERR);
|
|
}
|
|
#endif
|
|
if ((SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) ||
|
|
(SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type)) {
|
|
mask = mask | SDRV_UART_INTR_RX_FWF;
|
|
}
|
|
|
|
uart_base->INTR0.v = mask;
|
|
}
|
|
|
|
/**
|
|
* brief Srdv UART initializes tx interrupt status register.
|
|
*
|
|
* This function initializes sdrv uart module interrupt status.
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
*/
|
|
static void sdrv_uart_tx_intrstatus_clear(sdrv_uart_t *ctrl)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t mask = SDRV_UART_INTR_TX_ERROR;
|
|
if ((SDRV_TRANSFER_REALTIME_MODE == ctrl->txtransfer_type) ||
|
|
(SDRV_TRANSFER_ASYNC_MODE == ctrl->txtransfer_type)) {
|
|
mask = mask | SDRV_UART_INTR_TX_COMPLETED;
|
|
}
|
|
|
|
uart_base->INTR0.v = mask;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart baudrate round-off.
|
|
*
|
|
* param [in] dividend The clock frequency.
|
|
* param [in] divisor The value of baud.
|
|
* return The result of the baudrate after rounded off.
|
|
*/
|
|
static uint32_t sdrv_uart_baudrate_roundoff(uint32_t dividend, uint32_t divisor)
|
|
{
|
|
uint32_t temp = dividend * 10U / divisor;
|
|
return ((temp % 10U) < 5U) ? (temp / 10U) : (temp / 10U + 1U);
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart get char from rx fifo.
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] c The character to be received
|
|
* param [in] timeout The max times of query fifo empty register
|
|
* return The result of getting a character from rx fifo
|
|
*/
|
|
static inline bool sdrv_uart_getc(sdrv_uart_regs_t *base, uint8_t *c,
|
|
uint32_t timeout)
|
|
{
|
|
/* Wait for receiving data until timeout. */
|
|
while (base->FSR1.EMPTY) {
|
|
if (WaitForever != timeout) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
}
|
|
/* Read one character from rx fifo. */
|
|
*c = base->RXDR;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart put char in tx fifo.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* param [in] c The character to be transmitted
|
|
* param [in] timeout The max times of query fifo full register
|
|
* return The result of writting a character from tx fifo
|
|
*/
|
|
static inline bool sdrv_uart_putc(sdrv_uart_regs_t *base, uint8_t c,
|
|
uint32_t timeout)
|
|
{
|
|
/* Wait for transmitting data until timeout. */
|
|
while (base->FSR0.FULL) {
|
|
if (WaitForever != timeout) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
|
|
--timeout;
|
|
}
|
|
}
|
|
/* Write one character to tx fifo. */
|
|
base->TXDR = c;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart async read data from rx fifo
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] data Data buff
|
|
* param [in] size The size of data expected
|
|
* return The count of received characters
|
|
*/
|
|
static inline uint32_t sdrv_uart_read_async(sdrv_uart_regs_t *base,
|
|
uint8_t *data, uint32_t size)
|
|
{
|
|
uint32_t received = 0U;
|
|
|
|
/* Keep reading when there's character in RBR or Rx FIFO. */
|
|
while ((received < size) && (1U != (base->FSR1.EMPTY))) {
|
|
*data++ = base->RXDR;
|
|
received++;
|
|
}
|
|
|
|
return received;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart async write data to tx fifo
|
|
*
|
|
* param [in] base Sdrv uart register base
|
|
* param [in] data Data buff
|
|
* param [in] size The size of data expected
|
|
* return The count of transmitted characters
|
|
*/
|
|
static inline uint32_t sdrv_uart_send_async(sdrv_uart_regs_t *base,
|
|
const uint8_t *data, uint32_t size)
|
|
{
|
|
uint32_t transmitted = 0U;
|
|
|
|
while ((1U != (base->FSR0.FULL)) && (transmitted < size)) {
|
|
/* Fill the FIFO from the buffer */
|
|
base->TXDR = *data++;
|
|
/* Increment the send count. */
|
|
transmitted++;
|
|
}
|
|
|
|
return transmitted;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart get the length of data in rx fifo.
|
|
*
|
|
* param [in] base sdrv uart register base
|
|
* return The length of data in rx fifo
|
|
*/
|
|
static inline uint32_t sdrv_uart_get_rxfifolen(sdrv_uart_regs_t *base)
|
|
{
|
|
return base->FSR1.FILLLVL;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart clear rx fifo.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of clearing rx fifo.
|
|
*/
|
|
static bool sdrv_uart_rxfifo_clear(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Clear RX Fifo */
|
|
base->FCR1.CLR = 1U;
|
|
while (base->FCR1.CLR) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart clear tx fifo.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of clearing tx fifo.
|
|
*/
|
|
static bool sdrv_uart_txfifo_clear(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Clear RX Fifo */
|
|
base->FCR0.CLR = 1U;
|
|
while (base->FCR0.CLR) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart module reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart module.
|
|
*/
|
|
static bool sdrv_uart_module_reset(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Clear RX Fifo */
|
|
base->MCR0.MODRST = 1U;
|
|
while (base->MCR0.MODRST) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart rx dma reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart dma rx.
|
|
*/
|
|
static bool sdrv_uart_rxdma_reset(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Reset dma rx. */
|
|
base->DMACR.RXDMARST = 1U;
|
|
while (base->DMACR.RXDMARST) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Sdrv uart tx dma reset.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of resetting uart dma tx.
|
|
*/
|
|
static bool sdrv_uart_txdma_reset(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Reset dma tx. */
|
|
base->DMACR.TXDMARST = 1U;
|
|
while (base->DMACR.TXDMARST) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Waitting until sdrv uart tx io state changing to idle.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_txio_idle(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Wait for tx io idle. */
|
|
while (base->PSR0.IOTX_STATE) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Waitting until sdrv uart rx io state changing to idle.
|
|
*
|
|
* param[in] base The address of uart's register.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_rxio_idle(sdrv_uart_regs_t *base, uint32_t timeout)
|
|
{
|
|
/* Wait for rx io idle. */
|
|
while (base->PSR0.IORX_STATE) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Waitting until auto baudrate detect completed or timeout.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] timeout The value of timeout.
|
|
* return The result of Waitting.
|
|
*/
|
|
static bool sdrv_uart_wait_abr_ready(sdrv_uart_t *ctrl, uint32_t timeout)
|
|
{
|
|
/* Wait for rx io idle. */
|
|
while (Transfer_RxAbrReady != ctrl->abr_state) {
|
|
if (WaitForever != timeout) {
|
|
if (0U == timeout) {
|
|
return false;
|
|
}
|
|
--timeout;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Handle error interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_err_irq_handler(sdrv_uart_t *ctrl)
|
|
{
|
|
/* Transmission occurs rx fifo overflow error. */
|
|
if ((SDRV_UART_INTR_RX_FOVF & sdrv_uart_intr_status_get(ctrl)) &&
|
|
(SDRV_UART_INTR_RX_FOVF & sdrv_uart_intr_get(ctrl))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_RxFifoOverFlow, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoOverFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoOverFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoOverFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs rx fifo underflow error. */
|
|
if ((SDRV_UART_INTR_RX_FUDF & sdrv_uart_intr_status_get(ctrl)) &&
|
|
((SDRV_UART_INTR_RX_FUDF & sdrv_uart_intr_get(ctrl)))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_RxFifoUnderFlow, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoUnderFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoUnderFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxFifoUnderFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs parity error. */
|
|
if ((SDRV_UART_INTR_PARITYERR & sdrv_uart_intr_status_get(ctrl)) &&
|
|
(SDRV_UART_INTR_PARITYERR & sdrv_uart_intr_get(ctrl))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_ParityError, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_ParityError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_ParityError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_ParityError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs baudrate error. */
|
|
if ((SDRV_UART_INTR_BAUDRATEERR & sdrv_uart_intr_status_get(ctrl)) &&
|
|
((SDRV_UART_INTR_BAUDRATEERR & sdrv_uart_intr_get(ctrl)))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_BaudrateError, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_BaudrateError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_BaudrateError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_BaudrateError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs noise error. */
|
|
if ((SDRV_UART_INTR_NOISERERR & sdrv_uart_intr_status_get(ctrl)) &&
|
|
(SDRV_UART_INTR_NOISERERR & sdrv_uart_intr_get(ctrl))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_NoiseError, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_NoiseError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_NoiseError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_NoiseError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs frame error. */
|
|
if ((SDRV_UART_INTR_FRAMEERR & sdrv_uart_intr_status_get(ctrl)) &&
|
|
(SDRV_UART_INTR_FRAMEERR & sdrv_uart_intr_get(ctrl))) {
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_FramingError, ctrl->userData);
|
|
}
|
|
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_FramingError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_FramingError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_FramingError,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_ERROR);
|
|
}
|
|
|
|
/* Transmission occurs tx fifo overflow error. */
|
|
if ((SDRV_UART_INTR_TX_FOVF & sdrv_uart_intr_status_get(ctrl)) &&
|
|
(SDRV_UART_INTR_TX_FOVF & sdrv_uart_intr_get(ctrl))) {
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->txtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_TxFifoOverFlow, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->txtransfer_type) {
|
|
sdrv_uart_async_transmit_abort(ctrl);
|
|
if (ctrl->tx_async_cb != NULL) {
|
|
ctrl->tx_async_cb(ctrl, SDRV_UART_TxFifoOverFlow,
|
|
ctrl->tx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
/* Abort this transfer. */
|
|
sdrv_uart_dma_transmit_abort(ctrl);
|
|
if (ctrl->tx_async_cb != NULL) {
|
|
ctrl->tx_async_cb(ctrl, SDRV_UART_TxFifoOverFlow,
|
|
ctrl->tx_userparam);
|
|
}
|
|
} else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_TxFifoOverFlow,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_TX_ERROR);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* brief Handle receive interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_rx_irq_handler(sdrv_uart_t *ctrl)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* UART receive data. */
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_RxFWF, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_remain > 0U) {
|
|
uint32_t transfer_size =
|
|
sdrv_uart_read_async(uart_base, ctrl->rx_ptr, ctrl->rx_remain);
|
|
ctrl->rx_ptr += transfer_size;
|
|
ctrl->rx_remain -= transfer_size;
|
|
}
|
|
if (ctrl->rx_remain == 0U) {
|
|
sdrv_uart_rx_intr_ctrl(ctrl, false);
|
|
ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->rx_state = Transfer_RxIdle;
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxCompleted,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (0U != ctrl->rx_idle) {
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RXIDLE);
|
|
/* Enable uart rx idle interrupt. */
|
|
uart_base->INTEN0.RXIDLE = 1U;
|
|
uart_base->PCR1.RXIDLECTL = ctrl->rx_idle & 0x07U;
|
|
/* Disable RX interrupt */
|
|
uart_base->INTEN0.RXFWF = 0U;
|
|
}
|
|
}
|
|
#endif
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_FWF);
|
|
}
|
|
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
/**
|
|
* brief Handle rx idle interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_rx_idle_irq_handler(sdrv_uart_t *ctrl)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* UART receive data. */
|
|
if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
/* Enable uart rx idle interrupt. */
|
|
uart_base->PCR1.RXIDLECTL = 0U;
|
|
uart_base->INTEN0.RXIDLE = 0U;
|
|
sdrv_dma_stop_channel_xfer(ctrl->rx_dmachannel);
|
|
ctrl->bytes_rxcarried =
|
|
sdrv_dma_get_channel_xfer_bytes(ctrl->rx_dmachannel);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_RxIdle, ctrl->rx_userparam);
|
|
}
|
|
ctrl->bytes_rxcarried = 0U;
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RX_FWF);
|
|
uart_base->INTEN0.RXFWF = true;
|
|
|
|
/* Must invalidate rx linklist and dst_data cache */
|
|
arch_invalidate_cache_range((addr_t)ctrl->rx_ptr, ctrl->rx_remain);
|
|
sdrv_dma_clear_channel_xfer_bytes(ctrl->rx_dmachannel);
|
|
sdrv_dma_start_channel_xfer(ctrl->rx_dmachannel);
|
|
}
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_RXIDLE);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* brief Handle transmit interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_tx_irq_handler(sdrv_uart_t *ctrl)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* UART transmit data. */
|
|
if (SDRV_TRANSFER_ASYNC_MODE == ctrl->txtransfer_type) {
|
|
if (ctrl->tx_remain > 0U) {
|
|
uint32_t transfer_size =
|
|
sdrv_uart_send_async(uart_base, ctrl->tx_ptr, ctrl->tx_remain);
|
|
ctrl->tx_ptr += transfer_size;
|
|
ctrl->tx_remain -= transfer_size;
|
|
}
|
|
if (ctrl->tx_remain == 0U) {
|
|
/* Disable TX interrupt */
|
|
uart_base->INTEN0.TC = 0U;
|
|
/* Update tx status. */
|
|
ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
ctrl->tx_state = Transfer_TxIdle;
|
|
|
|
if (ctrl->tx_async_cb != NULL) {
|
|
ctrl->tx_async_cb(ctrl, SDRV_UART_TxCompleted,
|
|
ctrl->tx_userparam);
|
|
}
|
|
}
|
|
}
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_TX_COMPLETED);
|
|
}
|
|
|
|
/**
|
|
* brief Handle auto baudrate detect interrupt during transfer.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_abr_irq_handler(sdrv_uart_t *ctrl)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
/* UART auto baudrate detect pass. */
|
|
if (SDRV_UART_INTR_ABRPASS & sdrv_uart_intr_status_get(ctrl)) {
|
|
/* Disable abr pass interrupt */
|
|
uart_base->INTEN0.ABRPASS = 0U;
|
|
uart_base->INTEN0.ABRFAIL = 0U;
|
|
|
|
if (0U == uart_base->PSR1.AUTOBAUDRATE) {
|
|
ctrl->abr_state = Transfer_RxAbrFail;
|
|
/* Stop auto baudrate detect */
|
|
uart_base->PCR0.ABREN = 0U;
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_stop_realtime_receive(ctrl);
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_AbrFail, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrFail,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if ((SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) ||
|
|
(SDRV_TRANSFER_DMA_REALTIME_MODE ==
|
|
ctrl->rxtransfer_type)) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrFail,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
} else {
|
|
sdrv_uart_rxfifo_clear(uart_base, SDRV_UART_OPERATION_TIMEOUT);
|
|
/* Get abr result and calculate baud */
|
|
ctrl->baud = sdrv_uart_baudrate_roundoff(
|
|
ctrl->clk_freq, uart_base->PSR1.AUTOBAUDRATE);
|
|
ctrl->abr_state = Transfer_RxAbrReady;
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_AbrPass, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrPass,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if ((SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) ||
|
|
(SDRV_TRANSFER_DMA_REALTIME_MODE ==
|
|
ctrl->rxtransfer_type)) {
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrPass,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_ABRPASS);
|
|
}
|
|
/* UART auto baudrate detect fail. */
|
|
if (SDRV_UART_INTR_ABRFAIL & sdrv_uart_intr_status_get(ctrl)) {
|
|
if (ctrl->abr_count < SDRV_UART_MAX_ABR_NUM) {
|
|
uart_base->PCR0.ABREN = 0U;
|
|
++ctrl->abr_count;
|
|
/* enable auto baudrate detect */
|
|
uart_base->PCR0.ABREN = 1U;
|
|
} else {
|
|
ctrl->abr_state = Transfer_RxAbrFail;
|
|
/* Disable abr pass interrupt */
|
|
uart_base->INTEN0.ABRPASS = 0U;
|
|
uart_base->INTEN0.ABRFAIL = 0U;
|
|
/* Stop auto baudrate detect */
|
|
uart_base->PCR0.ABREN = 0U;
|
|
|
|
if (SDRV_TRANSFER_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_stop_realtime_receive(ctrl);
|
|
if (ctrl->callback != NULL) {
|
|
ctrl->callback(ctrl, SDRV_UART_AbrFail, ctrl->userData);
|
|
}
|
|
} else if (SDRV_TRANSFER_ASYNC_MODE == ctrl->rxtransfer_type) {
|
|
sdrv_uart_async_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrFail,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
else if ((SDRV_TRANSFER_DMA_ASYNC_MODE == ctrl->rxtransfer_type) ||
|
|
(SDRV_TRANSFER_DMA_REALTIME_MODE ==
|
|
ctrl->rxtransfer_type)) {
|
|
sdrv_uart_dma_receive_abort(ctrl);
|
|
if (ctrl->rx_async_cb != NULL) {
|
|
ctrl->rx_async_cb(ctrl, SDRV_UART_AbrFail,
|
|
ctrl->rx_userparam);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
/* Clear uart interrupt status. */
|
|
sdrv_uart_intr_status_clear(ctrl, SDRV_UART_INTR_ABRFAIL);
|
|
}
|
|
}
|
|
|
|
#if CONFIG_UART_ENABLE_DMA
|
|
/**
|
|
* brief Control uart rx dma interface.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] enable Enable or disable uart rx dma.
|
|
* param[in] timeout Timeout value.
|
|
*/
|
|
static bool sdrv_uart_dma_rx_ctrl(sdrv_uart_t *ctrl, bool enable,
|
|
uint32_t timeout)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t value = enable ? 1U : 0U;
|
|
|
|
sdrv_uart_rx_intr_ctrl(ctrl, enable);
|
|
sdrv_uart_rx_intrstatus_clear(ctrl);
|
|
if (SDRV_TRANSFER_DMA_REALTIME_MODE == ctrl->rxtransfer_type) {
|
|
/* Disable uart rx idle interrupt. */
|
|
uart_base->PCR1.RXIDLECTL = 0U;
|
|
uart_base->INTEN0.RXIDLE = 0U;
|
|
uart_base->INTR0.RXIDLE = 1U;
|
|
/* Enable/Disable RX fifo underflow interrupt. */
|
|
uart_base->INTEN0.RXFWF = value;
|
|
}
|
|
|
|
/* Enable/Disable rx dma. */
|
|
uart_base->DMACR.RXDMAE = value;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief Control uart tx dma interface.
|
|
*
|
|
* param[in] ctrl The uart controller entity.
|
|
* param[in] enable Enable or disable uart tx dma.
|
|
* param[in] timeout Timeout value.
|
|
*/
|
|
static bool sdrv_uart_dma_tx_ctrl(sdrv_uart_t *ctrl, bool enable,
|
|
uint32_t timeout)
|
|
{
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
|
|
uint32_t value = enable ? 1U : 0U;
|
|
|
|
/* Enable/Disable TX fifo overflow interrupt. */
|
|
sdrv_uart_tx_intr_ctrl(ctrl, enable);
|
|
sdrv_uart_tx_intrstatus_clear(ctrl);
|
|
|
|
/* Enable/Disable tx dma. */
|
|
uart_base->DMACR.TXDMAE = value;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* brief UART receive data with dma single mode.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [out] xfer_config the configuration of the dma channel
|
|
* param [in] channel_id the number of dma channel
|
|
* param [in] xfer_type the type of the dma transfer
|
|
* param [in] xfer_mode the mode of the dma transfer
|
|
* param [in] burst_len the port burst length
|
|
* param [in] data receive data buffer
|
|
* param [in] size the size of receive data
|
|
*/
|
|
static void sdrv_uart_dma_config_creat(sdrv_uart_t *ctrl, sdrv_dma_t *dma_ctrl,
|
|
sdrv_dma_channel_config_t *xfer_config,
|
|
sdrv_dma_channel_id_e channel_id,
|
|
sdrv_dma_xfer_type_e xfer_type,
|
|
sdrv_dma_xfer_mode_e xfer_mode,
|
|
uint32_t burst_len, uint8_t *data,
|
|
uint32_t size)
|
|
{
|
|
/* Get default config. */
|
|
sdrv_dma_init_channel_config(xfer_config, dma_ctrl);
|
|
/* Modify dma config param */
|
|
xfer_config->channel_id = channel_id; /* select channel */
|
|
xfer_config->xfer_type = xfer_type; /* mem2mem or mem2dev or dev2mem */
|
|
xfer_config->xfer_mode = xfer_mode; /* single or continuous or
|
|
linklist*/
|
|
if (SDRV_DMA_DIR_DEV2MEM == xfer_type) {
|
|
xfer_config->src_inc =
|
|
SDRV_DMA_ADDR_NO_INC; /* source address increase or not */
|
|
xfer_config->dst_inc =
|
|
SDRV_DMA_ADDR_INC; /* destination address increase or not */
|
|
xfer_config->src_port_sel =
|
|
SDRV_DMA_PORT_AHB32; /* periph -> SDRV_DMA_PORT_AHB32 */
|
|
xfer_config->dst_port_sel =
|
|
SDRV_DMA_PORT_AXI64; /* memory -> SDRV_DMA_PORT_AXI64 */
|
|
xfer_config->src_addr =
|
|
ctrl->base + SDRV_UART_RX_FIFO_OFFSET; /* set source address
|
|
(uart_rx_fifo address)*/
|
|
xfer_config->dst_addr = (paddr_t)data;
|
|
} else if (SDRV_DMA_DIR_MEM2DEV == xfer_type) {
|
|
xfer_config->src_inc =
|
|
SDRV_DMA_ADDR_INC; /* source address increase or not */
|
|
xfer_config->dst_inc =
|
|
SDRV_DMA_ADDR_NO_INC; /* destination address increase or not */
|
|
xfer_config->src_port_sel =
|
|
SDRV_DMA_PORT_AXI64; /* periph -> SDRV_DMA_PORT_AXI64 */
|
|
xfer_config->dst_port_sel =
|
|
SDRV_DMA_PORT_AHB32; /* memory -> SDRV_DMA_PORT_AHB32 */
|
|
xfer_config->src_addr = (paddr_t)data;
|
|
xfer_config->dst_addr =
|
|
ctrl->base + SDRV_UART_TX_FIFO_OFFSET; /* set source address
|
|
(uart_tx_fifo address)*/
|
|
}
|
|
xfer_config->src_width =
|
|
SDRV_DMA_BUSWIDTH_1_BYTE; /* source address width */
|
|
xfer_config->dst_width =
|
|
SDRV_DMA_BUSWIDTH_1_BYTE; /* destination address width */
|
|
xfer_config->src_burst_len = burst_len; /* source burst_length (transfer
|
|
level), max value is 4096. */
|
|
xfer_config->dst_burst_len =
|
|
burst_len; /* destination burst_length, max value is 4096. */
|
|
xfer_config->loop_mode =
|
|
SDRV_DMA_LOOP_MODE_1; /* mem2mem(MODE_0) mem2dev/dev2mem(MODE_1) */
|
|
xfer_config->interrupt_type =
|
|
SDRV_DMA_LAST_MAD_DONE; /* set interrupt type */
|
|
xfer_config->trig_mode =
|
|
SDRV_DMA_TRIGGER_BY_HARDWARE; /* by hardware trig */
|
|
xfer_config->xfer_bytes = size;
|
|
}
|
|
|
|
/**
|
|
* brief UART receive data with dma.
|
|
*
|
|
* This function receive data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [out] data receive data
|
|
* param [in] size the size of receive data
|
|
* param [in] rx_cb the callback function of receive
|
|
* param [in] rx_userparam the param of callback function
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [in] dma_channel sdrv dma channel controller entity
|
|
* param [in] channel_id The number of dma channel
|
|
* return The result of uart dma receive function
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart rx dma interface timeout.
|
|
* Status_Success : Starting the uart to receive with dma success.
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_dma_receive_single(
|
|
sdrv_uart_t *ctrl, uint8_t *data, uint32_t size, uart_callback_t rx_cb,
|
|
void *rx_userparam, sdrv_dma_t *dma_ctrl, sdrv_dma_channel_t *dma_channel,
|
|
sdrv_dma_channel_id_e channel_id)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
ASSERT(0 == (((uint32_t)data)) % CONFIG_ARCH_CACHE_LINE);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_dma_channel_config_t xfer_config;
|
|
/* Get configuration of the rx dma channel. */
|
|
sdrv_uart_dma_config_creat(ctrl, dma_ctrl, &xfer_config, channel_id,
|
|
SDRV_DMA_DIR_DEV2MEM,
|
|
SDRV_DMA_TRANSFER_MODE_SINGLE, 1U, data, size);
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK != sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
/* Must invalidate dst_data cache */
|
|
arch_invalidate_cache_range((addr_t)data, size);
|
|
/* Increase data buffer pointer. */
|
|
data += size;
|
|
|
|
/* Set interrupt callback */
|
|
dma_channel->irq_callback = sdrv_uart_dma_rx_handler;
|
|
dma_channel->irq_context = (void *)ctrl;
|
|
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 0U;
|
|
/* Update uart tranfer params. */
|
|
ctrl->dma_instance = dma_ctrl;
|
|
ctrl->rx_dmachannel = dma_channel;
|
|
ctrl->rx_ptr = data;
|
|
ctrl->rx_remain = 0U;
|
|
ctrl->rx_async_cb = rx_cb;
|
|
ctrl->rx_userparam = rx_userparam;
|
|
|
|
sdrv_dma_start_channel_xfer(dma_channel);
|
|
|
|
/* Enable rx dma interface. */
|
|
if (!sdrv_uart_dma_rx_ctrl(ctrl, true, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
return Status_Timeout;
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* brief UART transmit data with dma.
|
|
*
|
|
* This function transmit data with dma module.
|
|
* User should initializes dma module before use this function.
|
|
* User's data buffer must be __aligned(CONFIG_ARCH_CACHE_LINE).
|
|
*
|
|
* param [in] ctrl sdrv uart controller
|
|
* param [out] data transmit data
|
|
* param [in] size the size of transmit data
|
|
* param [in] tx_cb the callback function of transmit
|
|
* param [in] tx_userparam the param of callback function
|
|
* param [in] dma_ctrl sdrv dma controller entity
|
|
* param [in] dma_channel sdrv dma channel controller entity
|
|
* param [in] channel_id The number of dma channel
|
|
* return The result of uart dma transmit function
|
|
* Status_dma_channel_config_Err : The dma channel config error.
|
|
* Status_Timeout : Reset uart tx dma interface timeout.
|
|
* Status_Success : Starting the uart to transmit with dma success.
|
|
*/
|
|
static sdrv_uart_error_status_e sdrv_uart_dma_transmit_single(
|
|
sdrv_uart_t *ctrl, const uint8_t *data, uint32_t size,
|
|
uart_callback_t tx_cb, void *tx_userparam, sdrv_dma_t *dma_ctrl,
|
|
sdrv_dma_channel_t *dma_channel, sdrv_dma_channel_id_e channel_id)
|
|
{
|
|
ASSERT(ctrl != NULL);
|
|
ASSERT(ctrl->base > 0U);
|
|
ASSERT(data != NULL);
|
|
ASSERT(0 == (((uint32_t)data)) % CONFIG_ARCH_CACHE_LINE);
|
|
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(ctrl->base);
|
|
sdrv_dma_channel_config_t xfer_config;
|
|
/* Get configuration of the tx dma channel. */
|
|
sdrv_uart_dma_config_creat(
|
|
ctrl, dma_ctrl, &xfer_config, channel_id, SDRV_DMA_DIR_MEM2DEV,
|
|
SDRV_DMA_TRANSFER_MODE_SINGLE, 1U, (uint8_t *)data, size);
|
|
|
|
/* Init channel config */
|
|
if (SDRV_STATUS_OK != sdrv_dma_init_channel(dma_channel, &xfer_config)) {
|
|
return Status_dma_channel_config_Err;
|
|
}
|
|
|
|
/* Must clean dst_data cache */
|
|
arch_clean_cache_range((addr_t)data, size);
|
|
/* Increase data buffer pointer. */
|
|
data += size;
|
|
|
|
/* Set interrupt callback */
|
|
dma_channel->irq_callback = sdrv_uart_dma_tx_handler;
|
|
dma_channel->irq_context = (void *)ctrl;
|
|
|
|
/* Configurate tx water level. */
|
|
uart_base->FCR0.WMLVL = 0U;
|
|
/* Update uart tranfer params. */
|
|
ctrl->dma_instance = dma_ctrl;
|
|
ctrl->tx_dmachannel = dma_channel;
|
|
ctrl->tx_ptr = data;
|
|
ctrl->tx_remain = 0U;
|
|
ctrl->tx_async_cb = tx_cb;
|
|
ctrl->tx_userparam = tx_userparam;
|
|
|
|
sdrv_dma_start_channel_xfer(dma_channel);
|
|
|
|
/* Enable rx dma interface. */
|
|
if (!sdrv_uart_dma_tx_ctrl(ctrl, true, SDRV_UART_OPERATION_TIMEOUT)) {
|
|
return Status_Timeout;
|
|
}
|
|
|
|
return Status_Success;
|
|
}
|
|
|
|
/**
|
|
* brief Handle uart rx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_rx_handler(uint32_t status, uint32_t param,
|
|
void *context)
|
|
{
|
|
sdrv_uart_t *uart_ctrl = (sdrv_uart_t *)context;
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(uart_ctrl->base);
|
|
|
|
if ((SDRV_DMA_ERR == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_ASYNC_MODE == uart_ctrl->rxtransfer_type)) {
|
|
/* Stop uart rx dma channel transfer */
|
|
sdrv_dma_stop_channel_xfer(uart_ctrl->rx_dmachannel);
|
|
uart_ctrl->bytes_rxcarried =
|
|
sdrv_dma_get_channel_xfer_bytes(uart_ctrl->rx_dmachannel);
|
|
sdrv_uart_dma_receive_abort(uart_ctrl);
|
|
if (uart_ctrl->rx_async_cb) {
|
|
uart_ctrl->rx_async_cb(uart_ctrl, SDRV_UART_RxDmaError,
|
|
uart_ctrl->rx_userparam);
|
|
}
|
|
}
|
|
if ((SDRV_DMA_COMPLETED == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_ASYNC_MODE == uart_ctrl->rxtransfer_type)) {
|
|
/* Stop uart rx dma channel transfer */
|
|
sdrv_dma_stop_channel_xfer(uart_ctrl->rx_dmachannel);
|
|
if (uart_ctrl->rx_remain > 0U) {
|
|
sdrv_uart_dma_receive_single(
|
|
uart_ctrl, uart_ctrl->rx_ptr, uart_ctrl->rx_remain,
|
|
uart_ctrl->rx_async_cb, uart_ctrl->rx_userparam,
|
|
uart_ctrl->dma_instance, uart_ctrl->rx_dmachannel,
|
|
uart_ctrl->rx_dmachannel->channel_id);
|
|
} else {
|
|
uart_ctrl->bytes_rxcarried =
|
|
sdrv_dma_get_channel_xfer_bytes(uart_ctrl->rx_dmachannel);
|
|
sdrv_dma_clear_channel_xfer_bytes(uart_ctrl->rx_dmachannel);
|
|
/* Disable uart rx dma interface. */
|
|
sdrv_uart_dma_rx_ctrl(uart_ctrl, false,
|
|
SDRV_UART_OPERATION_TIMEOUT);
|
|
uart_ctrl->rx_state = Transfer_RxIdle;
|
|
uart_ctrl->rxtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
/* Configurate rx water level. */
|
|
uart_base->FCR1.WMLVL = 0U;
|
|
if (uart_ctrl->rx_async_cb) {
|
|
uart_ctrl->rx_async_cb(uart_ctrl, SDRV_UART_RxDmaDone,
|
|
uart_ctrl->rx_userparam);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* brief Handle uart tx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_tx_handler(uint32_t status, uint32_t param,
|
|
void *context)
|
|
{
|
|
sdrv_uart_t *uart_ctrl = (sdrv_uart_t *)context;
|
|
sdrv_uart_regs_t *uart_base = (sdrv_uart_regs_t *)(uart_ctrl->base);
|
|
|
|
if ((SDRV_DMA_ERR == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_ASYNC_MODE == uart_ctrl->txtransfer_type)) {
|
|
sdrv_uart_dma_transmit_abort(uart_ctrl);
|
|
if (uart_ctrl->tx_async_cb) {
|
|
uart_ctrl->tx_async_cb(uart_ctrl, SDRV_UART_TxDmaError,
|
|
uart_ctrl->tx_userparam);
|
|
}
|
|
} else if ((SDRV_DMA_COMPLETED == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_ASYNC_MODE == uart_ctrl->txtransfer_type)) {
|
|
/* Stop uart tx dma channel transfer */
|
|
sdrv_dma_stop_channel_xfer(uart_ctrl->tx_dmachannel);
|
|
if (uart_ctrl->tx_remain > 0U) {
|
|
sdrv_uart_dma_transmit_single(
|
|
uart_ctrl, uart_ctrl->tx_ptr, uart_ctrl->tx_remain,
|
|
uart_ctrl->tx_async_cb, uart_ctrl->tx_userparam,
|
|
uart_ctrl->dma_instance, uart_ctrl->tx_dmachannel,
|
|
uart_ctrl->tx_dmachannel->channel_id);
|
|
} else {
|
|
/* Disable uart tx dma interface. */
|
|
sdrv_uart_dma_tx_ctrl(uart_ctrl, false,
|
|
SDRV_UART_OPERATION_TIMEOUT);
|
|
uart_ctrl->tx_state = Transfer_TxIdle;
|
|
uart_ctrl->txtransfer_type = SDRV_TRANSFER_NO_MODE;
|
|
/* Configurate Tx water level. */
|
|
uart_base->FCR0.WMLVL = 0U;
|
|
if (uart_ctrl->tx_async_cb) {
|
|
uart_ctrl->tx_async_cb(uart_ctrl, SDRV_UART_TxDmaDone,
|
|
uart_ctrl->tx_userparam);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* brief Handle uart rx dma interrupt during transfer.
|
|
*
|
|
* param[in] status Dma event status.
|
|
* param[in] param User param.
|
|
* param[in] context The uart controller entity.
|
|
*/
|
|
static void sdrv_uart_dma_rx_realtime_handler(uint32_t status, uint32_t param,
|
|
void *context)
|
|
{
|
|
sdrv_uart_t *uart_ctrl = (sdrv_uart_t *)context;
|
|
|
|
uart_ctrl->bytes_rxcarried =
|
|
sdrv_dma_get_channel_xfer_bytes(uart_ctrl->rx_dmachannel);
|
|
|
|
if ((SDRV_DMA_ERR == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_REALTIME_MODE == uart_ctrl->rxtransfer_type)) {
|
|
/* Abort uart rx dma channel transfer */
|
|
sdrv_uart_dma_receive_abort(uart_ctrl);
|
|
if (uart_ctrl->rx_async_cb) {
|
|
uart_ctrl->rx_async_cb(uart_ctrl, SDRV_UART_RxDmaError,
|
|
uart_ctrl->rx_userparam);
|
|
}
|
|
}
|
|
|
|
if ((SDRV_DMA_COMPLETED == (sdrv_dma_status_e)status) &&
|
|
(SDRV_TRANSFER_DMA_REALTIME_MODE == uart_ctrl->rxtransfer_type)) {
|
|
/* The user's buffer is full. */
|
|
if (uart_ctrl->rx_remain <= uart_ctrl->bytes_rxcarried) {
|
|
sdrv_uart_dma_receive_abort(uart_ctrl);
|
|
if (uart_ctrl->rx_async_cb) {
|
|
uart_ctrl->rx_async_cb(uart_ctrl, SDRV_UART_RxBufferFull,
|
|
uart_ctrl->rx_userparam);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
/*************************Static Functions End*****************************/
|