Milk-v duo Nandflash USB下载实践

milk-v duo 系列开发板采用的 CV18xx 系列 USB 下载,通过一系列模式后,官方有提供相关文档,但是都比较散。在群友指点下,通过一系列摸索和实践,终于可以通过 USB 下载 milk-v duo了。

相关文档:

  1. USB 驱动安装:https://doc.sophgo.com/cvitek-develop-docs/master/docs_latest_release/CV180x_CV181x/zh/01.software/BSP/Production_Burning_User_Guide/build/html/3_Installing_The_USB_Driver.html

  2. USB 烧录:https://doc.sophgo.com/cvitek-develop-docs/master/docs_latest_release/CV180x_CV181x/zh/01.software/BSP/Cvitek_Bare_and_Non-Bare_Chip_Burning_Upgrade_Operation_Guide/build/html/3_Use_USB_to_Burn.html

1、进入下载模式

在 milk-v duo datasheet https://github.com/milkv-duo/duo-files/blob/main/duo/hardware/duo-datasheet-v1.2.pdf 中有介绍进入 USB 下载模式的方法:

The MILKV-DUO can operate in USB Device mode for firmware burning and downloading when USB_VBUS_DET (PIN45/ADC2) is detected through a resistor-divided
5V_USB_IN and powered high. However, if the USB port is not being used for burning,
USB_VBUS_DET (PIN45/ADC2) can be directly connected to ground, and the MILKV-DUO
will operate in Host mode, enabling it to connect to external USB devices such as USB
HUBs or USB 2.0 devices.

By default, PIN45 on the MILKV-DUO mainboard is used as an input for ADC2, with a
maximum 3.3V level divided to 1.65V using a voltage divider consisting of two resistors.
If the user wants to use PIN45 as a USB burning detection pin, it is recommended to add
a button in the baseboard design. When the button is pressed, the system will power on,
and USB_VBUS_DET will detect a high level, causing the USB interface to enter Device
mode for firmware downloading. On the other hand, when the button is not pressed,
USB_VBUS_DET detects a low level, and the USB interface enters Host mode, allowing
external connections to USB HUBs or USB 2.0 devices.

可以看到拉高芯片的 PIN45 脚(USB_VBUS_DET),即可进入 USB 烧录模式。

查看 milk-v duo 的原理图 https://github.com/milkv-duo/duo-files/blob/main/duo/hardware/duo-schematic-v1.2.pdf

可以看到这个管脚通过分压电路之后,连接到了开发板的 32 脚。不过 ADC2 是 1.8V 电压,所以外接电压不能超过 3.6V,否则有可能会烧坏管脚。
usb_pin

所以我们将 开发板的 32 脚上拉到 3.3V 后,即可进入 USB 下载模式。

2、u-boot 代码修改

上面说到拉高 USB_VBUS_DET 管脚可以进入 USB 烧录模式。不过 milk-v duo 的 SDK 在 u-boot 中将 USB_VBUS_DET 管脚定义为 ADC5 了,所以需要将这部分代码做修改。

修改 build/boards/cv180x/cv1800b_milkv_duo_sd/u-boot/cvi_board_init.c 文件,将以下语句注释。

	// PINMUX_CONFIG(USB_VBUS_DET, XGPIOB_6);   // ADC2

如使用的是 spi-norflash、spi-nandflash 可修改对应目录下的 cvi_board_init.c 文件。

修改完成后重新编译。

3、USB 驱动安装

  1. 连接 milk-v duo 开发板上的 USB 口

  2. 正常上电后进入 u-boot,在 u-boot 命令行中输入:

cv180x_c906# cvi_utask vid 0x3346 pid 0x1001

注意,milk-v duo 这里用的是 0x1001,否则后面连接下载软件会失败。其他板子如 duo-256 和duo-s 待验证。

如连接的是 windows 操作系统,此时会弹出 USB Com Port 设备。

  1. 下载 zadig 官网 https://zadig.akeo.ie 下载 zadig 最新版软件 https://github.com/pbatard/libwdi/releases/download/v1.5.0/zadig-2.8.exe

下载完成后运行 zadig,选择 list all devices。

然后选择 USB Com Port 设备,并将 Driver 切换至 libusb-win32

点击 Reinstall Driver 开始安装。

4、USB 下载

当前 USB 下载测试在 windows 下进行,Linux 操作系统下暂未测试。

  1. duo-buildroot-sdk 编译后的已经生成了用于 USB 下载的文件,位于 install 目录下,复制 install 下对应的 soc_cv1800b_milkv_duo_spinand 文件夹至 windows 下。

本人使用的是 nandflash。

  1. 安装 python3,并添加 python3 至环境变量。

  2. 安装 python 库

pip install pyusb pyserial
  1. 断开 milk-v duo 上的 usb 连接和电源,连接串口线至 PC。

  2. 切换到 soc_cv1800b_milkv_duo_spinand\tools\usb_dl 目录,输入

py cv181x_dl.py --libusb --image_dir C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinor
INFO: Using libusb
INFO: CV181X USB download start

fip_path: C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\fip.bin
CV181X USB download start
Connecting to ROM
Waiting for USB port:  |

其中 C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinor 为 fip.bin 所在目录。

此时下载软件会提示 Waiting for USB port

  1. 上拉 USB_VBUS_DET 即开发板 32 管脚,连接 USB,并上电,下载软件会自动开始下载。
INFO: Using libusb
INFO: CV181X USB download start

fip_path: C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\fip.bin
CV181X USB download start
Connecting to ROM
COM6ing for USB port:  /
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

done
Send cv_dl_magic.bin...
--- 0.0 Seconds ---
done
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send 4096B fip.bin...
--- 0.02 Seconds ---
set flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 4096
fip_tx_size 47616
--- 0.3 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 51712
fip_tx_size 4096
--- 0.01 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 55808
fip_tx_size 8192
--- 0.02 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 64000
fip_tx_size 14336
--- 0.03 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 78336
fip_tx_size 110592
--- 0.29 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 188928
fip_tx_size 512
--- 0.0 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
COM6ing for USB port:  |
USB VID:PID=3346:1000 SER=123456789ABC LOCATION=1-3.1

Send cv_dl_magic.bin...
--- 0.0 Seconds ---
fip_tx_offset 188928
fip_tx_size 263680
--- 1.21 Seconds ---
set MGN1 flag
break
Connecting to ROM 2nd stage...
Query pyserial device timeout!
Connected to u-boot cvi_utask by pyserial
INFO: Using libusb
LIBUSB on Windows
INFO: SEND FILE C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\fip.bin

C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\fip.bin is 452608 bytes
Send to address 0x82473000
--- 2.22 Seconds ---
LIBUSB on Windows
INFO: SEND FILE C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\boot.spinand

--- size 64 0.00893 Seconds ---
--- size 3372100 0.39134 Seconds ---
INFO: CVI_USB_PROGRAM
INFO: SEND FILE C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\rootfs.spinand

--- size 64 0.00248 Seconds ---
--- size 16777280 1.49693 Seconds ---
INFO: CVI_USB_PROGRAM
--- size 2359360 0.06944 Seconds ---
INFO: CVI_USB_PROGRAM
INFO: SEND FILE C:\Users\cys\Desktop\soc_cv1800b_milkv_duo_spinand\system.spinand

--- size 64 0.00248 Seconds ---
--- size 16777280 1.99293 Seconds ---
INFO: CVI_USB_PROGRAM
--- size 4718656 0.14087 Seconds ---
INFO: CVI_USB_PROGRAM
LIBUSB on Windows
INFO: reboot device done
INFO: USB download complete
INFO: CV181X USB download end

串口连接的日志窗口会显示 u-boot 相关日志:

Hit any key to stop autoboot:  0 
## Resetting to default environment
Start USB downloading...

start usb task!
NOTICE:  cvi_usb_hw_init
INFO:    waiting for connection ...
INFO:    detect vbus ...
INFO:    bulkBufAlloc: 0000000081badd80
INFO:    cmdBufAlloc: 0000000081badfc0
INFO:    ep0BuffAlloc: 0000000081beae80
INFO:    setup_buf: 0000000081bae200
INFO:    handler: 0000000081bae280
INFO:    cb0_buf: 0000000081bae690
INFO:    cb1_buf: 0000000081bae720
INFO:    cb2_buf: 0000000081bae7b0
INFO:    rsp_buf: 0000000081bae840
INFO:    acm_buf: 0000000081bae890
NOTICE:  Overwrite fip_src to FIP_SRC_USB
NOTICE:  fip_src 6
NOTICE:  bind()
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  Application: disconnect
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  USB enumeration done
NOTICE:  connection speed: 3
NOTICE:  CVI_USB_PRG_CMD
NOTICE:  run command: setenv filesize 0x6e800
INFO:    CVI_USB_BREAK
NOTICE:  Leave transfer loop
NOTICE:  Application: disconnect
NOTICE:  unbind()
NOTICE:  USB stop
addr 0000000082473000
fip.bin
do_cvi_update_spinand with version 0x1823a001
Scan and erase first 20 blocks
Generated checknum=0xebca6b98
fip size=452608 bytes
write 1 copy of fip
write 2 copy of fip
Saving Environment to NAND... Erasing redundant NAND...
Erasing at 0x8a0000 -- 100% complete.
Writing to redundant NAND... OK
OK

start usb task!
NOTICE:  cvi_usb_hw_init
INFO:    waiting for connection ...
INFO:    detect vbus ...
INFO:    bulkBufAlloc: 0000000081baee00
INFO:    cmdBufAlloc: 0000000081baf040
INFO:    ep0BuffAlloc: 0000000081beae80
INFO:    setup_buf: 0000000081baf280
INFO:    handler: 0000000081baf300
INFO:    cb0_buf: 0000000081baf710
INFO:    cb1_buf: 0000000081baf7a0
INFO:    cb2_buf: 0000000081baf830
INFO:    rsp_buf: 0000000081baf8c0
INFO:    acm_buf: 0000000081baf910
NOTICE:  Overwrite fip_src to FIP_SRC_USB
NOTICE:  fip_src 6
NOTICE:  bind()
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  Application: disconnect
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  USB enumeration done
NOTICE:  connection speed: 3

NAND erase.part: device 0 offset 0x280000, size 0x600000
Erasing at 0x860000 -- 100% complete.
OK

NAND write: device 0 offset 0x280000, size 0x337404
 3372036 bytes written: OK
nand nand speed 3.494 MB/s
NOTICE:  CVI_USB_PROGRAM done

NAND erase.part: device 0 offset 0x8c0000, size 0x2800000
Erasing at 0x30a0000 -- 100% complete.
OK

NAND write: device 0 offset 0x8c0000, size 0x1000000
 16777216 bytes written: OK
nand nand speed 3.536 MB/s
NOTICE:  CVI_USB_PROGRAM done

NAND write: device 0 offset 0x18c0000, size 0x240000
 2359296 bytes written: OK
nand nand speed 3.553 MB/s
NOTICE:  CVI_USB_PROGRAM done

NAND erase.part: device 0 offset 0x30c0000, size 0x4f40000
Skipping bad block at  0x07f80000                                          
Skipping bad block at  0x07fa0000                                          
Skipping bad block at  0x07fc0000                                          
Skipping bad block at  0x07fe0000                                          

OK

NAND write: device 0 offset 0x30c0000, size 0x1000000
 16777216 bytes written: OK
nand nand speed 3.671 MB/s
NOTICE:  CVI_USB_PROGRAM done

NAND write: device 0 offset 0x40c0000, size 0x480000
 4718592 bytes written: OK
nand nand speed 3.618 MB/s
NOTICE:  CVI_USB_PROGRAM done
INFO:    CVI_USB_BREAK
NOTICE:  Leave transfer loop
NOTICE:  Application: disconnect
NOTICE:  unbind()
NOTICE:  USB stop

start usb task!
NOTICE:  cvi_usb_hw_init
INFO:    waiting for connection ...
INFO:    detect vbus ...
INFO:    bulkBufAlloc: 0000000081bb0180
INFO:    cmdBufAlloc: 0000000081bb03c0
INFO:    ep0BuffAlloc: 0000000081beae80
INFO:    setup_buf: 0000000081bb0600
INFO:    handler: 0000000081bb0680
INFO:    cb0_buf: 0000000081bb0a90
INFO:    cb1_buf: 0000000081bb0b20
INFO:    cb2_buf: 0000000081bb0bb0
INFO:    rsp_buf: 0000000081bb0c40
INFO:    acm_buf: 0000000081bb0c90
NOTICE:  Overwrite fip_src to FIP_SRC_USB
NOTICE:  fip_src 6
NOTICE:  bind()
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  Application: disconnect
NOTICE:  Patch VID 3346
NOTICE:  Patch VID 3346
NOTICE:  USB enumeration done
NOTICE:  connection speed: 3
NOTICE:  CVI_USB_REBOOT

至此 USB 下载完成。

再此要特别感谢在 milk-v 微信群中给于指导的网友 xiaomin、hui,以及milk-v工程师 Carbon。

4 Likes

Thanks for your share. The usb dl need the SD/TF card to boot to u-boot? When I boot the duo without SD/TF Card, the board will be loop in USBI → reset. Like that:
WD.C.SCS/0/0.WD.URPL.USBI.USBW/1000.USBL.BS/EMMC.PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
PS. E:load param1 (-78)
E:Boot failed (8).
E:ra=0x440a264
E:RESET:panic:-1