| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2020-07-07 | gingko | 初次建立 | ===== 实验十九:USBD_MSC实验——虚拟U盘 ===== ==== 一、 实验目的与意义 ==== - 了解STM32 USB SLAVE结构。 - 了解STM32 USB SLAVE特征。 - 掌握USB SLAVE MSC的使用方法。 - 掌握STM32 HAL库中USB SLAVE属性的配置方法。 - 掌握KEIL MDK 集成开发环境使用方法。 ==== 二、 实验设备及平台 ==== - iCore4 双核心板[[https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22598974120.15.5923532fsFrHiE&id=551864196684|点击购买]]。 - JLINK(或相同功能)仿真器[[https://item.taobao.com/item.htm?id=554869837940|点击购买]]。 - Micro USB线缆。 - Keil MDK 开发平台。 - STM32CubeMX开发平台。 - 装有WIN XP(及更高版本)系统的计算机。 ==== 三、 实验原理 ==== === 1、USB MSC简介 === * USB大容量存储设备(英语:USB mass storage device class,也称为USB MSC或UMS)是一个协议,允许一个USB接口的设备与主计算设备相连接,以便在两者之间传输文件。对于主计算设备来说,USB设备看起来就像一个移动硬盘,允许拖放型文件传送。它实际上是由USB实施者论坛所通过许多通讯协议的汇总,这一标准提供了许多设备的界面。包括移动硬盘、闪存盘、移动光学驱动器、读卡器、数码相机、数码音乐播放器、PDA以及手机等等。 === 2、USB模块介绍 === * USB模块为PC主机和微控制器所实现的功能之间提供了符合USB规范的通信连接。PC主机和微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小所决定,每个端点最大可使用512字节缓冲区,最多可用于16个单向或8个双向端点。 * USB模块同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处理。整个传输的格式由硬件完成,其中包括CRC的生成和校验。每个端点都有一个缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。当USB模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。 * USB模块通过一个内部的16位寄存器实现端口与专用缓冲区的数据交换。在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的中断处理程序,微控制器可以确定:哪个端点需要得到服务;产生如位填充、格式、CRC、协议、缺失ACK、缓冲区溢出/缓冲区未满等错误时,正在进行的是哪种类型的传输。 === 3、USB_OTG主要特性 === * 主要特性可分为三类:通用特性、主机模式特性和从机模式特性。 == (1) 通用特性 == * OTG_FS/OTG_HS 接口的通用特性如下: *  经USB-IF认证,符合通用串行总线规范第2.0版 *  OTGHS支持3个PHY接口 * – 片上全速PHY * – 连接外部全速PHY的I2C接口 * – 连接外部高速PHY的ULPI接口 *  模块内嵌的PHY还完全支持定义在标准规范OTG补充第1.3版中的OTG协议 * – 支持A-B器件识别(ID线) * – 支持主机协商协议(HNP)和会话请求协议(SRP) * – 允许主机关闭VBUS以在OTG应用中节省电池电量 * – 支持通过内部比较器对VBUS电平采取OTG监控 * – 支持主机到从机的角色动态切换 *  可通过软件配置为以下角色: * – 具有SRP功能的USBFS/HS从机(B器件) * – 具有SRP功能的USBFS/HS/LS主机(A器件) * – USBOn-The-Go全速双角色设备 *  支持FS/HSSOF和LSKeep-alive令牌 * – SOF脉冲可通过PAD输出 * – SOF脉冲从内部连接到定时器(TIMx) * – 可配置的帧周期 * – 可配置的帧结束中断 *  OTGHS内嵌DMA,并可软件配置AHB的批量传输类型。 *  具有省电功能,例如在USB挂起期间停止系统、关闭数字模块时钟、对PHY和DFIFO电源加以管理 *  具有采用高级FIFO控制的1.25K[FS]/4K[HS]字节专用RAM: * – 可将RAM空间划分为不同FIFO,以便灵活有效地使用RAM * – 每个FIFO可存储多个数据包 * – 动态分配存储区 * – FIFO大小可配置为非2的幂次方值,以便连续使用存储单元 == (2) 主机模式特性 == * OTG_FS/OTG_HS接口在主机模式下具有以下主要特性和要求: *  通过外部电荷泵生成VBUS电压。 *  多达12[FS]/16[HS]个主机通道(又称之为管道):每个通道都可以动态实现重新配置,可支持任何类型的USB传输。 *  内置硬件调度器可: * – 在周期性传输硬件队列中存储多达12[FS]/16[HS]个中断加同步传输请求 * – 在非周期性传输硬件队列中存储多达12[FS]/16[HS]个控制加批量传输请求 *  管理一个共享RxFIFO、一个周期性传输TxFIFO和一个非周期性传输TxFIFO,以有效使用USB数据RAM。 == (3) 从机模式特性 == * OTG_FS/OTG_HS接口在从机模式下具有以下主要特性: *  1个双向控制端点0 *  5[FS]/7[HS]个IN端点(EP),可配置为支持批量传输、中断传输或同步传输 *  具有5[FS]/7[HS]个OUT端点,可配置为支持批量、中断或同步传输 *  管理一个共享RxFIFO和一个Tx-OUTFIFO,以高效使用USB数据RAM *  管理多达6[FS]/8[HS]个专用Tx-INFIFO(分别用于每个使能的INEP),降低应用程序负荷 *  支持软断开功能。 === 4、高速OTG模块框图 === {{ :icore4:icore4_arm_hal_19_1.png?direct&750 |}} === 5、OTG_HS中断 === {{ :icore4:icore4_arm_hal_19_2.png?direct |}} * 上图显示了中断层级,当OTG_HS控制器在一种模式下(设备模式或主机模式)工作时,应用程序不得以另一种角色模式访问寄存器。如果发生了非法访问,将会产生模式不匹配中断并在模块中断寄存器(OTG_GINTSTS寄存器中的MMIS位)中反映。当模块从一种角色模式切换到另一种角色模式时,新工作模式下的寄存器必须重新编程为上电复位后的状态。 === 6、原理图 === {{ :icore4:icore4_arm_hal_19_3.png?direct |}} * 本实验利用SD卡虚拟U盘,用USB线连接PC机与开发板,在电脑上就可以像操作普通U盘那样来操作开发板中的MicroSD卡。 ==== 四、 实验程序 ==== === 1、主函数 === int main(void) { /* MCU 配置 */ /* 重置所有外设, 初始化 Flash接口和Systick. */ HAL_Init(); /* 配置系统时钟 */ SystemClock_Config(); /* 初始化所有已配置的外设 */ MX_GPIO_Init(); MX_USB_DEVICE_Init(); while (1) { /* 三色LED灯交替点亮 */ LED_RED_ON; LED_GREEN_OFF; LED_BLUE_OFF; HAL_Delay(500); LED_RED_OFF; LED_GREEN_ON; LED_BLUE_OFF; HAL_Delay(500); LED_RED_OFF; LED_GREEN_OFF; LED_BLUE_ON; HAL_Delay(500); } } === 2、USB DEVICE初始化 === void MX_USB_DEVICE_Init(void) { /* 初始化设备库,添加支持的类并启动该库*/ /* 初始化设备堆栈并加载类驱动程序*/ USBD_Init(&hUsbDeviceHS, &HS_Desc, DEVICE_HS); /* 将驱动程序类连接到Device Core*/ USBD_RegisterClass(&hUsbDeviceHS, &USBD_MSC); USBD_MSC_RegisterStorage(&hUsbDeviceHS, &USBD_Storage_Interface_fops_HS); /* 启动USB Device 内核*/ USBD_Start(&hUsbDeviceHS); } === 3、STORAGE初始化 === int8_t STORAGE_Init_HS (uint8_t lun) { //初始化SD卡设备 if(BSP_SD_Init() != USBD_OK){ return -1; } return (USBD_OK); } === 4、获取存储容量 === int8_t STORAGE_GetCapacity_HS (uint8_t lun, uint32_t *block_num, uint16_t *block_size) { BSP_SD_GetCardInfo(&SDCardInfo); //获取有关特定SD卡的SD信息 *block_num = SDCardInfo.BlockNbr * SDCardInfo.BlockSize / 512;//块数量 *block_size = STORAGE_BLK_SIZ;//块大小 return (USBD_OK); } === 5、读取STORAGE === int8_t STORAGE_Read_HS (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { uint32_t timeout = 10000; /* 在轮询模式下,从SD卡中的指定地址读取数据块 */ if(BSP_SD_ReadBlocks((uint32_t*)buf, blk_addr, blk_len, timeout) == USBD_OK){ /* 获取当前SD卡数据状态 */ while(BSP_SD_GetCardState()!= MSD_OK) { if (timeout-- == 0) { return -1; } } } return (USBD_OK); 6、写入STORAGE int8_t STORAGE_Write_HS (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { uint32_t timeout = 10000; /* 在轮询模式下,将块写入SD卡中的指定地址。 */ if(BSP_SD_WriteBlocks((uint32_t*)buf, blk_addr, blk_len, timeout) == USBD_OK){ /* 获取当前SD卡数据状态 */ while(BSP_SD_GetCardState()!= MSD_OK) { if (timeout-- == 0) { return -1; } } } return (USBD_OK); } ==== 五、 实验步骤 ==== - 将SD卡插到SD卡槽中; - 把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连); - 将跳线帽跳至USB OTG; - 把iCore4(USB OTG)通过Micro USB线与计算机相连,为iCore4供电; - 打开Keil MDK 开发环境,并打开本实验工程; - 烧写程序到iCore4上,我的电脑中将出现一个磁盘; - 也可以进入Debug模式,单步运行或设置断点验证程序逻辑。 ==== 六、 实验现象 ==== * 如下图所示: {{ :icore4:icore4_arm_hal_19_4.png?direct&650 |}} {{ :icore4:icore4_arm_hal_19_5.png?direct&650 |}}