Обновление
This commit is contained in:
commit
cc2a93c099
|
|
@ -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
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
//
|
||||
// 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->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);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"cmake": {
|
||||
"inc_dirs": [
|
||||
"Inc"
|
||||
],
|
||||
"srcs": [
|
||||
"Src/**.c"
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue