feat(main): 新增usb连接状态检测与自动文件系统管理功能

- 新增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中的数据存储路径配置
This commit is contained in:
zhoujie 2026-02-02 23:36:20 +08:00
parent 4598f8f34f
commit 87bdfa09d9
14 changed files with 477 additions and 64 deletions

View File

@ -148,7 +148,7 @@
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE 3300U /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority */
#define TICK_INT_PRIORITY 0U /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U

View File

@ -59,6 +59,7 @@ void EXTI1_IRQHandler(void);
void DMA1_Stream0_IRQHandler(void);
void DMA1_Stream3_IRQHandler(void);
void TIM2_IRQHandler(void);
void SDIO_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void);
void OTG_FS_IRQHandler(void);

View File

@ -60,7 +60,7 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin : PC3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : ADC_DRY_Pin */

View File

@ -84,6 +84,11 @@ static uint32_t g_last_monitor_update = 0;
static uint8_t g_recording_enabled = 0;
static uint32_t g_sample_count = 0;
// USB连接状态管理
static uint8_t g_usb_connected = 0;
static uint8_t g_fatfs_mounted_for_sampling = 0;
static uint32_t g_last_usb_check = 0;
// 性能监控和调试输出
static uint32_t g_last_debug_output = 0;
static uint8_t g_debug_output_enabled = ENABLE_UART_DEBUG_OUTPUT;
@ -98,6 +103,12 @@ static void StartRecording(void);
static void StopRecording(void);
static void ProcessAdcData(void);
// USB连接状态管理函数
static uint8_t CheckUSBConnectionStatus(void);
static void HandleUSBConnectionChange(void);
static HAL_StatusTypeDef MountFileSystemForSampling(void);
static void UnmountFileSystemForSampling(void);
static void DebugOutput_Init(void);
static void DebugOutput_SendString(const char* str);
static void DebugOutput_PrintSystemStats(void);
@ -396,6 +407,141 @@ static void DebugOutput_PrintPerformanceStats(void)
#endif
}
/**
* @brief USB连接状态
* @retval 1: USB已连接, 0: USB未连接
*/
static uint8_t CheckUSBConnectionStatus(void)
{
// 通过检查USB设备状态来判断是否连接到PC
extern USBD_HandleTypeDef hUsbDeviceFS;
// 检查USB设备是否已配置枚举完成
if (hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED) {
return 1; // USB已连接并配置
}
return 0; // USB未连接或未配置
}
/**
* @brief USB连接状态变化
* @retval None
*/
static void HandleUSBConnectionChange(void)
{
uint8_t current_usb_status = CheckUSBConnectionStatus();
if (current_usb_status != g_usb_connected) {
g_usb_connected = current_usb_status;
if (g_usb_connected) {
// USB连接停止数据采集卸载文件系统用于USB存储
DebugOutput_SendString("USB Connected: Stopping data acquisition\r\n");
// 停止数据记录
StopRecording();
// 卸载用于采样的文件系统
UnmountFileSystemForSampling();
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_USB_MODE);
#endif
} else {
// USB断开重新挂载文件系统开始数据采集
DebugOutput_SendString("USB Disconnected: Starting data acquisition\r\n");
// 挂载文件系统用于数据采集
if (MountFileSystemForSampling() == HAL_OK) {
// 重新初始化数据存储
if (DataStorage_Init(&g_data_storage) == HAL_OK) {
StartRecording();
}
}
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_SetState(SYSTEM_STATE_IDLE);
#endif
}
}
}
/**
* @brief
* @retval HAL_OK: , HAL_ERROR:
*/
static HAL_StatusTypeDef MountFileSystemForSampling(void)
{
extern FATFS SDFatFS;
extern char SDPath[4];
extern SD_HandleTypeDef hsd;
if (g_fatfs_mounted_for_sampling) {
return HAL_OK; // 已经挂载
}
// 初始化SD卡
if (HAL_SD_Init(&hsd) != HAL_OK) {
DebugOutput_SendString("SD card init failed\r\n");
return HAL_ERROR;
}
// FRESULT format_result = f_mkfs(SDPath, FM_FAT32, 0, NULL, 0);
// 尝试挂载文件系统
FRESULT mount_result = f_mount(&SDFatFS, SDPath, 1);
if (mount_result != FR_OK) {
if (mount_result == FR_NO_FILESYSTEM)
{
DebugOutput_SendString("No filesystem found, formatting...\r\n");
// 格式化为FAT32
FRESULT format_result = f_mkfs(SDPath, FM_FAT32, 0, NULL, 0);
if (format_result == FR_OK) {
DebugOutput_SendString("Format successful, remounting...\r\n");
mount_result = f_mount(&SDFatFS, SDPath, 1);
if (mount_result != FR_OK) {
DebugOutput_SendString("Remount after format failed\r\n");
return HAL_ERROR;
}
} else {
DebugOutput_SendString("Format failed\r\n");
return HAL_ERROR;
}
} else {
DebugOutput_SendString("Mount failed with other error\r\n");
return HAL_ERROR;
}
}
g_fatfs_mounted_for_sampling = 1;
DebugOutput_SendString("Filesystem mounted for sampling\r\n");
return HAL_OK;
}
/**
* @brief
* @retval None
*/
static void UnmountFileSystemForSampling(void)
{
extern FATFS SDFatFS;
extern char SDPath[4];
if (!g_fatfs_mounted_for_sampling) {
return; // 已经卸载
}
// 卸载文件系统
f_mount(NULL, SDPath, 0);
g_fatfs_mounted_for_sampling = 0;
DebugOutput_SendString("Filesystem unmounted for USB mode\r\n");
}
/* USER CODE END 0 */
/**
@ -422,7 +568,7 @@ int main(void)
SystemClock_Config();
/* USER CODE BEGIN SysInit */
HAL_Delay(200);
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
@ -439,6 +585,11 @@ int main(void)
MX_USART3_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
// SD_NAND_Init_And_Mount();
// SD_Test_Write();
// SD_Test_Read();
// 初始化系统监控
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_Init();
@ -468,15 +619,35 @@ int main(void)
Init_CorrectionParams(&g_correction_params);
Load_CorrectionParams_FromFlash(&g_correction_params);
// 初始化数据存储
if (DataStorage_Init(&g_data_storage) != HAL_OK) {
// 检查初始USB连接状态并相应初始化
HAL_Delay(2000);
g_usb_connected = CheckUSBConnectionStatus();
if (!g_usb_connected) {
// USB未连接挂载文件系统用于数据采集
if (MountFileSystemForSampling() == HAL_OK) {
// 初始化数据存储
if (DataStorage_Init(&g_data_storage) == HAL_OK) {
// 开始数据记录
StartRecording();
} else {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
} else {
#if ENABLE_SYSTEM_MONITOR
SystemMonitor_ReportError(SYSTEM_ERROR_STORAGE);
#endif
}
} else {
// USB已连接不进行数据采集
DebugOutput_SendString("USB connected at startup - data acquisition disabled\r\n");
while(1)
{
;
}
}
// 开始数据记录
StartRecording();
// 系统初始化完成
#if ENABLE_SYSTEM_MONITOR
@ -519,8 +690,11 @@ int main(void)
g_last_monitor_update = current_tick;
}
// ADC数据处理已移至1ms定时器中断中处理
// USB连接状态检测 (每500ms检测一次)
if (current_tick - g_last_usb_check >= 500) {
HandleUSBConnectionChange();
g_last_usb_check = current_tick;
}
// 处理数据存储后台任务 (轮询方式)
if (g_recording_enabled) {

View File

@ -46,7 +46,7 @@ void MX_SDIO_SD_Init(void)
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
hsd.Init.ClockDiv = 2;
/* USER CODE BEGIN SDIO_Init 2 */
/* USER CODE END SDIO_Init 2 */
@ -75,8 +75,14 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
@ -85,7 +91,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
@ -100,7 +106,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
@ -121,7 +127,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
@ -133,6 +139,9 @@ void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
__HAL_LINKDMA(sdHandle,hdmatx,hdma_sdio_tx);
/* SDIO interrupt Init */
HAL_NVIC_SetPriority(SDIO_IRQn, 9, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
/* USER CODE BEGIN SDIO_MspInit 1 */
/* USER CODE END SDIO_MspInit 1 */
@ -166,6 +175,9 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef* sdHandle)
/* SDIO DMA DeInit */
HAL_DMA_DeInit(sdHandle->hdmarx);
HAL_DMA_DeInit(sdHandle->hdmatx);
/* SDIO interrupt Deinit */
HAL_NVIC_DisableIRQ(SDIO_IRQn);
/* USER CODE BEGIN SDIO_MspDeInit 1 */
/* USER CODE END SDIO_MspDeInit 1 */

View File

@ -60,6 +60,7 @@
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;
extern SD_HandleTypeDef hsd;
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi2_rx;
extern DMA_HandleTypeDef hdma_spi3_rx;
@ -266,6 +267,20 @@ void TIM2_IRQHandler(void)
/* USER CODE END TIM2_IRQn 1 */
}
/**
* @brief This function handles SDIO global interrupt.
*/
void SDIO_IRQHandler(void)
{
/* USER CODE BEGIN SDIO_IRQn 0 */
/* USER CODE END SDIO_IRQn 0 */
HAL_SD_IRQHandler(&hsd);
/* USER CODE BEGIN SDIO_IRQn 1 */
/* USER CODE END SDIO_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream0 global interrupt.
*/

View File

@ -20,7 +20,7 @@ Dma.SDIO_RX.3.Mode=DMA_PFCTRL
Dma.SDIO_RX.3.PeriphBurst=DMA_PBURST_INC4
Dma.SDIO_RX.3.PeriphDataAlignment=DMA_PDATAALIGN_WORD
Dma.SDIO_RX.3.PeriphInc=DMA_PINC_DISABLE
Dma.SDIO_RX.3.Priority=DMA_PRIORITY_LOW
Dma.SDIO_RX.3.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SDIO_RX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SDIO_TX.4.Direction=DMA_MEMORY_TO_PERIPH
Dma.SDIO_TX.4.FIFOMode=DMA_FIFOMODE_ENABLE
@ -33,7 +33,7 @@ Dma.SDIO_TX.4.Mode=DMA_PFCTRL
Dma.SDIO_TX.4.PeriphBurst=DMA_PBURST_INC4
Dma.SDIO_TX.4.PeriphDataAlignment=DMA_PDATAALIGN_WORD
Dma.SDIO_TX.4.PeriphInc=DMA_PINC_DISABLE
Dma.SDIO_TX.4.Priority=DMA_PRIORITY_LOW
Dma.SDIO_TX.4.Priority=DMA_PRIORITY_VERY_HIGH
Dma.SDIO_TX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,FIFOThreshold,MemBurst,PeriphBurst
Dma.SPI1_RX.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.SPI1_RX.0.FIFOMode=DMA_FIFOMODE_DISABLE
@ -76,8 +76,10 @@ Dma.USART1_TX.5.PeriphInc=DMA_PINC_DISABLE
Dma.USART1_TX.5.Priority=DMA_PRIORITY_LOW
Dma.USART1_TX.5.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
FATFS.BSP.number=1
FATFS.IPParameters=_USE_LFN,USE_DMA_CODE_SD
FATFS.IPParameters=_USE_LFN,USE_DMA_CODE_SD,_MAX_SS,_MIN_SS
FATFS.USE_DMA_CODE_SD=1
FATFS._MAX_SS=512
FATFS._MIN_SS=512
FATFS._USE_LFN=2
FATFS0.BSP.STBoard=false
FATFS0.BSP.api=Unknown
@ -164,11 +166,12 @@ NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.OTG_FS_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.OTG_FS_IRQn=true\:11\:0\:true\:false\:true\:false\:true\:true
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SDIO_IRQn=true\:9\:0\:true\:false\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:false\:true\:false
NVIC.TIM2_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA1.GPIOParameters=GPIO_Label
@ -214,22 +217,36 @@ PB3.Mode=RX_Only_Simplex_Unidirect_Slave
PB3.Signal=SPI3_SCK
PB5.Mode=RX_Only_Simplex_Unidirect_Slave
PB5.Signal=SPI3_MOSI
PC10.GPIOParameters=GPIO_PuPd
PC10.GPIO_PuPd=GPIO_PULLUP
PC10.Mode=SD_4_bits_Wide_bus
PC10.Signal=SDIO_D2
PC11.GPIOParameters=GPIO_PuPd
PC11.GPIO_PuPd=GPIO_PULLUP
PC11.Mode=SD_4_bits_Wide_bus
PC11.Signal=SDIO_D3
PC12.GPIOParameters=GPIO_PuPd
PC12.GPIO_PuPd=GPIO_NOPULL
PC12.Mode=SD_4_bits_Wide_bus
PC12.Signal=SDIO_CK
PC3.GPIOParameters=GPIO_PuPd
PC3.GPIO_PuPd=GPIO_PULLDOWN
PC3.Locked=true
PC3.Signal=GPIO_Input
PC7.GPIOParameters=GPIO_Label
PC7.GPIO_Label=RS485_CTL
PC7.Locked=true
PC7.Signal=GPIO_Output
PC8.GPIOParameters=GPIO_PuPd
PC8.GPIO_PuPd=GPIO_PULLUP
PC8.Mode=SD_4_bits_Wide_bus
PC8.Signal=SDIO_D0
PC9.GPIOParameters=GPIO_PuPd
PC9.GPIO_PuPd=GPIO_PULLUP
PC9.Mode=SD_4_bits_Wide_bus
PC9.Signal=SDIO_D1
PD2.GPIOParameters=GPIO_PuPd
PD2.GPIO_PuPd=GPIO_PULLUP
PD2.Mode=SD_4_bits_Wide_bus
PD2.Signal=SDIO_CMD
PH0-OSC_IN.Mode=HSE-External-Oscillator
@ -250,7 +267,7 @@ ProjectManager.DeviceId=STM32F405RGTx
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.28.3
ProjectManager.FreePins=false
ProjectManager.HalAssertFull=false
ProjectManager.HeapSize=0x200
ProjectManager.HeapSize=0x1000
ProjectManager.KeepUserCode=true
ProjectManager.LastFirmware=true
ProjectManager.LibraryCopy=1
@ -262,7 +279,7 @@ ProjectManager.ProjectFileName=STM_ATEM_F405.ioc
ProjectManager.ProjectName=STM_ATEM_F405
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.StackSize=0x800
ProjectManager.TargetToolchain=STM32CubeIDE
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
@ -302,6 +319,9 @@ RCC.VCOI2SOutputFreq_Value=192000000
RCC.VCOInputFreq_Value=1000000
RCC.VCOOutputFreq_Value=336000000
RCC.VcooutputI2S=96000000
SDIO.ClockDiv=2
SDIO.HardwareFlowControl=SDIO_HARDWARE_FLOW_CONTROL_DISABLE
SDIO.IPParameters=ClockDiv,HardwareFlowControl
SH.GPXTI1.0=GPIO_EXTI1
SH.GPXTI1.ConfNb=1
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
@ -332,7 +352,7 @@ USART3.IPParameters=VirtualMode
USART3.VirtualMode=VM_ASYNC
USB_DEVICE.CLASS_NAME_FS=MSC
USB_DEVICE.IPParameters=VirtualMode-MSC_FS,VirtualModeFS,CLASS_NAME_FS,MSC_MEDIA_PACKET-MSC_FS
USB_DEVICE.MSC_MEDIA_PACKET-MSC_FS=8192
USB_DEVICE.MSC_MEDIA_PACKET-MSC_FS=32768
USB_DEVICE.VirtualMode-MSC_FS=Msc
USB_DEVICE.VirtualModeFS=Msc_FS
USB_OTG_FS.IPParameters=VirtualMode

View File

@ -183,16 +183,21 @@ int8_t STORAGE_Init_FS(uint8_t lun)
{
/* USER CODE BEGIN 2 */
UNUSED(lun);
// 1. 检查 SD 句柄状态
// 如果之前在 main.c 里已经 HAL_SD_Init 过了,这里只要确认状态即可
HAL_SD_StateTypeDef state = HAL_SD_GetState(&hsd);
// 初始化SD卡
if (HAL_SD_Init(&hsd) != HAL_OK) {
return (USBD_FAIL);
}
// 挂载文件系统
if (f_mount(&SDFatFS, SDPath, 1) != FR_OK) {
return (USBD_FAIL);
if(state == HAL_SD_STATE_RESET)
{
// 只有在从未初始化的情况下才初始化
if (HAL_SD_Init(&hsd) != HAL_OK) {
return (USBD_FAIL);
}
}
// 2. 绝对不要在这里 f_mount 或 f_mkfs !!!
// USB 只是搬运工,文件系统由电脑端管理。
sd_initialized = 1;
return (USBD_OK);
@ -211,20 +216,26 @@ int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_
/* USER CODE BEGIN 3 */
UNUSED(lun);
if (!sd_initialized) {
return (USBD_FAIL);
}
HAL_SD_CardInfoTypeDef cardinfo;
if (HAL_SD_GetCardInfo(&hsd, &cardinfo) == HAL_OK) {
*block_num = cardinfo.LogBlockNbr;
*block_size = cardinfo.LogBlockSize;
} else {
*block_num = STORAGE_BLK_NBR;
*block_size = STORAGE_BLK_SIZ;
if (HAL_SD_GetCardInfo(&hsd, &cardinfo) == HAL_OK)
{
// 修正 2: 欺骗电脑,强制报告 512 字节扇区
*block_size = 512;
if (cardinfo.LogBlockSize == 512) {
*block_num = cardinfo.LogBlockNbr - 1;
}
else {
// 如果 SD NAND 是 2048/4096 字节页,需要转换块数量
// 例如:实际 4096那 USB 看到的块数就是 实际块数 * 8
uint32_t ratio = cardinfo.LogBlockSize / 512;
*block_num = (cardinfo.LogBlockNbr * ratio) - 1;
}
return (USBD_OK);
}
return (USBD_OK);
return (USBD_FAIL);
/* USER CODE END 3 */
}
@ -238,16 +249,14 @@ int8_t STORAGE_IsReady_FS(uint8_t lun)
/* USER CODE BEGIN 4 */
UNUSED(lun);
if (!sd_initialized) {
return (USBD_FAIL);
// 简单检查硬件状态
if (hsd.State == HAL_SD_STATE_RESET) {
return (USBD_FAIL);
}
HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&hsd);
if (state == HAL_SD_CARD_TRANSFER) {
return (USBD_OK);
}
return (USBD_FAIL);
// 对于 SD NAND即使内部 BUSY为了不让 USB 掉线,通常也返回 OK
// 实际的等待放到 Read/Write 函数里去做
return (USBD_OK);
/* USER CODE END 4 */
}
@ -278,12 +287,18 @@ int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t bl
/* USER CODE BEGIN 6 */
UNUSED(lun);
if (!sd_initialized || buf == NULL) {
// 使用较长的超时时间 (SD NAND 读写较慢)
uint32_t timeout = 2000;
if (HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, timeout) != HAL_OK) {
return (USBD_FAIL);
}
if (HAL_SD_ReadBlocks(&hsd, buf, blk_addr, blk_len, HAL_MAX_DELAY) != HAL_OK) {
return (USBD_FAIL);
// 等待传输完成 (重要: 确保 DMA/中断搬运完毕)
uint32_t tickstart = HAL_GetTick();
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
{
if((HAL_GetTick() - tickstart) > timeout) return USBD_FAIL;
}
return (USBD_OK);
@ -303,12 +318,19 @@ int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t b
/* USER CODE BEGIN 7 */
UNUSED(lun);
if (!sd_initialized || buf == NULL) {
// 修正 3: 增加超时时间,并等待 Busy 结束
uint32_t timeout = 5000; // 给 5秒SD NAND 写入由于要擦除/编程,很慢
if (HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, timeout) != HAL_OK) {
return (USBD_FAIL);
}
if (HAL_SD_WriteBlocks(&hsd, buf, blk_addr, blk_len, HAL_MAX_DELAY) != HAL_OK) {
return (USBD_FAIL);
// 【最关键的一步】等待 SD NAND 内部编程结束
// 如果没有这一步,文件就会丢失!
uint32_t tickstart = HAL_GetTick();
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
{
if((HAL_GetTick() - tickstart) > timeout) return USBD_FAIL;
}
return (USBD_OK);

View File

@ -91,7 +91,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
HAL_NVIC_SetPriority(OTG_FS_IRQn, 11, 0);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
/* USER CODE BEGIN USB_OTG_FS_MspInit 1 */

View File

@ -75,7 +75,7 @@
/*---------- -----------*/
#define USBD_SELF_POWERED 1U
/*---------- -----------*/
#define MSC_MEDIA_PACKET 8192U
#define MSC_MEDIA_PACKET 32768U
/****************************************/
/* #define for FS and HS identification */

View File

@ -349,4 +349,4 @@ HAL_StatusTypeDef DataStorage_SwitchBuffer(DataStorageHandle_t *handle)
next_buf->state = BUFFER_WRITING;
return HAL_OK;
}
}

View File

@ -11,7 +11,7 @@
// 数据存储配置
#define DATA_STORAGE_BUFFER_SIZE 32768 // 缓冲区大小(字节)
#define DATA_STORAGE_FILE_MAX_SIZE (10*1024*1024) // 单个文件最大10MB
#define DATA_STORAGE_PATH "0:/DATA/" // 数据存储路径
#define DATA_STORAGE_PATH "0:/DATA1" // 数据存储路径
#define DATA_STORAGE_FILE_PREFIX "ADC_DATA_" // 文件名前缀
// 缓冲区状态
@ -73,4 +73,4 @@ HAL_StatusTypeDef DataStorage_SwitchBuffer(DataStorageHandle_t *handle);
HAL_StatusTypeDef DataStorage_FlushBuffer(DataStorageHandle_t *handle, uint8_t buffer_index);
void DataStorage_ProcessBackgroundTasks(DataStorageHandle_t *handle);
#endif // DATA_STORAGE_H
#endif // DATA_STORAGE_H

168
User/sd_test.c Normal file
View File

@ -0,0 +1,168 @@
/* USER CODE BEGIN Includes */
#include <stdio.h> // 用于 printf 打印调试信息
#include "fatfs.h"
#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "sdio.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"
#include "main.h"
#include "fatfs.h"
#include "ff.h"
#include "data_packet.h"
#include "correction.h"
#include <stdint.h>
/* USER CODE END Includes */
/* USER CODE BEGIN 4 */
extern SD_HandleTypeDef hsd;
//DMA_HandleTypeDef hdma_sdio_rx;
//DMA_HandleTypeDef hdma_sdio_tx;
/**
* @brief SD NAND
* @return 0: , -1:
*/
int SD_NAND_Init_And_Mount(void)
{
FRESULT res;
BYTE workBuffer[4096]; // f_mkfs 需要的工作缓存
// 1. 物理层延时SD NAND 内部初始化比普通卡慢
HAL_Delay(500);
// 2. 检查底层 SDIO 是否通了
// 如果这里检测不到,说明硬件接线或 IOC 时钟配置有问题
HAL_SD_CardStateTypeDef cardState = HAL_SD_GetCardState(&hsd); // 确认句柄是 hsd1 还是 hsd
if (cardState == HAL_SD_CARD_ERROR) {
printf("Error: SD Card Hardware Not Ready!\r\n");
return -1;
}
// 3. 尝试挂载 (Force Mount = 1)
printf("Attempting to mount SD card...\r\n");
res = f_mount(&SDFatFS, SDPath, 1);
// 4. 分析挂载结果
if (res == FR_OK) {
// 挂载成功,打印容量信息
DWORD free_clusters;
FATFS *fs;
f_getfree(SDPath, &free_clusters, &fs);
uint32_t total_blocks = (fs->n_fatent - 2) * fs->csize;
printf("Mount Success! Total: %lu sectors\r\n", total_blocks);
return 0;
}
// 5. 如果没有文件系统 (新芯片或损坏),执行格式化
else if (res == FR_NO_FILESYSTEM)
{
printf("No Filesystem found. Starting formatting (Legacy Mode)...\r\n");
/* 针对你的 FatFs 版本 (5个参数) 的修正
:
1. path:
2. opt: (FM_FAT32, FM_SFD )
3. au: (Allocation Unit) 4096 SD NAND
4. work:
5. len:
*/
// 确保你的 ff.h 中定义了 FM_FAT32。如果没有尝试用 0x02 代替
BYTE format_opt = FM_FAT32; // 或者 FM_ANY | FM_SFD
// 【关键】针对 SD NAND强制使用 4096 字节的簇大小
DWORD au_size = 512;
// 修正后的函数调用:传入 5 个参数,而不是结构体
res = f_mkfs(SDPath, format_opt, au_size, workBuffer, sizeof(workBuffer));
if (res == FR_OK) {
printf("Format Successful! Remounting...\r\n");
// 格式化后建议取消挂载再重新挂载
f_mount(NULL, SDPath, 0);
res = f_mount(&SDFatFS, SDPath, 1);
if (res == FR_OK) {
printf("Remount Success!\r\n");
return 0;
}
} else {
printf("Format Failed! Error: %d\r\n", res);
}
}
return -1;
}
/* 简单的测试写文件函数 */
void SD_Test_Write(void) {
FIL fil;
UINT bw;
if (f_open(&fil, "SDTest.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {
f_write(&fil, "Hello SD NAND!", 14, &bw);
f_close(&fil);
printf("Write Test: OK\r\n");
} else {
printf("Write Test: Failed\r\n");
}
}
/**
* @brief
* SDTest.txt printf
*/
void SD_Test_Read(void)
{
FIL fil; // 文件对象
FRESULT res; // FatFs 返回结果
UINT br; // Bytes Read (实际读取到的字节数)
BYTE readBuf[128]; // 读取缓存 (根据需要调整大小)
printf("\r\n--- Starting Read Test ---\r\n");
// 1. 打开文件 (使用 FA_READ 模式)
// 注意:文件名必须与写入时完全一致
res = f_open(&fil, "SDTest.txt", FA_READ);
if (res != FR_OK) {
printf("Read Failed: f_open error code %d\r\n", res);
if (res == FR_NO_FILE) {
printf("Error: File does not exist. Did Write Test run successfully?\r\n");
}
return;
}
// 2. 读取文件
// 为了安全,读取长度设为 buffer大小 - 1留一个字节给字符串结束符
res = f_read(&fil, readBuf, sizeof(readBuf) - 1, &br);
if (res == FR_OK) {
// 3. 处理读取到的数据
readBuf[br] = '\0'; // 手动添加字符串结束符,方便 printf 打印
printf("Read Success!\r\n");
printf("Bytes Read: %d\r\n", br);
if (br > 0) {
printf("File Content: \r\n%s\r\n", readBuf);
} else {
printf("Warning: File is empty (0 bytes).\r\n");
}
} else {
printf("Read Failed: f_read error code %d\r\n", res);
}
// 4. 关闭文件 (读取完成后也必须关闭,释放句柄)
f_close(&fil);
printf("--- Read Test Finished ---\r\n");
}
/* USER CODE END 4 */

View File

@ -13,7 +13,8 @@ typedef enum {
SYSTEM_STATE_SAMPLING,
SYSTEM_STATE_RECORDING,
SYSTEM_STATE_ERROR,
SYSTEM_STATE_MAINTENANCE
SYSTEM_STATE_MAINTENANCE,
SYSTEM_STATE_USB_MODE
} SystemState_t;
// 系统错误类型