Skip to content

Commit d0b9b90

Browse files
authored
Merge pull request #8 from Neotron-Compute/booting_updates
Booting updates
2 parents 014e757 + c3af21f commit d0b9b90

File tree

7 files changed

+398
-125
lines changed

7 files changed

+398
-125
lines changed

.cargo/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# This will make a UF2 and copy it to the RP2040's Mass Storage Device bootloader
33
# runner = "elf2uf2-rs -d"
44
# This will flash over SWD with any compatible probe it finds. You need 0.3.1 or higher for RP2040 support.
5-
runner = "probe-run --chip RP2040"
5+
runner = "probe-run --chip RP2040 --measure-stack"
66

77
rustflags = [
88
# This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x

.github/workflows/rust.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ jobs:
3434
override: true
3535
- name: Install Rust targets for ${{ matrix.rust }}
3636
run: rustup target install --toolchain=${{ matrix.rust }} thumbv6m-none-eabi
37-
- name: Build
38-
run: cargo build --verbose
3937
- name: Build Release
4038
run: cargo build --release --verbose
4139
- name: Clippy

Cargo.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ version = "0.2.0"
1111
# Useful Cortex-M specific functions (e.g. SysTick)
1212
cortex-m = "0.7"
1313
# The Raspberry Pi Pico HAL
14-
pico = { git = "https://github.com/rp-rs/rp-hal.git" }
14+
rp-pico = "0.3"
1515
# Cortex-M run-time (or start-up) code
1616
cortex-m-rt = "0.7"
1717
# The BIOS API we export to the OS
@@ -28,12 +28,12 @@ defmt = "0.3"
2828
defmt-rtt = "0.3"
2929
# Send panics to the debugger
3030
panic-probe = "0.2"
31-
# Fetches the BIOS version from git
31+
# Fetches git hashes from git at compile time
3232
git-version = "0.3"
33-
# RP2040 PIO driver
34-
pio = { git = "https://github.com/rp-rs/pio-rs.git", branch = "main" }
35-
# RP2040 PIO driver macros
36-
pio-proc = { git = "https://github.com/rp-rs/pio-rs.git", branch = "main" }
33+
# RP2040 PIO assembler
34+
pio = "0.2"
35+
# Macros for RP2040 PIO assembler
36+
pio-proc = "0.2"
3737

3838
[features]
3939
default = [

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ The Neotron BIOS uses the [defmt](https://crates.io/crates/defmt) crate to provi
4747

4848
2. Flash your *Debugger* Pico with https://github.com/majbthrd/DapperMime firmware (e.g. by copying the UF2 file to the USB Mass Storage device)
4949

50-
3. On your PC, install *probe-rs-rp* from the RP2040-specific [probe-run](https://github.com/knurling-rs/probe-run) fork at https://github.com/rp-rs/probe-run.
50+
3. On your PC, install [*probe-rs*](https://github.com/knurling-rs/probe-run), the programming tool from [Ferrous System's](https://www.ferrous-systems.com) [Knurling Project](https://github.com/knurling).
5151

5252
```console
53-
user@host ~ $ cargo install probe-rs-rp
53+
user@host ~ $ cargo install probe-rs
5454
```
5555

5656
4. Power on your Neotron Pico.
5757

58-
5. Build and load the Neotron BIOS, and view the debug output stream, with `cargo run`:
58+
5. Build and load the Neotron BIOS, and view the debug output stream, with `cargo run --release`:
5959

6060
```console
61-
user@host ~/neotron-pico-bios $ cargo run --release
61+
user@host ~/neotron-pico-bios $ DEFMT_LOG=debug cargo run --release
6262
Compiling neotron-pico-bios v0.1.0 (/home/jonathan/Documents/neotron/neotron-pico-bios)
6363
Finished release [optimized + debuginfo] target(s) in 0.76s
6464
Running `probe-run-rp --chip RP2040 target/thumbv6m-none-eabi/release/neotron-pico-bios`
@@ -75,6 +75,8 @@ user@host ~/neotron-pico-bios $ cargo run --release
7575
└─ neotron_pico_bios::__cortex_m_rt_main @ src/main.rs:128
7676
```
7777

78+
You should see your Neotron Pico boot, both over RTT in the `probe-run` output, and also on the VGA output.
79+
7880
## Changelog
7981

8082
See [CHANGELOG.md](./CHANGELOG.md)

memory.x

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,46 @@ MEMORY {
2121
/*
2222
* This is the remainder of the 2048 KiB flash chip.
2323
*/
24-
FLASH_OS: ORIGIN = 0x10020000, LENGTH = 2048K - 128K
24+
FLASH_OS : ORIGIN = 0x10020000, LENGTH = 2048K - 128K
2525
/*
26-
* This is the internal SRAM in the RP2040.
26+
* This is the bottom of the four striped banks of SRAM in the RP2040.
2727
*/
28-
RAM : ORIGIN = 0x20000000, LENGTH = 256K
28+
RAM_OS : ORIGIN = 0x20000000, LENGTH = 0x3C000
29+
/*
30+
* This is the top of the four striped banks of SRAM in the RP2040.
31+
*/
32+
RAM : ORIGIN = 0x2003C000, LENGTH = 16K
33+
/*
34+
* This is the fifth bank, a 4KB block. We use this for Core 0 Stack.
35+
*/
36+
RAM_CORE0_STACK : ORIGIN = 0x20040000, LENGTH = 4K
37+
/*
38+
* This is the sixth bank, a 4KB block. We use this for Core 1 Stack.
39+
*/
40+
RAM_CORE1_STACK : ORIGIN = 0x20041000, LENGTH = 4K
2941
}
30-
/* This is where the call stack will be allocated. */
31-
/* The stack is of the full descending type. */
32-
/* You may want to use this variable to locate the call stack and static
33-
variables in different memory regions. Below is shown the default value */
34-
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
42+
43+
/*
44+
* This is where the call stack for Core 0 will be located. The stack is of
45+
* the full descending type. You may want to use this variable to locate the
46+
* call stack and static variables in different memory regions. Below is
47+
* shown the default value
48+
*/
49+
_stack_start = ORIGIN(RAM_CORE0_STACK) + LENGTH(RAM_CORE0_STACK);
50+
51+
/*
52+
* This is where the call stack for Core 1 will be located.
53+
*/
54+
_core1_stack_bottom = ORIGIN(RAM_CORE1_STACK);
55+
_core1_stack_len = LENGTH(RAM_CORE1_STACK);
3556

3657
/*
3758
* Export some symbols to tell the BIOS where it might find the OS.
3859
*/
3960
_flash_os_start = ORIGIN(FLASH_OS);
4061
_flash_os_len = LENGTH(FLASH_OS);
62+
_ram_os_start = ORIGIN(RAM_OS);
63+
_ram_os_len = LENGTH(RAM_OS);
4164

4265
SECTIONS {
4366
/* ### RP2040 Boot loader */

src/main.rs

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ pub mod vga;
4444
// -----------------------------------------------------------------------------
4545

4646
use cortex_m_rt::entry;
47-
use defmt::*;
47+
use defmt::info;
4848
use defmt_rtt as _;
4949
use embedded_hal::digital::v2::OutputPin;
5050
use embedded_time::rate::*;
5151
use git_version::git_version;
5252
use panic_probe as _;
53-
use pico::{
53+
use rp_pico::{
5454
self,
5555
hal::{
5656
self,
@@ -68,27 +68,27 @@ use pico::{
6868
// Static and Const Data
6969
// -----------------------------------------------------------------------------
7070

71-
/// This is the standard RP2040 bootloader. It must be stored in the first 256
72-
/// bytes of the external SPI Flash chip. It will map the external SPI flash
73-
/// chip to address `0x1000_0000` and jump to an Interrupt Vector Table at
74-
/// address `0x1000_0100` (i.e. immediately after the bootloader).
75-
///
76-
/// See `memory.x` for a definition of the `.boot2` section.
77-
#[link_section = ".boot2"]
78-
#[used]
79-
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
80-
8171
/// BIOS version
8272
const GIT_VERSION: &str = git_version!();
8373

8474
/// Create a new Text Console
8575
static TEXT_CONSOLE: vga::TextConsole = vga::TextConsole::new();
8676

77+
extern "C" {
78+
static mut _flash_os_start: u32;
79+
static mut _flash_os_len: u32;
80+
static mut _ram_os_start: u32;
81+
static mut _ram_os_len: u32;
82+
}
83+
8784
// -----------------------------------------------------------------------------
8885
// Functions
8986
// -----------------------------------------------------------------------------
9087

91-
/// Prints to the screen
88+
/// Prints to the screen.
89+
///
90+
/// This function is NOT interrupt safe. Only call from the main thread, on
91+
/// core 1.
9292
#[macro_export]
9393
macro_rules! print {
9494
($($arg:tt)*) => {
@@ -99,7 +99,10 @@ macro_rules! print {
9999
};
100100
}
101101

102-
/// Prints to the screen and puts a new-line on the end
102+
/// Prints to the screen and puts a new-line on the end.
103+
///
104+
/// This function is NOT interrupt safe. Only call from the main thread, on
105+
/// core 1.
103106
#[macro_export]
104107
macro_rules! println {
105108
() => (print!("\n"));
@@ -136,12 +139,12 @@ fn main() -> ! {
136139

137140
// Run at 126 MHz SYS_PLL, 48 MHz, USB_PLL
138141

139-
let xosc = hal::xosc::setup_xosc_blocking(pac.XOSC, pico::XOSC_CRYSTAL_FREQ.Hz())
142+
let xosc = hal::xosc::setup_xosc_blocking(pac.XOSC, rp_pico::XOSC_CRYSTAL_FREQ.Hz())
140143
.map_err(|_x| false)
141144
.unwrap();
142145

143146
// Configure watchdog tick generation to tick over every microsecond
144-
watchdog.enable_tick_generation((pico::XOSC_CRYSTAL_FREQ / 1_000_000) as u8);
147+
watchdog.enable_tick_generation((rp_pico::XOSC_CRYSTAL_FREQ / 1_000_000) as u8);
145148

146149
let mut clocks = hal::clocks::ClocksManager::new(pac.CLOCKS);
147150

@@ -183,7 +186,7 @@ fn main() -> ! {
183186
let mut sio = hal::sio::Sio::new(pac.SIO);
184187

185188
// Configure and grab all the RP2040 pins the Pico exposes.
186-
let pins = pico::Pins::new(
189+
let pins = rp_pico::Pins::new(
187190
pac.IO_BANK0,
188191
pac.PADS_BANK0,
189192
sio.gpio_bank0,
@@ -221,13 +224,49 @@ fn main() -> ! {
221224
&mut pac.PSM,
222225
);
223226

224-
TEXT_CONSOLE.set_text_buffer(unsafe { &mut vga::CHAR_ARRAY });
227+
TEXT_CONSOLE.set_text_buffer(unsafe { &mut vga::GLYPH_ATTR_ARRAY });
228+
229+
// A crude way to clear the screen
230+
for _col in 0..vga::NUM_TEXT_ROWS {
231+
println!();
232+
}
225233

226-
info!("VGA intialised");
234+
TEXT_CONSOLE.move_to(0, 0);
235+
236+
println!("Neotron Pico BIOS, for the Raspberry Pi RP2040");
237+
println!("Copyright © Jonathan 'theJPster' Pallant and the Neotron Developers, 2021");
238+
println!("Version {}", GIT_VERSION);
239+
println!();
240+
println!("This program is free software: you can redistribute it and/or modify");
241+
println!("it under the terms of the GNU General Public License as published by");
242+
println!("the Free Software Foundation, either version 3 of the License, or");
243+
println!("(at your option) any later version.");
244+
println!();
245+
println!("This program is distributed in the hope that it will be useful,");
246+
println!("but WITHOUT ANY WARRANTY; without even the implied warranty of");
247+
println!("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the");
248+
println!("GNU General Public License for more details.");
249+
println!();
250+
println!("You should have received a copy of the GNU General Public License");
251+
println!("along with this program. If not, see https://www.gnu.org/licenses/.");
252+
println!();
253+
println!("Searching for Neotron OS...");
254+
255+
let flash_os_start = unsafe { &mut _flash_os_start as *mut u32 as usize };
256+
let flash_os_len = unsafe { &mut _flash_os_len as *mut u32 as usize };
257+
let ram_os_start = unsafe { &mut _ram_os_start as *mut u32 as usize };
258+
let ram_os_len = unsafe { &mut _ram_os_len as *mut u32 as usize };
259+
260+
println!(
261+
"OS Flash @ 0x{:08x}, {} bytes",
262+
flash_os_start, flash_os_len
263+
);
264+
println!("OS RAM @ 0x{:08x}, {} bytes", ram_os_start, ram_os_len);
227265

266+
// A dummy loop so we know it's running
228267
let mut x: u32 = 0;
229268
loop {
230-
println!("x = {}", x);
269+
print!("\rx = {}", x);
231270
x = x.wrapping_add(1);
232271
}
233272
}

0 commit comments

Comments
 (0)