- 新增usb连接状态检测函数,根据usb连接状态自动切换数据采集模式 - 新增文件系统动态挂载/卸载功能,usb连接时卸载文件系统,断开时重新挂载 - 修改系统启动逻辑,根据初始usb连接状态决定是否开始数据采集 - 新增usb模式系统状态,完善系统状态机 🐛 fix(sdio): 修复sdio配置问题并启用中断 - 修改sdio时钟分频为2,优化sd nand通信时序 - 启用sdio数据线内部上拉电阻,提高信号稳定性 - 提高sdio dma传输优先级至最高,确保数据传输实时性 - 启用sdio全局中断并设置优先级为9 🔧 chore(config): 优化系统配置参数 - 修改系统滴答定时器中断优先级为0(最高优先级) - 增加堆栈大小至0x1000,增加堆大小至0x800 - 修改usb msc媒体数据包大小至32768,提高usb传输效率 - 修改fatfs配置,设置最大最小扇区大小为512字节 ♻️ refactor(usb): 重构usb存储接口实现 - 修改usb存储初始化逻辑,避免重复初始化sd卡 - 优化usb存储容量报告机制,强制报告512字节扇区 - 增加sd nand读写超时等待机制,确保数据传输完成 - 修改usb中断优先级为11,避免与sdio中断冲突 📝 docs(headers): 更新头文件声明 - 在stm32f4xx_it.h中添加sdio中断处理函数声明 - 在system_monitor.h中添加usb模式系统状态定义 - 更新data_storage.h中的数据存储路径配置
353 lines
9.6 KiB
C
353 lines
9.6 KiB
C
#include "data_storage.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
/**
|
|
* @brief 初始化数据存储模块
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_Init(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 初始化句柄
|
|
memset(handle, 0, sizeof(DataStorageHandle_t));
|
|
|
|
// 初始化双缓冲区
|
|
for (int i = 0; i < 2; i++) {
|
|
handle->buffers[i].index = 0;
|
|
handle->buffers[i].state = BUFFER_IDLE;
|
|
memset(handle->buffers[i].data, 0, DATA_STORAGE_BUFFER_SIZE);
|
|
}
|
|
|
|
// 设置活动缓冲区为0
|
|
handle->active_buffer = 0;
|
|
handle->flush_buffer = 1;
|
|
handle->flush_in_progress = 0;
|
|
|
|
// 创建数据存储目录
|
|
FRESULT res = f_mkdir(DATA_STORAGE_PATH);
|
|
if (res != FR_OK && res != FR_EXIST) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
handle->stats.state = DATA_STORAGE_IDLE;
|
|
handle->initialized = 1;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 停止数据记录
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_StopRecording(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
if (handle->stats.state != DATA_STORAGE_RECORDING) {
|
|
return HAL_OK; // 没有在记录中
|
|
}
|
|
|
|
// 刷新所有缓冲区
|
|
for (int i = 0; i < 2; i++) {
|
|
if (handle->buffers[i].index > 0) {
|
|
handle->buffers[i].state = BUFFER_READY_TO_FLUSH;
|
|
DataStorage_FlushBuffer(handle, i);
|
|
}
|
|
}
|
|
|
|
// 关闭文件
|
|
f_close(&handle->file);
|
|
|
|
handle->stats.state = DATA_STORAGE_IDLE;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 写入数据包到存储
|
|
* @param handle: 数据存储句柄指针
|
|
* @param packet: 数据包指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_WriteData(DataStorageHandle_t *handle, const DataPacket_t *packet)
|
|
{
|
|
if (handle == NULL || packet == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
if (handle->stats.state != DATA_STORAGE_RECORDING) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
|
|
|
|
// 检查当前活动缓冲区空间
|
|
if (active_buf->index + sizeof(DataPacket_t) > DATA_STORAGE_BUFFER_SIZE) {
|
|
// 切换缓冲区
|
|
if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
|
|
handle->stats.error_count++;
|
|
return HAL_ERROR;
|
|
}
|
|
active_buf = &handle->buffers[handle->active_buffer];
|
|
}
|
|
|
|
// 复制数据到活动缓冲区
|
|
memcpy(&active_buf->data[active_buf->index], packet, sizeof(DataPacket_t));
|
|
active_buf->index += sizeof(DataPacket_t);
|
|
active_buf->state = BUFFER_WRITING;
|
|
handle->stats.total_samples++;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 写入校正后的数据到存储
|
|
* @param handle: 数据存储句柄指针
|
|
* @param result: 校正结果指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_WriteCorrectedData(DataStorageHandle_t *handle, const CorrectionResult_t *result)
|
|
{
|
|
if (handle == NULL || result == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
if (handle->stats.state != DATA_STORAGE_RECORDING) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
DataBuffer_t *active_buf = &handle->buffers[handle->active_buffer];
|
|
|
|
// 检查当前活动缓冲区空间
|
|
if (active_buf->index + sizeof(CorrectionResult_t) > DATA_STORAGE_BUFFER_SIZE) {
|
|
// 切换缓冲区
|
|
if (DataStorage_SwitchBuffer(handle) != HAL_OK) {
|
|
handle->stats.error_count++;
|
|
return HAL_ERROR;
|
|
}
|
|
active_buf = &handle->buffers[handle->active_buffer];
|
|
}
|
|
|
|
// 复制校正后的数据到活动缓冲区
|
|
memcpy(&active_buf->data[active_buf->index], result, sizeof(CorrectionResult_t));
|
|
active_buf->index += sizeof(CorrectionResult_t);
|
|
active_buf->state = BUFFER_WRITING;
|
|
handle->stats.total_samples++;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 刷新缓冲区到文件
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_Flush(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 处理后台刷新任务
|
|
DataStorage_ProcessBackgroundTasks(handle);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 创建新的数据文件
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_CreateNewFile(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 生成文件名 (基于时间戳)
|
|
uint32_t timestamp = HAL_GetTick();
|
|
snprintf(handle->stats.current_filename, sizeof(handle->stats.current_filename),
|
|
"%s%s%08lX.dat", DATA_STORAGE_PATH, DATA_STORAGE_FILE_PREFIX, timestamp);
|
|
|
|
// 创建并打开文件
|
|
FRESULT res = f_open(&handle->file, handle->stats.current_filename,
|
|
FA_CREATE_ALWAYS | FA_WRITE);
|
|
|
|
if (res != FR_OK) {
|
|
handle->stats.error_count++;
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
handle->stats.file_count++;
|
|
handle->stats.current_file_size = 0;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 获取数据存储统计信息
|
|
* @param handle: 数据存储句柄指针
|
|
* @param stats: 统计信息结构体指针
|
|
* @retval None
|
|
*/
|
|
void DataStorage_GetStats(DataStorageHandle_t *handle, DataStorageStats_t *stats)
|
|
{
|
|
if (handle == NULL || stats == NULL || !handle->initialized) {
|
|
return;
|
|
}
|
|
|
|
memcpy(stats, &handle->stats, sizeof(DataStorageStats_t));
|
|
}
|
|
|
|
/**
|
|
* @brief 开始数据记录
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_StartRecording(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
if (handle->stats.state == DATA_STORAGE_RECORDING) {
|
|
return HAL_OK; // 已经在记录中
|
|
}
|
|
|
|
// 创建新文件
|
|
if (DataStorage_CreateNewFile(handle) != HAL_OK) {
|
|
handle->stats.state = DATA_STORAGE_ERROR;
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 重置双缓冲区状态
|
|
for (int i = 0; i < 2; i++) {
|
|
handle->buffers[i].index = 0;
|
|
handle->buffers[i].state = BUFFER_IDLE;
|
|
}
|
|
handle->active_buffer = 0;
|
|
handle->flush_buffer = 1;
|
|
handle->flush_in_progress = 0;
|
|
|
|
handle->stats.state = DATA_STORAGE_RECORDING;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 刷新指定缓冲区到文件
|
|
* @param handle: 数据存储句柄指针
|
|
* @param buffer_index: 缓冲区索引 (0 或 1)
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_FlushBuffer(DataStorageHandle_t *handle, uint8_t buffer_index)
|
|
{
|
|
if (handle == NULL || !handle->initialized || buffer_index > 1) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
DataBuffer_t *buffer = &handle->buffers[buffer_index];
|
|
|
|
// 检查缓冲区状态和数据
|
|
if (buffer->state != BUFFER_READY_TO_FLUSH || buffer->index == 0) {
|
|
return HAL_OK; // 没有数据需要刷新
|
|
}
|
|
|
|
// 标记缓冲区正在刷新
|
|
buffer->state = BUFFER_FLUSHING;
|
|
|
|
UINT bytes_written;
|
|
FRESULT res = f_write(&handle->file, buffer->data, buffer->index, &bytes_written);
|
|
|
|
if (res != FR_OK || bytes_written != buffer->index) {
|
|
handle->stats.error_count++;
|
|
buffer->state = BUFFER_READY_TO_FLUSH; // 恢复状态以便重试
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 同步到存储设备
|
|
f_sync(&handle->file);
|
|
|
|
// 更新统计信息
|
|
handle->stats.current_file_size += bytes_written;
|
|
|
|
// 重置缓冲区
|
|
buffer->index = 0;
|
|
buffer->state = BUFFER_IDLE;
|
|
|
|
// 检查文件大小是否超过限制
|
|
if (handle->stats.current_file_size >= DATA_STORAGE_FILE_MAX_SIZE) {
|
|
f_close(&handle->file);
|
|
DataStorage_CreateNewFile(handle);
|
|
}
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 处理后台任务(异步刷新缓冲区)
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval None
|
|
*/
|
|
void DataStorage_ProcessBackgroundTasks(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return;
|
|
}
|
|
|
|
// 检查是否有缓冲区需要刷新
|
|
for (int i = 0; i < 2; i++) {
|
|
if (handle->buffers[i].state == BUFFER_READY_TO_FLUSH) {
|
|
// 刷新缓冲区
|
|
DataStorage_FlushBuffer(handle, i);
|
|
break; // 一次只处理一个缓冲区,避免阻塞太久
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 切换活动缓冲区
|
|
* @param handle: 数据存储句柄指针
|
|
* @retval HAL_StatusTypeDef
|
|
*/
|
|
HAL_StatusTypeDef DataStorage_SwitchBuffer(DataStorageHandle_t *handle)
|
|
{
|
|
if (handle == NULL || !handle->initialized) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
DataBuffer_t *current_buf = &handle->buffers[handle->active_buffer];
|
|
|
|
// 标记当前缓冲区准备刷新
|
|
if (current_buf->index > 0) {
|
|
current_buf->state = BUFFER_READY_TO_FLUSH;
|
|
}
|
|
|
|
// 切换到另一个缓冲区
|
|
uint8_t next_buffer = (handle->active_buffer == 0) ? 1 : 0;
|
|
DataBuffer_t *next_buf = &handle->buffers[next_buffer];
|
|
|
|
// 检查目标缓冲区是否可用
|
|
if (next_buf->state == BUFFER_FLUSHING) {
|
|
// 目标缓冲区正在刷新,等待完成
|
|
handle->stats.error_count++;
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
// 切换活动缓冲区
|
|
handle->active_buffer = next_buffer;
|
|
next_buf->index = 0;
|
|
next_buf->state = BUFFER_WRITING;
|
|
|
|
return HAL_OK;
|
|
}
|