// // 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; } void CanSerialPortFrameSetId(tCanSerialPortFrameFlagchip *env, uint32_t id) { env->id = id; } void CanSerialPortFrameSetId1(tCanSerialPortFrameFlagchip *env, uint32_t id) { env->id1 = id; } void CanSerialPortFrameSetType(tCanSerialPortFrameFlagchip *env, eCanTypeFrame 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; } } } void vCanSerialPortFrameInit( tCanSerialPortFrameFlagchip *env, FLEXCAN_Type *CANx, // FLEXCAN0 PCC_ClkSrcType canClock, // PCC_CLK_FLEXCAN0 uint8 CAN_INDEX, // CAN0 = 0 ... CAN3 = 3 eCanBaudRate canBaudRate, uint8_t irqSubPriority, eCanTypeFrame 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; FLEXCAN_InitType tInitCfg; FLEXCAN_MBConfigType tMbCfg = {0}; uint32_t u32FuncClk; PCC_CtrlType bSP_PCC_Config; FLEXCAN_InterruptType tIntCfg = {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(&tInitCfg); tInitCfg.eBaudrate = FLEXCAN_BAUD_500K; tInitCfg.bEnRxFifo = TRUE; tInitCfg.bEnDma = FALSE; tInitCfg.bEnFd = FALSE; tInitCfg.bEnBrs = FALSE; tInitCfg.eMbDataWidth = FLEXCAN_DATAWIDTH_8; u32FuncClk = PCC_GetPccFunctionClock(s_ePccCanTable[CAN_INDEX]); tInitCfg.eClkSrcSel = FLEXCAN_CLOCK_FUNCTION; /* functional clock */ tInitCfg.eClkSrcHz = (FLEXCAN_BaudClkType) u32FuncClk; /* function clock frequency */ tInitCfg.eDirect = FLEXCAN_DIR_ENABLE_WITHOUT_TRIG; tRetVal = FLEXCAN_Init(CAN_INDEX, &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; tMbCfg.pRxFilterMBList = env->pRxFilterFifoList; tMbCfg.u8RxFilterMBCnt = sizeof(env->pRxFilterFifoList) / sizeof(env->pRxFilterFifoList[0]); tMbCfg.pRxBuf = CAN_GET_BUFFER(CAN_INDEX); /* tx config */ tMbCfg.u8TxMsgCnt = 3U; /* tx occupy 3 mb */ tRetVal = FLEXCAN_RxFilterConfig(CAN_INDEX, &tMbCfg); if (CAN_ErrorInterrupt_CallBack == NULL) { tIntCfg.bEnErrorInterrupt = 0U; tIntCfg.pErrorNotify = NULL; tIntCfg.bEnTxMBInterrupt = 0U; tIntCfg.pRxMBNotify = NULL; tIntCfg.bEnRxMBInterrupt = 0U; tIntCfg.pRxFifoNotify = NULL; tIntCfg.bEnRxFifoInterrupt = 0U; tIntCfg.pTxMBNotify = NULL; } else { tIntCfg.bEnErrorInterrupt = 1U; tIntCfg.pErrorNotify = CAN_ErrorInterrupt_CallBack; tIntCfg.bEnTxMBInterrupt = 1U; tIntCfg.pRxMBNotify = CAN_RxInterrupt_CallBack; tIntCfg.bEnRxMBInterrupt = 1U; tIntCfg.pRxFifoNotify = CAN_RxFifoInterrupt_CallBack; tIntCfg.bEnRxFifoInterrupt = 1U; tIntCfg.pTxMBNotify = CAN_TxInterrupt_CallBack; } FLEXCAN_SetInterrupt(CAN_INDEX, &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 CAN_RxInterrupt_CallBack_Handler(tCanSerialPortFrameFlagchip *env, uint8_t u8CanIndex, FLEXCAN_RxMsgType *pRxCfg) { can_rx_message_type rx_message_struct; rx_message_struct.u16CanId = pRxCfg->u32CanId; rx_message_struct.u8DataLen = pRxCfg->u32DataLen; memcpy(rx_message_struct.aData, pRxCfg->aData, rx_message_struct.u8DataLen); osMessageQueuePut(env->rxDataQueue[pRxCfg->u8MbIndex], &rx_message_struct, 0x0, 0U); if (env->rxDataSnifferQueue[pRxCfg->u8MbIndex]) { osMessageQueuePut(env->rxDataSnifferQueue[pRxCfg->u8MbIndex], &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 u8MbIndex, uint8_t *data, uint16_t size, uint32_t timeout) { return vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataQueue[u8MbIndex]); } static uint16_t vCanSerialPortFrameReceiveSniffer(tCanSerialPortFrameFlagchip *env, uint8_t u8MbIndex, uint8_t *data, uint16_t size, uint32_t timeout) { return env->rxDataSnifferQueue[u8MbIndex] ? vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue[u8MbIndex]) : 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_ID_STD; tTxMsg.bWaitTxCompleted = 1U; tTxMsg.u16WaitTxTimeout = 1000U; 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; } /* uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; uint16_t fullSize = size / 8; uint8_t tailSize = size % 8; uint8_t transmit_mailbox; can_tx_message_type TxMessage; if (env->canTypeFrame == CAN_STD_ID) { TxMessage.standard_id = env->id; TxMessage.extended_id = 0; TxMessage.id_type = CAN_ID_STANDARD; } if (env->canTypeFrame == CAN_EXT_ID) { TxMessage.standard_id = 0; TxMessage.extended_id = env->id; TxMessage.id_type = CAN_ID_EXTENDED; } TxMessage.frame_type = CAN_TFT_DATA; TxMessage.dlc = 8; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { uint16_t len = 0; for (uint16_t i = 0; i < fullSize; ++i) { memcpy(TxMessage.data, &data[len], 8); len += 8; transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX0); while (can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL) { if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } // if ((can_flag_get(env->can, CAN_BOF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EPF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EAF_FLAG) != RESET)) { // return sent; // } } sent += 8; size -= 8; } if (tailSize) { TxMessage.dlc = tailSize; memcpy(TxMessage.data, &data[len], tailSize); transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX0); can_transmit_status_type status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); while (status != CAN_TX_STATUS_SUCCESSFUL) { status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } } 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; }