commit cc2a93c099d8267160134932b962ec96d65799b9 Author: cfif Date: Thu Oct 30 15:14:01 2025 +0300 Обновление diff --git a/Inc/CanSerialPortFrameXCP.h b/Inc/CanSerialPortFrameXCP.h new file mode 100644 index 0000000..263b6e4 --- /dev/null +++ b/Inc/CanSerialPortFrameXCP.h @@ -0,0 +1,169 @@ +// +// Created by cfif on 16.03.2024. +// + +#ifndef CAN_MODULE_CAN_FRAME_XCP_H +#define CAN_MODULE_CAN_FRAME_XCP_H + +#include "SerialPortFrameIO.h" +#include "CanSerialPortFrame.h" +#include "LoggerToSerialPort.h" +#include "CmsisRtosThreadUtils.h" +#include "SystemMutexCmsis.h" + +#define MAX_CTO 8 +#define MAX_DTO 8 + +typedef enum { + XCP_ERR_CMD_SYNCH = 0x00, + XCP_ERR_CMD_BUSY = 0x10, + XCP_ERR_DAQ_ACTIVE = 0x11, + XCP_ERR_PGM_ACTIVE = 0x12, + XCP_ERR_CMD_UNKNOWN = 0x20, + XCP_ERR_CMD_SYNTAX = 0x21, + XCP_ERR_OUT_OF_RANGE = 0x22, + XCP_ERR_WRITE_PROTECTED = 0x23, + XCP_ERR_ACCESS_DENIED = 0x24, + XCP_ERR_ACCESS_LOCKED = 0x25, + XCP_ERR_PAGE_NOT_VALID = 0x26, + XCP_ERR_MODE_NOT_VALID = 0x27, + XCP_ERR_SEGMENT_NOT_VALID = 0x28, + XCP_ERR_SEQUENCE = 0x29, + XCP_ERR_DAQ_CONFIG = 0x2A, + XCP_ERR_MEMORY_OVERFLOW = 0x30, + XCP_ERR_GENERIC = 0x31, + XCP_ERR_VERIFY = 0x32, + XCP_ERR_RESOURCE_TEMPORARY_NOT_ACCESSIBLE = 0x33, + XCP_ERR_SUBCMD_UNKNOWN = 0x34 +} eXcpError; + +typedef enum { + XCP_COMMAND_CONNECT = 0xFF, + XCP_COMMAND_DISCONNECT = 0xFE, + XCP_COMMAND_GET_STATUS = 0xFD, + XCP_COMMAND_SYNCH = 0xFC, + + XCP_COMMAND_UPLOAD = 0xF5, + XCP_COMMAND_SHORT_UPLOAD = 0xF4, + + XCP_COMMAND_SET_MTA = 0xF6, + + XCP_COMMAND_DOWNLOAD = 0xF0, + XCP_COMMAND_DOWNLOAD_NEXT = 0xEF +} eXcpTypeCommand; + +typedef enum { + XCP_STANDBY = 0 + +} eXcpResult; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + + uint8_t CAL_PAG: 1; // CALibration and PAGing + uint8_t reserve1: 1; + uint8_t DAQ: 1; // DAQ lists supported + uint8_t STIM: 1; // STIMulation + uint8_t PGM: 1; // Flash programming + uint8_t reserve2: 1; + uint8_t reserve3: 1; + uint8_t reserve4: 1; + + uint8_t BYTE__ORDER: 1; // 0 - Intel + uint8_t ADDRESS_GRANULARITY_0: 1; + uint8_t ADDRESS_GRANULARITY_1: 1; + uint8_t reserve5: 1; + uint8_t reserve6: 1; + uint8_t reserve7: 1; + uint8_t SLAVE_BLOCK_MODE: 1; + uint8_t OPTIONAL: 1; + + uint8_t MAX_CTO_; + uint16_t MAX_DTO_; + + uint8_t XCP_PROTOCOL_VER; + uint8_t XCP_TRANSPORT_VER; + +} eXcpCommand_CONNECT; + + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + + uint8_t STORE_CAL_REQ: 1; + uint8_t reserve1: 1; + uint8_t STORE_DAQ_REQ: 1; + uint8_t CLEAR_DAQ_REQ: 1; + uint8_t reserve2: 1; + uint8_t reserve3: 1; + uint8_t DAQ_RUNNING: 1; + uint8_t RESUME: 1; + + uint8_t CAL_PAG: 1; + uint8_t reserve5: 1; + uint8_t DAQ: 1; + uint8_t STIM: 1; + uint8_t PGM: 1; + uint8_t reserve6: 1; + uint8_t reserve7: 1; + uint8_t reserve8: 1; + + uint8_t STATE_NUMBER; + + uint32_t SESSION_CONFIGURATION_ID; + + +} eXcpCommand_GET_STATUS; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t COUNT; +} eXcpCommand_Upload; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t COUNT; + uint8_t RESERVED; + uint8_t ADR_EX; + uint32_t ADR; +} eXcpCommand_SHORT_UPLOAD; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint16_t RESERVED; + uint8_t ADR_EX; + uint32_t ADR; +} eXcpCommand_SET_MTA; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t COUNT; +} eXcpCommand_Download; + +typedef struct { + tSerialPortFrameIO *ioCanFrame; + tLoggerToSerialPort *slog; + SystemMutexCmsis txAccessQueue; + + uint8_t ADR_EXT; + uint32_t ADR_MTA; + + can_rx_message_type canFrame; + bool isTransmitResponse; + bool isTransmitResponseError; + uint8_t downloadSize; + uint8_t response[8]; + uint8_t responseSize; + + tStaticThreadBlock(1024) T_can_Listener_XCP; + +} tCanSerialPortFrameXCP; + +void CanSerialPortFrameXcpInit( + tCanSerialPortFrameXCP *env, + SystemMutexCmsis txAccessQueue, + tSerialPortFrameIO *ioCanFrame, + tLoggerToSerialPort *slog +); + +#endif //CAN_MODULE_CAN_FRAME_XCP_H diff --git a/Src/CanSerialPortFrameXCP.c b/Src/CanSerialPortFrameXCP.c new file mode 100644 index 0000000..2f24105 --- /dev/null +++ b/Src/CanSerialPortFrameXCP.c @@ -0,0 +1,272 @@ +// +// Created by cfif on 16.03.2024. +// +#include +#include "CanSerialPortFrameXCP.h" +#include "memory.h" +#include "AsciiStringAssmeblingUtils.h" +#include "SystemMutexCmsis.h" +#include "CanPorts.h" + +#define LOG_SIGN "CAN_XCP" +#define LOGGER &env->slog->logger + + +void CanSerialPortFrameXcpInit( + tCanSerialPortFrameXCP *env, + SystemMutexCmsis txAccessQueue, + tSerialPortFrameIO *ioCanFrame, + tLoggerToSerialPort *slog +) { + env->ioCanFrame = ioCanFrame; + + env->txAccessQueue = txAccessQueue; + + env->slog = slog; + + InitThreadBlock(env->T_can_Listener_XCP, "CanListenerXCP", osPriorityNormal); +} + +eXcpResult vCanSerialPortFrameXcpReceive(tCanSerialPortFrameXCP *env, uint32 timeout) { + + uint16_t recv = env->ioCanFrame->receive(env->ioCanFrame->env, PROTOCOL_XCP, (uint8_t *) &env->canFrame, 1, + timeout); + + if (recv == 0) + return XCP_STANDBY; + + env->isTransmitResponse = true; + env->isTransmitResponseError = false; + + eXcpTypeCommand com = env->canFrame.data[0]; + + switch (com) { + XCP_COMMAND_CONNECT: + { + eXcpCommand_CONNECT *xcpCommand_CONNECT = (eXcpCommand_CONNECT *) env->response; + + xcpCommand_CONNECT->CAL_PAG = 0; // Калибровка и пагинация + xcpCommand_CONNECT->reserve1 = 0; + xcpCommand_CONNECT->DAQ = 1; // Поддержка DAQ + xcpCommand_CONNECT->STIM = 1; // Стимуляция (формирование инициативных запросов) + xcpCommand_CONNECT->PGM = 1; // Программирование FLASH + xcpCommand_CONNECT->reserve2 = 0; + xcpCommand_CONNECT->reserve3 = 0; + xcpCommand_CONNECT->reserve4 = 0; + + xcpCommand_CONNECT->BYTE__ORDER = 0; // 0 - Intel 1 - Motorola + xcpCommand_CONNECT->ADDRESS_GRANULARITY_0 = 0; + xcpCommand_CONNECT->ADDRESS_GRANULARITY_1 = 0; + xcpCommand_CONNECT->reserve5 = 1; + xcpCommand_CONNECT->reserve6 = 1; + xcpCommand_CONNECT->reserve7 = 1; + xcpCommand_CONNECT->SLAVE_BLOCK_MODE = 0; + xcpCommand_CONNECT->OPTIONAL = 1; // Поддержка команды XCP_COMMAND_GET_STATUS + + xcpCommand_CONNECT->MAX_CTO_ = MAX_CTO; + xcpCommand_CONNECT->MAX_DTO_ = MAX_DTO; + + xcpCommand_CONNECT->XCP_PROTOCOL_VER = 1; + xcpCommand_CONNECT->XCP_TRANSPORT_VER = 1; + + xcpCommand_CONNECT->COM = XCP_COMMAND_CONNECT; + + env->responseSize = 8; + + break; + } + + XCP_COMMAND_DISCONNECT: + { + + break; + }; + + XCP_COMMAND_GET_STATUS: + { + eXcpCommand_GET_STATUS *xcpCommand_GET_STATUS = (eXcpCommand_GET_STATUS *) env->response; + + xcpCommand_GET_STATUS->STORE_CAL_REQ = 0; + xcpCommand_GET_STATUS->reserve1 = 0; + xcpCommand_GET_STATUS->STORE_DAQ_REQ = 0; + xcpCommand_GET_STATUS->CLEAR_DAQ_REQ = 0; + xcpCommand_GET_STATUS->reserve2 = 0; + xcpCommand_GET_STATUS->reserve3 = 0; + xcpCommand_GET_STATUS->DAQ_RUNNING = 0; + xcpCommand_GET_STATUS->RESUME = 0; + + xcpCommand_GET_STATUS->CAL_PAG = 0; + xcpCommand_GET_STATUS->reserve5 = 0; + xcpCommand_GET_STATUS->DAQ = 0; + xcpCommand_GET_STATUS->STIM = 0; + xcpCommand_GET_STATUS->PGM = 0; + xcpCommand_GET_STATUS->reserve6 = 0; + xcpCommand_GET_STATUS->reserve7 = 0; + xcpCommand_GET_STATUS->reserve8 = 0; + + xcpCommand_GET_STATUS->STATE_NUMBER = 0; + + xcpCommand_GET_STATUS->SESSION_CONFIGURATION_ID = 0; + + xcpCommand_GET_STATUS->COM = XCP_COMMAND_CONNECT; + + env->responseSize = 8; + + break; + }; + + XCP_COMMAND_SYNCH: + { + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_CMD_SYNCH; + + env->responseSize = 2; + + break; + }; + + XCP_COMMAND_SET_MTA: + { + eXcpCommand_SET_MTA *request = (eXcpCommand_SET_MTA *) env->canFrame.data; + + env->ADR_EXT = request->ADR_EX; + env->ADR_MTA = request->ADR; + + env->response[0] = XCP_COMMAND_CONNECT; + env->responseSize = 1; + + break; + }; + + XCP_COMMAND_UPLOAD: + { + eXcpCommand_Upload *request = (eXcpCommand_Upload *) env->canFrame.data; + + env->isTransmitResponse = false; + + env->response[0] = XCP_COMMAND_CONNECT; + + uint8_t fullBlock = request->COUNT / 7; + uint8_t tailBlock = request->COUNT % 7; + + for (uint8_t i = 0; i < fullBlock; ++i) { + memcpy(&env->response[1], (uint8_t *) (env->ADR_MTA), request->COUNT); + env->ADR_MTA += 7; + env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, 7, timeout); + } + + if (tailBlock > 0) { + memcpy(&env->response[1], (uint8_t *) (env->ADR_MTA), tailBlock); + env->ADR_MTA += tailBlock; + env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, tailBlock, timeout); + } + + break; + }; + + XCP_COMMAND_SHORT_UPLOAD: + { + eXcpCommand_SHORT_UPLOAD *request = (eXcpCommand_SHORT_UPLOAD *) env->canFrame.data; + + if (request->COUNT > (MAX_CTO - 1)) { + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_OUT_OF_RANGE; + break; + } + + env->response[0] = XCP_COMMAND_CONNECT; + + memcpy(&env->response[1], (uint8_t *) request->ADR, request->COUNT); + + env->responseSize = request->COUNT + 1; + break; + }; + + + XCP_COMMAND_DOWNLOAD: + { + eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data; + + uint8_t COUNT = env->canFrame.dlc - 2; + + memcpy((uint8_t *) (env->ADR_MTA), &env->response[1], COUNT); + env->ADR_MTA += COUNT; + + env->response[0] = XCP_COMMAND_CONNECT; + env->responseSize = 1; + + env->downloadSize = request->COUNT - COUNT; + + break; + }; + + XCP_COMMAND_DOWNLOAD_NEXT: + { + eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data; + + uint8_t COUNT = env->canFrame.dlc - 2; + + memcpy((uint8_t *) (env->ADR_MTA), &env->response[1], COUNT); + env->ADR_MTA += COUNT; + + if (request->COUNT != env->downloadSize) { + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_SEQUENCE; + break; + } + + env->downloadSize -= COUNT; + + env->isTransmitResponse = false; + + if (env->downloadSize == 0) { + env->isTransmitResponse = true; + env->response[0] = XCP_COMMAND_CONNECT; + env->responseSize = 1; + } + + break; + }; + + XCP_COMMAND_DOWNLOAD_MAX: + { + eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data; + + uint8_t fullBlock = request->COUNT / 7; + uint8_t tailBlock = request->COUNT % 7; + + for (uint8_t i = 0; i < fullBlock; ++i) { + memcpy((uint8_t *) (env->ADR_MTA), &env->response[1], request->COUNT); + env->ADR_MTA += 7; + } + + if (tailBlock > 0) { + memcpy((uint8_t *) (env->ADR_MTA), &env->response[1], tailBlock); + env->ADR_MTA += tailBlock; + } + + env->response[0] = XCP_COMMAND_CONNECT; + env->responseSize = 1; + + break; + }; + + default: + break; + } + + if (env->isTransmitResponse) { + env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, env->responseSize, timeout); + } +} + +_Noreturn void CanXcpProcessing_ListenerTask(tCanSerialPortFrameXCP *env) { + + while (1) { + vCanSerialPortFrameXcpReceive(env, 1000); + } +} + +void CanSerialPortFrameTp_Start(tCanSerialPortFrameXCP *env, uint8_t numBuf) { + ThreadBlock_Start(env->T_can_Listener_XCP, env, CanXcpProcessing_ListenerTask); +} diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..71971cd --- /dev/null +++ b/modular.json @@ -0,0 +1,10 @@ +{ + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file