打印
[AT32 WorkBench]

AT32 WorkBench常用功能13—USB Device MSC

[复制链接]
1387|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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
硬件环境
l  AT-START-F405
l  USB线缆

软件环境
l  AT32 Workbench
l  MDK5

配置步骤:
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 ---------------------------------------------------------*/
  
/* add  user code begin private variables */
  
uint32_t sector_size = 2048;
  
uint32_t msc_flash_size;
  
/* add  user code end private variables */
  
6.2  修改msc_diskio.c文件的msc_disk_read(…)函数
  
usb_sts_type  msc_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)
  
//  {
  
//    case  INTERNAL_FLASH_LUN:
  
//      break;
  
//    case  SPI_FLASH_LUN:
  
//      break;
  
//    case  SD_LUN:
  
//      break;
  
//    default:
  
//      break;
  
//  }
  
  
  /* add user code begin msc_disk_read 1 */
  
uint32_t i = 0;
  
  uint32_t  flash_addr = (uint32_t)addr + USB_FLASH_ADDR_OFFSET;
  
  switch(lun)
  
  {
  
    case  INTERNAL_FLASH_LUN:
  
      for(i =  0; i < len; i ++)
  
      {
  
         read_buf = *((uint8_t *)flash_addr);
  
         flash_addr += 1;
  
      }
  
      break;
  
    case SPI_FLASH_LUN:
  
      break;
  
    case  SD_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_type  msc_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)
  
//  {
  
//    case  INTERNAL_FLASH_LUN:
  
//      break;
  
//    case  SPI_FLASH_LUN:
  
//      break;
  
//    case  SD_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_t  erase_addr = flash_addr;
  
  switch(lun)
  
  {
  
    case  INTERNAL_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;
  
    case  SPI_FLASH_LUN:
  
      break;
  
    case  SD_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_type  msc_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)
  
//  {
  
//    case  INTERNAL_FLASH_LUN:
  
//      break;
  
//    case  SPI_FLASH_LUN:
  
//      break;
  
//    case  SD_LUN:
  
//      break;
  
//    default:
  
//      break;
  
//  }
  
  
  /* add user code begin msc_disk_capacity 1  */
  
  uint32_t  devid = (*((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)
  
  {
  
    case  INTERNAL_FLASH_LUN:
  
      *blk_nbr  = msc_flash_size / sector_size;
  
       *blk_size = sector_size;
  
      break;
  
    case  SPI_FLASH_LUN:
  
      break;
  
    case  SD_LUN:
  
      break;
  
    default:
  
      break;
  
  }
  
  /* add user code end msc_disk_capacity 1 */
  
  
  return USB_OK;
  
}
  
6.5  在msc_diskio.h文件增加如下宏定义,然后编译并下载到开发板
  
/*  private define ------------------------------------------------------------*/
  
/* add  user 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
  
/* add  user 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);

这两处会报错

使用特权

评论回复
板凳
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.

使用特权

评论回复
5
哪里需要我了| | 2025-3-26 09:53 | 只看该作者
是我keil哪里的设置问题么?

使用特权

评论回复
6
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);
这两句按照上面文档修改应该就可以了,指针和指针指向地址的值是两个东西。

使用特权

评论回复
7
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);

使用特权

评论回复
8
buyaowangle| | 2025-3-26 10:30 | 只看该作者

使用特权

评论回复
9
buyaowangle| | 2025-3-26 11:35 | 只看该作者

image.png不好意思,前面发的内容被屏蔽了,按照图片修改

使用特权

评论回复
10
哪里需要我了| | 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[i]= *((uint8_t *)flash_addr);

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

使用特权

评论回复
11
哪里需要我了| | 2025-3-26 12:15 | 只看该作者
本帖最后由 哪里需要我了 于 2025-3-26 12:19 编辑

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

使用特权

评论回复
12
哪里需要我了| | 2025-3-26 12:37 | 只看该作者
本帖最后由 哪里需要我了 于 2025-3-26 12:57 编辑

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

1.png (30.52 KB )

1.png

2.png (70.22 KB )

2.png

3.png (151.49 KB )

3.png

4.png (113.42 KB )

4.png

5.png (156.27 KB )

5.png

6.png (152.39 KB )

6.png

7.png (18.2 KB )

7.png

8.png (74.47 KB )

8.png

9.png (296.3 KB )

9.png

使用特权

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

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

使用特权

评论回复
14
buyaowangle| | 2025-3-26 13:19 | 只看该作者
buyaowangle 发表于 2025-3-26 13:13
用开发板试一下,下载时选择整片擦除,BSP都是经过测试的,一般不会有问题。 ...

首次使用记得格式化一下

使用特权

评论回复
15
哪里需要我了| | 2025-3-26 14:12 | 只看该作者
本帖最后由 哪里需要我了 于 2025-3-26 14:18 编辑
buyaowangle 发表于 2025-3-26 13:19
首次使用记得格式化一下

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

10.png (29.75 KB )

10.png

使用特权

评论回复
16
哪里需要我了| | 2025-3-26 14:25 | 只看该作者
本帖最后由 哪里需要我了 于 2025-3-26 18:07 编辑
哪里需要我了 发表于 2025-3-26 14:12
谢谢!是这个原因。现在可以了,格式化时还要点一下“还原设备的默认值”,重新整篇擦除烧录后,也需要这 ...

   

使用特权

评论回复
17
buyaowangle| | 2025-3-31 09:58 | 只看该作者
哪里需要我了 发表于 2025-3-26 14:12
谢谢!是这个原因。现在可以了,格式化时还要点一下“还原设备的默认值”,重新整篇擦除烧录后,也需要这 ...

AN0012是代码里已经把FAT16文件系统建好了,所以不需要格式化;你现在建的工程,Flash U盘地址里面是空的,没有文件系统,计算机识别不出来,所以需要格式化,让计算机帮建个文件系统;那个99.9MB完全取决于代码设定,是MCU回报给计算机的不是真实的大小,可视情况修改msc_disk_capacity这个函数。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

212

主题

1971

帖子

32

粉丝