No Disk in the Drive 错误

本文记录了一次使用ghost捕获硬盘时遇到的错误:“Thereisnodiskinthedrive.PleaseinsertadiskintothedriveDeviceHarddisk2DR2”。通过更换USB接口解决了该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There is no disk in the drive. Please insert a disk into the drive \Device\Harddisk2\DR2".

 

微软有一篇文章讲的这个错误http://support.microsoft.com/kb/330137

当我用ghost capture机器中的hard disk时碰到这个错误,这时我的USB的盘符是F。

我换了一个USB口后,这个错误消失了,此时USB的盘符是E。

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "fatfs.h" #include "spi.h" #include "usb_device.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ #include "stdio.h" #include "string.h" #include "user_diskio.h" #include "w25qxx.h" #include "ff.h" #define User_Sector 4096 BYTE workBuffer[User_Sector]; FATFS fs; void Mount_FS() { static FRESULT res1 =FR_INT_ERR; res1 = f_mount(&fs, "", 1); if (res1 != FR_OK) { if (res1 == FR_NO_FILESYSTEM){ res1 = f_mkfs("",1,0); if(res1 != FR_OK){ HAL_Delay(10); return; } else{ res1 = f_mount(&fs,"",1); if (res1 != FR_OK) { HAL_Delay(10); } } } } } void FatFs_WriteTXTFile(void){ FIL fil; UINT bw; FRESULT res = f_open(&fil,"file.txt",FA_CREATE_ALWAYS|FA_WRITE); if(res != FR_OK){ return; } const char*text ="hello\n"; res = f_write(&fil, text, strlen(text), &bw); if(res != FR_OK){ return; } f_close(&fil); res = f_open(&fil,"file.txt",FA_READ); if(res != FR_OK){ return; } char BUFFE[20]; res = f_read(&fil,BUFFE,strlen(BUFFE),&bw); } /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USB_DEVICE_Init(); MX_FATFS_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ W25qxx_Init(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ uint8_t test_buf[]="Hello"; uint8_t send_cnt=0; Mount_FS(); while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // if(send_cnt%1000 == 0){ // CDC_Transmit_FS(test_buf,sizeof(test_buf)-1); // } // HAL_Delay(1); // send_cnt++; FatFs_WriteTXTFile(); HAL_Delay(100); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file user_diskio.c * @brief This file includes a diskio driver skeleton to be completed by the user. ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ #ifdef USE_OBSOLETE_USER_CODE_SECTION_0 /* * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0) * To be suppressed in the future. * Kept to ensure backward compatibility with previous CubeMx versions when * migrating projects. * User code previously added there should be copied in the new user sections before * the section contents can be deleted. */ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ #endif /* USER CODE BEGIN DECL */ /* Includes ------------------------------------------------------------------*/ #include <string.h> #include "ff_gen_drv.h" #include "w25qxx.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Disk status */ static volatile DSTATUS Stat = STA_NOINIT; /* USER CODE END DECL */ /* Private function prototypes -----------------------------------------------*/ DSTATUS USER_initialize (BYTE pdrv); DSTATUS USER_status (BYTE pdrv); DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count); #if _USE_WRITE == 1 DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count); #endif /* _USE_WRITE == 1 */ #if _USE_IOCTL == 1 DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff); #endif /* _USE_IOCTL == 1 */ Diskio_drvTypeDef USER_Driver = { USER_initialize, USER_status, USER_read, #if _USE_WRITE USER_write, #endif /* _USE_WRITE == 1 */ #if _USE_IOCTL == 1 USER_ioctl, #endif /* _USE_IOCTL == 1 */ }; /* Private functions ---------------------------------------------------------*/ /** * @brief Initializes a Drive * @param pdrv: Physical drive number (0..) * @retval DSTATUS: Operation status */ DSTATUS USER_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { /* USER CODE BEGIN INIT */ Stat = USER_status(pdrv); return Stat; /* USER CODE END INIT */ } /** * @brief Gets Disk Status * @param pdrv: Physical drive number (0..) * @retval DSTATUS: Operation status */ DSTATUS USER_status ( BYTE pdrv /* Physical drive number to identify the drive */ ) { /* USER CODE BEGIN STATUS */ Stat = STA_NOINIT; if(0 != W25qxx_ReadID()){ Stat &= ~STA_NOINIT; } return Stat; /* USER CODE END STATUS */ } /** * @brief Reads Sector(s) * @param pdrv: Physical drive number (0..) * @param *buff: Data buffer to store read data * @param sector: Sector address (LBA) * @param count: Number of sectors to read (1..128) * @retval DRESULT: Operation result */ DRESULT USER_read ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to read */ ) { /* USER CODE BEGIN READ */ uint32_t ReadAddr = sector * 4096; uint32_t NumByteToRead = count *4096; W25qxx_ReadBytes(buff,ReadAddr,NumByteToRead); return RES_OK; /* USER CODE END READ */ } /** * @brief Writes Sector(s) * @param pdrv: Physical drive number (0..) * @param *buff: Data to be written * @param sector: Sector address (LBA) * @param count: Number of sectors to write (1..128) * @retval DRESULT: Operation result */ #if _USE_WRITE == 1 DRESULT USER_write ( BYTE pdrv, /* Physical drive nmuber to identify the drive */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to write */ ) { /* USER CODE BEGIN WRITE */ /* USER CODE HERE */ if(pdrv != 0) return RES_PARERR; uint32_t ReadAddr = sector * 4096; UINT NumByteToRead = count; for(UINT i=0;i<NumByteToRead;i++){ W25qxx_EraseSector(sector+i); W25qxx_WriteSector((uint8_t*)buff,sector+i,0,4096); ReadAddr += 4096; buff += 4096; } // uint8_t secCount = (NumByteToRead / 4096); // if ((NumByteToRead%4096) > 0) // secCount++; //uint32_t SectorAddr = ReadAddr; //for(uint8_t k = 0; k < secCount; k++){ // W25qxx_EraseSector(secCount); //SectorAddr += 4096; //} // W25qxx_WriteSector((uint8_t*)buff,ReadAddr,0,NumByteToRead); return RES_OK; /* USER CODE END WRITE */ } #endif /* _USE_WRITE == 1 */ /** * @brief I/O control operation * @param pdrv: Physical drive number (0..) * @param cmd: Control code * @param *buff: Buffer to send/receive control data * @retval DRESULT: Operation result */ #if _USE_IOCTL == 1 DRESULT USER_ioctl ( BYTE pdrv, /* Physical drive nmuber (0..) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { /* USER CODE BEGIN IOCTL */ DRESULT res = RES_OK; switch (cmd){ case CTRL_SYNC: break; case GET_SECTOR_COUNT: *(DWORD*)buff = 4096; break; case GET_SECTOR_SIZE: *(WORD*)buff = 4096; break; case GET_BLOCK_SIZE: *(WORD*)buff = 16; break; default: res = RES_PARERR; } return res; /* USER CODE END IOCTL */ } #endif /* _USE_IOCTL == 1 */ 分析错误
最新发布
07-20
### 代码概述 本代码是一个基于STM32F104微控制器的嵌入式系统项目,使用SPI接口操作W25QXX系列Flash芯片,并通过FATFS文件系统实现文件读写功能。主程序中调用`FatFs_WriteTXTFile`函数创建并写入一个文本文件,使用自定义的`user_diskio.c`实现FATFS底层驱动。 ### 代码解析 #### 一、`FatFs_WriteTXTFile`函数存在的问题 1. **文件写入后未关闭文件**: ```c res = f_open(&fil,"file.txt",FA_READ); if(res != FR_OK){ return; } char BUFFE[20]; res = f_read(&fil,BUFFE,strlen(BUFFE),&bw); ``` - 该段代码打开了文件进行读取,但**没有调用`f_close`关闭文件**,可能导致后续文件操作失败或缓存未刷新。 2. **`strlen(BUFFE)`使用错误**: ```c char BUFFE[20]; res = f_read(&fil,BUFFE,strlen(BUFFE),&bw); ``` - `BUFFE`是一个未初始化的数组,`strlen(BUFFE)`的行为是未定义的,应该直接使用`sizeof(BUFFE)`来指定读取长度。 #### 二、`user_diskio.c`中的`USER_write`函数存在严重问题 1. **擦除与写入方式不当**: ```c for(UINT i=0;i<NumByteToRead;i++){ W25qxx_EraseSector(sector+i); W25qxx_WriteSector((uint8_t*)buff,sector+i,0,4096); ReadAddr += 4096; buff += 4096; } ``` - 每次写入都先擦除整个扇区,这是Flash操作的基本规则,但效率低下。 - 如果用户传入的`count`不是以4096字节对齐的扇区数量,会导致错误。 2. **写入函数参数处理错误**: - `count`表示的是**扇区数**(每个扇区为4096字节),但代码中直接使用`count`作为字节数操作: ```c UINT NumByteToRead = count; ``` 应改为: ```c UINT NumByteToRead = count * 4096; ``` 3. **逻辑错误**: - `W25qxx_WriteSector(...,4096)`参数可能不正确,如果函数期望的是字节数,应确保输入的长度是正确的。 #### 三、`USER_ioctl`函数配置问题 ```c case GET_SECTOR_COUNT: *(DWORD*)buff = 4096; ``` - `GET_SECTOR_COUNT`应返回**总扇区数**,而4096扇区意味着总容量只有`4096 * 4096 = 16MB`,如果W25QXX容量更大(如64MB或128MB),则此设置错误,会导致FATFS格式化失败或无法识别全部空间。 #### 四、内存使用问题 ```c BYTE workBuffer[User_Sector]; ``` - 使用了4096字节的全局缓冲区,对于STM32F104系列(SRAM小)可能造成内存紧张。 --- ### 知识点 1. **FATFS底层驱动实现**:需实现`disk_initialize`、`disk_read`、`disk_write`、`disk_ioctl`等函数,确保与硬件操作匹配。 2. **Flash擦写机制**:写入前必须先擦除扇区,且频繁擦写会缩短Flash寿命。 3. **内存管理与优化**:在小内存系统中应尽量避免大块内存的全局使用,采用局部或缓冲区复用方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值