This repository contains Rust crates for developing firmware for the Hactar UI chip. It currently contains three primary crates:
ui-app
: The device-independent aspects of the UI chip logic- Tests that verify that this logic works as intended, given the right inputs.
- An enum of events that can be emitted by the hardware (basically, async inputs)
- An
Outputs
trait that captures the ways that the app can invoke hardware capabilities
ui-stm32
: Code to instantiate the app on the Hactar stm32f405 chip- An implementation of the traits in the
ui-app
crate based on the Hactar EV12 hardware platform. - An entry point function that instantiates the app and the board abstraction, and routes events from ISRs to the app.
- An implementation of the traits in the
ui-tauri
: Code to instantiate the app in a Tauri webview
The cortex-m-stack
crate contains some basic tools for measuring stack usage
on STM32, leveraging the stack painting feature in the cortex-m-rt
crate.
The cmox
directory contains crates that enable the use of the STM
Cryptographic library ("Cortex-M Optimized Crypto Stack"). Following the Rust
"sys-crate" pattern, it contains two crates:
cmox-sys
: A bindgen-generated unsafe API and logic to link the CMOX librarycmox
: A safe, idiomatic API to the functions exposed bycmox-sys
These libraries currently build successfully, including building and running tests on the UI chip. However, tests are currently failing due to some low-level issues.
The archive
directory contains some earlier attempts at getting Rust running
on Hactar, some parts of which may be useful for future development. See the
README in that directory for more details.
# Prerequisites for Tauri
> cargo install tauri-cli
# To run the Tauri app
> cd ui-tauri
> cargo tauri dev
... or ...
# Prerequisites for on-device build/test
> brew install probe-rs
> rustup target add thumbv7em-none-eabihf
# To run on an actual UI chip, via ST-LINK
> cd ui-stm32
# Connect ST-LINK to UI chip
> cargo run
The expected behavior is:
- Pushing the PTT (top) button should illuminate the green LED
- Pushing the AI (bottom) button should illuminate the blue LED
- If both buttons are pushed at the same time, the LED should be cyan
To build / test the CMOX library, you will also need:
When you build / test the CMOX library, you will need to set environment
variables that indicate the location of these libraries. The ARM_STDLIB_PATH
environment variable needs to point to the directory that holds headers such as
stdint.h
. The CMOX_PATH
environment variable needs to point to the
directory that has CMOX headers under include
and binaries under lib
(within
the Middlewares
directory of the distribution bindle). If you provide these
on the command line you'll end up with something like the following:
ARM_STDLIB_PATH=<path to directory with ARM stdlib headers> \
CMOX_PATH=<path to STMCryptographic library and headers> \
cargo test -F stm32f4 --test self-test
What logic is implemented right now? Right now, the logic that is implemented is that the top (PTT) button activates the green LED and the bottom (AI) button activates the blue LED.
What external dependencies does the device firmware have? The primary external dependencies are:
- The stm32f4xx-hal HAL, which provides a clean, safe interface to the hardware with minimal overhead relative to bare register access.
- The cortex-m and cortex-m-rt crates, which provide the low-level structure for the program.
- The heapless and panic-halt crates for some simple utilities.
What if we want to reduce those dependencies? We re-write the relevent bits
by hand. The heapless
and panic-halt
dependencies are fairly small and
easily replaced by hand. The structure provided by the cortex-m
and
cortex-m-rt
crates is largely what is done in startup.rs
in the legacy
bare-rust
code. The largest problem would be the HAL -- we could build this
bottom-up (as bare-rust
attempts) or fork it and strip it down to only what we
need. I would probably tend toward the latter.
If we want to change out the stm32f405 for another processor, how do we do
that? We would create another instantiation crate that would map the new
processor to the needs of the app. Just like with the current ui-stm32
and
ui-laptop
crates.
How do we accommodate variations between iterations of the device? The
precise configuration of the EV12 board is almost entirely captured in the file
ev12.rs
. The only elements that leak outside that are ISR definitions, which
are short. To support EV13 and beyond, we can make a parallel ev13.rs
; its
use and any ISR adaptations should be easy to switch using cargo features.
- UART+DMA connectivity to the MGMT chip
- UART+DMA connectivity to the NET chip
- SPI+DMA connectivity to the screen
- GPIO scanning of the keyboard
- I2C+I2S connectivity to the audio chip
- Support for the EV13 board
- On-device testing using defmt-test or embedded-test crates
- Stack measurement using stack painting or SP instrumentation
- Use flip-link to protect against stack overflow
- More application functionality...