618 lines
19 KiB
C
618 lines
19 KiB
C
//
|
|
// Created by cfif on 16.03.2024.
|
|
//
|
|
#include <SystemDelayInterface.h>
|
|
#include "CanSerialPortFrame.h"
|
|
#include "memory.h"
|
|
|
|
|
|
#define CAN_USED_NUM 6U
|
|
#define CAN_RECEIVE_MB_NUM 2
|
|
static FLEXCAN_RxMsgType s_aaRxDataBuf[CAN_USED_NUM][CAN_RECEIVE_MB_NUM];
|
|
#define CAN_GET_BUFFER(index) s_aaRxDataBuf[index/2]
|
|
|
|
static const PCC_ClkSrcType s_ePccCanTable[] =
|
|
{
|
|
PCC_CLK_FLEXCAN0,
|
|
PCC_CLK_FLEXCAN1,
|
|
PCC_CLK_FLEXCAN2,
|
|
PCC_CLK_FLEXCAN3
|
|
};
|
|
|
|
static void BSP_CAN_INIT_CFG(FLEXCAN_InitType *pCfg) {
|
|
pCfg->bListenOnly = 0U;
|
|
pCfg->bEnBrs = 0;
|
|
pCfg->bEnDma = 0;
|
|
pCfg->bEnFd = 0;
|
|
pCfg->bEnRxFifo = 0;
|
|
pCfg->eBaudrate = FLEXCAN_BAUD_100K;
|
|
pCfg->eClkSrcHz = FLEXCAN_BAUDCLK_HZ_8M;
|
|
pCfg->eClkSrcSel = FLEXCAN_CLOCK_FUNCTION;
|
|
pCfg->eDataBaud = FLEXCAN_BAUD_100K;
|
|
pCfg->eMbDataWidth = FLEXCAN_DATAWIDTH_8;
|
|
pCfg->u8EnhancedFifoDmaWM = 0;
|
|
pCfg->eDirect = FLEXCAN_DIR_DISABLE;
|
|
}
|
|
|
|
static void BSP_CAN_INIT_MBConfig(FLEXCAN_MBConfigType *pMbCfg) {
|
|
pMbCfg->pRxFilterFifoList = NULL;
|
|
pMbCfg->u8RxFilterFifoCnt = 0;
|
|
pMbCfg->pRxFilterMBList = NULL;
|
|
pMbCfg->u8RxFilterMBCnt = 0;
|
|
pMbCfg->u8TxMsgCnt = 0;
|
|
pMbCfg->pRxBuf = NULL;
|
|
}
|
|
|
|
static void BSP_DMA_INIT_CFG(DMA_InitType *pDmaCfg) {
|
|
pDmaCfg->eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY;
|
|
pDmaCfg->bHaltOnError = false;
|
|
}
|
|
|
|
|
|
void CanSerialPortFrameSetId(tCanSerialPortFrameFlagchip *env, uint32_t id) {
|
|
env->id = id;
|
|
}
|
|
|
|
void CanSerialPortFrameSetType(tCanSerialPortFrameFlagchip *env, FLEXCAN_IdType canTypeFrame) {
|
|
env->canTypeFrame = canTypeFrame;
|
|
}
|
|
|
|
static void
|
|
vCanSerialPortFrameInitStructure(tCanSerialPortFrameFlagchip *env, uint16_t rxDataLength, uint16_t rxSnifferLength) {
|
|
|
|
env->rxDataQueue = osMessageQueueNew(rxDataLength, sizeof(can_rx_message_type), NULL);
|
|
if (rxSnifferLength) {
|
|
env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, sizeof(can_rx_message_type), NULL);
|
|
} else {
|
|
env->rxDataSnifferQueue = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
void vCanSerialPortFrameInit(
|
|
tCanSerialPortFrameFlagchip *env,
|
|
|
|
|
|
FLEXCAN_Type *CANx, // FLEXCAN0
|
|
PCC_ClkSrcType canClock, // PCC_CLK_FLEXCAN0
|
|
uint8 CAN_INDEX, // CAN0 = 0 ... CAN3 = 3
|
|
IRQn_Type IRQ_CAN, // FlexCAN0_IRQn ... FlexCAN3_IRQn
|
|
uint8 CAN_PRIORITY,
|
|
|
|
FLEXCAN_BaudType canBaudRate,
|
|
FLEXCAN_IdType canTypeFrame,
|
|
uint32_t canId,
|
|
FLEXCAN_ErrorInterruptCallBackType CAN_ErrorInterrupt_CallBack,
|
|
FLEXCAN_RxInterruptCallBackType CAN_RxInterrupt_CallBack,
|
|
FLEXCAN_RxInterruptCallBackType CAN_RxFifoInterrupt_CallBack,
|
|
FLEXCAN_TxInterruptCallBackType CAN_TxInterrupt_CallBack
|
|
|
|
) {
|
|
|
|
FLEXCAN_ErrorType tRetVal;
|
|
uint32_t u32FuncClk;
|
|
PCC_CtrlType bSP_PCC_Config;
|
|
|
|
env->can = CANx;
|
|
env->CAN_INDEX = CAN_INDEX;
|
|
|
|
bSP_PCC_Config.eClockName = canClock;
|
|
bSP_PCC_Config.bEn = TRUE;
|
|
bSP_PCC_Config.eClkSrc = PCC_CLKGATE_SRC_FOSCDIV;
|
|
bSP_PCC_Config.eDivider = PCC_CLK_DIV_BY1;
|
|
|
|
PCC_SetPcc(&bSP_PCC_Config);
|
|
|
|
|
|
BSP_CAN_INIT_CFG(&env->tInitCfg);
|
|
BSP_CAN_INIT_MBConfig(&env->tMbCfg);
|
|
|
|
env->tInitCfg.eBaudrate = canBaudRate;
|
|
env->tInitCfg.bEnRxFifo = TRUE;
|
|
env->tInitCfg.bEnDma = FALSE;
|
|
|
|
env->tInitCfg.bEnFd = FALSE;
|
|
env->tInitCfg.bEnBrs = FALSE;
|
|
env->tInitCfg.eMbDataWidth = FLEXCAN_DATAWIDTH_8;
|
|
|
|
u32FuncClk = PCC_GetPccFunctionClock(s_ePccCanTable[CAN_INDEX]);
|
|
|
|
env->tInitCfg.eClkSrcSel = FLEXCAN_CLOCK_FUNCTION; /* functional clock */
|
|
env->tInitCfg.eClkSrcHz = (FLEXCAN_BaudClkType) u32FuncClk; /* function clock frequency */
|
|
|
|
env->tInitCfg.eDirect = FLEXCAN_DIR_ENABLE_WITHOUT_TRIG;
|
|
|
|
|
|
tRetVal = FLEXCAN_Init(CAN_INDEX, &env->tInitCfg);
|
|
|
|
if (tRetVal == FLEXCAN_ERROR_OK) {
|
|
/* +++++++++++ can mb initial ++++++++++++ */
|
|
|
|
|
|
/* rx config */
|
|
/*
|
|
env->aRxFiltList[0].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->aRxFiltList[0].u32RxCanId = 0U;
|
|
env->aRxFiltList[0].u32RxCanIdMask = 0U;
|
|
|
|
env->aRxFiltList[1].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->aRxFiltList[1].u32RxCanId = 0U;
|
|
env->aRxFiltList[1].u32RxCanIdMask = 0U;
|
|
|
|
tMbCfg.pRxFilterMBList = env->aRxFiltList;
|
|
tMbCfg.u8RxFilterMBCnt = sizeof(env->aRxFiltList) / sizeof(env->aRxFiltList[0]);
|
|
*/
|
|
|
|
env->pRxFilterFifoList[0].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->pRxFilterFifoList[0].u32RxCanId = 0U;
|
|
env->pRxFilterFifoList[0].u32RxCanIdMask = 0U;
|
|
|
|
env->pRxFilterFifoList[1].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->pRxFilterFifoList[1].u32RxCanId = 0U;
|
|
env->pRxFilterFifoList[1].u32RxCanIdMask = 0U;
|
|
|
|
env->tMbCfg.pRxFilterMBList = env->pRxFilterFifoList;
|
|
env->tMbCfg.u8RxFilterMBCnt = sizeof(env->pRxFilterFifoList) / sizeof(env->pRxFilterFifoList[0]);
|
|
|
|
env->tMbCfg.pRxBuf = CAN_GET_BUFFER(CAN_INDEX);
|
|
|
|
/* tx config */
|
|
|
|
env->tMbCfg.u8TxMsgCnt = 3U; /* tx occupy 3 mb */
|
|
|
|
tRetVal = FLEXCAN_RxFilterConfig(CAN_INDEX, &env->tMbCfg);
|
|
|
|
if (CAN_ErrorInterrupt_CallBack == NULL) {
|
|
env->tIntCfg.bEnErrorInterrupt = 0U;
|
|
env->tIntCfg.pErrorNotify = NULL;
|
|
|
|
env->tIntCfg.bEnTxMBInterrupt = 0U;
|
|
env->tIntCfg.pRxMBNotify = NULL;
|
|
|
|
env->tIntCfg.bEnRxMBInterrupt = 0U;
|
|
env->tIntCfg.pRxFifoNotify = NULL;
|
|
|
|
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
|
env->tIntCfg.pTxMBNotify = NULL;
|
|
|
|
} else {
|
|
env->tIntCfg.bEnErrorInterrupt = 1U;
|
|
env->tIntCfg.pErrorNotify = CAN_ErrorInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnTxMBInterrupt = 1U;
|
|
env->tIntCfg.pRxMBNotify = CAN_RxInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnRxMBInterrupt = 1U;
|
|
env->tIntCfg.pRxFifoNotify = CAN_RxFifoInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnRxFifoInterrupt = 1U;
|
|
env->tIntCfg.pTxMBNotify = CAN_TxInterrupt_CallBack;
|
|
|
|
}
|
|
|
|
if ((env->tIntCfg.bEnErrorInterrupt) ||
|
|
(env->tIntCfg.bEnTxMBInterrupt) ||
|
|
(env->tIntCfg.bEnRxMBInterrupt) ||
|
|
(env->tIntCfg.bEnRxFifoInterrupt)) {
|
|
|
|
NVIC_SetPriority(IRQ_CAN, CAN_PRIORITY);
|
|
NVIC_EnableIRQ(IRQ_CAN);
|
|
|
|
FLEXCAN_SetInterrupt(CAN_INDEX, &env->tIntCfg);
|
|
}
|
|
|
|
FLEXCAN_Start(CAN_INDEX); /* Start CAN */
|
|
}
|
|
|
|
|
|
if (!env->reInit) {
|
|
env->reInit = true;
|
|
vCanSerialPortFrameInitStructure(env, 10, 0);
|
|
|
|
CanSerialPortFrameSetType(env, canTypeFrame);
|
|
CanSerialPortFrameSetId(env, canId);
|
|
|
|
env->canBaudRate = canBaudRate;
|
|
}
|
|
|
|
}
|
|
|
|
void vCanSerialPortFrameDMAInit(
|
|
tCanSerialPortFrameFlagchip *env,
|
|
|
|
FLEXCAN_Type *CANx, // FLEXCAN0
|
|
PCC_ClkSrcType canClock, // PCC_CLK_FLEXCAN0
|
|
uint8 CAN_INDEX, // CAN0 = 0 ... CAN3 = 3
|
|
|
|
IRQn_Type IRQ_CAN, // FlexCAN0_IRQn ... FlexCAN3_IRQn
|
|
uint8 CAN_PRIORITY,
|
|
|
|
DMA_ChannelType RX_DMA_CHANNEL,
|
|
DMA_RequestSourceType RX_DMA_CHANNEL_REQ, // DMA_REQ_FLEXCAN0
|
|
|
|
uint8_t *DMA_BUF,
|
|
|
|
IRQn_Type IRQ_DMA,
|
|
uint8_t IRQ_DMA_PRIORITY,
|
|
uint8_t IRQ_DMA_CHANNEL_PRIORITY,
|
|
|
|
FLEXCAN_BaudType canBaudRate,
|
|
FLEXCAN_IdType canTypeFrame,
|
|
uint32_t canId,
|
|
FLEXCAN_ErrorInterruptCallBackType CAN_ErrorInterrupt_CallBack,
|
|
FLEXCAN_RxInterruptCallBackType CAN_RxInterrupt_CallBack,
|
|
FLEXCAN_RxInterruptCallBackType CAN_RxFifoInterrupt_CallBack,
|
|
FLEXCAN_TxInterruptCallBackType CAN_TxInterrupt_CallBack,
|
|
|
|
DMA_TransferCompleteCallbackType DMA_TransferCompleteCallback,
|
|
DMA_TransferErrorCallbackType DMA_ErrorCallback
|
|
) {
|
|
|
|
|
|
FLEXCAN_ErrorType tRetVal;
|
|
uint32_t u32FuncClk;
|
|
PCC_CtrlType bSP_PCC_Config;
|
|
|
|
|
|
env->g_u32RxDataIndex = 0;
|
|
|
|
env->can = CANx;
|
|
env->CAN_INDEX = CAN_INDEX;
|
|
|
|
bSP_PCC_Config.eClockName = canClock;
|
|
bSP_PCC_Config.bEn = TRUE;
|
|
bSP_PCC_Config.eClkSrc = PCC_CLKGATE_SRC_FOSCDIV;
|
|
bSP_PCC_Config.eDivider = PCC_CLK_DIV_BY1;
|
|
|
|
PCC_SetPcc(&bSP_PCC_Config);
|
|
|
|
|
|
BSP_CAN_INIT_CFG(&env->tInitCfg);
|
|
BSP_CAN_INIT_MBConfig(&env->tMbCfg);
|
|
|
|
env->tInitCfg.eBaudrate = canBaudRate;
|
|
env->tInitCfg.bEnRxFifo = TRUE;
|
|
env->tInitCfg.bEnDma = TRUE;
|
|
|
|
env->tInitCfg.bEnFd = FALSE;
|
|
env->tInitCfg.bEnBrs = FALSE;
|
|
env->tInitCfg.eMbDataWidth = FLEXCAN_DATAWIDTH_8;
|
|
|
|
u32FuncClk = PCC_GetPccFunctionClock(s_ePccCanTable[CAN_INDEX]);
|
|
|
|
env->tInitCfg.eClkSrcSel = FLEXCAN_CLOCK_FUNCTION; /* functional clock */
|
|
env->tInitCfg.eClkSrcHz = (FLEXCAN_BaudClkType) u32FuncClk; /* function clock frequency */
|
|
|
|
env->tInitCfg.eDirect = FLEXCAN_DIR_ENABLE_WITHOUT_TRIG;
|
|
|
|
|
|
tRetVal = FLEXCAN_Init(CAN_INDEX, &env->tInitCfg);
|
|
|
|
if (tRetVal == FLEXCAN_ERROR_OK) {
|
|
/* +++++++++++ can mb initial ++++++++++++ */
|
|
|
|
env->pRxFilterFifoList[0].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->pRxFilterFifoList[0].u32RxCanId = 0U;
|
|
env->pRxFilterFifoList[0].u32RxCanIdMask = 0U;
|
|
|
|
env->pRxFilterFifoList[1].eRxFrameType = FLEXCAN_ID_STD;
|
|
env->pRxFilterFifoList[1].u32RxCanId = 0U;
|
|
env->pRxFilterFifoList[1].u32RxCanIdMask = 0U;
|
|
|
|
env->tMbCfg.pRxFilterMBList = env->pRxFilterFifoList;
|
|
env->tMbCfg.u8RxFilterMBCnt = sizeof(env->pRxFilterFifoList) / sizeof(env->pRxFilterFifoList[0]);
|
|
|
|
env->tMbCfg.pRxBuf = CAN_GET_BUFFER(CAN_INDEX);
|
|
|
|
/* tx config */
|
|
|
|
env->tMbCfg.u8TxMsgCnt = 3U; /* tx occupy 3 mb */
|
|
|
|
tRetVal = FLEXCAN_RxFilterConfig(CAN_INDEX, &env->tMbCfg);
|
|
|
|
if (CAN_ErrorInterrupt_CallBack == NULL) {
|
|
env->tIntCfg.bEnErrorInterrupt = 0U;
|
|
env->tIntCfg.pErrorNotify = NULL;
|
|
|
|
env->tIntCfg.bEnTxMBInterrupt = 0U;
|
|
env->tIntCfg.pRxMBNotify = NULL;
|
|
|
|
env->tIntCfg.bEnRxMBInterrupt = 0U;
|
|
env->tIntCfg.pRxFifoNotify = NULL;
|
|
|
|
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
|
env->tIntCfg.pTxMBNotify = NULL;
|
|
|
|
} else {
|
|
env->tIntCfg.bEnErrorInterrupt = 1U;
|
|
env->tIntCfg.pErrorNotify = CAN_ErrorInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnTxMBInterrupt = 1U;
|
|
env->tIntCfg.pRxMBNotify = CAN_RxInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnRxMBInterrupt = 1U;
|
|
env->tIntCfg.pRxFifoNotify = CAN_RxFifoInterrupt_CallBack;
|
|
|
|
env->tIntCfg.bEnRxFifoInterrupt = 1U;
|
|
env->tIntCfg.pTxMBNotify = CAN_TxInterrupt_CallBack;
|
|
|
|
}
|
|
|
|
|
|
DMA_InitType dmaInitCfg;
|
|
BSP_DMA_INIT_CFG(&dmaInitCfg);
|
|
|
|
DMA_ChannelCfgType chnCfg = {0};
|
|
|
|
DMA_InterruptCfgType interruptCfg = {0};
|
|
uint32_t u32TargetAddr;
|
|
|
|
dmaInitCfg.eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY;
|
|
dmaInitCfg.bHaltOnError = false;
|
|
|
|
DMA_Init(DMA_INSTANCE_0, &dmaInitCfg);
|
|
|
|
u32TargetAddr = (uint32_t) (DMA_BUF);
|
|
|
|
chnCfg.pSrcBuffer = &(CANx->RAM[0]);
|
|
chnCfg.pDestBuffer = (void *) (u32TargetAddr);
|
|
chnCfg.u32BlockSize = 16U;
|
|
chnCfg.u16BlockCount = 1U;
|
|
chnCfg.u8ChannelPriority = IRQ_DMA_CHANNEL_PRIORITY;
|
|
chnCfg.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
|
|
chnCfg.eDestDataSize = DMA_TRANSFER_SIZE_4B;
|
|
chnCfg.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
|
|
chnCfg.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
|
|
chnCfg.bSrcBlockOffsetEn = 0U;
|
|
chnCfg.bDestBlockOffsetEn = 0U;
|
|
chnCfg.s32BlockOffset = 0;
|
|
chnCfg.bSrcAddrLoopbackEn = 1U;
|
|
chnCfg.bDestAddrLoopbackEn = false;
|
|
chnCfg.bAutoStop = 0U;
|
|
chnCfg.bSrcCircularBufferEn = false;
|
|
chnCfg.u32SrcCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;
|
|
chnCfg.bDestCircularBufferEn = true;
|
|
chnCfg.u32DestCircBufferSize = 256U;
|
|
chnCfg.eTriggerSrc = RX_DMA_CHANNEL_REQ;
|
|
DMA_InitChannel(DMA_INSTANCE_0, (DMA_ChannelType) RX_DMA_CHANNEL, &chnCfg);
|
|
|
|
interruptCfg.bTransferCompleteIntEn = 1;
|
|
interruptCfg.pTransferCompleteNotify = DMA_TransferCompleteCallback;
|
|
interruptCfg.bTransferErrorIntEn = 1;
|
|
interruptCfg.pTransferErrorNotify = DMA_ErrorCallback;
|
|
|
|
DMA_InitChannelInterrupt(DMA_INSTANCE_0, (DMA_ChannelType) RX_DMA_CHANNEL, &interruptCfg);
|
|
|
|
NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUP_4);
|
|
|
|
|
|
NVIC_SetPriority(DMA_Error_IRQn, IRQ_DMA_PRIORITY);
|
|
NVIC_SetPriority(IRQ_DMA, IRQ_DMA_PRIORITY);
|
|
NVIC_EnableIRQ(IRQ_DMA);
|
|
|
|
DMA_StartChannel(DMA_INSTANCE_0, (DMA_ChannelType) RX_DMA_CHANNEL);
|
|
|
|
if ((env->tIntCfg.bEnErrorInterrupt) ||
|
|
(env->tIntCfg.bEnTxMBInterrupt) ||
|
|
(env->tIntCfg.bEnRxMBInterrupt) ||
|
|
(env->tIntCfg.bEnRxFifoInterrupt)) {
|
|
|
|
NVIC_SetPriority(IRQ_CAN, CAN_PRIORITY);
|
|
NVIC_EnableIRQ(IRQ_CAN);
|
|
|
|
FLEXCAN_SetInterrupt(CAN_INDEX, &env->tIntCfg);
|
|
|
|
}
|
|
|
|
FLEXCAN_Start(CAN_INDEX); /* Start CAN */
|
|
}
|
|
|
|
|
|
if (!env->reInit) {
|
|
env->reInit = true;
|
|
vCanSerialPortFrameInitStructure(env, 10, 0);
|
|
|
|
CanSerialPortFrameSetType(env, canTypeFrame);
|
|
CanSerialPortFrameSetId(env, canId);
|
|
|
|
env->canBaudRate = canBaudRate;
|
|
}
|
|
|
|
}
|
|
|
|
void CanSerialPortFrameIrqRxProcessing(tCanSerialPortFrameFlagchip *env, uint32_t *pBuf) {
|
|
can_rx_message_type rx_message_struct;
|
|
|
|
uint32_t u32TempAddr = (uint32_t) FLEXCAN_MB_WORDN_ADDR(pBuf, 0U, 8U, 0U);
|
|
|
|
uint32_t dlc = FLEXCAN_MB_DLC_GET(u32TempAddr);
|
|
rx_message_struct.dlc = FLEXCAN_DlcToDataLen(dlc);
|
|
|
|
rx_message_struct.id_type = FLEXCAN_MB_IDE_GET(u32TempAddr);
|
|
|
|
|
|
if (rx_message_struct.id_type == FLEXCAN_ID_STD) {
|
|
rx_message_struct.standard_id = FLEXCAN_MB_STDID_GET(u32TempAddr);
|
|
} else {
|
|
rx_message_struct.extended_id = FLEXCAN_MB_EXTID_GET(u32TempAddr);
|
|
}
|
|
|
|
uint32_t *pSrc = (uint32_t *) FLEXCAN_MB_WORDN_ADDR(pBuf, 0U, 8U, 8U);
|
|
uint32_t *pDest = (uint32_t *) &rx_message_struct.data[0];
|
|
|
|
uint32_t u32WordLen = rx_message_struct.dlc / 4U + (rx_message_struct.dlc % 4U > 0U ? 1U : 0U);
|
|
|
|
for (uint8_t u8Index = 0U; u8Index < u32WordLen; ++u8Index) {
|
|
REV_BYTES_32(pSrc[u8Index], pDest[u8Index]);
|
|
}
|
|
|
|
rx_message_struct.filter_index = 0xFF;
|
|
|
|
for (uint8_t i = 0; i < COUNT_QUEUE; ++i) {
|
|
|
|
if ((rx_message_struct.id_type == FLEXCAN_ID_STD) &&
|
|
(env->pRxFilterFifoList[i].eRxFrameType == FLEXCAN_ID_STD)) {
|
|
|
|
if (rx_message_struct.standard_id == env->pRxFilterFifoList[i].u32RxCanId) {
|
|
rx_message_struct.filter_index = i;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (rx_message_struct.extended_id == env->pRxFilterFifoList[i].u32RxCanId) {
|
|
rx_message_struct.filter_index = i;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
osMessageQueuePut(env->rxDataQueue, &rx_message_struct, 0x0, 0U);
|
|
|
|
if (env->rxDataSnifferQueue) {
|
|
osMessageQueuePut(env->rxDataSnifferQueue, &rx_message_struct, 0x0, 0U);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void CAN_RxInterrupt_CallBack_Handler(tCanSerialPortFrameFlagchip *env, uint8_t u8CanIndex, FLEXCAN_RxMsgType *pRxCfg) {
|
|
|
|
can_rx_message_type rx_message_struct;
|
|
|
|
rx_message_struct.standard_id = pRxCfg->u32CanId;
|
|
rx_message_struct.dlc = pRxCfg->u32DataLen;
|
|
memcpy(rx_message_struct.data, pRxCfg->aData, rx_message_struct.dlc);
|
|
|
|
osMessageQueuePut(env->rxDataQueue, &rx_message_struct, 0x0, 0U);
|
|
|
|
if (env->rxDataSnifferQueue) {
|
|
osMessageQueuePut(env->rxDataSnifferQueue, &rx_message_struct, 0x0, 0U);
|
|
}
|
|
|
|
}
|
|
|
|
static uint16_t vSerialPortFrameReceiveQueue(
|
|
tCanSerialPortFrameFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout, osMessageQueueId_t queueId
|
|
) {
|
|
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
|
|
vCanSerialPortFrameReceive(tCanSerialPortFrameFlagchip *env, uint8_t *data, uint16_t size,
|
|
uint32_t timeout) {
|
|
return vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataQueue);
|
|
}
|
|
|
|
static uint16_t
|
|
vCanSerialPortFrameReceiveSniffer(tCanSerialPortFrameFlagchip *env, uint8_t *data, uint16_t size,
|
|
uint32_t timeout) {
|
|
|
|
return env->rxDataSnifferQueue
|
|
? vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue)
|
|
: 0;
|
|
}
|
|
|
|
uint16_t vCanSerialPortFrameTransmit(tCanSerialPortFrameFlagchip *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
|
|
uint16_t fullSize = size / 8;
|
|
uint8_t tailSize = size % 8;
|
|
uint16_t sent = 0;
|
|
|
|
FLEXCAN_TxMsgType tTxMsg = {0};
|
|
FLEXCAN_ErrorType tRetval;
|
|
|
|
tTxMsg.u32CanId = env->id;
|
|
tTxMsg.u8TxHandler = 0U;
|
|
|
|
tTxMsg.bEnFd = FALSE;
|
|
tTxMsg.bEnBrs = FALSE;
|
|
tTxMsg.u32DataLen = 8;
|
|
|
|
tTxMsg.eDataType = FLEXCAN_FRAME_DATA;
|
|
tTxMsg.eFrameType = (FLEXCAN_IdType) env->canTypeFrame;
|
|
tTxMsg.bWaitTxCompleted = 1U;
|
|
tTxMsg.u16WaitTxTimeout = 10000U;
|
|
|
|
|
|
uint16_t len = 0;
|
|
for (uint16_t i = 0; i < fullSize; ++i) {
|
|
|
|
FCFUNC_FcOwnMemcpy(tTxMsg.aData, &data[len], fullSize, NULL);
|
|
len += 8;
|
|
|
|
tRetval = FLEXCAN_TransmitData(env->CAN_INDEX, &tTxMsg);
|
|
if (tRetval != FLEXCAN_ERROR_OK) {
|
|
FLEXCAN_TransmitAbort(env->CAN_INDEX, tTxMsg.u8TxHandler);
|
|
} else {
|
|
FLEXCAN_TransmitProcess(env->CAN_INDEX, tTxMsg.u8TxHandler);
|
|
}
|
|
|
|
sent += 8;
|
|
size -= 8;
|
|
}
|
|
|
|
if (tailSize) {
|
|
tTxMsg.u32DataLen = tailSize;
|
|
|
|
FCFUNC_FcOwnMemcpy(tTxMsg.aData, &data[len], tailSize, NULL);
|
|
|
|
tRetval = FLEXCAN_TransmitData(env->CAN_INDEX, &tTxMsg);
|
|
if (tRetval != FLEXCAN_ERROR_OK) {
|
|
FLEXCAN_TransmitAbort(env->CAN_INDEX, tTxMsg.u8TxHandler);
|
|
} else {
|
|
FLEXCAN_TransmitProcess(env->CAN_INDEX, tTxMsg.u8TxHandler);
|
|
}
|
|
|
|
sent += tailSize;
|
|
size -= tailSize;
|
|
}
|
|
|
|
return sent;
|
|
}
|
|
|
|
|
|
tSerialPortFrameIO CanPortFrame_GetIo(tCanSerialPortFrameFlagchip *env) {
|
|
tSerialPortFrameIO io = {
|
|
.env = env,
|
|
.receive = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceive,
|
|
.transmit = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit,
|
|
};
|
|
return io;
|
|
}
|
|
|
|
tSerialPortFrameIO CanPort_GetSnifferIo(tCanSerialPortFrameFlagchip *env) {
|
|
tSerialPortFrameIO io = {
|
|
.env = env,
|
|
.receive = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceiveSniffer,
|
|
.transmit = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit,
|
|
};
|
|
return io;
|
|
} |