-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathREADME.md
More file actions
274 lines (225 loc) · 9.09 KB
/
Copy pathREADME.md
File metadata and controls
274 lines (225 loc) · 9.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

## FREE Reverse Engineering Self-Study Course [HERE](https://github.com/mytechnotalent/Reverse-Engineering-Tutorial)
<br>
# Rust Embassy microbit Project
A simple embedded Rust project running on the microbit v2, built with Embassy async framework and no_std runtime.
<br>
# Features
- **5x5 LED Matrix Display**: Async display driver with custom fonts and animations
- **Dual Button Support**: Button A and Button B with debouncing
- **Motion Sensing**: LSM303AGR accelerometer and magnetometer support
- **Audio**: Speaker and microphone interfaces
- **Bluetooth Low Energy**: Optional BLE support with trouble stack
- **GPIO Access**: All edge connector pins available (P0-P20)
- **Communication**: UART, I2C, SPI peripheral access
- **Timers & PWM**: Multiple timer and PWM channel support
- **Async/Await**: Built on Embassy's cooperative scheduler
- **No Heap**: Runs entirely in static memory with deterministic behavior
<br>
# Project Structure
- `src/display/`: 5x5 LED matrix driver with fonts and bitmap support
- `examples/`: Various example applications demonstrating features
<br>
# Examples
## Display Example
Demonstrates LED matrix control with button interactions:
```bash
cd examples/display
cargo run --release
```
<br>
# How It Works (Step-by-Step)
1. **Startup**
- The nRF52833 boot ROM loads your program from flash memory
- The Cortex-M `cortex-m-rt` runtime (`#[no_main]`) bypasses traditional `main()`
- The reset vector jumps to `__cortex_m_rt_main_trampoline`
- Embassy executor is initialized and starts the async runtime
2. **Board Initialization**
- `embassy_nrf::init()` configures clocks, GPIO, and peripherals
- The `Microbit::default()` creates instances of all peripherals:
- 5x5 LED matrix (rows: P0_21, P0_22, P0_15, P0_24, P0_19)
- Button A (P0_14) and Button B (P0_23)
- Speaker (P0_00), Microphone (P0_05)
- All edge connector pins (P0-P20)
- Internal I2C for accelerometer/magnetometer
3. **Executor Task Management**
- Embassy's executor uses a lock-free task queue for cooperative scheduling
- Tasks are enqueued when spawned or when wakers are triggered
- The executor polls tasks in FIFO order
- When all tasks are pending, CPU enters WFI (Wait-For-Interrupt) for power efficiency
4. **Peripheral Abstractions**
- **LED Matrix**: Time-multiplexed 5x5 display with async frame timing
- **Buttons**: GPIO inputs with internal pull-ups, async edge detection
- **Motion Sensors**: I2C communication with LSM303AGR via async interface
- **Audio**: PWM-based speaker control and ADC microphone sampling
- **BLE**: Optional Bluetooth stack integration with async event handling
5. **Async Event Handling**
- GPIO interrupts trigger task wakers for button presses
- Timer interrupts handle display refresh and delays
- I2C/SPI interrupts manage sensor communication
- All operations are non-blocking, allowing concurrent execution
6. **Memory Management**
- Static allocation only - no heap fragmentation
- Compile-time memory layout with predictable behavior
- Embassy's static task allocation ensures deterministic performance
<br>
# Embassy Executor Deep Dive
## Task Scheduling Architecture
- **Enqueue Operation**: Tasks are added to the tail of a bounded queue when spawned or awakened
- **Dequeue Operation**: Executor pops tasks from the head (FIFO) for polling
- **Cooperative Scheduling**: Tasks must yield (await) to allow others to run
- **Waker System**: Peripheral interrupts trigger task re-scheduling via wakers
## Memory Layout
```
Flash Memory:
├── Vector Table (0x00000000)
├── Program Code
├── Static Data
└── Embassy Runtime
RAM Memory:
├── Task Queue (statically allocated)
├── Task Control Blocks
├── Stack Space
└── Peripheral Buffers
```
## Interrupt Integration
- **GPIOTE**: Button press/release detection
- **RTC**: Timer-based delays and scheduling
- **TWI**: I2C sensor communication
- **PWM**: Audio output generation
- **RADIO**: Bluetooth communication (optional)
<br>
# Peripheral Pin Mapping
## Internal Connections
| Function | Pin | Description |
| ---------------- | --------------------------------- | -------------------------- |
| LED Matrix Rows | P0_21, P0_22, P0_15, P0_24, P0_19 | Row drivers |
| LED Matrix Cols | P0_28, P0_11, P0_31, P1_05, P0_30 | Column drivers |
| Button A | P0_14 | Pull-up enabled |
| Button B | P0_23 | Pull-up enabled |
| Speaker | P0_00 | PWM audio output |
| Microphone | P0_05 | ADC input |
| Mic Enable | P0_20 | Microphone power |
| Internal I2C SCL | P0_08 | Accelerometer/Magnetometer |
| Internal I2C SDA | P0_16 | Accelerometer/Magnetometer |
## Edge Connector
| Connector | Pin | GPIO | Description |
| --------- | ----- | ----- | ------------------- |
| P0 | Large | P0_02 | General purpose I/O |
| P1 | Large | P0_03 | General purpose I/O |
| P2 | Large | P0_04 | General purpose I/O |
| P8 | Small | P0_10 | General purpose I/O |
| P9 | Small | P0_09 | General purpose I/O |
| P12 | Small | P0_12 | General purpose I/O |
| P13 | Small | P0_17 | General purpose I/O |
| P14 | Small | P0_01 | General purpose I/O |
| P15 | Small | P0_13 | General purpose I/O |
| P16 | Small | P1_02 | General purpose I/O |
| P19 | Small | P0_26 | General purpose I/O |
| P20 | Small | P1_00 | General purpose I/O |
<br>
# Building and Flashing
## Prerequisites
**Software:**
- Rust toolchain with `thumbv7em-none-eabihf` target
- [`probe-rs`](https://probe.rs/) for flashing and debugging
- [`rustup`](https://rustup.rs/) for Rust installation
**Hardware:**
- [BBC micro:bit v2](https://microbit.org/)
- USB cable for power and programming
- Optional: External debugger probe for advanced debugging
### Installation
```bash
# Install Rust if not already installed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Add the target for micro:bit
rustup target add thumbv7em-none-eabihf
# Install probe-rs
cargo install probe-rs-tools --locked
```
## Build Commands
```bash
# Build the library
cargo build
# Build with optimizations
cargo build --release
# Build specific example
cd examples/display
cargo build --release
```
## Flash Commands
```bash
# Flash example to micro:bit
cd examples/display
cargo run --release
# Flash with probe-rs directly
probe-rs run --chip nRF52833_xxAA target/thumbv7em-none-eabihf/release/display-example
# Flash and attach debugger
probe-rs run --chip nRF52833_xxAA --attach-under-reset target/thumbv7em-none-eabihf/release/display-example
```
## Debugging
```bash
# Start GDB session
probe-rs gdb --chip nRF52833_xxAA target/thumbv7em-none-eabihf/release/display-example
# View defmt logs
probe-rs run --chip nRF52833_xxAA target/thumbv7em-none-eabihf/release/display-example
```
<br>
# Feature Flags
| Feature | Description | Dependencies |
| --------- | -------------------------------------- | ------------------------------ |
| `default` | Basic functionality with defmt logging | `defmt` |
| `defmt` | Logging and debugging support | defmt crates |
| `trouble` | Bluetooth Low Energy support | nrf-sdc, nrf-mpsl, static_cell |
Enable features in Cargo.toml:
```toml
[dependencies]
microbit-bsp = { version = "0.4.0", features = ["trouble"] }
```
<br>
# API Examples
## Basic LED Matrix Control
```rust
use microbit_bsp::*;
use embassy_time::Duration;
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let board = Microbit::default();
let mut display = board.display;
// Show a heart pattern
let heart = display::bitmap![
[0, 1, 0, 1, 0]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[0, 1, 1, 1, 0]
[0, 0, 1, 0, 0]
];
display.display(heart, Duration::from_secs(2)).await;
}
```
## Button Handling
```rust
use embassy_futures::select::{select, Either};
loop {
match select(board.btn_a.wait_for_low(), board.btn_b.wait_for_low()).await {
Either::First(_) => {
// Button A pressed
display.display(display::fonts::ARROW_LEFT, Duration::from_millis(500)).await;
}
Either::Second(_) => {
// Button B pressed
display.display(display::fonts::ARROW_RIGHT, Duration::from_millis(500)).await;
}
}
}
```
<br>
# Requirements
- **Rust**: Nightly channel (for async embedded features)
- **Target**: thumbv7em-none-eabihf (Cortex-M4F with hardware FPU)
- **Hardware**: BBC micro:bit v2 with nRF52833 SoC
- **Memory**: 512KB Flash, 128KB RAM
- **Clock**: 64MHz ARM Cortex-M4F with FPU
<br>
# License
Apache-2.0 License