CanSerialPortFrame_XCP/Src/CanSerialPortFrameXCP.c

1892 lines
62 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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"
#include <stdio.h>
#define LOG_SIGN "CAN_XCP"
#define LOGGER env->logger
SECT_SRAM_XCP tXCP_DAQ DAQ[MAX_DAO];
static char strPrintfDebug_XCP[80];
static void PrintfDebug(uint8_t *data, uint8_t dlc) {
switch (dlc) {
case 0:
sprintf(strPrintfDebug_XCP, " ");
break;
case 1:
sprintf(strPrintfDebug_XCP, "0x%02X", data[0]);
break;
case 2:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X", data[0], data[1]);
break;
case 3:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X", data[0], data[1], data[2]);
break;
case 4:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X:0x%02X", data[0], data[1], data[2], data[3]);
break;
case 5:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X:0x%02X:0x%02X", data[0], data[1], data[2], data[3], data[4]);
break;
case 6:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X", data[0], data[1], data[2], data[3],
data[4], data[5]);
break;
case 7:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X", data[0], data[1], data[2],
data[3], data[4],
data[5], data[6]);
break;
case 8:
sprintf(strPrintfDebug_XCP, "0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X", data[0], data[1],
data[2], data[3], data[4],
data[5], data[6], data[7]);
break;
default:
sprintf(strPrintfDebug_XCP, " ");
}
}
static bool isUNLOCK(tCanSerialPortFrameXCP *env, eTypeProtect RESOURCE) {
if ((RESOURCE == XCP_PROTECT_CAL_PAG) && (env->PROTECT[0])) {
return true;
}
if ((RESOURCE == XCP_PROTECT_DAQ) && (env->PROTECT[1])) {
return true;
}
if ((RESOURCE == XCP_PROTECT_STM) && (env->PROTECT[2])) {
return true;
}
if ((RESOURCE == XCP_PROTECT_PGM) && (env->PROTECT[3])) {
return true;
}
return false;
}
/*
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;
}
*/
extern uint32_t generate_key(uint32_t seed);
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,
tVarsTabDumpObserver *varsTabDumpObserver,
tLoggerInterface *logger
) {
env->DAQ = DAQ;
env->varsTabDumpObserver = varsTabDumpObserver;
env->ioCanFrame = ioCanFrame;
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);
}
static void FREE_DAQ(tCanSerialPortFrameXCP *env) {
memset(&env->STATE, 0, sizeof(env->STATE));
memset(&env->SETUP, 0, sizeof(env->SETUP));
memset(env->DAQ, 0, sizeof(DAQ));
}
static uint8_t XCP_COMMAND_CONNECT_FF(tCanSerialPortFrameXCP *env) {
FREE_DAQ(env);
eXcpCommand_CONNECT *xcpCommand_CONNECT = (eXcpCommand_CONNECT *) env->response;
xcpCommand_CONNECT->COM = XCP_COMMAND_CONNECT;
xcpCommand_CONNECT->CAL_PAG = 1; // Калибровка и пагинация
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 = 0;
xcpCommand_CONNECT->reserve6 = 0;
xcpCommand_CONNECT->reserve7 = 0;
xcpCommand_CONNECT->_SLAVE_BLOCK_MODE = SLAVE_BLOCK_MODE; // Блочный режим не поддерживается
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;
}
static uint8_t XCP_COMMAND_DISCONNECT_FE(tCanSerialPortFrameXCP *env) {
FREE_DAQ(env);
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static void update_STATE(tCanSerialPortFrameXCP *env) {
env->STATE.STORE_CAL_REQ = 0; // ожидает сохранения в энергонезависимую память
env->STATE.STORE_DAQ_REQ = 0; // требуется сохранить DAQ-листы (не загрузить, а сохранить)
env->STATE.CLEAR_DAQ_REQ = 0; // требуется очистить все DAQ-листы
env->STATE.DAQ_RUNNING = 0; // минимум один DAQ-лист запущен и работает
for (uint16 i = 0; i < env->SETUP.DAQ_COUNT; ++i) {
if (env->DAQ[i].RUNNING) {
env->STATE.DAQ_RUNNING = 1; // минимум один DAQ-лист запущен и работает
break;
}
}
env->STATE.RESUME = 0; // устройство в режиме RESUME
}
static uint8_t XCP_COMMAND_GET_STATUS_FD(tCanSerialPortFrameXCP *env) {
update_STATE(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 = env->STATE.STORE_CAL_REQ;
xcpCommand_GET_STATUS->reserve1 = 0;
xcpCommand_GET_STATUS->STORE_DAQ_REQ = env->STATE.STORE_DAQ_REQ;
xcpCommand_GET_STATUS->CLEAR_DAQ_REQ = env->STATE.CLEAR_DAQ_REQ;
xcpCommand_GET_STATUS->reserve2 = 0;
xcpCommand_GET_STATUS->reserve3 = 0;
xcpCommand_GET_STATUS->DAQ_RUNNING = env->STATE.DAQ_RUNNING;
xcpCommand_GET_STATUS->RESUME = env->STATE.RESUME; // устройство не в режиме RESUME
// Статус защиты ресурсов
xcpCommand_GET_STATUS->CAL_PAG = PROTECT_CAL_PAG; // защита команд калибровки/пагинации
xcpCommand_GET_STATUS->reserve5 = 0;
xcpCommand_GET_STATUS->DAQ = PROTECT_DAQ; // защита DAQ-команд
xcpCommand_GET_STATUS->STIM = PROTECT_STIM; // защита STIM-команд
xcpCommand_GET_STATUS->PGM = PROTECT_PGM; // защита команд программирования
xcpCommand_GET_STATUS->reserve6 = 0;
xcpCommand_GET_STATUS->reserve7 = 0;
xcpCommand_GET_STATUS->reserve8 = 0;
xcpCommand_GET_STATUS->STATE_NUMBER = 2; // номер состояния ECU
xcpCommand_GET_STATUS->SESSION_CONFIGURATION_ID = 0; // ID конфигурации сессии
return 6;
}
static uint8_t XCP_COMMAND_SYNCH_FC(tCanSerialPortFrameXCP *env) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_CMD_SYNCH;
return 2;
}
static uint8_t XCP_GET_COMM_MODE_INFO_FB(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 = MASTER_BLOCK_MODE;
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;
}
static uint8_t XCP_GET_SEED_F8(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 = 0x853A08FB;
env->RESOURCE = request->RESOURCE;
return 6;
}
static uint8_t XCP_UNLOCK_F7(tCanSerialPortFrameXCP *env) {
eXcpCommand_REQ_UNLOCK *request = (eXcpCommand_REQ_UNLOCK *) env->canFrame.data;
uint32_t securitySeedMy = generate_key(0x853A08FB);//SeedToKeyHVAC_NAMI(0, 0x11223344);
if (securitySeedMy != request->KEY) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
if (env->RESOURCE == XCP_PROTECT_CAL_PAG) {
env->PROTECT[0] = false;
}
if (env->RESOURCE == XCP_PROTECT_DAQ) {
env->PROTECT[1] = false;
}
if (env->RESOURCE == XCP_PROTECT_STM) {
env->PROTECT[2] = false;
}
if (env->RESOURCE == XCP_PROTECT_PGM) {
env->PROTECT[3] = false;
}
} else {
env->response[0] = XCP_COMMAND_CONNECT;
env->response[1] = 0;
if (env->RESOURCE == XCP_PROTECT_CAL_PAG) {
env->PROTECT[0] = true;
}
if (env->RESOURCE == XCP_PROTECT_DAQ) {
env->PROTECT[1] = true;
}
if (env->RESOURCE == XCP_PROTECT_STM) {
env->PROTECT[2] = true;
}
if (env->RESOURCE == XCP_PROTECT_PGM) {
env->PROTECT[3] = true;
}
}
return 2;
}
static uint8_t XCP_COMMAND_SET_MTA_F6(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;
env->bufWriteFlashCount = 0;
return 2;
}
*/
env->ADR_EXT = request->ADR_EX;
env->ADR_MTA = request->ADR;
env->response[0] = XCP_COMMAND_CONNECT;
env->bufWriteFlashAdr = env->ADR_MTA;
return 1;
}
static uint8_t XCP_COMMAND_UPLOAD_F5(tCanSerialPortFrameXCP *env) {
eXcpCommand_Upload *request = (eXcpCommand_Upload *) env->canFrame.data;
env->response[0] = XCP_COMMAND_CONNECT;
if (SLAVE_BLOCK_MODE) {
if (request->COUNT == 0) {
#if (LOG_XCP == 1)
PrintfDebug(env->response, 1);
LoggerFormatInfo(LOGGER, LOG_SIGN, "< [%d] %s", 1, strPrintfDebug_XCP)
#endif
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, 1, PROTOCOL_CAN_ADR_XCP,
PROTOCOL_CAN_TYPE_XCP,
1000);
return 0;
}
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;
#if (LOG_XCP == 1)
PrintfDebug(env->response, 7 + 1);
LoggerFormatInfo(LOGGER, LOG_SIGN, "< [%d] %s", 7 + 1, strPrintfDebug_XCP)
#endif
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, 7 + 1, PROTOCOL_CAN_ADR_XCP,
PROTOCOL_CAN_TYPE_XCP,
1000);
}
if (tailBlock > 0) {
memcpy(&env->response[1], (uint8_t *) (env->ADR_MTA), tailBlock);
env->ADR_MTA += tailBlock;
#if (LOG_XCP == 1)
PrintfDebug(env->response, tailBlock + 1);
LoggerFormatInfo(LOGGER, LOG_SIGN, "< [%d] %s", tailBlock + 1, strPrintfDebug_XCP)
#endif
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, tailBlock + 1, PROTOCOL_CAN_ADR_XCP,
PROTOCOL_CAN_TYPE_XCP, 1000);
}
return 0;
} else {
memcpy(&env->response[1], (uint8_t *) (env->ADR_MTA), request->COUNT);
env->ADR_MTA += request->COUNT;
return request->COUNT + 1;
}
}
static uint8_t XCP_COMMAND_SHORT_UPLOAD_F4(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;
}
static uint8_t XCP_COMMAND_DOWNLOAD_F0(tCanSerialPortFrameXCP *env) {
eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data;
#if (PROTECT_CAL_PAG == 1)
if (isUNLOCK(env, XCP_PROTECT_CAL_PAG) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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;
}
static uint8_t XCP_COMMAND_DOWNLOAD_NEXT_EF(tCanSerialPortFrameXCP *env) {
eXcpCommand_Download *request = (eXcpCommand_Download *) env->canFrame.data;
#if (PROTECT_CAL_PAG == 1)
if (isUNLOCK(env, XCP_PROTECT_CAL_PAG) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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;
env->response[2] = env->downloadRemaining;
return 3;
}
env->downloadRemaining -= COUNT;
if (env->downloadRemaining == 0) {
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
return 0;
}
static uint8_t XCP_COMMAND_DOWNLOAD_MAX_EE(tCanSerialPortFrameXCP *env) {
#if (PROTECT_CAL_PAG == 1)
if (isUNLOCK(env, XCP_PROTECT_CAL_PAG) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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;
}
static uint8_t XCP_CLEAR_DAQ_LIST_E3(tCanSerialPortFrameXCP *env) {
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_GET_DAQ_LIST_INFO_D8(tCanSerialPortFrameXCP *env) {
eXcpCommand_Get_DAQ_List_Info_Request *request = (eXcpCommand_Get_DAQ_List_Info_Request *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_DAQ;
xcpCommand_Get_DAQ_List_Info->FIXED_EVENT = 0;
return 6;
}
static uint8_t XCP_ALLOC_DAQ_D5(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_DAQ *request = (eXcpCommand_ALLOC_DAQ *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->SETUP.DAQ_COUNT = request->DAQ_COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_FREE_DAQ_D6(tCanSerialPortFrameXCP *env) {
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
FREE_DAQ(env);
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_ALLOC_ODT_D4(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_ODT *request = (eXcpCommand_ALLOC_ODT *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->DAQ[request->DAQ_LIST_NUMBER].ODT_COUNT = request->ODT_COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_ALLOC_ODT_ENTRY_D3(tCanSerialPortFrameXCP *env) {
eXcpCommand_ALLOC_ODT_ENTRY *request = (eXcpCommand_ALLOC_ODT_ENTRY *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->DAQ[request->DAQ_LIST_NUMBER].ODT_NUMBER[request->ODT_NUMBER].ODT_ENTRIES_COUNT = request->ODT_ENTRIES_COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_SET_DAQ_PTR_E2(tCanSerialPortFrameXCP *env) {
eXcpCommand_SET_DAQ_PTR *request = (eXcpCommand_SET_DAQ_PTR *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if ((request->DAQ_LIST_NUMBER > MAX_DAO) ||
(request->ODT_NUMBER > MAX_ODT) ||
(request->ODT_ENTRY_NUMBER > MAX_ODT_ENTRIES_SIZE_DAQ)) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
env->SETUP.DAQ_LIST_NUMBER = request->DAQ_LIST_NUMBER;
env->SETUP.ODT_NUMBER = request->ODT_NUMBER;
env->SETUP.ODT_ENTRY_NUMBER = request->ODT_ENTRY_NUMBER;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_WRITE_DAQ_E1(tCanSerialPortFrameXCP *env) {
eXcpCommand_WRITE_DAQ *request = (eXcpCommand_WRITE_DAQ *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (env->SETUP.ODT_ENTRY_NUMBER > MAX_ODT_ENTRIES_SIZE_DAQ) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].BIT_OFFSET[env->SETUP.ODT_ENTRY_NUMBER] = request->BIT_OFFSET;
env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ADR_EXT[env->SETUP.ODT_ENTRY_NUMBER] = request->ADR_EXT;
env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ODT_ENTRIES_ADR[env->SETUP.ODT_ENTRY_NUMBER] = request->ADR;
env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ODT_ENTRIES_SIZE[env->SETUP.ODT_ENTRY_NUMBER] = request->ODT_ENTRY_SIZE;
++env->SETUP.ODT_ENTRY_NUMBER;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_SET_DAQ_LIST_MODE_E0(tCanSerialPortFrameXCP *env) {
eXcpCommand_SET_DAQ_LIST_MODE *request = (eXcpCommand_SET_DAQ_LIST_MODE *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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].EVENT_CHANNEL = request->EVENT_CHANNEL_NUMBER;
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].TRANSMISSION_RATE_PRESCALER = request->TRANSMISSION_RATE_PRESCALER - 1;
env->DAQ[request->DAQ_LIST_NUMBER].DAQ_LIST_PRIORITY = request->DAQ_LIST_PRIORITY;
env->DAQ[request->DAQ_LIST_NUMBER].PRESCALER_COUNTER = request->TRANSMISSION_RATE_PRESCALER - 1;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_START_STOP_DAQ_LIST_DE(tCanSerialPortFrameXCP *env) {
eXcpCommand_START_STOP_DAQ_LIST *request = (eXcpCommand_START_STOP_DAQ_LIST *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (request->DAQ_LIST_NUMBER > MAX_DAO) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
if (request->MODE == XCP_STOP) {
env->DAQ[request->DAQ_LIST_NUMBER].RUNNING = 0;
}
if (request->MODE == XCP_START) {
env->DAQ[request->DAQ_LIST_NUMBER].RUNNING = 1;
}
if (request->MODE == XCP_SELECT) {
env->DAQ[request->DAQ_LIST_NUMBER].SELECTED = 1;
}
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_START_STOP_SYNCH_DD(tCanSerialPortFrameXCP *env) {
eXcpCommand_START_STOP_SYNCH *request = (eXcpCommand_START_STOP_SYNCH *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (request->MODE == XCP_SYNC_START_SEL) {
for (uint16 i = 0; i < MAX_DAO; ++i) {
if (env->DAQ[i].SELECTED) {
env->DAQ[i].RUNNING = 1;
}
}
}
if (request->MODE == XCP_SYNC_STOP_ALL) {
for (uint16 i = 0; i < MAX_DAO; ++i) {
env->DAQ[i].RUNNING = 0;
}
FREE_DAQ(env);
}
if (request->MODE == XCP_SYNC_STOP_SEL) {
for (uint16 i = 0; i < MAX_DAO; ++i) {
if (env->DAQ[i].SELECTED) {
env->DAQ[i].RUNNING = 1;
}
}
}
env->response[0] = XCP_COMMAND_CONNECT;
return 2;
}
static uint8_t XCP_READ_DAQ_DB(tCanSerialPortFrameXCP *env) {
eXcpCommand_WRITE_DAQ *response = (eXcpCommand_WRITE_DAQ *) env->response;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
response->COM = XCP_COMMAND_CONNECT;
response->BIT_OFFSET = env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].BIT_OFFSET[env->SETUP.ODT_ENTRY_NUMBER];
response->ADR_EXT = env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ADR_EXT[env->SETUP.ODT_ENTRY_NUMBER];
response->ADR = env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ODT_ENTRIES_ADR[env->SETUP.ODT_ENTRY_NUMBER];
response->ODT_ENTRY_SIZE = env->DAQ[env->SETUP.DAQ_LIST_NUMBER].ODT_NUMBER[env->SETUP.ODT_NUMBER].ODT_ENTRIES_SIZE[env->SETUP.ODT_ENTRY_NUMBER];
++env->SETUP.ODT_ENTRY_NUMBER;
return 8;
}
static uint8_t XCP_GET_DAQ_PROCESSOR_INFO_DA(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_DAQ_PROCESSOR_INFO *response = (eXcpCommand_GET_DAQ_PROCESSOR_INFO *) env->response;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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;
}
static uint8_t XCP_GET_DAQ_RESOLUTION_INFO_D9(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_DAQ_RESOLUTION_INFO *response = (eXcpCommand_GET_DAQ_RESOLUTION_INFO *) env->response;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
response->COM = XCP_COMMAND_CONNECT;
response->GRANULARITY_ODT_ENTRY_SIZE_DAQ = 1;
response->MAX_ODT_ENTRY_SIZE_DAQ = MAX_ODT_ENTRIES_SIZE_DAQ;
response->GRANULARITY_ODT_ENTRY_SIZE_STIM = 1;
response->MAX_ODT_ENTRY_SIZE_STIM = MAX_ODT_ENTRIES_SIZE_DAQ;
response->TIMESTAMP_MODE = 0;
response->TIMESTAMP_TICKS = 0;
return 8;
}
static uint8_t XCP_GET_DAQ_LIST_MODE_DF(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_DAQ_LIST_MODE_GET *request = (eXcpCommand_GET_DAQ_LIST_MODE_GET *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_MODE *response = (eXcpCommand_GET_DAQ_LIST_MODE *) env->response;
response->COM = XCP_COMMAND_CONNECT;
response->SELECTED = env->DAQ[request->DAQ_LIST_NUMBER].SELECTED;
response->DIRECTION = env->DAQ[request->DAQ_LIST_NUMBER].DIRECTION;
response->RESERVED1 = 0;
response->DTO_CTR = env->DAQ[request->DAQ_LIST_NUMBER].DTO_CTR;
response->TIMESTAMP = env->DAQ[request->DAQ_LIST_NUMBER].TIMESTAMP;
response->PID_OFF = env->DAQ[request->DAQ_LIST_NUMBER].PID_OFF;
response->RUNNING = env->DAQ[request->DAQ_LIST_NUMBER].RUNNING;
response->RESUME = 0;
response->RESERVED2 = 0;
response->CURRENT_EVENT_CHANNEL_NUMBER = env->DAQ[request->DAQ_LIST_NUMBER].EVENT_CHANNEL;
response->CURRENT_PRESCALER = env->DAQ[request->DAQ_LIST_NUMBER].TRANSMISSION_RATE_PRESCALER;
response->CURRENT_DAQ_LIST_PRIORITY = env->DAQ[request->DAQ_LIST_NUMBER].DAQ_LIST_PRIORITY;
return 8;
}
static uint8_t XCP_GET_DAQ_EVENT_INFO_D7(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_DAQ_EVENT_INFO_GET *request = (eXcpCommand_GET_DAQ_EVENT_INFO_GET *) env->canFrame.data;
#if (PROTECT_DAQ == 1)
if (isUNLOCK(env, XCP_PROTECT_DAQ) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (request->EVENT_CHANNEL_NUMBER > MAX_EVENT_CHANNEL) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_OUT_OF_RANGE;
return 2;
}
eXcpCommand_GET_DAQ_EVENT_INFO *response = (eXcpCommand_GET_DAQ_EVENT_INFO *) env->response;
response->COM = XCP_COMMAND_CONNECT;
response->RESERVED1 = 0;
response->RESERVED2 = 0;
if (request->EVENT_CHANNEL_NUMBER == 0) { // DTO-STIM
response->DAQ = 1;
response->STM = 0;
} else { // DTO-DAQ
response->DAQ = 0;
response->STM = 1;
}
response->RESERVED3 = 0;
response->RESERVED4 = 0;
response->CONSISTENCY_DAQ = 0;
response->CONSISTENCY_EVENT = 0;
response->MAX_DAQ_LIST = 255;
response->EVENT_CHANNEL_NAME_LENGTH = 0;
response->EVENT_CHANNEL_TIME_CYCLE = 1;
response->EVENT_CHANNEL_TIME_UNIT = 7; // EVENT_CHANNEL _TIME_UNIT_10MS
response->EVENT_CHANNEL_PRIORITY = 255;
return 7;
}
static uint8_t XCP_GET_DAQ_STM(tCanSerialPortFrameXCP *env) {
eXcpCommand_GET_DAQ_STM *response = (eXcpCommand_GET_DAQ_STM *) env->canFrame.data;
uint8_t *COUNTER = &env->DAQ[response->DAQ].ODT_NUMBER[response->ODT].DATA_STM_COUNTER;
memcpy(env->DAQ[response->DAQ].ODT_NUMBER[response->ODT].DATA_STM[*COUNTER].DATA, &env->canFrame.data[3],
env->canFrame.dlc - 2);
++env->DAQ[response->DAQ].ODT_NUMBER[response->ODT].DATA_STM_COUNTER;
if (*COUNTER == env->DAQ[response->DAQ].ODT_COUNT) {
*COUNTER = 0;
env->DAQ[response->DAQ].IS_STIM_RECEIVED = 1;
}
return 0;
}
static uint8_t XCP_PROGRAM_START_D2(tCanSerialPortFrameXCP *env) {
eXcpCommand_PROGRAM_START *response = (eXcpCommand_PROGRAM_START *) env->response;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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 = SLAVE_BLOCK_MODE;
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_D1(tCanSerialPortFrameXCP *env) {
eXcpCommand_XCP_PROGRAM_CLEAR_D1 *request = (eXcpCommand_XCP_PROGRAM_CLEAR_D1 *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_D0(tCanSerialPortFrameXCP *env) {
eXcpCommand_Program_ProgramNext_D0_CA *request = (eXcpCommand_Program_ProgramNext_D0_CA *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
uint8_t COUNT = env->canFrame.dlc - 2;
for (uint8_t i = 0; i < COUNT; ++i) {
env->bufWriteFlash[env->bufWriteFlashCount] = env->canFrame.data[2 + i];
++env->bufWriteFlashCount;
if (env->bufWriteFlashCount >= PROGRAM_MAX_BUF) {
bool result = env->write_flash_func(env->bufWriteFlashAdr, env->bufWriteFlash, PROGRAM_MAX_BUF);
env->bufWriteFlashAdr += PROGRAM_MAX_BUF;
env->bufWriteFlashCount = 0;
}
}
env->ADR_MTA += request->COUNT;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t PROGRAM_VERIFY_C8(tCanSerialPortFrameXCP *env) {
eXcpCommand_Program_Verify_C8 *request = (eXcpCommand_Program_Verify_C8 *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (env->bufWriteFlashCount > 0) {
bool result = env->write_flash_func(env->bufWriteFlashAdr, env->bufWriteFlash, env->bufWriteFlashCount);
env->bufWriteFlashCount = 0;
}
VarsTabDumpObserverCalib_Load(env->varsTabDumpObserver);
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_PROGRAM_NEXT_CA(tCanSerialPortFrameXCP *env) {
eXcpCommand_Program_ProgramNext_D0_CA *request = (eXcpCommand_Program_ProgramNext_D0_CA *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_PREPARE_CC(tCanSerialPortFrameXCP *env) {
eXcpCommand_Program_Prepare_CC *request = (eXcpCommand_Program_Prepare_CC *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if ((env->ADR_MTA < env->startFlashAdr) || ((env->ADR_MTA + request->CODESIZE) > env->endFlashAdr)) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_GENERIC;
return 2;
}
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_PROGRAM_FORMAT_CB(tCanSerialPortFrameXCP *env) {
eXcpCommand_Program_Format_CB *request = (eXcpCommand_Program_Format_CB *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_PROGRAM_RESET_CF(tCanSerialPortFrameXCP *env) {
env->response[0] = XCP_COMMAND_CONNECT;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
if (env->bufWriteFlashCount > 0) {
bool result = env->write_flash_func(env->bufWriteFlashAdr, env->bufWriteFlash, env->bufWriteFlashCount);
env->bufWriteFlashCount = 0;
}
return 1;
}
static uint8_t XCP_GET_PGM_PROCESSOR_INFO_CE(tCanSerialPortFrameXCP *env) {
eXcpCommand_PGM_PROCESSOR_INFO_CE *response = (eXcpCommand_PGM_PROCESSOR_INFO_CE *) env->response;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_CD(tCanSerialPortFrameXCP *env) {
eXcpCommand_REQ_GET_SECTOR_INFO_CD *request = (eXcpCommand_REQ_GET_SECTOR_INFO_CD *) env->canFrame.data;
#if (PROTECT_PGM == 1)
if (isUNLOCK(env, XCP_PROTECT_PGM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
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_CD *response = (eXcpCommand_RESP_GET_SECTOR_INFO_CD *) 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;
}
static uint8_t XCP_SET_CALIBRATION_PAGE_EB(tCanSerialPortFrameXCP *env) {
eXcpCommand_SET_CALIBRATION_PAGE_EB *request = (eXcpCommand_SET_CALIBRATION_PAGE_EB *) env->canFrame.data;
env->PAGE_ID = request->PAGE;
env->response[0] = XCP_COMMAND_CONNECT;
return 1;
}
static uint8_t XCP_GET_CAL_PAGE_EA(tCanSerialPortFrameXCP *env) {
eXcpCommand_XCP_GET_CAL_PAGE_EA *request = (eXcpCommand_XCP_GET_CAL_PAGE_EA *) env->canFrame.data;
#if (PROTECT_CAL_PAG == 1)
if (isUNLOCK(env, XCP_PROTECT_CAL_PAG) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
return 2;
}
#endif
env->response[0] = XCP_COMMAND_CONNECT;
env->response[1] = env->PAGE_ID;
return 2;
}
const eXcp_com xcp_com[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, ""}, // 0xC5 DTO_CTR_PROPERTIES
{NULL, ""}, // 0xC6 TIME_CORRELATION_PROPERTIES
{NULL, ""}, // 0xC7 WRITE_DAQ_MULTIPLE
{PROGRAM_VERIFY_C8, "PROGRAM_VERIFY_C8"},
{NULL, ""}, // 0xC9 PROGRAM_MAX (This command does not support block transfer)
{XCP_PROGRAM_NEXT_CA, "XCP_PROGRAM_NEXT_CA"},
{XCP_PROGRAM_FORMAT_CB, "XCP_PROGRAM_FORMAT_CB"}, // 0xCB PROGRAM_FORMAT
{XCP_PROGRAM_PREPARE_CC, "XCP_PROGRAM_PREPARE_CC"}, // 0xCC PROGRAM_PREPARE
{XCP_GET_SECTOR_INFO_CD, "XCP_GET_SECTOR_INFO_CD"},
{XCP_GET_PGM_PROCESSOR_INFO_CE, "XCP_GET_PGM_PROCESSOR_INFO_CE"},
{XCP_PROGRAM_RESET_CF, "XCP_PROGRAM_RESET_CF"},
{XCP_PROGRAM_D0, "XCP_PROGRAM_D0"}, // This command does not support block transfer
{XCP_PROGRAM_CLEAR_D1, "XCP_PROGRAM_CLEAR_D1"},
{XCP_PROGRAM_START_D2, "XCP_PROGRAM_START_D2"},
{XCP_ALLOC_ODT_ENTRY_D3, "XCP_ALLOC_ODT_ENTRY_D3"},
{XCP_ALLOC_ODT_D4, "XCP_ALLOC_ODT_D4"},
{XCP_ALLOC_DAQ_D5, "XCP_ALLOC_DAQ_D5"},
{XCP_FREE_DAQ_D6, "XCP_FREE_DAQ_D6"},
{XCP_GET_DAQ_EVENT_INFO_D7, "XCP_GET_DAQ_EVENT_INFO_D7"},
{XCP_GET_DAQ_LIST_INFO_D8, "XCP_GET_DAQ_LIST_INFO_D8"},
{XCP_GET_DAQ_RESOLUTION_INFO_D9, "XCP_GET_DAQ_RESOLUTION_INFO_D9"},
{XCP_GET_DAQ_PROCESSOR_INFO_DA, "XCP_GET_DAQ_PROCESSOR_INFO_DA"},
{XCP_READ_DAQ_DB, "XCP_READ_DAQ_DB"},
{NULL, ""}, //0xDC GET_DAQ_CLOCK
{XCP_START_STOP_SYNCH_DD, "XCP_START_STOP_SYNCH_DD"},
{XCP_START_STOP_DAQ_LIST_DE, "XCP_START_STOP_DAQ_LIST_DE"},
{XCP_GET_DAQ_LIST_MODE_DF, "XCP_GET_DAQ_LIST_MODE_DF"},
{XCP_SET_DAQ_LIST_MODE_E0, "XCP_SET_DAQ_LIST_MODE_E0"},
{XCP_WRITE_DAQ_E1, "XCP_WRITE_DAQ_E1"},
{XCP_SET_DAQ_PTR_E2, "XCP_SET_DAQ_PTR_E2"},
{XCP_CLEAR_DAQ_LIST_E3, "XCP_CLEAR_DAQ_LIST_E3"},
{NULL, ""}, // 0xE4 COPY_CAL_PAGE
{NULL, ""}, // 0xE5 GET_SEGMENT_MODE
{NULL, ""}, // 0xE6 SET_SEGMENT_MODE
{NULL, ""}, // 0xE7 GET_PAGE_INFO
{NULL, ""}, // 0xE8 GET_SEGMENT_INFO
{NULL, ""}, // 0xE9 GET_PAG_PROCESSOR_INFO
{XCP_GET_CAL_PAGE_EA, "XCP_GET_CAL_PAGE_EA"}, // 0xEA GET_CAL_PAGE
{XCP_SET_CALIBRATION_PAGE_EB, "XCP_SET_CALIBRATION_PAGE_EB"},
{NULL, ""}, // 0xEC MODIFY_BITS
{NULL, ""}, // 0xEB SHORT_DOWNLOAD (This command does not support block transfer)
{XCP_COMMAND_DOWNLOAD_MAX_EE, "XCP_COMMAND_DOWNLOAD_MAX_EE"}, // This command does not support block transfer
{XCP_COMMAND_DOWNLOAD_NEXT_EF, "XCP_COMMAND_DOWNLOAD_NEXT_EF"},
{XCP_COMMAND_DOWNLOAD_F0, "XCP_COMMAND_DOWNLOAD_F0"},
{NULL, ""}, // 0XF1 USER_CMD
{NULL, ""}, // 0xF2 DOWNLOAD
{NULL, ""}, // 0xF3 DOWNLOAD_NEXT
{XCP_COMMAND_SHORT_UPLOAD_F4, "XCP_COMMAND_SHORT_UPLOAD_F4"}, // This command does not support block transfer
{XCP_COMMAND_UPLOAD_F5, "XCP_COMMAND_UPLOAD_F5"},
{XCP_COMMAND_SET_MTA_F6, "XCP_COMMAND_SET_MTA_F6"},
{XCP_UNLOCK_F7, "XCP_UNLOCK_F7"},
{XCP_GET_SEED_F8, "XCP_GET_SEED_F8"},
{NULL, ""}, // 0xF9 SET_REQUEST
{NULL, ""}, // 0xFA GET_ID
{XCP_GET_COMM_MODE_INFO_FB, "XCP_GET_COMM_MODE_INFO_FB"},
{XCP_COMMAND_SYNCH_FC, "XCP_COMMAND_SYNCH_FC"},
{XCP_COMMAND_GET_STATUS_FD, "XCP_COMMAND_GET_STATUS_FD"},
{XCP_COMMAND_DISCONNECT_FE, "XCP_COMMAND_DISCONNECT_FE"},
{XCP_COMMAND_CONNECT_FF, "XCP_COMMAND_CONNECT_FF"}
};
uint8_t vCanSerialPortFrameXcpReceive(tCanSerialPortFrameXCP *env, uint32 timeout) {
uint8_t response_size = 0;
uint16_t recv = env->ioCanFrame->receive(env->ioCanFrame->env, PROTOCOL_CAN_XCP, (uint8_t *) &env->canFrame,
1,
timeout);
if (recv == 0)
return 0;
if (osMutexAcquire(env->access, 100) == osOK) {
eXcpTypeCommand com = env->canFrame.data[0];
if (com > 0xBF) { // CMD
#if (LOG_XCP == 1)
if ((com != 0xD0) && (com != 0xF5)) {
PrintfDebug(env->canFrame.data, env->canFrame.dlc);
LoggerFormatInfo(LOGGER, LOG_SIGN, "> %s [%d] %s", xcp_com[com].desc, env->canFrame.dlc, strPrintfDebug_XCP)
}
#endif
if (xcp_com[com].func != NULL) {
response_size = xcp_com[com].func(env);
if (response_size) {
#if (LOG_XCP == 1)
if ((com != 0xD0) && (com != 0xF5)) {
PrintfDebug(env->response, response_size);
LoggerFormatInfo(LOGGER, LOG_SIGN, "< [%d] %s", response_size, strPrintfDebug_XCP)
}
#endif
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, response_size,
PROTOCOL_CAN_ADR_XCP,
PROTOCOL_CAN_TYPE_XCP, timeout);
}
} else {
asm("nop");
}
} else { // ODT
#if (PROTECT_STIM == 1)
if (isUNLOCK(env, XCP_PROTECT_STM) == false) {
env->response[0] = XCP_COMMAND_DISCONNECT;
env->response[1] = XCP_ERR_ACCESS_LOCKED;
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, 2,
PROTOCOL_CAN_ADR_XCP,
PROTOCOL_CAN_TYPE_XCP, timeout);
#endif
} else {
XCP_GET_DAQ_STM(env);
}
}
osMutexRelease(env->access);
}
return response_size;
}
_Noreturn void CanXcpProcessing_Service_Dto_Stim_Task(tCanSerialPortFrameXCP *env) {
uint8_t size;
while (1) {
if (osMutexAcquire(env->access, 1000) == osOK) {
for (uint16 i = 0; i < env->SETUP.DAQ_COUNT; ++i) {
if ((env->DAQ[i].DIRECTION == 1) &&
(env->DAQ[i].EVENT_CHANNEL == 0) &&
(env->DAQ[i].RUNNING)) { // STIM - DTO
if (env->DAQ[i].PRESCALER_COUNTER == 0) {
env->DAQ[i].PRESCALER_COUNTER = env->DAQ[i].TRANSMISSION_RATE_PRESCALER;
if (env->DAQ[i].IS_STIM_RECEIVED) {
for (uint8_t j = 0; j < env->DAQ[i].ODT_COUNT; ++j) {
size = 0;
for (uint8_t k = 0; k < MAX_ODT_ENTRIES_SIZE_DAQ; ++k) {
uint8_t ODT_ENTRIES_SIZE = env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_SIZE[k];
if (ODT_ENTRIES_SIZE) {
memcpy(&env->DATA[size],
env->DAQ[i].ODT_NUMBER[j].DATA_STM[k].DATA,
ODT_ENTRIES_SIZE);
size += ODT_ENTRIES_SIZE;
}
}
uint8_t size_stim = 0;
for (uint8_t k = 0; k < MAX_ODT_ENTRIES_SIZE_DAQ; ++k) {
uint8_t ODT_ENTRIES_SIZE = env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_SIZE[k];
if (ODT_ENTRIES_SIZE) {
if ((size_stim + ODT_ENTRIES_SIZE) <= size) {
memcpy((uint8_t *) env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_ADR[k],
&env->DAQ[i].ODT_NUMBER[j].DATA_STM[k].DATA[size_stim],
ODT_ENTRIES_SIZE);
size_stim += ODT_ENTRIES_SIZE;
} else {
asm("nop");
}
}
}
}
env->DAQ[i].IS_STIM_RECEIVED = 0;
} else {
asm("nop");
}
} else {
--env->DAQ[i].PRESCALER_COUNTER;
}
}
}
osMutexRelease(env->access);
}
SystemDelayMs(10);
}
}
void Dto_Daq(tCanSerialPortFrameXCP *env, uint16_t channel, uint32_t timeout) {
uint8_t size;
if (osMutexAcquire(env->access, 1000) == osOK) {
for (uint16 i = 0; i < env->SETUP.DAQ_COUNT; ++i) {
if ((env->DAQ[i].DIRECTION == 0) &&
(env->DAQ[i].EVENT_CHANNEL == channel) &&
(env->DAQ[i].RUNNING)) { // DAQ - DTO
if (env->DAQ[i].PRESCALER_COUNTER == 0) {
env->DAQ[i].PRESCALER_COUNTER = env->DAQ[i].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
size = 0;
for (uint8_t k = 0; k < MAX_ODT_ENTRIES_SIZE_DAQ; ++k) {
uint8_t ODT_ENTRIES_SIZE = env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_SIZE[k];
if (ODT_ENTRIES_SIZE) {
memcpy(&env->DATA[size],
(uint8_t *) env->DAQ[i].ODT_NUMBER[j].ODT_ENTRIES_ADR[k],
ODT_ENTRIES_SIZE);
size += ODT_ENTRIES_SIZE;
}
}
uint8_t count_size = size / BODY_MAX_LEN;
uint8_t count_size_tail = size % BODY_MAX_LEN;
size = 0;
for (uint8_t k = 0; k < count_size; ++k) {
memcpy(&env->response[2], &env->DATA[size], BODY_MAX_LEN);
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response, MAX_DTO,
PROTOCOL_CAN_ADR_XCP, PROTOCOL_CAN_TYPE_XCP,
1000);
size += BODY_MAX_LEN;
}
if (count_size_tail) {
memcpy(&env->response[2], &env->DATA[size], count_size_tail);
env->ioCanFrame->transmit(env->ioCanFrame->env, env->response,
count_size_tail + 2,
PROTOCOL_CAN_ADR_XCP, PROTOCOL_CAN_TYPE_XCP,
1000);
}
}
} else {
--env->DAQ[i].PRESCALER_COUNTER;
}
}
}
osMutexRelease(env->access);
}
SystemDelayMs(timeout);
}
_Noreturn void CanXcpProcessing_Service_Dto_Daq_10_Task(tCanSerialPortFrameXCP *env) {
while (1) {
Dto_Daq(env, 1, 10);
}
}
_Noreturn void CanXcpProcessing_Service_Dto_Daq_100_Task(tCanSerialPortFrameXCP *env) {
while (1) {
Dto_Daq(env, 2, 100);
}
}
_Noreturn void CanXcpProcessing_Service_Dto_Daq_1000_Task(tCanSerialPortFrameXCP *env) {
while (1) {
Dto_Daq(env, 3, 1000);
}
}
void CanXcpProcessing_Service_Start(tCanSerialPortFrameXCP *env) {
InitThreadBlock(env->T_can_Listener_Dto_Stim_XCP, "DtoStim_XCP", osPriorityNormal);
ThreadBlock_Start(env->T_can_Listener_Dto_Stim_XCP, env, CanXcpProcessing_Service_Dto_Stim_Task);
InitThreadBlock(env->T_can_Listener_Dto_Daq_10_XCP, "DtoDaq_10_XCP", osPriorityNormal);
ThreadBlock_Start(env->T_can_Listener_Dto_Daq_10_XCP, env, CanXcpProcessing_Service_Dto_Daq_10_Task);
InitThreadBlock(env->T_can_Listener_Dto_Daq_100_XCP, "DtoDaq_100_XCP", osPriorityNormal);
ThreadBlock_Start(env->T_can_Listener_Dto_Daq_100_XCP, env, CanXcpProcessing_Service_Dto_Daq_100_Task);
InitThreadBlock(env->T_can_Listener_Dto_Daq_1000_XCP, "DtoDaq_1000_XCP", osPriorityNormal);
ThreadBlock_Start(env->T_can_Listener_Dto_Daq_1000_XCP, env, CanXcpProcessing_Service_Dto_Daq_1000_Task);
}
_Noreturn void CanXcpProcessing_ListenerTask(tCanSerialPortFrameXCP *env) {
while (1) {
vCanSerialPortFrameXcpReceive(env, 1000);
}
}
void CanXcpProcessing_Listener_Start(tCanSerialPortFrameXCP *env) {
ThreadBlock_Start(env->T_can_Listener_XCP, env, CanXcpProcessing_ListenerTask);
CanXcpProcessing_Service_Start(env);
}