CanSerialPortFrame_Flagchip.../Src/CanSerialPortFrame.c

793 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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.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 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;
}