CanSerialPortFrame_XCP/Src/CanSerialPortFrameXCP.c

273 lines
8.2 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->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);
}