From 97954edfd6643f20ed2be0da00392a38f1ede454 Mon Sep 17 00:00:00 2001 From: cfif Date: Mon, 17 Nov 2025 16:28:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Inc/CanSerialPortFrameXCP.h | 94 +++++++++++++++++- Src/CanSerialPortFrameXCP.c | 187 ++++++++++++++++++++++++++++++++++-- 2 files changed, 272 insertions(+), 9 deletions(-) diff --git a/Inc/CanSerialPortFrameXCP.h b/Inc/CanSerialPortFrameXCP.h index 8071b19..dc359af 100644 --- a/Inc/CanSerialPortFrameXCP.h +++ b/Inc/CanSerialPortFrameXCP.h @@ -215,6 +215,10 @@ typedef struct __attribute__ ((packed)) { } eXcpCommand_SET_DAQ_PTR; +#define PROGRAM_MASTER_BLOCK_MODE 1 +#define PROGRAM_MAX_SECTOR 8 + + #define MAX_CTO 8 #define MAX_DTO 8 @@ -452,6 +456,80 @@ typedef struct __attribute__ ((packed)) { } eXcpCommand_GET_DAQ_EVENT_INFO; +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t RESERVED1; + + uint8_t MASTER_BLOCK_MODE: 1; + uint8_t INTERLEAVED_MODE: 1; + uint8_t RESERVED2: 1; + uint8_t RESERVED3: 1; + uint8_t RESERVED4: 1; + uint8_t RESERVED5: 1; + uint8_t SLAVE_BLOCK_MODE: 1; + uint8_t RESERVED6: 1; + + uint8_t MAX_CTO_PGM; + uint8_t MAX_BS_PGM; + uint8_t MIN_ST_PGM; + uint8_t QUEUE_SIZE_PGM; +} eXcpCommand_PROGRAM_START; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t MODE; + uint16_t RESERVED; + uint32_t CLEAR_RANGE; +} eXcpCommand_XCP_PROGRAM_CLEAR_209; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t COUNT; +} eXcpCommand_Program_ProgramNext_208_202; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + + uint8_t ABSOLUTE_MODE: 1; + uint8_t FUNCTIONAL_MODE: 1; + uint8_t COMPRESSION_SUPPORTED: 1; + uint8_t COMPRESSION_REQUIRED: 1; + uint8_t ENCRYPTION_SUPPORTED: 1; + uint8_t ENCRYPTION_REQUIRED: 1; + uint8_t NON_SEQ_PGM_SUPPORTED: 1; + uint8_t NON_SEQ_PGM_REQUIRED: 1; + + uint8_t MAX_SECTOR; + +} eXcpCommand_PGM_PROCESSOR_INFO_206; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t MODE; + uint8_t SECTOR_NUMBER; +} eXcpCommand_REQ_GET_SECTOR_INFO_205; + +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + uint8_t CLEAR_SEQUENCE_NUMBER; + uint8_t PROGRAM_SEQUENCE_NUMBER; + + uint8_t ABSOLUTE_MODE: 1; + uint8_t FUNCTIONAL_MODE: 1; + uint8_t PAGED_MODE: 1; + uint8_t SEQUENTIAL_ONLY: 1; + uint8_t ERASE_BEFORE_WRITE: 1; + uint8_t VERIFY_AFTER_WRITE: 1; + uint8_t RESERVED1: 1; + uint8_t RESERVED2: 1; + + uint32_t SECTOR_INFO; +} eXcpCommand_RESP_GET_SECTOR_INFO_205; + + +typedef bool (xcp_clear_flash_func)(uint32_t firstPageAddr, uint32_t totalSize); +typedef bool (xcp_write_flash_func)(uint32_t beginPageAddr, void *sourceRamAddr, uint32_t size); + typedef struct { tSerialPortFrameIO *ioCanFrame; tLoggerInterface *logger; @@ -478,6 +556,15 @@ typedef struct { osMutexId_t access; + uint32_t startRamAdr; + uint32_t endRamAdr; + + uint32_t startFlashAdr; + uint32_t endFlashAdr; + xcp_clear_flash_func *clear_flash_func; + + xcp_write_flash_func *write_flash_func; + tStaticThreadBlock(512) T_can_Listener_XCP; tStaticThreadBlock(512) T_can_Listener_Dto_Stim_XCP; tStaticThreadBlock(512) T_can_Listener_Dto_Daq_XCP; @@ -486,11 +573,16 @@ typedef struct { typedef uint8_t (*xcp_func_ptr)(tCanSerialPortFrameXCP *env); - void CanSerialPortFrameXcpInit( tCanSerialPortFrameXCP *env, tSerialPortFrameIO *ioCanFrame, tRtcIO *rtcIO, + uint32_t startRamAddr, + uint32_t endRamAdr, + uint32_t startFlashAdr, + uint32_t endFlashAdr, + xcp_clear_flash_func *clear_flash_func, + xcp_write_flash_func *write_flash_func, tLoggerInterface *logger ); diff --git a/Src/CanSerialPortFrameXCP.c b/Src/CanSerialPortFrameXCP.c index deea0be..876e6b6 100644 --- a/Src/CanSerialPortFrameXCP.c +++ b/Src/CanSerialPortFrameXCP.c @@ -34,6 +34,12 @@ void CanSerialPortFrameXcpInit( tCanSerialPortFrameXCP *env, tSerialPortFrameIO *ioCanFrame, tRtcIO *rtcIO, + uint32_t startRamAdr, + uint32_t endRamAdr, + uint32_t startFlashAdr, + uint32_t endFlashAdr, + xcp_clear_flash_func *clear_flash_func, + xcp_write_flash_func *write_flash_func, tLoggerInterface *logger ) { env->ioCanFrame = ioCanFrame; @@ -41,6 +47,14 @@ void CanSerialPortFrameXcpInit( env->rtcIO = rtcIO; env->logger = logger; + env->startRamAdr = startRamAdr; + env->endRamAdr = endRamAdr; + + env->startFlashAdr = startFlashAdr; + env->endFlashAdr = endFlashAdr; + env->clear_flash_func = clear_flash_func; + env->write_flash_func = write_flash_func; + env->access = osMutexNew(NULL); InitThreadBlock(env->T_can_Listener_XCP, "CanListenerXCP", osPriorityNormal); @@ -173,6 +187,15 @@ static uint8_t XCP_UNLOCK_247(tCanSerialPortFrameXCP *env) { static uint8_t XCP_COMMAND_SET_MTA_246(tCanSerialPortFrameXCP *env) { eXcpCommand_SET_MTA *request = (eXcpCommand_SET_MTA *) env->canFrame.data; + if (((request->ADR < env->startRamAdr) || (request->ADR > env->endRamAdr)) && + ((request->ADR < env->startFlashAdr) || (request->ADR > env->endFlashAdr))) { + + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_ACCESS_DENIED; + + return 2; + } + env->ADR_EXT = request->ADR_EX; env->ADR_MTA = request->ADR; @@ -248,8 +271,9 @@ static uint8_t XCP_COMMAND_DOWNLOAD_NEXT_239(tCanSerialPortFrameXCP *env) { if (request->COUNT != env->downloadRemaining) { env->response[0] = XCP_COMMAND_DISCONNECT; env->response[1] = XCP_ERR_SEQUENCE; + env->response[2] = env->downloadRemaining; - return 2; + return 3; } env->downloadRemaining -= COUNT; @@ -637,6 +661,153 @@ static uint8_t XCP_GET_DAQ_STM(tCanSerialPortFrameXCP *env) { return 0; } +static uint8_t XCP_PROGRAM_START_210(tCanSerialPortFrameXCP *env) { + eXcpCommand_PROGRAM_START *response = (eXcpCommand_PROGRAM_START *) env->response; + + response->COM = XCP_COMMAND_CONNECT; + response->RESERVED1 = 0; + + response->MASTER_BLOCK_MODE = PROGRAM_MASTER_BLOCK_MODE; + response->INTERLEAVED_MODE = 0; + response->RESERVED2 = 0; + response->RESERVED3 = 0; + response->RESERVED4 = 0; + response->RESERVED5 = 0; + response->SLAVE_BLOCK_MODE = 1; + response->RESERVED6 = 0; + + response->MAX_CTO_PGM = 8; + response->MAX_BS_PGM = 255; // Максимальный размер блока в режиме программирования. Определяет, сколько пакетов можно отправить подряд в блочном режиме + response->MIN_ST_PGM = 1; // Минимальное время шага (Minimum Separation Time). Определяет минимальную паузу (в миллисекундах) + response->QUEUE_SIZE_PGM = 10; // Размер очереди. Указывает, сколько пакетов типа CTO мастер может отправить "подряд" + + return 8; +} + +static uint8_t XCP_PROGRAM_CLEAR_209(tCanSerialPortFrameXCP *env) { + eXcpCommand_XCP_PROGRAM_CLEAR_209 *request = (eXcpCommand_XCP_PROGRAM_CLEAR_209 *) env->canFrame.data; + + if (request->MODE == 0) { + + if ((env->ADR_MTA < env->startFlashAdr) || ((env->ADR_MTA + request->CLEAR_RANGE) > env->endFlashAdr)) { + + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_ACCESS_DENIED; + + return 2; + } + + env->clear_flash_func(env->ADR_MTA, request->CLEAR_RANGE); + } else { + + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_OUT_OF_RANGE; + + return 2; + } + + env->response[0] = XCP_COMMAND_CONNECT; + return 1; +} + +static uint8_t XCP_PROGRAM_208(tCanSerialPortFrameXCP *env) { + eXcpCommand_Program_ProgramNext_208_202 *request = (eXcpCommand_Program_ProgramNext_208_202 *) env->canFrame.data; + + uint8_t COUNT = env->canFrame.dlc - 2; + + env->write_flash_func(env->ADR_MTA, &env->canFrame.data[2], request->COUNT); + + env->ADR_MTA += request->COUNT; + +#ifndef PROGRAM_MASTER_BLOCK_MODE + env->response[0] = XCP_COMMAND_CONNECT; + return 1; +#else + if (request->COUNT == 0) { + env->response[0] = XCP_COMMAND_CONNECT; + return 1; + } + + return 0; +#endif +} + +static uint8_t XCP_PROGRAM_NEXT_202(tCanSerialPortFrameXCP *env) { + eXcpCommand_Program_ProgramNext_208_202 *request = (eXcpCommand_Program_ProgramNext_208_202 *) env->canFrame.data; + + uint8_t COUNT = env->canFrame.dlc - 2; + + env->write_flash_func(env->ADR_MTA, &env->canFrame.data[2], request->COUNT); + + env->ADR_MTA += request->COUNT; + + return 0; +} + +static uint8_t XCP_PROGRAM_RESET_207(tCanSerialPortFrameXCP *env) { + env->response[0] = XCP_COMMAND_CONNECT; + return 1; +} + +static uint8_t XCP_GET_PGM_PROCESSOR_INFO_206(tCanSerialPortFrameXCP *env) { + eXcpCommand_PGM_PROCESSOR_INFO_206 *response = (eXcpCommand_PGM_PROCESSOR_INFO_206 *) env->response; + + response->COM = XCP_COMMAND_CONNECT; + + response->ABSOLUTE_MODE = 1; + response->FUNCTIONAL_MODE = 0; + response->COMPRESSION_SUPPORTED = 0; + response->COMPRESSION_REQUIRED = 0; + response->ENCRYPTION_SUPPORTED = 0; + response->ENCRYPTION_REQUIRED = 0; + response->NON_SEQ_PGM_SUPPORTED = 0; + response->NON_SEQ_PGM_REQUIRED = 0; + + response->MAX_SECTOR = PROGRAM_MAX_SECTOR; + + return 3; +} + +static uint8_t XCP_GET_SECTOR_INFO_205(tCanSerialPortFrameXCP *env) { + eXcpCommand_REQ_GET_SECTOR_INFO_205 *request = (eXcpCommand_REQ_GET_SECTOR_INFO_205 *) env->canFrame.data; + + if (request->SECTOR_NUMBER > PROGRAM_MAX_SECTOR) { + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_OUT_OF_RANGE; + + return 2; + } + + eXcpCommand_RESP_GET_SECTOR_INFO_205 *response = (eXcpCommand_RESP_GET_SECTOR_INFO_205 *) env->response;\ + response->COM = XCP_COMMAND_CONNECT; + response->CLEAR_SEQUENCE_NUMBER = request->SECTOR_NUMBER; + response->PROGRAM_SEQUENCE_NUMBER = request->SECTOR_NUMBER; + + response->ABSOLUTE_MODE = 1; + response->FUNCTIONAL_MODE = 0; + response->PAGED_MODE = 0; + response->SEQUENTIAL_ONLY = 1; + response->ERASE_BEFORE_WRITE = 1; + response->VERIFY_AFTER_WRITE = 0; + response->RESERVED1 = 0; + response->RESERVED2 = 0; + + if (request->MODE == 0) { + response->SECTOR_INFO = request->SECTOR_NUMBER * FLASH_PAGE_SIZE + env->startFlashAdr; + } else if (request->MODE == 1) { + response->SECTOR_INFO = FLASH_PAGE_SIZE; + } else if (request->MODE == 2) { + env->response[1] = 0; + return 2; + } else { + env->response[0] = XCP_COMMAND_DISCONNECT; + env->response[1] = XCP_ERR_CMD_SYNTAX; + return 2; + } + + return 8; +} + const xcp_func_ptr fXcp_func_ptr[256] = { NULL, NULL, @@ -840,15 +1011,15 @@ const xcp_func_ptr fXcp_func_ptr[256] = { NULL, NULL, NULL, + XCP_PROGRAM_NEXT_202, NULL, NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + XCP_GET_SECTOR_INFO_205, + XCP_GET_PGM_PROCESSOR_INFO_206, + XCP_PROGRAM_RESET_207, + XCP_PROGRAM_208, + XCP_PROGRAM_CLEAR_209, + XCP_PROGRAM_START_210, XCP_ALLOC_ODT_ENTRY_211, XCP_ALLOC_ODT_212, XCP_ALLOC_DAQ_213,