Nuoeriris · 2020年06月22日

MM32 USB功能学习笔记 —— 模拟U盘

在上一节我们介绍了MM32 MCU的CDC功能,CDC简单而且常用。

本节我们来讲解如何在MM32 MCU实现U盘功能。

USB大容量存储设备(英语:USB mass storage device class,也称为USB MSC或UMS)是一个协议,允许一个USB接口的设备与主计算设备相连接,以便在两者之间传输文件。对于主计算设备来说,USB设备看起来就像一个移动硬盘,允许拖放型文件传送,用 USB 线连接 PC 机与开发板,在电脑上就可以像操作普通 U 盘那样来操作开发板中的 MicroSD 卡或者SPI FLASH。它实际上是由USB实施者论坛所通过许多通讯协议的汇总,这一标准提供了许多设备的界面,包括移动硬盘、闪存盘、移动光学驱动器、读卡器、数码相机、数码音乐播放器、Pad以及手机等等。

本次我们采用MM32L373 miniboard作为测试开发板。为了方便大家使用MM32 MCU的MSC功能,我们已经封装好全部代码,用户不需要自己配置以上的那些描述符等参数,只需要知道如何处理MSC的数据接收和发送即可。

软件资源如下:

对于MM32 MCU的MSC功能来说,在使用MSC功能之前先调用USB初始化函数来初始化USB协议栈。

int main(void)
{
// USB Device Initialization and connect
usbd_init();
usbd_connect(__TRUE);
while (!usbd_configured())   // Wait for USB Device to configure
{
}
while (1)
{
……
if (flags & FLAGS_MAIN_90MS)
{
vfs_mngr_periodic(90); // FLAGS_MAIN_90MS
}
……
}
}

在MM32 MCU 的MSC功能里面,增加了一个虚拟FAT,用户不需要了解,只需要了解MSC数据收发处理函数,USB数据处理函数如下:

//MSC初始化函数
 
void usbd_msc_init(void)
{
sync_init();
build_filesystem();
vfs_state = VFS_MNGR_STATE_DISCONNECTED;
vfs_state_next = VFS_MNGR_STATE_DISCONNECTED;
time_usb_idle = 0;
USBD_MSC_MediaReady = 0;
}
//MSC读函数
void usbd_msc_read_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors)
{
sync_assert_usb_thread();
 
// dont proceed if we're not ready
if (!USBD_MSC_MediaReady) {
return;
}
vfs_read(sector, buf, num_of_sectors);
}
//虚拟文件读函数
void vfs_read(uint32_t requested_sector, uint8_t *buf, uint32_t num_sectors)
{
uint8_t i = 0;
uint32_t current_sector;
// Zero out the buffer
memset(buf, 0, num_sectors * VFS_SECTOR_SIZE);
current_sector = 0;
 
for (i = 0; i < ELEMENTS_IN_ARRAY(virtual_media); i++) {
uint32_t vm_sectors = virtual_media[i].length / VFS_SECTOR_SIZE;
uint32_t vm_start = current_sector;
uint32_t vm_end = current_sector + vm_sectors;
 
// Data can be used in this sector
if ((requested_sector >= vm_start) && (requested_sector < vm_end)) {
uint32_t sector_offset;
uint32_t sectors_to_write = vm_end - requested_sector;
sectors_to_write = MIN(sectors_to_write, num_sectors);
sector_offset = requested_sector - current_sector;
virtual_media[i].read_cb(sector_offset, buf, sectors_to_write);
// Update requested sector
requested_sector += sectors_to_write;
num_sectors -= sectors_to_write;
}
 
// If there is no more data to be read then break
if (num_sectors == 0) {
break;
}
 
// Move to the next virtual media entry
current_sector += vm_sectors;
}
}
//MSC写函数
void usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors)
{
sync_assert_usb_thread();
 
if (!USBD_MSC_MediaReady) {
return;
}
 
// Restart the disconnect counter on every packet
// so the device does not detach in the middle of a
// transfer.
time_usb_idle = 0;
 
if (TRASNFER_FINISHED == file_transfer_state.transfer_state) {
return;
}
 
// indicate msc activity
vfs_write(sector, buf, num_of_sectors);
if (TRASNFER_FINISHED == file_transfer_state.transfer_state) {
return;
}
file_data_handler(sector, buf, num_of_sectors);
}
//虚拟文件写函数
void vfs_write(uint32_t requested_sector, const uint8_t *buf, uint32_t num_sectors)
{
uint8_t i = 0;
uint32_t current_sector;
current_sector = 0;
 
for (i = 0; i < virtual_media_idx; i++) {
uint32_t vm_sectors = virtual_media[i].length / VFS_SECTOR_SIZE;
uint32_t vm_start = current_sector;
uint32_t vm_end = current_sector + vm_sectors;
 
// Data can be used in this sector
if ((requested_sector >= vm_start) && (requested_sector < vm_end)) {
uint32_t sector_offset;
uint32_t sectors_to_read = vm_end - requested_sector;
sectors_to_read = MIN(sectors_to_read, num_sectors);
sector_offset = requested_sector - current_sector;
virtual_media[i].write_cb(sector_offset, buf, sectors_to_read);
// Update requested sector
requested_sector += sectors_to_read;
num_sectors -= sectors_to_read;
}
 
// If there is no more data to be read then break
if (num_sectors == 0) {
break;
}
 
// Move to the next virtual media entry
current_sector += vm_sectors;
}
}

 如上,我们就完成MM32 MCU的MSC功能,将程序下载到板子中,USB插上电脑,电脑上会枚举出U盘,如下显示:
1.png
图1 MM32 MCU模拟U盘属性

U盘容量可以用户自定义,在本次程序中定义U盘64M,实际容量小于MCU flash容量,用户可以选择外扩SDRAM、MicroSD 卡或者SPI FLASH等其他存储单元,可以实现大容量数据存储功能,需要用户根据实际存储外设将USB通信和存储单元进行关联操作。
2.png
图2 电脑U盘盘符

打开 U 盘,可以进行新建、复制、粘贴、格式化等操作。与操作我们的普通 U 盘没什么区别,以上就是MM32 MCU USB的MSC功能。

推荐阅读
关注数
6152
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息