Alomst the best I have ever seen (three)

Pinpong

Follow the guide to install pinpong.zip (my mirror), only for V1.0.4 system image, and then:

blink2.py

import time
from pinpong.board import Board,Pin

Board("MILKV-DUO").begin()

led = Pin(Pin.D0, Pin.OUT)

while True:
  led.value(1)
  time.sleep(1)
  led.value(0)
  time.sleep(1)

The pinpong library covers quite a lot of functionality, and useful examples:

root@milkv-duo2]~# ls /usr/lib/python3.9/site-packages/pinpong/examples/milkv-Duo/
__init__.py               gravityPM2.5.py           oled2864.pyc
__init__.pyc              i2c.py                    ozone.py
adc.py                    i2c.pyc                   ozone.pyc
adc.pyc                   i2c_scan.py               paj7620.py
as7341.py                 i2c_scan.pyc              paj7620.pyc
as7341.pyc                iic_to_serial.py          ph1.py
blink.py                  iic_to_serial.pyc         ph1.pyc
blink.pyc                 ir_recv.py                ph2.py
bme280.py                 ir_recv.pyc               ph2.pyc
bme280.pyc                ir_send.py                pwm.py
bme680.py                 ir_send.pyc               pwm.pyc
bme680.pyc                irq.py                    rgb_panel.py
bmi160_acc.py             irq.pyc                   rgb_panel.pyc
bmi160_acc.pyc            lcd1602.py                sen0483.py
bmi160_step.py            lcd1602.pyc               sen0483.pyc
bmi160_step.pyc           lis2dh.py                 servo.py
bmp280.py                 lis2dh.pyc                servo.pyc
bmp280.pyc                max30103.py               sht31.py
bmp388.py                 max30103.pyc              sht31.pyc
bmp388.pyc                mics_enable_power.py      speech_synthesis.py
button.py                 mics_enable_power.pyc     speech_synthesis.pyc
button.pyc                mics_get_adc_data.py      spi.py
buzzer.py                 mics_get_adc_data.pyc     spi.pyc
buzzer.pyc                mics_get_gas_exist.py     sr04_urm10.py
ccs811_read_baseline.py   mics_get_gas_exist.pyc    sr04_urm10.pyc
ccs811_read_baseline.pyc  mics_get_gas_ppm.py       st7789-as7341.py
ccs811_read_data.py       mics_get_gas_ppm.pyc      st7789.py
ccs811_read_data.pyc      mlx90614.py               st7789.pyc
dht.py                    mlx90614.pyc              tcs34725.py
dht.pyc                   mp3.py                    tcs34725.pyc
dht20.py                  mp3.pyc                   tds.py
dht20.pyc                 neopixel.py               tds.pyc
ds0469.py                 neopixel.pyc              tone.py
ds0469.pyc                nfc.py                    tone.pyc
ds1307.py                 nfc.pyc                   uart.py
ds1307.pyc                nfc_card_info.py          uart.pyc
ds18b20.py                nfc_card_info.pyc         urm09.py
ds18b20.pyc               nfc_uart.py               urm09.pyc
ens160.py                 nfc_uart.pyc              vl53l0.py
ens160.pyc                nfc_uart_card.py          vl53l0.pyc
gp2y1010au0f.py           nfc_uart_card.pyc
gp2y1010au0f.pyc          oled2864.py

I will explore those examples.

Start Script at Boot

As of V1.0.4 system image, the /etc/init.d/S99user executes /mnt/data/auto.sh if it exists:

% mkdir /mnt/data
% vi /mnt/data/auto.sh

and list each of the processes:

/path/to/my/script.sh &
python /path/to/another/script.py &

TinyCC

According this post, tinycc has been ported as well – C compiler and C interpreter in one – download the .zip (my mirror) and run its install.sh, and then fix missing executable bit:

% chmod +x /usr/local/bin/tcc

and start playing with test.c:

#!/usr/local/bin/tcc -run

#include <stdio.h>

int main(int argc, char **argv) {
    printf("%s---\n", "hello milk-v!");
    return 0;
}
% tcc -o test test.c
% ./test
hello milk-v!---
% chmod +x test.c
% ./test.c
hello milk-v!---

Thanks to Yang who ported and provided the download.

I2C: SSD1306 OLED

I followed the example, and compiled the sources on the board itself with tcc:

tcc -r ssd1306.c -I .
tcc -r linux_i2c.c -I .
tcc -o ssd1306 main.c linux_i2c.o ssd1306.o -I .
./ssd1306 -I 128x64
./ssd1306 -c
./ssd1306 -m "Hello world!\nMilk-V Duo"

OLED SSD1306 connected to Milk-V Duo via I2C, controlled via RISC-V binary ssd1306 from ssd1306_linux

Software State

ON-BOARD BUILDROOT V1.0.4-2023-0908 BUILDROOT V1.0.4-2023-1017-SPIRITDUDE ARCHLINUX 2023-10-09 V0.0.1 SPIRITDUDE
available memory (RAM) 48MB 55MB 55MB
ssh server ok (dropbear v2020.81) ok (dropbear v2020.81) ok (dropbear v2022.83)
ssh client ok (dropbear v2020.81) ok (dropbear v2020.81) ok (dropbear v2022.83)
python ok (python 3.9.5) ok (python 3.9.5) ok (python 3.11)
py web-server (with socket) ok ok ok
py gpio (with pinpong or gpio) ok ok
py spi (with built-in spidev) available, not yet tested available, not yet tested
py i2c (with pinpong ) available, not yet tested with pinpong
ok with .c (see above section) available, not yet tested with pinpong
ok with .c (see above section)
py pwm (with pinpong) not found, /sys/class/pwm/* is empty not found, /sys/class/pwm/* is empty
pip failed (hangs), enable swap space to use it barely works, enable swap space works (swap space enabled)
cc/gcc/clang not found not included not included
tinycc/tcc ok, see this post how to install ok, see this post how to install ok
rsync not found included included
wget ok, but no https (only http, ftp) ok, but no https (only http, ftp) not included, installable
lua/luac lua (5.4.6): segmentation fault, luac (5.4.6): seems to work (both compiled with tinycc) lua & luac (5.3.6) works lua & luac (5.4.6) works
extras quickjs/qjs, micropython, nano, screen, git, make (no gcc/cc, use tinycc), thttpd, nginx, lighttpd, php-cgi, file, which, sudo pacman (package mgr), lighttpd, file, which, sudo, make

Internet Access for Milk-V Duo

RNDIS (Virtual Ethernet over USB)

The host has to run Ethernet over USB and also operate as transparent router and let the connected board(s) reach the internet, see this guide (use google translate to english), here the brief description:

On The Host

The outgoing_if is the outgoing interface, either eth0 or wpl0s0 or something, check with ifconfig of the proper name, and then as root perform:

% sysctl net.ipv4.ip_forward=1
% iptables -P FORWARD ACCEPT
% iptables -t nat -A POSTROUTING -o outgoing_if -j MASQUERADE

Also, find out which IP your host got (ip_of_host) from the connected board, e.g. 192.168.42.120, also check with ifconfig.

On The Board

% ip r add default via ip_of_host
% echo "nameserver 8.8.8.8" >> /etc/resolv.conf

Custom BuildRoot Milk-V Duo Disk Image

Here my brief guide – see also this guide (use google translate) – how to customize packages included in the base distribution of the image for the SD card:

% cd duo-buildroot-sdk/buildroot-2021.05
% make menuconfig

then go into the “Target packages”, and then walk through:

  • Audio and video applications
  • Compressors and decompressors
  • Debugging, profiling and benchmark
  • Development tools
  • Filesystem and flash utilities
  • Fonts, cursors, icons, sounds and themes
  • Games
  • Graphic libraries and applications (graphic/text)
  • Hardware handling
  • Interpreter languages and scripting
  • Libraries
  • Mail
  • Miscellaneous
  • Networking applications
  • Package managers
  • Real-Time
  • Security
  • Shell and utilities
  • System tools
  • Text editors and viewers

once you selected the packages you like to have included, choose “Save” and confirm as ‘.config’ and then “Exit”.

% cp .config configs/milkv_duo_musl_riscv64_defconfig
% cd ..
% ./build_milkv.sh

and after while, depending on how many packages you selected, you find in out/ folder your new disk image you can copy on the SD card.

Note: buildroot is quite a quirky package, e.g. when you select a package and make a build, later deselect a package, it will still be included – worse, if you commit a clean slate in output/, some packages might not fully build anymore – you have to go back to an earlier state of fewer packages, remake the build, and restart re-selecting new packages.

Postfixing missing .so file

As of 2023/10 v1.0.4 buildroot-2021.05 environment, there seems a problem regarding a missing shared library for some of the compiled apps (like qjs), you can fix this:

% cd /lib
% ln -s ld-musl-riscv64v0p7_xthead.so.1 ld-musl-riscv64.so.1

My BuildRoot Custom Disk Images

DISK IMAGE NOTES
milkv-duo-v1.0.4-20231017-spiritdude-64mb_ram-nocam.img lua, quickjs/qjs, micropython, nano, screen, git, make (no gcc/cc, use tinycc), thttpd), nginx, lighttpd, php-cgi, 55MB RAM available, “fixed” image has .so lib-fix included
milkv-duo-v1.0.4-20231017-spiritdude-64mb_ram-nocam-fixed.img lua, quickjs/qjs, micropython, nano, screen, git, make (no gcc/cc, use tinycc), thttpd), nginx, lighttpd, php-cgi, 55MB RAM available, “fixed” image has .so lib-fix included
milkv-duo-v1.0.4-20231016-spiritdude-64mb_ram-nocam.img lua, quickjs/qjs, micropython, nano, screen, git, make (no gcc/cc, use tinycc), lighttpd (doesn’t work yet out of the box),55MB RAM available
  1. apprx. 55MB actual available RAM, no camera support, INO_SIZE=0
  2. thttpd, nginx and lighttpd are all http-server, only use one, see /etc/init.d/ where those are started.

Ethernet Add-On

The easier way is to get proper networking is to add a real ethernet port and properly wire it to the ethernet router. There are several options & sources (2023/09):

RJ45 Add-on (EUR 2.50)

RJ45 Add-on (EUR 2.50)

IO Expansion: 4x USB 1x Ethernet (USD 5.00 – 9.50)

Printable Case

I did a small case for the bare board without Ethernet or Extension board to be 3D printed:

Milk-V Duo (bare):
bottom case & lid

Milk-V Duo (bare): bottom case

Milk-V Duo case closed

Printed in white & black PLA

white vs black case blue & red LEDs see-through

white PLA cases allow LEDs see through

white PLA (FFF/FDM), white & clear resin (MSLA)

Download

As the Milk-V Duo has the same width and depth (X/Y) as the Raspberry Pico but it’s a bit thicker so the some of the existing cases work only partially:

As soon my Ethernet connectors and Extension boards arrived I will provide case variants (2023/10/05).

References

1 Like