Skip to content

Commit 2a7ab1c

Browse files
committed
Updates to how we boot.
1. Re-arranged it so we use the top of RAM and the bottom of Flash. 2. Updated all the crates. 3. Changed rendering to more accurately map Unicode to font glyphs. 4. Add space for attributes (not currently rendered) 5. Print OS memory locations, ready for OS booting.
1 parent 80a3e48 commit 2a7ab1c

File tree

3 files changed

+87
-42
lines changed

3 files changed

+87
-42
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

src/main.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ const GIT_VERSION: &str = git_version!();
7474
/// Create a new Text Console
7575
static TEXT_CONSOLE: vga::TextConsole = vga::TextConsole::new();
7676

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+
7784
// -----------------------------------------------------------------------------
7885
// Functions
7986
// -----------------------------------------------------------------------------
@@ -217,8 +224,9 @@ fn main() -> ! {
217224
&mut pac.PSM,
218225
);
219226

220-
TEXT_CONSOLE.set_text_buffer(unsafe { &mut vga::CHAR_ARRAY });
227+
TEXT_CONSOLE.set_text_buffer(unsafe { &mut vga::GLYPH_ATTR_ARRAY });
221228

229+
// A crude way to clear the screen
222230
for _col in 0..vga::NUM_TEXT_ROWS {
223231
println!();
224232
}
@@ -244,29 +252,18 @@ fn main() -> ! {
244252
println!();
245253
println!("Searching for Neotron OS...");
246254

247-
extern "C" {
248-
static mut _flash_os_start: u32;
249-
static mut _flash_os_len: u32;
250-
static mut _ram_os_start: u32;
251-
static mut _ram_os_len: u32;
252-
}
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 };
253259

254-
let flash_os_start = unsafe {
255-
&mut _flash_os_start as *mut u32 as usize
256-
};
257-
let flash_os_len = unsafe {
258-
&mut _flash_os_len as *mut u32 as usize
259-
};
260-
let ram_os_start = unsafe {
261-
&mut _ram_os_start as *mut u32 as usize
262-
};
263-
let ram_os_len = unsafe {
264-
&mut _ram_os_len as *mut u32 as usize
265-
};
266-
267-
println!("OS Flash is {:08x}, {} bytes", flash_os_start, flash_os_len);
268-
println!("OS RAM is {:08x}, {} bytes", ram_os_start, ram_os_len);
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);
269265

266+
// A dummy loop so we know it's running
270267
let mut x: u32 = 0;
271268
loop {
272269
print!("\rx = {}", x);

src/vga/mod.rs

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct RenderEngine {
6666
pub struct TextConsole {
6767
current_col: AtomicU16,
6868
current_row: AtomicU16,
69-
text_buffer: AtomicPtr<u8>,
69+
text_buffer: AtomicPtr<GlyphAttr>,
7070
}
7171

7272
/// Describes one scan-line's worth of pixels, including the length word required by the Pixel FIFO.
@@ -133,6 +133,22 @@ pub struct RGBColour(u16);
133133
#[derive(Copy, Clone, PartialEq, Eq)]
134134
pub struct RGBPair(u32);
135135

136+
/// Represents a glyph in the current font.
137+
#[repr(transparent)]
138+
#[derive(Copy, Clone, PartialEq, Eq)]
139+
pub struct Glyph(u8);
140+
141+
/// Represents VGA format foreground/background attributes.
142+
#[repr(transparent)]
143+
#[derive(Copy, Clone, PartialEq, Eq)]
144+
pub struct Attr(u8);
145+
146+
/// Represents a glyph/attribute pair. This is what out text console is made
147+
/// out of. They work in exactly the same way as IBM PC VGA.
148+
#[repr(transparent)]
149+
#[derive(Copy, Clone, PartialEq, Eq, Default)]
150+
pub struct GlyphAttr(u16);
151+
136152
// -----------------------------------------------------------------------------
137153
// Static and Const Data
138154
// -----------------------------------------------------------------------------
@@ -206,11 +222,12 @@ static mut PIXEL_DATA_BUFFER_ODD: LineBuffer = LineBuffer {
206222
/// This is our text buffer.
207223
///
208224
/// This is arranged as `NUM_TEXT_ROWS` rows of `NUM_TEXT_COLS` columns. Each
209-
/// item is an index into `font::FONT_DATA` (or a Code-Page 850 character).
225+
/// item is an index into `font::FONT_DATA` (or a Code-Page 850 character)
226+
/// plus an 8-bit attribute.
210227
///
211228
/// Written to by Core 0, and read from by `RenderEngine` running on Core 1.
212-
pub static mut CHAR_ARRAY: [u8; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize] =
213-
[0u8; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize];
229+
pub static mut GLYPH_ATTR_ARRAY: [GlyphAttr; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize] =
230+
[GlyphAttr(0); NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize];
214231

215232
/// Core 1 entry function.
216233
///
@@ -740,7 +757,7 @@ impl RenderEngine {
740757
// state. At least our platform is fixed, so we can simply
741758
// test if it works, for some given version of the Rust compiler.
742759
let row_slice = unsafe {
743-
&CHAR_ARRAY[(text_row * NUM_TEXT_COLS)..((text_row + 1) * NUM_TEXT_COLS)]
760+
&GLYPH_ATTR_ARRAY[(text_row * NUM_TEXT_COLS)..((text_row + 1) * NUM_TEXT_COLS)]
744761
};
745762
// Every font look-up we are about to do for this row will
746763
// involve offsetting by the row within each glyph. As this
@@ -754,14 +771,15 @@ impl RenderEngine {
754771
let mut px_idx = 0;
755772

756773
// Convert from characters to coloured pixels, using the font as a look-up table.
757-
for ch in row_slice.iter() {
758-
let index = (*ch as isize) * 16;
774+
for glyphattr in row_slice.iter() {
775+
let index = (glyphattr.glyph().0 as isize) * 16;
759776
// Note (unsafe): We use pointer arithmetic here because we
760777
// can't afford a bounds-check on an array. This is safe
761778
// because the font is `256 * width` bytes long and we can't
762779
// index more than `255 * width` bytes into it.
763780
let mono_pixels = unsafe { *font_ptr.offset(index) } as usize;
764-
// Convert from eight mono pixels in one byte to four RGB pairs
781+
// Convert from eight mono pixels in one byte to four RGB
782+
// pairs. Hopefully the `& 3` elides the panic calls.
765783
unsafe {
766784
core::ptr::write_volatile(
767785
scan_line_buffer_ptr.offset(px_idx),
@@ -808,7 +826,10 @@ impl TextConsole {
808826
/// Update the text buffer we are using.
809827
///
810828
/// Will reset the cursor. The screen is not cleared.
811-
pub fn set_text_buffer(&self, text_buffer: &'static mut [u8; NUM_TEXT_ROWS * NUM_TEXT_COLS]) {
829+
pub fn set_text_buffer(
830+
&self,
831+
text_buffer: &'static mut [GlyphAttr; NUM_TEXT_ROWS * NUM_TEXT_COLS],
832+
) {
812833
self.text_buffer
813834
.store(text_buffer.as_mut_ptr(), Ordering::Relaxed)
814835
}
@@ -817,14 +838,14 @@ impl TextConsole {
817838
///
818839
/// Adjusts the current row and column automatically. Also understands
819840
/// Carriage Return and New Line bytes.
820-
pub fn write_font_glyph(&self, font_glyph: u8) {
841+
pub fn write_font_glyph(&self, glyph: Glyph) {
821842
// Load from global state
822843
let mut row = self.current_row.load(Ordering::Relaxed);
823844
let mut col = self.current_col.load(Ordering::Relaxed);
824845
let buffer = self.text_buffer.load(Ordering::Relaxed);
825846

826847
if !buffer.is_null() {
827-
self.write_at(font_glyph, buffer, &mut row, &mut col);
848+
self.write_at(glyph, buffer, &mut row, &mut col);
828849
// Push back to global state
829850
self.current_row.store(row as u16, Ordering::Relaxed);
830851
self.current_col.store(col as u16, Ordering::Relaxed);
@@ -848,10 +869,10 @@ impl TextConsole {
848869
/// Zero-width and modifier Unicode Scalar Values (e.g. `U+0301 COMBINING,
849870
/// ACCENT`) are not supported. Normalise your Unicode before calling
850871
/// this function.
851-
fn map_char_to_glyph(input: char) -> u8 {
872+
fn map_char_to_glyph(input: char) -> Glyph {
852873
// This fixed table only works for the default font. When we support
853874
// changing font, we will need to plug-in a different table for each font.
854-
match input {
875+
let index = match input {
855876
'\u{0000}'..='\u{007F}' => input as u8,
856877
'\u{00A0}' => 255, // NBSP
857878
'\u{00A1}' => 173, // ¡
@@ -982,22 +1003,27 @@ impl TextConsole {
9821003
'\u{2593}' => 178, // ▓
9831004
'\u{25A0}' => 254, // ■
9841005
_ => b'?',
985-
}
1006+
};
1007+
Glyph(index)
9861008
}
9871009

9881010
/// Put a single character at a specified point on screen.
9891011
///
9901012
/// The character is relative to the current font.
991-
fn write_at(&self, font_glyph: u8, buffer: *mut u8, row: &mut u16, col: &mut u16) {
992-
if font_glyph == b'\r' {
1013+
fn write_at(&self, glyph: Glyph, buffer: *mut GlyphAttr, row: &mut u16, col: &mut u16) {
1014+
if glyph.0 == b'\r' {
9931015
*col = 0;
994-
} else if font_glyph == b'\n' {
1016+
} else if glyph.0 == b'\n' {
9951017
*col = 0;
9961018
*row += 1;
9971019
} else {
9981020
let offset = (*col as usize) + (NUM_TEXT_COLS * (*row as usize));
9991021
// Note (safety): This is safe as we bound `col` and `row`
1000-
unsafe { buffer.add(offset).write_volatile(font_glyph) };
1022+
unsafe {
1023+
buffer
1024+
.add(offset)
1025+
.write_volatile(GlyphAttr::new(glyph, Attr(0)))
1026+
};
10011027
*col += 1;
10021028
}
10031029
if *col == (NUM_TEXT_COLS as u16) {
@@ -1018,7 +1044,11 @@ impl TextConsole {
10181044

10191045
for blank_col in 0..NUM_TEXT_COLS {
10201046
let offset = (blank_col as usize) + (NUM_TEXT_COLS * (*row as usize));
1021-
unsafe { buffer.add(offset).write_volatile(b' ') };
1047+
unsafe {
1048+
buffer
1049+
.add(offset)
1050+
.write_volatile(GlyphAttr::new(Glyph(b' '), Attr(0)))
1051+
};
10221052
}
10231053
}
10241054
}
@@ -1266,6 +1296,24 @@ impl RGBPair {
12661296
}
12671297
}
12681298

1299+
impl GlyphAttr {
1300+
/// Make a new glyph/attribute pair.
1301+
pub const fn new(glyph: Glyph, attr: Attr) -> GlyphAttr {
1302+
let value: u16 = (glyph.0 as u16) + ((attr.0 as u16) << 8);
1303+
GlyphAttr(value)
1304+
}
1305+
1306+
/// Get the glyph component of this pair.
1307+
pub const fn glyph(self) -> Glyph {
1308+
Glyph(self.0 as u8)
1309+
}
1310+
1311+
/// Get the attribute component of this pair.
1312+
pub const fn attr(self) -> Attr {
1313+
Attr((self.0 >> 8) as u8)
1314+
}
1315+
}
1316+
12691317
// -----------------------------------------------------------------------------
12701318
// End of file
12711319
// -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)