Milk-V Duo

Milk-V Duo

  • SoC: CVITEK CV1800B
  • CPU: RISC-V C906 @ 1 GHz + C906 @ 700 MHz
  • MCU: 8051, 8 KB SRAM
  • memory: 64 MB SIP DRAM
  • storage: 1 x microSD connector
  • usb: 1 x USB-C, power and data
  • CSI: 1 x MIPI CSI 2-lane, 1 x 16 FPC connector
  • Ethernet: 100 Mbps with phy (via optional add-on board)
  • GPIO: up to 26
  • power: 5V, 1A
  • OS support: Linux, RTOS
  • Integrated CVITEK TPU for smart detection

back to machines page.

Links

Milk-V Duo, docs, Milk-V Duo tutorial, community forum, CV1800B, Baremetal, 8051 core inside CV1800B, Github milkv-duo duo-buildroot-sdk, CV180-Duo, Rust on Milk-V Duo Linux side: I Got a Milk-V Duo, milkv-duo-rust, milkv-duo-rust-helloworld, bare metal side milkv-duo-hal, Milk-V Duo S Little Core Rust Firmware,

Sophgo forum: Duo English forum, Use Opensbi to boot your own operating system, sophgo-hardware, sophgo-doc, sophgo-arduino, Ubuntu on the Milk-V Duo, MILK-V Linux and Arduino Example of using inter-core mailbox on the MILK-V DUO,

local links

c2, ti21, t121-w10,

History

2024-08-29: ti21-w10 - after doing pip install pyserial from powershell, uploading code from arduino IDE (2.3.2) works in w10 also. The compiler generates these errors, but the compiled program works

C:/Users/torfinn.ingolfsen/AppData/Local/Arduino15/packages/sophgo/tools/xpack-riscv-none-elf-gcc/13.2.0-2/bin/../lib/gcc/riscv-none-elf/13.2.0/../../../../riscv-none-elf/bin/ld.exe: C:/Users/torfinn.ingolfsen/AppData/Local/Arduino15/packages/sophgo/tools/xpack-riscv-none-elf-gcc/13.2.0-2/bin/../lib/gcc/riscv-none-elf/13.2.0/../../../../riscv-none-elf/lib/rv64imfd_zicsr/lp64d\libc_nano.a(libc_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): warning: _getpid is not implemented and will always fail
C:/Users/torfinn.ingolfsen/AppData/Local/Arduino15/packages/sophgo/tools/xpack-riscv-none-elf-gcc/13.2.0-2/bin/../lib/gcc/riscv-none-elf/13.2.0/../../../../riscv-none-elf/bin/ld.exe: C:/Users/torfinn.ingolfsen/AppData/Local/Arduino15/packages/sophgo/tools/xpack-riscv-none-elf-gcc/13.2.0-2/bin/../lib/gcc/riscv-none-elf/13.2.0/../../../../riscv-none-elf/lib/rv64imfd_zicsr/lp64d\libc_nano.a(libc_a-signalr.o): in function `.L0 ':
signalr.c:(.text._kill_r+0x20): warning: _kill is not implemented and will always fail

2024-08-29: ti21-w10 - I had to install Microsoft UsbNcm Host Device driver manually to get the network interface working. After that, ssh'ing to 'root@192.168.42.1' works.

2024-08-27: c2 - from /var/log/messages

Aug 27 19:32:37 kg-core2 kernel: ugen1.9: <Cvitek NCM> at usbus1
Aug 27 19:32:37 kg-core2 kernel: ugen1.9: <Cvitek NCM> at usbus1 (disconnected)
Aug 27 19:32:37 kg-core2 kernel: ugen1.9: <Cvitek NCM> at usbus1
Aug 27 19:32:37 kg-core2 kernel: cdce0 on uhub3
Aug 27 19:32:37 kg-core2 kernel: cdce0: <CDC Network Control Model (NCM)> on usbus1
Aug 27 19:32:37 kg-core2 kernel: umodem0 on uhub3
Aug 27 19:32:37 kg-core2 kernel: ue0: <USB Ethernet> on cdce0
Aug 27 19:32:37 kg-core2 kernel: ue0: Ethernet address: d2:02:e9:da:4a:e2
Aug 27 19:32:37 kg-core2 kernel: umodem0: <CDC Abstract Control Model (ACM)> on usbus1
Aug 27 19:32:37 kg-core2 kernel: umodem0: data interface 3, has no CM over data, has no break

so, one network interface and one serial port. The serial port is

root@kg-core2:~ # sysctl dev.umodem.0.ttyname
dev.umodem.0.ttyname: U0

and

root@kg-core2:~ # ll /dev/cuaU0 /dev/ttyU0
crw-rw----  1 uucp  dialer  0x22b Aug 27 19:32 /dev/cuaU0
crw-------  1 root  wheel   0x228 Aug 27 19:32 /dev/ttyU0

get the network interface up

root@kg-core2:~ # ifconfig ue0
ue0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=80000<LINKSTATE>
    ether d2:02:e9:da:4a:e2
    media: Ethernet autoselect
    nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
root@kg-core2:~ # ifconfig ue0 up
root@kg-core2:~ # ifconfig ue0
ue0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=80000<LINKSTATE>
    ether d2:02:e9:da:4a:e2
    media: Ethernet autoselect
    status: active
    nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
root@kg-core2:~ # dhclient ue0
DHCPDISCOVER on ue0 to 255.255.255.255 port 67 interval 4
DHCPOFFER from 192.168.42.1
DHCPREQUEST on ue0 to 255.255.255.255 port 67
DHCPACK from 192.168.42.1
bound to 192.168.42.108 -- renewal in 1800 seconds.

try to ping it

tingo@kg-core2:~ $ ping 192.168.42.1
PING 192.168.42.1 (192.168.42.1): 56 data bytes
64 bytes from 192.168.42.1: icmp_seq=0 ttl=64 time=0.668 ms
64 bytes from 192.168.42.1: icmp_seq=1 ttl=64 time=0.707 ms
^C
--- 192.168.42.1 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.668/0.688/0.707/0.020 ms

and ssh into it

tingo@kg-core2:~ $ ssh root@192.168.42.1
root@192.168.42.1's password: 
[root@milkv-duo]~# 

yes, it works

2024-08-27: c2 - I connect a Milk-V Duo to my FreeBSD workstation. It shows up in usbconfig as

root@kg-core2:~ # usbconfig -d ugen1.9
ugen1.9: <Cvitek NCM> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (120mA)

usbconfig - device description

root@kg-core2:~ # usbconfig -d ugen1.9 dump_device_desc
ugen1.9: <Cvitek NCM> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (120mA)

  bLength = 0x0012 
  bDescriptorType = 0x0001 
  bcdUSB = 0x0200 
  bDeviceClass = 0x00ef  <Miscellaneous device>
  bDeviceSubClass = 0x0002 
  bDeviceProtocol = 0x0001 
  bMaxPacketSize0 = 0x0040 
  idVendor = 0x3346 
  idProduct = 0x100c 
  bcdDevice = 0x0510 
  iManufacturer = 0x0001  <Cvitek>
  iProduct = 0x0002  <NCM>
  iSerialNumber = 0x0003  <0123456789>
  bNumConfigurations = 0x0001 

usbconfig - current config

root@kg-core2:~ # usbconfig -d ugen1.9 dump_curr_config_desc
ugen1.9: <Cvitek NCM> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (120mA)


 Configuration index 0

    bLength = 0x0009 
    bDescriptorType = 0x0002 
    wTotalLength = 0x00a0 
    bNumInterfaces = 0x0004 
    bConfigurationValue = 0x0001 
    iConfiguration = 0x0004  <config1>
    bmAttributes = 0x0080 
    bMaxPower = 0x003c 

    Additional Descriptor

    bLength = 0x08
    bDescriptorType = 0x0b
    bDescriptorSubType = 0x00
     RAW dump: 
     0x00 | 0x08, 0x0b, 0x00, 0x02, 0x02, 0x0d, 0x00, 0x08


    Interface 0
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0000 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0001 
      bInterfaceClass = 0x0002  <Communication device>
      bInterfaceSubClass = 0x000d 
      bInterfaceProtocol = 0x0000 
      iInterface = 0x0005  <CDC Network Control Model (NCM)>

      Additional Descriptor

      bLength = 0x05
      bDescriptorType = 0x24
      bDescriptorSubType = 0x00
       RAW dump: 
       0x00 | 0x05, 0x24, 0x00, 0x10, 0x01


      Additional Descriptor

      bLength = 0x05
      bDescriptorType = 0x24
      bDescriptorSubType = 0x06
       RAW dump: 
       0x00 | 0x05, 0x24, 0x06, 0x00, 0x01


      Additional Descriptor

      bLength = 0x0d
      bDescriptorType = 0x24
      bDescriptorSubType = 0x0f
       RAW dump: 
       0x00 | 0x0d, 0x24, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 
       0x08 | 0xea, 0x05, 0x00, 0x00, 0x00


      Additional Descriptor

      bLength = 0x06
      bDescriptorType = 0x24
      bDescriptorSubType = 0x1a
       RAW dump: 
       0x00 | 0x06, 0x24, 0x1a, 0x00, 0x01, 0x11


     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0082  <IN>
        bmAttributes = 0x0003  <INTERRUPT>
        wMaxPacketSize = 0x0010 
        bInterval = 0x0009 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 


    Interface 1
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0001 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0000 
      bInterfaceClass = 0x000a  <CDC-data>
      bInterfaceSubClass = 0x0000 
      bInterfaceProtocol = 0x0001 
      iInterface = 0x0007  <CDC Network Data>


    Interface 1 Alt 1
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0001 
      bAlternateSetting = 0x0001 
      bNumEndpoints = 0x0002 
      bInterfaceClass = 0x000a  <CDC-data>
      bInterfaceSubClass = 0x0000 
      bInterfaceProtocol = 0x0001 
      iInterface = 0x0007  <CDC Network Data>

     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0081  <IN>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0200 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

     Endpoint 1
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0001  <OUT>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0200 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

      Additional Descriptor

      bLength = 0x08
      bDescriptorType = 0x0b
      bDescriptorSubType = 0x02
       RAW dump: 
       0x00 | 0x08, 0x0b, 0x02, 0x02, 0x02, 0x02, 0x01, 0x0c



    Interface 2
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0002 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0001 
      bInterfaceClass = 0x0002  <Communication device>
      bInterfaceSubClass = 0x0002 
      bInterfaceProtocol = 0x0001 
      iInterface = 0x000a  <CDC Abstract Control Model (ACM)>

      Additional Descriptor

      bLength = 0x05
      bDescriptorType = 0x24
      bDescriptorSubType = 0x00
       RAW dump: 
       0x00 | 0x05, 0x24, 0x00, 0x10, 0x01


      Additional Descriptor

      bLength = 0x05
      bDescriptorType = 0x24
      bDescriptorSubType = 0x01
       RAW dump: 
       0x00 | 0x05, 0x24, 0x01, 0x00, 0x03


      Additional Descriptor

      bLength = 0x04
      bDescriptorType = 0x24
      bDescriptorSubType = 0x02
       RAW dump: 
       0x00 | 0x04, 0x24, 0x02, 0x02


      Additional Descriptor

      bLength = 0x05
      bDescriptorType = 0x24
      bDescriptorSubType = 0x06
       RAW dump: 
       0x00 | 0x05, 0x24, 0x06, 0x02, 0x03


     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0084  <IN>
        bmAttributes = 0x0003  <INTERRUPT>
        wMaxPacketSize = 0x000a 
        bInterval = 0x0009 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 


    Interface 3
      bLength = 0x0009 
      bDescriptorType = 0x0004 
      bInterfaceNumber = 0x0003 
      bAlternateSetting = 0x0000 
      bNumEndpoints = 0x0002 
      bInterfaceClass = 0x000a  <CDC-data>
      bInterfaceSubClass = 0x0000 
      bInterfaceProtocol = 0x0000 
      iInterface = 0x000b  <CDC ACM Data>

     Endpoint 0
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0083  <IN>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0200 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

     Endpoint 1
        bLength = 0x0007 
        bDescriptorType = 0x0005 
        bEndpointAddress = 0x0002  <OUT>
        bmAttributes = 0x0002  <BULK>
        wMaxPacketSize = 0x0200 
        bInterval = 0x0000 
        bRefresh = 0x0000 
        bSynchAddress = 0x0000 

2024-08-27: it doesn't look like there is a SVD file for CV1800B anywhere. But still, the Arduino code uses sg200x.

2024-08-27: ti21 - it is possible to upload firmware with the burntool script like so

tingo@no-osl-ti21-linux:~/work/2024/0827_til_fredagsinnslag/Milk-V_Duo/milkv-duo-hal$ python3 ~/.arduino15/packages/sophgo/tools/burntool_py/0.3/burntool.py --port /dev/ttyACM0 --firmware blinky.elf

burntool.py v0.3

upload firmware blinky.elf

start upload...

communication and testing...

connecting...

connection successful...
stop firmware...

ready to update firmware...
start to update firmware...
send data... 10.00%
send data... 20.00%
send data... 30.00%
send data... 40.00%
send data... 50.00%
send data... 60.00%
send data... 70.00%
send data... 80.00%
send data... 90.00%
send data... 100.00%
send data... 100.00%
update firmware done...

restart firmware...

upload and runing success...

so far I haven't had any success in getting the LED to blink.

2024-08-27: ti21 - I install Arduino IDE 2.3.2 (appimage), add the additional boards manager URL for the Milk-V Duo

https://github.com/milkv-duo/duo-arduino/releases/download/config/package_sg200x_index.json

install the SG200X from Boards Manager, select he board "Duo Dev Module" and port /dev/ttyACM0. I open Examples, 01. Basics, Blink, then I upload the code. First it failed becasue I didn't have python3-serial installed, but after that

burntool.py v0.3

upload firmware /tmp/arduino/sketches/EF3734BEDA1DB34961E05C32CFD65B45/Blink.ino.elf

start upload...
send data... 100.00%
update firmware done...

restart firmware...

upload and runing success...

and the blue LED next to the usb-C connector starts blinking again. On the duo, I check various things

[root@milkv-duo]~# ls -l /lib/firmware
total 96
-rw-r--r-- 1 root root 97976 Jan  1 00:14 arduino.elf
[root@milkv-duo]~# cat /sys/class/remoteproc/remoteproc0/name 
c906l_rproc@0
[root@milkv-duo]~# cat /sys/class/remoteproc/remoteproc0/state 
running

interesting. burntool.py is in ~/.arduino15/packages/sophgo/tools/burntool_py/0.3/burntool.py

2024-08-27: duo - I remove the blink script with

[root@milkv-duo]~# mv /mnt/system/blink.sh /mnt/system/no_blink.sh
[root@milkv-duo]~# reboot
[root@milkv-duo]~# Connection to 192.168.42.1 closed by remote host.

after the machine has rebooted, the bluie LED next to the usb-C connector doesn't blink anymore.

2024-08-27: ti21 - there is also a usb serial port

$ ls -l /dev/tty[ACU]*
crw-rw---- 1 root dialout 166, 0 Aug 27 12:36 /dev/ttyACM0

2024-08-27: duo - related to remote proc aka 'arduino'

[root@milkv-duo]~# ls -l /lib/firmware
total 0
[root@milkv-duo]~# ls -l /usr/bin/burnd
-rwxr-xr-x 1 root root 585056 Aug  1  2024 /usr/bin/burnd

[root@milkv-duo]~# ls -l /sys/class/remoteproc
total 0
lrwxrwxrwx 1 root root 0 Jan  1 01:07 remoteproc0 -> ../../devices/platform/c906l_rproc@0/remoteproc/remoteproc0
[root@milkv-duo]~# ls -l /sys/class/remoteproc/remoteproc0/
total 0
-rw-r--r-- 1 root root 4096 Jan  1 01:07 coredump
lrwxrwxrwx 1 root root    0 Jan  1 01:07 device -> ../../../c906l_rproc@0
-rw-r--r-- 1 root root 4096 Jan  1 01:07 firmware
-r--r--r-- 1 root root 4096 Jan  1 01:07 name
-rw-r--r-- 1 root root 4096 Jan  1 01:07 recovery
-rw-r--r-- 1 root root 4096 Jan  1 01:07 state
lrwxrwxrwx 1 root root    0 Jan  1 01:07 subsystem -> ../../../../../class/remoteproc
-rw-r--r-- 1 root root 4096 Jan  1 01:07 uevent

and more

[root@milkv-duo]~# cat /sys/class/remoteproc/remoteproc0/name
c906l_rproc@0
[root@milkv-duo]~# cat /sys/class/remoteproc/remoteproc0/state
offline

2024-08-27: duo - scripts in /mnt/system auto.sh

[root@milkv-duo]~# more /mnt/system/auto.sh 
#!/bin/sh

# Put the program you want to run automatically here

blink.sh

[root@milkv-duo]~# more /mnt/system/blink.sh 
#!/bin/sh

LED_PIN=440

LED_GPIO=/sys/class/gpio/gpio${LED_PIN}

if test -d ${LED_GPIO}; then
    echo "PIN ${LED_PIN} already exported"
else
    echo ${LED_PIN} > /sys/class/gpio/export
fi

echo out > ${LED_GPIO}/direction

while true; do
    echo 0 > ${LED_GPIO}/value
    sleep 0.5
    echo 1 > ${LED_GPIO}/value
    sleep 0.5
done

duo-init.sh

[root@milkv-duo]~# more /mnt/system/duo-init.sh 
#!/bin/sh

# Set Pin-29(GP22) to GPIO
devmem 0x0502707c 32 0x111
devmem 0x03001068 32 0x3

# Set Pin-19(GP14) to GPIO
duo-pinmux -w GP14/GP14 > /dev/null

# Insmod PWM Module
insmod /mnt/system/ko/cv180x_pwm.ko

usb-host.sh

[root@milkv-duo]~# more /mnt/system/usb-host.sh
#!/bin/sh

echo host > /proc/cviusb/otg_role >> /tmp/usb.log 2>&1

usb-ncm.sh

[root@milkv-duo]~# more /mnt/system/usb-ncm.sh
#!/bin/sh

/etc/uhubon.sh device >> /tmp/ncm.log 2>&1
/etc/run_usb.sh probe ncm >> /tmp/ncm.log 2>&1
if test -e /usr/bin/burnd; then
  /etc/run_usb.sh probe acm >> /tmp/ncm.log 2>&1
fi
/etc/run_usb.sh start ncm >> /tmp/ncm.log 2>&1

sleep 0.5
ifconfig usb0 192.168.42.1

count=`ps | grep dnsmasq | grep -v grep | wc -l`
if [ ${count} -lt 1 ] ;then
  echo "/etc/init.d/S80dnsmasq start" >> /tmp/ncm.log 2>&1
  /etc/init.d/S80dnsmasq start >> /tmp/ncm.log 2>&1
fi

sleep 2
mkdir -p /lib/firmware
if test -e /usr/bin/burnd; then
  burnd &
  if test -e /lib/firmware/arduino.elf; then
    sleep 2
    echo stop  > /sys/class/remoteproc/remoteproc0/state
    echo start > /sys/class/remoteproc/remoteproc0/state
  fi
fi

usb-rndis.sh

[root@milkv-duo]~# more /mnt/system/usb-rndis.sh
#!/bin/sh

/etc/uhubon.sh device >> /tmp/rndis.log 2>&1
/etc/run_usb.sh probe rndis >> /tmp/rndis.log 2>&1
if test -e /usr/bin/burnd; then
  /etc/run_usb.sh probe acm >> /tmp/rndis.log 2>&1
fi
/etc/run_usb.sh start rndis >> /tmp/rndis.log 2>&1

sleep 0.5
ifconfig usb0 192.168.42.1

count=`ps | grep dnsmasq | grep -v grep | wc -l`
if [ ${count} -lt 1 ] ;then
  echo "/etc/init.d/S80dnsmasq start" >> /tmp/rndis.log 2>&1
  /etc/init.d/S80dnsmasq start >> /tmp/rndis.log 2>&1
fi

sleep 2
mkdir -p /lib/firmware
if test -e /usr/bin/burnd; then
  burnd &
  if test -e /lib/firmware/arduino.elf; then
    sleep 2
    echo stop  > /sys/class/remoteproc/remoteproc0/state
    echo start > /sys/class/remoteproc/remoteproc0/state
  fi
fi

2024-08-27: duo - from /mnt

[root@milkv-duo]~# ls -l /mnt
total 4
drwxr-xr-x 3 root root 1024 Aug  1  2024 cfg
drwxr-xr-x 2 root root 1024 Aug  1  2024 cvimodel
drwxr-xr-x 2 root root 1024 Aug  1  2024 data
drwxr-xr-x 5 root root 1024 Aug  1  2024 system

/mnt/data

[root@milkv-duo]~# ls -la /mnt/data
total 6
drwxr-xr-x 2 root root 1024 Aug  1  2024 .
drwxr-xr-x 6 root root 1024 Aug  1  2024 ..
lrwxrwxrwx 1 root root   21 Aug  1  2024 sensor_cfg.ini -> sensor_cfg_GC2083.ini
-rw-r--r-- 1 root root  259 Aug  1  2024 sensor_cfg_GC2083.ini
-rw-r--r-- 1 root root  259 Aug  1  2024 sensor_cfg_OV5647.ini
-rw-r--r-- 1 root root  263 Aug  1  2024 sensor_cfg_SC035HGS.ini
-rw-r--r-- 1 root root  258 Aug  1  2024 sensor_cfg_SC200AI.ini

/mnt/system

[root@milkv-duo]~# ls -la /mnt/system
total 14
drwxr-xr-x 5 root root 1024 Aug  1  2024 .
drwxr-xr-x 6 root root 1024 Aug  1  2024 ..
-rwxr-xr-x 1 root root   65 Aug  1  2024 auto.sh
-rwxr-xr-x 1 root root  336 Aug  1  2024 blink.sh
-rwxr-xr-x 1 root root  212 Aug  1  2024 duo-init.sh
drwxr-xr-x 3 root root 1024 Aug  1  2024 ko
drwxr-xr-x 2 root root 3072 Aug  1  2024 lib
-rw-r--r-- 1 root root  101 Aug  1  2024 sdk-release
-rwxr-xr-x 1 root root   67 Aug  1  2024 usb-host.sh
-rwxr-xr-x 1 root root  715 Aug  1  2024 usb-ncm.sh
-rwxr-xr-x 1 root root  731 Aug  1  2024 usb-rndis.sh
lrwxrwxrwx 1 root root   10 Aug  1  2024 usb.sh -> usb-ncm.sh
drwxr-xr-x 3 root root 1024 Aug  1  2024 usr

/mnt/cfg

[root@milkv-duo]~# ls -la /mnt/cfg
total 3
drwxr-xr-x 3 root root 1024 Aug  1  2024 .
drwxr-xr-x 6 root root 1024 Aug  1  2024 ..
drwxr-xr-x 2 root root 1024 Aug  1  2024 param
[root@milkv-duo]~# ls -la /mnt/cfg/param/
total 1074
drwxr-xr-x 2 root root   1024 Aug  1  2024 .
drwxr-xr-x 3 root root   1024 Aug  1  2024 ..
lrwxrwxrwx 1 root root     18 Aug  1  2024 cvi_sdr_bin -> cvi_sdr_bin_GC2083
-rw-r--r-- 1 root root 628456 Aug  1  2024 cvi_sdr_bin_GC2083
-rw-r--r-- 1 root root 229179 Aug  1  2024 cvi_sdr_bin_OV5647.bin
-rw-r--r-- 1 root root 233368 Aug  1  2024 cvi_sdr_bin_SC035HGS

/mnt/cvimodel

[root@milkv-duo]~# ls -la /mnt/cvimodel/
total 862
drwxr-xr-x 2 root root   1024 Aug  1  2024 .
drwxr-xr-x 6 root root   1024 Aug  1  2024 ..
-rwxr-xr-x 1 root root 874920 Aug  1  2024 scrfd_480_270_int8.cvimodel

2024-08-27: duo - from /sys/class/gpio

[root@milkv-duo]~# ls -l /sys/class/gpio
total 0
--w------- 1 root root 4096 Jan  1 00:00 export
lrwxrwxrwx 1 root root    0 Jan  1 00:00 gpio440 -> ../../devices/platform/3022000.gpio/gpiochip2/gpio/gpio440
lrwxrwxrwx 1 root root    0 Jan  1 00:42 gpiochip352 -> ../../devices/platform/5021000.gpio/gpio/gpiochip352
lrwxrwxrwx 1 root root    0 Jan  1 00:42 gpiochip384 -> ../../devices/platform/3023000.gpio/gpio/gpiochip384
lrwxrwxrwx 1 root root    0 Jan  1 00:42 gpiochip416 -> ../../devices/platform/3022000.gpio/gpio/gpiochip416
lrwxrwxrwx 1 root root    0 Jan  1 00:42 gpiochip448 -> ../../devices/platform/3021000.gpio/gpio/gpiochip448
lrwxrwxrwx 1 root root    0 Jan  1 00:42 gpiochip480 -> ../../devices/platform/3020000.gpio/gpio/gpiochip480
--w------- 1 root root 4096 Jan  1 00:42 unexport

2024-08-27: duo - network interfaces

[root@milkv-duo]~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 9e:7a:67:9d:56:81 brd ff:ff:ff:ff:ff:ff
    inet 169.254.101.59/16 brd 169.254.255.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::7e49:6379:b610:bd0f/64 scope link 
       valid_lft forever preferred_lft forever
3: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 7e:48:f6:ce:44:57 brd ff:ff:ff:ff:ff:ff
    inet 192.168.42.1/24 brd 192.168.42.255 scope global usb0
       valid_lft forever preferred_lft forever
    inet6 fe80::7c48:f6ff:fece:4457/64 scope link 
       valid_lft forever preferred_lft forever

2024-08-27: duo - various info from dmesg

[    0.000000] earlycon: sbi0 at I/O port 0x0 (options '')

[    0.000000] SBI specification v0.3 detected
[    0.000000] SBI implementation ID=0x1 Version=0x9
[    0.000000] SBI v0.2 TIME extension detected
[    0.000000] SBI v0.2 IPI extension detected
[    0.000000] SBI v0.2 RFENCE extension detected
[    0.000000] riscv: ISA extensions acdfimsuv
[    0.000000] riscv: ELF capabilities acdfimv

[    0.000000] Memory: 56196K/64768K available (4045K kernel code, 494K rwdata, 1818K rodata, 152K init, 210K bss, 8572K reserved, 0K cma-reserved)

[    0.241367] Ion: ion_parse_dt_heap_common: id 0 type 2 name carveout align 1000
[    0.249262] Ion: rmem_ion_device_init: heap carveout base 0x0000000083e3f000 size 0x0000000000000000 dev (____ptrval____)
[    0.260551] ion_carveout_heap_create, size=0x0
[    0.265323] cvi_get_rtos_ion_size, rtos ion_size get:0x0

[    0.445540] RTOS_CMDQU_INIT
[    0.448452] mbox_reg=(____ptrval____)
[    0.452297] mbox_done_reg=(____ptrval____)
[    0.456596] mailbox_context=(____ptrval____)
[    0.461115] cvi_rtos_cmdqu_probe DONE
[    0.465081] cvi_rtos_cmdqu_init done
[    0.468746] [cvi_spinlock_init] success
[    0.472993] Serial: 8250/16550 driver, 5 ports, IRQ sharing disabled
[    0.481576] printk: console [ttyS0] disabled
[    0.486107] 4140000.serial: ttyS0 at MMIO 0x4140000 (irq = 15, base_baud = 1562500) is a 16550A
[    0.495276] printk: console [ttyS0] enabled
[    0.503869] printk: bootconsole [sbi0] disabled
[    0.514158] 4150000.serial: ttyS1 at MMIO 0x4150000 (irq = 16, base_baud = 1562500) is a 16550A
[    0.524109] 4160000.serial: ttyS2 at MMIO 0x4160000 (irq = 17, base_baud = 1562500) is a 16550A
[    0.534095] 4170000.serial: ttyS3 at MMIO 0x4170000 (irq = 18, base_baud = 1562500) is a 16550A
[    0.544065] 41c0000.serial: ttyS4 at MMIO 0x41c0000 (irq = 19, base_baud = 1562500) is a 16550A

[    0.588697] bm-dwmac 4070000.ethernet: IRQ eth_wake_irq not found
[    0.595071] bm-dwmac 4070000.ethernet: IRQ eth_lpi not found
[    0.601061] bm-dwmac 4070000.ethernet: Hash table entries set to unexpected value 0
[    0.609138] bm-dwmac 4070000.ethernet: no reset control found
[    0.615385] bm-dwmac 4070000.ethernet: User ID: 0x10, Synopsys ID: 0x37
[    0.622307] bm-dwmac 4070000.ethernet:       DWMAC1000
[    0.627211] bm-dwmac 4070000.ethernet: DMA HW capability register supported
[    0.634434] bm-dwmac 4070000.ethernet: RX Checksum Offload Engine supported
[    0.641659] bm-dwmac 4070000.ethernet: COE Type 2
[    0.646551] bm-dwmac 4070000.ethernet: TX Checksum insertion supported
[    0.653327] bm-dwmac 4070000.ethernet: Normal descriptors
[    0.658936] bm-dwmac 4070000.ethernet: Ring mode enabled
[    0.664458] bm-dwmac 4070000.ethernet: Enable RX Mitigation via HW Watchdog Timer
[    0.672224] bm-dwmac 4070000.ethernet: device MAC address 9e:7a:67:9d:56:81
[    0.706367] libphy: stmmac: probed
[    0.711684] bm-dwmac 4070000.ethernet: Cannot get clk_500m_eth!
[    0.717948] bm-dwmac 4070000.ethernet: Cannot get gate_clk_axi4!

[    0.863164] mmc0: SDHCI controller on 4310000.cv-sd [4310000.cv-sd] using ADMA 64-bit

[    1.214978] mmc0: Problem switching card into high-speed mode!
[    1.235225] mmc0: new SDHC card at address 0001
[    1.240829] mmcblk0: mmc0:0001 SD32G 28.8 GiB 
[    1.248786]  mmcblk0: p1 p2 p3

[    2.329223] bm-dwmac 4070000.ethernet eth0: PHY [stmmac-0:00] driver [Generic PHY] (irq=POLL)
[    2.355206] dwmac1000: Master AXI performs any burst length
[    2.362167] bm-dwmac 4070000.ethernet eth0: No Safety Features support found
[    2.369957] bm-dwmac 4070000.ethernet eth0: IEEE 1588-2002 Timestamp supported
[    2.378799] bm-dwmac 4070000.ethernet eth0: configuring for phy/rmii link mode

2024-08-27: ti21 - ssh into the duo (ssh keys do not work, need to check the config)

tingo@no-osl-ti21-linux:~$ ssh root@192.168.42.1
root@192.168.42.1's password: 
[root@milkv-duo]~# ls -la
total 3
drwx------  2 root root 1024 Jan  1 00:09 .
drwxr-xr-x 19 root root 1024 Jan  1 00:00 ..
-rw-------  1 root root   12 Jan  1 00:10 .ash_history
[root@milkv-duo]~# 

version

[root@milkv-duo]~# cat /etc/os-release
NAME=Buildroot
VERSION=20240801-1858
ID=buildroot
VERSION_ID=2021.05
PRETTY_NAME="Buildroot 2021.05"

kernel

[root@milkv-duo]~# uname -a
Linux milkv-duo 5.10.4-tag- #1 PREEMPT Thu Aug 1 18:51:26 CST 2024 riscv64 GNU/Linux

lsblk info

[root@milkv-duo]~# lsblk -f
NAME        FSTYPE FSVER LABEL  UUID                                 FSAVAIL FSUSE% MOUNTPOINT
mmcblk0                                                                             
|-mmcblk0p1 vfat         boot   AA94-3653                             124.6M     2% /boot
|-mmcblk0p2 ext4         rootfs 75ee0820-1cdd-479e-a7cc-8f51cfbb6386  565.4M    18% /
`-mmcblk0p3                                                                         

df info

[root@milkv-duo]~# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       746M  138M  566M  20% /
devtmpfs         28M     0   28M   0% /dev
tmpfs            28M     0   28M   0% /dev/shm
tmpfs            28M   56K   28M   1% /tmp
tmpfs            28M   28K   28M   1% /run
/dev/mmcblk0p1  128M  3.2M  125M   3% /boot

info from /proc

[root@milkv-duo]~# cat /proc/cmdline 
root=/dev/mmcblk0p2 rootwait rw console=ttyS0,115200 earlycon=sbi riscv.fwsz=0x80000 loglevel=9
[root@milkv-duo]~# cat /proc/cpuinfo 
processor   : 0
hart        : 0
isa     : rv64imafdvcsu
mmu     : sv39

2024-08-27: ti21 - connecting the Duo to my machine with a usb-C cable. A red LED near the top left corner close to the microSD card lights up. On my machine I have

$ lsusb -d 3346:100c
Bus 005 Device 010: ID 3346:100c Cvitek NCM

and a new network interface

$ ip link show dev enxcaa52c3a1c1b
4: enxcaa52c3a1c1b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether ca:a5:2c:3a:1c:1b brd ff:ff:ff:ff:ff:ff
$ ip a show  enxcaa52c3a1c1b
4: enxcaa52c3a1c1b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether ca:a5:2c:3a:1c:1b brd ff:ff:ff:ff:ff:ff
    inet 192.168.42.103/24 brd 192.168.42.255 scope global dynamic noprefixroute enxcaa52c3a1c1b
       valid_lft 3135sec preferred_lft 3135sec
    inet6 fe80::6108:a689:a4c5:c561/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

2024-08-27: ti21 - the microSD card written from image (arduino-milkv-duo-sd-v1.1.2-2024-0801.img.zip) looks like this:

$ sudo parted /dev/sde print
Model: Generic- MicroSD/M2 (scsi)
Disk /dev/sde: 30.9GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start  End    Size   Type     File system  Flags
 1      512B   134MB  134MB  primary  fat16        boot, lba
 2      134MB  940MB  805MB  primary  ext4

mount and explore the boot partition

$ sudo mount /dev/sde1 /mnt
$ ls -l /mnt
total 3250
-rwxr-xr-x 1 root root 3007172 Aug  1 20:59 boot.sd
-rwxr-xr-x 1 root root  317952 Aug  1 20:59 fip.bin

not much. Unmount, then mount and explore the root partition

$ sudo mount /dev/sde2 /mnt
$ l -F /mnt/*
/mnt/lib64@  /mnt/linuxrc@

/mnt/bin:
./   busybox*  compile_et*  dir@        false@    gunzip@    linux32@  lsblk*    mount@       nuke@       pwd@    setarch@    su@      uname@
../  cat@      cp@      dmesg*      fdflush@  gzip@      linux64@  mk_cmds*  mountpoint@  pidof@          resume@     setpriv@    sync@    usleep@
arch@    chattr*   cpio@    dnsdomainname@  fgrep@    hostname@  ln@       mkdir@    mt@          ping@       rm@     setserial@  tar@     vdir@
ash@     chgrp@    date@    dumpkmap@   findmnt*  join@      login@    mknod@    mv@          pipe_progress@  rmdir@      sh@         touch@   vi@
base32@  chmod@    dd@      echo@       getopt@   kill@      ls@       mktemp@   netstat@     printenv@       run-parts@  sleep@      true@    watch@
base64@  chown@    df@      egrep@      grep@     link@      lsattr*   more@     nice@        ps@         sed@    stty@       umount@  zcat@

/mnt/dev:
./  ../  fd@  log@  pts/  shm/  stderr@  stdin@  stdout@

/mnt/etc:
./       dnsmasq.conf  group     init.d/  libnl/       network/ passwd      protocols     services  ssl/    wpa_supplicant.conf
../      dropbear@     hostname  inittab  mke2fs.conf  ntp.conf profile     resolv.conf@  shadow    uhubon.sh*
dhcpcd.conf  fstab     hosts     issue    mtab@    os-release@  profile.d/  run_usb.sh*   shells    wgetrc

/mnt/lib:
./   ld-musl-riscv64v0p7_xthead.so.1@  libblkid.so.1@      libfdisk.so.1.1.0*  libmount.so.1.1.0*      libstdc++.so.6@      libuuid.so.1@
../  libatomic.so.1@           libblkid.so.1.1.0*  libgcc_s.so.1*      libsmartcols.so.1@      libstdc++.so.6.0.28*     libuuid.so.1.3.0*
dhcpcd/  libatomic.so.1.2.0*           libfdisk.so.1@      libmount.so.1@      libsmartcols.so.1.1.0*  libstdc++.so.6.0.28-gdb.py*  lp64d@
ls: cannot open directory '/mnt/lost+found': Permission denied

/mnt/media:
./  ../

/mnt/mnt:
./  ../  cfg/  cvimodel/  data/  system/

/mnt/opt:
./  ../

/mnt/proc:
./  ../
ls: cannot open directory '/mnt/root': Permission denied

/mnt/run:
./  ../

/mnt/sbin:
./       cfdisk*      e2label@  fsck*       hdparm@    ipaddr@    logsave*   mkfs.ext2@     poweroff@    sfdisk*         syslogd@
../      chcpu*   e2mmpstatus@  fsck.ext2@  hwclock@   iplink@    losetup@   mkfs.ext3@     reboot@  start-stop-daemon@  tc@
arp@         ctrlaltdel*  e2undo*   fsck.ext3@  ifconfig@  ipneigh@   lsmod@     mkfs.ext4@     resize2fs*   sulogin@        tune2fs*
badblocks*   devmem@      e4crypt*  fsck.ext4@  ifdown@    iproute@   makedevs@  mklost+found*  rmmod@   swaplabel*      udhcpc@
blkdiscard*  dhcpcd*      fdisk*    fsfreeze*   ifup@      iprule@    mdev@      mkswap*        route@   swapoff*        uevent@
blkid*       dumpe2fs*    filefrag* fstrim*     init@      iptunnel@  mkdosfs@   modprobe@      run-init@    swapon*         vconfig@
blkzone*     e2freefrag*  findfs*   getty@      insmod@    klogd@     mke2fs*    nameif@        runlevel@    switch_root@        watchdog@
blockdev*    e2fsck*      freeramdisk@  halt@       ip@        loadkmap@  mkfs*      pivot_root@    setconsole@  sysctl@

/mnt/sys:
./  ../

/mnt/tmp:
./  ../

/mnt/usr:
./  ../  bin/  lib/  lib64@  lib64v0p7_xthead/  libexec/  local/  sbin/  share/

/mnt/var:
./  ../  cache@  db/  lib/  lock@  log@  run@  spool@  tmp@  www/

2024-08-25: I created this page.

2023-10-17: the package was delivered, straight into my mailbox.

2023-10-16: shipping notice from Posten.

2023-10-11 the package was shipped.

2023-10-09: I ordered 4 x Milk-V Duo from a seller on Aliexpress. The price was USD 6.89 each (total USD 27.56), with shipping the total is USD 41.15 (about NOK 474.76 via PayPal)