From 78a92ae1029dd474190c93c94af812bb0220f310 Mon Sep 17 00:00:00 2001 From: flyingcys <294102238@qq.com> Date: Sat, 2 Jun 2018 14:44:32 +0800 Subject: [PATCH] update serail_api.c --- rtthread_patch/SConscript | 1 + .../realtek/8711b/mbed/serial_api.c | 1502 +++++++++++++++++ .../component/common/mbed/SConscript | 1 - 3 files changed, 1503 insertions(+), 1 deletion(-) create mode 100644 rtthread_patch/realtek/8711b/mbed/serial_api.c diff --git a/rtthread_patch/SConscript b/rtthread_patch/SConscript index 65d32d4..01bb92a 100644 --- a/rtthread_patch/SConscript +++ b/rtthread_patch/SConscript @@ -7,6 +7,7 @@ src = Split(''' os/rtthread_service.c realtek/8711b/rtl8710b_startup.c realtek/8711b/app_start.c + realtek/8711b/mbed/serial_api.c realtek/common/wifi/wifi_conf.c ''') diff --git a/rtthread_patch/realtek/8711b/mbed/serial_api.c b/rtthread_patch/realtek/8711b/mbed/serial_api.c new file mode 100644 index 0000000..e477fed --- /dev/null +++ b/rtthread_patch/realtek/8711b/mbed/serial_api.c @@ -0,0 +1,1502 @@ +/** 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 + +#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 +} + +/** + * @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 + // 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); + } + } +} + +/** + * @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; + + if (!serial_readable(obj)) + return -1; + 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); + + 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); + + 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****/ diff --git a/sdk-ameba-v4.0b_without_NDA_GCC_V1.0.0/component/common/mbed/SConscript b/sdk-ameba-v4.0b_without_NDA_GCC_V1.0.0/component/common/mbed/SConscript index 0c93fca..015874f 100644 --- a/sdk-ameba-v4.0b_without_NDA_GCC_V1.0.0/component/common/mbed/SConscript +++ b/sdk-ameba-v4.0b_without_NDA_GCC_V1.0.0/component/common/mbed/SConscript @@ -21,7 +21,6 @@ targets/hal/rtl8711b/pinmap_common.c targets/hal/rtl8711b/port_api.c targets/hal/rtl8711b/pwmout_api.c targets/hal/rtl8711b/rtc_api.c -targets/hal/rtl8711b/serial_api.c targets/hal/rtl8711b/sleep.c targets/hal/rtl8711b/spi_api.c targets/hal/rtl8711b/sys_api.c