muyichuan2012 发表于 2024-8-15 16:52

AT32 WorkBench常用功能13—USB Device MSC

本帖最后由 muyichuan2012 于 2024-8-15 17:25 编辑

AT32WorkBench常用功能 13—USB Device MSC
AT32 WorkBench最新版下载地址:https://www.arterytek.com/file/download/1710

USB MSC工程建立
本文主要介绍如何基于AT32 WorkBench配置USB MSC
硬件环境
lAT-START-F405
lUSB线缆

软件环境
lAT32 Workbench
lMDK5

配置步骤:
1.    打开AT32 WorkBench新建AT32F405RCT7工程
2.    在外设中打开USB_OTGHS1并选择设备,视情况选择是否勾选相关信号,本案例不勾选
3.    可以看到时钟配置菜单栏打了红叉,这是因为缺少12M外部晶振为OTGHS PHY提供时钟,所以需要在外设CRM中打开高速外部晶振。
4.    在中间件USB_DEVICE中选择OTGHS1设备类为MSC,HS设备描述符和端点FIFO可根据需要修改,本案例使用默认数值。
5.    点击生成代码,然后生成MDK_V5工程即可完成MSC基础工程的建立
6.    使用MDK_V5打开项目,修改msc_diskio.c和msc_diskio.h文件相关内容6.1在msc_diskio.c文件开头添加如下变量
/*private variables ---------------------------------------------------------*//* adduser code begin private variables */uint32_t sector_size = 2048;uint32_t msc_flash_size;/* adduser code end private variables */
6.2修改msc_diskio.c文件的msc_disk_read(…)函数
usb_sts_typemsc_disk_read(uint8_t lun, uint64_t addr, uint8_t *read_buf, uint32_t len){/* add user code begin msc_disk_read 0 */
/* add user code end msc_disk_read 0 */
//   switch(lun)//{//    caseINTERNAL_FLASH_LUN://      break;//    caseSPI_FLASH_LUN://      break;//    caseSD_LUN://      break;//    default://      break;//}
/* add user code begin msc_disk_read 1 */uint32_t i = 0;uint32_tflash_addr = (uint32_t)addr + USB_FLASH_ADDR_OFFSET;switch(lun){    caseINTERNAL_FLASH_LUN:      for(i =0; i < len; i ++)      {         read_buf = *((uint8_t *)flash_addr);         flash_addr += 1;      }      break;    case SPI_FLASH_LUN:      break;    caseSD_LUN:      break;    default:      break;}/* add user code end msc_disk_read 1 */
return USB_OK;}
6.3修改msc_diskio.c文件的msc_disk_write(…)函数
usb_sts_typemsc_disk_write(uint8_t lun, uint64_t addr, uint8_t *buf, uint32_t len){/* add user code begin msc_disk_write 0 */
/* add user code end msc_disk_write 0 */
//   switch(lun)//{//    caseINTERNAL_FLASH_LUN://      break;//    caseSPI_FLASH_LUN://      break;//    caseSD_LUN://      break;//    default://       break;;//}
/* add user code begin msc_disk_write 1 */uint32_t flash_addr = (uint32_t)addr + USB_FLASH_ADDR_OFFSET;uint32_t i =0, tolen = len;uint32_terase_addr = flash_addr;switch(lun){    caseINTERNAL_FLASH_LUN:       flash_unlock();       while(tolen >= sector_size)      {         flash_sector_erase(erase_addr);      tolen-= sector_size;         erase_addr += sector_size;      }      for(i =0; i < len; i ++)      {         flash_byte_program(flash_addr+i, buf);      }       flash_lock();      break;    caseSPI_FLASH_LUN:      break;    caseSD_LUN:      break;    default:      break;;}/* add user code end msc_disk_write 1 */
return USB_OK;}
6.4修改msc_diskio.c文件的msc_disk_capacity (…)函数
usb_sts_typemsc_disk_capacity(uint8_t lun, uint32_t *blk_nbr, uint32_t *blk_size){/* add user code begin msc_disk_capacity 0*/
/* add user code end msc_disk_capacity 0 */
//   switch(lun)//{//    caseINTERNAL_FLASH_LUN://      break;//    caseSPI_FLASH_LUN://      break;//    caseSD_LUN://      break;//    default://      break;//}
/* add user code begin msc_disk_capacity 1*/uint32_tdevid = (*((uint32_t *)DEBUG_BASE) & 0x00007000) >> 12;   msc_flash_size = (*((uint32_t *)0x1FFFF7E0) << 10) -(USB_FLASH_ADDR_OFFSET - FLASH_BASE);   switch(devid){    case 2:       sector_size = SECTOR_SIZE_1K;      break;    case 3:       sector_size = SECTOR_SIZE_2K;      break;    case 4:      sector_size= SECTOR_SIZE_4K;      break;    default:       sector_size = SECTOR_SIZE_2K;      break;}switch(lun){    caseINTERNAL_FLASH_LUN:      *blk_nbr= msc_flash_size / sector_size;       *blk_size = sector_size;      break;    caseSPI_FLASH_LUN:      break;    caseSD_LUN:      break;    default:      break;}/* add user code end msc_disk_capacity 1 */
return USB_OK;}
6.5在msc_diskio.h文件增加如下宏定义,然后编译并下载到开发板
/*private define ------------------------------------------------------------*//* adduser code begin private define */#define USB_FLASH_ADDR_OFFSET            0x08005000#define SECTOR_SIZE_1K                   1024#define SECTOR_SIZE_2K                   2048#define SECTOR_SIZE_4K                   4096/* adduser code end private define */


7.    将开发板HS_Device口连接到PC并复位,可以观察到PC识别到U盘,查看设备管理器可以看到新增的MSC设备
注意:对于USB_OTGFS来说,步骤相似,但可以不开启12M高速外部时钟,且输入到OTGFS控制器的时钟必须是48MHz。若选择hick to usbfs则可以解锁外设AAC功能,可以在AT32 WorkBench时钟配置界面进行确认。


哪里需要我了 发表于 2025-3-25 13:56

大佬,第2.和第3.图片对不上文字说明,我使用的芯片是AT32F403A,按上面修改以后

read_buf = *((uint8_t *)flash_addr);

flash_byte_program(flash_addr+i, buf);

这两处会报错{:funk:}

buyaowangle 发表于 2025-3-25 18:49

哪里需要我了 发表于 2025-3-25 13:56
大佬,第2.和第3.图片对不上文字说明,我使用的芯片是AT32F403A,按上面修改以后

read_buf = *((uint8_t...

2.图贴错了,后面会改,贴下报错信息看看

哪里需要我了 发表于 2025-3-26 09:52

Build started: Project: AT32F403AVGT7_MSC
*** Using Compiler 'V5.06 update 7 (build 960)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'AT32F403AVGT7_MSC'
compiling msc_diskio.c...
../src/msc_diskio.c(145): error:#513: a value of type "uint8_t" cannot be assigned to an entity of type "uint8_t *"
         read_buf = *((uint8_t *)flash_addr);
../src/msc_diskio.c(112): warning:#550-D: parameter "read_buf"was set but never used
usb_sts_type msc_disk_read(uint8_t lun, uint64_t addr, uint8_t *read_buf, uint32_t len)
../src/msc_diskio.c(228): error:#167: argument of type "uint8_t *" is incompatible with parameter of type "uint8_t"
         flash_byte_program(flash_addr+i, buf);
../src/msc_diskio.c: 1 warning, 2 errors
compiling msc_bot_scsi.c...
".\objects\AT32F403AVGT7_MSC.axf" - 2 Error(s), 1 Warning(s).
Target not created.

哪里需要我了 发表于 2025-3-26 09:53

是我keil哪里的设置问题么?

buyaowangle 发表于 2025-3-26 10:22

哪里需要我了 发表于 2025-3-26 09:53
是我keil哪里的设置问题么?

read_buf = *((uint8_t *)flash_addr);
flash_byte_program(flash_addr+i, buf);
这两句按照上面文档修改应该就可以了,指针和指针指向地址的值是两个东西。

buyaowangle 发表于 2025-3-26 10:26

buyaowangle 发表于 2025-3-26 10:22
read_buf = *((uint8_t *)flash_addr);
flash_byte_program(flash_addr+i, buf);
这两句按照上面文档修改 ...

按照这个修改:
read_buf = *((uint8_t *)flash_addr);
flash_byte_program(flash_addr+i, buf);

buyaowangle 发表于 2025-3-26 10:30

buyaowangle 发表于 2025-3-26 11:35

!(data/attachment/forum/202503/26/113526e0ycee3il1wck13x.png "image.png")不好意思,前面发的内容被屏蔽了,按照图片修改

哪里需要我了 发表于 2025-3-26 11:58

read_buf = *((uint8_t *)flash_addr);这这行具体是什么意思,取FLASH存储的一个字节赋值到传入的read_buff数组吗?
这里把FLASH地址的一个字节数据直接赋值给uint8_t类型的指针read_buf,我的理解对吗?

是不是说应该这样?
*(read_buf + i) = *((uint8_t *)flash_addr);
或者read_buf= *((uint8_t *)flash_addr);

flash_byte_program第二个参数类型是uint8_t,这里是不是也应该改一下
flash_byte_program(flash_addr+i, buf);
还是我理解错了

哪里需要我了 发表于 2025-3-26 12:15

本帖最后由 哪里需要我了 于 2025-3-26 12:19 编辑

OKOK,刚刚没刷新网页,没看到回复

哪里需要我了 发表于 2025-3-26 12:37

本帖最后由 哪里需要我了 于 2025-3-26 12:57 编辑

但是我这修改了以后还是有问题,可以显示U盘,但是打不开,不能读写。想请教一下是哪里配置错了会这样,按下面图片配置。我直接用403a最新库2.2.0的msc例程也是这样,使用an0012例程却可以显示U盘,大小好像不准确,是100M,会不会是硬件上的问题?

buyaowangle 发表于 2025-3-26 13:13

哪里需要我了 发表于 2025-3-26 12:37
但是我这修改了以后还是有问题,可以显示U盘,但是打不开,不能读写。想请教一下是哪里配置错了会 ...

用开发板试一下,下载时选择整片擦除,BSP都是经过测试的,一般不会有问题。

buyaowangle 发表于 2025-3-26 13:19

buyaowangle 发表于 2025-3-26 13:13
用开发板试一下,下载时选择整片擦除,BSP都是经过测试的,一般不会有问题。 ...

首次使用记得格式化一下

哪里需要我了 发表于 2025-3-26 14:12

本帖最后由 哪里需要我了 于 2025-3-26 14:18 编辑

buyaowangle 发表于 2025-3-26 13:19
首次使用记得格式化一下
谢谢!是这个原因。现在可以了,格式化时还要点一下“还原设备的默认值”,重新整篇擦除烧录后,也需要这样格式化,感觉操作上有点奇怪。我现在想试一下MSC IAP升级,为什么用an0012的例程不需要手动格式化,下载就可以用直接弹出设备,但是显示99.9MB。

哪里需要我了 发表于 2025-3-26 14:25

本帖最后由 哪里需要我了 于 2025-3-26 18:07 编辑

哪里需要我了 发表于 2025-3-26 14:12
谢谢!是这个原因。现在可以了,格式化时还要点一下“还原设备的默认值”,重新整篇擦除烧录后,也需要这 ...
   

buyaowangle 发表于 2025-3-31 09:58

哪里需要我了 发表于 2025-3-26 14:12
谢谢!是这个原因。现在可以了,格式化时还要点一下“还原设备的默认值”,重新整篇擦除烧录后,也需要这 ...

AN0012是代码里已经把FAT16文件系统建好了,所以不需要格式化;你现在建的工程,Flash U盘地址里面是空的,没有文件系统,计算机识别不出来,所以需要格式化,让计算机帮建个文件系统;那个99.9MB完全取决于代码设定,是MCU回报给计算机的不是真实的大小,可视情况修改msc_disk_capacity这个函数。
页: [1]
查看完整版本: AT32 WorkBench常用功能13—USB Device MSC