298 lines
11 KiB
C
298 lines
11 KiB
C
//
|
|
// Created by cfif on 16.09.22.
|
|
//
|
|
#include <SystemDelayInterface.h>
|
|
#include "SerialPortFlagchip.h"
|
|
|
|
#include "string.h"
|
|
|
|
static const PCC_ClkSrcType s_ePccUartTable[] =
|
|
{
|
|
PCC_CLK_FCUART0,
|
|
PCC_CLK_FCUART1,
|
|
PCC_CLK_FCUART2,
|
|
PCC_CLK_FCUART3,
|
|
PCC_CLK_FCUART4,
|
|
PCC_CLK_FCUART5,
|
|
PCC_CLK_FCUART6,
|
|
PCC_CLK_FCUART7
|
|
};
|
|
|
|
void vSerialPortInitDMA(
|
|
tSerialPortFlagchip *env,
|
|
|
|
FCUART_Type *uart,
|
|
uint32_t BoundRate,
|
|
uint8 UART_INDEX, // UART0 = 0 ... UART7 = 7
|
|
IRQn_Type IRQ_UART, // FCUART0_IRQn ... FCUART7_IRQn
|
|
uint8 UART_PRIORITY,
|
|
|
|
uint8_t *dataBufTransmit,
|
|
uint32_t dataBufTransmitLen,
|
|
|
|
DMA_ChannelType DMA_CHANNEL_RX,
|
|
DMA_RequestSourceType DMA_CHANNEL_REQ_RX,
|
|
uint8_t *DMA_BUF_RX,
|
|
uint16_t DMA_BUF_LEN_RX,
|
|
IRQn_Type IRQ_DMA_RX,
|
|
uint8_t IRQ_DMA_PRIORITY_RX,
|
|
uint8_t IRQ_DMA_CHANNEL_PRIORITY_RX,
|
|
|
|
uint32_t rxBufferLength,
|
|
uint32_t rxSnifferLength,
|
|
|
|
DMA_TransferCompleteCallbackType pTransferCompleteNotify,
|
|
DMA_TransferErrorCallbackType pTransferErrorNotify,
|
|
|
|
FCUART_IdleInterrupt_CallBackType FCUART_IldeInterrupt_CallBack,
|
|
FCUART_ErrorInterrupt_CallBackType FCUART_ErrorInterrupt_CallBack,
|
|
|
|
FCUART_TxRxInterrupt_CallBackType FCUART_TxEmptyInterrupt_CallBack,
|
|
FCUART_TxRxInterrupt_CallBackType FCUART_TxCompleteInterrupt_CallBack
|
|
|
|
|
|
) {
|
|
env->UART_INDEX = UART_INDEX;
|
|
env->RX_DMA_CHANNEL = DMA_CHANNEL_RX;
|
|
env->UART = uart;
|
|
env->DMA_BUF_LEN = DMA_BUF_LEN_RX;
|
|
env->UART_DMA_RECEIVED_LEN_BUF = 0;
|
|
env->dataBufTransmit = dataBufTransmit;
|
|
env->dataBufTransmitLen = dataBufTransmitLen;
|
|
env->txAccessQueue = osMessageQueueNew(1, 1, NULL);
|
|
env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL);
|
|
|
|
if (rxSnifferLength) {
|
|
env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL);
|
|
} else {
|
|
env->rxDataSnifferQueue = 0;
|
|
}
|
|
|
|
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
|
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
|
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
|
|
|
env->chnCfg_RX.pSrcBuffer = &(uart->DATA);
|
|
env->chnCfg_RX.pDestBuffer = DMA_BUF_RX;
|
|
env->chnCfg_RX.u32BlockSize = 1U;
|
|
env->chnCfg_RX.u16BlockCount = 1U;
|
|
env->chnCfg_RX.u8ChannelPriority = IRQ_DMA_CHANNEL_PRIORITY_RX;
|
|
env->chnCfg_RX.eSrcDataSize = DMA_TRANSFER_SIZE_1B;
|
|
env->chnCfg_RX.eDestDataSize = DMA_TRANSFER_SIZE_1B;
|
|
env->chnCfg_RX.eSrcIncMode = DMA_INCREMENT_DISABLE;
|
|
env->chnCfg_RX.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
|
|
env->chnCfg_RX.bSrcBlockOffsetEn = false;
|
|
env->chnCfg_RX.bDestBlockOffsetEn = false;
|
|
env->chnCfg_RX.s32BlockOffset = 0;
|
|
env->chnCfg_RX.bSrcAddrLoopbackEn = false;
|
|
env->chnCfg_RX.bDestAddrLoopbackEn = false;
|
|
env->chnCfg_RX.bAutoStop = false;
|
|
|
|
env->chnCfg_RX.bSrcCircularBufferEn = false;
|
|
env->chnCfg_RX.u32SrcCircBufferSize = 0U;
|
|
env->chnCfg_RX.bDestCircularBufferEn = true;
|
|
env->chnCfg_RX.u32DestCircBufferSize = DMA_BUF_LEN_RX;
|
|
|
|
env->chnCfg_RX.eTriggerSrc = DMA_CHANNEL_REQ_RX;
|
|
DMA_InitChannel(DMA_INSTANCE_0, DMA_CHANNEL_RX, &env->chnCfg_RX);
|
|
|
|
env->interruptCfg_RX.bTransferCompleteIntEn = true;
|
|
env->interruptCfg_RX.pTransferCompleteNotify = pTransferCompleteNotify;
|
|
env->interruptCfg_RX.bTransferErrorIntEn = true;
|
|
env->interruptCfg_RX.pTransferErrorNotify = pTransferErrorNotify;
|
|
DMA_InitChannelInterrupt(DMA_INSTANCE_0, DMA_CHANNEL_RX, &env->interruptCfg_RX);
|
|
|
|
DMA_StartChannel(DMA_INSTANCE_0, DMA_CHANNEL_RX);
|
|
|
|
NVIC_SetPriority(DMA_Error_IRQn, IRQ_DMA_PRIORITY_RX);
|
|
NVIC_SetPriority(IRQ_DMA_RX, IRQ_DMA_PRIORITY_RX);
|
|
NVIC_EnableIRQ(IRQ_DMA_RX);
|
|
|
|
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
|
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
|
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
|
|
|
|
|
//начало------------------------------------UART--------------------------------------------------------------------
|
|
//начало------------------------------------UART--------------------------------------------------------------------
|
|
//начало------------------------------------UART--------------------------------------------------------------------
|
|
|
|
FCUART_ErrorType tRetVal;
|
|
uint32_t u32PccFuncClk;
|
|
|
|
FCUART_InitMemory(UART_INDEX);
|
|
|
|
u32PccFuncClk = PCC_GetPccFunctionClock(s_ePccUartTable[UART_INDEX]);
|
|
|
|
if (u32PccFuncClk != 0U) {
|
|
env->tInitCfg.bEnRxFullDma = true; // UART receiver full DMA disable
|
|
|
|
env->tInitCfg.bEnTxFifo = true;
|
|
env->tInitCfg.u8TxFifoWaterMark = 0U;
|
|
|
|
env->tInitCfg.bEnRxFifo = true;
|
|
env->tInitCfg.u8RxFifoWaterMark = 0U;
|
|
|
|
env->tInitCfg.eIdleCharNum = FCUART_IDLE_CHARCTER_64; // UART idle character number 64
|
|
env->tInitCfg.eIdleStart = FCUART_START_AFTER_STOPBIT; // UART idle character type
|
|
env->tInitCfg.u32Baudrate = BoundRate; // UART baud-rate
|
|
env->tInitCfg.eBitMode = UART_BITMODE_8; // UART bit mode
|
|
env->tInitCfg.bParityEnable = false; // UART parity check enable
|
|
env->tInitCfg.eStopBit = UART_STOPBIT_NUM_1; // UART stop bit number
|
|
env->tInitCfg.u32ClkSrcHz = u32PccFuncClk; // UART function clock
|
|
env->tInitCfg.u32TransmitTimeout = 0xFFFFFFFFU; // Transmit timeout tick
|
|
|
|
// start initial UART
|
|
tRetVal = FCUART_Init(UART_INDEX, &env->tInitCfg);
|
|
|
|
if (tRetVal == FCUART_ERROR_OK) {
|
|
|
|
env->s_tFCUART_TxMsg.pDatas = (uint8_t *) env->dataBufTransmit; // data buffer must set an array address
|
|
env->s_tFCUART_TxMsg.u32DataLen = 0;
|
|
env->tInterruptCfg.pTxBuf = &env->s_tFCUART_TxMsg;
|
|
|
|
env->tInterruptCfg.bEnIdleInterrupt = true;
|
|
env->tInterruptCfg.pIdleNotify = FCUART_IldeInterrupt_CallBack;
|
|
env->tInterruptCfg.bEnErrorInterrupt = true;
|
|
env->tInterruptCfg.pErrorNotify = FCUART_ErrorInterrupt_CallBack;
|
|
env->tInterruptCfg.bEnRxInterrupt = false;
|
|
env->tInterruptCfg.pRxNotify = NULL;
|
|
|
|
env->tInterruptCfg.bEnTxInterrupt = false;
|
|
env->tInterruptCfg.pTxEmptyNotify = FCUART_TxEmptyInterrupt_CallBack;
|
|
env->tInterruptCfg.pTxCompleteNotify = FCUART_TxCompleteInterrupt_CallBack;
|
|
|
|
tRetVal = FCUART_BufTransmitted(UART_INDEX, &env->tInterruptCfg);
|
|
|
|
tRetVal = FCUART_SetInterrupt(UART_INDEX, &env->tInterruptCfg);
|
|
|
|
NVIC_SetPriority(IRQ_UART, UART_PRIORITY);
|
|
NVIC_EnableIRQ(IRQ_UART);
|
|
|
|
tRetVal = FCUART_StartReceive(UART_INDEX);
|
|
|
|
}
|
|
}
|
|
|
|
//конец------------------------------------UART---------------------------------------------------------------------
|
|
//конец------------------------------------UART---------------------------------------------------------------------
|
|
//конец------------------------------------UART---------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
|
|
static uint16_t vSerialPortReceiveQueue(tSerialPortFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout,
|
|
osMessageQueueId_t queueId) {
|
|
|
|
PROCESS_UNUSED_VAR(env)
|
|
|
|
uint16_t received = 0;
|
|
|
|
if (timeout) {
|
|
uint32_t endMs = SystemGetMs() + timeout;
|
|
uint32_t leftMs;
|
|
|
|
while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) {
|
|
leftMs = endMs - SystemGetMs();
|
|
if (osMessageQueueGet(queueId, data, NULL, leftMs) == osOK) {
|
|
--size;
|
|
++received;
|
|
++data;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
while (size) {
|
|
if (osMessageQueueGet(queueId, data, NULL, 0) == osOK) {
|
|
--size;
|
|
++received;
|
|
++data;
|
|
} else {
|
|
return received;
|
|
}
|
|
}
|
|
}
|
|
|
|
return received;
|
|
|
|
}
|
|
|
|
static uint16_t vSerialPortReceive(tSerialPortFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
return vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataQueue);
|
|
}
|
|
|
|
static uint16_t vSerialPortReceiveSniffer(tSerialPortFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
|
|
return env->rxDataSnifferQueue
|
|
? vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue)
|
|
: 0;
|
|
}
|
|
|
|
|
|
static uint16_t
|
|
vSerialPortTransmitOverCore(tSerialPortFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
|
|
uint16_t sent = 0;
|
|
|
|
FCUART_ErrorType tRetVal;
|
|
|
|
tRetVal = FCUART_AssignTxInterruptData(env->UART_INDEX, env->dataBufTransmit, size);
|
|
|
|
tRetVal = FCUART_StartTransmit(env->UART_INDEX);
|
|
|
|
PROCESS_UNUSED_VAR(tRetVal)
|
|
|
|
uint8_t res;
|
|
|
|
sent = (osMessageQueueGet(env->txAccessQueue, &res, 0, timeout) == osOK) ? size : 0;
|
|
|
|
return sent;
|
|
}
|
|
|
|
void SerialPort_TxEndTransmitted(tSerialPortFlagchip *env, uint8_t data) {
|
|
osMessageQueuePut(env->txAccessQueue, &data, 0x0, 0U);
|
|
}
|
|
|
|
void SerialPort_RxDmaBufToQueue(tSerialPortFlagchip *env, const void *pSrcBuffer) {
|
|
|
|
for (uint32_t i = 0; i < env->UART_DMA_RECEIVED_LEN_BUF; ++i) {
|
|
osMessageQueuePut(env->rxDataQueue, &((uint8 *) pSrcBuffer)[i], 0x0, 0U);
|
|
if (env->rxDataSnifferQueue) {
|
|
osMessageQueuePut(env->rxDataSnifferQueue, &((uint8 *) pSrcBuffer)[i], 0x0, 0U);
|
|
}
|
|
}
|
|
|
|
env->UART_DMA_RECEIVED_POINTER_BUF += env->UART_DMA_RECEIVED_LEN_BUF;
|
|
env->UART_DMA_RECEIVED_LEN_BUF = 0;
|
|
if (env->UART_DMA_RECEIVED_POINTER_BUF >= env->DMA_BUF_LEN)
|
|
env->UART_DMA_RECEIVED_POINTER_BUF = 0;
|
|
|
|
}
|
|
|
|
|
|
static SerialPortIOTransaction vSerialPortTransmitterGet(tSerialPortFlagchip *env) {
|
|
|
|
PROCESS_UNUSED_VAR(env)
|
|
|
|
return (SerialPortIOTransaction) vSerialPortTransmitOverCore;
|
|
|
|
}
|
|
|
|
tSerialPortIO vSerialPortGetIo(tSerialPortFlagchip *env) {
|
|
tSerialPortIO io = {
|
|
.env = env,
|
|
.receive = (SerialPortIOTransaction) vSerialPortReceive,
|
|
.transmit = vSerialPortTransmitterGet(env)
|
|
};
|
|
return io;
|
|
}
|
|
|
|
tSerialPortIO vSerialPortGetSnifferIo(tSerialPortFlagchip *env) {
|
|
tSerialPortIO io = {
|
|
.env = env,
|
|
.receive = (SerialPortIOTransaction) vSerialPortReceiveSniffer,
|
|
.transmit = vSerialPortTransmitterGet(env)
|
|
};
|
|
return io;
|
|
}
|