Analytical Instruments Empowered by Rust - Tismo Technology

Page created by Alfredo Lowe
 
CONTINUE READING
Analytical Instruments Empowered by Rust - Tismo Technology
Analytical Instruments Empowered
                        by Rust
                          Deepak Hegde

                      Vishal Keshava Murthy

A case study on the use of the Rust programming language in
            Analytical Instrument development

                  Presented at Pittcon 2021

                 Tismo Technology Solutions (P) Ltd.
                       22/2, Palmgrove Road
                     Bangalore 560047, INDIA

                                                              1
Analytical Instruments Empowered by Rust - Tismo Technology
design paradigms and other facets of Rust in
ABSTRACT                                        the context of software development for an
                                                analytical instrument, which in this case is
The objective of this paper is to explore the   an elemental analyzer.
value of the Rust programming language in
the development of an analytical instrument.    Background
The study was carried out by developing a
part of an Analytical Instrument software       Analytical systems encompass various
using Rust. Experimental results and            hardware interfaces, sensor frontends,
anecdotal evidence suggest that Rust is a       external hardware and software systems,
viable option to tackle typical challenges      communication mediums, computations
associated with developing analytical           and HMIs.
instruments. Rust’s emphasis on safety, its     An elemental analyzer for example could
support     for    modern       programming     contain sensors, values, actuators, PWMs,
paradigms and a thriving Eco system aids        communication interfaces that make up the
the developer greatly in rapidly developing     hardware interfaces of the system. It would
robust and reliable, high quality code          also need data acquisition subsystems for
without    incurring    any     performance     measuring temperature, pressure, flow etc.
penalties.                                      In addition to these hardware interfaces the
                                                system would need software subsystems for
1. INTRODUCTION                                 instrument configuration management,
                                                various control processes for all relevant
A typical analytical system in the embedded     parameters, coupled with sensor data
space is a combination of a multitude of        calibration processing and analyzing
hardware and software subsystems. The           capabilities.
development of these high stakes, complex       Processing and control aside, a system of
systems which demand high reliability,          this nature also mandates the need for
computational accuracy and repeatability        various forms of communication interfaces
often poses unique technical challenges to      and corresponding protocol support.
the developer. Long lifetimes, strict           Command interface and UI is also a part of
regulatory requirements and critical time to    this growing list of requirements.
market windows further add to the
complexity of development from a product        Software      reliability, repeatability  of
management perspective.                         measurements and computational accuracy
                                                are critical to products of this nature. The
Rust is a statically typed, systems level       environments in which these devices are
programming language designed for safety,       deployed demand adherence to multiple
concurrency     and   performance.    The       safety and regulatory compliance. Time to
language promises to alleviate the design       market is also paramount to the commercial
challenges that plague the world of             success of such an undertaking.
embedded software development. The
study focuses on exploring these issues in      Owing to the scale of features of a product
detail and the language as a whole, diving      like this, abstraction of hardware and
into the ecosystem, language constructs,        functionality is a major hurdle in

                                                                                          2
architecting software. The control and          language, offers an important set of features
measurement algorithms deployed are             that promises to address most of the needs
arduous to develop, implement and test.         established above.
The system is inherently asynchronous
which makes concurrency and safety              Objectives
cardinal for reliable operation of the
software. A wide variety of standard
                                                The main objective of this study was to
communication interfaces such as CAN,
                                                evaluate Rust as a language for the
Modbus, OPC etc. that need to be
                                                development of embedded analytical
supported adds to the complexity. Features
                                                systems. Quantifiable Code metrics such as
such as diagnostics, firmware upgrade
                                                code size, binary size were collected and
support, intuitive GUI and portability, while
                                                presented. In addition to these, soft metrics
not a part of the core features of the system
                                                like ease of development, debug support,
are still imperative from a usability and
                                                hardware architecture support etc. were
convenience perceptive.
                                                also evaluated.

The key therefore, for successful
                                                Evaluation of RTIC, a real time framework
development of instrument software are
                                                developed in Rust that employs an interrupt
robust     implementation       architecture,
                                                driven approach to writing concurrent code
support for inherently safe and reliable
                                                was also an important goal. The tool chain,
programming paradigms and the ability to
                                                package management system, external
manage and abstract the complexities and
                                                library support etc. were also put under
real time observance of the system.
                                                scrutiny since the development ecosystem is
                                                an inseparable part of the software
C and C++ are the established programming
                                                development experience.
languages currently in use for embedded
software       development.       Something
                                                Since Rust is still evolving, it was also a part
seemingly as innocuous as the use of an
                                                of the research effort to recognize
uninitialized variable can wreak havoc in an
                                                shortcomings of the language and
otherwise perfect program. Once pointers,
                                                determine future areas of study.
memory management and concurrency are
involved, null pointer dereferencing,
dangling pointers, memory leaks, stack          Scope of the research
corruption and a whole host of hard to track
problems that affect code in insidious ways     1. Evaluation of Rust language features,
are introduced to the code base. The lack of    development ecosystem and library support
ready to use modules and associated
package managers, like npm or NuGet             2. Evaluation of RTIC framework
offered by other modern languages also
result in slower development process            3. Collection of code metrics for Rust code
hindered by their inability to leverage         compared against equivalent C code
mature prewritten modules.

Rust, a relatively new systems programming

                                                                                              3
Research methods

A development environment was set up
with the Rust toolchain including the Rust
stable and nightly compiler, package
manager cargo, Rust formatter, Rust
language server RLS and debugger
codeLLDB.

A TCD controller application, one of the
subsystems of the elemental analyzer
involving    temperature     control    and
measurement, configuration management,
timed tasks, a simple CLI, status indication
and a PID loop were developed in both C
and Rust. The code bases were developed
iteratively    using    established     best
development practices and were subject to
multiple reviews and refactoring to ensure
code quality and performance.

Code metrics were collected for both
applications under various optimization
settings. Other non-quantifiable aspects of
development      such    as   development
environment,      toolchain,    ease     of
development, testing support etc. were also
evaluated and presented.

The structure of the document

The following sections will be covered in the
report:

1.   Overview of Rust
2.   Embedded Rust
3.   Embedded Rust ecosystem
4.   Embedded Rust Crates
5.   Developed application
6.   Useful Language features
7.   Observations

                                                4
3. Move semantics: Assignment, copy and
                                                    move operations are clearly distinct and
2. DETAILED ANALYSIS                                operate by different sets of rules.

2.1. Overview of Rust                               While the core features described above
                                                    help with code correctness, a variety of
                                                    concepts and paradigms inspired heavily
Rust[1] is a multi-paradigm systems
                                                    from other languages such as pattern
programming language developed by the
                                                    matching, anonymous functions and
Mozilla foundation with heavy emphasis on
                                                    algebraic data types from functional
safety, performance and support for
                                                    programming      languages,    traits   and
concurrency. This systems programming
                                                    structures      from        object-oriented
language converts memory and concurrency
                                                    programming and features such as macros
related run time problems into errors that
                                                    and     template     programming       from
get caught early during the compilation
                                                    metaprogramming languages makes Rust a
process. The compiler accomplishes to do so
                                                    very powerful and expressive language.
by adhering to the following fundamental
principles.
                                                    Rust also features the concept of unsafe
                                                    code, sections of the code can be marked
1. Immutability: Every entity is immutable
                                                    unsafe, inside of which potentially
by default
                                                    dangerous operations such as raw pointer
2. Ownership: Every entity has a clear
                                                    manipulation can be made under the
owner at all times which determines its
                                                    discretion of the programmer foregoing the
scope and lifetime. This enables memory
                                                    compiler checks for extra flexibility. Other
safety at compile time without relying on
                                                    prominent features include built in support
garbage collection
                                                    for testing, code formatting and profiling.
2.2. Embedded Rust
                                                    This distinction between the core and the
                                                    standard library ensures that the features
Bare-metal hardware environments are first
                                                    required for the application can be
class citizens of Rust[2]. The language itself is
                                                    customized as required based on the target
built in layers with a core layer libcore which
                                                    hardware and application requirements.
implements platform agnostic operations,
                                                    Rust also extends the powerful Ownership
provides API for language primitives and
                                                    mechanism to manage the peripherals by
APIs for processor features. All platform
                                                    treating them as variables. One can enforce
integration APIs and the run time
                                                    singleton pattern on peripherals, and these
environment are implemented in the stdlib.
                                                    can be shared as read-only, read-write types
Development for embedded applications
                                                    using the borrow checker paradigm
take place in a no_std environment meaning
that only the core layer is used. Memory
                                                    Since concurrency is one of the core focus of
management           schemes,      run     time
                                                    rust, depending on the target platform,
environments , stack protection schemes
                [12]
                                                    there is native support for atomic
and data structures[15] such as vectors and
                                                    operations. Synchronization mechanisms
maps are added as required externally on
                                                    such as critical sections, mutexes, interior
top of the libcore using crates[11].
                                                    mutability refcells are also provided. Real

                                                                                               5
Time      Interrupt     Driven  Concurrency
framework , RTIC is another option if RTOS
            [6]
                                                  HAL crates are built atop PACs, by providing
like functionality is required.                   definitions      to   traits   defined     in
                                                  embedded-hal . This layer provides
                                                                  [12]

Support for interoperability with C is            peripheral specific hardware APIs using
another attractive feature of rust. This is       which applications can be built. It should be
useful when validated C code needs to be          noted however that these HALs are
integrated with Rust. Rust provides Foreign       community driven and often do not support
Function interface (FFI) for this purpose.        all features provided by the hardware due to
Tools like bindgen aid in generation of           which Hardware registers of the device may
mapping metadata between languages.[1][8]         still have to be manipulated directly through
                                                  services provided by the device specific PAC.

2.3. Embedded Rust ecosystem                      RustC[3], the Rust compiler is pivotal to the
                                                  traction that Rust has been gaining lately.
                                                  Compilation times can be pretty long in
A good development ecosystem is critical for
                                                  contrast with that of C or C++ but the
the adoption of the language into
                                                  output is fairly well optimized for the target
production quality software work. The Rust
                                                  platform. The error messages are very
ecosystem while still in its infancy, provides
                                                  explicit and provide relevant and helpful
excellent tools and reasonable coverage for
                                                  suggestions. Rust also ships with package
most target platforms. The toolchain set up
                                                  and build manager cargo that helps with the
process is fairly straight forward, and is
                                                  build process as well with dependency
explored in detail in the later sections of the
                                                  management and integration of external
paper.
                                                  libraries crates. RustC, and cargo coupled
                                                  with the debugger GDB can be setup inside
There is extensive support for the ARM
                                                  text editors such as VScode for a complete
cortex M series of processors, with
                                                  building, flashing and debugging platform.
Hardware abstractions available for MCUs
                                                  The Rust ecosystem also features inbuilt
from major chip vendors such as STM,
                                                  support for testing and code profiling.
Microchip, NXP, TI and Nordic. Xtensa and
                                                  Formatter rustfmt and static code checker
AVR are some of the notable architectures
                                                  rust-Clippy are other utilities packaged into
that yet aren't supported.[11]
                                                  the system.

The conventional layered approach for
development is followed, with the lowest          2.4. Embedded Rust crates
layer being the Peripheral Access Crate. The
PAC defines memory mapped registers for           Rust crates are a large part of the appeal of
the particular target hardware. This layer is     embedded rust. The libraries managed by
generally used in conjunction with a micro        Cargo[4] helps the developer in leveraging
architecture crate that encompasses               the Rust community and integrate tested
routines and functions common to the              and verified features into the code. Crates
target architecture. SVD2Rust is a tool that      are an indispensable part of the Rust
can be used for the generation of these           ecosystem.
target specific Peripheral Access crates.[14]

                                                                                              6
Since      bare-metal     embedded         Rust   The TCD subsystem of an elemental analyzer
development takes place in the embedded           for the detection of nitrogen content in
environment it is up to the developer to          protein samples was developed for the sake
select the required memory management             of the experiment. The overall system works
scheme utilizing the respective crate[11].        on the Dumas principle in which a sample is
PACs and HALs introduced earlier, if              purged and heated in a high temperature
available are also developed in the form of       combustion furnace in the presence of pure
crates that can be used to build up               oxygen such that the sample decomposes
applications. Several crates that are             into carbon dioxide, water, nitrogen dioxide
designed to be used in no_std environments        in addition with nitrogen as several oxides.
provide a wide variety of functionality
ranging from atomic access, bit field             The combustion products are collected and
manipulation methods, circular buffers and        the gas mixture is passed over hot copper to
heapless data structures. CRCs, linear            remove any oxygen and convert nitrogen
algebra libraries, FFT support are some the       dioxides into molecular nitrogen. The
prominent math libraries. Device drivers[17]      sample is passed through traps that remove
for a large class of devices ranging from         water and carbon dioxide. The measured
simple peripheral based sensors, memory           signal from the thermal conductivity
modules, to displays and cellular modules         detector for the sample is then converted
are also pervasive. Stacks developed in Rust      into total nitrogen content.
for Bluetooth, Ethernet are some of the
protocol crates that are gaining traction. PID    The TCD detector subsystem was
control[16], CLI[15] were some of the             implemented in both C and Rust on
application specific crates evaluated and         TM4C123XX[10], an ARM cortex M4 based
used in this project.                             board. Initial prototyping was carried out
                                                  using the Tiva launch pad with the same
2.5. Application overview                         MCU and an STM32F407 discovery board on
                                                  which the RTIC framework[6] was evaluated.

                                      Figure 1

                                                                                            7
Figure: 2

A traditional layered architecture was           using the RTIC framework.[7]
utilized for the code structure with the MCU
HAL making up most of the lower layers           2.6. Useful language features
through the tm4c123x-hal[13] crate for
dealing with various onboard peripherals
                                                 The following language features were
such as SPI, UART etc. Additional crates
                                                 heavily utilized for the development of the
were used for runtime[11], memory
                                                 project.
management[14], and low-level register
access[17] functions. Other purely software
                                                 Struct and traits
constructs such as PID control[16] and CLI[15]
                                                 Structures in Rust are similar to C struct
were also built around crates for rapid
                                                 allowing heterogeneous data types. Unlike a
prototyping and development.
                                                 traditional Object Oriented programming
                                                 language Rust has no support for classes.
The hardware API layer was built atop the
                                                 Object oriented behavior is implemented
previously described HAL. Object based
                                                 using struct and traits instead. Traits are
design approach was utilized here, grouping
                                                 implemented for structures giving the
all similar functions into modules that
                                                 structure traditional class like methods.
exposed to the application layers above only
                                                 These methods however need to take an
the functionality required.
                                                 explicit self parameter if they need to act on
                                                 themselves. Since immutability is a core
The application layer is comprised of
                                                 aspect of the language all elements and
independent tasks for PID control, Heater
                                                 traits are private and immutable by default.
control, Data acquisition and a command
                                                 Consider the heater struct defined below:
Line Interface task. These were tied together

                                                                                             8
pub struct Heater
{
  status : bool,
  pwm_pin : pwm::EvenPWM,
  pwm_period_us:u32 ,
  pwm_duty_cycle:u32,
}
impl Heater
{
  pub fn disable(&mut self)
  {
    self.status = false;
    self.pwm_pin.disable(());
  }

    fn dutycycle_to_period(&mut self,duty_percent:u32) -> u32
    {
      let res = duty_percent*(self.pwm_period_us)/100;
      return res ;
    }
}
                                       Code snippet: 1

Here, the disable trait is defined for
structure heater. The elements on the           Option type
structure are private by default and            Null types are a common source of bugs in
therefore are not accessible to outside         most traditional programming languages.
modules. The disable function takes a           Rust provides Option type and Result type
mutable reference to itself and acts on the     that can represent variables that can be
elements of the structure Heater. This API,     uninitialized.   Internally  they     are
marked as public is exposed to other            implemented using templates.
modules so that they can interact with the      Consider the example below:
heater       structure.      The     function
dutycycle_to_period is a private method
that is inaccessible to outside modules.

pub fn do_pid_control_task(softtimer_block:&mut SoftTimers, task_frequency:u32, pid_bloc
k : &mut PidControl, prev_output : f32) ->Option
{
   if softtimer_block.check_timer_ms(ESoftTimers::LedSoftTimer)
   {
      let res:Option;
      let control_output = pid_block.run_loop(prev_output);
      res = Some(control_output);
      softtimer_block.set_timer_ms(ESoftTimers::PidSofttimer,task_frequency);

                                                                                           9
return res;
    }
    else
    {
      return Option::None;
    }
}
                                       Code snippet: 2

The temperature control task runs only           of the operation if the timer has expired or
periodically and returns res which is an         returns the None type
option type. The res type contains the result

heater_control::do_temperature_control_task(&mut my_mcu.heater_controller , pid_output)
                                    Code snippet: 3

                                                 Pattern Matching
This result is captured in option variable       The match statement is used extensively in
pid_output and passed down to the                the program, particularity when the option
do_temperature_control_task. The function        type        is        involved.        The
can then act on this parameter depending         do_temperature_control_task from the
on whether it has a value or not.                previous example utilizes match effectively
                                                 as shown.

pub fn do_temperature_control_task(pwm_block : &mut Heater, control_input_option : Opti
on)
{
  match control_input_option
  {
    Some(val) => {pwm_block.set_dutycycle(val as u32);},
    None => {},
  }
}
                                    Code snippet: 4

Here, if the option type does not have a         Closures or anonymous functions as known
value then, no action is taken.                  in C++ are used extensively in the PACs.
                                                 Register manipulations are done utilizing
Closures                                         closures

timer.icr.write(|w| w.tatocint().set_bit());
                                        Code snippet: 5

                                                                                          10
In this example, |W| is the closure that       determining the visibility of functions inside.
performs the operation for setting a           The scope operator as used in C++ is also
respective bit.                                available in Rust to keep the code structured
                                               and modular. The syntax results in highly
Modules                                        modular yet readable code without having
The Rust file system employs modules for       to deal with separate implementation and
structuring code. Files are treated as         interface files.
modules each with their own namespaces,        Module heater control is imported into the
with access specifier as explained above       file here using the keyword mod

mod heater_control;
heater_control::do_temperature_control_task(&mut my_mcu.heater_controller , pid_output)
;
                                    Code snippet: 6

Public functions exposed by the heater         the compiler cannot guarantee safety. While
module are accessed using the scope            the language discourages the use of unsafe,
operator in this file.                         it is useful when dealing with raw pointers
                                               or global values when it is determined to be
Unsafe blocks                                  safe to do so by the developer as
unsafe keyword is necessary in places where    demonstrated in the code snippet below.[9]

unsafe {
    tm4c123x_hal::tm4c123x::NVIC::unmask(tm4c123x_hal::tm4c123x::Interrupt::TIMER0A)
  }
                                   Code snippet: 7

                                               typestate checking[3]. The hardware
Templates                                      therefore can be characterized as having
Templates are powerful features from the       only a limited set of valid states with a clear
metaprogramming paradigm. It is useful for     sequence of possible operations. A clear
generic programming and is used by Rust to     example of this is the GPIO pin which is
accomplish monomorphization. Templates         modeled such that the validity of operations
result in the increase in compile types but    on it is determined by the state of the pin.
incur no performance penalties. Templated      This results in much safer code that prevents
types are also used in the HAL libraries for   wrong initialization at compile time

gpioc::PC5< AlternateFunction< AF1,PushPull>>
                                     Code snippet: 8

PC5 here is defined as a pin of type           configuration. The methods that can be
Alternate type AF1 with push pull              applied on this pin are dictated by the

                                                                                           11
typestate. It would result in a compiler error   of guaranteeing safe concurrent access.
for an invalid method not defined for pins of    While the usage of global mutable data is
this type.                                       discouraged to prevent data race conditions,
                                                 they can help still be used inside unsafe
Concurrency                                      blocks under the programmers discretion.[3]
Rust provides several features to aid
concurrency.                                     The example below demonstrates the use of
The common paradigm of Foreground                both the interrupt attribute for defining the
background process of using superloops           timer0 interrupt as well as the utilization of
with interrupts is well supported, with the      global           mutable              variable
use of attributes to define interrupt            RUNNING_COUNTER.
handlers. On a few platforms atomic access
is supported for simple and effective means

static mut RUNNING_COUNTER:u32 = 0;
#[interrupt]
fn TIMER0A()
{
      unsafe {
       let periph_temp = tm4c123x_hal::Peripherals::steal();
       let timer = periph_temp.TIMER0;
       timer.icr.write(|w| w.tatocint().set_bit());

      if RUNNING_COUNTER > MAX_TICK {RUNNING_COUNTER = 0;}
      else {RUNNING_COUNTER+= 1 ;}
               }
 }
                                        Code snippet: 9

                                                 within the critical section. The runtime
Critical sections are another crude but          environment crate cortex_m also provides
effective concurrency mechanism supported        standard       resource         management
by Rust. The functionality is provided by        mechanisms such as mutexes to ensure safe
runtime environment crates such as               concurrent access.
cortex_m[12]. These are often used with          In the example below, the value of
closures, whose operations take place            LED_MUTEX is set inside a critical section.

static LED_MUTEX: Mutex = Mutex::new(Cell::new(0));
cortex_m::interrupt::free(|cs| LED_MUTEX.borrow(cs).set(2) );
                                    Code snippet: 10

                                                                                            12
which project creation, library creation and
Real-Time Interrupt-driven Concurrency          management are handled. CodeLLDB in
(RTIC)[7] is a framework that can be used for   conjunction with JlinkGDB was used for
the development of larger more intricate        flashing and debugging binaries.
real time systems. Features such as tasks,      Since there were no IDEs for Rust
message passing, queues and scheduling          development at the time, Microsoft Visual
provided by this framework makes this an        Studio Code was used with the official Rust
excellent       middle   ground     between     extension. Tasks were setup for building and
developing concurrent programs from             flashing the project within the IDE.
scratch using the concurrency mechanisms        Debugging within the IDE was setup using
explained above and using full blown            cortex-debug extension used in conjunction
schedulers such as FreeRtos.                    with Jlink GDB server.

                                                Productivity
2.7. Development experience                     With the initial set up out of the way,
                                                community driven libraries hosted on crates
                                                were a good starting point for the project.
Learning
                                                Embedded HAL implementation for TI and
The initial learning curve for Rust is steep
                                                STM boards were readily available, although
especially for programmers with only C/C++
                                                some features were unavailable or under
background. Programming concepts novel
                                                the process of development requiring
to Rust such as the borrow checker and
                                                register level manipulation of the hardware
move semantics are challenging and take
                                                using the respective Peripheral Access crates.
time to get accustomed to. HAL interface
                                                This is in stark contrast with C code since
construction requires careful thought and
                                                chip manufacturer provide near complete
planning, established imperative or object
                                                HAL which cuts down on development time
oriented approach for the same are hard to
                                                of lower layers.
express in Rust. There are various official
                                                Application development on the other hand
and community driven high quality
                                                was made much simpler due to external
documentation for embedded systems
                                                Crates. Suitable implementations for circular
development in Rust. The crates however
                                                buffers, PID algorithms, CLI implementations
are purely community driven and therefore
                                                etc. hosted on crates.io were easily
vary wildly in quality.
                                                integrated into the code base. Inbuilt
                                                support for testing and a built-in formatter
Setup and tools
                                                also contributes to writing better quality
Setting up the development ecosystem is
                                                code faster.
not a very involved process. There are
several tools that help the developer get
                                                Ease of development
productive with the tool chain fairly early.
                                                Rust provides strong abstraction with no
Rustup is the installer which aids in setting
                                                performance tradeoffs which makes for
up the compiler and package manager for
                                                highly expressive code. The compile times
development in Windows, Linux and Mac
                                                are quite large especially if templates are
environment. Package management is
                                                used heavily, due to all the static checks
handled by the Rust package manger Cargo,
                                                performed. The error messages provided by
which also serves as the build system with

                                                                                           13
the compiler are helpful and generally very      Check Appendix section for metrics
accurate. Use of modules help with code          collected in other optimization profiles.
architecture and help develop highly
structured easily maintainable code. Rusts
statically typed nature feel prohibitive at
                                                 SUMMARY AND CONCLUSIONS
times since it disallows implicit conversions,
or unhandled cases thereby making it hard        The Rust programming language offers a
to use for prototyping. The use of raw           rich set of features emphasizing safety
pointers is discouraged and the language         which results in the development of reliable
does not fully support conventional OOP          software. Safe programming paradigm helps
paradigms.                                       in meeting safety requirements whereas
                                                 built-in support for testability helps with
2.8. Observations                                reliability and verifiability of critical
                                                 applications. Development process aided by
                                                 modern programming constructs and
The developed C and Rust code were used
                                                 portability across hardware, thanks to highly
for the capture of key code metrics. The
                                                 modular architecture, helps in improving
development process was kept identical for
                                                 time to market. The open source community
both languages. An effort was made to use
                                                 driven development helps in quick
idiomatic conventions to result in not only
                                                 adaptability in both developer communities
high performance but also high quality
                                                 and organization looking for a safe,
maintainable code. Memory footprint data
                                                 sustainable and stable ecosystem.
were collected from release versions of both
code bases with link time optimization
                                                 Code metrics collected suggest that the
enabled. The results are tabulated below:
                                                 code developed in Rust while about fifty
                                                 percent larger than code developed with its
Size    No Optimization Size Optimized
                                                 counterpart C, is smaller in terms code base
        ROM        RAM        ROM     RAM
                                                 by close to fifteen percent. These penalties
C       20956 1348            18970 1243
                                                 however can be overlooked considering
Rust    100780 24             27936 24
                                                 improvements in code quality. While the
The code footprint in Rust is 50% larger         ecosystem for embedded Rust is satisfactory
                  Table: 1                       but pales in comparison to the maturity that
                                                 C/C++ provides. However the ecosystem is
Lines of code were also captured for both        continuously evolving, and as the language
metrics as they are indicative of the            gains traction this aspect will get better.
development effort.                              Overall, this modern language that is not
               Lines of code                     weighed down by legacy like C++ is, offers a
C                       1750                     refreshing new option which, regardless of
Rust                    1500                     its future demands strong consideration
Rust code-base is 15% smaller
                 Table: 2

                                                                                           14
References

1. S. Klabnik, C. Nichols. (2020). The Rust Programming Language.

2. Embedded Working Group. (2020). The Embedded Rust Book.

3. Embedded Working Group. (2020). The rustc book

4. Embedded Working Group. (2020). The Cargo book

5. Embedded Working Group. (2020). The Rustonomicon

6. P. Lindgren, Embedded Systems Group. (2020). Real-Time Interrupt-driven Concurrency.

7. Embedded Working Group. (2020). Discovery.

8. Embedded Working Group. (2020). The Embedonomicon.

9. Texas Instruments. (2014). TM4C123GH6PM Microcontroller.

10. The resources team. (2021). rust-embedded

11. The Cortex-M Team. (2020). Cortex-m-rt

12. J. Pallant, J. Aparicio. (2020). embedded-hal

13. D. Wood, J. Pallant, J.Aparicio, M. poulhies. (2020). tm4c123x-hal

14. J. Aparicio, P. Lindgren. (2021). heapless

                                                                                          15
15. R. Horn. (2019). light-cli

16. K. Elkabany. (2020). PID Controller for Rust

17. D. Dockter. (2021). device-driver
You can also read