This commit is contained in:
cfif 2025-06-02 14:32:56 +03:00
commit 9611aacdf5
3 changed files with 721 additions and 0 deletions

155
Inc/CanSerialPortFrameTP.h Normal file
View File

@ -0,0 +1,155 @@
//
// Created by cfif on 16.03.2024.
//
#ifndef CAN_MODULE_CAN_FRAME_UDS_H
#define CAN_MODULE_CAN_FRAME_UDS_H
#include "SerialPortFrameIO.h"
#include "SerialPortFrameTpIO.h"
#include "CanSerialPortFrame.h"
#include "LoggerToSerialPort.h"
#include "CmsisRtosThreadUtils.h"
#include "SystemMutexCmsis.h"
#define TP_FRAME_PADDING 0xaa
#define WAIT_FC_FRAME_TIMEOUT 200
#define WAIT_FF_FRAME_TIMEOUT 300
#define WAIT_FRAME_WRITE 300
typedef enum {
TP_TYPE_FRAME_SF = 0,
TP_TYPE_FRAME_FF = 1,
TP_TYPE_FRAME_CF = 2,
TP_TYPE_FRAME_FC = 3
} eTpTypeFrame;
typedef enum {
TP_RECEIVED_DATA = 0,
TP_RECEIVED_FC_DATA = 1,
TP_ERROR_FS_ERROR_SIZE = 2,
TP_ERROR_FC_TIMEOUT = 3,
TP_ERROR_FC_ERROR = 4,
TP_ERROR_FF_ERROR = 5,
TP_ERROR_FF_ERROR_SIZE = 6,
TP_ERROR_FF_ERROR_TIMEOUT = 7,
TP_ERROR_CF_ERROR = 8,
TP_ERROR_CF_ERROR_SIZE = 9,
TP_ERROR_CF_ERROR_SN = 10,
TP_ERROR_WRONG_ADDRESS= 11,
TP_STANDBY = 12
} eTpResult;
typedef struct __attribute__ ((packed)) {
eTpTypeFrame typeFrame: 4;
} eTpFrameHead;
typedef struct __attribute__ ((packed)) {
uint8_t dl: 4;
eTpTypeFrame typeFrame: 4;
uint8_t data[7];
} eTpFrameSF;
typedef struct __attribute__ ((packed)) {
uint8_t dlM: 4;
eTpTypeFrame typeFrame: 4;
uint8_t dlL;
uint8_t data[6];
} eTpFrameFF;
typedef struct __attribute__ ((packed)) {
uint8_t sn: 4;
eTpTypeFrame typeFrame: 4;
uint8_t data[7];
} eTpFrameCF;
typedef struct __attribute__ ((packed)) {
uint8_t status: 4;
eTpTypeFrame typeFrame: 4;
uint8_t blockSize;
uint8_t timeST;
} eTpFrameFC;
typedef struct {
uint32_t adrCan;
uint16_t len;
uint8_t data[50];
} tCanTP_data;
typedef struct {
uint32_t adrCan;
uint16_t len;
uint8_t data[1024];
} tCanTP_Ext_data;
typedef void (*tReceivedTP_func)(void *arg, tCanTP_data *data);
typedef bool (*tReceivedCan_func)(void *arg, can_rx_message_type *data);
typedef struct {
tSerialPortFrameIO *ioCanFrame;
tLoggerToSerialPort *slog;
char hexString[2048 * 2];
volatile bool isFlowControl;
SystemMutexCmsis txAccessQueue;
uint32_t timeoutFF;
tCanTP_data *dataBuf;
uint16_t dataBufMaxSize;
uint16_t dataBufWorkLen;
uint16_t dataBufLen;
uint16_t dataReceivedConsecutiveFrameLen;
uint8_t sn;
tReceivedCan_func ReceivedCan_func;
void *callback_argCan;
tReceivedTP_func receivedTP_func;
void *callback_argTp;
uint8_t filterIdCount;
uint32_t *filterReqId;
uint32_t *filterRespId;
uint8_t *filterDirReq;
uint8_t numBuf;
tStaticThreadBlock(1024) T_can_Listener0;
tStaticThreadBlock(1024) T_can_Listener1;
} tCanSerialPortFrameTp;
void CanSerialPortFrameTpInit(
tCanSerialPortFrameTp *env,
uint8_t numBuf,
SystemMutexCmsis txAccessQueue,
tReceivedCan_func receivedCan_func,
void *callback_argCan,
tReceivedTP_func receivedTP_func,
void *callback_argTp,
tSerialPortFrameIO *ioCanFrame,
tCanTP_data *dataBuf,
uint16_t dataBufMaxSize,
tLoggerToSerialPort *slog,
uint8_t filterIdCount,
uint32_t *filterReqId,
uint32_t *filterRespId,
uint8_t *filterDirReq
);
void CanSerialPortFrameTp_Start(tCanSerialPortFrameTp *env, uint8_t numBuf);
bool
CanSerialPortFrameTpTransmit(tCanSerialPortFrameTp *env, uint8_t *data, uint16_t size, uint32_t id, uint32_t timeout);
#endif //CAN_MODULE_CAN_FRAME_UDS_H

549
Src/CanSerialPortFrameTP.c Normal file
View File

@ -0,0 +1,549 @@
//
// Created by cfif on 16.03.2024.
//
#include <SystemDelayInterface.h>
#include "CanSerialPortFrameTP.h"
#include "memory.h"
#include "AsciiStringAssmeblingUtils.h"
#include "SystemMutexCmsis.h"
#define LOG_SIGN "CAN"
#define LOGGER &env->slog->logger
_Noreturn void CanTpProcessing_ListenerTask0(tCanSerialPortFrameTp *env);
_Noreturn void CanTpProcessing_ListenerTask1(tCanSerialPortFrameTp *env);
void CanSerialPortFrameTpInit(
tCanSerialPortFrameTp *env,
uint8_t numBuf,
SystemMutexCmsis txAccessQueue,
tReceivedCan_func receivedCan_func,
void *callback_argCan,
tReceivedTP_func receivedTP_func,
void *callback_arg,
tSerialPortFrameIO *ioCanFrame,
tCanTP_data *dataBuf,
uint16_t dataBufMaxSize,
tLoggerToSerialPort *slog,
uint8_t filterIdCount,
uint32_t *filterReqId,
uint32_t *filterRespId,
uint8_t *filterDirReq
) {
env->ioCanFrame = ioCanFrame;
env->numBuf = numBuf;
env->txAccessQueue = txAccessQueue;
env->dataBuf = dataBuf;
env->dataBufMaxSize = dataBufMaxSize;
env->dataBufLen = 0;
env->dataBufWorkLen = 0;
env->isFlowControl = false;
env->filterIdCount = filterIdCount;
env->filterReqId = filterReqId;
env->filterRespId = filterRespId;
env->filterDirReq = filterDirReq;
env->dataReceivedConsecutiveFrameLen = 0;
env->ReceivedCan_func = receivedCan_func;
env->callback_argCan = callback_argCan;
env->receivedTP_func = receivedTP_func;
env->callback_argTp = callback_arg;
env->timeoutFF = 0;
env->slog = slog;
InitThreadBlock(env->T_can_Listener0, "CanListener0", osPriorityNormal);
InitThreadBlock(env->T_can_Listener1, "CanListener1", osPriorityNormal);
}
void CanSerialPortFrameTp_Start(tCanSerialPortFrameTp *env, uint8_t numBuf) {
if (numBuf == 0)
ThreadBlock_Start(env->T_can_Listener0, env, CanTpProcessing_ListenerTask0);
if (numBuf == 1)
ThreadBlock_Start(env->T_can_Listener1, env, CanTpProcessing_ListenerTask1);
}
char *sendLogCanHex(tCanSerialPortFrameTp *env, uint8_t *data, size_t size) {
memset(env->hexString, 0, sizeof(env->hexString));
size_t len = 0;
vAsciiStringAddBytesAsHex(env->hexString, &len, data, size);
LoggerStrInfo(LOGGER, LOG_SIGN, env->hexString, strlen(env->hexString));
return env->hexString;
}
uint16_t sendFlowFrame(tCanSerialPortFrameTp *env, uint32_t id, uint32_t timeout) {
uint8_t dataTpFrame[8];
memset(dataTpFrame, TP_FRAME_PADDING, sizeof(dataTpFrame));
eTpFrameFC *frame = (eTpFrameFC *) dataTpFrame;
frame->typeFrame = TP_TYPE_FRAME_FC;
frame->status = 0;
frame->blockSize = 0;
frame->timeST = 0;
uint16_t sent = 0;
if (osMutexAcquire(env->txAccessQueue, 1000) == osOK) {
CanSerialPortFrameSetId(env->ioCanFrame->env, id);
sent = env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) frame, 8, timeout);
osMutexRelease(env->txAccessQueue);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа sendFlowFrame")
}
return sent;
}
eTpResult vCanSerialPortFrameTpReceive(tCanSerialPortFrameTp *env, uint32_t timeout) {
can_rx_message_type canFrame;
if ((env->timeoutFF > 0) && (env->timeoutFF < SystemGetMs())) {
env->timeoutFF = 0;
env->dataReceivedConsecutiveFrameLen = 0;
env->dataBufLen = 0;
env->dataBufWorkLen = 0;
return TP_ERROR_FF_ERROR_TIMEOUT;
}
uint16_t recv = 0;
if (env->numBuf == 0) {
recv = env->ioCanFrame->receive0(env->ioCanFrame->env, (uint8_t *) &canFrame, 1, timeout);
}
if (env->numBuf == 1) {
recv = env->ioCanFrame->receive1(env->ioCanFrame->env, (uint8_t *) &canFrame, 1, timeout);
}
if (recv == 0)
return TP_STANDBY;
bool isTesterPresent = env->ReceivedCan_func(env->callback_argCan, &canFrame);
if (isTesterPresent) {
// return TP_STANDBY;
}
bool isFilterFind = false;
uint32_t reqId = 0;
for (uint8_t i = 0; i < env->filterIdCount; ++i) {
if (canFrame.standard_id == env->filterReqId[i]) {
reqId = env->filterRespId[i];
isFilterFind = true;
break;
}
}
if (!isFilterFind) {
return TP_ERROR_WRONG_ADDRESS;
}
if ((recv > 0) && (canFrame.dlc == 8)) {
// Flow control Frame FC фрейм управления потоком
if ((canFrame.data[0] >> 4) == TP_TYPE_FRAME_FC) {
eTpFrameFC *frame = (eTpFrameFC *) canFrame.data;
if (frame->status == 0)
return TP_RECEIVED_FC_DATA;
return TP_ERROR_FC_ERROR;
}
// Single Frame SF Однократный фрейм
if ((canFrame.data[0] >> 4) == TP_TYPE_FRAME_SF) {
eTpFrameSF *frame = (eTpFrameSF *) canFrame.data;
if (frame->dl < env->dataBufMaxSize) {
//memcpy(env->dataBuf, &canFrame.data[1], frame->dl);
env->dataBufLen = frame->dl;
memcpy(env->dataBuf->data, &canFrame.data[1], frame->dl);
env->dataBuf->len = env->dataBufLen;
env->dataBuf->adrCan = canFrame.standard_id;
env->dataBufWorkLen = 0;
return TP_RECEIVED_DATA;
} else {
env->dataBufWorkLen = 0;
return TP_ERROR_FS_ERROR_SIZE;
}
}
// First Frame FF Первый фрейм из серии фреймов
if ((canFrame.data[0] >> 4) == TP_TYPE_FRAME_FF) {
if (env->dataReceivedConsecutiveFrameLen) {
return TP_ERROR_FF_ERROR;
}
eTpFrameFF *frame = (eTpFrameFF *) canFrame.data;
if (env->dataBufWorkLen + (frame->dlL | (frame->dlM << 8)) > env->dataBufMaxSize) {
return TP_ERROR_FF_ERROR_SIZE;
}
uint16_t dll = frame->dlL | (frame->dlM << 8);
if (dll > 100) {
asm("nop");
}
env->timeoutFF = SystemGetMs() + WAIT_FF_FRAME_TIMEOUT;
env->sn = 1;
env->dataBufWorkLen = 0;
env->dataReceivedConsecutiveFrameLen = (frame->dlL | (frame->dlM << 8));
for (uint8_t j = 2; j < 8; ++j) {
//env->dataBuf[env->dataBufWorkLen] = canFrame.data[j];
env->dataBuf->data[env->dataBufWorkLen] = canFrame.data[j];
++env->dataBufWorkLen;
if (env->dataBufWorkLen > env->dataBufMaxSize) {
env->timeoutFF = 0;
env->dataReceivedConsecutiveFrameLen = 0;
env->dataBufWorkLen = 0;
return TP_ERROR_CF_ERROR_SIZE;
}
--env->dataReceivedConsecutiveFrameLen;
}
sendFlowFrame(env, reqId, WAIT_FRAME_WRITE);
}
// Consecutive Frame CF последующий фрейм.
if ((canFrame.data[0] >> 4) == TP_TYPE_FRAME_CF) {
if (env->dataReceivedConsecutiveFrameLen == 0) {
return TP_ERROR_CF_ERROR;
}
eTpFrameCF *frame = (eTpFrameCF *) canFrame.data;
if (frame->sn != env->sn) {
env->timeoutFF = 0;
env->dataReceivedConsecutiveFrameLen = 0;
env->dataBufWorkLen = 0;
return TP_ERROR_CF_ERROR_SN;
}
++env->sn;
if (env->sn > 15)
env->sn = 0;
for (uint8_t j = 1; j < 8; ++j) {
//env->dataBuf[env->dataBufWorkLen] = canFrame.data[j];
env->dataBuf->data[env->dataBufWorkLen] = canFrame.data[j];
++env->dataBufWorkLen;
if (env->dataBufWorkLen > env->dataBufMaxSize) {
env->timeoutFF = 0;
env->dataReceivedConsecutiveFrameLen = 0;
env->dataBufWorkLen = 0;
return TP_ERROR_CF_ERROR_SIZE;
}
--env->dataReceivedConsecutiveFrameLen;
if (env->dataReceivedConsecutiveFrameLen == 0) {
env->timeoutFF = 0;
env->dataBufLen = env->dataBufWorkLen;
env->dataBuf->len = env->dataBufLen;
env->dataBuf->adrCan = canFrame.standard_id;
env->dataBufWorkLen = 0;
return TP_RECEIVED_DATA;
}
}
}
}
return TP_ERROR_FC_TIMEOUT;
}
_Noreturn void CanTpProcessing_ListenerTask0(tCanSerialPortFrameTp *env) {
while (1) {
eTpResult result = vCanSerialPortFrameTpReceive(env, 1000);
if (result == TP_RECEIVED_FC_DATA) {
if (env->isFlowControl) {
env->isFlowControl = false;
// LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Принят Flow control Frame");
} else {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Принят не ожидаемый Flow control Frame");
}
}
if (result == TP_RECEIVED_DATA) {
// LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Приняты данные: ");
// sendLogCanHex(env, env->dataBuf->data, env->dataBuf->len);
env->receivedTP_func(env->callback_argTp, env->dataBuf);
}
if (result == TP_ERROR_FS_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Переполнение приемного буфера (1)");
}
if (result == TP_ERROR_FC_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Выставлен статус ошибки в Flow control Frame");
}
if (result == TP_ERROR_FF_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN,
"0: Ошибка. Принят First Frame FF, но еще не завершен прием Consecutive Frame");
}
if (result == TP_ERROR_FF_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Переполнение приемного буфера (2)");
}
if (result == TP_ERROR_CF_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Принят не ожидаемый Consecutive Frame");
}
if (result == TP_ERROR_CF_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Переполнение приемного буфера (3)");
}
if (result == TP_ERROR_CF_ERROR_SN) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Ошибка. Не совпадение счетчика SN в Consecutive Frame");
}
if (result == TP_ERROR_FF_ERROR_TIMEOUT) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "0: Истекло время ожидания приема Consecutive Frame");
}
}
}
_Noreturn void CanTpProcessing_ListenerTask1(tCanSerialPortFrameTp *env) {
while (1) {
eTpResult result = vCanSerialPortFrameTpReceive(env, 1000);
if (result == TP_RECEIVED_FC_DATA) {
if (env->isFlowControl) {
env->isFlowControl = false;
// LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Принят Flow control Frame");
} else {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Принят не ожидаемый Flow control Frame");
}
}
if (result == TP_RECEIVED_DATA) {
// LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Приняты данные: ");
// sendLogCanHex(env, env->dataBuf->data, env->dataBuf->len);
env->receivedTP_func(env->callback_argTp, env->dataBuf);
}
if (result == TP_ERROR_FS_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Переполнение приемного буфера (1)");
}
if (result == TP_ERROR_FC_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Выставлен статус ошибки в Flow control Frame");
}
if (result == TP_ERROR_FF_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN,
"1: Ошибка. Принят First Frame FF, но еще не завершен прием Consecutive Frame");
}
if (result == TP_ERROR_FF_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Переполнение приемного буфера (2)");
}
if (result == TP_ERROR_CF_ERROR) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Принят не ожидаемый Consecutive Frame");
}
if (result == TP_ERROR_CF_ERROR_SIZE) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Переполнение приемного буфера (3)");
}
if (result == TP_ERROR_CF_ERROR_SN) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Ошибка. Не совпадение счетчика SN в Consecutive Frame");
}
if (result == TP_ERROR_FF_ERROR_TIMEOUT) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "1: Истекло время ожидания приема Consecutive Frame");
}
}
}
uint16_t sendSingleFrame(tCanSerialPortFrameTp *env, uint8_t *data, uint16_t size, uint32_t id, uint32_t timeout) {
uint8_t dataTpFrame[8];
memset(dataTpFrame, TP_FRAME_PADDING, sizeof(dataTpFrame));
eTpFrameSF *frame = (eTpFrameSF *) dataTpFrame;
frame->typeFrame = TP_TYPE_FRAME_SF;
frame->dl = size;
memcpy(&frame->data[0], data, size);
uint16_t sent = 0;
if (osMutexAcquire(env->txAccessQueue, 1000) == osOK) {
CanSerialPortFrameSetId(env->ioCanFrame->env, id);
sent = env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) frame, 8, timeout);
osMutexRelease(env->txAccessQueue);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа sendSingleFrame")
}
return sent;
}
uint16_t sendConsecutiveFrame(tCanSerialPortFrameTp *env, uint8_t *data, uint16_t size, uint32_t id, uint8_t sn,
uint32_t timeout) {
uint8_t dataTpFrame[8];
memset(dataTpFrame, TP_FRAME_PADDING, sizeof(dataTpFrame));
eTpFrameCF *frame = (eTpFrameCF *) dataTpFrame;
frame->typeFrame = TP_TYPE_FRAME_CF;
frame->sn = sn;
memcpy(&frame->data[0], data, size);
uint16_t sent = 0;
if (osMutexAcquire(env->txAccessQueue, 1000) == osOK) {
CanSerialPortFrameSetId(env->ioCanFrame->env, id);
sent = env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) frame, 8, timeout);
osMutexRelease(env->txAccessQueue);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа sendConsecutiveFrame")
}
return sent;
}
bool waitFlowControl(tCanSerialPortFrameTp *env) {
env->isFlowControl = true;
uint32_t timeEnd = SystemGetMs() + WAIT_FC_FRAME_TIMEOUT;
while (timeEnd > SystemGetMs()) {
if (!env->isFlowControl) {
break;
}
}
if (env->isFlowControl) {
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Таймаут ожидания Flow control Frame");
return false;
}
return true;
}
bool sendFirstFrame(tCanSerialPortFrameTp *env, uint8_t *data, uint16_t size, uint32_t id, uint32_t timeout) {
uint8_t dataTpFrame[8];
uint16_t pDataLen = 0;
memset(dataTpFrame, TP_FRAME_PADDING, sizeof(dataTpFrame));
eTpFrameFF *frame = (eTpFrameFF *) dataTpFrame;
frame->typeFrame = TP_TYPE_FRAME_FF;
frame->dlL = size;
frame->dlM = (size >> 8);
memcpy(&frame->data[0], &data[pDataLen], 6);
pDataLen += 6;
uint16_t sent = 0;
if (osMutexAcquire(env->txAccessQueue, 1000) == osOK) {
CanSerialPortFrameSetId(env->ioCanFrame->env, id);
sent = env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) frame, 8, timeout);
osMutexRelease(env->txAccessQueue);
} else {
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка доступа sendFirstFrame")
}
bool result = waitFlowControl(env);
if (!result)
return false;
uint16_t countPacketFull = (size - 6) / 7;
uint16_t sizePacketTail = (size - 6) % 7;
uint8_t sn = 1;
for (uint16_t i = 0; i < countPacketFull; ++i) {
sendConsecutiveFrame(env, &data[pDataLen], 7, id, sn, timeout);
pDataLen += 7;
++sn;
if (sn == 15)
sn = 1;
}
if (sizePacketTail) {
sendConsecutiveFrame(env, &data[pDataLen], sizePacketTail, id, sn, timeout);
pDataLen += sizePacketTail;
}
return true;
}
bool
CanSerialPortFrameTpTransmit(tCanSerialPortFrameTp *env, uint8_t *data, uint16_t size, uint32_t id, uint32_t timeout) {
bool result;
// Single Frame SF
if (size <= 7) {
result = sendSingleFrame(env, data, size, id, timeout);
} else {
result = sendFirstFrame(env, data, size, id, timeout);
}
return result;
}

17
modular.json Normal file
View File

@ -0,0 +1,17 @@
{
"dep": [
{
"type": "git",
"provider": "Smart_Components_Aurus",
"repo": "SerialPort"
}
],
"cmake": {
"inc_dirs": [
"Inc"
],
"srcs": [
"Src/**.c"
]
}
}