/*******************************************************************************
|
* File Name : Uart.c
|
* Description :
|
* Created on : 2018Äê4ÔÂ24ÈÕ
|
* Author : ¶Å¼ü
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Include Files *
|
*******************************************************************************/
|
#include "string.h"
|
#ifdef _USE_OS_
|
#include "cmsis_os.h"
|
#endif
|
#include <stdio.h>
|
#include "HIDO_Util.h"
|
#include "HIDO_VLQueue.h"
|
#include "HIDO_ArraryQueue.h"
|
#include "HIDO_Lock.h"
|
#include "HIDO_ATLite.h"
|
|
#include "UART.h"
|
|
/*******************************************************************************
|
* Macro *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Type Definition *
|
*******************************************************************************/
|
typedef struct
|
{
|
#ifdef _USE_OS_
|
osMutexId m_mutexLock;
|
#endif
|
E_UartID m_eUartID;
|
enum UART_DEV_T m_eUartPort;
|
|
E_UartTxMode m_eTxMode;
|
E_UartRxMode m_eRxMode;
|
|
HIDO_UINT8 *m_pu8RxBuf;
|
HIDO_UINT32 m_u32RxBufSize;
|
HIDO_UINT8 *m_pu8RxLastPos;
|
HIDO_UINT8 *m_pu8RxBufEnd;
|
HIDO_ArraryQueueStruct m_stRxArraryQueue;
|
|
HIDO_UINT8 *m_pu8TxBuf;
|
HIDO_UINT32 m_u32TxBufSize;
|
HIDO_UINT32 m_u32TxQueueMemberCnt;
|
HIDO_VLQStruct m_stTxVLQueue;
|
|
HIDO_UINT8 m_u8RxValue;
|
HIDO_UINT32 m_u32Flag;
|
FN_RxISR m_fnRxISR;
|
} ST_UartInfo;
|
|
/*******************************************************************************
|
* Local Variable *
|
*******************************************************************************/
|
static ST_UartInfo l_astUartInfo[UART_ID_LAST];
|
|
/*******************************************************************************
|
* Local Function Declaration *
|
*******************************************************************************/
|
static void uart_receive_callback(void *dev, uint32_t err_code);
|
|
const static struct baud_map
|
{
|
enum UART_BAUD_T baud;
|
HIDO_UINT32 u32Baud;
|
} baud_map[] =
|
{
|
{BAUD_1200, 1200},
|
{BAUD_2400, 2400},
|
{BAUD_4800, 4800},
|
{BAUD_9600, 9600},
|
{BAUD_19200, 19200},
|
{BAUD_38400, 38400},
|
{BAUD_57600, 57600},
|
{BAUD_115200, 115200},
|
{BAUD_230400, 230400},
|
{BAUD_460800, 460800},
|
{BAUD_921600, 921600},
|
{BAUD_1843200, 1843200},
|
{BAUD_1000000, 1000000},
|
{BAUD_2000000, 2000000},
|
};
|
|
/*******************************************************************************
|
* Local Function *
|
*******************************************************************************/
|
static enum UART_BAUD_T get_baud(HIDO_UINT32 u32Baud)
|
{
|
for(HIDO_UINT32 i = 0; i < HIDO_ARRARY_COUNT(baud_map); i++)
|
{
|
if(u32Baud == baud_map[i].u32Baud)
|
{
|
return baud_map[i].baud;
|
}
|
}
|
|
return BAUD_115200;
|
}
|
|
/*******************************************************************************
|
* Global Function *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_Register(E_UartID _eUartID, enum UART_DEV_T _ePort)
|
{
|
/* ³õʼ»¯²ÎÊý */
|
HIDO_UtilBzero(&l_astUartInfo[_eUartID], sizeof(ST_UartInfo));
|
|
l_astUartInfo[_eUartID].m_eUartPort = _ePort;
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_Init(E_UartID _eUartID, ST_UartInit *_pstInit)
|
{
|
if((HIDO_NULL == _pstInit) || (_eUartID >= UART_ID_LAST))
|
{
|
return HIDO_ERR;
|
}
|
|
#ifdef _USE_OS_
|
l_astUartInfo[_eUartID].m_mutexLock = osMutexCreate(HIDO_NULL);
|
#endif
|
|
struct UART_CFG_T uart_cfg =
|
{
|
.parity = UART_PARITY_NONE,
|
.stop = UART_STOP_BITS_1,
|
.data = UART_DATA_BITS_8,
|
.flow = UART_FLOW_CONTROL_NONE,
|
.rx_level = UART_RXFIFO_CHAR_1,
|
.tx_level = UART_TXFIFO_EMPTY,
|
.baud = get_baud(_pstInit->m_u32BaudRate),
|
.dma_en = true,
|
.int_rx = false,
|
.int_tx = false,
|
};
|
|
l_astUartInfo[_eUartID].m_eUartID = _eUartID;
|
l_astUartInfo[_eUartID].m_eTxMode = _pstInit->m_eTxMode;
|
l_astUartInfo[_eUartID].m_eRxMode = _pstInit->m_eRxMode;
|
|
l_astUartInfo[_eUartID].m_pu8RxBuf = _pstInit->m_pu8RxBuf;
|
l_astUartInfo[_eUartID].m_u32RxBufSize = _pstInit->m_u32RxBufSize;
|
if(UART_RX_MODE_DMA == _pstInit->m_eRxMode)
|
{
|
l_astUartInfo[_eUartID].m_pu8RxLastPos= l_astUartInfo[_eUartID].m_pu8RxBuf;
|
l_astUartInfo[_eUartID].m_pu8RxBufEnd = l_astUartInfo[_eUartID].m_pu8RxBuf + l_astUartInfo[_eUartID].m_u32RxBufSize - 1;
|
}
|
else if(UART_RX_MODE_INT == _pstInit->m_eRxMode)
|
{
|
HIDO_ArraryQueueInit(
|
&l_astUartInfo[_eUartID].m_stRxArraryQueue,
|
_pstInit->m_pu8RxBuf,
|
_pstInit->m_u32RxBufSize,
|
sizeof(HIDO_UINT8));
|
}
|
|
l_astUartInfo[_eUartID].m_pu8TxBuf = _pstInit->m_pu8TxBuf;
|
l_astUartInfo[_eUartID].m_u32TxBufSize = _pstInit->m_u32TxBufSize;
|
l_astUartInfo[_eUartID].m_fnRxISR = _pstInit->m_fnRxISR;
|
l_astUartInfo[_eUartID].m_u32TxQueueMemberCnt = _pstInit->m_u32TxQueueMemberCnt;
|
|
uart_open(l_astUartInfo[_eUartID].m_eUartPort, &uart_cfg);
|
|
if((UART_TX_MODE_DMA == _pstInit->m_eTxMode) || (UART_TX_MODE_INT == _pstInit->m_eTxMode))
|
{
|
HIDO_VLQInit(
|
&(l_astUartInfo[_eUartID].m_stTxVLQueue),
|
_pstInit->m_pu8TxBuf,
|
_pstInit->m_u32TxBufSize,
|
_pstInit->m_u32TxQueueMemberCnt);
|
}
|
|
if (UART_RX_MODE_INT == _pstInit->m_eRxMode)
|
{
|
uart_receive(l_astUartInfo[_eUartID].m_eUartPort, &l_astUartInfo[_eUartID].m_u8RxValue, 1, uart_receive_callback);
|
}
|
|
return HIDO_OK;
|
}
|
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_ReInit(E_UartID _eUartID)
|
{
|
if(UART_RX_MODE_DMA == l_astUartInfo[_eUartID].m_eRxMode)
|
{
|
l_astUartInfo[_eUartID].m_pu8RxLastPos= l_astUartInfo[_eUartID].m_pu8RxBuf;
|
l_astUartInfo[_eUartID].m_pu8RxBufEnd = l_astUartInfo[_eUartID].m_pu8RxBuf + l_astUartInfo[_eUartID].m_u32RxBufSize - 1;
|
}
|
else if(UART_RX_MODE_INT == l_astUartInfo[_eUartID].m_eRxMode)
|
{
|
HIDO_ArraryQueueInit(
|
&l_astUartInfo[_eUartID].m_stRxArraryQueue,
|
l_astUartInfo[_eUartID].m_pu8RxBuf,
|
l_astUartInfo[_eUartID].m_u32RxBufSize,
|
sizeof(HIDO_UINT8));
|
}
|
|
if((UART_TX_MODE_DMA == l_astUartInfo[_eUartID].m_eTxMode) || (UART_TX_MODE_INT == l_astUartInfo[_eUartID].m_eTxMode))
|
{
|
HIDO_VLQInit(
|
&(l_astUartInfo[_eUartID].m_stTxVLQueue),
|
l_astUartInfo[_eUartID].m_pu8TxBuf,
|
l_astUartInfo[_eUartID].m_u32TxBufSize,
|
l_astUartInfo[_eUartID].m_u32TxQueueMemberCnt);
|
}
|
|
uart_receive(l_astUartInfo[_eUartID].m_eUartPort, &l_astUartInfo[_eUartID].m_u8RxValue, 1, uart_receive_callback);
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_ReConfigBaudRate(E_UartID _eUartID, HIDO_UINT32 _u32BaudRate)
|
{
|
uart_close(l_astUartInfo[_eUartID].m_eUartPort);
|
|
struct UART_CFG_T uart_cfg =
|
{
|
.parity = UART_PARITY_NONE,
|
.stop = UART_STOP_BITS_1,
|
.data = UART_DATA_BITS_8,
|
.flow = UART_FLOW_CONTROL_NONE,
|
.rx_level = UART_RXFIFO_CHAR_1,
|
.tx_level = UART_TXFIFO_EMPTY,
|
.baud = get_baud(_u32BaudRate),
|
.dma_en = false,
|
.int_rx = true,
|
.int_tx = false,
|
};
|
|
uart_open(l_astUartInfo[_eUartID].m_eUartPort, &uart_cfg);
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
static void uart_send_callback(void *dev, uint32_t err_code)
|
{
|
E_UartID eUartID = (E_UartID) 0;
|
|
for (eUartID = (E_UartID) 0; eUartID < UART_ID_LAST; eUartID++)
|
{
|
if (l_astUartInfo[eUartID].m_eUartPort == *(enum UART_DEV_T *)dev)
|
{
|
if(UART_TX_MODE_DMA == l_astUartInfo[eUartID].m_eTxMode)
|
{
|
HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
|
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
|
HIDO_VLQDequeue(&(l_astUartInfo[eUartID].m_stTxVLQueue), pstMember);
|
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
|
if (pstMember)
|
{
|
uart_send(l_astUartInfo[eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
|
}
|
}
|
else if(UART_TX_MODE_INT == l_astUartInfo[eUartID].m_eTxMode)
|
{
|
HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
|
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
|
HIDO_VLQDequeue(&(l_astUartInfo[eUartID].m_stTxVLQueue), pstMember);
|
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[eUartID].m_stTxVLQueue));
|
if (pstMember)
|
{
|
uart_send(l_astUartInfo[eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
|
}
|
}
|
|
break;
|
}
|
}
|
}
|
|
|
/*******************************************************************************
|
* Function Name : Uart_RxOverFromISR
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
static void uart_receive_callback(void *dev, uint32_t err_code)
|
{
|
E_UartID eUartID = UART_ID_4G;
|
|
HIDO_UINT8 u8RecvByte = l_astUartInfo[eUartID].m_u8RxValue;
|
|
HIDO_ArraryQueueIn(&l_astUartInfo[eUartID].m_stRxArraryQueue, &u8RecvByte);
|
|
/* Æô¶¯INT½ÓÊÕ */
|
uart_receive(l_astUartInfo[eUartID].m_eUartPort, &l_astUartInfo[eUartID].m_u8RxValue, 1, uart_receive_callback);
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_GetChar(E_UartID _eUartID, HIDO_UINT8 *_pu8Char)
|
{
|
HIDO_INT32 i32Result = HIDO_ERR;
|
|
if (HIDO_NULL == _pu8Char || _eUartID >= UART_ID_LAST)
|
{
|
return HIDO_ERR;
|
}
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astUartInfo[_eUartID].m_mutexLock, osWaitForever);
|
#endif
|
|
if (UART_RX_MODE_INT == l_astUartInfo[_eUartID].m_eRxMode)
|
{
|
if (HIDO_ArraryQueueOut(&l_astUartInfo[_eUartID].m_stRxArraryQueue, _pu8Char) == HIDO_OK)
|
{
|
i32Result = HIDO_OK;
|
}
|
}
|
|
#ifdef _USE_OS_
|
osMutexRelease(l_astUartInfo[_eUartID].m_mutexLock);
|
#endif
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : ¶Å¼ü
|
* Modified Date: : 2018Äê4ÔÂ24ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 Uart_Send(E_UartID _eUartID, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32Len)
|
{
|
HIDO_INT32 i32Result = HIDO_OK;
|
|
if (HIDO_NULL == _pu8Data || 0 == _u32Len || _eUartID >= UART_ID_LAST)
|
{
|
return HIDO_ERR;
|
}
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astUartInfo[_eUartID].m_mutexLock, osWaitForever);
|
#endif
|
|
if (UART_TX_MODE_DMA == l_astUartInfo[_eUartID].m_eTxMode)
|
{
|
HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
|
|
HIDO_Lock();
|
pstMember = HIDO_VLQGetEnqueueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue), _u32Len);
|
|
if (HIDO_NULL == pstMember)
|
{
|
HIDO_UnLock();
|
i32Result = HIDO_ERR;
|
}
|
else
|
{
|
HIDO_VLQEnqueue(&(l_astUartInfo[_eUartID].m_stTxVLQueue), pstMember);
|
memcpy(pstMember->m_pDataAddr, _pu8Data, _u32Len);
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue));
|
HIDO_UnLock();
|
|
uart_send(l_astUartInfo[_eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
|
}
|
}
|
else if (UART_TX_MODE_INT == l_astUartInfo[_eUartID].m_eTxMode)
|
{
|
HIDO_VLQMemberStruct *pstMember = HIDO_NULL;
|
|
HIDO_Lock();
|
pstMember = HIDO_VLQGetEnqueueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue), _u32Len);
|
|
if (HIDO_NULL == pstMember)
|
{
|
HIDO_UnLock();
|
i32Result = HIDO_ERR;
|
}
|
else
|
{
|
HIDO_VLQEnqueue(&(l_astUartInfo[_eUartID].m_stTxVLQueue), pstMember);
|
memcpy(pstMember->m_pDataAddr, _pu8Data, _u32Len);
|
pstMember = HIDO_VLQGetDequeueMember(&(l_astUartInfo[_eUartID].m_stTxVLQueue));
|
HIDO_UnLock();
|
|
uart_send(l_astUartInfo[_eUartID].m_eUartPort, pstMember->m_pDataAddr, pstMember->m_u32DataLen, uart_send_callback);
|
}
|
}
|
else if (UART_TX_MODE_POLL == l_astUartInfo[_eUartID].m_eTxMode)
|
{
|
uart_send(l_astUartInfo[_eUartID].m_eUartPort, _pu8Data, _u32Len, NULL);
|
}
|
|
#ifdef _USE_OS_
|
osMutexRelease(l_astUartInfo[_eUartID].m_mutexLock);
|
#endif
|
|
return i32Result;
|
}
|
HIDO_VOID HIDO_Lock(void)
|
{
|
int_lock();
|
}
|
HIDO_VOID HIDO_UnLock(void)
|
{
|
uint32_t lock = int_lock();
|
int_unlock(lock);
|
}
|