790 lines
28 KiB
C
790 lines
28 KiB
C
//
|
||
// Created by cfif on 16.03.2024.
|
||
//
|
||
#include <SystemDelayInterface.h>
|
||
#include "CanSerialPortFrame.h"
|
||
#include "memory.h"
|
||
#include "candb.h"
|
||
#include "CanPorts.h"
|
||
|
||
#define CAN_USED_NUM 2U // Количество CAN
|
||
#define CAN_RECEIVE_MB_NUM 128 // Количество mailbox на один CAN
|
||
|
||
static FLEXCAN_RxMsgType s_aaRxDataBuf[CAN_USED_NUM][CAN_RECEIVE_MB_NUM];
|
||
|
||
#define CAN_GET_BUFFER(index) (FLEXCAN_RxMsgType*)s_aaRxDataBuf[index]
|
||
|
||
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;
|
||
}
|
||
|
||
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) {
|
||
|
||
for (uint8_t i = 0; i < COUNT_QUEUE; ++i) {
|
||
env->rxDataQueue[i] = osMessageQueueNew(rxDataLength, sizeof(can_rx_message_type), NULL);
|
||
if (rxSnifferLength) {
|
||
env->rxDataSnifferQueue[i] = osMessageQueueNew(rxSnifferLength, sizeof(can_rx_message_type), NULL);
|
||
} else {
|
||
env->rxDataSnifferQueue[i] = NULL;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
bool vCanSerialPortFrameDMAInit(
|
||
tCanSerialPortFrameFlagchip *env,
|
||
FLEXCAN_Type *CANx, // FLEXCAN0
|
||
uint8 CAN_INDEX, // CAN0 = 0 ... CAN3 = 3
|
||
IRQn_Type IRQ_CAN, // FlexCAN0_IRQn ... FlexCAN3_IRQn
|
||
uint8 CAN_PRIORITY,
|
||
|
||
DMA_ChannelType DMA_CHANNEL_RX,
|
||
DMA_RequestSourceType DMA_CHANNEL_REQ_RX, // DMA_REQ_FLEXCAN0
|
||
const uint8_t *DMA_BUF_RX,
|
||
uint8_t DMA_BUF_LEN_RX,
|
||
|
||
const FilterTo_FLEXCAN_RxMbFilterType *IdHardSoftFilter_RX,
|
||
uint8_t CountHardSoftFilter_RX,
|
||
|
||
const FLEXCAN_RxMbFilterType *IdFilterFifo_RX,
|
||
uint8_t CountFilterFifo_RX,
|
||
|
||
IRQn_Type IRQ_DMA_RX,
|
||
uint8_t IRQ_DMA_PRIORITY_RX,
|
||
uint8_t IRQ_DMA_CHANNEL_PRIORITY_RX,
|
||
|
||
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
|
||
) {
|
||
env->g_u32RxDataIndex = 0;
|
||
env->can = CANx;
|
||
env->CAN_INDEX = CAN_INDEX;
|
||
env->DMA_BUF_LEN_RX = DMA_BUF_LEN_RX;
|
||
env->IdHardSoftFilter_RX = (FilterTo_FLEXCAN_RxMbFilterType *) IdHardSoftFilter_RX;
|
||
env->CountHardSoftFilter_RX = CountHardSoftFilter_RX;
|
||
env->canBaudRate = canBaudRate;
|
||
env->IRQ_CAN = IRQ_CAN;
|
||
|
||
env->CAN_ErrorInterrupt_CallBack = CAN_ErrorInterrupt_CallBack;
|
||
env->CAN_RxInterrupt_CallBack = CAN_RxInterrupt_CallBack;
|
||
env->CAN_RxFifoInterrupt_CallBack = CAN_RxFifoInterrupt_CallBack;
|
||
env->CAN_TxInterrupt_CallBack = CAN_TxInterrupt_CallBack;
|
||
env->DMA_TransferCompleteCallback = DMA_TransferCompleteCallback;
|
||
env->DMA_ErrorCallback = DMA_ErrorCallback;
|
||
|
||
|
||
|
||
env->access = osMutexNew(NULL);
|
||
|
||
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
||
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
||
//начало-----------------------------------DMA-RX-------------------------------------------------------------------
|
||
|
||
uint32_t u32TargetAddr = (uint32_t) (DMA_BUF_RX);
|
||
|
||
env->chnCfg_RX.pSrcBuffer = &(CANx->RAM[0]);
|
||
env->chnCfg_RX.pDestBuffer = (void *) (u32TargetAddr);
|
||
env->chnCfg_RX.u32BlockSize = DMA_BUF_LEN_RX;
|
||
env->chnCfg_RX.u16BlockCount = 1U;
|
||
env->chnCfg_RX.u8ChannelPriority = IRQ_DMA_CHANNEL_PRIORITY_RX;
|
||
env->chnCfg_RX.eSrcDataSize = DMA_TRANSFER_SIZE_4B;
|
||
env->chnCfg_RX.eDestDataSize = DMA_TRANSFER_SIZE_4B;
|
||
env->chnCfg_RX.eSrcIncMode = DMA_INCREMENT_DATA_SIZE;
|
||
env->chnCfg_RX.eDestIncMode = DMA_INCREMENT_DATA_SIZE;
|
||
env->chnCfg_RX.bSrcBlockOffsetEn = 0U;
|
||
env->chnCfg_RX.bDestBlockOffsetEn = 0U;
|
||
env->chnCfg_RX.s32BlockOffset = 0;
|
||
env->chnCfg_RX.bSrcAddrLoopbackEn = 1U;
|
||
env->chnCfg_RX.bDestAddrLoopbackEn = false;
|
||
env->chnCfg_RX.bAutoStop = 0U;
|
||
env->chnCfg_RX.bSrcCircularBufferEn = false;
|
||
env->chnCfg_RX.u32SrcCircBufferSize = DMA_CIRCULAR_BUFFER_SIZE_1B;
|
||
env->chnCfg_RX.bDestCircularBufferEn = true;
|
||
env->chnCfg_RX.u32DestCircBufferSize = 256U;
|
||
env->chnCfg_RX.eTriggerSrc = DMA_CHANNEL_REQ_RX;
|
||
DMA_InitChannel(DMA_INSTANCE_0, (DMA_ChannelType) DMA_CHANNEL_RX, &env->chnCfg_RX);
|
||
|
||
env->interruptCfg_RX.bTransferCompleteIntEn = 1;
|
||
env->interruptCfg_RX.pTransferCompleteNotify = DMA_TransferCompleteCallback;
|
||
env->interruptCfg_RX.bTransferErrorIntEn = 1;
|
||
env->interruptCfg_RX.pTransferErrorNotify = DMA_ErrorCallback;
|
||
|
||
DMA_InitChannelInterrupt(DMA_INSTANCE_0, (DMA_ChannelType) DMA_CHANNEL_RX, &env->interruptCfg_RX);
|
||
|
||
NVIC_SetPriority(IRQ_DMA_RX, IRQ_DMA_PRIORITY_RX);
|
||
NVIC_EnableIRQ(IRQ_DMA_RX);
|
||
|
||
DMA_StartChannel(DMA_INSTANCE_0, (DMA_ChannelType) DMA_CHANNEL_RX);
|
||
|
||
|
||
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
||
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
||
//конец-----------------------------------DMA-RX--------------------------------------------------------------------
|
||
|
||
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
|
||
FLEXCAN_ErrorType tRetVal;
|
||
uint32_t u32FuncClk;
|
||
|
||
tRetVal = FLEXCAN_DeInit(CAN_INDEX);
|
||
|
||
BSP_CAN_INIT_CFG(&env->tInitCfg);
|
||
BSP_CAN_INIT_MBConfig(&env->tMbCfg);
|
||
|
||
env->tInitCfg.eBaudrate = canBaudRate;
|
||
env->tInitCfg.eDataBaud = canBaudRate;
|
||
env->tInitCfg.bEnRxFifo = TRUE;
|
||
// env->tInitCfg.bEnRxFifo = FALSE;
|
||
|
||
env->tInitCfg.bEnDma = 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) {
|
||
|
||
|
||
env->tMbCfg.pRxFilterMBList = NULL;
|
||
env->tMbCfg.u8RxFilterMBCnt = 0;
|
||
|
||
for (uint8_t i = 0; i < CountFilterFifo_RX; ++i) {
|
||
env->pRxFilterFifoList[i].eRxFrameType = IdFilterFifo_RX[i].eRxFrameType;
|
||
env->pRxFilterFifoList[i].u32RxCanId = IdFilterFifo_RX[i].u32RxCanId;
|
||
env->pRxFilterFifoList[i].u32RxCanIdMask = IdFilterFifo_RX[i].u32RxCanIdMask;
|
||
}
|
||
|
||
env->tMbCfg.pRxFilterFifoList = env->pRxFilterFifoList;
|
||
env->tMbCfg.u8RxFilterFifoCnt = CountFilterFifo_RX;
|
||
|
||
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.pTxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxMBInterrupt = 0U;
|
||
env->tIntCfg.pRxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
||
env->tIntCfg.pRxFifoNotify = NULL;
|
||
|
||
} else {
|
||
env->tIntCfg.bEnErrorInterrupt = 1U;
|
||
env->tIntCfg.pErrorNotify = CAN_ErrorInterrupt_CallBack;
|
||
|
||
env->tIntCfg.bEnTxMBInterrupt = 0U;
|
||
env->tIntCfg.pTxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxMBInterrupt = 1U;
|
||
env->tIntCfg.pRxMBNotify = CAN_RxInterrupt_CallBack;
|
||
|
||
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
||
env->tIntCfg.pRxFifoNotify = CAN_RxFifoInterrupt_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);
|
||
|
||
}
|
||
|
||
if (!env->reInit) {
|
||
env->reInit = true;
|
||
vCanSerialPortFrameInitStructure(env, 10, 0);
|
||
|
||
CanSerialPortFrameSetType(env, canTypeFrame);
|
||
CanSerialPortFrameSetId(env, canId);
|
||
|
||
env->canBaudRate = canBaudRate;
|
||
}
|
||
|
||
FLEXCAN_Start(CAN_INDEX); // Start CAN
|
||
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
|
||
return true;
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
}
|
||
|
||
|
||
bool vCanSerialPortFrameMbInit(
|
||
tCanSerialPortFrameFlagchip *env,
|
||
FLEXCAN_Type *CANx, // FLEXCAN0
|
||
uint8 CAN_INDEX, // CAN0 = 0 ... CAN3 = 3
|
||
IRQn_Type IRQ_CAN, // FlexCAN0_IRQn ... FlexCAN3_IRQn
|
||
uint8 CAN_PRIORITY,
|
||
|
||
const FilterTo_FLEXCAN_RxMbFilterType *IdHardSoftFilter_RX,
|
||
uint8_t CountHardSoftFilter_RX,
|
||
|
||
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
|
||
|
||
) {
|
||
env->g_u32RxDataIndex = 0;
|
||
env->can = CANx;
|
||
env->CAN_INDEX = CAN_INDEX;
|
||
// env->DMA_BUF_LEN_RX = DMA_BUF_LEN_RX;
|
||
env->IdHardSoftFilter_RX = (FilterTo_FLEXCAN_RxMbFilterType *) IdHardSoftFilter_RX;
|
||
env->CountHardSoftFilter_RX = CountHardSoftFilter_RX;
|
||
env->canBaudRate = canBaudRate;
|
||
env->IRQ_CAN = IRQ_CAN;
|
||
|
||
env->CAN_ErrorInterrupt_CallBack = CAN_ErrorInterrupt_CallBack;
|
||
env->CAN_RxInterrupt_CallBack = CAN_RxInterrupt_CallBack;
|
||
env->CAN_RxFifoInterrupt_CallBack = CAN_RxFifoInterrupt_CallBack;
|
||
env->CAN_TxInterrupt_CallBack = CAN_TxInterrupt_CallBack;
|
||
// env->DMA_TransferCompleteCallback = DMA_TransferCompleteCallback;
|
||
// env->DMA_ErrorCallback = DMA_ErrorCallback;
|
||
|
||
env->access = osMutexNew(NULL);
|
||
|
||
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
//начало------------------------------------CAN---------------------------------------------------------------------
|
||
|
||
FLEXCAN_ErrorType tRetVal;
|
||
uint32_t u32FuncClk;
|
||
|
||
tRetVal = FLEXCAN_DeInit(CAN_INDEX);
|
||
|
||
BSP_CAN_INIT_CFG(&env->tInitCfg);
|
||
BSP_CAN_INIT_MBConfig(&env->tMbCfg);
|
||
|
||
env->tInitCfg.eBaudrate = canBaudRate;
|
||
env->tInitCfg.eDataBaud = canBaudRate;
|
||
// env->tInitCfg.bEnRxFifo = TRUE;
|
||
env->tInitCfg.bEnRxFifo = FALSE;
|
||
|
||
// env->tInitCfg.bEnDma = 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
|
||
|
||
tRetVal = FLEXCAN_Init(CAN_INDEX, &env->tInitCfg);
|
||
|
||
if (tRetVal == FLEXCAN_ERROR_OK) {
|
||
|
||
for (uint8_t i = 0; i < CountHardSoftFilter_RX; ++i) {
|
||
env->pRxMbFilterList[i].eRxFrameType = IdHardSoftFilter_RX[i].eRxFrameType;
|
||
env->pRxMbFilterList[i].u32RxCanId = IdHardSoftFilter_RX[i].u32RxCanId;
|
||
env->pRxMbFilterList[i].u32RxCanIdMask = IdHardSoftFilter_RX[i].u32RxCanIdMask;
|
||
}
|
||
|
||
env->tMbCfg.pRxFilterMBList = env->pRxMbFilterList;
|
||
env->tMbCfg.u8RxFilterMBCnt = CountHardSoftFilter_RX;
|
||
|
||
env->tMbCfg.pRxFilterFifoList = NULL;
|
||
env->tMbCfg.u8RxFilterFifoCnt = 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.pTxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxMBInterrupt = 0U;
|
||
env->tIntCfg.pRxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
||
env->tIntCfg.pRxFifoNotify = NULL;
|
||
|
||
} else {
|
||
env->tIntCfg.bEnErrorInterrupt = 1U;
|
||
env->tIntCfg.pErrorNotify = CAN_ErrorInterrupt_CallBack;
|
||
|
||
env->tIntCfg.bEnTxMBInterrupt = 0U;
|
||
env->tIntCfg.pTxMBNotify = NULL;
|
||
|
||
env->tIntCfg.bEnRxMBInterrupt = 1U;
|
||
env->tIntCfg.pRxMBNotify = CAN_RxInterrupt_CallBack;
|
||
|
||
env->tIntCfg.bEnRxFifoInterrupt = 0U;
|
||
env->tIntCfg.pRxFifoNotify = CAN_RxFifoInterrupt_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);
|
||
|
||
}
|
||
|
||
if (!env->reInit) {
|
||
env->reInit = true;
|
||
vCanSerialPortFrameInitStructure(env, 10, 0);
|
||
|
||
CanSerialPortFrameSetType(env, canTypeFrame);
|
||
CanSerialPortFrameSetId(env, canId);
|
||
|
||
env->canBaudRate = canBaudRate;
|
||
}
|
||
|
||
FLEXCAN_Start(CAN_INDEX); // Start CAN
|
||
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
|
||
return true;
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
//конец------------------------------------CAN----------------------------------------------------------------------
|
||
}
|
||
|
||
|
||
bool vCanSerialPortSetMaskCount(tCanSerialPortFrameFlagchip *env, uint8_t maskCount)
|
||
{
|
||
FLEXCAN_ErrorType tRetVal;
|
||
uint8_t i;
|
||
|
||
|
||
// Отключаем прерывания CAN
|
||
NVIC_DisableIRQ(env->IRQ_CAN);
|
||
|
||
// Останавливаем CAN модуль (переводим в режим заморозки)
|
||
tRetVal = FLEXCAN_Stop(env->CAN_INDEX);
|
||
if (tRetVal != FLEXCAN_ERROR_OK) {
|
||
NVIC_EnableIRQ(env->IRQ_CAN);
|
||
return false;
|
||
}
|
||
|
||
// Обновляем список фильтров в рабочем буфере (первые maskCount элементов)
|
||
for (i = 0; i < maskCount; i++) {
|
||
env->pRxMbFilterList[i].eRxFrameType = env->IdHardSoftFilter_RX[i].eRxFrameType;
|
||
env->pRxMbFilterList[i].u32RxCanId = env->IdHardSoftFilter_RX[i].u32RxCanId;
|
||
env->pRxMbFilterList[i].u32RxCanIdMask = env->IdHardSoftFilter_RX[i].u32RxCanIdMask;
|
||
}
|
||
|
||
for (i = maskCount; i < 32; i++) {
|
||
env->pRxMbFilterList[i].eRxFrameType = env->IdHardSoftFilter_RX[0].eRxFrameType;
|
||
env->pRxMbFilterList[i].u32RxCanId = env->IdHardSoftFilter_RX[0].u32RxCanId;
|
||
env->pRxMbFilterList[i].u32RxCanIdMask = env->IdHardSoftFilter_RX[0].u32RxCanIdMask;
|
||
}
|
||
|
||
|
||
// Обновляем конфигурационную структуру для драйвера
|
||
// env->CountHardSoftFilter_RX = maskCount;
|
||
env->tMbCfg.pRxFilterMBList = env->pRxMbFilterList;
|
||
// env->tMbCfg.u8RxFilterMBCnt = maskCount;
|
||
|
||
// Убеждаемся, что в tMbCfg сохранены правильные настройки TX
|
||
// (они были установлены при инициализации и не должны измениться)
|
||
// Если нужно, можно перечитать их из глобальной таблицы драйвера
|
||
// но обычно они уже корректны.
|
||
|
||
// Переконфигурируем фильтры (без полной деинициализации CAN)
|
||
tRetVal = FLEXCAN_RxFilterConfig(env->CAN_INDEX, &env->tMbCfg);
|
||
|
||
if (tRetVal != FLEXCAN_ERROR_OK) {
|
||
// В случае ошибки пытаемся восстановить предыдущее состояние
|
||
// (можно также попробовать перечитать старые фильтры)
|
||
FLEXCAN_Start(env->CAN_INDEX);
|
||
NVIC_EnableIRQ(env->IRQ_CAN);
|
||
return false;
|
||
}
|
||
|
||
// Запускаем CAN снова (выход из режима заморозки)
|
||
tRetVal = FLEXCAN_Start(env->CAN_INDEX);
|
||
if (tRetVal != FLEXCAN_ERROR_OK) {
|
||
NVIC_EnableIRQ(env->IRQ_CAN);
|
||
return false;
|
||
}
|
||
|
||
// Включаем прерывания обратно
|
||
NVIC_EnableIRQ(env->IRQ_CAN);
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
static void CanSerialPortFrameAddDataQueue(tCanSerialPortFrameFlagchip *env, can_rx_message_type *rx_message_struct,
|
||
uint8_t filter) {
|
||
osStatus_t status = osMessageQueuePut(env->rxDataQueue[filter], rx_message_struct, 0x0, 0U);
|
||
|
||
if (status != osOK) {
|
||
asm("nop");
|
||
}
|
||
|
||
if (env->rxDataSnifferQueue[filter]) {
|
||
status = osMessageQueuePut(env->rxDataSnifferQueue[filter], rx_message_struct, 0x0, 0U);
|
||
}
|
||
}
|
||
|
||
|
||
void CanSerialPortFrameIrqRxProcessingNO_DMA(tCanSerialPortFrameFlagchip *env, FLEXCAN_RxMsgType *pRxCfg) {
|
||
if (pRxCfg->eDataType != FLEXCAN_FRAME_DATA) {
|
||
return; // Ранний выход
|
||
}
|
||
|
||
// Копируем основные данные один раз
|
||
const uint32_t rx_id = pRxCfg->u32CanId;
|
||
const uint8_t dlc = pRxCfg->u32DataLen;
|
||
const FLEXCAN_IdType id_type = pRxCfg->eFrameType;
|
||
|
||
// Заполняем структуру
|
||
can_rx_message_type *pMsg = &env->rx_message_struct;
|
||
pMsg->dlc = dlc;
|
||
pMsg->id_type = id_type;
|
||
|
||
if (id_type == FLEXCAN_ID_STD) {
|
||
pMsg->standard_id = rx_id;
|
||
} else {
|
||
pMsg->extended_id = rx_id;
|
||
}
|
||
|
||
// Быстрый поиск по ID (можно использовать switch или бинарный поиск)
|
||
uint8_t filter_index = 0xFF;
|
||
const uint8_t count = env->CountHardSoftFilter_RX;
|
||
|
||
// Линейный поиск ID
|
||
for (uint8_t i = 0; i < count; i++) {
|
||
if (rx_id == env->IdHardSoftFilter_RX[i].u32RxCanId) {
|
||
filter_index = env->IdHardSoftFilter_RX[i].filter;
|
||
pMsg->filter_index = filter_index;
|
||
|
||
if (i> 2) {
|
||
asm("nop");
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Если ID найден или фильтров нет
|
||
if (filter_index != 0xFF || count == 0) {
|
||
memcpy(pMsg->data, pRxCfg->aData, dlc);
|
||
CanSerialPortFrameAddDataQueue(env, pMsg, filter_index != 0xFF ? filter_index : 0);
|
||
}
|
||
}
|
||
|
||
|
||
void CanSerialPortFrameIrqRxProcessing(tCanSerialPortFrameFlagchip *env, uint32_t *pBuf) {
|
||
|
||
// message buffer 1th word
|
||
uint32_t u32TempAddr = (uint32_t) FLEXCAN_MB_WORDN_ADDR(&pBuf[env->pBufCounter << 2], 0U, 8U, 0U);
|
||
|
||
uint32_t dlc = FLEXCAN_MB_DLC_GET(u32TempAddr);
|
||
env->rx_message_struct.dlc = FLEXCAN_DlcToDataLen(dlc);
|
||
|
||
env->rx_message_struct.id_type = FLEXCAN_MB_IDE_GET(u32TempAddr);
|
||
|
||
// message buffer 2th word
|
||
u32TempAddr = (uint32_t) FLEXCAN_MB_WORDN_ADDR(&pBuf[env->pBufCounter << 2], 0U, 8U, 4U);
|
||
|
||
if (env->rx_message_struct.id_type == FLEXCAN_ID_STD) {
|
||
env->rx_message_struct.standard_id = FLEXCAN_MB_STDID_GET(u32TempAddr);
|
||
} else {
|
||
env->rx_message_struct.extended_id = FLEXCAN_MB_EXTID_GET(u32TempAddr);
|
||
}
|
||
|
||
uint8_t index = 0xFF;
|
||
|
||
for (uint8_t i = 0; i < env->CountHardSoftFilter_RX; ++i) {
|
||
|
||
if ((env->rx_message_struct.id_type == FLEXCAN_ID_STD) &&
|
||
(env->IdHardSoftFilter_RX[i].eRxFrameType == FLEXCAN_ID_STD)) {
|
||
|
||
if (env->rx_message_struct.standard_id == env->IdHardSoftFilter_RX[i].u32RxCanId) {
|
||
env->rx_message_struct.filter_index = env->IdHardSoftFilter_RX[i].filter;
|
||
index = i;
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
|
||
if (env->rx_message_struct.extended_id == env->IdHardSoftFilter_RX[i].u32RxCanId) {
|
||
|
||
if (env->rx_message_struct.extended_id == env->IdHardSoftFilter_RX[i].u32RxCanId) {
|
||
env->rx_message_struct.filter_index = env->IdHardSoftFilter_RX[i].filter;
|
||
index = i;
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
if (index != 0xFF) {
|
||
|
||
// message buffer 3th word
|
||
uint32_t *pSrc = (uint32_t *) FLEXCAN_MB_WORDN_ADDR(&pBuf[env->pBufCounter << 2], 0U, 8U, 8U);
|
||
uint32_t *pDest = (uint32_t *) &env->rx_message_struct.data[0];
|
||
|
||
uint32_t u32WordLen = env->rx_message_struct.dlc / 4U + (env->rx_message_struct.dlc % 4U > 0U ? 1U : 0U);
|
||
|
||
for (uint32_t u8Index = 0U; u8Index < u32WordLen; ++u8Index) {
|
||
REV_BYTES_32(pSrc[u8Index], pDest[u8Index]);
|
||
}
|
||
|
||
CanSerialPortFrameAddDataQueue(env, &env->rx_message_struct, env->IdHardSoftFilter_RX[index].filter);
|
||
|
||
}
|
||
|
||
if (env->CountHardSoftFilter_RX == 0) {
|
||
// message buffer 3th word
|
||
uint32_t *pSrc = (uint32_t *) FLEXCAN_MB_WORDN_ADDR(&pBuf[env->pBufCounter << 2], 0U, 8U, 8U);
|
||
uint32_t *pDest = (uint32_t *) &env->rx_message_struct.data[0];
|
||
|
||
uint32_t u32WordLen = env->rx_message_struct.dlc / 4U + (env->rx_message_struct.dlc % 4U > 0U ? 1U : 0U);
|
||
|
||
for (uint32_t u8Index = 0U; u8Index < u32WordLen; ++u8Index) {
|
||
REV_BYTES_32(pSrc[u8Index], pDest[u8Index]);
|
||
}
|
||
|
||
CanSerialPortFrameAddDataQueue(env, &env->rx_message_struct, 0);
|
||
}
|
||
|
||
++env->pBufCounter;
|
||
|
||
if (env->pBufCounter >= env->DMA_BUF_LEN_RX) {
|
||
env->pBufCounter = 0;
|
||
}
|
||
|
||
}
|
||
|
||
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 idFilter, uint8_t *data, uint16_t size,
|
||
uint32_t timeout) {
|
||
return vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataQueue[idFilter]);
|
||
}
|
||
|
||
//static uint16_t
|
||
//vCanSerialPortFrameReceiveSniffer(tCanSerialPortFrameFlagchip *env, uint8_t idFilter, uint8_t *data, uint16_t size,
|
||
// uint32_t timeout) {
|
||
|
||
// return env->rxDataSnifferQueue
|
||
// ? vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue[idFilter])
|
||
// : 0;
|
||
//}
|
||
|
||
uint16_t vCanSerialPortFrameTransmit(tCanSerialPortFrameFlagchip *env, uint8_t *data, uint16_t size, uint32_t adr,
|
||
uint8_t canType, uint32_t timeout) {
|
||
|
||
uint16_t sent = 0;
|
||
|
||
if (osMutexAcquire(env->access, 1000) == osOK) {
|
||
|
||
env->id = adr;
|
||
env->canTypeFrame = canType;
|
||
|
||
uint16_t fullSize = size / 8;
|
||
uint8_t tailSize = size % 8;
|
||
|
||
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], 8, 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;
|
||
}
|
||
|
||
osMutexRelease(env->access);
|
||
}
|
||
|
||
return sent;
|
||
}
|
||
|
||
|
||
tSerialPortFrameIO CanPortFrame_GetIo(tCanSerialPortFrameFlagchip *env) {
|
||
tSerialPortFrameIO io = {
|
||
.env = env,
|
||
.receive = (SerialPortFrameReceivedTransaction) vCanSerialPortFrameReceive,
|
||
.transmit = (SerialPortFrameTransmitTransaction) vCanSerialPortFrameTransmit
|
||
};
|
||
return io;
|
||
}
|
||
|
||
tSerialPortFrameIO CanPort_GetSnifferIo(tCanSerialPortFrameFlagchip *env) {
|
||
tSerialPortFrameIO io = {
|
||
.env = env,
|
||
.receive = (SerialPortFrameReceivedTransaction) vCanSerialPortFrameReceive,
|
||
.transmit = (SerialPortFrameTransmitTransaction) vCanSerialPortFrameTransmit
|
||
};
|
||
return io;
|
||
} |