// // Created by cfif on 16.03.2024. // #include #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; }