From 5bd8ffd494b4cb108ce5b6b4f23f2d7c9612132f Mon Sep 17 00:00:00 2001 From: cfif Date: Fri, 3 Oct 2025 14:38:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81?= =?UTF-8?q?=20CAN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/CanSerialPortFrame.h | 98 +++++++++ Src/CanSerialPortFrame.c | 423 +++++++++++++++++++++++++++++++++++++++ modular.json | 24 +++ 3 files changed, 545 insertions(+) create mode 100644 Inc/CanSerialPortFrame.h create mode 100644 Src/CanSerialPortFrame.c create mode 100644 modular.json diff --git a/Inc/CanSerialPortFrame.h b/Inc/CanSerialPortFrame.h new file mode 100644 index 0000000..04e25c4 --- /dev/null +++ b/Inc/CanSerialPortFrame.h @@ -0,0 +1,98 @@ +// +// Created by cfif on 16.03.2024. +// + +#ifndef FLAGCHIP_CAN_MODULE_CAN_FRAME_H +#define FLAGCHIP_CAN_MODULE_CAN_FRAME_H + +#include "SerialPortFrameIO.h" +#include "cmsis_os2.h" +#include "stdbool.h" + + +#include "device_header.h" +#include "interrupt_manager.h" + +#include "fc7xxx_driver_flexcan.h" +#include "fc7xxx_driver_pcc.h" + + + + +typedef enum { + CAN_BAUD_RATE_1000K, + CAN_BAUD_RATE_500K, + CAN_BAUD_RATE_250K, + CAN_BAUD_RATE_125K +} eCanBaudRate; + +typedef enum { + CAN_STD_ID, + CAN_EXT_ID +} eCanTypeFrame; + +#define COUNT_QUEUE 2 + +typedef struct +{ + uint16_t u16CanId; /**< FLEXCAN id */ + uint8_t u8DataLen; /**< data length */ + uint8_t aData[8]; /**< data buffer */ + +} can_rx_message_type; + +typedef struct { + + FLEXCAN_Type *can; + + uint8_t CAN_INDEX; + + uint32_t id; + uint32_t id1; + eCanTypeFrame canTypeFrame; + bool canFilterEnable; + + bool reInit; + + eCanBaudRate canBaudRate; + + FLEXCAN_RxMbFilterType aRxFiltList[COUNT_QUEUE]; + FLEXCAN_RxMbFilterType pRxFilterFifoList[COUNT_QUEUE]; + + osMessageQueueId_t rxDataQueue[COUNT_QUEUE]; + osMessageQueueId_t rxDataSnifferQueue[COUNT_QUEUE]; + + osMessageQueueId_t txAccessQueue; + +} tCanSerialPortFrameFlagchip; + + + +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 + +); + +void CAN_RxInterrupt_CallBack_Handler(tCanSerialPortFrameFlagchip *env, uint8_t u8CanIndex, FLEXCAN_RxMsgType *pRxCfg); + +void CanSerialPortFrameSetId(tCanSerialPortFrameFlagchip *env, uint32_t id); +void CanSerialPortFrameSetId1(tCanSerialPortFrameFlagchip *env, uint32_t id); +void CanSerialPortFrameSetType(tCanSerialPortFrameFlagchip *env, eCanTypeFrame canTypeFrame); +tSerialPortFrameIO CanPortFrame_GetIo(tCanSerialPortFrameFlagchip *env); +tSerialPortFrameIO CanPortFrame_GetSnifferIo(tCanSerialPortFrameFlagchip *env); + +#endif //FLAGCHIP_CAN_MODULE_CAN_FRAME_H diff --git a/Src/CanSerialPortFrame.c b/Src/CanSerialPortFrame.c new file mode 100644 index 0000000..ce7634e --- /dev/null +++ b/Src/CanSerialPortFrame.c @@ -0,0 +1,423 @@ +// +// 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; +} \ No newline at end of file diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..ada8004 --- /dev/null +++ b/modular.json @@ -0,0 +1,24 @@ +{ + "dep": [ + { + "type": "git", + "provider": "HVAC_M7", + "repo": "SerialPort" + }, + { + "type": "git", + "provider": "HVAC_M7", + "repo": "SerialPortFrameInterface" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} + +