From faaf533343dd242cc607f815451305afd55c5a1f Mon Sep 17 00:00:00 2001 From: cfif Date: Mon, 10 Nov 2025 11:54:03 +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 | 67 ++++++++-- Src/CanSerialPortFrameXCP.c | 240 ++++++++++++++++++++++++++++++------ 2 files changed, 255 insertions(+), 52 deletions(-) diff --git a/Inc/CanSerialPortFrameXCP.h b/Inc/CanSerialPortFrameXCP.h index abe1bc0..0c94b77 100644 --- a/Inc/CanSerialPortFrameXCP.h +++ b/Inc/CanSerialPortFrameXCP.h @@ -11,9 +11,6 @@ #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, @@ -80,9 +77,11 @@ typedef enum { } eXcpDAQ_Mode; typedef enum { - XCP_STANDBY = 0 + XCP_SYNC_STOP_ALL = 0, + XCP_SYNC_START_SEL = 1, + XCP_SYNC_STOP_SEL = 2 -} eXcpResult; +} eXcpDAQ_Sync_Mode; typedef struct __attribute__ ((packed)) { eXcpTypeCommand COM; @@ -215,27 +214,39 @@ typedef struct __attribute__ ((packed)) { uint8_t ODT_ENTRY_NUMBER; } eXcpCommand_SET_DAQ_PTR; + +#define MAX_CTO 8 +#define MAX_DTO 8 + #define MAX_DAO 6 -#define MAX_ODT 10 -#define MAX_ODT_ENTRIES_SIZE 16 +#define MAX_ODT 20 +#define MAX_ODT_ENTRIES_SIZE 6 + +#define MAX_EVENT_CHANNEL 20 typedef struct { uint8_t ODT_ENTRIES_COUNT; + uint8_t BIT_OFFSET[MAX_ODT_ENTRIES_SIZE]; + uint8_t ADR_EXT[MAX_ODT_ENTRIES_SIZE]; uint8_t ODT_ENTRIES_SIZE[MAX_ODT_ENTRIES_SIZE]; uint32_t ODT_ENTRIES_ADR[MAX_ODT_ENTRIES_SIZE]; } tXCP_ODT_ENTRIES; - typedef struct { uint8_t ALTERNATING; uint8_t DIRECTION; uint8_t DTO_CTR; uint8_t TIMESTAMP; uint8_t PID_OFF; - uint16_t EVENT_CHANNEL_NUMBER; uint8_t TRANSMISSION_RATE_PRESCALER; uint8_t DAQ_LIST_PRIORITY; + uint8_t COUNTER; + +} tXCP_EVENT_CHANNEL; + +typedef struct { + uint16_t EVENT_CHANNEL; eXcpDAQ_Mode MODE; uint8_t ODT_COUNT; tXCP_ODT_ENTRIES ODT_NUMBER[MAX_ODT]; @@ -298,6 +309,11 @@ typedef struct __attribute__ ((packed)) { uint16_t DAQ_LIST_NUMBER; } eXcpCommand_START_STOP_DAQ_LIST; +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + eXcpDAQ_Sync_Mode MODE; +} eXcpCommand_START_STOP_SYNCH; + typedef struct __attribute__ ((packed)) { eXcpTypeCommand COM; uint8_t RESERVED; @@ -319,6 +335,33 @@ typedef struct __attribute__ ((packed)) { uint8_t ODT_ENTRIES_COUNT; } eXcpCommand_ALLOC_ODT_ENTRY; +typedef struct __attribute__ ((packed)) { + eXcpTypeCommand COM; + + uint8_t DAQ_CONFIG_TYPE: 1; + uint8_t PRESCALER_SUPPORTED: 1; + uint8_t RESUME_SUPPORTED: 1; + uint8_t BIT_STIM_SUPPORTED: 1; + uint8_t TIMESTAMP_SUPPORTED: 1; + uint8_t PID_OFF_SUPPORTED: 1; + uint8_t OVERLOAD_MSB: 1; + uint8_t OVERLOAD_EVENT: 1; + + uint16_t MAX_DAQ; + uint16_t MAX_EVENT_CHANNEL_; + uint8_t MIN_DAQ; + + uint8_t Optimisation_Type_0: 1; + uint8_t Optimisation_Type_1: 1; + uint8_t Optimisation_Type_2: 1; + uint8_t Optimisation_Type_3: 1; + uint8_t Address_Extension_ODT: 1; + uint8_t Address_Extension_DAQ: 1; + uint8_t Identification_Field_Type_0: 1; + uint8_t Identification_Field_Type_1: 1; + +} eXcpCommand_GET_DAQ_PROCESSOR_INFO; + typedef struct { tSerialPortFrameIO *ioCanFrame; tLoggerInterface *logger; @@ -332,15 +375,17 @@ typedef struct { uint8_t ODT_ENTRY_NUMBER; can_rx_message_type canFrame; - bool isTransmitResponse; uint8_t downloadRemaining; uint8_t response[8]; + tXCP_EVENT_CHANNEL EVENT_CHANNEL[MAX_EVENT_CHANNEL]; tXCP_DAQ DAQ[MAX_DAO]; uint16_t DAQ_COUNT; tRtcIO *rtcIO; + osMutexId_t access; + tStaticThreadBlock(1024) T_can_Listener_XCP; } tCanSerialPortFrameXCP; @@ -355,6 +400,6 @@ void CanSerialPortFrameXcpInit( tLoggerInterface *logger ); -void CanSerialPortFrameTp_Start(tCanSerialPortFrameXCP *env); +void CanXcpProcessing_Listener_Start(tCanSerialPortFrameXCP *env); #endif //CAN_MODULE_CAN_FRAME_XCP_H diff --git a/Src/CanSerialPortFrameXCP.c b/Src/CanSerialPortFrameXCP.c index 8517656..4220ad3 100644 --- a/Src/CanSerialPortFrameXCP.c +++ b/Src/CanSerialPortFrameXCP.c @@ -41,6 +41,8 @@ void CanSerialPortFrameXcpInit( env->rtcIO = rtcIO; env->logger = logger; + env->access = osMutexNew(NULL); + InitThreadBlock(env->T_can_Listener_XCP, "CanListenerXCP", osPriorityNormal); } @@ -61,10 +63,10 @@ uint8_t XCP_COMMAND_CONNECT_255(tCanSerialPortFrameXCP *env) { 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->reserve5 = 0; + xcpCommand_CONNECT->reserve6 = 0; + xcpCommand_CONNECT->reserve7 = 0; + xcpCommand_CONNECT->SLAVE_BLOCK_MODE = 0; // Блочный режим не поддерживается xcpCommand_CONNECT->OPTIONAL = 1; // Поддержка команды XCP_COMMAND_GET_STATUS xcpCommand_CONNECT->MAX_CTO_ = MAX_CTO; @@ -78,7 +80,9 @@ uint8_t XCP_COMMAND_CONNECT_255(tCanSerialPortFrameXCP *env) { uint8_t XCP_COMMAND_DISCONNECT_254(tCanSerialPortFrameXCP *env) { - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + + return 1; } uint8_t XCP_COMMAND_GET_STATUS_253(tCanSerialPortFrameXCP *env) { @@ -250,10 +254,7 @@ uint8_t XCP_COMMAND_DOWNLOAD_NEXT_239(tCanSerialPortFrameXCP *env) { env->downloadRemaining -= COUNT; - env->isTransmitResponse = false; - if (env->downloadRemaining == 0) { - env->isTransmitResponse = true; env->response[0] = XCP_COMMAND_CONNECT; return 1; } @@ -275,7 +276,10 @@ uint8_t XCP_COMMAND_DOWNLOAD_MAX_238(tCanSerialPortFrameXCP *env) { uint8_t XCP_CLEAR_DAQ_LIST_227(tCanSerialPortFrameXCP *env) { - return 0; + + env->response[0] = XCP_COMMAND_CONNECT; + + return 1; } @@ -319,7 +323,8 @@ uint8_t XCP_FREE_DAQ_214(tCanSerialPortFrameXCP *env) { } } - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } uint8_t XCP_ALLOC_DAQ_213(tCanSerialPortFrameXCP *env) { @@ -327,7 +332,8 @@ uint8_t XCP_ALLOC_DAQ_213(tCanSerialPortFrameXCP *env) { env->DAQ_COUNT = request->DAQ_COUNT; - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } uint8_t XCP_ALLOC_ODT_212(tCanSerialPortFrameXCP *env) { @@ -335,7 +341,8 @@ uint8_t XCP_ALLOC_ODT_212(tCanSerialPortFrameXCP *env) { env->DAQ[request->DAQ_LIST_NUMBER].ODT_COUNT = request->ODT_COUNT; - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } @@ -344,7 +351,8 @@ uint8_t XCP_ALLOC_ODT_ENTRY_211(tCanSerialPortFrameXCP *env) { env->DAQ[request->DAQ_LIST_NUMBER].ODT_NUMBER[request->ODT_NUMBER].ODT_ENTRIES_COUNT = request->ODT_ENTRIES_COUNT; - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } @@ -366,13 +374,14 @@ uint8_t XCP_SET_DAQ_PTR_226(tCanSerialPortFrameXCP *env) { env->ODT_ENTRY_NUMBER = request->ODT_ENTRY_NUMBER; - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } uint8_t XCP_WRITE_DAQ_225(tCanSerialPortFrameXCP *env) { eXcpCommand_WRITE_DAQ *request = (eXcpCommand_WRITE_DAQ *) env->canFrame.data; - if (request->ODT_ENTRY_SIZE > MAX_ODT_ENTRIES_SIZE) { + if (env->ODT_ENTRY_NUMBER > MAX_ODT_ENTRIES_SIZE) { env->response[0] = XCP_COMMAND_DISCONNECT; env->response[1] = XCP_ERR_OUT_OF_RANGE; @@ -380,33 +389,42 @@ uint8_t XCP_WRITE_DAQ_225(tCanSerialPortFrameXCP *env) { return 2; } + env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].BIT_OFFSET[env->ODT_ENTRY_NUMBER] = request->BIT_OFFSET; + env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ADR_EXT[env->ODT_ENTRY_NUMBER] = request->ADR_EXT; env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ODT_ENTRIES_ADR[env->ODT_ENTRY_NUMBER] = request->ADR; env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ODT_ENTRIES_SIZE[env->ODT_ENTRY_NUMBER] = request->ODT_ENTRY_SIZE; - return 0; + ++env->ODT_ENTRY_NUMBER; + + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } uint8_t XCP_SET_DAQ_LIST_MODE_224(tCanSerialPortFrameXCP *env) { eXcpCommand_SET_DAQ_LIST_MODE *request = (eXcpCommand_SET_DAQ_LIST_MODE *) env->canFrame.data; - if (request->DAQ_LIST_NUMBER > MAX_DAO) { + if ((request->DAQ_LIST_NUMBER > MAX_DAO) || (request->EVENT_CHANNEL_NUMBER > MAX_EVENT_CHANNEL)) { env->response[0] = XCP_COMMAND_DISCONNECT; env->response[1] = XCP_ERR_OUT_OF_RANGE; return 2; } - env->DAQ[request->DAQ_LIST_NUMBER].ALTERNATING = request->ALTERNATING; - env->DAQ[request->DAQ_LIST_NUMBER].DIRECTION = request->DIRECTION; - env->DAQ[request->DAQ_LIST_NUMBER].DTO_CTR = request->DTO_CTR; - env->DAQ[request->DAQ_LIST_NUMBER].TIMESTAMP = request->TIMESTAMP; - env->DAQ[request->DAQ_LIST_NUMBER].PID_OFF = request->PID_OFF; + env->DAQ[request->DAQ_LIST_NUMBER].EVENT_CHANNEL = request->EVENT_CHANNEL_NUMBER; - env->DAQ[request->DAQ_LIST_NUMBER].EVENT_CHANNEL_NUMBER = request->EVENT_CHANNEL_NUMBER; - env->DAQ[request->DAQ_LIST_NUMBER].TRANSMISSION_RATE_PRESCALER = request->TRANSMISSION_RATE_PRESCALER; - env->DAQ[request->DAQ_LIST_NUMBER].DAQ_LIST_PRIORITY = request->DAQ_LIST_PRIORITY; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].ALTERNATING = request->ALTERNATING; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].DIRECTION = request->DIRECTION; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].DTO_CTR = request->DTO_CTR; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].TIMESTAMP = request->TIMESTAMP; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].PID_OFF = request->PID_OFF; - return 0; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].TRANSMISSION_RATE_PRESCALER = request->TRANSMISSION_RATE_PRESCALER; + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].DAQ_LIST_PRIORITY = request->DAQ_LIST_PRIORITY; + + env->EVENT_CHANNEL[request->EVENT_CHANNEL_NUMBER].COUNTER = request->TRANSMISSION_RATE_PRESCALER; + + env->response[0] = XCP_COMMAND_CONNECT; + return 1; } uint8_t XCP_START_STOP_DAQ_LIST_222(tCanSerialPortFrameXCP *env) { @@ -421,7 +439,83 @@ uint8_t XCP_START_STOP_DAQ_LIST_222(tCanSerialPortFrameXCP *env) { env->DAQ[request->DAQ_LIST_NUMBER].MODE = request->MODE; - return 0; + env->response[0] = XCP_COMMAND_CONNECT; + return 1; +} + +uint8_t XCP_START_STOP_SYNCH_221(tCanSerialPortFrameXCP *env) { + eXcpCommand_START_STOP_SYNCH *request = (eXcpCommand_START_STOP_SYNCH *) env->canFrame.data; + + if (request->MODE == XCP_SYNC_START_SEL) { + for (uint16 i = 0; i < MAX_DAO; ++i) { + if (env->DAQ[i].MODE == XCP_SELECT) { + env->DAQ[i].MODE = XCP_START; + } + } + } + + if (request->MODE == XCP_SYNC_STOP_ALL) { + for (uint16 i = 0; i < MAX_DAO; ++i) { + env->DAQ[i].MODE = XCP_STOP; + } + } + + if (request->MODE == XCP_SYNC_STOP_SEL) { + for (uint16 i = 0; i < MAX_DAO; ++i) { + if (env->DAQ[i].MODE == XCP_SELECT) { + env->DAQ[i].MODE = XCP_STOP; + } + } + } + + env->response[0] = XCP_COMMAND_CONNECT; + return 2; +} + +uint8_t XCP_READ_DAQ_219(tCanSerialPortFrameXCP *env) { + eXcpCommand_WRITE_DAQ *response = (eXcpCommand_WRITE_DAQ *) env->response; + + response->COM = XCP_COMMAND_CONNECT; + response->BIT_OFFSET = env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].BIT_OFFSET[env->ODT_ENTRY_NUMBER]; + response->ADR_EXT = env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ADR_EXT[env->ODT_ENTRY_NUMBER]; + response->ADR = env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ODT_ENTRIES_ADR[env->ODT_ENTRY_NUMBER]; + response->ODT_ENTRY_SIZE = env->DAQ[env->DAQ_LIST_NUMBER].ODT_NUMBER[env->ODT_NUMBER].ODT_ENTRIES_SIZE[env->ODT_ENTRY_NUMBER]; + + ++env->ODT_ENTRY_NUMBER; + + return 8; +} + +uint8_t XCP_GET_DAQ_PROCESSOR_INFO_218(tCanSerialPortFrameXCP *env) { + + eXcpCommand_GET_DAQ_PROCESSOR_INFO *response = (eXcpCommand_GET_DAQ_PROCESSOR_INFO *) env->response; + + response->COM = XCP_COMMAND_CONNECT; + + response->DAQ_CONFIG_TYPE = 1; // dynamic DAQ list configuration + response->PRESCALER_SUPPORTED = 1; // prescaler supported + response->RESUME_SUPPORTED = 0; // DAQ lists can not be set to RESUME mode + response->BIT_STIM_SUPPORTED = 0; // bitwise data stimulation not supported + response->TIMESTAMP_SUPPORTED = 0; // time-stamped mode not supported + response->PID_OFF_SUPPORTED = 0; // Identification field can not be switched off + response->OVERLOAD_MSB = 0; // No overload indication + response->OVERLOAD_EVENT = 0; // No overload indication + + response->MAX_DAQ = MAX_DAO; + response->MAX_EVENT_CHANNEL_ = MAX_EVENT_CHANNEL; + response->MIN_DAQ = 0; + + response->Optimisation_Type_0 = 0; + response->Optimisation_Type_1 = 1; + response->Optimisation_Type_2 = 0; + response->Optimisation_Type_3 = 1; + response->Address_Extension_ODT = 0; + response->Address_Extension_DAQ = 0; + response->Identification_Field_Type_0 = 1; // Relative ODT number, absolute DAQ list number (BYTE) + response->Identification_Field_Type_1 = 0; // Relative ODT number, absolute DAQ list number (BYTE) + + + return 8; } @@ -644,10 +738,10 @@ const xcp_func_ptr fXcp_func_ptr[256] = { NULL, XCP_GET_DAQ_LIST_INFO_216, NULL, + XCP_GET_DAQ_PROCESSOR_INFO_218, + XCP_READ_DAQ_219, NULL, - NULL, - NULL, - NULL, + XCP_START_STOP_SYNCH_221, XCP_START_STOP_DAQ_LIST_222, NULL, XCP_SET_DAQ_LIST_MODE_224, @@ -685,40 +779,104 @@ const xcp_func_ptr fXcp_func_ptr[256] = { }; -eXcpResult vCanSerialPortFrameXcpReceive(tCanSerialPortFrameXCP *env, uint32 timeout) { +uint8_t vCanSerialPortFrameXcpReceive(tCanSerialPortFrameXCP *env, uint32 timeout) { + uint8_t response_size = 0; uint16_t recv = env->ioCanFrame->receive(env->ioCanFrame->env, PROTOCOL_XCP, (uint8_t *) &env->canFrame, 1, timeout); if (recv == 0) - return XCP_STANDBY; + return 0; - env->isTransmitResponse = true; + if (osMutexAcquire(env->access, 100) == osOK) { - eXcpTypeCommand com = env->canFrame.data[0]; + eXcpTypeCommand com = env->canFrame.data[0]; - if (fXcp_func_ptr[com] != NULL) { + if (fXcp_func_ptr[com] != NULL) { - uint8_t response_size = fXcp_func_ptr[com](env); + response_size = fXcp_func_ptr[com](env); + + if (response_size) { + env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, response_size, timeout); + } + + } else { - if (response_size) { - env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, response_size, timeout); } - } else { + osMutexRelease(env->access); + } + return response_size; +} + +_Noreturn void CanXcpProcessing_ServiceTask(tCanSerialPortFrameXCP *env) { + uint8_t response_size; + + while (1) { + + if (osMutexAcquire(env->access, 100) == osOK) { + + for (uint16 i = 0; i < env->DAQ_COUNT; ++i) { + if (env->DAQ[i].MODE == XCP_START) { + + + if (env->EVENT_CHANNEL[env->DAQ[i].EVENT_CHANNEL].COUNTER == 0) { + + env->EVENT_CHANNEL[env->DAQ[i].EVENT_CHANNEL].COUNTER = env->EVENT_CHANNEL[env->DAQ[i].EVENT_CHANNEL].TRANSMISSION_RATE_PRESCALER; + + for (uint8_t j = 0; j < env->DAQ[i].ODT_COUNT; ++j) { + + env->response[0] = j; // ODT + env->response[1] = i; // DAQ + response_size = 0; + + for (uint8_t k = 0; k < env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_COUNT; ++k) { + + memcpy(&env->response[2] + response_size, + (uint8_t *) env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_ADR[k], + env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_SIZE[k]); + + response_size += env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_SIZE[k]; + + } + + if (response_size) { + env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, response_size, 1000); + } + + } + + } else { + --env->EVENT_CHANNEL[env->DAQ[i].EVENT_CHANNEL].COUNTER; + } + + + } + + + } + + osMutexRelease(env->access); + } + + SystemDelayMs(50); } } -_Noreturn void CanXcpProcessing_ListenerTask(tCanSerialPortFrameXCP *env) { +void CanXcpProcessing_Service_Start(tCanSerialPortFrameXCP *env) { + ThreadBlock_Start(env->T_can_Listener_XCP, env, CanXcpProcessing_ServiceTask); +} +_Noreturn void CanXcpProcessing_ListenerTask(tCanSerialPortFrameXCP *env) { while (1) { vCanSerialPortFrameXcpReceive(env, 1000); } } -void CanSerialPortFrameTp_Start(tCanSerialPortFrameXCP *env) { +void CanXcpProcessing_Listener_Start(tCanSerialPortFrameXCP *env) { ThreadBlock_Start(env->T_can_Listener_XCP, env, CanXcpProcessing_ListenerTask); + CanXcpProcessing_Service_Start(env); }