#include #include "stm32f4xx.h" #include "main.h" // #include "config.h" #include "elog.h" #include "bsp_driver_sd.h" #include "fatfs.h" HAL_SD_CardInfoTypeDef SDCardInfo; extern SD_HandleTypeDef hsd; FATFS fs; //工作空间 FIL fil; // 文件项目 extern void printf_sdcard_info(void); extern int Init_FatFas_Mount(void); extern int creat_file(char * filename); extern int open_file(char * filename); extern int close_file( ); extern uint8_t BSP_SD_Init(void); uint8_t BSP_SD_Init(void) { uint8_t sd_state = MSD_OK; /* Check if the SD card is plugged in the slot */ if (BSP_SD_IsDetected() != SD_PRESENT) { return MSD_ERROR; } /* HAL SD initialization */ sd_state = HAL_SD_Init(&hsd); /* Configure SD Bus width (4 bits mode selected) */ if (sd_state == MSD_OK) { hsd.Init.ClockDiv = 6; // hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; /* Enable wide operation */ if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { sd_state = MSD_ERROR; } } return sd_state; } void printf_sdcard_info(void) { uint64_t CardCap; //SD卡容量 HAL_SD_CardCIDTypeDef SDCard_CID; char * card_type[8] = {0}; HAL_SD_GetCardCID(&hsd,&SDCard_CID); //获取CID HAL_SD_GetCardInfo(&hsd,&SDCardInfo); //获取SD卡信息 CardCap=(uint64_t)(SDCardInfo.LogBlockNbr)*(uint64_t)(SDCardInfo.LogBlockSize); //计算SD卡容量 switch(SDCardInfo.CardType) { case CARD_SDSC: { if(SDCardInfo.CardVersion == CARD_V1_X) { memcpy(card_type, (void*)("SDSC V1"),7); // printf("Card Type:SDSC V1\r\n"); } else if (SDCardInfo.CardVersion == CARD_V2_X) { memcpy(card_type, (void*)("SDSC V2"),7); // printf("Card Type:SDSC V2\r\n"); } break; } case CARD_SDHC_SDXC: { memcpy(card_type, (void*)("SDHC"),4); printf("Card Type:SDHC\r\n"); break; } default:break; } #if 1 log_i("Card Type: %s \r\n",card_type); //card 类型 log_i("Card ManufacturerID: %d \r\n",SDCard_CID.ManufacturerID); //制造商ID log_i("CardVersion: %d \r\n",(uint32_t)(SDCardInfo.CardVersion)); //卡版本号 log_i("Class: %d \r\n",(uint32_t)(SDCardInfo.Class)); // log_i("Card RCA(RelCardAdd):%d \r\n",SDCardInfo.RelCardAdd); //卡相对地址 log_i("Card BlockNbr: %d \r\n",SDCardInfo.BlockNbr); //块数量 log_i("Card BlockSize: %d \r\n",SDCardInfo.BlockSize); //块大小 log_i("LogBlockNbr: %d \r\n",(uint32_t)(SDCardInfo.LogBlockNbr)); //逻辑块数量 log_i("LogBlockSize: %d \r\n",(uint32_t)(SDCardInfo.LogBlockSize)); //逻辑块大小 log_i("Card Capacity: %d MB\r\n",(uint32_t)(CardCap>>20)); //卡容量 #endif #if 0 printf("Card ManufacturerID: %d \r\n",SDCard_CID.ManufacturerID); //制造商ID printf("CardVersion: %d \r\n",(uint32_t)(SDCardInfo.CardVersion)); //卡版本号 printf("Class: %d \r\n",(uint32_t)(SDCardInfo.Class)); // printf("Card RCA(RelCardAdd):%d \r\n",SDCardInfo.RelCardAdd); //卡相对地址 printf("Card BlockNbr: %d \r\n",SDCardInfo.BlockNbr); //块数量 printf("Card BlockSize: %d \r\n",SDCardInfo.BlockSize); //块大小 printf("LogBlockNbr: %d \r\n",(uint32_t)(SDCardInfo.LogBlockNbr)); //逻辑块数量 printf("LogBlockSize: %d \r\n",(uint32_t)(SDCardInfo.LogBlockSize)); //逻辑块大小 printf("Card Capacity: %d MB\r\n",(uint32_t)(CardCap>>20)); //卡容量 #endif } int Init_FatFas_Mount(void) { int retSD = f_mount(&fs, "0:", 0); return retSD; } /** * @brief 创建文件 * @param [in] filename "0:aa.txt" * * @details * creat_file( "0:aa.txt" ); */ int creat_file(char * filename) { // f_mkfs( ); int retSD = f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE); //打开文件,权限包括创建、写(如果没有该文件,会创建该文件) if(retSD==FR_OK) { // printf("\r\ncreate file success!!! \r\n"); f_close(&fil); //关闭该文件 return retSD; } else { // printf("\r\ncreate file error : %d\r\n",retSD); f_close(&fil); //关闭该文件 return retSD; } // f_close(&fil); //关闭该文件 // HAL_Delay(100); } int open_file(char * filename) { // f_mkfs( ); int retSD = f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE); //打开文件,权限包括创建、写(如果没有该文件,会创建该文件) if(retSD==FR_OK) { return retSD; } else { return retSD; } // HAL_Delay(100); } int close_file( ) { // f_mkfs( ); f_close(&fil); //关闭该文件 } /** * @brief open write close * @param [in] data * @param [in] len * * @details */ void write_file( char * data, uint32_t len ) { uint32_t byteswritten; /*##-3- Write data to the text files ###############################*/ int retSD = f_write(&fil, data, len, (void *)&byteswritten); if(retSD) log_i(" write file error : %d\r\n",retSD); else { log_i(" write file sucess!!! \r\n"); log_i(" write Data[%d] : %s\r\n",byteswritten,data); } /*##-4- Close the open text files ################################*/ retSD = f_close(&fil); if(retSD) log_i(" close error : %d\r\n",retSD); else log_i(" close sucess!!! \r\n"); } void SD_Read_block_Test(void) { // uint8_t read_buf[512]; // int sdcard_status = HAL_SD_ReadBlocks(&hsd, (uint8_t *)read_buf, 0, 1, 0xffff); // if(sdcard_status == HAL_OK) // { // printf("Read block data ok! \r\n"); // } // else // { // printf("Read block data fail! status = %d \r\n", sdcard_status); // } } /* 修改方案: ### SD 初始化 ***创建文件失败错误*** SDIO.c文件 hsd.Init.BusWide = SDIO_BUS_WIDE_1B; hsd.Init.ClockDiv = SDIO_INIT_CLK_DIV; //SDIO_TRANSFER_CLK_DIV; ### DMA FIFO WORD ### 中断 SDIO 优于 DMA 优于 USB 值正好相反 ### heap stack 0x1000 ox1500 f_mount等要放任务中,增加了堆栈大小 StartDefaultTask 堆栈要调大 1024 ### 最大最小扇区大小 512 -> 4096 FATFS 两处地方 USB_Device 两处地方 ### USB 的调整 ***CubeMX 自动将 MX_USB_DEVICE_Init() 函数放到 StartDefaultTask 中 *** 优于定义了 StartDefaultTask 虚函数, 不执行 需要手动移植到实际函数中 USB_Device初始化函数在默认任务中,所以要增加默认任务 StartDefaultTask 的堆栈, MX_USB_DEVICE_Init(); ### 重写usbd_storage_if.c USB_DEVICE\App\usbd_storage_if.c *** 不写的话 读取不到Upan信息, 显示upan大小都不对 *** #define STORAGE_LUN_NBR 1 // 逻辑单元号,只有一个外部flash,设置为1 #define STORAGE_BLK_NBR 2048 //扇区的数量,外部flash的大小是8Mbyte,有128块,每块16个扇区,故128*16=2048个扇区 #define STORAGE_BLK_SIZ 4096 // 每个扇区的大小,外部flash扇区的大小为4096byte/ 以上通过输出SD信息改写 因为加入了FreeRTOS,fatfs对sd卡读写用的是发送消息机制, 所以usbd_storage_if.c里的读写不能再去调用bsp_driver_sd.c里的读写方法了, 大家有兴趣的可以对比一下有无FreeRTOS,bsp_driver_sd.c源码的内容 读写方法等 STM32F407 开发板没有用到 VUSB 电压检测,所以要在 usb_conf.h 里面 将宏定义:#define VBUS_SENSING_ENABLED,屏蔽掉。 3,通过修改 usbd_conf.h 里面的 MSC_MEDIA_PACKET 定义值大小,可以一定程度提高 USB 读写速度(越大越快),本例程我们设置 12*1024,也就是 12K 大小。 ***官方例程不支持大于 4G 的 SD 卡*** Middlewares\ST\STM32_USB_Device_Library\Class\MSC\Src 官方例程不支持大于 4G 的 SD 卡,得修改 usbd_msc_scsi.c 里面的 或 usbd_msc.h( Cubemx HAl) SCSI_blk_addr 类型为 uint64_t,才可以支持大于 4G 的卡,官方默认是 uint32_t,最大只能支持 4G 卡。 注意: usbd_msc.h uint64_t scsi_blk_addr; uint64_t scsi_blk_len; usbd_msc_scsi.c 文件,是只读的,得先修改属性,去掉只读属性,才可以更改。 HS FS 标记 #define DEVICE_FS 1 #define DEVICE_HS 0 usb_devioce MSC_MEDIA_PAKCET 改32678 32*1024U #### usb 编译 -DUSE_USB_OTG_FS */