LoggerToSerialPort/Src/LoggerToSerialPort.c

300 lines
9.8 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 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(&timestamp, &timestampTM);
asctime_r(&timestampTM, 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, &timestamp);
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 == 1024) {
asm("nop");
}
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);
}
}