Compiling a Sensor Watch firmware on FreeBSD
Context
As I wrote in that article, I am "testing" a bunch of watches, and started with the Sensor Watch / Casio F-91W, a board swap for the aforementioned famous watch.
You can also use the very good online Sensor Watch Builder, but hey, why not trying to make it work on FreeBSD? :-)
First steps
The excellent documentation gives clear instructions on how to build the firmware.
The page only lists Linux and MacOS, and not FreeBSD - but that's not gonna scare me.
Here are the simple steps you have to follow:
- clone the repo,
cd Sensor-Watch/movement/make
make COLOR=RED
(since I'm using a Sensor Watch Lite board).
I initially tried with make
but got plenty of errors.
The rest of the article will explain what I did to make it work - but before
that, for folks in a hurry, I have a TL;DR
version just below.
Making it work! - The TL;DR version
pkg install arm-none-eabi-binutils arm-none-eabi-newlib gcc-arm-embedded
export PATH=$PATH:/usr/local/gcc-arm-embedded/bin
gmake COLOR=RED
Making it work! - The complete version, with pain and sweat
The documentation specifies that you need to install the GNU ARM Embedded Toolchain.
A quick search in the FreeBSD packages yields a promising result:
# pkg search embedded
gcc-arm-embedded-10.3.20210921 Complete gcc-based toolcahin for embedded ARM development
Using gmake
worked better, but after a while I got:
gmake: arm-none-eabi-gcc: No such file or directory
gmake: *** [../../rules.mk:50: build/tusb.o] Error 127
Again, a pkg search eabi
yielded a few results, including one that looked spot
on:
arm-none-eabi-gcc-11.3.0_2 GNU Compiler Collection for bare metal arm cross-development
After yet another pkg install
and running gmake
again, I still encountered
issues:
/usr/local/bin/arm-none-eabi-ld: cannot find crt0.o: No such file or directory
collect2: error: ld returned 1 exit status
gmake: *** [../../rules.mk:27: build/watch.elf] Error 1
OK, let's look for arm-none
in the FreeBSD packages:
# pkg search arm-none
arm-none-eabi-binutils-2.40_4,1 GNU binary tools
arm-none-eabi-gcc-11.3.0_2 GNU Compiler Collection for bare metal arm cross-development
arm-none-eabi-newlib-2.4.0_2 Newlib distribution for arm-none-eabi targets
Right, the last one (arm-none-eabi-newlib-2.4.0_2
) looks interesting, let's
install it and run gmake
again - here's the result:
git submodule update --init
LD build/watch.elf
Memory region Used Size Region Size %age Used
bootloader: 0 GB 8 KB 0.00%
rom: 121556 B 240 KB 49.46%
eeprom: 0 GB 8 KB 0.00%
ram: 12576 B 32 KB 38.38%
OBJCOPY build/watch.hex
OBJCOPY build/watch.bin
UF2CONV build/watch.uf2
gmake: python3: No such file or directory
gmake: *** [../../rules.mk:39: build/watch.uf2] Error 127
Alright, it goes a bit further, but still an error about python3.
Installing python with pkg install python
fixed it:
# pkg install python
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 2 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
python: 3.9_3,2
python3: 3_3
Number of packages to be installed: 2
and finally:
√ make % gmake COLOR=RED
git submodule update --init
UF2CONV build/watch.uf2
Converting to uf2, output size: 247808, start address: 0x2000
Wrote 247808 bytes to build/watch.uf2
size:
text data bss dec hex filename
121556 2296 10280 134132 20bf4 build/watch.elf
121556 2296 10280 134132 20bf4 (TOTALS)
Youhou!! we have a build/watch.uf2
and indeed, when checking the build
directory, we can see a watch.uf2
file,
which is the one we'll need to upload to the watch:
-rw-r--r-- 1 nc user 247808 Feb 12 17:33 watch.uf2
Epilog
While trying to compile again with fewers watchfaces, I got the following:
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:432:9: error: unknown type name '__ssize_t'
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:433:9: error: unknown type name '__ssize_t'
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:449:25: error: unknown type name '__off_t'; did you mean '_off_t'?
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:453:1: error: unknown type name '__off_t'; did you mean '_off_t'?
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:453:21: error: unknown type name '__off_t'; did you mean '_off_t'?
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:457:46: error: unknown type name '__off_t'; did you mean '_off_t'?
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:461:33: error: unknown type name '__off_t'; did you mean '_off_t'?
/usr/local/lib/gcc/arm-none-eabi/11.3.0/include-fixed/stdio.h:545:25: error: expected ';' before 'typedef'
gmake: *** [../../rules.mk:50: build/tusb.o] Error 1
Damned! What went wrong? It worked before.
Well, it turns out that installing the arm-none-eabi-newlib
package was not a
good idea, as it conflicts with the arm-none-eabi-binutils
.
When looking a bit closer at the first error message I got:
% gmake COLOR=RED
git submodule update --init
CC build/tusb.o
gmake: arm-none-eabi-gcc: No such file or directory
gmake: *** [../../rules.mk:50: build/tusb.o] Error 127
It struck me that the arm-none-eabi-gcc
was actually the missing binary!
A search on the FreeBSD forums gave me that interesting
result:
this binary had actually been installed by the gcc-arm-embedded
package, and
could be found in /usr/local/gcc-arm-embedded/bin
:
√ ~ % ls -l /usr/local/gcc-arm-embedded/bin/ |grep gcc
-rwxr-xr-x 2 root wheel 1615624 Jan 8 03:21 arm-none-eabi-gcc
-rwxr-xr-x 2 root wheel 1615624 Jan 8 03:21 arm-none-eabi-gcc-10.3.1
-rwxr-xr-x 1 root wheel 29136 Jan 8 03:21 arm-none-eabi-gcc-ar
-rwxr-xr-x 1 root wheel 29136 Jan 8 03:21 arm-none-eabi-gcc-nm
-rwxr-xr-x 1 root wheel 29136 Jan 8 03:21 arm-none-eabi-gcc-ranlib
I added this directory to my path with this command:
export PATH=$PATH:/usr/local/gcc-arm-embedded/bin
then compiled again, and this time it succeeded!
So to recap, here are the packages needed:
# pkg version |grep -i arm
arm-none-eabi-binutils-2.40_4,1 >
gcc-arm-embedded-10.3.20210921 =
Customizing the watchfaces
By default, compiling Sensor Watch will give the default watchfaces.
As detailed in that
page,
if you want your own set of watchfaces, all you have to do is:
- edit the
movement/movement_config.h
file, - modify the below array with your liking,
- run
gmake COLOR=red
again.
Here's the default array:
const watch_face_t watch_faces[] = {
simple_clock_face,
world_clock_face,
sunrise_sunset_face,
moon_phase_face,
stopwatch_face,
preferences_face,
set_time_face,
thermistor_readout_face,
voltage_face
};
Here's the resulting watch.uf2
file:
-rw-r--r-- 1 nc user 217600 Feb 13 14:13 watch.uf2
and if I only select the simple clock face:
const watch_face_t watch_faces[] = {
simple_clock_face
};
Of course, the watch.uf2
file will be smaller:
-rw-r--r-- 1 nc user 170496 Feb 13 14:23 watch.uf2
Tags: FreeBSD