From 87bdfa09d9958e6b45cb4c736c2caed839cb292c Mon Sep 17 00:00:00 2001 From: zhoujie <929834232@qq.com> Date: Mon, 2 Feb 2026 23:36:20 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(main):=20=E6=96=B0=E5=A2=9Eusb?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E7=8A=B6=E6=80=81=E6=A3=80=E6=B5=8B=E4=B8=8E?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=96=87=E4=BB=B6=E7=B3=BB=E7=BB=9F=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增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中的数据存储路径配置 --- Core/Inc/stm32f4xx_hal_conf.h | 2 +- Core/Inc/stm32f4xx_it.h | 1 + Core/Src/gpio.c | 2 +- Core/Src/main.c | 192 +++++++++++++++++++++++++++++-- Core/Src/sdio.c | 24 +++- Core/Src/stm32f4xx_it.c | 15 +++ STM_ATEM_F405.ioc | 36 ++++-- USB_DEVICE/App/usbd_storage_if.c | 88 ++++++++------ USB_DEVICE/Target/usbd_conf.c | 2 +- USB_DEVICE/Target/usbd_conf.h | 2 +- User/data_storage.c | 2 +- User/data_storage.h | 4 +- User/sd_test.c | 168 +++++++++++++++++++++++++++ User/system_monitor.h | 3 +- 14 files changed, 477 insertions(+), 64 deletions(-) create mode 100644 User/sd_test.c diff --git a/Core/Inc/stm32f4xx_hal_conf.h b/Core/Inc/stm32f4xx_hal_conf.h index a75f280..8ba266f 100644 --- a/Core/Inc/stm32f4xx_hal_conf.h +++ b/Core/Inc/stm32f4xx_hal_conf.h @@ -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 diff --git a/Core/Inc/stm32f4xx_it.h b/Core/Inc/stm32f4xx_it.h index fcedcd4..f336bbe 100644 --- a/Core/Inc/stm32f4xx_it.h +++ b/Core/Inc/stm32f4xx_it.h @@ -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); diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c index a22265f..30a01fd 100644 --- a/Core/Src/gpio.c +++ b/Core/Src/gpio.c @@ -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 */ diff --git a/Core/Src/main.c b/Core/Src/main.c index a41d0ed..cee2310 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -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) { diff --git a/Core/Src/sdio.c b/Core/Src/sdio.c index e6cf89d..b71da8c 100644 --- a/Core/Src/sdio.c +++ b/Core/Src/sdio.c @@ -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 */ diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c index 418d021..5cefb89 100644 --- a/Core/Src/stm32f4xx_it.c +++ b/Core/Src/stm32f4xx_it.c @@ -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. */ diff --git a/STM_ATEM_F405.ioc b/STM_ATEM_F405.ioc index 9c6c6e6..f7f64db 100644 --- a/STM_ATEM_F405.ioc +++ b/STM_ATEM_F405.ioc @@ -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 diff --git a/USB_DEVICE/App/usbd_storage_if.c b/USB_DEVICE/App/usbd_storage_if.c index cdfa36b..7fdcc37 100644 --- a/USB_DEVICE/App/usbd_storage_if.c +++ b/USB_DEVICE/App/usbd_storage_if.c @@ -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); diff --git a/USB_DEVICE/Target/usbd_conf.c b/USB_DEVICE/Target/usbd_conf.c index 3d47031..64c0fd2 100644 --- a/USB_DEVICE/Target/usbd_conf.c +++ b/USB_DEVICE/Target/usbd_conf.c @@ -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 */ diff --git a/USB_DEVICE/Target/usbd_conf.h b/USB_DEVICE/Target/usbd_conf.h index 1c853c3..92a2ab1 100644 --- a/USB_DEVICE/Target/usbd_conf.h +++ b/USB_DEVICE/Target/usbd_conf.h @@ -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 */ diff --git a/User/data_storage.c b/User/data_storage.c index bde6783..6edc051 100644 --- a/User/data_storage.c +++ b/User/data_storage.c @@ -349,4 +349,4 @@ HAL_StatusTypeDef DataStorage_SwitchBuffer(DataStorageHandle_t *handle) next_buf->state = BUFFER_WRITING; return HAL_OK; -} \ No newline at end of file +} diff --git a/User/data_storage.h b/User/data_storage.h index 843c7db..a42ffae 100644 --- a/User/data_storage.h +++ b/User/data_storage.h @@ -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 \ No newline at end of file +#endif // DATA_STORAGE_H diff --git a/User/sd_test.c b/User/sd_test.c new file mode 100644 index 0000000..911f589 --- /dev/null +++ b/User/sd_test.c @@ -0,0 +1,168 @@ +/* USER CODE BEGIN Includes */ +#include // 用于 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 + +/* 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 */ diff --git a/User/system_monitor.h b/User/system_monitor.h index 84a8834..b8fcfec 100644 --- a/User/system_monitor.h +++ b/User/system_monitor.h @@ -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; // 系统错误类型