Archives For Uncategorized

Inky pHat on FreeBSD/Pi

November 14, 2018 — Leave a comment

About a month ago I purchased Inky pHat from Pimoroni, Pi hat with 220×104 red and black eInk screen. The device has an SPI interface with three additional GPIO signals: reset pin, command/data pin, and busy pin. Reset and busy pins are self-explanatory: the former resets device MCU the latter signals to the Pi whether the MCU is busy handling previous command/data. Command/data signals the type of SPI transaction that is about to be sent to Inky: low means command, high – data. It more or less matches interface to SSD1306 OLED display I played with before.

There is no datasheet or protocol description, so I used Pimoroni’s python library as a reference.

To communicate with the device over SPI, you need to apply spigen device-tree overlay and load spigen driver. For Raspberry Pi 3 you probably need a patch from this review applied. To load overlay add respective dtbo name to the fdt_overlays variable in /boot/loader.conf, e.g.:


I didn’t have any practical purpose for the device in mind so after several failed attempts to output RGB images in two color I ended up writing random ornament generator:



If you’re trying to boot FreeBSD with latest RaspberryPi firmware – be aware that this commit changed default frequency for UART0 on at least RaspberryPi 2, so to get serial console working in u-boot/ubldr again you need to add this line to config.txt:


You can get source for current kernel FDT blob by running following command

sysctl -b hw.fdt.dtb | dtc -I dtb -O dts

Edit 27/10/2017: added -O option, looks like it’s required in newer dtc

I’ve just added extended filters to Now filter can be either committer, or path, or both. Path is indicated by adding @ character to the beginning, so gonzo means all commits by gonzo, @sys/arm means all commits to sys/arm directory, and gonzo@sys/arm means all commits by gonzo to sys/arm directory. If there are more then one expression separated by space the result will be all filters OR-ed together: @sys/arm @boot/efi means all commits to sys/arm plus all commits to boot/efi directory.

raspberrypi-userland git repo was synced to the latest upstream code base:

Dear Future Me,

I guess you came here googling for “FreeBSD PXE UEFI” trying to find out how to netboot your x86 dev box. Or arm64 box. Who knows what you’re hacking on in the future. To do that you need follow these simple steps:

  • Put loader.efi to tftpboot dir
  • Configure dhcpd along these lines:
    host amd64 {
            hardware ethernet  b8:ae:ed:77:88:99;
            filename "loader.efi";
            option root-path "/src/FreeBSD/tftproot/amd64";
            option routers;
  • Make sure root-path is in /etc/exports.
  • If you use MINIMAL-derived config add your NIC driver to /boot/loader.conf:

That’s pretty much it.

Take care

Untethering Jetson-TK1

September 25, 2016 — Leave a comment

Normally I netboot all my ARM devices but in case of Jetson TK1 I thought it would be nice to go and try to make it “real computer” – running by itself, may be use it for some port builds. I added Samsung EVO to it but the plan was to use SSD for builds/source code, and to use either external SD card or eMMC as a root device. TK1 survived buildworld/buildkernel (I had to add swap though, clang is a memory monster) so it was time to populate root device and eMMC was picked as a target. There were some ms-basic-data partitions on eMMC but I didn’t think much of it and happily typed dd if=/dev/zero of=/dev/mmcsd0 bs=128m. Well… Big mistake. Among those partitions was u-boot. And probably earlier stage boot loader as well. So I had to install ubuntu on one of unused machines and re-flash TK1. Luckily no permanent damage was done to the device. After this accident I added a little bit of planning into the process. Here is short summary:

Default eMMC partition looks like this:

Tegra124 (Jetson TK1) #  mmc part

Partition Map for MMC device 0  --   Partition Type: EFI

Part    Start LBA       End LBA         Name
        Type GUID
        Partition GUID
  1     0x00017000      0x01c16fff      "APP"
        attrs:  0x0001000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   7369c667-ff51-ec4a-29cd-baabf2fbe346
  2     0x01c17000      0x01c18fff      "DTB"
        attrs:  0x0002000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   f854c27c-e81b-8de7-765a-2e63339fc99a
  3     0x01c19000      0x01c38fff      "EFI"
        attrs:  0x0003000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   b70d3266-5831-5aa3-255d-051758e95ed4
  4     0x01c39000      0x01c3afff      "USP"
        attrs:  0x0004000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   c6cdb2ab-b49b-1154-0e82-7441213ddc87
  5     0x01c3b000      0x01c3cfff      "TP1"
        attrs:  0x0005000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   a13ee970-e141-67fc-3e01-7e97eadc6b96
  6     0x01c3d000      0x01c3efff      "TP2"
        attrs:  0x0006000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   2a5c388f-b0ec-fb3b-32af-3c54ec18db5c
  7     0x01c3f000      0x01c40fff      "TP3"
        attrs:  0x0007000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   43fe1a02-fafb-3aaa-fb29-d1e6053c7c94
  8     0x01c41000      0x01c41fff      "WB0"
        attrs:  0x0008000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   61bed875-f989-bb5c-a899-0f95b1ebf1b3
  9     0x01c42000      0x01d58fff      "UDA"
        attrs:  0x0009000000000001
        type:   ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
        guid:   00f7ef05-a1e9-e53a-ca0b-cbd0484764bd

We need two things to make TK1 bootable: place ubldr on flash so u-boot can load it and create rootfs. The latter one is simple: APP partition is the one to be user as root. For the former either of TPx partitions can be used, TP stands for “Temporary Placeholder” and can be used for app-specific tasks. All three TPx are just 4Mb but ubldr is small enough to fit just fine. So let’s place ubldr to TP1:

# newfs_msdos /dev/gpt/TP1
# mount_msdosfs /dev/gpt/TP1 /mnt
# cp ubldr.tk1 /mnt/
# umount /mnt

Then populate rootfs:

# newfs /dev/gpt/APP
# mount /dev/gpt/APP /mnt

Then build/install stuff: … buildworld, buildkernel. installworld, distribution and installkernel with DESTDIR=/mnt …

Create /etc/fstab so kernel would pick up correct rootfs location. I also use nullfs to mount /tmp to the directory on SSD drive, and added swap file on SSD.

/dev/gpt/APP /       ufs     rw,noatime     0       0
/dev/ada0    /src    ufs     rw,noatime     0       0
md99         none    swap    sw,file=/src/swap,late      0       0
/src/tmp     /tmp    nullfs  rw             0       0
# umount /mnt

Reboot to u-boot and set up boot command:

Tegra124 (Jetson TK1) # setenv bootcmd 'fatload mmc 0:5 $loadaddr ubldr.tk1; bootelf'
Tegra124 (Jetson TK1) # saveenv
Saving Environment to MMC...
Writing to MMC(0)... done
Tegra124 (Jetson TK1) # boot

That’s it. Also if I need to revert back to netbooting TK1 I can just set loaderdev to “net” in u-boot:

Tegra124 (Jetson TK1) # setenv loaderdev net; boot

Two months ago I tried to setup dev environment using FreeBSD Vagrant box just to find out that FreeBSD does not support VirtualBox shared folders. After some googling I found Li-Wen Hsu’s github repository with some work in this area. Li-Wen and Will Andrews has already done major chunk of work: patches to VirtualBox build system, skeleton VFS driver, API to talk to hypervisor but hit a block with some implementation details in VirtualBox’s virtual-memory compatibility layer. Will provided very comprehensive analysis of the problem.

Li-Wen was occupied with some other projects so he gave me his OK to work on shared folder support on my own. Will’s suggestion was easy to implement – lock only userland memory, like Solaris driver does. VFS part was more complicated though: fs nodes, vnode, their lifecycle and locking is too hairy for drive-by hacking. I used tmpfs as a reference to learn some VFS magic, but a lot of things are still obscure. Nevertheless after few weeks of tinkering first milestone has been achieved: I can mount/unmount shared VirtualBox folder and navigate mounted filesystem without immediate kernel panic. Next goal (if time permits): stable and non-leaking read-only filesystem.

Being able to power cycle ARM boards remotely (without spending a lot of $$$) was on my wish list for way to long, so I finally got around to put something together. The obvious way to do this is power relay controlled by GPIO + remotely accessible GPIO port. For the former I picked up this relay by Digital Loggers. It was four ports, only two of them are connected at a time, you can switch selected pair by setting control port level. For a controller part I picked up RIoTBoard but actually any ARM board with sshd running on it and user-accessible GPIO pin would do.

On riotboard there are several GPIO pins available on J13 expansion port. You can find values in board’s user manual. Just in case you don’t know (and it’s not in manual) pin 1 on the port marked with white triangle, if you look at port so that pin 1 is in top-left corner, next to it on the right is pin 2, and right under it is pin 3. So it goes like:
[ 1 2 ]
[ 3 4 ]
[ 5 6 ]
… and so on …

I used GPIO4_16 (pin 5). You need to connect GND and GPIO pin to relay’s control port. Polarity does not matter in this case. For port control you can use gpioctl utility. But first we need to identify this pin on FreeBSD’s side. For each GPIO bank FreeBSD has /dev/gpiocX device node, where X starts from zero. But it’s not uncommon for SoC vendors to start numbering GPIO banks from 1. riotboard’s vendor is one of them so GPIO4 is actually controlled through /dev/gpioc3. By default pin 16 is configured as input, so you need to change it to out:

# gpioctl -f /dev/gpioc3 -c 16 OUT

and then you can start giving orders to relay:

# gpioctl -f /dev/gpioc3 16 0
# gpioctl -f /dev/gpioc3 16 1
# gpioctl -f /dev/gpioc3 -t 16

Demo video:

Back from vacation and back to work. Once I got RIoTboard up and running next natural step was to wrap up some i.MX6 project I had in “almost finished” state for months. So now they’re in “going through review” state: drivers for HDMI framer and IPU. They add basic 1024×768 console for iMX6 board. Video mode management requires more sophisticated timers framework, that is being work on as a part of Jetson TK1 port.