Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb48e8fbdd | ||
|
|
492ef04d3d | ||
|
|
d8ee697999 | ||
|
|
3da68b5f1d | ||
|
|
69c27cf5f2 | ||
|
|
fe7a225b00 | ||
|
|
e4e030c109 | ||
|
|
f278ec36b1 | ||
|
|
6cc89a0423 | ||
|
|
b08613a7fd | ||
|
|
44c312271e | ||
|
|
84783bca5e | ||
|
|
7e1dd57395 | ||
|
|
5810565cf6 | ||
|
|
bd34b10823 | ||
|
|
f2dcd25d4e | ||
|
|
a46be27bce | ||
|
|
d16c5af8f7 | ||
|
|
d2351e6049 | ||
|
|
d6e4a70e25 | ||
|
|
eeabf6b056 | ||
|
|
0fdc235a3c | ||
|
|
aa3cc8bcb3 | ||
|
|
8545dda435 | ||
|
|
7641877efe | ||
|
|
d37d5726ce | ||
|
|
2e48356a55 | ||
|
|
feec6bfb2a | ||
|
|
78bf6ff538 | ||
|
|
9c6bcd2ee8 | ||
|
|
c2d5c26e49 | ||
|
|
590efd3cfd | ||
|
|
498601c451 | ||
|
|
1edb3b94e3 | ||
|
|
28e7da3ad1 | ||
|
|
ec59c1c010 | ||
|
|
da3e868599 |
@@ -1,9 +1,14 @@
|
|||||||
|
# Configure builds for our target, the micro:bit's architecture
|
||||||
[target.thumbv6m-none-eabi]
|
[target.thumbv6m-none-eabi]
|
||||||
|
# Execute binary using gdb when calling cargo run
|
||||||
runner = "arm-none-eabi-gdb"
|
runner = "arm-none-eabi-gdb"
|
||||||
|
# Tweak to the linking process required by the cortex-m-rt crate
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "link-arg=-Wl,-Tlink.x",
|
"-C", "link-arg=-Tlink.x",
|
||||||
"-C", "link-arg=-nostartfiles",
|
# The LLD linker is selected by default
|
||||||
|
#"-C", "linker=arm-none-eabi-ld",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Automatically select this target when cargo building this project
|
||||||
[build]
|
[build]
|
||||||
target = "thumbv6m-none-eabi"
|
target = "thumbv6m-none-eabi"
|
||||||
|
|||||||
2
.gdbinit
2
.gdbinit
@@ -2,5 +2,5 @@ target remote :3333
|
|||||||
monitor arm semihosting enable
|
monitor arm semihosting enable
|
||||||
set print asm-demangle on
|
set print asm-demangle on
|
||||||
load
|
load
|
||||||
#break main
|
break main
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
language: rust
|
language: rust
|
||||||
rust: nightly-2018-08-01
|
rust: nightly-2018-10-12
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
|
MDBOOK_VER=0.2.1
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|
||||||
if [ "$(mdbook -V)" != "mdbook v0.1.8" ]; then
|
if [ "$(mdbook -V)" != "mdbook v$MDBOOK_VER" ]; then
|
||||||
curl -LSfs https://japaric.github.io/trust/install.sh | \
|
curl -LSfs https://japaric.github.io/trust/install.sh | \
|
||||||
sh -s -- \
|
sh -s -- \
|
||||||
--force \
|
--force \
|
||||||
--git rust-lang-nursery/mdBook \
|
--git rust-lang-nursery/mdBook \
|
||||||
--tag v0.1.8 \
|
--tag v$MDBOOK_VER \
|
||||||
--target x86_64-unknown-linux-musl \
|
--target x86_64-unknown-linux-musl \
|
||||||
|| true
|
|| true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(mdbook -V)" != "mdbook v0.1.8" ]; then
|
if [ "$(mdbook -V)" != "mdbook v$MDBOOK_VER" ]; then
|
||||||
cargo install --target x86_64-unknown-linux-gnu --version 0.1.8 mdbook \
|
cargo install --target x86_64-unknown-linux-gnu --version $MDBOOK_VER mdbook \
|
||||||
|| true
|
|| true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$(mdbook -V)" != "mdbook v0.1.8" ]; then
|
if [ "$(mdbook -V)" != "mdbook v$MDBOOK_VER" ]; then
|
||||||
cargo install --force --target x86_64-unknown-linux-gnu --version 0.1.8 mdbook
|
cargo install --force --target x86_64-unknown-linux-gnu --version $MDBOOK_VER mdbook
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rustup target add thumbv6m-none-eabi
|
rustup target add thumbv6m-none-eabi
|
||||||
|
|||||||
@@ -56,9 +56,11 @@
|
|||||||
- [Multiplexing](display/03.02.MULT.md)
|
- [Multiplexing](display/03.02.MULT.md)
|
||||||
- [Full Solution](display/03.03.FULL.md)
|
- [Full Solution](display/03.03.FULL.md)
|
||||||
|
|
||||||
|
- [WIP - Sensors and I²C](sensors/00.00.README.md)
|
||||||
|
|
||||||
- [WIP - Non-blocking](nb/00.00.README.md)
|
- [WIP - Non-blocking](nb/00.00.README.md)
|
||||||
|
|
||||||
- [WIP - Sensors and I²C](sensors/00.00.README.md)
|
- [WIP - Interrupts](nb/00.00.README.md)
|
||||||
|
|
||||||
- [WIP - Real time](rtfm/00.00.README.md)
|
- [WIP - Real time](rtfm/00.00.README.md)
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ in procedure 'ocd_bouncer'
|
|||||||
without root privilege.
|
without root privilege.
|
||||||
- Windows: You are probably missing the USB drivers.
|
- Windows: You are probably missing the USB drivers.
|
||||||
|
|
||||||
[these instructions]: setup/LINUX.html#udev%20rules
|
[these instructions]: ../setup/LINUX.html#udev%20rules
|
||||||
|
|
||||||
### can't connect to OpenOCD - "Polling again in X00ms"
|
### can't connect to OpenOCD - "Polling again in X00ms"
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ $ rustup target add thumbv7em-none-eabihf
|
|||||||
|
|
||||||
## Build problems
|
## Build problems
|
||||||
|
|
||||||
### `error: language item required, but not found: \`eh_personality\``
|
### `error: language item required, but not found: 'eh_personality'`
|
||||||
|
|
||||||
#### Cause
|
#### Cause
|
||||||
|
|
||||||
@@ -147,3 +147,14 @@ The `eh_personality` language item is used to implement stack unwinding in case
|
|||||||
You need to use the correct target
|
You need to use the correct target
|
||||||
by using `--target thumbv6m-none-eabi`
|
by using `--target thumbv6m-none-eabi`
|
||||||
or modifying `.cargo/config`
|
or modifying `.cargo/config`
|
||||||
|
|
||||||
|
### `error: ld: cannot open linker script file memory.x: No such file or directory`
|
||||||
|
|
||||||
|
#### Cause
|
||||||
|
|
||||||
|
A memory.x file is needed, this specifies memory layout.
|
||||||
|
|
||||||
|
#### Fix
|
||||||
|
|
||||||
|
Either ask the board support crate maintainer to add memory.x to their crate,
|
||||||
|
or add a memory.x file to your project.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
> Create a time delay.
|
> Create a time delay.
|
||||||
|
|
||||||
Another piece of information you will need is how to create a time delay before moving to the next row.
|
Another piece of information you will need is how to create a time delay before moving to the next row.
|
||||||
we want the time spent switching LED lines on and off to be much shorter than the time spent waiting with LEDs on.
|
We want the time spent switching LED lines on and off to be much shorter than the time spent waiting with LEDs on.
|
||||||
|
|
||||||
### For loop
|
### For loop
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "display"
|
name = "display"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m-rt="~0.5"
|
cortex-m-rt="~0.6"
|
||||||
cortex-m-semihosting="~0.3"
|
cortex-m-semihosting="~0.3"
|
||||||
panic-semihosting = "~0.3"
|
panic-semihosting = "~0.5"
|
||||||
microbit="~0.5"
|
microbit="~0.8"
|
||||||
|
|||||||
@@ -4,12 +4,10 @@
|
|||||||
extern crate panic_semihosting;
|
extern crate panic_semihosting;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
|
|
||||||
use microbit::hal::delay::Delay;
|
use microbit::hal::delay::Delay;
|
||||||
@@ -20,18 +18,6 @@ use microbit::hal::serial;
|
|||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
type LED = PIN<Output<PushPull>>;
|
type LED = PIN<Output<PushPull>>;
|
||||||
|
|
||||||
const DEFAULT_DELAY_MS: u32 = 2;
|
const DEFAULT_DELAY_MS: u32 = 2;
|
||||||
@@ -83,10 +69,10 @@ impl Display {
|
|||||||
/// Clear display
|
/// Clear display
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
for row in &mut self.rows {
|
for row in &mut self.rows {
|
||||||
row.set_low();
|
row.set_low().unwrap();
|
||||||
}
|
}
|
||||||
for col in &mut self.cols {
|
for col in &mut self.cols {
|
||||||
col.set_high();
|
col.set_high().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,38 +97,38 @@ impl Display {
|
|||||||
let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms);
|
let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms);
|
||||||
for _ in 0..loops {
|
for _ in 0..loops {
|
||||||
for (row_line, led_matrix_row) in self.rows.iter_mut().zip(led_matrix.iter()) {
|
for (row_line, led_matrix_row) in self.rows.iter_mut().zip(led_matrix.iter()) {
|
||||||
row_line.set_high();
|
row_line.set_high().unwrap();
|
||||||
for (col_line, led_matrix_val) in self.cols.iter_mut().zip(led_matrix_row.iter()) {
|
for (col_line, led_matrix_val) in self.cols.iter_mut().zip(led_matrix_row.iter()) {
|
||||||
// We are keeping it simple, and not adding brightness
|
// We are keeping it simple, and not adding brightness
|
||||||
if *led_matrix_val > 0 {
|
if *led_matrix_val > 0 {
|
||||||
col_line.set_low();
|
col_line.set_low().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delay.delay_ms(self.delay_ms);
|
delay.delay_ms(self.delay_ms);
|
||||||
for col_line in &mut self.cols {
|
for col_line in &mut self.cols {
|
||||||
col_line.set_high();
|
col_line.set_high().unwrap();
|
||||||
}
|
}
|
||||||
row_line.set_low();
|
row_line.set_low().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry!(main);
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
// Split GPIO
|
// Split GPIO
|
||||||
let mut gpio = p.GPIO.split();
|
let gpio = p.GPIO.split();
|
||||||
|
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
// Configure serial communication
|
// Configure serial communication
|
||||||
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
||||||
writeln!(tx, "");
|
writeln!(tx, "").unwrap();
|
||||||
writeln!(tx, "Init");
|
writeln!(tx, "Init").unwrap();
|
||||||
|
|
||||||
// Create delay provider
|
// Create delay provider
|
||||||
let mut delay = Delay::new(p.TIMER0);
|
let mut delay = Delay::new(p.TIMER0);
|
||||||
@@ -193,10 +179,10 @@ fn main() -> ! {
|
|||||||
[0, 1, 1, 1, 0],
|
[0, 1, 1, 1, 0],
|
||||||
];
|
];
|
||||||
|
|
||||||
writeln!(tx, "Starting!");
|
writeln!(tx, "Starting!").unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
writeln!(tx, "I <3 Rust on the micro:bit!");
|
writeln!(tx, "I <3 Rust on the micro:bit!").unwrap();
|
||||||
leds.display(&mut delay, letter_I, 1000);
|
leds.display(&mut delay, letter_I, 1000);
|
||||||
leds.display(&mut delay, heart, 1000);
|
leds.display(&mut delay, heart, 1000);
|
||||||
leds.display(&mut delay, letter_U, 1000);
|
leds.display(&mut delay, letter_U, 1000);
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
[target.thumbv6m-none-eabi]
|
|
||||||
runner = "arm-none-eabi-gdb"
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=-Wl,-Tlink.x",
|
|
||||||
"-C", "link-arg=-nostartfiles",
|
|
||||||
]
|
|
||||||
|
|
||||||
[build]
|
|
||||||
target = "thumbv6m-none-eabi"
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# New Project
|
# New Project
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ cargo new rustled
|
$ cargo new microrust-start
|
||||||
Created binary (application) `rustled` project
|
Created binary (application) `microrust-start` project
|
||||||
$ cd rustled
|
$ cd microrust-start
|
||||||
Cargo.toml src
|
Cargo.toml src
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ error[E0463]: can't find crate for `std`
|
|||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0463`.
|
For more information about this error, try `rustc --explain E0463`.
|
||||||
error: Could not compile `rustled`.
|
error: Could not compile `microrust-start`.
|
||||||
|
|
||||||
To learn more, run the command again with --verbose.
|
To learn more, run the command again with --verbose.
|
||||||
```
|
```
|
||||||
@@ -75,9 +75,6 @@ fn main() {
|
|||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ cargo build --target thumbv6m-none-eabi
|
$ cargo build --target thumbv6m-none-eabi
|
||||||
```
|
|
||||||
|
|
||||||
``` shell
|
|
||||||
error: cannot find macro `println!` in this scope
|
error: cannot find macro `println!` in this scope
|
||||||
--> src/main.rs:4:5
|
--> src/main.rs:4:5
|
||||||
|
|
|
|
||||||
@@ -91,11 +88,11 @@ We don't need it at the moment, so we can remove it and try to build again.
|
|||||||
## Build 3
|
## Build 3
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
error: language item required, but not found: `panic_impl`
|
$ cargo build --target thumbv6m-none-eabi
|
||||||
|
error: `#[panic_handler]` function required, but not found
|
||||||
```
|
```
|
||||||
|
|
||||||
This error, is because the panic macro is unimplemented,
|
This error, is because rustc required a panic handler to be implemented.
|
||||||
when rustc needs it to have an implementation.
|
|
||||||
|
|
||||||
### `panic_impl`
|
### `panic_impl`
|
||||||
|
|
||||||
@@ -112,15 +109,14 @@ If you have forgotten how to do this, try looking at [the cargo book][cargo].
|
|||||||
|
|
||||||
`Cargo.toml`
|
`Cargo.toml`
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies]
|
{{#include Cargo.toml:5:6}}
|
||||||
panic-abort = "~0.2"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`src/main.rs`
|
`src/main.rs`
|
||||||
``` rust
|
``` rust
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
@@ -130,9 +126,6 @@ fn main() {
|
|||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ cargo build --target thumbv6m-none-eabi
|
$ cargo build --target thumbv6m-none-eabi
|
||||||
```
|
|
||||||
|
|
||||||
``` shell
|
|
||||||
error: requires `start` lang_item
|
error: requires `start` lang_item
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -143,19 +136,21 @@ executing the binary usually has the operating system start by executing the C r
|
|||||||
This in turn invokes the Rust runtime, as marked by the `start` language item,
|
This in turn invokes the Rust runtime, as marked by the `start` language item,
|
||||||
which in turn invokes the main function.
|
which in turn invokes the main function.
|
||||||
|
|
||||||
Having enabled `no_std`, as we are targeting on a microcontroller,
|
Having enabled `no_std`, as we are targeting a microcontroller,
|
||||||
neither the crt0 nor the rust runtime are available,
|
neither the crt0 nor the rust runtime are available,
|
||||||
so even implementing `start` would not help us.
|
so even implementing `start` would not help us.
|
||||||
We need to replace the operating system entry point.
|
We need to replace the operating system entry point.
|
||||||
|
|
||||||
You could for example name a function after the default entry point,
|
You could for example name a function after the default entry point,
|
||||||
which for linux is `_start`, and start that way.
|
which for linux is `_start`, and start that way.
|
||||||
Note, you would also need to disable [name mangling][nm]:
|
Note, you would also need to disable [name mangling][nm]:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
extern crate panic_halt;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
@@ -172,9 +167,7 @@ At this point we need the help of a board-specific support crate and a few cargo
|
|||||||
Let us add a dependency on the board crate for the micro:bit.
|
Let us add a dependency on the board crate for the micro:bit.
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies]
|
{{#include Cargo.toml:5:7}}
|
||||||
panic-abort = "~0.2"
|
|
||||||
microbit="~0.5"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The microbit crate has 2 notable dependencies:
|
The microbit crate has 2 notable dependencies:
|
||||||
@@ -192,13 +185,15 @@ be implemented by board specific crates.
|
|||||||
|
|
||||||
This crate implements the minimal startup / runtime for Cortex-M microcontrollers.
|
This crate implements the minimal startup / runtime for Cortex-M microcontrollers.
|
||||||
Among other things this crate provides:
|
Among other things this crate provides:
|
||||||
- the `entry!` macro, to define the entry point of the program.
|
- the `#[entry]` attribute, to define the entry point of the program.
|
||||||
- the `exception!` macro, to set or override a processor core exception handler.
|
- a definition of the hard fault handler
|
||||||
|
- a definition of the default exception handler
|
||||||
|
|
||||||
This crate requires:
|
This crate requires:
|
||||||
- a definition of the specific microcontroller's memory layout as a memory.x file.
|
- a definition of the specific microcontroller's memory layout as a memory.x file.
|
||||||
- a definition of the hard fault handler
|
fortunately this is usually provided by the board support crates
|
||||||
- a definition of the default exception handler
|
|
||||||
|
To use the `#[entry]` attribute, we will need to add this as a dependency.
|
||||||
|
|
||||||
For more detailed information,
|
For more detailed information,
|
||||||
you can use the helpful [cortex-m-quickstart crate][qs] and [its documentation][doc].
|
you can use the helpful [cortex-m-quickstart crate][qs] and [its documentation][doc].
|
||||||
@@ -209,7 +204,7 @@ you can use the helpful [cortex-m-quickstart crate][qs] and [its documentation][
|
|||||||
## cargo config
|
## cargo config
|
||||||
|
|
||||||
Before we go any further,
|
Before we go any further,
|
||||||
we are going to tweak the cargo's configuration by editing `rustled/.cargo/config`.
|
we are going to tweak the cargo's configuration by editing `microrust-start/.cargo/config`.
|
||||||
For more information, you can read [the documentation here][cargoconfig].
|
For more information, you can read [the documentation here][cargoconfig].
|
||||||
|
|
||||||
[cargoconfig]: https://doc.rust-lang.org/cargo/reference/config.html
|
[cargoconfig]: https://doc.rust-lang.org/cargo/reference/config.html
|
||||||
@@ -217,19 +212,7 @@ For more information, you can read [the documentation here][cargoconfig].
|
|||||||
### `.cargo/config`
|
### `.cargo/config`
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
# Configure builds for our target
|
{{#include ../../.cargo/config}}
|
||||||
[target.thumbv6m-none-eabi]
|
|
||||||
# Execute binary using gdb
|
|
||||||
runner = "arm-none-eabi-gdb"
|
|
||||||
# Tweak to the linking process required by the cortex-m-rt crate
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=-Tlink.x",
|
|
||||||
"-C", "link-arg=-nostartfiles",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Automatically select this target when running cargo for this project
|
|
||||||
[build]
|
|
||||||
target = "thumbv6m-none-eabi"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### arm-none-eabi-gdb
|
### arm-none-eabi-gdb
|
||||||
@@ -246,20 +229,21 @@ and cargo will automatically add `--target thumbv6m-none-eabi`.
|
|||||||
|
|
||||||
### `Cargo.toml`
|
### `Cargo.toml`
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies]
|
{{#include Cargo.toml:5:8}}
|
||||||
panic-abort = "~0.2"
|
|
||||||
microbit="~0.5"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### `src/main.rs`
|
### `src/main.rs`
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
|
extern crate microbit;
|
||||||
|
|
||||||
entry!(main);
|
use cortex_m_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -269,22 +253,20 @@ $ cargo build
|
|||||||
```
|
```
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
error[E0308]: mismatched types
|
error: custom attribute panicked
|
||||||
--> src/main.rs:9:1
|
--> src/main.rs:7:1
|
||||||
|
|
|
|
||||||
8 | entry!(main);
|
7 | #[entry]
|
||||||
| ^^^^^^^^^^^^^ expected !, found ()
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: expected type `fn() -> !`
|
= help: message: `#[entry]` function must have signature `[unsafe] fn() -> !`
|
||||||
found type `fn() {main}`
|
|
||||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## `!` return type
|
## `!` return type
|
||||||
|
|
||||||
A little known rust feature, so I will forgive you if you do not know what this means.
|
A little known rust feature, so I will forgive you if you do not know what this means.
|
||||||
A return type of `!` means that the function cannot return
|
A return type of `!` means that the function cannot return.
|
||||||
An easy way to implement this, is by using an infinite loop.
|
An easy way to implement this is to use an infinite loop.
|
||||||
|
|
||||||
### `src/main.rs`
|
### `src/main.rs`
|
||||||
|
|
||||||
@@ -292,12 +274,12 @@ An easy way to implement this, is by using an infinite loop.
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
|
|
||||||
#[macro_use(entry)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
entry!(main);
|
use cortex_m_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
@@ -305,98 +287,19 @@ fn main() -> ! {
|
|||||||
|
|
||||||
## Build 6
|
## Build 6
|
||||||
|
|
||||||
``` shell
|
|
||||||
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
|
|
||||||
|
|
|
||||||
= note: "arm-none-eabi-gcc" "-L" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "/home/xxx/rust/rustled/target/thumbv6m-none-eabi/debug/deps/rustled-e6053d34b0422141.2yhvr0tmp69gb94x.rcgu.o" "-o"
|
|
||||||
# SNIP
|
|
||||||
"/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcore-fb37a4ea1db1e473.rlib" "-Wl,--end-group" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcompiler_builtins-f2357c0397dd7e0d.rlib" "-Wl,-Tlink.x" "-nostartfiles" "-Wl,-Bdynamic"
|
|
||||||
= note: /usr/lib/gcc/arm-none-eabi/8.1.0/../../../../arm-none-eabi/bin/ld: cannot open linker script file memory.x: No such file or directory
|
|
||||||
collect2: error: ld returned 1 exit status
|
|
||||||
```
|
|
||||||
|
|
||||||
A scary error, but if you look closely you will see `cannot open linker script file memory.x: No such file or directory`.
|
|
||||||
We mentioned something a little earlier about memory.x file.
|
|
||||||
To save you the hassle of scouring the internet for one or creating your own, you can copy it over into your project:
|
|
||||||
|
|
||||||
``` shell
|
|
||||||
$ cp ../../memory.x ./
|
|
||||||
```
|
|
||||||
|
|
||||||
> Often a board support crate will already include this, so this step will not be necessary.
|
|
||||||
|
|
||||||
## Build 7
|
|
||||||
|
|
||||||
``` shell
|
|
||||||
error: linking with `arm-none-eabi-gcc` failed: exit code: 1
|
|
||||||
|
|
|
||||||
= note: "arm-none-eabi-gcc" "-L" "/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib" "/home/xxx/rust/rustled/target/thumbv6m-none-eabi/debug/deps/rustled-e6053d34b0422141.2yhvr0tmp69gb94x.rcgu.o" "-o"
|
|
||||||
# SNIP
|
|
||||||
"/home/xxx/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/thumbv6m-none-eabi/lib/libcompiler_builtins-f2357c0397dd7e0d.rlib" "-Wl,-Tlink.x" "-nostartfiles" "-Wl,-Bdynamic"
|
|
||||||
= note: device.x:1: undefined symbol `DefaultHandler' referenced in expression
|
|
||||||
collect2: error: ld returned 1 exit status
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice `undefined symbol 'DefaultHandler' referenced in expression`.
|
|
||||||
We said earlier, as with the memory,
|
|
||||||
that the hard fault handler and default exception handler both need defining.
|
|
||||||
|
|
||||||
### `Cargo.toml`
|
|
||||||
|
|
||||||
``` toml
|
|
||||||
[dependencies]
|
|
||||||
panic-abort = "~0.2"
|
|
||||||
cortex-m-rt="~0.5"
|
|
||||||
microbit="~0.5"
|
|
||||||
```
|
|
||||||
|
|
||||||
### `src/main.rs`
|
|
||||||
|
|
||||||
``` rust
|
|
||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
|
|
||||||
extern crate panic_abort;
|
|
||||||
extern crate cortex_m_rt as rt;
|
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
|
||||||
|
|
||||||
use rt::ExceptionFrame;
|
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
It is all a bit ugly, but fortunately it only needs to be done once.
|
|
||||||
If you try building now, you should finally be greeted with `Finished`!
|
If you try building now, you should finally be greeted with `Finished`!
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ cargo build
|
$ cargo build
|
||||||
Finished dev [unoptimized + debuginfo] target(s) in 20.51s
|
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build Complete
|
## Build Complete
|
||||||
|
|
||||||
As a sanity check, let's verify that the produced executable is actually an ARM binary:
|
As a sanity check, let's verify that the produced executable is actually an ARM binary:
|
||||||
|
|
||||||
``` console
|
``` shell
|
||||||
$ file target/thumbv6m-none-eabi/debug/rustled
|
$ file target/thumbv6m-none-eabi/debug/microrust-start
|
||||||
target/thumbv6m-none-eabi/debug/rustled: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
|
target/thumbv6m-none-eabi/debug/microrust-start: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
|
||||||
^^^ ^^^^
|
^^^ ^^^^^
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Flashing is the process of moving our program into the microcontroller's (persistent) memory. Once flashed, the microcontroller will execute the flashed program every time it is powered on.
|
Flashing is the process of moving our program into the microcontroller's (persistent) memory. Once flashed, the microcontroller will execute the flashed program every time it is powered on.
|
||||||
|
|
||||||
In this case, our `rustled` program will be the only program in the microcontroller memory. By this I mean that there's nothing else running on the microcontroller: no OS, no daemon, nothing. `rustled` has full control over the device. This is what is meant by *bare-metal* programming.
|
In this case, our `microrust-start` program will be the only program in the microcontroller memory. By this I mean that there's nothing else running on the microcontroller: no OS, no daemon, nothing. `microrust-start` has full control over the device. This is what is meant by *bare-metal* programming.
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>OS</dt>
|
<dt>OS</dt>
|
||||||
@@ -71,8 +71,9 @@ available.
|
|||||||
I mentioned that OpenOCD provides a GDB server so let's connect to that right now:
|
I mentioned that OpenOCD provides a GDB server so let's connect to that right now:
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ arm-none-eabi-gdb -q target/thumbv6m-none-eabi/debug/rustled
|
# On Ubuntu use `gdb-mutliarch -q target/thumbv6m-none-eabi/debug//microrust-start`
|
||||||
Reading symbols from target/thumbv6m-none-eabi/debug/rustled...done.
|
$ arm-none-eabi-gdb -q target/thumbv6m-none-eabi/debug/microrust-start
|
||||||
|
Reading symbols from target/thumbv6m-none-eabi/debug/microrust-start...done.
|
||||||
(gdb)
|
(gdb)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -157,9 +158,9 @@ set print asm-demangle on
|
|||||||
# Load your program, breaks at entry
|
# Load your program, breaks at entry
|
||||||
load
|
load
|
||||||
# (optional) Add breakpoint at function
|
# (optional) Add breakpoint at function
|
||||||
break rustled::main
|
break main
|
||||||
# Continue with execution
|
# Continue with execution
|
||||||
continue
|
continue
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we can learn how to debug code on the micro:bit.
|
Now we can learn how to debug code on the micro:bit.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Before we start, let's add some code to debug:
|
|||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
// -- snip --
|
// -- snip --
|
||||||
entry!(main);
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let _y;
|
let _y;
|
||||||
let x = 42;
|
let x = 42;
|
||||||
@@ -28,14 +28,14 @@ At this time, we are not interested in that "pre-main" part so let's skip right
|
|||||||
the `main` function. We'll do that using a breakpoint:
|
the `main` function. We'll do that using a breakpoint:
|
||||||
|
|
||||||
```
|
```
|
||||||
(gdb) break rustled::main
|
(gdb) break main
|
||||||
Breakpoint 1 at 0x8000218: file src/main.rs, line 8.
|
Breakpoint 1 at 0x8000218: file src/main.rs, line 8.
|
||||||
|
|
||||||
(gdb) continue
|
(gdb) continue
|
||||||
Continuing.
|
Continuing.
|
||||||
Note: automatically using hardware breakpoints for read-only addresses.
|
Note: automatically using hardware breakpoints for read-only addresses.
|
||||||
|
|
||||||
Breakpoint 1, rustled::main () at src/rustled/src/main.rs:13
|
Breakpoint 1, main () at src/microrust-start/src/main.rs:13
|
||||||
13 let x = 42;
|
13 let x = 42;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -87,15 +87,15 @@ $1 = 42
|
|||||||
$2 = (i32 *) 0x10001fdc
|
$2 = (i32 *) 0x10001fdc
|
||||||
|
|
||||||
(gdb) print _y
|
(gdb) print _y
|
||||||
$3 = 134219052
|
$3 = -1
|
||||||
|
|
||||||
(gdb) print &_y
|
(gdb) print &_y
|
||||||
$4 = (i32 *) 0x10001fd8
|
$4 = (i32 *) 0x10001fd8
|
||||||
```
|
```
|
||||||
|
|
||||||
As expected, `x` contains the value `42`.
|
As expected, `x` contains the value `42`.
|
||||||
`_y` however, contains the value `134219052` (?).
|
`_y` however, contains the value `-1` (?).
|
||||||
Because `_y` has not been initialized yet, it contains some garbage value.
|
Because `_y` has not been initialized yet, it contains `-1`.
|
||||||
|
|
||||||
The command `print &x` prints the address of the variable `x`.
|
The command `print &x` prints the address of the variable `x`.
|
||||||
The interesting bit here is that GDB output shows the type of the reference:
|
The interesting bit here is that GDB output shows the type of the reference:
|
||||||
@@ -108,7 +108,7 @@ Instead of printing the local variables one by one, you can also use the `info l
|
|||||||
```
|
```
|
||||||
(gdb) info locals
|
(gdb) info locals
|
||||||
x = 42
|
x = 42
|
||||||
_y = 134219052
|
_y = -1
|
||||||
```
|
```
|
||||||
|
|
||||||
OK. With another `step`, we'll be on top of the `loop {}` statement:
|
OK. With another `step`, we'll be on top of the `loop {}` statement:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ This is a recap of what we have done so far.
|
|||||||
## `.cargo/config`
|
## `.cargo/config`
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
{{#include .cargo/config}}
|
{{#include ../../.cargo/config}}
|
||||||
```
|
```
|
||||||
|
|
||||||
## `.gdbinit`
|
## `.gdbinit`
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "start"
|
name = "start"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
panic-abort = "~0.2"
|
panic-halt = "~0.2"
|
||||||
cortex-m-rt="~0.5"
|
microbit="~0.8"
|
||||||
microbit="~0.5"
|
cortex-m-rt="~0.6"
|
||||||
|
|||||||
@@ -1,30 +1,16 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate cortex_m_rt;
|
||||||
extern crate cortex_m_rt as rt;
|
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
extern crate panic_halt;
|
||||||
|
|
||||||
use rt::ExceptionFrame;
|
use cortex_m_rt::entry;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let _y;
|
let _y;
|
||||||
let x = 42;
|
let x = 42;
|
||||||
_y = x;
|
_y = x;
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
In this chapter, we will discuss the basic I/O of embedded development in rust.
|
In this chapter, we will discuss the basic I/O of embedded development in rust.
|
||||||
|
|
||||||
After this chapter,you should have all the neccesary basic knowledge to do embedded development in Rust,
|
After this chapter, you should have all the neccesary basic knowledge to do embedded development in Rust,
|
||||||
with anything remaining being solution specific.
|
with anything remaining being solution specific.
|
||||||
|
|||||||
@@ -18,18 +18,19 @@ The micro:bit allows us to transmit and receive this serial communication over U
|
|||||||
|
|
||||||
To read and write to the serial bus from your computer, you will need to configure your tooling:
|
To read and write to the serial bus from your computer, you will need to configure your tooling:
|
||||||
|
|
||||||
- [*nix](hello-world/02.01.NIX.html)
|
- [*nix](../hello-world/02.01.NIX.html)
|
||||||
- [Windows](hello-world/02.02.WINDOWS.html)
|
- [Windows](../hello-world/02.02.WINDOWS.html)
|
||||||
|
|
||||||
## Code
|
## Code
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
|
use core::fmt::Write;
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
// -- snip --
|
// -- snip --
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
let mut gpio = p.GPIO.split();
|
let gpio = p.GPIO.split();
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ You now know enough to start playing around with the micro:bit's LED display and
|
|||||||
as well as logging data back to the host.
|
as well as logging data back to the host.
|
||||||
|
|
||||||
You should know that the microbit crate already includes an abstraction for the LED display for you to use.
|
You should know that the microbit crate already includes an abstraction for the LED display for you to use.
|
||||||
How to implemented a simple blocking display driver is demonstrated in the [LED display chapter](display/00.00.README.html).
|
How to implemented a simple blocking display driver is demonstrated in the [LED display chapter](../display/00.00.README.html).
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hello"
|
name = "hello"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m-rt="~0.5"
|
microbit="~0.8"
|
||||||
cortex-m-semihosting=""
|
cortex-m-rt="~0.6"
|
||||||
panic-semihosting = "~0.3"
|
cortex-m-semihosting="~0.3"
|
||||||
microbit="~0.5"
|
panic-semihosting = "~0.5"
|
||||||
|
|||||||
@@ -4,50 +4,36 @@
|
|||||||
extern crate panic_semihosting;
|
extern crate panic_semihosting;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
|
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
// Split GPIO
|
// Split GPIO
|
||||||
let mut gpio = p.GPIO.split();
|
let gpio = p.GPIO.split();
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
// Configure serial communication
|
// Configure serial communication
|
||||||
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
||||||
write!(tx, "serial - start\r\n");
|
write!(tx, "serial - start\r\n").unwrap();
|
||||||
// Get row and column for display
|
// Get row and column for display
|
||||||
let mut led = gpio.pin13.into_push_pull_output();
|
let mut led = gpio.pin13.into_push_pull_output();
|
||||||
let _ = gpio.pin4.into_push_pull_output();
|
let _ = gpio.pin4.into_push_pull_output();
|
||||||
// Set row high (column starts low)
|
// Set row high (column starts low)
|
||||||
led.set_high();
|
led.set_high().unwrap();
|
||||||
// Write string with newline and carriage return
|
// Write string with newline and carriage return
|
||||||
write!(tx, "serial - LED on\r\n");
|
write!(tx, "serial - LED on\r\n").unwrap();
|
||||||
}
|
}
|
||||||
panic!("End");
|
panic!("End");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Display
|
# Display
|
||||||
|
|
||||||
The micro:bit display is not trivial to control, so a driver is needed;
|
The micro:bit display is not trivial to control, so a driver is needed;
|
||||||
see [the display chapter](display/00.00.README.html) for more details.
|
see [the display chapter](../display/00.00.README.html) for more details.
|
||||||
|
|
||||||
Display calls for now are only blocking, and can either be for binary images (0 for off, 1 for on),
|
Display calls for now are only blocking, and can either be for binary images (0 for off, 1 for on),
|
||||||
or for monochrome images with differing brightness levels
|
or for monochrome images with differing brightness levels
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "microbit"
|
name = "micro"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m-rt="~0.5"
|
cortex-m-rt="~0.6"
|
||||||
cortex-m-semihosting=""
|
cortex-m-semihosting="~0.3"
|
||||||
panic-abort = "~0.2"
|
panic-halt = "~0.2"
|
||||||
panic-semihosting = "~0.3"
|
panic-semihosting = "~0.5"
|
||||||
microbit="~0.5"
|
microbit="~0.8"
|
||||||
|
|||||||
@@ -1,36 +1,22 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
|
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
// Split GPIO
|
// Split GPIO
|
||||||
let mut gpio = p.GPIO.split();
|
let gpio = p.GPIO.split();
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
|
|
||||||
#[macro_use(entry, exception)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
@@ -15,19 +13,7 @@ use microbit::hal::delay::Delay;
|
|||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
// Split GPIO
|
// Split GPIO
|
||||||
|
|||||||
@@ -5,57 +5,43 @@
|
|||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
extern crate panic_abort;
|
extern crate panic_halt;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
use rt::entry;
|
||||||
use rt::ExceptionFrame;
|
|
||||||
|
|
||||||
use microbit::hal::delay::Delay;
|
use microbit::hal::delay::Delay;
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
use microbit::led;
|
use microbit::led;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
let mut gpio = p.GPIO.split();
|
let mut gpio = p.GPIO.split();
|
||||||
let mut delay = Delay::new(p.TIMER0);
|
let mut delay = Delay::new(p.TIMER0);
|
||||||
|
|
||||||
// Configure display pins
|
// Configure display pins
|
||||||
let row1 = gpio.pin13.into_push_pull_output().downgrade();
|
let row1 = gpio.pin13.into_push_pull_output();
|
||||||
let row2 = gpio.pin14.into_push_pull_output().downgrade();
|
let row2 = gpio.pin14.into_push_pull_output();
|
||||||
let row3 = gpio.pin15.into_push_pull_output().downgrade();
|
let row3 = gpio.pin15.into_push_pull_output();
|
||||||
let col1 = gpio.pin4.into_push_pull_output().downgrade();
|
let col1 = gpio.pin4.into_push_pull_output();
|
||||||
let col2 = gpio.pin5.into_push_pull_output().downgrade();
|
let col2 = gpio.pin5.into_push_pull_output();
|
||||||
let col3 = gpio.pin6.into_push_pull_output().downgrade();
|
let col3 = gpio.pin6.into_push_pull_output();
|
||||||
let col4 = gpio.pin7.into_push_pull_output().downgrade();
|
let col4 = gpio.pin7.into_push_pull_output();
|
||||||
let col5 = gpio.pin8.into_push_pull_output().downgrade();
|
let col5 = gpio.pin8.into_push_pull_output();
|
||||||
let col6 = gpio.pin9.into_push_pull_output().downgrade();
|
let col6 = gpio.pin9.into_push_pull_output();
|
||||||
let col7 = gpio.pin10.into_push_pull_output().downgrade();
|
let col7 = gpio.pin10.into_push_pull_output();
|
||||||
let col8 = gpio.pin11.into_push_pull_output().downgrade();
|
let col8 = gpio.pin11.into_push_pull_output();
|
||||||
let col9 = gpio.pin12.into_push_pull_output().downgrade();
|
let col9 = gpio.pin12.into_push_pull_output();
|
||||||
|
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
|
|
||||||
let mut leds = led::Display::new(
|
let mut leds = led::Display::new(
|
||||||
row1, row2, row3, col1, col2, col3, col4, col5, col6, col7, col8, col9,
|
col1, col2, col3, col4, col5, col6, col7, col8, col9, row1, row2, row3,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
||||||
@@ -98,4 +84,4 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("End");
|
panic!("End");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serial"
|
name = "serial"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
heapless="~0.3"
|
heapless="~0.5"
|
||||||
cortex-m-rt="~0.5"
|
cortex-m-rt="~0.6"
|
||||||
cortex-m-semihosting=""
|
cortex-m-semihosting="~0.3"
|
||||||
panic-semihosting = "~0.3"
|
panic-semihosting = "~0.5"
|
||||||
microbit="~0.5"
|
microbit="~0.8"
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ extern crate panic_semihosting;
|
|||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
extern crate heapless;
|
extern crate heapless;
|
||||||
|
|
||||||
#[macro_use(entry, exception, block)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
use heapless::{consts, Vec, String};
|
use heapless::{consts, Vec, String};
|
||||||
|
|
||||||
@@ -19,19 +17,7 @@ use microbit::hal::delay::Delay;
|
|||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ extern crate panic_semihosting;
|
|||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
extern crate heapless;
|
extern crate heapless;
|
||||||
|
|
||||||
#[macro_use(entry, exception, block)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
use heapless::{consts, Vec, String};
|
use heapless::{consts, Vec, String};
|
||||||
|
|
||||||
@@ -19,19 +17,7 @@ use microbit::hal::delay::Delay;
|
|||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
|
|||||||
@@ -4,12 +4,10 @@
|
|||||||
extern crate panic_semihosting;
|
extern crate panic_semihosting;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
|
||||||
#[macro_use(entry, exception, block)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
|
|
||||||
use microbit::hal::delay::Delay;
|
use microbit::hal::delay::Delay;
|
||||||
@@ -18,18 +16,6 @@ use microbit::hal::serial;
|
|||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
use microbit::led;
|
use microbit::led;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
const WINNING_SCORE: u8 = 6;
|
const WINNING_SCORE: u8 = 6;
|
||||||
const QUESTION_COUNT: u8 = 2*WINNING_SCORE - 1;
|
const QUESTION_COUNT: u8 = 2*WINNING_SCORE - 1;
|
||||||
|
|
||||||
@@ -49,7 +35,7 @@ const LETTER_B: [[u8; 5]; 5] = [
|
|||||||
[0, 1, 1, 0, 0],
|
[0, 1, 1, 0, 0],
|
||||||
];
|
];
|
||||||
|
|
||||||
entry!(main);
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ extern crate panic_semihosting;
|
|||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
extern crate heapless;
|
extern crate heapless;
|
||||||
|
|
||||||
#[macro_use(entry, exception, block)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
use heapless::{consts, Vec};
|
use heapless::{consts, Vec};
|
||||||
|
|
||||||
@@ -19,19 +17,7 @@ use microbit::hal::delay::Delay;
|
|||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
|
|||||||
@@ -4,46 +4,33 @@
|
|||||||
extern crate panic_semihosting;
|
extern crate panic_semihosting;
|
||||||
extern crate cortex_m_rt as rt;
|
extern crate cortex_m_rt as rt;
|
||||||
extern crate cortex_m_semihosting as sh;
|
extern crate cortex_m_semihosting as sh;
|
||||||
|
|
||||||
#[macro_use(entry, exception, block)]
|
|
||||||
extern crate microbit;
|
extern crate microbit;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use rt::ExceptionFrame;
|
use rt::entry;
|
||||||
use sh::hio;
|
use sh::hio;
|
||||||
|
|
||||||
use microbit::hal::prelude::*;
|
use microbit::hal::prelude::*;
|
||||||
use microbit::hal::serial;
|
use microbit::hal::serial;
|
||||||
use microbit::hal::serial::BAUD115200;
|
use microbit::hal::serial::BAUD115200;
|
||||||
|
use microbit::block;
|
||||||
|
|
||||||
exception!(HardFault, hard_fault);
|
#[entry]
|
||||||
|
|
||||||
fn hard_fault(ef: &ExceptionFrame) -> ! {
|
|
||||||
panic!("{:#?}", ef);
|
|
||||||
}
|
|
||||||
|
|
||||||
exception!(*, default_handler);
|
|
||||||
|
|
||||||
fn default_handler(irqn: i16) {
|
|
||||||
panic!("Unhandled exception (IRQn = {})", irqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry!(main);
|
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let mut stdout = hio::hstdout().unwrap();
|
let mut stdout = hio::hstdout().unwrap();
|
||||||
writeln!(stdout, "Start").unwrap();
|
writeln!(stdout, "Start").unwrap();
|
||||||
if let Some(p) = microbit::Peripherals::take() {
|
if let Some(p) = microbit::Peripherals::take() {
|
||||||
// Split GPIO
|
// Split GPIO
|
||||||
let mut gpio = p.GPIO.split();
|
let gpio = p.GPIO.split();
|
||||||
// Configure RX and TX pins accordingly
|
// Configure RX and TX pins accordingly
|
||||||
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
let tx = gpio.pin24.into_push_pull_output().downgrade();
|
||||||
let rx = gpio.pin25.into_floating_input().downgrade();
|
let rx = gpio.pin25.into_floating_input().downgrade();
|
||||||
// Configure serial communication
|
// Configure serial communication
|
||||||
let (mut tx, mut rx) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
let (mut tx, mut rx) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();
|
||||||
writeln!(tx, "Start");
|
writeln!(tx, "Start").unwrap();
|
||||||
loop {
|
loop {
|
||||||
let val = block!(rx.read()).unwrap();
|
let val = block!(rx.read()).unwrap();
|
||||||
block!(tx.write(val));
|
block!(tx.write(val)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("End");
|
panic!("End");
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Here are the installation commands for a few Linux distributions.
|
|||||||
``` shell
|
``` shell
|
||||||
$ sudo apt-get install \
|
$ sudo apt-get install \
|
||||||
gcc-arm-none-eabi \
|
gcc-arm-none-eabi \
|
||||||
gdb-arm-none-eabi \
|
gdb-multiarch \
|
||||||
minicom \
|
minicom \
|
||||||
openocd
|
openocd
|
||||||
```
|
```
|
||||||
@@ -85,8 +85,6 @@ $ # ^^^^
|
|||||||
|
|
||||||
If `uucp` appears in the output. You are all set! Go to the [next section]. Otherwise, keep reading:
|
If `uucp` appears in the output. You are all set! Go to the [next section]. Otherwise, keep reading:
|
||||||
|
|
||||||
[next section]: setup/VERIFY.html
|
|
||||||
|
|
||||||
- Add yourself to the `uucp` group.
|
- Add yourself to the `uucp` group.
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
@@ -117,3 +115,5 @@ shells *won't* have access to `uucp` devices unless you manually re-log on them
|
|||||||
command.
|
command.
|
||||||
|
|
||||||
Now, go to the [next section].
|
Now, go to the [next section].
|
||||||
|
|
||||||
|
[next section]: ../setup/VERIFY.html
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
# macOS
|
# macOS
|
||||||
|
|
||||||
> UNTESTED: please submit an issue if you can confirm this works.
|
|
||||||
|
|
||||||
All the tools can be install using [Homebrew]:
|
All the tools can be install using [Homebrew]:
|
||||||
|
|
||||||
[Homebrew]: http://brew.sh/
|
[Homebrew]: http://brew.sh/
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ brew cask install gcc-arm-embedded
|
$ brew cask install https://raw.githubusercontent.com/Homebrew/homebrew-cask/b88346667547cc85f8f2cacb3dfe7b754c8afc8a/Casks/gcc-arm-embedded.rb
|
||||||
$ brew install minicom openocd
|
$ brew install minicom openocd
|
||||||
```
|
```
|
||||||
|
|
||||||
If the `brew cask` command doesn't work (`Error: Unknown command: cask`), then run `brew tap
|
Unfortunately gcc-arm-embedded has been [removed from Homebrew casks] in an attempt to force somebody to move it to Homebrew, and so it has to be installed using the cask in an earlier commit.
|
||||||
Caskroom/tap` first and try again.
|
|
||||||
|
[removed from Homebrew casks]: https://github.com/Homebrew/homebrew-cask/pull/56802
|
||||||
|
|
||||||
That's all! Go to the [next section].
|
That's all! Go to the [next section].
|
||||||
|
|
||||||
[next section]: setup/VERIFY.html
|
[next section]: ../setup/VERIFY.html
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ any recent version should work but we have listed the version we have tested.
|
|||||||
|
|
||||||
- `arm-none-eabi-gdb`.
|
- `arm-none-eabi-gdb`.
|
||||||
|
|
||||||
- `minicom` on Linux and macOS. Tested version: 2.7.
|
- `minicom` on Linux and macOS. Tested version: 2.7.
|
||||||
Readers report that `picocom` also works but we'll use `minicom` in this book.
|
Readers report that `picocom` also works but we'll use `minicom` in this book.
|
||||||
|
|
||||||
- `PuTTY` on Windows.
|
- `PuTTY` on Windows.
|
||||||
@@ -38,24 +38,18 @@ Next, follow OS-agnostic installation instructions for a few of the tools:
|
|||||||
|
|
||||||
Install rustup by following the instructions at [https://rustup.rs](https://rustup.rs).
|
Install rustup by following the instructions at [https://rustup.rs](https://rustup.rs).
|
||||||
|
|
||||||
Then, install or switch to the nightly channel.
|
**NOTE** Make sure you have a recent version, but only `1.39.0` is validated.
|
||||||
|
|
||||||
``` shell
|
|
||||||
$ rustup default nightly
|
|
||||||
```
|
|
||||||
|
|
||||||
**NOTE** Make sure you have a nightly newer than `nightly-2018-06-22`.
|
|
||||||
`rustc -V` should return a date newer than the one shown below:
|
`rustc -V` should return a date newer than the one shown below:
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ rustc -V
|
$ rustc -V
|
||||||
rustc 1.28.0-nightly (056f589fb 2018-06-22)
|
rustc 1.39.0 (4560ea788 2019-11-04)
|
||||||
```
|
```
|
||||||
|
|
||||||
### OS specific instructions
|
### OS specific instructions
|
||||||
|
|
||||||
Now follow the instructions specific to the OS you are using:
|
Now follow the instructions specific to the OS you are using:
|
||||||
|
|
||||||
- [Linux](setup/LINUX.html)
|
- [Linux](../setup/LINUX.html)
|
||||||
- [Windows](setup/WINDOWS.html)
|
- [Windows](../setup/WINDOWS.html)
|
||||||
- [macOS](setup/MACOS.html)
|
- [macOS](../setup/MACOS.html)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Bus 002 Device 033: ID 0d28:0204 NXP ARM mbed
|
|||||||
```
|
```
|
||||||
|
|
||||||
In my case, the micro:bit got connected to the bus #2 and got enumerated as the device #33.
|
In my case, the micro:bit got connected to the bus #2 and got enumerated as the device #33.
|
||||||
This means the file `/dev/bus/usb/002/033` *is* the Fmicro:bit3.
|
This means the file `/dev/bus/usb/002/033` is the micro:bit.
|
||||||
Let's check its permissions:
|
Let's check its permissions:
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
@@ -30,7 +30,7 @@ crw-rw---- 1 root uucp 189, 160 Jul 8 14:06 /dev/bus/usb/002/033
|
|||||||
The group should be `uucp`.
|
The group should be `uucp`.
|
||||||
If it's not ... then check your [udev rules] and try re-loading them with:
|
If it's not ... then check your [udev rules] and try re-loading them with:
|
||||||
|
|
||||||
[udev rules]: setup/LINUX.html#udev%20rules
|
[udev rules]: ../setup/LINUX.html#udev%20rules
|
||||||
|
|
||||||
``` shell
|
``` shell
|
||||||
$ sudo udevadm control --reload-rules
|
$ sudo udevadm control --reload-rules
|
||||||
@@ -79,7 +79,7 @@ Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
|
|||||||
|
|
||||||
(If you don't ... then check the [general troubleshooting] instructions.)
|
(If you don't ... then check the [general troubleshooting] instructions.)
|
||||||
|
|
||||||
[general troubleshooting]: appendix/troubleshooting.html
|
[general troubleshooting]: ../appendix/troubleshooting.html
|
||||||
|
|
||||||
`openocd` will block the terminal. That's fine.
|
`openocd` will block the terminal. That's fine.
|
||||||
|
|
||||||
|
|||||||
@@ -40,4 +40,4 @@ Download the latest `putty.exe` from [this site] and place it somewhere in your
|
|||||||
|
|
||||||
That's all! Go to the [next section].
|
That's all! Go to the [next section].
|
||||||
|
|
||||||
[next section]: setup/VERIFY.html
|
[next section]: ../setup/VERIFY.html
|
||||||
|
|||||||
@@ -9,42 +9,36 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="theme-color" content="#ffffff" />
|
<meta name="theme-color" content="#ffffff" />
|
||||||
|
|
||||||
<base href="{{ path_to_root }}">
|
<link rel="shortcut icon" href="{{ path_to_root }}{{ favicon }}">
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}css/general.css">
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
|
||||||
|
|
||||||
<link rel="stylesheet" href="book.css">
|
<!-- Fonts -->
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
|
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="{{ favicon }}">
|
<!-- Highlight.js Stylesheets -->
|
||||||
|
<link rel="stylesheet" href="{{ path_to_root }}highlight.css">
|
||||||
<!-- Font Awesome -->
|
<link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
|
||||||
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
<link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="highlight.css">
|
|
||||||
<link rel="stylesheet" href="tomorrow-night.css">
|
|
||||||
<link rel="stylesheet" href="ayu-highlight.css">
|
|
||||||
|
|
||||||
<!-- Custom theme stylesheets -->
|
<!-- Custom theme stylesheets -->
|
||||||
{{#each additional_css}}
|
{{#each additional_css}}
|
||||||
<link rel="stylesheet" href="{{this}}">
|
<link rel="stylesheet" href="{{ this }}">
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#if mathjax_support}}
|
{{#if mathjax_support}}
|
||||||
<!-- MathJax -->
|
<!-- MathJax -->
|
||||||
<script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
<script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
||||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-111729278-2"></script>
|
|
||||||
<script>
|
|
||||||
window.dataLayer = window.dataLayer || [];
|
|
||||||
function gtag(){dataLayer.push(arguments);}
|
|
||||||
gtag('js', new Date());
|
|
||||||
gtag('config', 'UA-111729278-2');
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="light">
|
<body class="light">
|
||||||
|
<!-- Provide site root to javascript -->
|
||||||
|
<script type="text/javascript">var path_to_root = "{{ path_to_root }}";</script>
|
||||||
|
|
||||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
try {
|
try {
|
||||||
@@ -116,7 +110,7 @@
|
|||||||
<h1 class="menu-title">{{ book_title }}</h1>
|
<h1 class="menu-title">{{ book_title }}</h1>
|
||||||
|
|
||||||
<div class="right-buttons">
|
<div class="right-buttons">
|
||||||
<a href="print.html" class="icon-button" title="Print this book" aria-label="Print this book">
|
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
|
||||||
<i id="print-button" class="fa fa-print"></i>
|
<i id="print-button" class="fa fa-print"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/droogmic/microrust" class="icon-button" title="Go to GitHub repo" aria-label="Link to GitHub repo">
|
<a href="https://github.com/droogmic/microrust" class="icon-button" title="Go to GitHub repo" aria-label="Link to GitHub repo">
|
||||||
@@ -156,13 +150,13 @@
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
{{#previous}}
|
{{#previous}}
|
||||||
<a rel="prev" href="{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
{{/previous}}
|
{{/previous}}
|
||||||
|
|
||||||
{{#next}}
|
{{#next}}
|
||||||
<a rel="next" href="{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
{{/next}}
|
{{/next}}
|
||||||
@@ -174,13 +168,13 @@
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
{{#previous}}
|
{{#previous}}
|
||||||
<a href="{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
{{/previous}}
|
{{/previous}}
|
||||||
|
|
||||||
{{#next}}
|
{{#next}}
|
||||||
<a href="{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
{{/next}}
|
{{/next}}
|
||||||
@@ -225,29 +219,26 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if playpen_js}}
|
{{#if playpen_js}}
|
||||||
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if search_enabled}}
|
|
||||||
<script src="searchindex.js" type="text/javascript" charset="utf-8"></script>
|
|
||||||
{{/if}}
|
|
||||||
{{#if search_js}}
|
{{#if search_js}}
|
||||||
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}mark.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}searcher.js" type="text/javascript" charset="utf-8"></script>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
<script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
|
||||||
<!-- Custom JS scripts -->
|
<!-- Custom JS scripts -->
|
||||||
{{#each additional_js}}
|
{{#each additional_js}}
|
||||||
<script type="text/javascript" src="{{this}}"></script>
|
<script type="text/javascript" src="{{ path_to_root }}{{this}}"></script>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#if is_print}}
|
{{#if is_print}}
|
||||||
|
|||||||
Reference in New Issue
Block a user