Release of Rust 1.96. Evaluation of Rust's suitability for creating firmware for microcontrollers

The release of version 1.96 of the Rust programming language has been announced. Originally created by Mozilla, Rust is now developed under the auspices of the independent nonprofit organization Rust Foundation. The language focuses on safe memory handling and provides tools to achieve high task parallelism without relying on a garbage collector and runtime (the runtime is limited to basic initialization and support for the standard library).

Memory handling methods in Rust aim to eliminate errors when manipulating pointers and protect against issues arising from low-level memory operations, such as accessing memory after it has been freed, dereferencing null pointers, buffer overflows, etc. To facilitate library distribution, ensure compilation, and manage project dependencies, the package manager Cargo is being developed. A repository, crates.io, is supported for hosting libraries.

Safe memory handling in Rust is ensured at compile time through reference checking, ownership tracking of objects, lifetime consideration (scope) of objects, and assessment of memory access correctness during code execution. Rust also provides means to protect against integer overflows, mandates the initialization of variable values before use, improved error handling in the standard library, employs the concept of immutability for references and variables by default, and offers strong static typing to minimize logical errors.

Key innovations:

  • A new module, range, has been added, implementing new types designed to replace the outdated types Range, RangeInclusive, RangeToInclusive, and RangeFrom, allowing ranges to be stored in Copy structures. The Range type defines ranges bounded by a minimum and maximum permissible value (excluding the maximum), the RangeFrom type specifies numbers starting from a given value, and the RangeInclusive type includes both endpoints of the specified range. Future releases will introduce additional types, RangeFull and RangeTo, while the old implementation will be moved to core::range::legacy::*, and the syntax 'N..M' will transition to the new type variants.

    The new types differ in that they implement the IntoIterator trait instead of the Iterator trait, meaning they define how to convert a type into an iterator rather than relying on a built-in iterator. This approach allows the use of the Copy operation (the Copy trait indicates that values of the type can be duplicated through simple copying), which was previously unavailable due to incompatibility with types having built-in iterators.
    For example, the new types allow for the boundaries of a slice to be stored in a structure that can be fully copied without separately saving the initial and final values:

    use core::range::Range;

    #[derive(Clone, Copy)]
    pub struct Span(Range);

    impl Span {
    pub fn of(self, s: &str) -> &str {
    &s[self.0]
    }
    }

  • Macros "assert_matches!" and "debug_assert_matches!" have been added to check if a value matches a specified pattern and to terminate execution on mismatch. Unlike the expressions "assert!(matches!(..))" and "debug_assert!(matches!(..))", the new macros provide debug output with the values that caused the failure. To avoid conflicts with external macros provided with similar names, the new macros require explicit import of the library "core::assert_matches."

    use core::assert_matches;

    fn get_random_number() -> u32 {
    4
    }

    fn main() {
    assert_matches!(get_random_number(), 1..=6);
    }

  • When building for the WebAssembly target, the option "—allow-undefined" has been removed from the linker, which allowed linking when there were undefined symbols that were converted into imports from the "env" module. When building for WebAssembly, all symbols related to linking must now be defined by default. To return to the old behavior, you can use the environment variable "RUSTFLAGS=-Clink-arg=—allow-undefined" or the expression ‘#[link(wasm_import_module = "env")]’ in the code.
  • A new batch of APIs has been promoted to stable, including stabilized methods and trait implementations:
    • assert_matches!
    • debug_assert_matches!
    • From for AssertUnwindSafe
    • From for LazyCell
    • From for LazyLock
    • core::range::RangeToInclusive
    • core::range::RangeToInclusiveIter
    • core::range::RangeFrom
    • core::range::RangeFromIter
    • core::range::Range
    • core::range::RangeIter
  • The Cargo package manager has addressed the CVE-2026-5223 vulnerability, which could be used to overwrite the source code of another crate package in the local package cache from the same repository through manipulation of symbolic links within the crate packages. The vulnerability manifests only when working with third-party package repositories and does not affect users of the crates.io repository, as uploading packages with symbolic links is prohibited on crates.io.

Additionally, it is worth noting the publication (PDF) of the results of an analysis of the suitability of the Rust language for developing firmware for microcontrollers and embedded systems with limited resources.
The research was conducted by STMicroelectronics with the participation of several European universities. Two isolated development teams were tasked with implementing the same firmware for STM32U585AI microcontrollers with an Arm Cortex-M33 core. The first team created the firmware in C, while the second team used Rust.

Testing of the completed work revealed no significant advantages of using the C language over Rust for firmware development for microcontrollers when comparing memory consumption and performance. Moreover, utilizing the system runtime written in Rust from the open-source project Ariel OS resulted in lower memory consumption in the Rust project than in the C implementation using a traditional stack based on the newlib library.

The resulting firmware size was 84100 bytes in the Rust project and 76744 bytes in the C project (10% smaller), but the RAM consumption in the Rust firmware was significantly lower—24640 bytes versus 42608 bytes. Regarding performance, during testing of initial prototypes developed over 6 weeks, the Rust implementation outperformed the C implementation by two times; however, both implementations fell short of the calculated maximum performance. After 4 weeks spent on optimization, both implementations achieved roughly the same result, close to the theoretical maximum.



Source: opennet.ru
Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster