Coding nRF52 with Rust and Apache Mynewt on Visual Studio Code

Posted by

Introduction

Embedded systems development has traditionally been dominated by low-level languages like C and Assembly. However, with the rise of more modern and secure programming languages like Rust, developers now have the opportunity to bring the benefits of these languages to the embedded domain. In this article, we will explore how to leverage Rust and the Apache Mynewt operating system to program the nRF52 series of microcontrollers from Nordic Semiconductor, using the Visual Studio Code (VSCode) development environment.

Prerequisites

Before we dive into the coding process, ensure that you have the following prerequisites installed on your development machine:

Additionally, you will need a nRF52 development board, such as the nRF52840 DK or the nRF52832 DK.

Setting up the Development Environment

how to arduino programming and software Installing for Arduino UNO, Nano, Mega and NodeMcu

1. Install the Required Extensions for VSCode

Open Visual Studio Code and navigate to the Extensions view by clicking on the square icon on the left sidebar or by pressing Ctrl+Shift+X (Windows/Linux) or Cmd+Shift+X (macOS). Search for and install the following extensions:

  • rust-lang.rust (Rust Language Server)
  • binarycodeddata.ionide-installer (Ionide-fsharp)
  • ms-vscode.cpptools (C/C++ Tools)

2. Clone the Apache Mynewt Repository

Next, we need to clone the Apache Mynewt repository, which contains the operating system and the necessary tools for building and flashing our Rust-based firmware.

Open a terminal or command prompt and navigate to a directory where you want to clone the repository. Run the following command:Copy code

git clone https://github.com/apache/mynewt-core.git

This will create a mynewt-core directory containing the Mynewt codebase.

3. Install the Mynewt Tool

The Apache Mynewt project provides a command-line tool called newt for managing and building Mynewt projects. To install the newt tool, follow these steps:

  1. Navigate to the mynewt-core directory:

Copy code

cd mynewt-core

  1. Run the installation script:

Copy code

# On Linux or macOS ./install.sh # On Windows install.sh

This script will install the newt tool and other required dependencies.

4. Create a New Mynewt Project for nRF52

With the newt tool installed, we can now create a new Mynewt project for our nRF52 board. Run the following command, replacing project_name with your desired project name:Copy code

newt install -v newt newt create project_name

This will create a new project directory with the specified name and populate it with the necessary files and directories.

5. Target the nRF52 Board

Next, we need to set the target for our project to the nRF52 board. Run the following command, replacing project_name with your project name:Copy code

cd project_name newt target create nrf52_board newt target set nrf52_board app=@apache-mynewt-core/apps/blinky newt target set nrf52_board bsp=@apache-mynewt-core/hw/bsp/nrf52 newt target set nrf52_board build_profile=debug

These commands create a new target called nrf52_board, set the application to the blinky example (which blinks an LED), set the board support package to the nRF52 BSP, and set the build profile to debug.

6. Build and Flash the Firmware

With the project configured, we can now build and flash the firmware to our nRF52 board. Connect your board to your development machine via USB and run the following commands:Copy code

newt build nrf52_board newt create-rev -repo=repo_name versions newt run nrf52_board 0.0.0 [tgt.app-rev=@repo_name/apps/blinky@0.0.0]

Replace repo_name with a name for your local repository (e.g., mynewt-project). These commands build the firmware, create a versioned repository, and flash the firmware to the connected board.

If everything is set up correctly, you should see the LED on your nRF52 board blinking.

Developing with Rust and Apache Mynewt

Now that we have our development environment set up and a working example, let’s explore how to develop Rust applications for the nRF52 using Apache Mynewt.

1. Add Rust Support to Your Project

Apache Mynewt supports Rust applications out of the box. To add Rust support to your project, run the following command:Copy code

newt install -v rust

This command installs the necessary Rust components and dependencies for your project.

2. Create a Rust Application

Let’s create a new Rust application for our project. Run the following command, replacing app_name with your desired application name:Copy code

newt pkg new -r rust-app@0.0.0 app_name

This command creates a new package for your Rust application with the specified name and version (0.0.0 in this case).

3. Edit the Rust Application Code

Navigate to the apps/app_name/src directory within your project. You should see a main.rs file, which is the entry point for your Rust application. Open this file in Visual Studio Code and modify the code as desired.

Here’s an example of a simple Rust application that blinks an LED:

rustCopy code

use kernel::allocator; use kernel::component::Component; use kernel::mem; use kernel::sysinit; use mynewt; use nrf52; struct HelllmnrApp { sysinit_comp: kernel::component::Component<'static>, } impl kernel::sys::App for HelllmnrApp { fn prepare_start(&'static self) { self.sysinit_comp.init_components(); } fn start(&'static self) { let led_pin = nrf52::pins::p0_pin::P0_13.make_output(); loop { led_pin.set(); kernel::sys::os::delay_ms(500u32); led_pin.clear(); kernel::sys::os::delay_ms(500u32); } } } fn main() { let app = HelllmnrApp { sysinit_comp: kernel::component::init_mpu(), }; kernel::os::main(&app as &dyn kernel::sys::App); }

This code sets up a Rust application that blinks an LED connected to pin P0.13 on the nRF52 board. You can modify the code to implement your desired functionality.

4. Build and Flash the Rust Application

To build and flash your Rust application, follow these steps:

  1. Set the target for your Rust application:

Copy code

newt target set nrf52_board app=@repo_name/apps/app_name

Replace repo_name with the name you used earlier for your local repository, and app_name with the name of your Rust application.

  1. Build and flash the firmware:

Copy code

newt build nrf52_board newt create-rev -repo=repo_name versions newt run nrf52_board 0.0.0 [app.loader=bootloader@0.0.0]

These commands build the firmware, create a versioned repository, and flash the firmware to the connected board.

Your Rust application should now be running on your nRF52 board!

Debugging with Visual Studio Code

Visual Studio Code provides excellent support for debugging Rust applications. To debug your Rust application running on the nRF52 board, follow these steps:

  1. Install the CodeLLDB extension in Visual Studio Code. This extension provides a debug adapter for the LLDB debugger, which is used for debugging Rust applications.
  2. Create a new file called launch.json in the .vscode directory of your project. If the .vscode directory doesn’t exist, create it.
  3. Paste the following content into the launch.json file and modify the program path to match the path to your Rust application’s ELF file:

jsonCopy code

{ "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "Debug Rust Application", "program": "${workspaceFolder}/bin/targets/nrf52_board/app/apps/app_name/app_name.elf", "cwd": "${workspaceFolder}", "preLaunchTask": "build", "postLaunchTask": "monitor" } ] }

Replace app_name with the name of your Rust application.

  1. Create a new file called tasks.json in the .vscode directory of your project and paste the following content:

jsonCopy code

{ "version": "2.0.0", "tasks": [ { "type": "shell", "label": "build", "command": "newt build nrf52_board", "problemMatcher": [] }, { "type": "shell", "label": "monitor", "command": "newt run nrf52_board 0.0.0 [app.loader=bootloader@0.0.0]", "problemMatcher": [] } ] }

  1. Connect your nRF52 board to your development machine via USB.
  2. In Visual Studio Code, open the Debug view by clicking on the bug icon on the left sidebar or by pressing Ctrl+Shift+D (Windows/Linux) or Cmd+Shift+D (macOS).
  3. Select the “Debug Rust Application” configuration from the dropdown list.
  4. Set any desired breakpoints in your Rust code.
  5. Click the green “Start Debugging” button or press F5 to start the debugging process.

Visual Studio Code will now build your Rust application, flash it to the nRF52 board, and start the debugging session. You can step through your code, inspect variables, and take advantage of the full debugging capabilities provided by Visual Studio Code and the LLDB debugger.

Frequently Asked Questions (FAQ)

  1. Q: Can I use Rust for bare-metal programming on the nRF52? A: Yes, you can use Rust for bare-metal programming on the nRF52. Apache Mynewt provides a lightweight and modular operating system that allows you to develop Rust applications that run directly on the hardware without the need for a full-fledged operating system.
  2. Q: How does Apache Mynewt compare to other embedded operating systems like FreeRTOS or Zephyr? A: Apache Mynewt is a lightweight and modular operating system specifically designed for embedded systems and IoT devices. It offers a similar feature set to FreeRTOS and Zephyr but with a focus on security, modularity, and support for various programming languages, including Rust. Mynewt’s modular architecture allows you to include only the necessary components, resulting in a smaller memory footprint.
  3. Q: Can I use other programming languages besides Rust with Apache Mynewt? A: Yes, Apache Mynewt supports multiple programming languages, including C and C++, in addition to Rust. However, Rust offers several advantages in terms of memory safety, concurrency, and performance, making it a compelling choice for embedded systems development.
  4. Q: How do I handle hardware peripherals like I2C, SPI, or UART in Rust with Apache Mynewt? A: Apache Mynewt provides a Hardware Abstraction Layer (HAL) that abstracts the low-level hardware details and exposes a consistent API for interacting with peripherals like I2C, SPI, and UART. You can use the Rust bindings for the HAL to access and control these peripherals from your Rust code.
  5. Q: Can I use third-party Rust crates (libraries) in my Apache Mynewt project? A: Yes, you can use third-party Rust crates in your Apache Mynewt project. However, it’s important to ensure that the crates are compatible with the embedded environment and the specific target architecture (in this case, nRF52). Some crates may rely on features or dependencies that are not available or supported in the embedded context.

Conclusion

In this article, we explored how to set up a development environment for coding the nRF52 microcontrollers using Rust and the Apache Mynewt operating system on Visual Studio Code. We covered the installation process, project setup, building and flashing firmware, developing Rust applications, and debugging with Visual Studio Code.

Using Rust for embedded systems development offers several advantages, including memory safety, concurrency support, and improved performance. Combined with the lightweight and modular Apache Mynewt operating system, Rust provides a powerful and secure foundation for developing applications for the nRF52 and other embedded platforms.

While this article focused on the nRF52 and Apache Mynewt, the principles and tools demonstrated can be applied to other microcontrollers and embedded operating systems that support Rust development. As the embedded systems landscape continues to evolve, languages like Rust and development environments like Visual Studio Code will play an increasingly important role in enabling more secure, efficient, and maintainable embedded software development.