Недавно вышла новая версия куба – STM32CubeF4 1.6.0. В рамках релиза расскажу, как поднять MSC с полноценной файловой системой на борту. Поднимать будем на базе отладочной платы STM32F429I-DISCO.
Будем менять проект, который работает на SDIO, проект Projects\STM324x9I_EVAL\Applications\USB_Device\MSC_Standalone\, после изменений проект будет работать через внешнее ОЗУ.
Далее будем следовать мои инструкциям:
1. Удаляем каталоги в проекте:
Drivers/BSP/Components
Drivers/BSP/STM324x9I_EVAL
2. Добавляем каталоги в проект:
Drivers/BSP/STM32429I_DISCO
stm32f429i_discovery.c
stm32f429i_discovery_sdram.c
Middlewares/FatFs/Core
diskio.c
ff.c
ff_gen_drv.c
Middlewares/FatFs/Drivers
sdram_disco.c
было
стало
3. Макрос HSE_VALUE нужно во всех файлах поменять на #define HSE_VALUE ((uint32_t)8000000),(был 25000000)
либо определить глобально в настройках проекта.
Первый делитель для ФАПЧ должен быть 8, поэтому изменяем его RCC_OscInitStruct.PLL.PLLM = 8; (был 25)
Плюс еще несколько изменений (смотреть скриншоты).
4. Изменяем файлы проекта для работы с USB MSC Device.
main.c
/** ****************************************************************************** * @file USB_Device/MSC_Standalone/Src/main.c * @author MCD Application Team * @version V1.2.2 * @date 25-May-2015 * @brief USB device Mass storage demo main file ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ USBD_HandleTypeDef USBD_Device; /* Private function prototypes -----------------------------------------------*/ static void SystemClock_Config(void); /* Private functions ---------------------------------------------------------*/ /** * @brief Main program * @param None * @retval None */ int main(void) { /* STM32F4xx HAL library initialization: - Configure the Flash prefetch, instruction and Data caches - Configure the Systick to generate an interrupt each 1 msec - Set NVIC Group Priority to 4 - Global MSP (MCU Support Package) initialization */ HAL_Init(); /* Configure the system clock to 168 MHz */ SystemClock_Config(); // /* Configure LED1, LED2, LED3 and LED4 */ // BSP_LED_Init(LED1); // BSP_LED_Init(LED2); // BSP_LED_Init(LED3); // BSP_LED_Init(LED4); /* Init MSC Application */ USBD_Init(&USBD_Device, &MSC_Desc, 0); /* Add Supported Class */ USBD_RegisterClass(&USBD_Device, USBD_MSC_CLASS); /* Add Storage callbacks for MSC Class */ USBD_MSC_RegisterStorage(&USBD_Device, &USBD_DISK_fops); /* Start Device Process */ USBD_Start(&USBD_Device); /* Run Application (Interrupt mode) */ while (1) { } } /** * @brief System Clock Configuration * The system Clock is configured as follow : * System Clock source = PLL (HSE) * SYSCLK(Hz) = 168000000 * HCLK(Hz) = 168000000 * AHB Prescaler = 1 * APB1 Prescaler = 4 * APB2 Prescaler = 2 * HSE Frequency(Hz) = 25000000 * PLL_M = 25 * PLL_N = 336 * PLL_P = 2 * PLL_Q = 7 * VDD(V) = 3.3 * Main regulator output voltage = Scale1 mode * Flash Latency(WS) = 5 * @param None * @retval None */ static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; /* Enable Power Control clock */ __HAL_RCC_PWR_CLK_ENABLE(); /* The voltage scaling allows optimizing the power consumption when the device is clocked below the maximum system frequency, to update the voltage scaling value regarding system frequency refer to product datasheet. */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* Configure RCC Oscillators: All parameters can be changed according to userӳ needs */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = 2; RCC_OscInitStruct.PLL.PLLQ = 7; HAL_RCC_OscConfig(&RCC_OscInitStruct); /* RCC Clocks: All parameters can be changed according to userӳ needs */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); } /** * @brief Toggles LEDs to show user input state. * @param None * @retval None */ //void Toggle_Leds(void) //{ // static uint32_t ticks; // // if(ticks++ == 100) // { // BSP_LED_Toggle(LED1); // BSP_LED_Toggle(LED2); // BSP_LED_Toggle(LED3); // BSP_LED_Toggle(LED4); // ticks = 0; // } //} #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 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) */ /* Infinite loop */ while (1) { } } #endif /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
main.h
/** ****************************************************************************** * @file USB_Device/MSC_Standalone/Inc/main.h * @author MCD Application Team * @version V1.2.2 * @date 25-May-2015 * @brief Header for main.c module ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __MAIN_H #define __MAIN_H /* Includes ------------------------------------------------------------------*/ #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_msc.h" #include "usbd_storage.h" //#include "stm324x9i_eval.h" //#include "stm324x9i_eval_sd.h" /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ //void Toggle_Leds(void); #endif /* __MAIN_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
stm32f4xx_it.c
/** ****************************************************************************** * @file USB_Device/MSC_Standalone/Src/stm32f4xx_it.c * @author MCD Application Team * @version V1.2.2 * @date 25-May-2015 * @brief Main Interrupt Service Routines. * This file provides template for all exceptions handler and * peripherals interrupt service routine. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "stm32f4xx_it.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ extern PCD_HandleTypeDef hpcd; /* Private function prototypes -----------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /* Cortex-M4 Processor Exceptions Handlers */ /******************************************************************************/ /** * @brief This function handles NMI exception. * @param None * @retval None */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. * @param None * @retval None */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles Memory Manage exception. * @param None * @retval None */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** * @brief This function handles Bus Fault exception. * @param None * @retval None */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** * @brief This function handles Usage Fault exception. * @param None * @retval None */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. * @param None * @retval None */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. * @param None * @retval None */ void DebugMon_Handler(void) { } /** * @brief This function handles PendSVC exception. * @param None * @retval None */ void PendSV_Handler(void) { } /** * @brief This function handles SysTick Handler. * @param None * @retval None */ void SysTick_Handler(void) { HAL_IncTick(); // Toggle_Leds(); } /******************************************************************************/ /* STM32F4xx Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_stm32f4xx.s). */ /******************************************************************************/ /** * @brief This function handles USB-On-The-Go FS global interrupt request. * @param None * @retval None */ #ifdef USE_USB_FS void OTG_FS_IRQHandler(void) #else void OTG_HS_IRQHandler(void) #endif { HAL_PCD_IRQHandler(&hpcd); } /** * @brief This function handles SDIO interrupt request. * @param None * @retval None */ void SDIO_IRQHandler(void) { // BSP_SD_IRQHandler(); } /** * @brief This function handles DMA2 Stream 3 interrupt request. * @param None * @retval None */ void DMA2_Stream3_IRQHandler(void) { // BSP_SD_DMA_Rx_IRQHandler(); } /** * @brief This function handles DMA2 Stream 6 interrupt request. * @param None * @retval None */ void DMA2_Stream6_IRQHandler(void) { // BSP_SD_DMA_Tx_IRQHandler(); } /** * @brief This function handles PPP interrupt request. * @param None * @retval None */ /*void PPP_IRQHandler(void) { }*/ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
usbd_storage.c
/** ****************************************************************************** * @file USB_Device/MSC_Standalone/Src/usbd_storage.c * @author MCD Application Team * @version V1.2.2 * @date 25-May-2015 * @brief Memory management layer ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_storage.h" #include "ff_gen_drv.h" #include "sdram_diskio.h" //#include "stm324x9I_eval_sd.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define STORAGE_LUN_NBR 1 #define STORAGE_BLK_NBR 0x10000 #define STORAGE_BLK_SIZ 0x200 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* USB Mass storage Standard Inquiry Data */ int8_t STORAGE_Inquirydata[] = { /* 36 */ /* LUN 0 */ 0x00, 0x80, 0x02, 0x02, (STANDARD_INQUIRY_DATA_LEN - 5), 0x00, 0x00, 0x00, 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer: 8 bytes */ 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '.', '0','1', /* Version : 4 Bytes */ }; /* Private function prototypes -----------------------------------------------*/ int8_t STORAGE_Init(uint8_t lun); int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size); int8_t STORAGE_IsReady(uint8_t lun); int8_t STORAGE_IsWriteProtected(uint8_t lun); int8_t STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t STORAGE_GetMaxLun(void); USBD_StorageTypeDef USBD_DISK_fops = { STORAGE_Init, STORAGE_GetCapacity, STORAGE_IsReady, STORAGE_IsWriteProtected, STORAGE_Read, STORAGE_Write, STORAGE_GetMaxLun, STORAGE_Inquirydata, }; FATFS RAMDISKFatFs; /* File system object for RAM disk logical drive */ FIL MyFile; /* File object */ char RAMDISKPath[4]; /* RAM disk logical drive path */ /* Private functions ---------------------------------------------------------*/ /** * @brief Initailizes the storage unit (medium) * @param lun: Logical unit number * @retval Status (0 : Ok / -1 : Error) */ int8_t STORAGE_Init(uint8_t lun) { volatile int8_t Error_Handler_Return = 0; FRESULT res; /* FatFs function common result code */ uint32_t byteswritten, bytesread; /* File write/read counts */ uint8_t wtext[] = "Привет, мир!!!"; /* File write buffer */ uint8_t rtext[100]; /* File read buffer */ /*##-1- Link the RAM disk I/O driver #######################################*/ if(FATFS_LinkDriver(&SDRAMDISK_Driver, RAMDISKPath) == 0) { /*##-2- Register the file system object to the FatFs module ##############*/ if(f_mount(&RAMDISKFatFs, (TCHAR const*)RAMDISKPath, 0) != FR_OK) { /* FatFs Initialization Error */ Error_Handler_Return = -1; } else { /*##-3- Create a FAT file system (format) on the logical drive #########*/ if(f_mkfs((TCHAR const*)RAMDISKPath, 0, 0) != FR_OK) { /* FatFs Format Error */ Error_Handler_Return = -1; } else { /*##-4- Create and Open a new text file object with write access #####*/ if(f_open(&MyFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { /* 'STM32.TXT' file Open for write Error */ Error_Handler_Return = -1; } else { /*##-5- Write data to the text file ################################*/ res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten); if((byteswritten == 0) || (res != FR_OK)) { /* 'STM32.TXT' file Write or EOF Error */ Error_Handler_Return = -1; } else { /*##-6- Close the open text file #################################*/ f_close(&MyFile); /*##-7- Open the text file object with read access ###############*/ if(f_open(&MyFile, "STM32.TXT", FA_READ) != FR_OK) { /* 'STM32.TXT' file Open for read Error */ Error_Handler_Return = -1; } else { /*##-8- Read data from the text file ###########################*/ res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread); if((bytesread == 0) || (res != FR_OK)) { /* 'STM32.TXT' file Read or EOF Error */ Error_Handler_Return = -1; } else { /*##-9- Close the open text file #############################*/ f_close(&MyFile); /*##-10- Compare read data with the expected data ############*/ if ((bytesread != byteswritten)) { /* Read data is different from the expected data */ Error_Handler_Return = -1; } else { /* Success of the demo: no error occurrence */ } } } } } } } } /*##-11- Unlink the RAM disk I/O driver ####################################*/ FATFS_UnLinkDriver(RAMDISKPath); return Error_Handler_Return ; // BSP_SD_Init(); // return 0; } /** * @brief Returns the medium capacity. * @param lun: Logical unit number * @param block_num: Number of total block number * @param block_size: Block size * @retval Status (0: Ok / -1: Error) */ int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { // HAL_SD_CardInfoTypedef info; // int8_t ret = -1; // // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) // { // BSP_SD_GetCardInfo(&info); // // *block_num = (info.CardCapacity)/STORAGE_BLK_SIZ - 1; // *block_size = STORAGE_BLK_SIZ; // ret = 0; // } // return ret; *block_num = STORAGE_BLK_NBR; *block_size = STORAGE_BLK_SIZ; return 0; } /** * @brief Checks whether the medium is ready. * @param lun: Logical unit number * @retval Status (0: Ok / -1: Error) */ int8_t STORAGE_IsReady(uint8_t lun) { // static int8_t prev_status = 0; // int8_t ret = -1; // // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) // { // if(prev_status < 0) // { // BSP_SD_Init(); // prev_status = 0; // // } // if(BSP_SD_GetStatus() == SD_TRANSFER_OK) // { // ret = 0; // } // } // else if(prev_status == 0) // { // prev_status = -1; // } // return ret; return 0; } /** * @brief Checks whether the medium is write protected. * @param lun: Logical unit number * @retval Status (0: write enabled / -1: otherwise) */ int8_t STORAGE_IsWriteProtected(uint8_t lun) { return 0; } /** * @brief Reads data from the medium. * @param lun: Logical unit number * @param blk_addr: Logical block address * @param blk_len: Blocks number * @retval Status (0: Ok / -1: Error) */ int8_t STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { // int8_t ret = -1; // // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) // { // BSP_SD_ReadBlocks_DMA((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len); // ret = 0; // } // return ret; memcpy(buf, (void *)(SDRAM_DEVICE_ADDR + (STORAGE_BLK_SIZ * blk_addr)), (STORAGE_BLK_SIZ * blk_len)); return 0; } /** * @brief Writes data into the medium. * @param lun: Logical unit number * @param blk_addr: Logical block address * @param blk_len: Blocks number * @retval Status (0 : Ok / -1 : Error) */ int8_t STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { // int8_t ret = -1; // // if(BSP_SD_IsDetected() != SD_NOT_PRESENT) // { // BSP_SD_WriteBlocks_DMA((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len); // ret = 0; // } // return ret; memcpy((void *)(SDRAM_DEVICE_ADDR + (STORAGE_BLK_SIZ * blk_addr)), buf, (STORAGE_BLK_SIZ * blk_len)); return 0; } /** * @brief Returns the Max Supported LUNs. * @param None * @retval Lun(s) number */ int8_t STORAGE_GetMaxLun(void) { return(STORAGE_LUN_NBR - 1); } /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Проект целиком, MSC_Standalone.7z, нужно заменить его на исходный проект в каталоге куба.