Skip to content

Commit

Permalink
Add hello world example
Browse files Browse the repository at this point in the history
  • Loading branch information
rstropek committed Nov 1, 2024
1 parent 72dbb1f commit 2ccdc1d
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 0 deletions.
7 changes: 7 additions & 0 deletions hello-embedded/hello-world/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[build]
target = "thumbv7em-none-eabihf"

[target.thumbv7em-none-eabihf]
rustflags = [
"-C", "link-arg=-Tlink.x"
]
5 changes: 5 additions & 0 deletions hello-embedded/hello-world/.embed.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[default.general]
chip = "nRF52833_xxAA"

[default.rtt]
enabled = true
5 changes: 5 additions & 0 deletions hello-embedded/hello-world/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rust-analyzer.check.targets": "thumbv7em-none-eabihf",
"rust-analyzer.cargo.allTargets": false,
"rust-analyzer.check.allTargets": false
}
10 changes: 10 additions & 0 deletions hello-embedded/hello-world/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "hello-world"
version = "0.1.0"
edition = "2021"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.3"
panic-halt = "1.0.0"
rtt-target = "0.5.0"
5 changes: 5 additions & 0 deletions hello-embedded/hello-world/memory.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
}
61 changes: 61 additions & 0 deletions hello-embedded/hello-world/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![no_std]
#![no_main]

use core::ptr::write_volatile;

use cortex_m::asm::nop;
use cortex_m_rt::entry;
use panic_halt as _;
use rtt_target::{rprintln, rtt_init_print};

#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("Hello world!");

// The LED matrix is organized into rows (ROW1 to ROW5) and columns (COL1 to COL5). Each row and column represents
// connections to LEDs in a grid formation, where each intersection can turn on or off an LED by controlling the flow of current.
// In a 5x5 matrix like this, there are 25 LEDs, arranged in rows and columns. Each LED is placed at an intersection of a row and a column.
// By setting a row to a high (positive) voltage and a column to low (grounded), current can flow through the corresponding LED
// in that row and column, causing it to light up.
// (see also Microbit Schematic at https://tech.microbit.org/hardware/schematic/, page 2

// In our example, we will use ROW1 and COL1 to turn on an LED. From the schematics (page 3), we can see that
// ROW1 is connected to Port 0/Pin 21 and COL1 is connected to Port 0/Pin 28.

// Configuration of GPIO happens in the PIN_CNF registers. The data sheet for nRF52833
// (https://docs-be.nordicsemi.com/bundle/ps_nrf52833/attach/nRF52833_PS_v1.7.pdf?_LANG=enus) tells us that the
// base address for PIN_CNF registers is 0x5000_0000 (page 231). The offset for GPIO21 is 0x754 and for GPIO28 it is 0x770
// (page 232). We control the value of the pins using the OUT register. To set pin 21 high, we need to
// write 1 to bit 21 of the OUT register (page 232). The offset for the OUT register is 0x504 (page 231).

const GPIO0_PINCNF21_ROW1_ADDR: *mut u32 = 0x5000_0754 as *mut u32;
const GPIO0_PINCNF28_COL1_ADDR: *mut u32 = 0x5000_0770 as *mut u32;
const DIR_OUTPUT_POS: u32 = 0; // Bit in configuration register to choose between input and output (page 269)
const PINCNF_DRIVE_LED: u32 = 1 << DIR_OUTPUT_POS; // 1 means output, 0 means input (page 269) -> we need 1

// Configure the direction of the pins to output
unsafe {
// Set the direction of the pins 21 and 28 to output
write_volatile(GPIO0_PINCNF21_ROW1_ADDR, PINCNF_DRIVE_LED);
write_volatile(GPIO0_PINCNF28_COL1_ADDR, PINCNF_DRIVE_LED);
}

const GPIO0_OUT_ADDR: *mut u32 = 0x5000_0504 as *mut u32;
const GPIO0_OUT_ROW1_POS: u32 = 21; // Bit in the OUT register to control GPIO21
let mut is_on = false;
loop {
rprintln!("Echo...");
unsafe {
// Set the value of the OUT register to turn on or off the LED
// We do not set the value for GPIO28 because we want it to be off
write_volatile(GPIO0_OUT_ADDR, (is_on as u32) << GPIO0_OUT_ROW1_POS);
}

for _ in 0..100_000 {
nop();
}

is_on = !is_on;
}
}

0 comments on commit 2ccdc1d

Please sign in to comment.