/** mbed Microcontroller Library ****************************************************************************** * @file serial_api.c * @author * @version V1.0.0 * @date 2016-08-01 * @brief This file provides mbed API for UART. ****************************************************************************** * @attention * * This module is a confidential and proprietary property of RealTek and * possession or use of this module requires written permission of RealTek. * * Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. ****************************************************************************** */ #include "objects.h" #include "serial_api.h" #include "serial_ex_api.h" #include "pinmap.h" #include typedef VOID (*UARTCB_FUN)(VOID *); typedef struct { int TxCount; // how many byte to TX int RxCount; // how many bytes to RX u8 *pTxBuf; u8 *pRxBuf; u8 UartIndex; GDMA_InitTypeDef UARTTxGdmaInitStruct; GDMA_InitTypeDef UARTRxGdmaInitStruct; UART_InitTypeDef UART_InitStruct; UART_TypeDef* UARTx; IRQn_Type IrqNum; /* for rx DMA timeout */ u32 last_dma_addr; VOID (*TxCompCallback)(VOID *para); // User Tx complete callback function VOID (*RxCompCallback)(VOID *para); // User Rx complete callback function VOID *TxCompCbPara; // the pointer argument for TxCompCbPara VOID *RxCompCbPara; // the pointer argument for RxCompCallback }MBED_UART_ADAPTER, *PMBED_UART_ADAPTER; #define UART_NUM (3) #define SERIAL_TX_IRQ_EN 0x01 #define SERIAL_RX_IRQ_EN 0x02 #define SERIAL_TX_DMA_EN 0x01 #define SERIAL_RX_DMA_EN 0x02 //#define UART_USE_GTIMER_TO 1 #define UART_TIMER_ID 1 #define UART_TIMER_TO 5000 static uint32_t serial_irq_ids[UART_NUM] = {0, 0, 0}; static uart_irq_handler irq_handler[UART_NUM]; static uint32_t serial_irq_en[UART_NUM]={0, 0, 0}; #ifdef CONFIG_GDMA_EN static uint32_t serial_dma_en[UART_NUM] = {0, 0, 0}; #endif MBED_UART_ADAPTER uart_adapter[MAX_UART_INDEX+1]; #ifdef CONFIG_MBED_ENABLED int stdio_uart_inited = 0; serial_t stdio_uart; #endif int uart1_inited = 0; int uart0_inited = 0; #ifdef UART_USE_GTIMER_TO static void uart_gtimer_deinit(void); #endif static const PinMap PinMap_UART_TX[] = { {PA_4, UART_0, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_23, UART_0, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_26, UART_1, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_17, UART_2, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_30, UART_2, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {NC, NC, 0} }; static const PinMap PinMap_UART_RX[] = { {PA_1, UART_0, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_18, UART_0, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_25, UART_1, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_16, UART_2, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {PA_29, UART_2, PIN_DATA(PullUp, PINMUX_FUNCTION_UART)}, {NC, NC, 0} }; static u32 uart_index_get(PinName tx) { if ((tx == _PA_4) || (tx == _PA_23)) { return 0; } else if (tx == _PA_26) { return 1; } else if ((tx == _PA_17) || (tx == _PA_30)) { return 2; } else { assert_param(0); } return 3; } static u32 uart_dmasend_complete( IN VOID *Data ) { PMBED_UART_ADAPTER puart_adapter = (PMBED_UART_ADAPTER) Data; PGDMA_InitTypeDef GDMA_InitStruct; u8 IsrTypeMap; puart_adapter->TxCount = 0; GDMA_InitStruct = &puart_adapter->UARTTxGdmaInitStruct; // Clean Auto Reload Bit GDMA_ChCleanAutoReload(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, CLEAN_RELOAD_DST); // Clear Pending ISR IsrTypeMap = GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); /*disable UART TX DMA*/ UART_TXDMACmd(puart_adapter->UARTx, DISABLE); GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); GDMA_ChnlFree(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); UART_SetTxFlag(puart_adapter->UartIndex, 0); // Call user TX complete callback if (NULL != puart_adapter->TxCompCallback) { puart_adapter->TxCompCallback(puart_adapter->TxCompCbPara); } return 0; } static u32 uart_dmarecv_complete( IN VOID *Data ) { PMBED_UART_ADAPTER puart_adapter = (PMBED_UART_ADAPTER) Data; PGDMA_InitTypeDef GDMA_InitStruct; u8 IsrTypeMap; u8 LineStatus; GDMA_InitStruct = &puart_adapter->UARTRxGdmaInitStruct; #ifdef UART_USE_GTIMER_TO RTIM_Cmd(TIMx[UART_TIMER_ID], DISABLE); uart_gtimer_deinit(); #endif // Clean Auto Reload Bit GDMA_ChCleanAutoReload(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, CLEAN_RELOAD_SRC); // Clear Pending ISR IsrTypeMap = GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); /*disable UART RX DMA*/ UART_RXDMACmd(puart_adapter->UARTx, DISABLE); GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); GDMA_ChnlFree(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); // Check the Line Status LineStatus = (u8)UART_LineStatusGet(puart_adapter->UARTx); UART_SetRxFlag(puart_adapter->UartIndex, 0); /* close time out */ UART_INTConfig(puart_adapter->UARTx, RUART_IER_ERBI | RUART_IER_ELSI |RUART_IER_ETOI, DISABLE); // Call User Rx complete callback if (puart_adapter->RxCompCallback != NULL) { puart_adapter->RxCompCallback (puart_adapter->RxCompCbPara); } return 0; } static u32 uart_dmarecv_irqhandler( IN VOID *Data ) { PMBED_UART_ADAPTER puart_adapter = (PMBED_UART_ADAPTER) Data; puart_adapter->RxCount = 0; uart_dmarecv_complete(puart_adapter); return 0; } static void uart_txdone_callback(VOID *pAdapter) { PMBED_UART_ADAPTER puart_adapter = pAdapter; u8 uart_idx = puart_adapter->UartIndex; // Mask UART TX FIFI empty UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, DISABLE); if (irq_handler[uart_idx] != NULL) { irq_handler[uart_idx](serial_irq_ids[uart_idx], TxIrq); } } static void uart_rxdone_callback(VOID *pAdapter) { PMBED_UART_ADAPTER puart_adapter = pAdapter; u8 uart_idx = puart_adapter->UartIndex; if (irq_handler[uart_idx] != NULL) { irq_handler[uart_idx](serial_irq_ids[uart_idx], RxIrq); } } static VOID uart_intrecv_complete( IN PMBED_UART_ADAPTER puart_adapter ) { volatile u8 LineStatus; // Disable RX Interrupt UART_INTConfig(puart_adapter->UARTx, (RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI), DISABLE); // Check the Line Status LineStatus = (u8)UART_LineStatusGet(puart_adapter->UARTx); UART_SetRxFlag(puart_adapter->UartIndex, 0); // Call User Rx complete callback if (puart_adapter->RxCompCallback != NULL) { puart_adapter->RxCompCallback (puart_adapter->RxCompCbPara); } } static VOID uart_intsend_complete( IN PMBED_UART_ADAPTER puart_adapter ) { // Disable Tx FIFO empty interrupt UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, DISABLE); UART_SetTxFlag(puart_adapter->UartIndex, 0); // Call user TX complete callback if (NULL != puart_adapter->TxCompCallback) { puart_adapter->TxCompCallback(puart_adapter->TxCompCbPara); } } static u32 uart_irqhandler( IN VOID *Data ) { volatile u8 reg_iir; u8 IntId; u32 RegValue; PMBED_UART_ADAPTER puart_adapter = (PMBED_UART_ADAPTER) Data; reg_iir = UART_IntStatus(puart_adapter->UARTx); if ((reg_iir & RUART_IIR_INT_PEND) != 0) { // No pending IRQ return 0; } IntId = (reg_iir & RUART_IIR_INT_ID) >> 1; switch (IntId) { case RUART_LP_RX_MONITOR_DONE: RegValue = UART_LPRxMonitorSatusGet(puart_adapter->UARTx); break; case RUART_MODEM_STATUS: RegValue = UART_ModemStatusGet(puart_adapter->UARTx); break; case RUART_RECEIVE_LINE_STATUS: RegValue = UART_LineStatusGet(puart_adapter->UARTx); break; case RUART_TX_FIFO_EMPTY: if (UART_GetTxFlag(puart_adapter->UartIndex)) { u32 TransCnt = UART_SendDataTO(puart_adapter->UARTx, puart_adapter->pTxBuf, puart_adapter->TxCount, 1); puart_adapter->TxCount -= TransCnt; puart_adapter->pTxBuf += TransCnt; if (0 == puart_adapter->TxCount) { uart_intsend_complete(puart_adapter); } } else { // Call Tx done callback uart_txdone_callback(puart_adapter); } break; case RUART_RECEIVER_DATA_AVAILABLE: case RUART_TIME_OUT_INDICATION: if (UART_GetRxFlag(puart_adapter->UartIndex) == STATERX_INT) { u32 TransCnt = 0; TransCnt = UART_ReceiveDataTO(puart_adapter->UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= TransCnt; puart_adapter->pRxBuf += TransCnt; if (puart_adapter->RxCount == 0) { uart_intrecv_complete(puart_adapter); } } else { // Call Rx data ready callback RegValue = (UART_LineStatusGet(puart_adapter->UARTx)); if (RegValue & RUART_LINE_STATUS_REG_DR) { uart_rxdone_callback(puart_adapter); } } break; default: DBG_PRINTF(MODULE_UART, LEVEL_ERROR, "Unknown Interrupt \n"); break; } return 0; } #ifdef UART_USE_GTIMER_TO static void uart_gtimer_handle( IN VOID *Data ) { PMBED_UART_ADAPTER puart_adapter = (PMBED_UART_ADAPTER) Data; PGDMA_InitTypeDef GDMA_InitStruct; u32 TransCnt = 0; GDMA_InitStruct = &puart_adapter->UARTRxGdmaInitStruct; RTIM_INTClear(TIMx[UART_TIMER_ID]); if (UART_GetRxFlag(puart_adapter->UartIndex) == STATERX_DMA) { u32 Current_Addr = GDMA_GetDstAddr(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); u32 data_in_fifo = UART_Readable(puart_adapter->UARTx); /* have Rx some data */ if ((Current_Addr != (u32)(puart_adapter->pRxBuf)) || data_in_fifo) { /* not increase for 5ms */ if (puart_adapter->last_dma_addr == Current_Addr) { /* rx stop 5ms, packet complete */ RTIM_Cmd(TIMx[UART_TIMER_ID], DISABLE); //DBG_8195A("%s:UART DMA TO Current_Addr:%x start_addr:%x RxCount: %d\n", // __func__, Current_Addr, puart_adapter->pRxBuf, puart_adapter->RxCount); puart_adapter->RxCount = puart_adapter->RxCount - (Current_Addr - (u32)puart_adapter->pRxBuf); puart_adapter->pRxBuf = (u8*)Current_Addr; TransCnt = UART_ReceiveDataTO(puart_adapter->UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= TransCnt; puart_adapter->pRxBuf += TransCnt; uart_dmarecv_complete(puart_adapter); GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); //DBG_8195A("UART DMA TO RxCount: %d\n", puart_adapter->RxCount); } else { puart_adapter->last_dma_addr = Current_Addr; } } else { /* rx not start */ puart_adapter->last_dma_addr = (u32)(puart_adapter->pRxBuf); } } } /** * @brief Initialize the timer used for the Uart Rx Dma time out. * @param puart_adapter: a PRUART_VERIFY_PARAMETER pointer. * @param Period: the desired timeout value (Unit: microsecond). * * @retval none */ static void uart_gtimer_init(PMBED_UART_ADAPTER puart_adapter, u32 PeriodUs) { RTIM_TimeBaseInitTypeDef TIM_InitStructTmp; RTIM_TimeBaseStructInit(&TIM_InitStructTmp); TIM_InitStructTmp.TIM_Idx = UART_TIMER_ID; TIM_InitStructTmp.TIM_Prescaler = 0x00; TIM_InitStructTmp.TIM_Period = (PeriodUs / 31 - 1); TIM_InitStructTmp.TIM_UpdateEvent = ENABLE; /* UEV enable */ TIM_InitStructTmp.TIM_UpdateSource = TIM_UpdateSource_Overflow; TIM_InitStructTmp.TIM_ARRProtection = DISABLE; RTIM_TimeBaseInit(TIMx[UART_TIMER_ID], &TIM_InitStructTmp, TIMx_irq[UART_TIMER_ID], (IRQ_FUN) uart_gtimer_handle, (u32)puart_adapter); RTIM_INTConfig(TIMx[UART_TIMER_ID], TIM_IT_Update, ENABLE); } static void uart_gtimer_deinit(void) { InterruptDis(TIMx_irq[UART_TIMER_ID]); InterruptUnRegister(TIMx_irq[UART_TIMER_ID]); RTIM_DeInit(TIMx[UART_TIMER_ID]); } #endif /** * @brief Initializes the UART device, include clock/function/interrupt/UART registers. * @param obj: uart object define in application software. * @param tx: Tx PinName according to pinmux spec. * @param rx: Rx PinName according to pinmux spec. * @retval none */ void serial_init(serial_t *obj, PinName tx, PinName rx) { uint8_t uart_idx = uart_index_get(tx); UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); UARTName UARTx = (UARTName)pinmap_merge(uart_tx, uart_rx); PMBED_UART_ADAPTER puart_adapter = NULL; assert_param(UARTx != (UARTName)NC); obj->uart_idx = uart_idx; puart_adapter = &(uart_adapter[obj->uart_idx]); puart_adapter->UartIndex = uart_idx; puart_adapter->UARTx = UART_DEV_TABLE[uart_idx].UARTx; puart_adapter->IrqNum = UART_DEV_TABLE[uart_idx].IrqNum; InterruptRegister((IRQ_FUN)uart_irqhandler, puart_adapter->IrqNum, (u32)puart_adapter, 10); InterruptEn(puart_adapter->IrqNum, 10); /*Enable Uart Ip Clock*/ switch (puart_adapter->UartIndex) { case 0: /* UART 0 */ RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, ENABLE); break; case 1: /* UART 1 */ RCC_PeriphClockCmd(APBPeriph_UART1, APBPeriph_UART1_CLOCK, ENABLE); break; default: break; } /* Configure the UART pins */ pinmap_pinout(tx, PinMap_UART_TX); pinmap_pinout(rx, PinMap_UART_RX); UART_StructInit(&puart_adapter->UART_InitStruct); UART_Init(puart_adapter->UARTx, &puart_adapter->UART_InitStruct); #ifdef CONFIG_MBED_ENABLED // For stdio management if (uart_idx == STDIO_UART) { stdio_uart_inited = 1; memcpy(&stdio_uart, obj, sizeof(serial_t)); } #endif if (uart_idx == 0) uart0_inited = 1; if (uart_idx == 1) uart1_inited = 1; } /** * @brief Deinitializes the UART device, include clock/function/interrupt/UART registers. * @param obj: uart object define in application software. * @retval none */ void serial_free(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter = &(uart_adapter[obj->uart_idx]); UART_DeInit(puart_adapter->UARTx); InterruptDis(puart_adapter->IrqNum); InterruptUnRegister(puart_adapter->IrqNum); #ifdef UART_USE_GTIMER_TO uart_gtimer_deinit(); #endif #ifdef CONFIG_GDMA_EN if (serial_dma_en[obj->uart_idx] & SERIAL_RX_DMA_EN) { GDMA_ChnlFree(puart_adapter->UARTRxGdmaInitStruct.GDMA_Index, puart_adapter->UARTRxGdmaInitStruct.GDMA_ChNum); serial_dma_en[obj->uart_idx] &= ~SERIAL_RX_DMA_EN; } if (serial_dma_en[obj->uart_idx] & SERIAL_TX_DMA_EN) { GDMA_ChnlFree(puart_adapter->UARTTxGdmaInitStruct.GDMA_Index, puart_adapter->UARTTxGdmaInitStruct.GDMA_ChNum); serial_dma_en[obj->uart_idx] &= ~SERIAL_TX_DMA_EN; } #endif if (obj->uart_idx == 0) uart0_inited = 0; if (obj->uart_idx == 1) uart1_inited = 0; // TODO: recovery Pin Mux } /** * @brief Set UART device baudrate. * @param obj: uart object define in application software. * @param baudrate: Baud Rate Val, like 115200 (unit is HZ). * @retval none */ void serial_baud(serial_t *obj, int baudrate) { PMBED_UART_ADAPTER puart_adapter = &(uart_adapter[obj->uart_idx]); UART_SetBaud(puart_adapter->UARTx, baudrate); UART_RxCmd(puart_adapter->UARTx, ENABLE); if (baudrate <= 500000) { if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE) { LPUART_InitTypeDef LPUART_InitStruct; UART_LPRxpathSet(puart_adapter->UARTx, ENABLE); UART_LPRxIPClockSet(puart_adapter->UARTx, UART_RX_CLK_OSC_8M); UART_LPRxStructInit(&LPUART_InitStruct); UART_LPRxInit(puart_adapter->UARTx, &LPUART_InitStruct); UART_LPRxMonitorCmd(puart_adapter->UARTx, ENABLE); UART_LPRxBaudSet(puart_adapter->UARTx, baudrate, OSC8M_CLOCK); UART_LPRxCmd(puart_adapter->UARTx, ENABLE); }else{ UART_LPRxpathSet(puart_adapter->UARTx, DISABLE); UART_LPRxIPClockSet(puart_adapter->UARTx, UART_RX_CLK_XTAL_40M); } } } /** * @brief Set UART format. * @param obj: uart object define in application software. * @param data_bits: data bits, this parameter can be one of the following values: * @arg 7 * @arg 8 * @param parity: this parameter can be one of the following values: * @arg ParityNone * @arg ParityOdd * @arg ParityEven * @arg ParityForced1: same action with ParityOdd * @arg ParityForced0: same action with ParityEven * @param stop_bits: this parameter can be one of the following values: * @arg 2 * @arg 1 * @retval none */ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { PMBED_UART_ADAPTER puart_adapter = &(uart_adapter[obj->uart_idx]); UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; UART_RxCmd(puart_adapter->UARTx, DISABLE); if (data_bits == 8) { puart_adapter->UART_InitStruct.WordLen = RUART_WLS_8BITS; } else { puart_adapter->UART_InitStruct.WordLen = RUART_WLS_7BITS; } switch (parity) { case ParityOdd: case ParityForced0: puart_adapter->UART_InitStruct.Parity = RUART_PARITY_ENABLE; puart_adapter->UART_InitStruct.ParityType = RUART_ODD_PARITY; break; case ParityEven: case ParityForced1: puart_adapter->UART_InitStruct.Parity = RUART_PARITY_ENABLE; puart_adapter->UART_InitStruct.ParityType = RUART_EVEN_PARITY; break; default: // ParityNone puart_adapter->UART_InitStruct.Parity = RUART_PARITY_DISABLE; break; } if (stop_bits == 2) { puart_adapter->UART_InitStruct.StopBit = RUART_STOP_BIT_2; } else { puart_adapter->UART_InitStruct.StopBit = RUART_STOP_BIT_1; } UARTx->LCR = ((puart_adapter->UART_InitStruct.WordLen) | (puart_adapter->UART_InitStruct.StopBit << 2) | (puart_adapter->UART_InitStruct.Parity << 3) | (puart_adapter->UART_InitStruct.ParityType << 4) | (puart_adapter->UART_InitStruct.StickParity << 5)); UART_RxCmd(puart_adapter->UARTx, ENABLE); } /** * @brief Set UART interrupt hander if needed. * @param obj: uart object define in application software. * @param handler: interrupt callback function * @param handler: interrupt callback parameter * @retval none */ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { PMBED_UART_ADAPTER puart_adapter; u8 uart_idx; puart_adapter = &(uart_adapter[obj->uart_idx]); uart_idx = puart_adapter->UartIndex; irq_handler[uart_idx] = handler; serial_irq_ids[uart_idx] = id; } /** * @brief Enable/Disable UART interrupt. * @param obj: uart object define in application software. * @param irq: Tx or Rx interrupt, this parameter can be one of the following values: * @arg RxIrq * @arg TxIrq * @param enable:, this parameter can be one of the following values: * @arg 0 disable * @arg 1 enable * @retval none */ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { PMBED_UART_ADAPTER puart_adapter; u8 uart_idx; puart_adapter = &(uart_adapter[obj->uart_idx]); uart_idx = puart_adapter->UartIndex; if (enable) { if (irq == RxIrq) { serial_irq_en[uart_idx] |= SERIAL_RX_IRQ_EN; UART_INTConfig(puart_adapter->UARTx, RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI, ENABLE); } else { serial_irq_en[uart_idx] |= SERIAL_TX_IRQ_EN; } } else { // disable if (irq == RxIrq) { serial_irq_en[uart_idx] &= ~SERIAL_RX_IRQ_EN; UART_INTConfig(puart_adapter->UARTx, (RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI), DISABLE); } else { serial_irq_en[uart_idx] &= ~SERIAL_TX_IRQ_EN; UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, DISABLE); } } } /** * @brief get one byte from UART. * @param obj: uart object define in application software. * @retval received data * @note this function is asynchronous API. */ int serial_getc(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); u8 RxByte = 0; while (!serial_readable(obj)); UART_CharGet(puart_adapter->UARTx, &RxByte); return (int)RxByte; } /** * @brief send one byte use UART. * @param obj: uart object define in application software. * @param c: the data to transmit. * @retval none * @note this function is asynchronous API. */ void serial_putc(serial_t *obj, int c) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); while (!serial_writable(obj)); UART_CharPut(puart_adapter->UARTx, (c & 0xFF)); if (serial_irq_en[obj->uart_idx] & SERIAL_TX_IRQ_EN) { // UnMask TX FIFO empty IRQ UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, ENABLE); } } /** * @brief check if there is data in rx fifo. * @param obj: uart object define in application software. * @retval status value: * - 1: TRUE * - 0: FALSE */ int serial_readable(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); if (UART_Readable(puart_adapter->UARTx)) { return 1; } else { return 0; } } /** * @brief check if write data to tx fifo is permitted. * @param obj: uart object define in application software. * @retval status value: * - 1: TRUE * - 0: FALSE */ int serial_writable(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); if (UART_Writable(puart_adapter->UARTx)) { return 1; } else { return 0; } } /** * @brief Clear Rx fifo. * @param obj: uart object define in application software. */ void serial_clear(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter; puart_adapter = &(uart_adapter[obj->uart_idx]); UART_ClearRxFifo(puart_adapter->UARTx); } /** * @brief set tx pinmux. * @param tx: Tx PinName according to pinmux spec. */ void serial_pinout_tx(PinName tx) { Pinmux_Config(tx, PINMUX_FUNCTION_UART); } /** * @brief enable UART break contol function. * @param obj: uart object define in application software. */ void serial_break_set(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); UART_BreakCtl(puart_adapter->UARTx, 1); } /** * @brief disable UART break contol function. * @param obj: uart object define in application software. */ void serial_break_clear(serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); UART_BreakCtl(puart_adapter->UARTx, 0); } /** * @brief set TX complete handler. * @param obj: uart object define in application software. * @param handler: TX complete callback function. * @param id: TX complete callback function parameter. * @retval none * @note this function is used when asynchronous API is used. */ void serial_send_comp_handler(serial_t *obj, void *handler, uint32_t id) { PMBED_UART_ADAPTER puart_adapter; puart_adapter = &(uart_adapter[obj->uart_idx]); puart_adapter->TxCompCallback = (UARTCB_FUN)handler; puart_adapter->TxCompCbPara = (void*)id; } /** * @brief set RX complete handler. * @param obj: uart object define in application software. * @param handler: RX complete callback function. * @param id: RX complete callback function parameter. * @retval none * @note this function is used when asynchronous API is used. */ void serial_recv_comp_handler(serial_t *obj, void *handler, uint32_t id) { PMBED_UART_ADAPTER puart_adapter; puart_adapter = &(uart_adapter[obj->uart_idx]); puart_adapter->RxCompCallback = (UARTCB_FUN)handler; puart_adapter->RxCompCbPara = (void*)id; } /** * @brief recv target length data use interrupt mode. * @param obj: uart object define in application software. * @param prxbuf: buffer to save data read from UART FIFO. * @param len: number of data to be read. * @retval HAL_Status * @note this function is asynchronous API. */ int32_t serial_recv_stream (serial_t *obj, char *prxbuf, uint32_t len) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); int ret = HAL_OK; u32 TransCnt = 0; assert_param(prxbuf != NULL); assert_param(len != 0); if (UART_GetRxFlag(puart_adapter->UartIndex)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart int rx: busy\n"); return HAL_BUSY; } obj->rx_len = len; puart_adapter->pRxBuf = (uint8_t*)prxbuf; puart_adapter->RxCount = len; UART_SetRxFlag(puart_adapter->UartIndex, STATERX_INT); // Could be the RX FIFO has some data already TransCnt = UART_ReceiveDataTO(puart_adapter->UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= TransCnt; puart_adapter->pRxBuf += TransCnt; if (puart_adapter->RxCount == 0) { uart_intrecv_complete(puart_adapter); } else { // Enable RX Interrupt UART_INTConfig(puart_adapter->UARTx, RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI, ENABLE); } return (ret); } /** * @brief send target length data use interrupt mode. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be send. * @retval HAL_Status * @note this function is asynchronous API. */ int32_t serial_send_stream (serial_t *obj, char *ptxbuf, uint32_t len) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); int ret = 0; u32 TransCnt = 0; assert_param(ptxbuf != NULL); assert_param(len != 0); if (UART_GetTxFlag(puart_adapter->UartIndex)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart int tx: busy\n"); return HAL_BUSY; } obj->tx_len = len; puart_adapter->pTxBuf = (uint8_t*)ptxbuf; puart_adapter->TxCount = len; UART_SetTxFlag(puart_adapter->UartIndex, STATETX_INT); TransCnt = UART_SendDataTO(puart_adapter->UARTx, puart_adapter->pTxBuf, puart_adapter->TxCount, 1); puart_adapter->TxCount -= TransCnt; puart_adapter->pTxBuf += TransCnt; if (0 == puart_adapter->TxCount) { uart_intsend_complete(puart_adapter); } else { // Enable Tx FIFO empty interrupt UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, ENABLE); } return (ret); } /** * @brief recv target length data use DMA mode. * @param obj: uart object define in application software. * @param prxbuf: buffer to save data read from UART FIFO. * @param len: number of data to be read. * @retval HAL_Status * @note this function is asynchronous API. */ int32_t serial_recv_stream_dma (serial_t *obj, char *prxbuf, uint32_t len) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); HAL_Status ret = HAL_OK; u32 ret1; if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE) { return serial_recv_stream (obj, prxbuf, len); } //ret = HalRuartRecv(puart_adapter, (u8*)prxbuf, len, DMA_BASED); assert_param(prxbuf != NULL); assert_param(len != 0); if (UART_GetRxFlag(puart_adapter->UartIndex)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart dma rx: busy\n"); return HAL_BUSY; } obj->rx_len = len; puart_adapter->pRxBuf = (uint8_t*)prxbuf; puart_adapter->RxCount = len; puart_adapter->last_dma_addr = (u32)prxbuf; UART_SetRxFlag(puart_adapter->UartIndex, STATERX_DMA); // Disable Rx interrupt UART_INTConfig(puart_adapter->UARTx, (RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI), DISABLE); UART_RXDMAConfig(puart_adapter->UARTx, 4); UART_RXDMACmd(puart_adapter->UARTx, ENABLE); ret1 = UART_RXGDMA_Init(puart_adapter->UartIndex, &puart_adapter->UARTRxGdmaInitStruct, puart_adapter, uart_dmarecv_irqhandler, puart_adapter->pRxBuf, puart_adapter->RxCount); NVIC_SetPriority(GDMA_IrqNum[0][puart_adapter->UARTRxGdmaInitStruct.GDMA_ChNum], 12); if ((serial_dma_en[obj->uart_idx] & SERIAL_RX_DMA_EN)==0) { if(ret1 == _TRUE) { serial_dma_en[obj->uart_idx] |= SERIAL_RX_DMA_EN; } else { return HAL_BUSY; } } #ifdef UART_USE_GTIMER_TO uart_gtimer_init(puart_adapter, UART_TIMER_TO); RTIM_Cmd(TIMx[UART_TIMER_ID], ENABLE); #endif return (ret); } /** * @brief send target length data use DMA mode. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be send. * @retval HAL_Status * @note this function is asynchronous API. */ int32_t serial_send_stream_dma (serial_t *obj, char *ptxbuf, uint32_t len) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); int32_t ret = HAL_OK; u32 ret1; if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE) { return serial_send_stream (obj, ptxbuf, len); } assert_param(ptxbuf != NULL); assert_param(len != 0); if (UART_GetTxFlag(puart_adapter->UartIndex)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart dma tx: busy\n"); return HAL_BUSY; } obj->tx_len = len; puart_adapter->pTxBuf = (uint8_t*)ptxbuf; puart_adapter->TxCount = len; UART_SetTxFlag(puart_adapter->UartIndex, STATETX_DMA); UART_TXDMAConfig(puart_adapter->UARTx, 8); UART_TXDMACmd(puart_adapter->UARTx, ENABLE); ret1 = UART_TXGDMA_Init(puart_adapter->UartIndex, &puart_adapter->UARTTxGdmaInitStruct, puart_adapter, uart_dmasend_complete, puart_adapter->pTxBuf, puart_adapter->TxCount); NVIC_SetPriority(GDMA_IrqNum[0][puart_adapter->UARTTxGdmaInitStruct.GDMA_ChNum], 12); if ((serial_dma_en[obj->uart_idx] & SERIAL_TX_DMA_EN)==0) { if(ret1 == _TRUE) { serial_dma_en[obj->uart_idx] |= SERIAL_TX_DMA_EN; } else { return HAL_BUSY; } } return (ret); } /** * @brief stop the sream or steam_dma RX. * @param obj: uart object define in application software. */ int32_t serial_send_stream_abort (serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); int ret = 0; if (!UART_GetTxFlag(puart_adapter->UartIndex)) { //DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart tx abort: Not in TX state \n"); return HAL_OK; } // Disable Tx FIFO empty interrupt UART_INTConfig(puart_adapter->UARTx, RUART_IER_ETBEI, DISABLE); if(UART_GetTxFlag(puart_adapter->UartIndex) == STATERX_DMA) { if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE == DISABLE) { u32 Current_Addr; PGDMA_InitTypeDef GDMA_InitStruct = &puart_adapter->UARTTxGdmaInitStruct; u8 IsrTypeMap; Current_Addr = GDMA_GetSrcAddr(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); puart_adapter->TxCount = puart_adapter->TxCount - (Current_Addr - (u32)puart_adapter->pTxBuf); puart_adapter->pTxBuf = (u8*)Current_Addr; // Clean Auto Reload Bit GDMA_ChCleanAutoReload(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, CLEAN_RELOAD_DST); // Clear Pending ISR IsrTypeMap = GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); //GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); GDMA_ChnlFree(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); UART_TXDMACmd(puart_adapter->UARTx, DISABLE); } } UART_SetTxFlag(puart_adapter->UartIndex, 0); UART_ClearTxFifo(puart_adapter->UARTx); ret = obj->tx_len - puart_adapter->TxCount; return (ret); } /** * @brief stop the sream or steam_dma TX. * @param obj: uart object define in application software. */ int32_t serial_recv_stream_abort (serial_t *obj) { PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); int ret = 0; if (!UART_GetRxFlag(puart_adapter->UartIndex)) { //DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart rx abort: Not in TX state \n"); return HAL_OK; } // Disable Rx interrupt UART_INTConfig(puart_adapter->UARTx, (RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI), DISABLE); if(UART_GetRxFlag(puart_adapter->UartIndex) == STATERX_DMA) { if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE == DISABLE) { u32 Current_Addr; u32 TransCnt; PGDMA_InitTypeDef GDMA_InitStruct = &puart_adapter->UARTRxGdmaInitStruct; u8 IsrTypeMap; /*when stream DMA mode used, some data may be in uart rx fifo, get it if transmission aborted*/ Current_Addr = GDMA_GetDstAddr(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); puart_adapter->RxCount = puart_adapter->RxCount - (Current_Addr - (u32)puart_adapter->pRxBuf); puart_adapter->pRxBuf = (u8*)Current_Addr; TransCnt = UART_ReceiveDataTO(puart_adapter->UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= TransCnt; puart_adapter->pRxBuf += TransCnt; // Clean Auto Reload Bit GDMA_ChCleanAutoReload(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, CLEAN_RELOAD_DST); // Clear Pending ISR IsrTypeMap = GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); //GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE); GDMA_ChnlFree(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum); UART_RXDMACmd(puart_adapter->UARTx, DISABLE); } } UART_SetRxFlag(puart_adapter->UartIndex, 0); UART_ClearRxFifo(puart_adapter->UARTx); ret = obj->rx_len - puart_adapter->RxCount; return (ret); } /** * @brief Clear TX fifo. * @param obj: uart object define in application software. */ void serial_clear_tx(serial_t *obj) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; UART_ClearTxFifo(UARTx); } /** * @brief Clear RX fifo. * @param obj: uart object define in application software. */ void serial_clear_rx(serial_t *obj) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; UART_ClearRxFifo(UARTx); } /** * @brief recv target length data use poll mode, with time out. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be recv. * @param timeout_ms: polling time before timeout. * @retval return received bytes count * @note this function is synchronous API. */ int32_t serial_recv_blocked (serial_t *obj, char *prxbuf, uint32_t len, uint32_t timeout_ms) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; uint32_t cnt = 0; uint32_t startcount = SYSTIMER_TickGet(); obj->rx_len = len; while (1) { while (!serial_readable(obj)); UART_CharGet(UARTx, prxbuf); prxbuf++; cnt++; if (cnt == len) { break; } if (SYSTIMER_GetPassTime(startcount) > timeout_ms) { break; } } return cnt; } /** * @brief send target length data use poll mode, with time out. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be send. * @param timeout_ms: polling time before timeout. * @retval transmitted bytes count * @note this function is synchronous API. */ int32_t serial_send_blocked (serial_t *obj, char *ptxbuf, uint32_t len, uint32_t timeout_ms) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; uint32_t cnt = 0; uint32_t startcount = SYSTIMER_TickGet(); obj->tx_len = len; while (1) { while (!serial_writable(obj)); UART_CharPut(UARTx, *ptxbuf); ptxbuf++; cnt++; if (cnt == len) { break; } if (SYSTIMER_GetPassTime(startcount) > timeout_ms) { break; } } return cnt; } /** * @brief disable uart clock and function. * @retval none */ void serial_disable (serial_t *obj) { switch (obj->uart_idx) { case 0: /* UART 0 */ RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, DISABLE); break; case 1: /* UART 1 */ RCC_PeriphClockCmd(APBPeriph_UART1, APBPeriph_UART1_CLOCK, DISABLE); break; default: break; } } /** * @brief enable uart clock and function. * @retval none */ void serial_enable (serial_t *obj) { switch (obj->uart_idx) { case 0: /* UART 0 */ RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, ENABLE); break; case 1: /* UART 1 */ RCC_PeriphClockCmd(APBPeriph_UART1, APBPeriph_UART1_CLOCK, ENABLE); break; default: break; } } /** * @brief send target length data use interrupt mode. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be recv. * @retval the byte count received before timeout, or error(<0) * @note this function is asynchronous API. */ int32_t serial_recv_stream_timeout (serial_t *obj, char *prxbuf, uint32_t len, uint32_t timeout_ms, void *force_cs) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); u32 TransCnt = 0; void (*task_yield)(void); uint32_t startcount = SYSTIMER_TickGet(); assert_param(prxbuf != NULL); assert_param(len != 0); assert_param(timeout_ms > 0); //ret = HalRuartRecv(puart_adapter, (u8*)prxbuf, len, INT_BASED); if (UART_GetRxFlag(obj->uart_idx)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart int rx: busy\n"); return -1; } puart_adapter->pRxBuf = (uint8_t*)prxbuf; puart_adapter->RxCount = len; UART_SetRxFlag(obj->uart_idx, STATERX_INT); // Could be the RX FIFO has some data already TransCnt = UART_ReceiveDataTO(UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= TransCnt; puart_adapter->pRxBuf += TransCnt; if (puart_adapter->RxCount == 0) { uart_intrecv_complete(puart_adapter); return len; } else { // Enable RX Interrupt UART_INTConfig(UARTx, RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI, ENABLE); } if (puart_adapter->RxCount > 0) { task_yield = (void (*)(void))force_cs; while (1) { /* complete */ if (UART_GetRxFlag(obj->uart_idx) != STATERX_INT) { break; } /* time out */ if (SYSTIMER_GetPassTime(startcount) > timeout_ms) { serial_recv_stream_abort(obj); } if (NULL != task_yield) { task_yield(); } } } return (len - puart_adapter->RxCount); } /** * @brief send target length data use DMA mode. * @param obj: uart object define in application software. * @param ptxbuf: buffer to be written to Tx FIFO. * @param len: number of data to be recv. * @retval the byte count received before timeout, or error(<0) * @note this function is asynchronous API. */ int32_t serial_recv_stream_dma_timeout (serial_t *obj, char *prxbuf, uint32_t len, uint32_t timeout_ms, void *force_cs) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; PMBED_UART_ADAPTER puart_adapter=&(uart_adapter[obj->uart_idx]); void (*task_yield)(void); uint32_t startcount = SYSTIMER_TickGet(); u32 ret1; if (uart_config[obj->uart_idx].LOW_POWER_RX_ENABLE) { return serial_recv_stream_timeout (obj, prxbuf, len, timeout_ms, force_cs); } assert_param(prxbuf != NULL); assert_param(len != 0); assert_param(timeout_ms > 0); if (UART_GetRxFlag(puart_adapter->UartIndex)) { DBG_PRINTF(MODULE_UART, LEVEL_WARN, "uart dma rx: busy\n"); return -1; } puart_adapter->pRxBuf = (u8*)prxbuf; puart_adapter->RxCount = len; puart_adapter->last_dma_addr = (u32)prxbuf; UART_SetRxFlag(puart_adapter->UartIndex, STATERX_DMA); // Disable Rx interrupt UART_INTConfig(puart_adapter->UARTx, (RUART_IER_ERBI | RUART_IER_ELSI | RUART_IER_ETOI), DISABLE); UART_RXDMAConfig(puart_adapter->UARTx, 4); UART_RXDMACmd(puart_adapter->UARTx, ENABLE); ret1 = UART_RXGDMA_Init(puart_adapter->UartIndex, &puart_adapter->UARTRxGdmaInitStruct, puart_adapter, uart_dmarecv_irqhandler, puart_adapter->pRxBuf, puart_adapter->RxCount); if ((serial_dma_en[obj->uart_idx] & SERIAL_RX_DMA_EN)==0) { if(ret1 == _TRUE) { serial_dma_en[obj->uart_idx] |= SERIAL_RX_DMA_EN; } else { return -1; } } if (puart_adapter->RxCount > 0) { task_yield = (void (*)(void))force_cs; while (1) { /* complete */ if (UART_GetRxFlag(obj->uart_idx) != STATERX_DMA) { break; } /* time out */ if (SYSTIMER_GetPassTime(startcount) > timeout_ms) { uint32_t current_dst_addr = GDMA_GetDstAddr(puart_adapter->UARTRxGdmaInitStruct.GDMA_Index, puart_adapter->UARTRxGdmaInitStruct.GDMA_ChNum); uint32_t data_in_fifo = UART_Readable(puart_adapter->UARTx); uint32_t trans_cnt = 0; /* have Rx some data */ if ((current_dst_addr != (u32)(puart_adapter->pRxBuf)) || data_in_fifo) { puart_adapter->RxCount = puart_adapter->RxCount - (current_dst_addr - (u32)puart_adapter->pRxBuf); puart_adapter->pRxBuf = (u8*)current_dst_addr; trans_cnt = UART_ReceiveDataTO(puart_adapter->UARTx, puart_adapter->pRxBuf, puart_adapter->RxCount, 1); puart_adapter->RxCount -= trans_cnt; puart_adapter->pRxBuf += trans_cnt; } uart_dmarecv_complete(puart_adapter); break; } if (NULL != task_yield) { task_yield(); } } } return (len - puart_adapter->RxCount); } /** * @brief set uart rx fifo trigger level. * @param obj: uart object define in application software. * @param FifoLv: FIFO level enum index. * @retval none */ void serial_rx_fifo_level(serial_t *obj, SerialFifoLevel FifoLv) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; u32 Temp; switch(FifoLv) { case FifoLv1Byte: Temp = UART_RX_FIFOTRIG_LEVEL_1BYTES; break; case FifoLvQuarter: Temp = UART_RX_FIFOTRIG_LEVEL_4BYTES; break; case FifoLvHalf: Temp = UART_RX_FIFOTRIG_LEVEL_8BYTES; break; case FifoLvFull: Temp = UART_RX_FIFOTRIG_LEVEL_14BYTES; break; default: assert_param(0); break; } /*set rx fifo level*/ UART_SetRxLevel(UARTx, Temp); } /** * @brief uart autoflow contol setting. * @param obj: uart object define in application software. * @param type: autoflow control type. * @param rxflow: RTS pin. * @param txflow: CTS pin. * @retval none */ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { UART_TypeDef* UARTx = UART_DEV_TABLE[obj->uart_idx].UARTx; /*Only UART0 supports auto flow control in AmebaZ*/ assert_param(obj->uart_idx == 0); /*autoflow control configuration*/ if(type != FlowControlNone) { /*config UART0 pinmux*/ if(rxflow == PA_3) { /*UART0 "S0" */ Pinmux_Config(_PA_3, PINMUX_FUNCTION_UART); /*RTS*/ Pinmux_Config(_PA_2, PINMUX_FUNCTION_UART); /*CTS*/ } else if (rxflow == PA_22) { /*UART0 "S1" */ Pinmux_Config(_PA_22, PINMUX_FUNCTION_UART); /*RTS*/ Pinmux_Config(_PA_19, PINMUX_FUNCTION_UART); /*CTS*/ } else { assert_param(0); } /*enable auto flow control*/ UARTx->MCR |= BIT(5); } else { /*disable auto flow control*/ UARTx->MCR &= ~ BIT(5); } /*no matter auto flow control is enabled or disabled, RTS pin should be always Low, and thus peer can send data*/ UARTx->MCR |= BIT(1); } /******************* (C) COPYRIGHT 2016 Realtek Semiconductor *****END OF FILE****/