Rblhost
This is a concept implementation of the blhost tool in Rust programming language. It includes McuBoot implementation, similar to the one in spsdk, together with spsdk-like Python bindings using pyo3 crate.
Features
- UART communication with configurable baudrate and timeout
- I2C communication with configurable slave address
- Command-line interface compatible with the original blhost tool
- Python bindings for integration with other tools
- C/C++ bindings
Documentation
- API Documentation: docs.rs/rblhost
- Examples: See the examples folder for usage examples
Changelog
Version 0.2.0
- Added support for
flash-imagecommand with S-record format parsing - Implemented S-record file format support in image parser
- Fixed stub files for Python bindings
Performance Benchmark
The Rust implementation offers performance improvements compared to both the Python SPSDK implementation and the original C/C++ blhost tool.
Benchmark performed on MacBook Air M2 comparing rblhost with SPSDK blhost and C/C++ blhost 2.6.7. Benchmark measures get-property 1 command execution time with MCXN236 board and 57600 baud rate. Resulting time is in miliseconds.
Key performance highlights:
- Faster startup time compared to both Python and C++ implementations
- Improved command execution speed
- Native performance with the convenience of Python bindings
Installation
Prerequisites
- Rust toolchain
- For Python bindings: Python 3.8+ with development headers
- libudev-dev package (for Linux)
Building from Source
Clone the repository and cd into it:
Refer to sections below to build bindings or the CLI tool.
Building CLI tool
Build the CLI tool:
The binary will be available at target/release/rblhost. For example usage of the library, look in examples folder.
Building Python bindings
- Create and activate a virtual environment.
- Build rblhost with Python bindings
- Install
pymbootinto the virtual environment- Normal installation
- Development installation:
- Normal installation
For examples on how to use Python bindings, look into examples folder.
Building C bindings
Note: Compiling together python and c_api features/bindings may result in malfunctioning libraries.
Prerequisites:
- Rust toolchain (rustc, cargo)
- C compiler (gcc, clang)
- For Linux: libudev-dev package
- For macOS: Xcode command line tools
- Run the following to build C bindings:
- This build process will:
- Compile the Rust library
- Generate C header files (compatible with C++) using cbindgen
- Create the shared library
- Output files are:
- Library:
- Linux:
target/release/libmboot.so - macOS:
target/release/libmboot.dylib - Windows:
target/release/mboot.dll
- Linux:
- Header file:
include/mboot.h
- Library:
For more information about the bindings, refer to C Bindings section. For examples on how to use C bindings and an example CMakeLists.txt file, look into examples folder.
System-specific Requirements
Linux
- For UART: No additional requirements
- For I2C: The i2c-dev kernel module must be loaded
Windows
- For UART: No additional requirements
- I2C communication is not supported on Windows
macOS
- For UART: No additional requirements
- I2C communication is not supported on macOS
CLI Usage
Basic Command Structure
rblhost [OPTIONS] -- COMMAND [ARGS]...
Communication Options
UART Connection
rblhost -p <port>[,<baudrate>] [OPTIONS] -- COMMAND [ARGS]...
<port>: Serial port name (e.g., COM3, /dev/ttyUSB0)<baudrate>: Optional baudrate (default: 57600)
Example:
rblhost -p COM3,115200 -- reset
I2C Connection
Basic information:
- Uses the Linux I2C device interface (
/dev/i2c-X) - Supports specifying a slave address or uses the default (0x10)
- Follows the same packet protocol as UART communication
- Requires the i2c-dev kernel module to be loaded on Linux systems (refer to System-specific Requirements)
rblhost --i2c <device>:<slave_address> [OPTIONS] -- COMMAND [ARGS]...
<device>: I2C device path in/dev/i2c-Xformat, whereXis the I2C bus number<slave_address>: Optional slave address in hex format (e.g.,0x3A), default is0x10
Example:
rblhost --i2c /dev/i2c-1:0x3A -- reset
Common Options
-t, --timeout <MILLISECONDS>: Serial read timeout in milliseconds (default: 5000)-s, --silent: Suppress status response and response words-v, --verbose: Increase verbosity level (can be used multiple times)
Example with timeout:
rblhost -p COM3 -t 10000 -- flash-erase-all
Available Commands
get-property: Queries various bootloader properties and settingsreset: Reset the deviceexecute: Jumps to code at the provided addresscall: Invokes code at an address, passing an argument to itflash-erase-all: Perform an erase of the entire flash memoryfill-memory: Fills the memory with a patternread-memory: Reads the memory and writes it to a file or stdoutset-property: Changes properties and options in the bootloaderconfigure-memory: Sets a config at internal memory to memory with IDflash-erase-all-unsecure: Erase Complete Flash and Unlockflash-erase-region: Erases one or more sectors of the flash memorywrite-memory: Write memory from a file or CLIfuse-program: Program fusefuse-read: Reads the fuse and writes it to the file or stdoutreceive-sb-file: Receives a file in a Secure Binary (SB) formatflash-read-once: Read from MCU flash program once region (eFuse/OTP)flash-program-once: Write into MCU program once region (eFuse/OTP)trust-provisioning: Group of subcommands related to trust provisioningkey-provisioning: Group of subcommands related to key provisioningload-image: Sends a boot image file to the device
MBoot C Bindings
The MCU Boot library provides a C API that allows C/C++ applications to communicate with MCU bootloaders. The API provides functions for:
- Connecting to MCU bootloaders over UART
- Reading and writing memory
- Getting device properties
- Executing commands on the device
Including the Library
-
Include the header file in your C code:
-
Compile your C program with the library:
# Linux/macOS # WindowsYou can also use cmake example in examples.
Look into the generated header to see all currently available functions.
Error Handling
The API functions return integer status codes:
0: Success-1: Invalid parameters (null pointers)-2: Invalid property tag-3: Communication error
All of these errors are specified as macros in the generated header. It's also possible to use mbot_get_status_text function to get a text description of the error during runtime.
Memory Management
All functions containing Allocations section in their documentation allocate data on heap, which must be later freed.
Thread Safety
The MCU Boot C API is not thread-safe. Do not use the same MBOOT_CMcuBoot instance from multiple threads simultaneously.
Troubleshooting
Library Not Found
If you get a "library not found" error when running your program:
-
Linux: Set the
LD_LIBRARY_PATHenvironment variable: -
macOS: Set the
DYLD_LIBRARY_PATHenvironment variable: -
Windows: Add the library directory to your PATH or copy the DLL to the same directory as your executable.
Linking Errors
If you get undefined symbol errors when linking:
- Make sure you're using the correct library name (
-lmboot) - Check that the library path is correct (
-L./target/release) - Verify that the library was built successfully
- "Undefined reference to Py*" -- Build the library with only the
c_apifeature, like shown here:
License
This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.
Missing and unimplemented features
- Implement all of
blhostandMcuBootcommands - Add doc comments to everything This could be enforced by using lints in rustdoc.
- Implement missing python bindings
- Address all TODO and FIXME comments
- Add different texts for different board families
- Refactor and optimize the code
State of work
This table compares the commands available in rblhost (Rust implementation) with the original blhost (C implementation), and indicates which commands are supported in the Python bindings.
| Command | rblhost | blhost | Python Bindings | C Bindings |
|---|---|---|---|---|
| reset | ✅ | ✅ | ✅ | ❌ |
| get-property | ✅ | ✅ | ✅ | ✅ |
| set-property | ✅ | ✅ | ✅ | ❌ |
| flash-erase-region | ✅ | ✅ | ✅ | ❌ |
| flash-erase-all | ✅ | ✅ | ✅ | ✅ |
| flash-erase-all-unsecure | ✅ | ✅ | ✅ | ❌ |
| read-memory | ✅ | ✅ | ✅ | ✅ |
| write-memory | ✅ | ✅ | ✅ | ✅ |
| fill-memory | ✅ | ✅ | ✅ | ❌ |
| receive-sb-file | ✅ | ✅ | ✅ | ✅ |
| execute | ✅ | ✅ | ✅ | ❌ |
| call | ✅ | ✅ | ✅ | ❌ |
| flash-security-disable | ❌ | ✅ | ❌ | ❌ |
| flash-program-once | ✅ | ✅ | ✅ | ✅ |
| flash-read-once | ✅ | ✅ | ✅ | ✅ |
| efuse-program-once | ❌ | ✅ | ❌ | ❌ |
| efuse-read-once | ❌ | ✅ | ❌ | ❌ |
| flash-read-resource | ❌ | ✅ | ❌ | ❌ |
| configure-memory | ✅ | ✅ | ✅ | ❌ |
| flash-image | ✅ | ✅ | ❌ | ❌ |
| reliable-update | ❌ | ✅ | ❌ | ❌ |
| generate-key-blob | ❌ | ✅ | ❌ | ❌ |
| key-provisioning | ✅ | ✅ | ✅ | ❌ |
| load-image | ✅ | ✅ | ✅ | ❌ |
| program-aeskey | ❌ | ✅ | ❌ | ❌ |
| fuse-program | ✅ | ❌ | ✅ | ❌ |
| fuse-read | ✅ | ❌ | ✅ | ❌ |
| trust-provisioning | ✅ | ❌ | ✅ | ❌ |