The Signaloid C0-microSD is an FPGA system-on-module (SoM) that sets itself apart from others in the field with the fact that it fits in a microSD slot. Since the FPGA fabric is connected to the standard microSD pins, it can present as a "normal" SD card, and even be dynamically reconfigured with different images. In practice, these are typically custom FPGA bitstreams, or the pre-loaded RISC-V-based SoC. The latter can be used to run custom RISC-V applications, which can even communicate with the host, resulting in some interesting hardware combinations, such as this mashup with the M5Stack Cardputer. Setting up the toolchain to build SoC apps can be a fairly complicated process, which we will try to ameliorate with this guide.
Getting Started ๐ฐ ๐ฉโ๐ปThe easiest way to get the required RISC-V GNU compiler toolchain up and running is by downloading a pre-compiled binary from Releases on GitHub. However, I found out the hard way that the supplied binaries do not fully support the SoC's functionality, and after submitting an issue about it, the Signaloid documentation was updated to recommend users build the toolchain from source. This is a time-consuming, but relatively straightforward process if everything goes well. I'm using Ubuntu, and I would recommend that Windows users use Ubuntu as well via WSL; macOS users will need to adjust accordingly, e.g. brew
in place of apt-get
as well as installing gcc-mp-13
and g++-mp-13
using sudo port install gcc13
(plus export CXX=g++-mp-13 CC=gcc-mp-13
).
An important step that Signaloid's own docs completely gloss over is the need to install prerequisites, so we'll do that first:
sudo apt-get update
sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip python3-tomli libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev
You may already have some or most of these tools installed, but apt
is a clever package manager and will only add what's lacking, so it's ok to make greedy requests.
Next, recursively clone the toolchain source:
git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain.git
The repository is large; the release tarballs are hundreds of MBs after xz
compression, so now might be a good time to grab a snack or beverage (why not both!). You'll want to ensure you have a couple dozen GB available on your machine, between the repo, the required tools, and the resulting binaries.
Change directory to wherever you cloned the repo, and configure the installation as follows:
cd riscv-gnu-toolchain
./configure --prefix=CHANGETHIS --with-arch=rv32i --with-abi=ilp32 --disable-gdb
The placeholder CHANGETHIS
should be changed to the path where you would like it to be installed, e.g. I chose /opt/riscv
(actually, I chose /opt/riscv-15.1.0
so that I could easily switch between this and my /opt/riscv-14.2.0
installation by re-pointing /opt/riscv
accordingly).
Now, it's time to build:
make -j4
The -j4
parameter indicates the use of four parallel workers โ feel free to adjust or omit this as preferred; you may also need to use sudo
depending on your access to the path specified in --prefix
earlier. Even parallelized, this process takes an extremely long time. I was able to walk to a restaurant, wait for carry-out, and eat it before the build completed.
Once it is done, you can confirm its success by checking the version of the resultant gcc binary:
riscv32-unknown-elf-gcc -v
the result should be something like the following (paths, versions etc. will vary):
Using built-in specs.
COLLECT_GCC=riscv32-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/opt/riscv/bin/../libexec/gcc/riscv32-unknown-elf/15.1.0/lto-wrapper
Target: riscv32-unknown-elf
Configured with: /home/ishotjr/bin/riscv-gnu-toolchain/gcc/configure --target=riscv32-unknown-elf --prefix=/path/to/installation/dir --disable-shared --disable-threads --disable-tls --enable-languages=c,c++ --with-system-zlib --with-newlib --with-sysroot=/path/to/installation/dir/riscv32-unknown-elf --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --disable-multilib --with-abi=ilp32 --with-arch=rv32i --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 15.1.0 (GCC)
At this point, you are ready to build Signaloid C0-microSD SoC applications! ๐
Building the SoC Application ๐ช ๐ปThe easiest place to start is with the signaloid-soc-examples
in Signaloid's C0-microSD-hardware repo. Clone it recursively:
git clone --recursive git@github.com:signaloid/C0-microSD-hardware.git
cd C0-microSD-hardware
and then update the Makefile
for breathe-led
to reflect your toolchain installation path and where the device can be found (after plugging the C0-microSD into your computer's SD drive or an adapter) using the text editor of your choice:
cd ~C0-microSD-hardware
cd signaloid-soc-examples
cd breathe-led
code Makefile
for me these values are:
TOOLCHAIN = /opt/riscv
DEVICE = /dev/sda
Note that DEVICE
can change often depending on what else you have attached to your computer, so you may find yourself having to update the Makefile
. You can identify the C0-microSD by using lsblk
to look for a device around ~20MB.
Navigate to the breathe-led
directory as above if you're not still there, and run make
. This will result in the creation of main.bin
, which is a binary that you can flash and execute on the C0-microSD. ๐๐
The C0-microSD must be in bootloader mode in order to flash the binary application. The Makefile
comes with handy tools to facilitate this. Bootloader mode is indicated by the red LED being lit solidly. If this is not currently the case, use make switch
to switch to bootloader mode.
For bootloader mode to actually take effect, the board must be power-cycled, so remove and re-insert it. There is a reminder in the resultant output, but it takes a while to get used to the process and make it a habit.
make switch
sudo python3 ../../submodules/C0-microSD-utilities/C0_microSD_toolkit.py -t /dev/sda -s
Signaloid C0-microSD | Loaded configuration: Signaloid SoC | Version: 1.0 | State IDLE
Switching device boot mode from Signaloid SoC to Bootloader...
Device configured successfully. Power cycle the device to boot in new mode.
Done.
Now that the device is in bootloader mode (solid red LED) you can use make flash
to write the binary to the device. If you're curious to learn more about what these commands are doing, you can look for flash:
and switch: in the Makefile
, or just observe their output as they run:
make flash
sudo python3 ../../submodules/C0-microSD-utilities/C0_microSD_toolkit.py -t /dev/sda -b main.bin -u -p 128K
Signaloid C0-microSD | Loaded configuration: Bootloader | Version: 1.0 | State IDLE
Filename: main.bin
File size: 176 bytes.
Input file padded to 131072 bytes.
Flashing user data bitstream...
Attempt 1 of 5: Flashing... Verifying...
Success: The data matches.
Done.
You can see the C0_microSD_toolkit.py
tool in action along with various parameters; for more details on using it directly, check out the C0-microSD-utilities repo on GitHub.
Since we're still in bootloader mode, we need to run make switch
again and power-cycle the device to return to SoC mode. This is indicated by a solid green LED:
Because of the particular application that we've chosen, you should also see the red LED begin to "breathe" (ramp up and down in intensity). Congratulations on building and running your first SoC application! ๐๐๐
Results and Conclusions โ๏ธ ๐The breathe-led
example is practically a "blink"/"Hello World" for the C0-microSD; the possibilities from here are almost limitless. Check out the docs and examples for more inspiration, and be sure to check out the Cardputer demo while you're at it. ๐๐ญโจ๏ธโจ
In addition to its RISC-V SoC capabilities, the C0-microSD can function as an FPGA System-on-Module (SoM), offering virtually limitless hardware possibilities. Check out the FPGA docs for more information. You can also use the C0-microSD to build binaries from GitHub repos using Signaloid's cloud; check out the repo's README
and API Utilities docs for details. Whichever path you choose, let me know about it in the comments, and feel free to reach out if you run into issues along the way! ๐ค๐
Comments