-
Installing a Rust toolchain
7 days ago • 0 commentsThis log will be amended as I fill in details that I may have missed.
Your OS may have Rust available in their package repositories. But due to the rapid pace of development it's best to install a Rust toolchain outside of the package system. Rust developers have streamlined this task.
You need two important programs: rustup which is a toolchain installer (and maintainer), and cargo, installed by rustup, which is a project manager. The other programs like rustc, the compiler, will be installed by rustup.
Before you install rustup, you need to decide if you accept the standard location for the software, in the case of Linux, under your home directory in ~/.cargo, as explained here. If like me, you dislike lots of package files under home (unfortunately this is the norm these days with Arduino, PlatformIO, etc. etc.), you can change the directories. There are two environment variables, and I've set them thus:
export RUSTUP_HOME=/usr/local/lib/rustup CARGO_HOME=/usr/local/lib/cargo
If you choose to change them, edif your ~/.bash_profile to export these environment variables. Also put this command in ~/.bash_profile after so that the correct executables are found.
. "$CARGO_HOME/env"Logout and login again if necessary to ensure that these settings are in place before you install rustup following the instructions at the website.
The help text for rustup indicates what it does:
$ rustup --help rustup 1.29.0 (28d1352db 2026-03-05) The Rust toolchain installer Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND] Commands: install Install or update the given toolchains, or by default the active toolchain uninstall Uninstall the given toolchains toolchain Install, uninstall, or list toolchains default Set the default toolchain show Show the active and installed toolchains or profiles update Update Rust toolchains and rustup check Check for updates to Rust toolchains and rustup target Modify a toolchain's supported targets component Modify a toolchain's installed components override Modify toolchain overrides for directories run Run a command with an environment configured for a given toolchain which Display which binary will be run for a given command doc Open the documentation for the current toolchain man View the man page for a given command self Modify the rustup installation set Alter rustup settings completions Generate tab-completion scripts for your shell help Print this message or the help of the given subcommand(s) Arguments: [+toolchain] Release channel (e.g. +stable) or custom toolchain to set override Options: -v, --verbose Set log level to 'DEBUG' if 'RUSTUP_LOG' is unset -q, --quiet Disable progress output, set log level to 'WARN' if 'RUSTUP_LOG' is unset -h, --help Print help -V, --version Print version Discussion: Rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated. It makes cross-compiling simpler with binary builds of the standard library for common platforms. If you are new to Rust consider running `rustup doc --book` to learn Rust. Common commands: Update Rust toolchains and rustup $ rustup update Install the current stable release of Rust for your host platform $ rustup toolchain install stableToolchain means a release channel, e.g. default, nightly. If you are thinking about MCU targets, then the term is target.
Here's a relevant fact: gcc requires a different toolchain for each MCU family. That's why the toolchain for the classic Arduino starts with avr-, that for the STM32 starts with arm-, and for the WCH32V series riscv-. LLVM however uses the same compiler for all targets, and you can install a new target without installing another compiler. Here are the targets I have installed:
$ rustup target list | grep installed riscv32i-unknown-none-elf (installed) thumbv6m-none-eabi (installed) x86_64-unknown-linux-gnu (installed)Riscv32i is for the WCH32V MCUs, thumbv6m is for the RP2040, and x86_64 is for my Linux workhorse.
Now we come to cargo. This is a project manager which allows you to manage all aspects of a project, initialising the project directory structure, installing dependencies, building binaries, running them, debugging them, installing them, and so forth. It's modelled after the successful Ruby on Rails tool rails which triggered similar programs for other development environments, like gradle for Groovy (java). Here is the help text for cargo which gives you an idea of what it does:
$ cargo --help Rust's package manager Usage: cargo [+toolchain] [OPTIONS] [COMMAND] cargo [+toolchain] [OPTIONS] -Zscript <MANIFEST_RS> [ARGS]... Options: -V, --version Print version info and exit --list List installed commands --explain <CODE> Provide a detailed explanation of a rustc error message -v, --verbose... Use verbose output (-vv very verbose/build.rs output) -q, --quiet Do not print cargo log messages --color <WHEN> Coloring [possible values: auto, always, never] -C <DIRECTORY> Change to DIRECTORY before doing anything (nightly-only) --locked Assert that `Cargo.lock` will remain unchanged --offline Run without accessing the network --frozen Equivalent to specifying both --locked and --offline --config <KEY=VALUE|PATH> Override a configuration value -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details -h, --help Print help Commands: build, b Compile the current package check, c Analyze the current package and report errors, but don't build object files clean Remove the target directory doc, d Build this package's and its dependencies' documentation new Create a new cargo package init Create a new cargo package in an existing directory add Add dependencies to a manifest file remove Remove dependencies from a manifest file run, r Run a binary or example of the local package test, t Run the tests bench Run the benchmarks update Update dependencies listed in Cargo.lock search Search registry for crates publish Package and upload this package to the registry install Install a Rust binary uninstall Uninstall a Rust binary ... See all commands with --list See 'cargo help <command>' for more information on a specific command.If you're thinking what does package have to do with my project, your project is a package too, and cargo is how you manage it. Crate is the Rust term for a standard package.
Fun fact: Look at the executables in $CARGO_HOME/bin. You'll see that a lot of them are just links to rustup, including cargo and rustc. Rustup is a chameleon program, playing different roles depending on how it's invoked.
(To be continued)
-
Toolchains
06/17/2026 at 02:34 • 0 comments![]()
Microcontrollers need firmware and toolchains used to develop them. This is an overview and will undergo revision as I will no doubt overlook some concepts at the time of writing.
Assemblers
Unless you have one of those educational kits where you toggle switches (or the equivalent thereof) to program the hardware, it's assumed the basic requirement is an assembler which will take assembly code and turn it into bits to be loaded into the MCU.
This is the case for the 8048/8042 MCUs I have mentioned. The toolchain is the ASxxxx cross assembler and linker. The MCU is too weak to support a HLL like C. Wikipedia claims that a PL/M compiler existed for the 8048 but I am dubious because the architecture is severely limited.
Compilers
I consider the basic requirement for a MCU toolchain to be a C compiler toolchain. This true of all the MCUs I have used from the 8051 onwards, although early PIC models had very restrictive architectures like for example a two-level stack which forces one to flatten out function calls.
CLI Development Environments
The first step up from a compiler is something to automate the repeated steps of a embedded app edit and build. You could do it with scripts, but I started off with a text editor and a Makefile which is very familiar from the desktop Linux environment..
This can be elaborated with any number of improved build tools like CMake, meson + ninja, etc.
It's worthwhile retaining CLI build facilities even if one is using an IDE, to have a reproducible means of creating production artifacts.
Integrated Development Environments
A great boon of a GUI IDE is multiple views. In one window you could be editing source code, another could be a command window, and of course you could have output and debugging windows. When editing, the IDE can help the programmer by suggesting completions for library calls, sparing having to look up the programming manual.
Many of IDEs are front-ends to traditional CLI programs, simply because that's how the tools are invoked. For example, when you use the Arduino IDE, possibly the best known, you can see the compile commands launched in response to firing off a build. Some IDEs like the Microchip MPLAB X even generate Makefiles to control the build process.
IDEs can be specific to a platform, e.g. Window, or could be cross-platform. The preference these days is for cross-platform IDEs to capture a large audience. Traditionally cross-platform IDEs relied technology like Java e.g. in the form of the Eclipse platform. Many IDEs, for example Moun River are based on this. But these days cross-platform GUI toolkits are not a big deal, so an IDE like Arduino has support for the main OSes. Java GUIs these days look square and quaint.
IDEs can also be multi-target. Arduino started off supporting the AVR MCUs, but these days the Espressif, ARM, and RISC-V MCUs are transparently supported. The compiler toolchains moved from the Arduino application package to optional library packages.
But one great aid that IDEs provide is configuration for multiple models of MCUs. Unlike desktop CPUs where generations of processors can be accomodated in the kernel and runtime libraries, and it's all hidden from you, a Linux app works the same whether you are using a 10 year-old processor, or this year's, MCUs come in a huge variety of models targeted for various fields, e.g. consumer, automotive, instrumentation, with differences in peripherals. It's expensive and unnecessary to make embedded programs work on many models, so builds are configured for just the intended target. You can see this in the Arduino IDE where you have to select the board you are working with.
![]()
This customisation is extensive in IDEs like the ARM CubeMX IDE for STMicro's line of STM32 processors. A separate GUI program takes you through the selection of the company's MCU models and generates a configuration file which is used to influence build configuration.
![]()
Another dimension of IDEs is proprietary vs generic. Configurable IDEs like Codium, which is a general-purpose development environment, can also support embedded development using frameworks like PlatformIO.
Other Language Environments
Some development environments are based on a particular programming language, e.g. MicroPython, Lua, Forth, Rust. These will impose their own requirements on the development tools.
Hardware Adaptation Layer
Taking things further, a toolchain can present a higher level view of a hardware peripheral to the programmer. Instead of dealing with peripheral registers, constants, bit positions and so forth, the interface provides a resource with functions = operations on it. This fits well with an object-oriented view of resources, with instances, and lifecycle, of objects representing the peripheral. For example a Real Time Clock class can be used to represent many instances of RTC chips, and expose operations such as initialisation, setting the time, reading the time, setting and reacting to alarms. This is impetus to support C++ say by using the g++ compiler in the GCC tools. This is the reason that when GCC is not supported but SDCC is for a MCU like the 8051 family, the libraries cannot support OO features.
Sometimes the HAL imposes limitations. The paradigm of a setup() routine and a loop() routine in Arduino sketches differs from the familar pattern of a C or C++ main() as the start point of a program.
Standardised file hierarchy
Often the toolchain will impose a particular hierarchy for the files and resources for a build. A typical structure might be:
root source libraries resources (e.g. sound files, icons) build documentationbuild is where the results end up. It might be further split into debugging and production folders.
Often the structure is based on an existing layout, such as the one popularised by Ruby on Rails. There using the rails tool, one can create a project, populate it with a standard template, and then various operations are immediately available for building and testing. The Rust cargo tool works like this. Other IDEs have their preferred folder structure.
Downloading the executable to the MCU
About the only thing that can certainly be said is that there is no standardised way of doing this. Back in the days of the 8048s and 8051s you might program an UV-EPROM version of the MCU, or use an external (E)EPROM to test the executable. You usually needed an (E)EPROM programmer for this.
Then MCUs acquired flash memory, which obsoleted (E)EPROMs and shortened the develop/test cycle. Next manufacturers starting putting bootloaders in a read-only part of the flash memory. The bootloader might use serial interface pins to receive the download from a desktop computer. This was the case for the STC89C52 I used. Sometimes you needed a special dongle (in many cases containing another MCU) for the download. This was the case for the STM8 and STM32 families. These dongles could also be used for debugging, to single-step the processor through instructions, and show the state of internal registers and RAM. Some MCU families had a proprietary trap where you had to buy a specific dongle, like the Nuvoton 8051 family MCUs. It could make development expensive.
MCU development boards that could receive their programs via the USB interface started appearing. This allowed a single interface to provide power and data. And to be sure, many of the MCUs programmed by a serial port relied on a USB to serial interface chip.
The MCU can also act as a USB peripheral and respond to USB commands instead of emulating a serial interface device.
Since USB devices can also be storage devices, MCUs like the RP2040 were designed to look like a USB fiash drive to the desktop host, and you downloaded a program by coping a executable file into the storage area.
WiFi capable MCUs have not surprisingly acquired the ability of OTA (Over The Air) downloading. Very useful if the MCU is inside equipment; you don't have to open the case to connect downloading cables.
AI
Recent IDEs include support for AI assistance. I'm not going there in this overview. No doubt somebody else can.
An Abundance of Choice
All this means one is spoilt for choice where toolchains are concerned. Often constraints such as MCU model and memory will lead to particular tools.
My preference is to use whatever is most suitable and convenient for my project. I have no qualms switching to a different tool if it makes life easier.
It's very difficult to provide specific recommendation in a general overview log such as this. When I discuss the development board I'll be using, things will get more concrete.
-
Which 32-bit MCU family should I pick?
05/27/2026 at 14:55 • 2 comments![]()
My early attempt at a 32-bit CPU. No, just kidding.
Having decided to move on from the MCUs I am using, now that 32-bit MCUs are cheap commodities what are the candidates?
Before that, one advantage is clear: going to 32-bit gets decent HLL support. You can have a gcc/g++ toolchain, or one based on the up and coming rival, LLVM. You can also have other languages like Rust.
ARM
ARM is everywhere. A lot of hobbyists got introduced to ARM via Raspberry Pi. But the range extends from small MCU boards like the STM32 Blue Pill, to smartphones and tablets, to desktops, and to 64-bit servers in the datacentres. The PlasticARM project put a minimal Cortex-M0 on a flexible substrate, providing more areas for IoT to colonise.
ARM will be around for a long time. It should be noted here that the core architecture is licensed but the MCU chip manufacturer has absorbed that cost for you.
In practical terms, I could develop with the STM32 family or the RP series. I probably will for high performance uses.
RISC-V
RISC-V is an open architecture, there is no licensing to deploy it, so it has become attractive to chip makers as an alternative to ARM. I have a GigaDevice 32V dev board, but it's really the WCH series of 32V chips that are challenging the low-end uses of ARM. This makes them attractive to me.
Xtensa
Xtensa is the MCU architecture that Espressif Systems used in their popular series of WiFi and Bluetooth capable modules, such as the ESP8266 and ESP32. It's very popular due to the wireless capabilities, just look at the number of projects on Hackaday. I have several Espressif modules that badly need a few round tuits from me, so I will also develop with these.
But here's the rub: Espressif is shifting their product lines to RISC-V cores. The Xtensa based MCUs will be around for a while, if only because there's so much stock around.
Also the RP2350 has an interesting design: two ARM cores and two RISC-V cores, the first use of RISC-V in the RP series.
Which will it be?
Actually, with a good toolchain, I don't have to stick exclusively to one family. I'll just let the project, the available MCUs, and my wallet provide the decision parameters. More about toolchains in another log.
-
My personal history with MCUs
05/25/2026 at 11:26 • 0 comments![]()
This project #Restoring a Beckman neon display clock is what got me started on MCUs several years ago. It contained an 8048 family MCU and I wrote code to replace the original firmware. I managed to live within the limitations of assembly language, 1kB code space, 64B RAM, and 13 I/O pins, several lost to using external ROM. Definitely no high level language.
As it turned out I had quite a few of the 8048 family, and the related 8041/2 family chips in my junk box. I think the '48s came from full height 5¼ inch floppy drives, and the '42s came from PC keyboard controllers. I put them to use in projects like #8042 clock #8042 metronome and 8048 clock. No that last link is not a mistake, the instruction set is almost the same for the '48 and the '42 so the code is usable for both.
Well that was a good way to use up those chips. I have to say there are quite hardy and resisted many accidents. But boy were they power hogs.
![]()
As we know Intel came out with the 8051, the successor to the 8048. The breakthrough improvement was putting peripherals in the I/O address space rather than having specific instructions for each I/O port. The '51 has gone on to be probably the most durable MCU family and descendants live on as programmable cores for many chips.
It actually is a fairly decent MCU to learn on. The hardware and instruction set are easy to understand and there is even C language support in the form of the GPL Small Device C Compiler (SDCC) and commercial offerings. Descendants have increased the clock rate to be tens of times faster than the original. Some are one-chip wonders only needing a handful of passives for a working system like this. The one above is a STC89C52 workalike for the 8052 with flash ROM for code, but otherwise a drop-in equivalent, used in #89C52 clock board. I used this dev board with them: #Adventures with a STC89C52 development board. Other projects using a '51 include #Ancient 12 hour display and #Modularnixie.
But ultimately, it's an 8-bit MCU with all the attendant limitations. (Some expanded architectures like the '251 were developed.) So I used up the handful of MCUs and dev boards I bought and bade them farewell.
![]()
Next cab off the rank was the STM8 which I got interested in thanks to #eForth for cheap STM8S gadgets. They appear in the millions if not billions in small gadgets. You probably have a few around the house. (An interesting development was that 8051 derivatives started to muscle in on the STM8 based gadgets by coming out with pin (but not architecture) compatible models, presumably because the '51 core architecture was free to reimplement.) Modules are readily available from AliExpress and the per MCU price was between 10 and 20¢, although it was a while before my SMD soldering skills were up to doing TSSOP-20.
This has a decent architecture and is also well supported by SDCC. It has a good selection of on-chip peripherals including standards like I2C which wasn't in the '51 descendants until well into its reign. The GPIO pins can do true bidirectional and true push-pull in addition to other modes like hi-Z and open drain, unlike the 8051's weak pullup. The HAL takes a bit of getting used to but it is worth it.
I liked this MCU and used it in #Repurposing an old nixie thermometer, #Third life for a radio alarm clock, and the driver for #Vertical LED digit display boards. I still have a few chips but won't be starting any new projects with them.
![]()
The AVR family is represented by the Arduino models I have. Strangely I haven't done any projects with them because I think of them as test equipment which I used frequently, as a driver in the above photo. One drawback is that they have 5 V GPIO which means I have to turn to the ESP32 Arduino lookalikes that work with 3.3 V logic.
I did have a couple of early DIP AVR chips for which I managed to nut out the details of to use in this project, and this project. The architecture is decent, it manages to get gcc support but it's still basically an 8-bit MCU.
![]()
A couple of ancient PIC MCUs in my junk box caused me to look for projects to use them in, but ultimately I decided this family wasn't worth getting involved with. I know that the family is very broad and there are many models specialised for niches, but somehow I can't bring myself to like them.
To finish off
I should mention some CPU families that I have. CPUs are more trouble to use in projects than MCUs because you have to add peripheral chips to make them useful which adds to parts count and board space. And besides, I am not nostalgic about retro boxes. If I want to have the feel of CP/M or DOS, I can fire up an emulator.
I have 8085s and Z80s which I have developed SBCs for but haven't tested yet. Similarly many 8088s. I may need a few round tuits to proceed with them.
I was tempted to delve into the 6502 family as I have memories of the KIM-1, but I don't actually have any CPU chips. I was tempted to dip my toes with the WDC 65C816 which I like the look of, but decided not to go there.
I had some 68000 CPUs but gave them away to not have to ponder what to do with them.
In a following log I will describe the current 32-bit MCUs I have and how I hope to use them.
Ken Yap







