Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
MCU
STM32
上海航芯 | 从STM32F103到ACM32F403的U盘程序移植工程
发布于 2022-01-07 11:29:27 浏览:994
订阅该版
本项目是以SPI Flash(如W25Q128等)存储元件作为存储单元,MCU主控完成USB接口通信并根据SCSI协议实现U盘功能。其结构如下图所示: ![1.png](https://oss-club.rt-thread.org/uploads/20220107/087f40e580033c3a3b9881a27e45baff.png) **SPI Flash部分移植** SPI功能部分相对简单,ACM32F403的接口引脚和STM32F103的相同,可直接对接,按照ACM32F403的说明对SPI接口进行初始化,并对底层读写函数进行更改即可。 **USB部分移植** 1.STM32F103代码结构 在ST的芯片上,USB的数据是由两个中断,USB_LP_CAN1_RX0_IRQHandler和USB_HP_CAN1_TX_IRQHandler来进行,其中高优先级中断(USB_HP_CAN1_TX_IRQHandler)用于处理同步(Isochronous)模式传输或双缓冲块(Bulk)传输模式下的正确传输事件,而低优先级中断(USB_LP_CAN1_RX0_IRQHandler)用于处理其他传输时间。ST的USB数据处理如下图所示: ![2.png](https://oss-club.rt-thread.org/uploads/20220107/7a4b106f6707e337f4c49cf65128cdf3.png.webp) 由于USBFS协议的限制,一包数据中最多可携带64字节数据,因此,当存在大量数据需要进行传输(IN或OUT包)时,需要分批次进行传输。在ST的代码中,通过变量“Bot_State”来进行控制,以Read10指令为例,其读数据流程可如下图所示: ![3.png](https://oss-club.rt-thread.org/uploads/20220107/d720a760ff04ae2de14573c10fc04464.png.webp) 需要注意的是,Read10指令解析完成之后(即上图左侧流程图)则进入数据传输阶段,此阶段是通过多次进入USB高优先级中断中,调用Read_Memory();来实现的。Read_Memory();函数内每次传输64字节数据。 **ACM32F403代码移植要点** 本文基于上海航芯官方USB例程进行移植,移植后的程序结构如下图所示: ![4.png](https://oss-club.rt-thread.org/uploads/20220107/3f02a7aaa157350965cd90c880c32d99.png.webp) ACM32F403的USB是采用一个中断来进行数据处理。在官方例程中,USB的中断函数内判定接收数据类型,包括suspend,resume,reset,EP0_pack以及其他端点的接收数据。判定结束后,会调用USB_Monitor();函数来处理suspend,resume,reset以及EP0_pack数据。而其他端点数据会在usb_transfer_monitor();函数中进行解析,该函数由客户调用,一般在主函数的死循环中进行处理。在本文的移植中,主要需对USB的端点数据进行处理。 **A. EP0_Pack** EP0接收的setup数据会被存放在SETIP_0_3_DATA和SETIP_4_7_DATA寄存器中 ,数据结构如下所示: ```c dev_req.bmRequestType=USBCTRL->SETIP_0_3_DATA &0xff; dev_req.bRequest=(USBCTRL->SETIP_0_3_DATA>>8)&0xff; dev_req.wValue=(USBCTRL->SETIP_0_3_DATA>>16)&0xffff; dev_req.wIndex = USBCTRL->SETIP_4_7_DATA&0xffff; dev_req.wLength=(USBCTRL->SETIP_4_7_DATA>>16)&0xffff; ``` 该部分解析,可由用户在函数void usb_control_transfer(void)中添加需要的处理函数。该函数由航芯官方例程里提供。在做U Disk程序移植时,需添加GetMaxLun和Storage_Reset处理函数,如下图所示: ![5.png](https://oss-club.rt-thread.org/uploads/20220107/c10accabab9e4f9cdef350ca0012e878.png) **B. EP1_Pack** 在本文所述的代码中,ACM32F403采用EP1完成数据的收发工作。主要是完成对SCSI协议的解析工作。移植过程中,需要文件mass_mal.c、memory.c、scsi_data.c、usb_scsi.c、usb_bot.c及其头文件。本段主要就上述文件中代码需要改动的地方进行说明,部分参数需要重新定义,读者可自行解决。下表列出了ST和Aisino的USB收发功能函数,该部分移植时需要修改的主要部分: ![6.png](https://oss-club.rt-thread.org/uploads/20220107/803e93cb44c18194c049a115ec4ddb83.png.webp) a. void Mass_Storage_In (void) 在ST的工程代码中该部分主要用于处理SCSI的读指令。由于全速USB一包数据最大支持64字节,因此,当需要传输的数据个数大于该数值时,则需要分包传输。在使用ACM32F403时,可直接传送需要的数据长度,内部会进行分包处理,因此,该函数可省略。 b. void Mass_Storage_Out (void) 该函数用于处理SCSI指令解析以及发送指令,需在usb_transfer_monitor()中调用,并将函数内部的接收数据部分更改为: ```c Data_Len = HAL_FSUSB_Receive_Data(Bulk_Data_Buff, 64, out_ep_index, 1); ``` c.void Transfer_Data_Request(uint8_t* Data_Pointer, uint16_t Data_Len) 将USB发送函数更改为ACM32F403对应的发送函数。在ST的工程中,该函数用于传输完数据后,进入BOT_DATA_IN_LAST状态,并在下一次的Mass_Storage_In()函数调用时,回复CSW指令。而本文的移植代码中,省略了Mass_Storage_In()函数,因此,可在该函数的尾部增加CSW发送指令: ```c Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); d.void Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission) ``` 将USB发送函数更改为ACM32F403对应的发送函数。 e.void Bot_Abort(uint8_t Direction) 该函数主要对收发端点的STALL状态进行处理,在ACM32F403的收发库函数中,对端点的STALL已做出相应控制,因此,该函数可省略。 f.`void Read_Memory(uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length)` Read_Memory函数用于收到PC端的IN包请求后将存储器中的数据读取并发送至PC端。而ACM32F403的USB发送库函数中,自行进行分包操作(一包最大数据为64字节),因此在数据缓冲区容量允许条件下,可直接发送完毕,该函数修改如下: ```c { uint32_t Offset, Length; Offset = Memory_Offset * Mass_Block_Size[lun]; Length = Transfer_Length * Mass_Block_Size[lun]; CSW.dDataResidue = CBW.dDataLength; while(Transfer_Length --) { MAL_Read(lun , Offset , Data_Buffer, Mass_Block_Size[lun]); Length = min(Mass_Block_Size[lun], CSW.dDataResidue); Offset += Mass_Block_Size[lun]; HAL_FSUSB_Send_Data((uint8_t *)(Data_Buffer), Length, in_ep_index); CSW.dDataResidue -= Length; } Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); } ``` g.`void Write_Memory (uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length)` 写数据指令完成后,将Bot_State 值更改为 BOT_IDLE。ST的工程代码中,变量“Bot_State”收发状态机的状态值,其值如下表所示: ![7.png](https://oss-club.rt-thread.org/uploads/20220107/e3c120147308fd0abdd2c3ea3b885551.png.webp) 而基于ACM32F403的U Disk工程,IN包可由函数HAL_FSUSB_Send_Data()在其内部进行分包处理,不需要额外逻辑,因此,移植后Bot_State仅需要在BOT_IDLE、BOT_DATA_OUT、BOT_ERROR之间转换,其他对Bot_State的控制可省略。
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
上海航芯
这家伙很懒,什么也没写!
文章
7
回答
0
被采纳
0
关注TA
发私信
相关文章
1
裸机工程移植 RT-Thread
2
Keil MDK 移植 RT-Thread Nano
3
移植 Nano,rt_thread_mdelay()延迟时间不对
4
裸机工程移植 RT-Thread内核
5
关于利用0x68000000作为扩展sram?
6
STM32F413 SD 卡写入速度提升方法
7
STM32 RTC 闹钟
8
http_ota 提示no memory
9
studio中怎么把PB3 和PA15引脚设置为普通IO口使用?
10
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
4
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部