Выбрать главу

openocd -f interface/stlink-v2.cfg -f target/stm32f3x.cfg

openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg

If one of those commands works it means you got an old hardware revision of the discovery board. That won't be a problem but commit that fact to memory as you'll need to configure things a bit differently later on. You can move to the next section.

If none of the commands work as a normal user then try to run them with root permission (e.g. sudo openocd ..). If the commands do work with root permission then check that the udev rules have been correctly set.

If you have reached this point and OpenOCD is not working please open an issue and we'll help you out!

In this section we'll walk you through the process of writing, building, flashing and debugging embedded programs. You will be able to try most of the examples without any special hardware as we will show you the basics using QEMU, a popular open-source hardware emulator. The only section where hardware is required is, naturally enough, the Hardware section, where we use OpenOCD to program an STM32F3DISCOVERY.

We'll start writing a program for the LM3S6965, a Cortex-M3 microcontroller. We have chosen this as our initial target because it can be emulated using QEMU so you don't need to fiddle with hardware in this section and we can focus on the tooling and the development process.

IMPORTANT We'll use the name "app" for the project name in this tutorial. Whenever you see the word "app" you should replace it with the name you selected for your project. Or, you could also name your project "app" and avoid the substitutions.

We'll use the cortex-m-quickstart project template to generate a new project from it. The created project will contain a barebone application: a good starting point for a new embedded rust application. In addition, the project will contain an examples directory, with several separate applications, highlighting some of the key embedded rust functionality.

First install cargo-generate

cargo install cargo-generate

Then generate a new project

cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart

Project Name: app

Creating project called `app`...

Done! New project created /tmp/app

cd app

Clone the repository

git clone https://github.com/rust-embedded/cortex-m-quickstart app

cd app

And then fill in the placeholders in the Cargo.toml file

[package]

authors = ["{{authors}}"] # "{{authors}}" -> "John Smith"

edition = "2018"

name = "{{project-name}}" # "{{project-name}}" -> "app"

version = "0.1.0"

# ..

[[bin]]

name = "{{project-name}}" # "{{project-name}}" -> "app"

test = false

bench = false

Grab the latest snapshot of the cortex-m-quickstart template and extract it.

curl -LO https://github.com/rust-embedded/cortex-m-quickstart/archive/master.zip

unzip master.zip

mv cortex-m-quickstart-master app

cd app

Or you can browse to cortex-m-quickstart, click the green "Clone or download" button and then click "Download ZIP".

Then fill in the placeholders in the Cargo.toml file as done in the second part of the "Using git" version.

For convenience here are the most important parts of the source code in src/main.rs:

#![no_std]

#![no_main]

use panic_halt as _;

use cortex_m_rt::entry;

#[entry]

fn main() -> ! {

loop {

// your code goes here

}

}

This program is a bit different from a standard Rust program so let's take a closer look.

#![no_std] indicates that this program will not link to the standard crate, std. Instead it will link to its subset: the core crate.

#![no_main] indicates that this program won't use the standard main interface that most Rust programs use. The main (no pun intended) reason to go with no_main is that using the main interface in no_std context requires nightly.

use panic_halt as _;. This crate provides a panic_handler that defines the panicking behavior of the program. We will cover this in more detail in the Panicking chapter of the book.

#[entry] is an attribute provided by the cortex-m-rt crate that's used to mark the entry point of the program. As we are not using the standard main interface we need another way to indicate the entry point of the program and that'd be #[entry].

fn main() -> !. Our program will be the only process running on the target hardware so we don't want it to end! We use a divergent function (the -> ! bit in the function signature) to ensure at compile time that'll be the case.

The next step is to cross compile the program for the Cortex-M3 architecture. That's as simple as running cargo build --target $TRIPLE if you know what the compilation target ($TRIPLE) should be. Luckily, the .cargo/config.toml in the template has the answer:

tail -n6 .cargo/config.toml

[build]

# Pick ONE of these compilation targets

# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+

target = "thumbv7m-none-eabi" # Cortex-M3