337 lines
15 KiB
C
337 lines
15 KiB
C
/**
|
||
* @file blf.h
|
||
* @brief Заголовочный файл библиотеки для создания BLF-файлов (Vector).
|
||
* @details Определяет структуры, константы и функции для работы с форматом BLF.
|
||
* Поддерживает stdio (ПК) и FatFS (встраиваемые системы) через условную компиляцию.
|
||
* Не использует динамическую память – контекст выделяется пользователем.
|
||
*
|
||
* @author (Ваше имя)
|
||
* @date 2026-03-20
|
||
*/
|
||
|
||
#ifndef BLF_H
|
||
#define BLF_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Обёртка для вывода ошибок (может быть переопределена до включения заголовка)
|
||
* ------------------------------------------------------------------------- */
|
||
#ifndef BLF_ERROR_PRINTF
|
||
#include <stdio.h>
|
||
#define BLF_ERROR_PRINTF(...) printf(__VA_ARGS__)
|
||
#endif
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Константы формата BLF (сигнатуры, типы объектов, флаги)
|
||
* ------------------------------------------------------------------------- */
|
||
#define BL_FILE_SIGNATURE 0x47474F4Cu /* "LOGG" – сигнатура файла */
|
||
#define BL_OBJ_SIGNATURE 0x4A424F4Cu /* "LOBJ" – сигнатура объекта */
|
||
#define BL_OBJ_TYPE_CAN_MESSAGE 1 /* CAN-сообщение */
|
||
#define BL_OBJ_TYPE_LIN_MESSAGE 11 /* LIN-сообщение */
|
||
#define BL_OBJ_TYPE_LIN_SND_ERROR 15 /* Ошибка отправки LIN */
|
||
#define BL_OBJ_TYPE_LOG_CONTAINER 10 /* Контейнер */
|
||
#define BL_OBJ_TYPE_ENV_DATA 9 /* Данные окружения (ENV_DATA) */
|
||
#define BL_OBJ_FLAG_TIME_ONE_NANS 0x00000002 /* Временная метка в наносекундах */
|
||
|
||
/* Флаги CAN-сообщения: бит 7 = RTR, биты 0-3 = направление */
|
||
#define CAN_MSG_FLAGS(dir, rtr) \
|
||
((uint8_t)(((uint8_t)(rtr & 0x01) << 7) | ((uint8_t)(dir & 0x0F))))
|
||
#define CAN_DIR_TX 1 /* передача */
|
||
#define CAN_DIR_RX 0 /* приём */
|
||
|
||
/* Направления LIN-сообщений */
|
||
#define LIN_DIR_RX 0
|
||
#define LIN_DIR_TX 1
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Упакованные структуры BLF (соответствуют двоичному формату Vector)
|
||
* ------------------------------------------------------------------------- */
|
||
#if defined(_MSC_VER)
|
||
#pragma pack(push, 1)
|
||
#else
|
||
#define PACKED __attribute__((packed))
|
||
#endif
|
||
|
||
/* Системное время (используется в заголовке файла) */
|
||
typedef struct PACKED {
|
||
uint16_t year; /* год */
|
||
uint16_t month; /* месяц (1–12) */
|
||
uint16_t dayOfWeek; /* день недели (0–6, 0 = воскресенье) */
|
||
uint16_t day; /* день месяца */
|
||
uint16_t hour; /* часы (0–23) */
|
||
uint16_t minute; /* минуты (0–59) */
|
||
uint16_t second; /* секунды (0–59) */
|
||
uint16_t milliseconds; /* миллисекунды (0–999) */
|
||
} SYSTEMTIME;
|
||
|
||
/**
|
||
* @brief Заголовок BLF-файла (структура FileStatistics).
|
||
* @details Размер 144 байта. Содержит общую информацию о файле.
|
||
*/
|
||
typedef struct PACKED {
|
||
uint32_t signature; /* "LOGG" */
|
||
uint32_t statisticsSize; /* sizeof(FileHeader) = 144 */
|
||
uint32_t apiNumber; /* версия API, например 4070100 */
|
||
uint8_t applicationId; /* 1 = CANalyzer/CANoe */
|
||
uint8_t compressionLevel; /* 0 – без сжатия */
|
||
uint8_t applicationMajor; /* старшая версия приложения */
|
||
uint8_t applicationMinor; /* младшая версия приложения */
|
||
uint64_t fileSize; /* полный размер файла (с выравниванием) */
|
||
uint64_t uncompressedFileSize; /* размер несжатых данных */
|
||
uint32_t objectCount; /* количество объектов верхнего уровня */
|
||
uint32_t applicationBuild; /* номер сборки приложения */
|
||
SYSTEMTIME measurementStartTime; /* время начала записи */
|
||
SYSTEMTIME lastObjectTime; /* время последнего объекта */
|
||
uint64_t restorePointsOffset; /* смещение до точек восстановления (0) */
|
||
uint32_t reservedFileStatistics[16]; /* зарезервировано */
|
||
} FileHeader;
|
||
|
||
/* Базовый заголовок объекта (16 байт) */
|
||
typedef struct PACKED {
|
||
uint32_t mSignature; /* "LOBJ" */
|
||
uint16_t mHeaderSize; /* размер полного заголовка (обычно sizeof(VBLObjectHeader)) */
|
||
uint16_t mHeaderVersion; /* версия заголовка (1) */
|
||
uint32_t mObjectSize; /* полный размер объекта (заголовок + данные) */
|
||
uint32_t mObjectType; /* тип объекта */
|
||
} VBLObjectHeaderBase;
|
||
|
||
/* Полный заголовок объекта версии 1 (32 байта) */
|
||
typedef struct PACKED {
|
||
VBLObjectHeaderBase mBase; /* базовые поля */
|
||
uint32_t mObjectFlags; /* флаги (например, временная метка в наносекундах) */
|
||
uint16_t mClientIndex; /* индекс клиента (обычно 0) */
|
||
uint16_t mObjectVersion; /* версия данных объекта (0) */
|
||
uint64_t mObjectTimeStamp; /* временная метка (наносекунды) */
|
||
} VBLObjectHeader;
|
||
|
||
/* Данные CAN-сообщения (16 байт) */
|
||
typedef struct PACKED {
|
||
uint16_t mChannel; /* номер канала */
|
||
uint8_t mFlags; /* бит 7 = RTR, остальные – направление */
|
||
uint8_t mDLC; /* длина данных (0-8) */
|
||
uint32_t mID; /* идентификатор */
|
||
uint8_t mData[8]; /* данные */
|
||
} VBLCANMessage;
|
||
|
||
/* Данные LIN-сообщения (устаревший тип, 20 байт) */
|
||
typedef struct PACKED {
|
||
uint16_t mChannel;
|
||
uint8_t mID; /* идентификатор (6 бит) */
|
||
uint8_t mDLC;
|
||
uint8_t mData[8];
|
||
uint8_t mFSMId; /* всегда 0 */
|
||
uint8_t mFSMState; /* всегда 0 */
|
||
uint8_t mHeaderTime; /* длительность заголовка в битовых временах */
|
||
uint8_t mFullTime; /* длительность всего кадра в битовых временах */
|
||
uint16_t mCRC; /* контрольная сумма */
|
||
uint8_t mDir; /* направление */
|
||
uint8_t mReserved;
|
||
} VBLLINMessage;
|
||
|
||
/* Данные ошибки LIN (отсутствие ответа, 10 байт) */
|
||
typedef struct PACKED {
|
||
uint16_t mChannel;
|
||
uint8_t mID;
|
||
uint8_t mDLC;
|
||
uint8_t mFSMId;
|
||
uint8_t mFSMState;
|
||
uint8_t mHeaderTime;
|
||
uint8_t mFullTime;
|
||
} VBLLINSendError;
|
||
|
||
/* Дополнительные данные контейнера (тип 10) */
|
||
typedef struct PACKED {
|
||
uint16_t compressionMethod; /* 0 – без сжатия */
|
||
uint16_t reserved1;
|
||
uint32_t reserved2;
|
||
uint32_t uncompressedFileSize; /* размер данных внутри контейнера */
|
||
uint32_t reserved3;
|
||
} LogContainerData;
|
||
|
||
/* Полный заголовок контейнера (базовый + данные) */
|
||
typedef struct PACKED {
|
||
VBLObjectHeaderBase base;
|
||
LogContainerData data;
|
||
} ContainerHeader;
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Удобные структуры для передачи данных (в миллисекундах)
|
||
* ------------------------------------------------------------------------- */
|
||
typedef struct PACKED {
|
||
uint8_t channel;
|
||
uint32_t id;
|
||
uint8_t flags;
|
||
uint8_t dlc;
|
||
uint8_t data[8];
|
||
uint32_t timestamp; /* в миллисекундах */
|
||
} CanMessageStruct;
|
||
|
||
typedef struct PACKED {
|
||
uint8_t channel;
|
||
uint8_t id;
|
||
uint8_t dlc;
|
||
uint8_t data[8];
|
||
uint8_t dir;
|
||
uint32_t timestamp; /* в миллисекундах */
|
||
uint16_t checksum;
|
||
} LinMessageStruct;
|
||
|
||
typedef struct PACKED {
|
||
uint8_t channel;
|
||
uint8_t id;
|
||
uint8_t dlc;
|
||
uint32_t timestamp; /* в миллисекундах */
|
||
} LinSendErrorStruct;
|
||
|
||
typedef struct PACKED {
|
||
char name[4]; /* имя переменной (до 3 символов) */
|
||
const uint8_t* data;
|
||
uint32_t data_len;
|
||
uint32_t timestamp; /* в миллисекундах */
|
||
} EnvDataStruct;
|
||
|
||
|
||
/* Возврат к стандартному выравниванию */
|
||
#if defined(_MSC_VER)
|
||
#pragma pack(pop)
|
||
#else
|
||
#undef PACKED
|
||
#endif
|
||
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Контекст BLF-файла (полное определение – для выделения на стеке)
|
||
* ------------------------------------------------------------------------- */
|
||
/* Условное включение дескриптора файла в зависимости от USE_FATFS */
|
||
#ifdef USE_FATFS
|
||
#include "ff.h" /* FatFS */
|
||
typedef FIL BlfFileHandle;
|
||
#else
|
||
#include <stdio.h>
|
||
typedef FILE* BlfFileHandle;
|
||
#endif
|
||
|
||
typedef struct {
|
||
BlfFileHandle fp; /* дескриптор файла */
|
||
FileHeader header; /* заголовок файла (будет перезаписан в конце) */
|
||
long headerPos; /* позиция заголовка в файле */
|
||
int objectCount; /* количество объектов верхнего уровня */
|
||
uint64_t maxTimestamp; /* максимальная временная метка (для lastObjectTime) */
|
||
int in_container; /* флаг: внутри контейнера */
|
||
ContainerHeader container_hdr; /* заголовок открытого контейнера */
|
||
long container_hdr_pos; /* позиция заголовка контейнера в файле */
|
||
uint64_t container_timestamp; /* временная метка контейнера */
|
||
} BLFContext;
|
||
|
||
/* -------------------------------------------------------------------------
|
||
* Прототипы функций API
|
||
* ------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* @brief Инициализирует BLF-контекст и создаёт новый файл.
|
||
* @param ctx Указатель на предварительно выделенный контекст.
|
||
* @param filename Имя файла.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_open(BLFContext *ctx, const char *filename);
|
||
|
||
/**
|
||
* @brief Начинает новый контейнер (объект типа LOG_CONTAINER).
|
||
* @param ctx Контекст.
|
||
* @param timestamp Временная метка контейнера (наносекунды).
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_start_container(BLFContext *ctx, uint64_t timestamp);
|
||
|
||
/**
|
||
* @brief Завершает текущий контейнер, обновляя его заголовок.
|
||
* @param ctx Контекст.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_end_container(BLFContext *ctx);
|
||
|
||
/**
|
||
* @brief Добавляет CAN-сообщение.
|
||
* @param ctx Контекст.
|
||
* @param channel Номер канала.
|
||
* @param id Идентификатор.
|
||
* @param flags Флаги (направление, RTR).
|
||
* @param dlc Длина данных (0-8).
|
||
* @param data Данные (если NULL, заполняет нулями).
|
||
* @param timestamp Временная метка в наносекундах.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_add_can_message(BLFContext *ctx,
|
||
uint16_t channel,
|
||
uint32_t id,
|
||
uint8_t flags,
|
||
uint8_t dlc,
|
||
const uint8_t *data,
|
||
uint64_t timestamp);
|
||
|
||
/**
|
||
* @brief Добавляет LIN-сообщение (устаревший тип).
|
||
* @param ctx Контекст.
|
||
* @param channel Номер канала.
|
||
* @param id Идентификатор (6 бит).
|
||
* @param dlc Длина данных.
|
||
* @param data Данные.
|
||
* @param dir Направление (LIN_DIR_RX / LIN_DIR_TX).
|
||
* @param timestamp Временная метка в наносекундах.
|
||
* @param checksum Контрольная сумма.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_add_lin_message_obsolete(BLFContext *ctx,
|
||
uint16_t channel,
|
||
uint8_t id,
|
||
uint8_t dlc,
|
||
const uint8_t *data,
|
||
uint8_t dir,
|
||
uint64_t timestamp,
|
||
uint16_t checksum);
|
||
|
||
/**
|
||
* @brief Добавляет событие отсутствия ответа LIN.
|
||
* @param ctx Контекст.
|
||
* @param channel Номер канала.
|
||
* @param id Идентификатор.
|
||
* @param dlc Ожидаемая длина данных.
|
||
* @param timestamp Временная метка в наносекундах.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_add_lin_send_error(BLFContext *ctx,
|
||
uint16_t channel,
|
||
uint8_t id,
|
||
uint8_t dlc,
|
||
uint64_t timestamp);
|
||
|
||
/**
|
||
* @brief Добавляет данные окружения (ENV_DATA).
|
||
* @param ctx Контекст.
|
||
* @param name Имя переменной (строка).
|
||
* @param data Указатель на данные.
|
||
* @param data_len Длина данных в байтах.
|
||
* @param timestamp Временная метка в наносекундах.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_add_env_data(BLFContext *ctx,
|
||
const char *name,
|
||
const uint8_t *data,
|
||
uint32_t data_len,
|
||
uint64_t timestamp);
|
||
|
||
/* Удобные обёртки, принимающие структуры с временем в миллисекундах */
|
||
int blf_add_can_message_struct(BLFContext *ctx, const CanMessageStruct *msg);
|
||
int blf_add_lin_message_struct(BLFContext *ctx, const LinMessageStruct *msg);
|
||
int blf_add_lin_send_error_struct(BLFContext *ctx, const LinSendErrorStruct *err);
|
||
int blf_add_env_data_struct(BLFContext *ctx, const EnvDataStruct *env);
|
||
|
||
/**
|
||
* @brief Закрывает BLF-файл, обновляет заголовок.
|
||
* @param ctx Контекст.
|
||
* @return 0 при успехе, -1 при ошибке.
|
||
*/
|
||
int blf_close(BLFContext *ctx);
|
||
|
||
#endif /* BLF_H */ |