The Luckfox Pico Mini B

A while back during my spate of RK3588 reviews, I came across Luckfox and found their development boards intriguing, since they were marketed as being able to run Linux in the same postage stamp form factor as an MCU.

That seemed pretty amaazing, so I reached out to them and got a sample.

Disclaimer: Luckfox provided me with a Luckfox Pico Mini board and a CSI camera (for which I thank them), and this article follows my .

What followed has been a surprisingly pleasant experience, and I’ve been tinkering with the Luckfox Pico Mini on and off for a few weeks now–to be fair, mostly off given several work shenanigans, but that’s beside the point right now…

Hardware

I got the B model, which has a soldered on 128MB SPI NAND flash:

tiniest Linux machine I own
Both sides of the board, which is pretty compact.

The specs for the version I got are:

  • Single Cortex A7 1.2GHz core
  • 0.5 TOPS NPU (with int4, int8, int16 support, so it can run OpenCV and simple neural networks, but nothing too fancy)
  • 64MB RAM
  • USB-C 2.0 host/device connector
  • CSI connector (I also got a 3mp camera)
  • MicroSD connector
  • 17 GPIO pins

An intriguing part of the RV1103 chip that I haven’t explored is that it includes a RISC-V MCU and an integrated signal processor for speeding up camera operations–I intend to play with that at some point, but simply haven’t had the time yet.

If you’ve been following along in the and space, you’re certainly wondering about price right now, since the overall specs compare pretty favourably with similarly sized and boards, especially if you consider its secret sauce–i.e., running Linux natively.

Right now it’s selling for $8.99, which is around twice the price of similarly-sized boards, but which still looks like a bargain if you need the extra processing power and the ability to run Linux.

On the flip side, this particular model doesn’t have wireless connectivity, which is a bit of a bummer. But I can see how that would complicate the design and increase the price further.

I’d say we’re about a year away from seeing a Cortex A7 with wireless connectivity at this price point, but don’t hold me to that.

Going In Headfirst

Since the B version of the board has on-board storage and comes pre-flashed with a working 5.10 kernel, I decided to see how far I could go with the board as it comes out of the box.

Connecting

I plugged the Luckfox Pico into one of my Linux machines, and it showed up immediately as a RNDIS device:

 dmesg

[57790.089476] usb 3-2: new high-speed USB device number 3 using xhci_hcd
[57790.220263] usb 3-2: New USB device found, idVendor=2207, idProduct=0019, bcdDevice= 3.10
[57790.220280] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[57790.220287] usb 3-2: Product: rk3xxx
[57790.220292] usb 3-2: Manufacturer: rockchip
[57790.220298] usb 3-2: SerialNumber: c800c8d03cffebb8
[57790.333460] usbcore: registered new interface driver cdc_ether
[57790.341712] rndis_host 3-2:1.0 usb0: register 'rndis_host' at usb-0000:04:00.4-2, RNDIS device, ae:5c:b5:d3:ee:1e
[57790.341790] usbcore: registered new interface driver rndis_host
[57790.380103] rndis_host 3-2:1.0 enp4s0f4u2: renamed from usb0

This means there’s none of the usual serial port/FTDI-style shenanigans (well, when you’re not flashing it, of course). Instead, you have to do some TCP/IP shenanigans.

My host machine auto-generated the enp4s0f4u2 interface, but if you need to flash a number of these and keep inventory, here’s a quick snippet to figure out the right interface from the MAC address without going into dmesg:

 ip addr list | grep -B 1 -A 2 ae:5c:b5:d3:ee:1e

5: enp4s0f4u2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
    link/ether ae:5c:b5:d3:ee:1e brd ff:ff:ff:ff:ff:ff
    inet6 fe80::f8c1:e2a2:dd8a:c6c1/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

As you can see, there’s no assigned IPv4 (only the system-assigned link-local IPv6 on the host side). And the Luckfox Pico does not support RFC 3927, so you don’t get an automatic link-local IPv4 address.

The docs specify the default IP as 172.32.0.93, so let’s set an address at our end and test the Ethernet over USB link:

 sudo ip addr add 172.32.0.1/16 dev enp4s0f4u2
❯ ping 172.32.0.93                             
PING 172.32.0.93 (172.32.0.93) 56(84) bytes of data.
64 bytes from 172.32.0.93: icmp_seq=1 ttl=64 time=0.754 ms
64 bytes from 172.32.0.93: icmp_seq=2 ttl=64 time=0.580 ms
^C
--- 172.32.0.93 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1008ms
rtt min/avg/max/mdev = 0.580/0.667/0.754/0.087 ms

It feels a bit weird to log in to what is almost an MCU via ssh, but it works fine:

 ssh [email protected]
The authenticity of host '172.32.0.93 (172.32.0.93)' can't be established.
ED25519 key fingerprint is SHA256:VnUEEITBSJ7Y7h+wmk8bTqw47QwdLWudvM0tRgke4Kc.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.32.0.93' (ED25519) to the list of known hosts.
[email protected]'s password: 
# uname -a
Linux luckfox 5.10.110 #1 Tue Nov 14 18:06:04 CST
 2023 armv7l GNU/Linux
# cat /etc/issue 
Welcome to luckfox pico

Running Processes

The runtime is, as you’d expect, pretty sparse, and on the base image there aren’t a lot of things besides kernel workers:

# ps -ef
PID   USER     COMMAND
    1 root     init
    2 root     [kthreadd]
    4 root     [kworker/0:0H]
    6 root     [mm_percpu_wq]
    7 root     [ksoftirqd/0]
    8 root     [kdevtmpfs]
    9 root     [oom_reaper]
   10 root     [writeback]
   11 root     [kcompactd0]
   12 root     [ksmd]
   28 root     [kblockd]
   29 root     [kconsole]
   30 root     [devfreq_wq]
   31 root     [watchdogd]
   32 root     [kworker/0:1-eve]
   33 root     [rpciod]
   34 root     [kworker/u3:0]
   35 root     [xprtiod]
   36 root     [kswapd0]
   37 root     [nfsiod]
   38 root     [irq/60-rockchip]
   39 root     [irq/61-rockchip]
   40 root     [kworker/u2:1-ev]
   41 root     [hwrng]
   42 root     [spi0]
   51 root     [kworker/0:3-eve]
   52 root     [irq/22-rockchip]
   53 root     [kworker/u2:2-ev]
   54 root     [ubi_bgt0d]
   57 root     [ubifs_bgt0_0]
   73 root     /sbin/syslogd -n
   77 root     /sbin/klogd -n
   88 root     /sbin/udevd -d
  141 root     [ubi_bgt4d]
  146 root     [ubifs_bgt4_0]
  155 root     [ubi_bgt5d]
  160 root     [ubifs_bgt5_0]
  182 root     [irq/50-ffa70000]
  200 root     [irq/41-rga2]
  202 root     [queue_work0]
  203 root     [queue_work1]
  204 root     [irq/48-ffa50000]
  205 root     [irq/49-ffa60000]
  206 root     [vcodec_thread_0]
  208 root     [rknpu_power_off]
  215 root     sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
  246 root     [vlog]
  247 root     [vsys]
  248 root     [vrga]
  250 root     [vpss]
  251 root     [vrgn]
  253 root     [vmcu]
  326 root     /usr/bin/adbd
  334 root     [irq/62-dwc3]
  370 root     smbd -D
  373 root     {smbd-notifyd} smbd -D
  374 root     {smbd-cleanupd} smbd -D
  379 root     nmbd -D
  384 root     /sbin/getty -L console 0 vt100
  397 root     sshd: root@pts/0
  399 root     -sh
  409 root     ps -ef

Wait, is that… Samba? Seriously?

# cat /etc/samba/smb.conf 
[global]
        workgroup = WORKGROUP
        server string = luckfox samba server
        security = user  
        passdb backend = smbpasswd
        smb passwd file = /etc/samba/smbpasswd
[public]
        comment = public share
        path = /
        read only = no
        user = root
        create mask = 0755
        directory mask = 0755# 

Yep. This when you start realizing the Luckfox Pico is an embedded system you can mount over –crazy times.

Running My First Binary

At the time I got this I didn’t have any cross-compilation environments set up, but I did have , and I have a fairly long history of building impromptu binaries for weird ARM architectures using, it.

So I thought I’d add to that list:

 go mod init luckfox/hello

...a few moments later...
❯ cat hello.go 
package main

import "fmt"

func main() {
        fmt.Println("Hello, Luckfox!")
} env GOOS=linux GOARCH=arm GOARM=7 go build -o hello.armv7

❯ file hello.armv7 
hello.armv7: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, Go BuildID=fMvkSlf1kYWYnV88GhTQ/J1Y1phDV859SF5L4bFxZ/P3d-713IBZ6mHIbEpIub/hZRSRS5aBTm4NBaU8f_g, with debug_info, not stripped

❯ scp hello.armv7 [email protected]:~/

...a few moments later...

# ./hello.armv7
Hello Luckfox!

The resulting binary is 1823294 bytes in size (which is reasonable given that it is fully static), and the other (relatively simplistic) stuff I’ve built since hasn’t yet crossed the 2MB mark. And keep in mind this isn’t TinyGo, it’s the full-fat Go runtime.

A few days later, while rummaging around, I realised that the Luckfox Pico ships with 3.11. Not MicroPython, mind you, but, again, the whole thing (or at least a good chunk of it that it hasn’t mattered yet).

I’ve since built some binaries, and eventually realized I can actually run gdb locally on the device–which is the kind of frictionless, iterative development approach that I love.

This opens up the opportunity for taking existing or code that would be a pain to port to Arduino or a simpler MCU and just cross-compile and copy across and test it within an hour or so, which is pretty great.

GPIO Control

The Luckfox Pico Mini has the usual set of GPIO pins, overlapping with 4 UARTs, an SPI interface and an I2C one:

reasonably comprehensive
Pinout for the Mini A/B models

The nice thing about having a Linux kernel is that GPIOs are mapped as device folders under /sys/class/gpio, so literally anything can use them without special libraries.

However, there are shipping libraries to make things easier, and the documentation covers that in detail–there’s a C example in the Luckfox Wiki that demonstrates GPIO access, and matching ones for I2C, SPI, etc.

Sadly, there’s no I2S support on this model–so my initial idea of getting a PCM5102A DAC to work didn’t pan out.

Building and Flashing New Firmware

I didn’t yet have time to build anything truly complex (I was planning to incorporate the Luckfox Pico into a little audio project, and now I am considering other uses), but since that’s usually something I very much want to do, I investigated how to go about it.

In short, there’s a set of comprehensive docs regarding getting an SDK going on Ubuntu 22.04, and a public repository (not on Github, though) with reference tarballs and patches for various libraries. Given the propensity of Rockchip SDKs to come with assorted binaries, I’d be prepared for a little work, but couldn’t see anything too out of the ordinary.

As to pre-built images, as usual with Chinese companies they’re available via Google Drive download (I’m not a fan of this, but it’s a common practice), and the flashing process is pretty straightforward.

A Nice Surprise

On that note, to my surprise, Luckfox actually has Linux and MacOS instructions for flashing, so the that I got expressey to deal with Rockchip tools for the RK3588 boards sat this one out.

Connectivity

My original idea was to leverage the Cortex A7 for building a tiny synthesiser with a bit more oomph than the ones that have been making the rounds–but that hasn’t come to pass, and the lack of wireless connectivity prevents me from using it in my home automation projects.

But with four UARTs, you can hook up more MCUs and use the Luckfox Pico’s SD card as a sensor data logger as well–I can see this being used in drones and other applications where you need a bit more processing power than a typical MCU.

What I eventually did was to force route the Luckfox Pico through my Linux machine and play around with little TCP servers on it. This is a bit of a kludge, but it works even if it’s not an elegant solution.

Conclusion

So who is this for? Well, for starters, I’d say the Luckfox Pico is for people who already have a code base that absolutely requires full POSIX compliance or is already running on ARMv7 chips and don’t want to mess with the complexity of porting it to a “plain” MCU.

And, in a nutshell, that’s why I have been tinkering with it–I can get something working, build an ARM binary, and copy it across in seconds–or just let the Luckfox Pico route through my machine and fetch the binary from there, without using any board-specific tools whatsoever. That’s something you can’t do with any other development board this size.

I haven’t yet had the time to play with RKNN inference and the baked in YOLO support–I need a quieter time, and will update this post when I get aroudn to it–but I can see the Luckfox Pico being used as a smart, field-programmable part inspector in manufacturing, or a tiny, self-contained auto-tracking camera (like the I’ve been using).

But given that this is an A7 with a pretty decent FPU, I’d say signal processing appliations would be a great candidate (I’m still stuck on the idea of using it as the core of a tiny synthesizer, even without I2S).

This page is referenced in: