From 6eb52208efd9e2ee6954400bc1a6245bdcb00210 Mon Sep 17 00:00:00 2001 From: cfif Date: Wed, 4 Dec 2024 13:10:48 +0300 Subject: [PATCH] Init --- Inc/CanSerialPort.h | 80 +++++++++++ Src/CanSerialPort.c | 338 ++++++++++++++++++++++++++++++++++++++++++++ modular.json | 17 +++ 3 files changed, 435 insertions(+) create mode 100644 Inc/CanSerialPort.h create mode 100644 Src/CanSerialPort.c create mode 100644 modular.json diff --git a/Inc/CanSerialPort.h b/Inc/CanSerialPort.h new file mode 100644 index 0000000..1163b1b --- /dev/null +++ b/Inc/CanSerialPort.h @@ -0,0 +1,80 @@ +// +// Created by cfif on 16.03.2024. +// + +#ifndef NATION_CAN_MODULE_CAN_H +#define NATION_CAN_MODULE_CAN_H + +#include "SerialPortIO.h" +#include "cmsis_os2.h" +#include "n32g45x.h" +/* +#define CAN_FILTER_STDID(STDID) ((STDID & 0x3FF) << 5) +#define CAN_FILTER_EXTID_H(EXTID) ((uint16_t)(((EXTID >> 18) << 5 ) | ((EXTID & 0x2FFFF) >> 13))) +#define CAN_FILTER_EXTID_L(EXTID) ((uint16_t)((EXTID & 0x2FFFF) << 3)) +*/ +#define CAN_FILTER_STDID(STDID) ((STDID & 0x7FF) << 5) +#define CAN_FILTER_EXTID_H(EXTID) ((uint16_t)(((EXTID << 3) | CAN_ID_EXT) >> 16)) +#define CAN_FILTER_EXTID_L(EXTID) ((uint16_t)(( EXTID << 3) | CAN_ID_EXT)) + + +#define CAN_FILTER_STDMASK(STDMASK) ((STDMASK & 0x7FF) << 5) +#define CAN_FILTER_EXTMASK_H(EXTMASK) ((uint16_t)(((EXTMASK << 3) >> 16))) +#define CAN_FILTER_EXTMASK_L(EXTMASK) ((uint16_t)(EXTMASK << 3)) + + +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; + +typedef struct { + CAN_Module *can; + uint32_t id; + eCanTypeFrame canTypeFrame; + bool canFilterEnable; + uint32_t canFilterId; + uint32_t canFilterMask; + + osMessageQueueId_t rxDataQueue; + osMessageQueueId_t rxDataSnifferQueue; + osMessageQueueId_t txAccessQueue; + +} tCanSerialPortNation; + +void CanSerialPortIrqRxProcessing(tCanSerialPortNation *env); + +void CanSerialPortSetFilter(tCanSerialPortNation *env, + bool canFilterEnable, + uint32_t canFilterId, + uint32_t canFilterMask); + +void CanSerialPortSetId(tCanSerialPortNation *env, uint32_t id); + +void vCanSerialPortInit( + tCanSerialPortNation *env, + CAN_Module *CANx, + eCanBaudRate canBaudRate, + uint8_t irqSubPriority, + eCanTypeFrame canTypeFrame, + uint32_t canId, + bool canFilterEnable, + uint32_t canFilterId, + uint32_t canFilterMask, + uint32_t rxBufferLength, + uint32_t rxSnifferLength +); + + +tSerialPortIO CanPort_GetIo(tCanSerialPortNation *env); + +tSerialPortIO CanPort_GetSnifferIo(tCanSerialPortNation *env); + +#endif //NATION_CAN_MODULE_CAN_H diff --git a/Src/CanSerialPort.c b/Src/CanSerialPort.c new file mode 100644 index 0000000..b6c958b --- /dev/null +++ b/Src/CanSerialPort.c @@ -0,0 +1,338 @@ +// +// Created by cfif on 16.03.2024. +// +#include +#include "CanSerialPort.h" +#include "memory.h" + +static void vCanSerialPortInitNVICEnable(CAN_Module *CANx, uint8_t irqSubPriority) { + + NVIC_InitType NVIC_InitStructure; + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); + + if (CANx == CAN1) { + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; + } + + if (CANx == CAN2) { + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn; + } + + NVIC_InitStructure.NVIC_IRQChannelSubPriority = irqSubPriority; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + if (CANx == CAN1) { + NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, irqSubPriority); + } + + if (CANx == CAN2) { + NVIC_SetPriority(CAN2_RX0_IRQn, irqSubPriority); + } +} + +static void vCanSerialPortInitStructure( + tCanSerialPortNation *env, + CAN_Module *CANx, + uint32_t rxBufferLength, + uint32_t rxSnifferLength +) { + env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL); + if (rxSnifferLength) { + env->rxDataSnifferQueue = osMessageQueueNew(rxSnifferLength, 1, NULL); + } else { + env->rxDataSnifferQueue = 0; + } + env->can = CANx; +} + +void CanSerialPortSetFilter(tCanSerialPortNation *env, + bool canFilterEnable, + uint32_t canFilterId, + uint32_t canFilterMask) { + + env->canFilterEnable = canFilterEnable; + env->canFilterId = canFilterId; + env->canFilterMask = canFilterMask; + + CAN_FilterInitType CAN_FilterInitStructure; + + CAN_FilterInitStructure.Filter_Num = 0; + CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode; + CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale; + + if (env->canTypeFrame == CAN_STD_ID) { + CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_STDID(env->canFilterId); + CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_STDID(env->canFilterId); + CAN_FilterInitStructure.FilterMask_HighId = CAN_FILTER_STDMASK(env->canFilterMask); + CAN_FilterInitStructure.FilterMask_LowId = CAN_FILTER_STDMASK(env->canFilterMask); + } + + if (env->canTypeFrame == CAN_EXT_ID) { + CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_EXTID_H(env->canFilterId); + CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_EXTID_L(env->canFilterId); + CAN_FilterInitStructure.FilterMask_HighId = CAN_FILTER_EXTMASK_H(env->canFilterMask); + CAN_FilterInitStructure.FilterMask_LowId = CAN_FILTER_EXTMASK_L(env->canFilterMask); + } + + CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0; + + if (env->canFilterEnable) { + CAN_FilterInitStructure.Filter_Act = ENABLE; + } else { + CAN_FilterInitStructure.Filter_Act = DISABLE; + } + + if (env->can == CAN1) + CAN1_InitFilter(&CAN_FilterInitStructure); + + if (env->can == CAN2) + CAN2_InitFilter(&CAN_FilterInitStructure); +} + +void CanSerialPortSetId(tCanSerialPortNation *env, uint32_t id) { + env->id = id; + + CanSerialPortSetFilter(env, env->canFilterEnable, env->canFilterId, env->canFilterMask); +} + +void vCanSerialPortInit( + tCanSerialPortNation *env, + CAN_Module *CANx, + eCanBaudRate canBaudRate, + uint8_t irqSubPriority, + eCanTypeFrame canTypeFrame, + uint32_t canId, + bool canFilterEnable, + uint32_t canFilterId, + uint32_t canFilterMask, + uint32_t rxBufferLength, + uint32_t rxSnifferLength +) { + vCanSerialPortInitStructure(env, CANx, rxBufferLength, rxSnifferLength); + + vCanSerialPortInitNVICEnable(CANx, irqSubPriority); + + CAN_InitType CAN_InitStructure; + CAN_DeInit(CANx); + + CAN_InitStruct(&CAN_InitStructure); + CAN_InitStructure.TTCM = DISABLE; + CAN_InitStructure.ABOM = DISABLE; + CAN_InitStructure.AWKUM = DISABLE; + CAN_InitStructure.NART = DISABLE; + CAN_InitStructure.RFLM = DISABLE; + CAN_InitStructure.TXFP = ENABLE; + CAN_InitStructure.OperatingMode = CAN_Normal_Mode; + + if (canBaudRate == CAN_BAUD_RATE_1000K) { + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_5tq; + CAN_InitStructure.TBS2 = CAN_TBS2_3tq; + CAN_InitStructure.BaudRatePrescaler = 4; + } + + if (canBaudRate == CAN_BAUD_RATE_500K) { + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_5tq; + CAN_InitStructure.TBS2 = CAN_TBS2_2tq; + CAN_InitStructure.BaudRatePrescaler = 9; + } + + if (canBaudRate == CAN_BAUD_RATE_250K) { +/* + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_14tq; + CAN_InitStructure.TBS2 = CAN_TBS2_3tq; + CAN_InitStructure.BaudRatePrescaler = 8; +*/ + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_4tq; + CAN_InitStructure.TBS2 = CAN_TBS2_3tq; + CAN_InitStructure.BaudRatePrescaler = 18; + } + + if (canBaudRate == CAN_BAUD_RATE_125K) { + /* + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_6tq; + CAN_InitStructure.TBS2 = CAN_TBS2_5tq; + CAN_InitStructure.BaudRatePrescaler = 24; +*/ + CAN_InitStructure.RSJW = CAN_RSJW_1tq; + CAN_InitStructure.TBS1 = CAN_TBS1_13tq; + CAN_InitStructure.TBS2 = CAN_TBS2_4tq; + CAN_InitStructure.BaudRatePrescaler = 16; + } + + CAN_Init(CANx, &CAN_InitStructure); + + env->canTypeFrame = canTypeFrame; + + CanSerialPortSetId(env, canId); + CanSerialPortSetFilter(env, canFilterEnable, canFilterId, canFilterMask); + + CAN_INTConfig(CANx, CAN_INT_FMP0, ENABLE); + +} + + +void CanSerialPortIrqRxProcessing(tCanSerialPortNation *env) { + CanRxMessage CAN_RxMessage; + CAN_ReceiveMessage(env->can, CAN_FIFO0, &CAN_RxMessage); + + for (uint8_t i = 0; i < CAN_RxMessage.DLC; ++i) { + osMessageQueuePut(env->rxDataQueue, &CAN_RxMessage.Data[i], 0x0, 0U); + if (env->rxDataSnifferQueue) { + osMessageQueuePut(env->rxDataSnifferQueue, &CAN_RxMessage.Data[i], 0x0, 0U); + } + } + +// if (env->can->RFF0 & CAN_RFF0_FFULL0) { +// CAN_ReceiveMessage(env->can, CAN_FIFO0, &CAN_RxMessage); +// +// for (uint8_t i = 0; i < CAN_RxMessage.DLC; ++i) { +// osMessageQueuePut(env->rxDataQueue, &CAN_RxMessage.Data[i], 0x0, 0U); +// if (env->rxDataSnifferQueue) { +// osMessageQueuePut(env->rxDataSnifferQueue, &CAN_RxMessage.Data[i], 0x0, 0U); +// } +// } +// } +// +// if (env->can->RFF1 & CAN_RFF1_FFULL1) { +// +// CAN_ReceiveMessage(env->can, CAN_FIFO1, &CAN_RxMessage); +// +// for (uint8_t i = 0; i < CAN_RxMessage.DLC; ++i) { +// osMessageQueuePut(env->rxDataQueue, &CAN_RxMessage.Data[i], 0x0, 0U); +// if (env->rxDataSnifferQueue) { +// osMessageQueuePut(env->rxDataSnifferQueue, &CAN_RxMessage.Data[i], 0x0, 0U); +// } +// } +// } + +} + +static uint16_t vSerialPortReceiveQueue( + tCanSerialPortNation *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 vCanSerialPortReceive(tCanSerialPortNation *env, uint8_t *data, uint16_t size, uint32_t timeout) { + return vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataQueue); +} + +static uint16_t vCanSerialPortReceiveSniffer(tCanSerialPortNation *env, uint8_t *data, uint16_t size, uint32_t timeout) { + + return env->rxDataSnifferQueue + ? vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue) + : 0; +} + +uint16_t vCanSerialPortTransmit(tCanSerialPortNation *env, uint8_t *data, uint16_t size, uint32_t timeout) { + uint16_t sent = 0; + uint32_t endMs = SystemGetMs() + timeout; + + uint16_t fullSize = size / 8; + uint8_t tailSize = size % 8; + + CanTxMessage TxMessage; + + TxMessage.StdId = env->id; + + if (env->canTypeFrame == CAN_STD_ID) + TxMessage.IDE = CAN_ID_STD; + + if (env->canTypeFrame == CAN_EXT_ID) + TxMessage.IDE = CAN_ID_EXT; + + TxMessage.RTR = CAN_RTRQ_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; + + CAN_TransmitMessage(env->can, &TxMessage); + + while (CAN_TransmitSTS(env->can, 0) != CANTXSTSOK) { + if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { + return sent; + } + } + + sent += 8; + size -= 8; + } + + if (tailSize) { + TxMessage.DLC = tailSize; + memcpy(TxMessage.Data, &data[len], tailSize); + + CAN_TransmitMessage(env->can, &TxMessage); + + while (CAN_TransmitSTS(env->can, 0) != CANTXSTSOK) { + if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { + return sent; + } + } + + sent += tailSize; + size -= tailSize; + } + + } + + return sent; +} + +tSerialPortIO CanPort_GetIo(tCanSerialPortNation *env) { + tSerialPortIO io = { + .env = env, + .receive = (SerialPortIOTransaction) vCanSerialPortReceive, + .transmit = (SerialPortIOTransaction) vCanSerialPortTransmit + }; + return io; +} + +tSerialPortIO CanPort_GetSnifferIo(tCanSerialPortNation *env) { + tSerialPortIO io = { + .env = env, + .receive = (SerialPortIOTransaction) vCanSerialPortReceiveSniffer, + .transmit = (SerialPortIOTransaction) vCanSerialPortTransmit + }; + return io; +} \ No newline at end of file diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..b630424 --- /dev/null +++ b/modular.json @@ -0,0 +1,17 @@ +{ + "dep": [ + { + "type": "git", + "provider": "NAVIGATOR_UVEOS_NATION_TELIT", + "repo": "SerialPort" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file