STM32 USB HOST MSC
In this tutorial, we will see how to use STM32 USB as a host to interface any Mass Storage Device, for eg- flash drive, or a SD card. To do so, we need to use USB as a Mass Storage Class (MSC). We will also use FATFS (FAT File System) to create some directories, and files on the USB.
CubeMX Setup
First of all we need to select the USB_OTG_FS in Host Only mode. Also make sure you activate the VBUS, as the USB devices mostly don’t have the Power supply, and that’s why VBUS will provide the required power to such devices.
Next, select the USB_HOST and select the class as Mass Storage Class. Leave everything here to default.
Above is the Setup for the FATFS.
I have enabled the use of Long File names.
Increase the MAX sector size to 4096
I have also enabled the support for EXFAT File System.
And now we need to enable the voltage supply to the VBUS pin. To do that you need to look at the user manual for your board. I am using STM32F4 discovery board, and it have the following diagram for the USB
As you can see above, the VBUS is powered from the PC0 pin. But PC0 is connected to the EN Pin, which is an active Low pin. This means in order to supply the voltage to the VBUS, we must Pull down the PC0 Pin, or basically Set it LOW.
The final PINOUT is as shown above
- UART2 is connected to PC, so that we can see the output for the debugging purpose
- PC0 is set as output, to enable the voltage to the VBUS
- USB Pins are automatically selected, when you select the USB HOST
Some Insight into the code
First of all we need to copy the file handling library files. This is just some FATFS functions arranged in some ways to make the interface a bit easier.
We need to write our program in the usb_host.c file. It is located in root->USB_HOST->App folder
static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id)
{
/* USER CODE BEGIN CALL_BACK_1 */
switch(id)
{
case HOST_USER_SELECT_CONFIGURATION:
break;
case HOST_USER_DISCONNECTION:
Appli_state = APPLICATION_DISCONNECT;
Unmount_USB();
break;
case HOST_USER_CLASS_ACTIVE:
Appli_state = APPLICATION_READY;
Mount_USB();
Check_USB_Details(); // check space details
Scan_USB("/"); // scan for files and directories
Create_File("/ROOTFILE.txt");
Write_File("/ROOTFILE.txt", "This data should be in root file\n");
Create_Dir("/DIR1");
Create_File("/DIR1/DIR1FILE.txt");
Write_File("/DIR1/DIR1FILE.txt", "This data should be in DIR1 file\n");
Create_Dir("/DIR2");
Create_Dir("/DIR2/SUBDIR1");
Create_File("/DIR2/SUBDIR1/DIR2FILE.txt");
Write_File("/DIR2/SUBDIR1/DIR2FILE.txt", "This data should be in DIR2/SUBDIR1 file\n as i have nothing better to write/n so i just wrote this\n");
Update_File("/ROOTFILE.txt", "This updated data must be in second line of Root File\n");
break;
case HOST_USER_CONNECTION:
Appli_state = APPLICATION_START;
break;
default:
break;
}
/* USER CODE END CALL_BACK_1 */
}
USBH_UserProcess is called at different states, for eg- when the USB Connects, or Disconnects, or When it is Ready for Communication. We will write our program once the Application is READY
The above program is self explanatory. We are creating some files, and Directories. Also we are writing some data inside those files.
Once you connect the USB, the UART output of the above program is shown below