Change Location EUR
 
Mouser Europe - Flag Mouser Europe

Incoterms: DDP is available to customers in EU Member States.
All prices include duty and customs fees on select shipping methods.

Incoterms: DDU applies to most non-EU customers.
Duty, customs fees and taxes are collected at time of delivery.


Please confirm your currency selection:

Euros
Euros are accepted for payment only in EU member states these countries.

US Dollars
USD is accepted in all countries.

Other currency options may also be available - see
Mouser Worldwide.

Bench Talk for Design Engineers

Bench Talk

rss

Bench Talk for Design Engineers | The Official Blog of Mouser Electronics


Rust Programming Language for Microcontrollers Mike Parks

(Source: mirsad/stock.adobe.com)

New programming languages are typically created in response to shortcomings within existing languages, often related to performance, ease of use, or an inability to support the emergence of new computer science concepts. In the world of embedded electronics, specifically those built around a microcontroller, the emergence of the Rust programming language has been mainly in response to numerous shortcomings of the C programming language, which has dominated embedded system development for decades.

The C language, created in the early 1970s, lacks many modern features that today's software developers rely on. The following list highlights some of the key shortcomings of C in embedded systems development:

  •  
  • Package management: Rust offers the Cargo build system and package manager, whereas C lacks an official package management solution. Package management encourages code reuse because libraries (called “crates” in Cargo) can be easily integrated into a new project. Using existing, proven code libraries reduces development risks compared to writing code from scratch.
  •  
  • Better memory management: Rust's memory ownership and borrowing system eliminates the risk of memory leaks and other memory-related errors that C-based languages are prone to due to their reliance on less-reliable garbage-collection techniques.
  •  
  • Concurrency: Rust's ownership system and data structures enable safer and more efficient concurrency, which is crucial in embedded systems.
  •  
  • No null dereferencing: Rust eliminates null pointer dereferencing, a common source of bugs in C, by using the Option type for values that can be null.
  •  
  • Modern data structures: Rust supports data structure concepts such as generics and traits, improving source code maintainability.

While C presents numerous shortcomings, it is still the dominant language today. Thus, Rust's creators have ensured their emerging language can interoperate with C code, allowing embedded systems developers to leverage existing C libraries in Rust applications.

Rust: From the Web to Microcontrollers

Rust is the brainchild of Graydon Hoare, who started building the programming language in 2006 as a personal project while employed at Mozilla. His concern at the time was improving the performance and reliability of complex parallel computing tasks, which were becoming a significant problem with web browsers of the day. Flash forward to 2022, when Rust became only the third programming language permitted for use in the development of the Linux kernel, after assembly and C.

In 2018, the Rust user group established the Embedded Rust Working Group to oversee the development of a lightweight version of Rust made specifically for embedded platforms like Arm® Cortex®-M, MSP430, and RISC-V. Embedded Rust development tools are available for Windows, macOS, and numerous Linux distributions, and many modern code editors—such as Visual Studio Code, Sublime, Atom, RustOver, and Eclipse—offer support for Rust. Before looking at the practical aspects of Embedded Rust, let's review some unique concepts that may help traditional software developers making the transition to embedded system development:

  •  
  • Peripheral Access Crate (PAC): The PAC provides a direct interface to a microchip's peripherals. Users won't often interact with the PAC unless they are developing a hardware abstraction layer for a new microcontroller or if the higher layers fail to meet the application's needs.
  •  
  • Hardware Abstraction Layer (HAL): The HAL builds on the chip's PAC and provides an abstraction that requires no intimate knowledge of the chip's unique behaviors. Usually, they abstract whole peripherals into single structures (also known as structs), such as a unified structure that can be used to send data to and from on-chip peripherals.
  •  
  • Board Support Crate (BSC): Known in other embedded development environments as the board support package, the BSC abstracts an entire board. As a result, it must create abstractions for the board's microcontroller as well as any peripherals, such as sensors and LEDs. In most cases, engineers will work only with the chip's HAL and then either build drivers for peripherals or search for them on crate aggregator sites.

A Practical Example for an STMicroelectronics Board

The most crucial part of the Rust embedded ecosystem is the embedded-hal Rust library, which provides a common interface for working with hardware peripherals across different microcontroller platforms. The goal of embedded-hal is to enable code portability and reusability when developing software for embedded systems. The embedded-hal defines traits and abstractions for common embedded hardware peripherals like GPIO pins, SPI, I²C, UART, timers, and more. These traits provide a standardized API for interacting with these peripherals, making it easier to write portable embedded code.

One of the main benefits of embedded-hal is its platform-agnostic nature. You can write code using embedded-hal that works across various microcontroller architectures and development boards without modification as long as the target platform implements the required traits.

While embedded-hal provides common abstractions, it also allows for customization. If a specific microcontroller or platform has unique features or capabilities, you can implement the embedded-hal traits for those features to provide a consistent interface.

Here's an example of how you might use embedded-hal in Rust code:

use embedded_hal::digital::v2::{OutputPin, InputPin};

use stm32f4xx_hal::{gpio::gpioa::PA5, stm32};

 

fn main() {

 

 

   // Initialize the microcontroller

   let dp = stm32::Peripherals::take().unwrap();

   let cp = cortex_m::peripheral::Peripherals::take().unwrap():

   let mut rcc = dp.RCC.constrain();

   let _clocks = rcc.cfgr.freeze();

 

   // Configure a GPIO pin using embedded_hal

   let gpioa = dp.GPIOA.split();

   let mut led = gpioa.pa5.into_push_pull_output();

 

   // Blink the LED

   loop {

      led.set_high().unwrap();

      cortex_m::asm::delay(1_000_000);

      led.set_low().unwrap();

      cortex_m::asm::delay(1_000_000);

   }

}

In this example, we use embedded-hal traits like OutputPin to control an LED connected to a GPIO pin. The code is written in a way that can be reused on a different STM32 microcontroller by changing only the second line of code with whichever board is desired. Note that this is true so long as they support the embedded-hal traits for GPIO pins and have the required peripherals.

Conclusion

Rust was created to address the shortcomings of the C programming language, particularly in embedded systems. With features like package management, better memory management, safe concurrency, and modern data structures, Rust offers significant improvements over C. Rust's interoperability with C also allows developers to leverage existing C libraries. The creation of the Embedded Rust Working Group and tools like the embedded-hal library highlight Rust's commitment to enhancing embedded system development, offering a platform-agnostic and customizable approach that promotes code portability and reusability across various microcontroller platforms.



« Back


Michael Parks, P.E. is the co-founder of Green Shoe Garage, a custom electronics design studio and embedded security research firm located in Western Maryland. He produces the Gears of Resistance Podcast to help raise public awareness of technical and scientific matters. Michael is also a licensed Professional Engineer in the state of Maryland and holds a Master’s degree in systems engineering from Johns Hopkins University.


All Authors

Show More Show More
View Blogs by Date

Archives