CanSerialPortFrame_XCP/Src/CanSerialPortFrameXCP.c

725 lines
17 KiB
C

//
// Created by cfif on 16.03.2024.
//
#include <SystemDelayInterface.h>
#include "CanSerialPortFrameXCP.h"
#include "memory.h"
#include "AsciiStringAssmeblingUtils.h"
#include "SystemMutexCmsis.h"
#include "CanPorts.h"
#define LOG_SIGN "CAN_XCP"
#define LOGGER &env->logger
static unsigned long SeedToKeyHVAC_NAMI(unsigned char rnd, unsigned long dwSeedInfo) {
#define Mask 0x55F388A6UL
unsigned char i;
unsigned long key = dwSeedInfo;
rnd += 35;
if (rnd < 35) rnd = 255;
for (i = 0; i < rnd; i++) {
if (key & 0x80000000UL)
key = (key << 1) ^ Mask;
else
key <<= 1;
}
return key;
}
void CanSerialPortFrameXcpInit(
tCanSerialPortFrameXCP *env,
tSerialPortFrameIO *ioCanFrame,
tRtcIO *rtcIO,
tLoggerInterface *logger
) {
env->ioCanFrame = ioCanFrame;
env->rtcIO = rtcIO;
env->logger = logger;
InitThreadBlock(env->T_can_Listener_XCP, "CanListenerXCP", osPriorityNormal);
}
uint8_t XCP_COMMAND_CONNECT_255(tCanSerialPortFrameXCP *env) {
eXcpCommand_CONNECT *xcpCommand_CONNECT = (eXcpCommand_CONNECT *) env->response;
xcpCommand_CONNECT->COM = XCP_COMMAND_CONNECT;
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;
return 8;
}
uint8_t XCP_COMMAND_DISCONNECT_254(tCanSerialPortFrameXCP *env) {
return 0;
}
uint8_t XCP_COMMAND_GET_STATUS_253(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_STATUS *xcpCommand_GET_STATUS = (eXcpCommand_GET_STATUS *) env->response;
xcpCommand_GET_STATUS->COM = XCP_COMMAND_CONNECT;
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;
return 8;
}
uint8_t XCP_COMMAND_SYNCH_252(tCanSerialPortFrameXCP *env) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_CMD_SYNCH;
return 2;
}
uint8_t XCP_GET_COMM_MODE_INFO_251(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_COMM_MODE_INFO *xcpCommand_GET_COMM_MODE_INFO = (eXcpCommand_GET_COMM_MODE_INFO *) env->response;
xcpCommand_GET_COMM_MODE_INFO->RESERVED1 = 0;
xcpCommand_GET_COMM_MODE_INFO->MASTER_BLOCK_MODE = 1;
xcpCommand_GET_COMM_MODE_INFO->INTERLEAVED_MODE = 0;
xcpCommand_GET_COMM_MODE_INFO->RESERVED2 = 0;
xcpCommand_GET_COMM_MODE_INFO->RESERVED3 = 0;
xcpCommand_GET_COMM_MODE_INFO->MAX_BS = 255;
xcpCommand_GET_COMM_MODE_INFO->MIN_ST = 0;
xcpCommand_GET_COMM_MODE_INFO->QUEUE_SIZE = 0;
xcpCommand_GET_COMM_MODE_INFO->VERSION = 1;
return 8;
}
uint8_t XCP_GET_SEED_248(tCanSerialPortFrameXCP *env) {
eXcpCommand_REQ_GET_SEED *request = (eXcpCommand_REQ_GET_SEED *) env->canFrame.data;
eXcpCommand_GET_SEED *xcpCommand_GET_SEED = (eXcpCommand_GET_SEED *) env->response;
xcpCommand_GET_SEED->COM = XCP_COMMAND_CONNECT;
xcpCommand_GET_SEED->LEN = 4;
xcpCommand_GET_SEED->KEY = 0x11223344;
env->RND = request->RESOURCE;
return 6;
}
uint8_t XCP_UNLOCK_247(tCanSerialPortFrameXCP *env) {
eXcpCommand_REQ_UNLOCK *request = (eXcpCommand_REQ_UNLOCK *) env->canFrame.data;
uint32_t securitySeedMy = SeedToKeyHVAC_NAMI(env->RND, 0x11223344);
if (securitySeedMy != request->KEY) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
} else {
env->response[0] = XCP_COMMAND_CONNECT;
env->response[1] = 0;
}
return 2;
}
uint8_t XCP_COMMAND_SET_MTA_246(tCanSerialPortFrameXCP *env) {
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;
return 1;
}
uint8_t XCP_COMMAND_UPLOAD_245(tCanSerialPortFrameXCP *env) {
eXcpCommand_Upload *request = (eXcpCommand_Upload *) env->canFrame.data;
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, 1000);
}
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, 1000);
}
return 0;
}
uint8_t XCP_COMMAND_SHORT_UPLOAD_244(tCanSerialPortFrameXCP *env) {
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;
return 2;
}
env->response[0] = XCP_COMMAND_CONNECT;
memcpy(&env->response[1], (uint8_t *) request->ADR, request->COUNT);
return request->COUNT + 1;
}
uint8_t XCP_COMMAND_DOWNLOAD_240(tCanSerialPortFrameXCP *env) {
eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data;
uint8_t COUNT = env->canFrame.dlc - 2;
memcpy((uint8_t *) (env->ADR_MTA), &env->response[2], COUNT);
env->ADR_MTA += COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
env->downloadRemaining = request->COUNT - COUNT;
return 1;
}
uint8_t XCP_COMMAND_DOWNLOAD_NEXT_239(tCanSerialPortFrameXCP *env) {
eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data;
uint8_t COUNT = env->canFrame.dlc - 2;
memcpy((uint8_t *) (env->ADR_MTA), &env->response[2], COUNT);
env->ADR_MTA += COUNT;
if (request->COUNT != env->downloadRemaining) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_SEQUENCE;
return 2;
}
env->downloadRemaining -= COUNT;
env->isTransmitResponse = false;
if (env->downloadRemaining == 0) {
env->isTransmitResponse = true;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
return 0;
}
uint8_t XCP_COMMAND_DOWNLOAD_MAX_238(tCanSerialPortFrameXCP *env) {
uint8_t COUNT = env->canFrame.dlc - 1;
memcpy((uint8_t *) (env->ADR_MTA), &env->response[1], COUNT);
env->ADR_MTA += COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
uint8_t XCP_CLEAR_DAQ_LIST_227(tCanSerialPortFrameXCP *env) {
return 0;
}
uint8_t XCP_GET_DAQ_LIST_INFO_216(tCanSerialPortFrameXCP *env) {
eXcpCommand_Get_DAQ_List_Info_Request *request = (eXcpCommand_Get_DAQ_List_Info_Request *) env->canFrame.data;
if (request->DAQ_LIST_NUMBER > MAX_DAO) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
eXcpCommand_Get_DAQ_List_Info *xcpCommand_Get_DAQ_List_Info = (eXcpCommand_Get_DAQ_List_Info *) env->response;
xcpCommand_Get_DAQ_List_Info->COM = XCP_COMMAND_CONNECT;
xcpCommand_Get_DAQ_List_Info->PREDEFINED = 0;
xcpCommand_Get_DAQ_List_Info->EVENT_FIXED = 0;
xcpCommand_Get_DAQ_List_Info->DAQ = 1;
xcpCommand_Get_DAQ_List_Info->STIM = 1;
xcpCommand_Get_DAQ_List_Info->RESERVER = 0;
xcpCommand_Get_DAQ_List_Info->MAX_ODT_ = MAX_ODT;
xcpCommand_Get_DAQ_List_Info->MAX_ODT_ENTRIES_ = MAX_ODT_ENTRIES_SIZE;
xcpCommand_Get_DAQ_List_Info->FIXED_EVENT = 0;
return 6;
}
uint8_t XCP_FREE_DAQ_214(tCanSerialPortFrameXCP *env) {
env->DAQ_COUNT = 0;
for (uint16_t i = 0; i < MAX_DAO; ++i) {
env->DAQ[i].MODE = XCP_STOP;
env->DAQ[i].ODT_COUNT = 0;
for (uint8_t j = 0; j < MAX_ODT; ++j) {
env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_COUNT = 0;
}
}
return 0;
}
uint8_t XCP_ALLOC_DAQ_213(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_DAQ *request = (eXcpCommand_ALLOC_DAQ *) env->canFrame.data;
env->DAQ_COUNT = request->DAQ_COUNT;
return 0;
}
uint8_t XCP_ALLOC_ODT_212(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_ODT *request = (eXcpCommand_ALLOC_ODT *) env->canFrame.data;
env->DAQ[request->DAQ_LIST_NUMBER].ODT_COUNT = request->ODT_COUNT;
return 0;
}
uint8_t XCP_ALLOC_ODT_ENTRY_211(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_ODT_ENTRY *request = (eXcpCommand_ALLOC_ODT_ENTRY *) env->canFrame.data;
env->DAQ[request->DAQ_LIST_NUMBER].ODT_NUMBER[request->ODT_NUMBER].ODT_ENTRIES_COUNT = request->ODT_ENTRIES_COUNT;
return 0;
}
uint8_t XCP_SET_DAQ_PTR_226(tCanSerialPortFrameXCP *env) {
eXcpCommand_SET_DAQ_PTR *request = (eXcpCommand_SET_DAQ_PTR *) env->canFrame.data;
if ((request->DAQ_LIST_NUMBER > MAX_DAO) ||
(request->ODT_NUMBER > MAX_ODT) ||
(request->ODT_ENTRY_NUMBER > MAX_ODT_ENTRIES_SIZE)) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
env->DAQ_LIST_NUMBER = request->DAQ_LIST_NUMBER;
env->ODT_NUMBER = request->ODT_NUMBER;
env->ODT_ENTRY_NUMBER = request->ODT_ENTRY_NUMBER;
return 0;
}
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) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
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;
}
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) {
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_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;
return 0;
}
uint8_t XCP_START_STOP_DAQ_LIST_222(tCanSerialPortFrameXCP *env) {
eXcpCommand_START_STOP_DAQ_LIST *request = (eXcpCommand_START_STOP_DAQ_LIST *) env->canFrame.data;
if (request->DAQ_LIST_NUMBER > MAX_DAO) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
env->DAQ[request->DAQ_LIST_NUMBER].MODE = request->MODE;
return 0;
}
const xcp_func_ptr fXcp_func_ptr[256] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
XCP_ALLOC_ODT_ENTRY_211,
XCP_ALLOC_ODT_212,
XCP_ALLOC_DAQ_213,
XCP_FREE_DAQ_214,
NULL,
XCP_GET_DAQ_LIST_INFO_216,
NULL,
NULL,
NULL,
NULL,
NULL,
XCP_START_STOP_DAQ_LIST_222,
NULL,
XCP_SET_DAQ_LIST_MODE_224,
XCP_WRITE_DAQ_225,
XCP_SET_DAQ_PTR_226,
XCP_CLEAR_DAQ_LIST_227,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
XCP_COMMAND_DOWNLOAD_MAX_238,
XCP_COMMAND_DOWNLOAD_NEXT_239,
XCP_COMMAND_DOWNLOAD_240,
NULL,
NULL,
NULL,
XCP_COMMAND_SHORT_UPLOAD_244,
XCP_COMMAND_UPLOAD_245,
XCP_COMMAND_SET_MTA_246,
XCP_UNLOCK_247,
XCP_GET_SEED_248,
NULL,
NULL,
XCP_GET_COMM_MODE_INFO_251,
XCP_COMMAND_SYNCH_252,
XCP_COMMAND_GET_STATUS_253,
XCP_COMMAND_DISCONNECT_254,
XCP_COMMAND_CONNECT_255
};
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;
eXcpTypeCommand com = env->canFrame.data[0];
if (fXcp_func_ptr[com] != NULL) {
uint8_t response_size = fXcp_func_ptr[com](env);
if (response_size) {
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, response_size, timeout);
}
} else {
}
}
_Noreturn void CanXcpProcessing_ListenerTask(tCanSerialPortFrameXCP *env) {
while (1) {
vCanSerialPortFrameXcpReceive(env, 1000);
}
}
void CanSerialPortFrameTp_Start(tCanSerialPortFrameXCP *env) {
ThreadBlock_Start(env->T_can_Listener_XCP, env, CanXcpProcessing_ListenerTask);
}