296 lines
9.8 KiB
C
296 lines
9.8 KiB
C
//
|
||
// Created by CFIF on 13.11.22.
|
||
//
|
||
#include <stdbool.h>
|
||
#include "LoggerToSerialPort.h"
|
||
#include "SystemDelayInterface.h"
|
||
#include "AsciiStringAssmeblingUtils.h"
|
||
#include "Rtc.h"
|
||
#include <time.h>
|
||
#include "CmsisRtosThreadUtils.h"
|
||
#include "memory.h"
|
||
#include CMSIS_device_header
|
||
|
||
static uint8_t *
|
||
getMemLoggerBufLog(tLoggerToSerialPort *env, char *authorStatic, const uint8_t authorLen, LOG_BUF_TYPE logBufType) {
|
||
|
||
for (uint8_t i = 0; i < env->countBufLoggerNames; ++i) {
|
||
if (memcmp(env->bufLoggerNames[i], authorStatic, authorLen) == 0) {
|
||
|
||
if (logBufType == LOG_BUF_SMALL) {
|
||
return env->bufLogger[i].buf_small;
|
||
}
|
||
|
||
if (logBufType == LOG_BUF_BIG1) {
|
||
return env->bufLogger[i].buf_big1;
|
||
}
|
||
|
||
return env->bufLogger[i].buf_big2;
|
||
}
|
||
}
|
||
|
||
configASSERT(env->countBufLoggerNames < MAX_COUNT_BUF_LOG);
|
||
|
||
uint8_t len = authorLen;
|
||
if (authorLen > MAX_LEN_BUF_NAME_LOG) {
|
||
len = MAX_LEN_BUF_NAME_LOG;
|
||
}
|
||
|
||
memcpy(env->bufLoggerNames[env->countBufLoggerNames], authorStatic, len);
|
||
++env->countBufLoggerNames;
|
||
|
||
if (logBufType == LOG_BUF_SMALL) {
|
||
return env->bufLogger[env->countBufLoggerNames - 1].buf_small;
|
||
}
|
||
|
||
if (logBufType == LOG_BUF_BIG1) {
|
||
return env->bufLogger[env->countBufLoggerNames - 1].buf_big1;
|
||
}
|
||
|
||
return env->bufLogger[env->countBufLoggerNames - 1].buf_big2;
|
||
|
||
}
|
||
|
||
static void LoggerToSerialPort_TimeToString(time_t timestamp, char *strbuf) {
|
||
struct tm timestampTM;
|
||
localtime_r(×tamp, ×tampTM);
|
||
asctime_r(×tampTM, strbuf);
|
||
}
|
||
|
||
static uint32_t LoggerToSerialPort_PrintLegend(
|
||
tLoggerToSerialPort *env,
|
||
char *outStr[],
|
||
char *authorStatic,
|
||
const uint8_t authorLen,
|
||
eLoggerLevel loglevel
|
||
) {
|
||
//char str[128];
|
||
char *str = (char *) getMemLoggerBufLog(env, authorStatic, authorLen, LOG_BUF_BIG1);
|
||
size_t strLen = 0;
|
||
|
||
if (env->flags & (SERIAL_LOGGER_SHOW_DATE | SERIAL_LOGGER_SHOW_TIME)) {
|
||
|
||
time_t timestamp;
|
||
//char timeString[24];
|
||
char *timeString = (char *) getMemLoggerBufLog(env, authorStatic, authorLen, LOG_BUF_SMALL);
|
||
|
||
if (env->rtc) {
|
||
RtcGet(env->rtc, ×tamp);
|
||
timestamp += env->greenwichOffset * 3600;
|
||
} else {
|
||
uint32_t msFromDeviceStart = SystemGetMs() / 1000;
|
||
timestamp = 1672531200 + msFromDeviceStart;
|
||
}
|
||
|
||
LoggerToSerialPort_TimeToString(timestamp, timeString);
|
||
|
||
if (env->flags & SERIAL_LOGGER_SHOW_DATE) {
|
||
vAsciiStringAdd(str, &strLen, &timeString[20], 4);
|
||
vAsciiStringAdd(str, &strLen, &timeString[3], 7);
|
||
vAsciiStringAdd(str, &strLen, " ", 1);
|
||
}
|
||
|
||
if (env->flags & SERIAL_LOGGER_SHOW_TIME) {
|
||
vAsciiStringAdd(str, &strLen, &timeString[11], 8);
|
||
vAsciiStringAdd(str, &strLen, " ", 1);
|
||
}
|
||
}
|
||
|
||
if (env->flags & SERIAL_LOGGER_SHOW_AUTHOR) {
|
||
//выводим автора сообщения
|
||
vAsciiStringAdd(str, &strLen, authorStatic, authorLen);
|
||
}
|
||
|
||
if (env->flags & SERIAL_LOGGER_SHOW_LOG_LEVEL) {
|
||
tStringStatic levelName = LOGGER_LEVEL_NAMES[loglevel];
|
||
//выводим уровень сообщения
|
||
vAsciiStringAddChar(str, &strLen, '[');
|
||
vAsciiStringAdd(str, &strLen, levelName.data, levelName.length);
|
||
vAsciiStringAddChar(str, &strLen, ']');
|
||
}
|
||
|
||
|
||
//разделитель
|
||
if (env->flags)
|
||
vAsciiStringAdd(str, &strLen, ": ", 2);
|
||
|
||
// SerialPortTransmit(env->serialPortIo_VIRT, (uint8_t *) str, strLen, env->timeout);
|
||
*outStr = str;
|
||
|
||
env->open = true;
|
||
|
||
return strLen;
|
||
}
|
||
|
||
#include <stddef.h> // для offsetof
|
||
|
||
static void LoggerCanToSerialPort_Logging(
|
||
tLoggerToSerialPort *env,
|
||
uint16_t mChannel,
|
||
uint8_t mFlags,
|
||
uint8_t mDLC,
|
||
uint32_t mID,
|
||
uint8_t *mData,
|
||
uint32_t timestamp
|
||
) {
|
||
if (osMutexAcquire(env->access, env->timeout) == osOK) {
|
||
CanLogPacket_t *pkt = (CanLogPacket_t*)env->bufLoggerCan;
|
||
|
||
// Заполняем структуру
|
||
pkt->start_pkt = 0x02;
|
||
pkt->type_pkt = 1;
|
||
pkt->timestamp = timestamp;
|
||
pkt->channel = mChannel;
|
||
pkt->flags = mFlags;
|
||
pkt->dlc = mDLC;
|
||
pkt->id = mID;
|
||
|
||
// Копируем данные (только mDLC байт)
|
||
if (mData != NULL && mDLC > 0) {
|
||
memcpy(pkt->data, mData, mDLC);
|
||
}
|
||
// Остальные байты data[8] не трогаем – они не будут отправлены
|
||
|
||
// Вычисляем len_pkt = полезная нагрузка (без start, type, len, end)
|
||
pkt->len_pkt = (4 + 1 + 1 + 4 + mDLC + 1); // = mDLC + 11 (без CRC)
|
||
|
||
// Размер данных без завершающих байтов (CRC и 0x03)
|
||
size_t data_size = offsetof(CanLogPacket_t, data) + mDLC; // от начала пакета до конца данных
|
||
|
||
// Вычисляем CRC как сумму всех байтов, кроме pkt->start_pkt,
|
||
// т.е. начиная с type_pkt и заканчивая последним байтом данных
|
||
uint8_t crc = 0;
|
||
uint8_t *crc_start = (uint8_t*)pkt + 1; // пропускаем start_pkt
|
||
size_t crc_len = data_size - 1; // размер данных для CRC (без start_pkt)
|
||
for (size_t i = 0; i < crc_len; i++) {
|
||
crc += crc_start[i];
|
||
}
|
||
|
||
// Записываем CRC после данных
|
||
uint8_t *crc_ptr = (uint8_t*)pkt + data_size;
|
||
*crc_ptr = crc;
|
||
|
||
// Записываем байт 0x03 после CRC
|
||
uint8_t *end_ptr = (uint8_t*)pkt + data_size + 1;
|
||
*end_ptr = 0x03;
|
||
|
||
// Размер для отправки: от начала до 0x03 включительно
|
||
size_t pkt_size = data_size + 2; // данные + CRC + 0x03
|
||
|
||
// Отправка
|
||
SerialPortTransmit(env->serialPortIo_VIRT, env->bufLoggerCan, pkt_size, env->timeout);
|
||
|
||
osMutexRelease(env->access);
|
||
}
|
||
}
|
||
|
||
static void LoggerToSerialPort_Logging(
|
||
tLoggerToSerialPort *env,
|
||
char *authorStatic,
|
||
const uint8_t authorLen,
|
||
eLoggerLevel loglevel,
|
||
char *msg,
|
||
uint16_t msgLen,
|
||
bool complete
|
||
) {
|
||
|
||
// uint32_t adr = *(uint32_t *)(env->serialPortIo->env);
|
||
|
||
// uint32_t timeoutLocal = env->timeout;
|
||
// Если это UART (виртуальный)
|
||
// if (adr < PERIPH_BASE) {
|
||
// env->timeout = 0;
|
||
// }
|
||
char *outStr = NULL;
|
||
uint32_t lenStr;
|
||
|
||
// if (!env->open) {
|
||
lenStr = LoggerToSerialPort_PrintLegend(env, &outStr, authorStatic, authorLen, loglevel);
|
||
// }
|
||
|
||
if (osMutexAcquire(env->access, env->timeout) == osOK) {
|
||
|
||
//выводим сообщение
|
||
if (outStr != NULL) {
|
||
SerialPortTransmit(env->serialPortIo_VIRT, (uint8_t *) outStr, lenStr, env->timeout);
|
||
}
|
||
|
||
SerialPortTransmit(env->serialPortIo_VIRT, (uint8_t *) msg, msgLen, env->timeout);
|
||
|
||
if (complete) {
|
||
//переводим строку
|
||
SerialPortTransmit(env->serialPortIo_VIRT, (uint8_t *) "\r\n", 2, env->timeout);
|
||
// env->open = false;
|
||
} else {
|
||
// env->open = true;
|
||
}
|
||
osMutexRelease(env->access);
|
||
}
|
||
|
||
// env->timeout = timeoutLocal;
|
||
}
|
||
|
||
void LoggerToSerialPort_Cmd(tLoggerToSerialPort *env, char *msg, uint16_t msgLen) {
|
||
|
||
if (osMutexAcquire(env->access, env->timeout) == osOK) {
|
||
SerialPortTransmit(env->serialPortIo_VIRT, (uint8_t *) msg, msgLen, env->timeout);
|
||
osMutexRelease(env->access);
|
||
}
|
||
}
|
||
|
||
void LoggerToSerialPort_Init(
|
||
tLoggerToSerialPort *env,
|
||
int32_t greenwichOffset,
|
||
tSerialPortIO *serialPortIo_VIRT,
|
||
tSerialPortIO *serialPortIo_PHYSIC,
|
||
tRtcIO *rtc,
|
||
uint16_t flags,
|
||
uint32_t timeoutTransmittedLog
|
||
) {
|
||
env->serialPortIo_VIRT = serialPortIo_VIRT;
|
||
env->serialPortIo_PHYSIC = serialPortIo_PHYSIC;
|
||
env->open = false;
|
||
env->timeout = 0;// не ждем на каждой операции так как если порт исправен то все должно отрабатывать моментально
|
||
env->logger.env = env;
|
||
env->greenwichOffset = greenwichOffset;
|
||
env->logger.logging = (LoggerGenericMethod) LoggerToSerialPort_Logging;
|
||
|
||
env->logger.loggingCan = (LoggerGenericCanMethod) LoggerCanToSerialPort_Logging;
|
||
|
||
env->logger.getMemPrintfBufLog = (getMemPrintfBufLogMethod) getMemLoggerBufLog;
|
||
env->rtc = rtc;
|
||
env->flags = flags;
|
||
env->timeoutTransmittedLog = timeoutTransmittedLog;
|
||
|
||
env->access = osMutexNew(NULL);
|
||
|
||
// env->showDate = showDate;
|
||
// env->showTime = showTime;
|
||
// env->showLoglevel = showLoglevel;
|
||
// env->showAuthor = showAuthor;
|
||
|
||
InitThreadAtrStatic(&env->thread.attr, "LogTransmitter", env->thread.controlBlock, env->thread.stack,
|
||
osPriorityNormal);
|
||
|
||
LogTransmitter_StartThread(env);
|
||
}
|
||
|
||
|
||
static _Noreturn void LogTransmitter_Thread(tLoggerToSerialPort *env) {
|
||
for (;;) {
|
||
uint16_t len = env->serialPortIo_VIRT->receive(env->serialPortIo_VIRT->env, env->buf_LOG,
|
||
sizeof(env->buf_LOG), env->timeoutTransmittedLog);
|
||
|
||
if (len > 0) {
|
||
len = env->serialPortIo_PHYSIC->transmit(env->serialPortIo_PHYSIC->env, env->buf_LOG,
|
||
len, env->timeoutTransmittedLog);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void LogTransmitter_StartThread(tLoggerToSerialPort *env) {
|
||
if (!env->thread.id) {
|
||
env->thread.id = osThreadNew((osThreadFunc_t) (LogTransmitter_Thread), (void *) (env), &env->thread.attr);
|
||
}
|
||
} |