Skip to content

Commit 362db34

Browse files
authored
Merge pull request #48 from Neotron-Compute/release/0.4.0
Release 0.4.0
2 parents 8bd0638 + 45c5f5a commit 362db34

18 files changed

+782
-171
lines changed

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
rustup component add llvm-tools-preview
2323
cargo install cargo-binutils
2424
- name: Build
25-
run: ./build.sh
25+
run: ./build.sh --verbose
2626
- name: Upload files to Release
2727
if: github.event_name == 'push' && startswith(github.ref, 'refs/tags/')
2828
uses: softprops/action-gh-release@v1

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased changes
44

5+
## v0.4.0
6+
7+
* The `load` command now takes ELF binaries, not raw binaries.
8+
* Neotron OS can now be used as a dependency within an application, if desired.
9+
510
## v0.3.3
611

712
* Add `dir` command

Cargo.lock

Lines changed: 31 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
[package]
22
name = "neotron-os"
3-
version = "0.3.3"
4-
authors = ["Jonathan 'theJPster' Pallant <github@thejpster.org.uk>", "The Neotron Developers"]
3+
version = "0.4.0"
4+
authors = [
5+
"Jonathan 'theJPster' Pallant <github@thejpster.org.uk>",
6+
"The Neotron Developers"
7+
]
58
edition = "2018"
69
description = "The Neotron Operating System"
710
license = "GPL-3.0-or-later"
@@ -46,3 +49,8 @@ serde = { version = "1.0", default-features = false }
4649
menu = "0.3"
4750
chrono = { version = "0.4", default-features = false }
4851
embedded-sdmmc = { version = "0.5", default-features = false }
52+
neotron-api = "0.1"
53+
neotron-loader = "0.1"
54+
55+
[features]
56+
lib-mode = []

build.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ for TARGET_ARCH in thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabi; do
1111
echo "TARGET is ${TARGET_ARCH}"
1212
for BINARY in flash0002 flash0802 flash1002; do
1313
echo "BINARY is ${BINARY}"
14-
cargo build --verbose --release --target=${TARGET_ARCH} --bin ${BINARY}
14+
cargo build $* --release --target=${TARGET_ARCH} --bin ${BINARY}
1515
# objcopy would do the build for us first, but it doesn't have good build output
16-
cargo objcopy --verbose --release --target=${TARGET_ARCH} --bin ${BINARY} -- -O binary ${RELEASE_DIR}/${TARGET_ARCH}-${BINARY}-libneotron_os.bin
16+
cargo objcopy $* --release --target=${TARGET_ARCH} --bin ${BINARY} -- -O binary ${RELEASE_DIR}/${TARGET_ARCH}-${BINARY}-libneotron_os.bin
1717
# Keep the ELF file too (for debugging)
1818
cp ./target/${TARGET_ARCH}/release/${BINARY} ${RELEASE_DIR}/${TARGET_ARCH}-${BINARY}-libneotron_os.elf
1919
done

neotron-flash-0002.ld

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ MEMORY
3232

3333
/* # Entry point = what the BIOS calls to start the OS */
3434
ENTRY(main);
35-
EXTERN(__RESET_VECTOR);
35+
36+
/*
37+
Where the Transient Program Area starts.
38+
*/
39+
_tpa_start = ORIGIN(RAM) + LENGTH(RAM);
3640

3741
/* # Sections */
3842
SECTIONS

neotron-flash-0802.ld

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ MEMORY
3232

3333
/* # Entry point = what the BIOS calls to start the OS */
3434
ENTRY(main);
35-
EXTERN(__RESET_VECTOR);
35+
36+
/*
37+
Where the Transient Program Area starts.
38+
*/
39+
_tpa_start = ORIGIN(RAM) + LENGTH(RAM);
3640

3741
/* # Sections */
3842
SECTIONS

neotron-flash-1002.ld

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,24 @@ MEMORY
2323
{
2424
/* The first 128 KiB is for the BIOS. We get the rest. */
2525
FLASH (rx) : ORIGIN = 0x10020000, LENGTH = 128K
26+
2627
/*
27-
* We get the bottom 4KB of RAM. Anything above that is for applications
28-
* (up to wherever the BIOS tells us we can use.)
28+
* The RAM reserved for the OS. Above this is the Transient Program Area.
29+
*
30+
* This is defined by the Neotron specification for a given platform. On this
31+
* Cortex-M based platform, it's the start of Cortex-M SRAM, plus 4 KiB, or
32+
* 0x2000_1000.
2933
*/
3034
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
3135
}
3236

3337
/* # Entry point = what the BIOS calls to start the OS */
3438
ENTRY(main);
35-
EXTERN(__RESET_VECTOR);
39+
40+
/*
41+
Where the Transient Program Area starts.
42+
*/
43+
_tpa_start = ORIGIN(RAM) + LENGTH(RAM);
3644

3745
/* # Sections */
3846
SECTIONS

src/bin/flash0002.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
/// of our portion of Flash.
1414
#[link_section = ".entry_point"]
1515
#[used]
16-
pub static ENTRY_POINT_ADDR: extern "C" fn(*const neotron_common_bios::Api) -> ! = neotron_os::main;
16+
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

src/bin/flash0802.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
/// of our portion of Flash.
1414
#[link_section = ".entry_point"]
1515
#[used]
16-
pub static ENTRY_POINT_ADDR: extern "C" fn(*const neotron_common_bios::Api) -> ! = neotron_os::main;
16+
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

src/bin/flash1002.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
/// of our portion of Flash.
1414
#[link_section = ".entry_point"]
1515
#[used]
16-
pub static ENTRY_POINT_ADDR: extern "C" fn(*const neotron_common_bios::Api) -> ! = neotron_os::main;
16+
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

src/commands/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub static COMMAND_ITEM: menu::Item<Ctx> = menu::Item {
2222

2323
/// Called when the "config" command is executed.
2424
fn command(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &mut Ctx) {
25-
let command = args.get(0).cloned().unwrap_or("print");
25+
let command = args.first().cloned().unwrap_or("print");
2626
match command {
2727
"reset" => match config::Config::load() {
2828
Ok(new_config) => {

src/commands/fs.rs

Lines changed: 9 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
//! File Systems related commands for Neotron OS
22
3-
use chrono::{Datelike, Timelike};
43
use embedded_sdmmc::VolumeIdx;
54

6-
use crate::{bios, print, println, Ctx, API};
5+
use crate::{bios, print, println, Ctx};
76

87
pub static DIR_ITEM: menu::Item<Ctx> = menu::Item {
98
item_type: menu::ItemType::Callback {
@@ -14,7 +13,6 @@ pub static DIR_ITEM: menu::Item<Ctx> = menu::Item {
1413
help: Some("Dir the root directory on block device 0"),
1514
};
1615

17-
#[cfg(target_os = "none")]
1816
pub static LOAD_ITEM: menu::Item<Ctx> = menu::Item {
1917
item_type: menu::ItemType::Callback {
2018
function: load,
@@ -27,89 +25,12 @@ pub static LOAD_ITEM: menu::Item<Ctx> = menu::Item {
2725
help: Some("Load a file into the application area"),
2826
};
2927

30-
struct BiosBlock();
31-
32-
impl embedded_sdmmc::BlockDevice for BiosBlock {
33-
type Error = bios::Error;
34-
35-
fn read(
36-
&self,
37-
blocks: &mut [embedded_sdmmc::Block],
38-
start_block_idx: embedded_sdmmc::BlockIdx,
39-
_reason: &str,
40-
) -> Result<(), Self::Error> {
41-
let api = API.get();
42-
let byte_slice = unsafe {
43-
core::slice::from_raw_parts_mut(
44-
blocks.as_mut_ptr() as *mut u8,
45-
blocks.len() * embedded_sdmmc::Block::LEN,
46-
)
47-
};
48-
match (api.block_read)(
49-
0,
50-
bios::block_dev::BlockIdx(u64::from(start_block_idx.0)),
51-
blocks.len() as u8,
52-
bios::ApiBuffer::new(byte_slice),
53-
) {
54-
bios::Result::Ok(_) => Ok(()),
55-
bios::Result::Err(e) => Err(e),
56-
}
57-
}
58-
59-
fn write(
60-
&self,
61-
blocks: &[embedded_sdmmc::Block],
62-
start_block_idx: embedded_sdmmc::BlockIdx,
63-
) -> Result<(), Self::Error> {
64-
let api = API.get();
65-
let byte_slice = unsafe {
66-
core::slice::from_raw_parts(
67-
blocks.as_ptr() as *const u8,
68-
blocks.len() * embedded_sdmmc::Block::LEN,
69-
)
70-
};
71-
match (api.block_write)(
72-
0,
73-
bios::block_dev::BlockIdx(u64::from(start_block_idx.0)),
74-
blocks.len() as u8,
75-
bios::ApiByteSlice::new(byte_slice),
76-
) {
77-
bios::Result::Ok(_) => Ok(()),
78-
bios::Result::Err(e) => Err(e),
79-
}
80-
}
81-
82-
fn num_blocks(&self) -> Result<embedded_sdmmc::BlockCount, Self::Error> {
83-
let api = API.get();
84-
match (api.block_dev_get_info)(0) {
85-
bios::Option::Some(info) => Ok(embedded_sdmmc::BlockCount(info.num_blocks as u32)),
86-
bios::Option::None => Err(bios::Error::InvalidDevice),
87-
}
88-
}
89-
}
90-
91-
struct BiosTime();
92-
93-
impl embedded_sdmmc::TimeSource for BiosTime {
94-
fn get_timestamp(&self) -> embedded_sdmmc::Timestamp {
95-
let time = API.get_time();
96-
embedded_sdmmc::Timestamp {
97-
year_since_1970: (time.year() - 1970) as u8,
98-
zero_indexed_month: time.month0() as u8,
99-
zero_indexed_day: time.day0() as u8,
100-
hours: time.hour() as u8,
101-
minutes: time.minute() as u8,
102-
seconds: time.second() as u8,
103-
}
104-
}
105-
}
106-
10728
/// Called when the "dir" command is executed.
10829
fn dir(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
10930
fn work() -> Result<(), embedded_sdmmc::Error<bios::Error>> {
11031
println!("Listing files on Block Device 0, /");
111-
let bios_block = BiosBlock();
112-
let time = BiosTime();
32+
let bios_block = crate::fs::BiosBlock();
33+
let time = crate::fs::BiosTime();
11334
let mut mgr = embedded_sdmmc::VolumeManager::new(bios_block, time);
11435
// Open the first partition
11536
let volume = mgr.get_volume(VolumeIdx(0))?;
@@ -165,33 +86,12 @@ fn dir(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &
16586
}
16687

16788
/// Called when the "load" command is executed.
168-
#[cfg(target_os = "none")]
169-
fn load(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], _ctx: &mut Ctx) {
170-
fn work(args: &[&str]) -> Result<(), embedded_sdmmc::Error<bios::Error>> {
171-
println!("Loading /{} from Block Device 0", args[0]);
172-
let bios_block = BiosBlock();
173-
let time = BiosTime();
174-
let mut mgr = embedded_sdmmc::VolumeManager::new(bios_block, time);
175-
// Open the first partition
176-
let mut volume = mgr.get_volume(VolumeIdx(0))?;
177-
let root_dir = mgr.open_root_dir(&volume)?;
178-
let mut file = mgr.open_file_in_dir(
179-
&mut volume,
180-
&root_dir,
181-
args[0],
182-
embedded_sdmmc::Mode::ReadOnly,
183-
)?;
184-
let file_length = file.length();
185-
// Application space starts 4K into Cortex-M SRAM
186-
const APPLICATION_START_ADDR: usize = 0x2000_1000;
187-
let application_ram: &'static mut [u8] = unsafe {
188-
core::slice::from_raw_parts_mut(APPLICATION_START_ADDR as *mut u8, file_length as usize)
189-
};
190-
mgr.read(&mut volume, &mut file, application_ram)?;
191-
Ok(())
192-
}
193-
194-
match work(args) {
89+
fn load(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &mut Ctx) {
90+
let Some(filename) = args.first() else {
91+
println!("Need a filename");
92+
return;
93+
};
94+
match ctx.tpa.load_program(filename) {
19595
Ok(_) => {}
19696
Err(e) => {
19797
println!("Error: {:?}", e);

src/commands/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ pub static OS_MENU: menu::Menu<Ctx> = menu::Menu {
2323
&fs::DIR_ITEM,
2424
&hardware::LSHW_ITEM,
2525
&ram::HEXDUMP_ITEM,
26-
#[cfg(target_os = "none")]
2726
&ram::RUN_ITEM,
28-
#[cfg(target_os = "none")]
27+
&ram::LOAD_ITEM,
2928
&fs::LOAD_ITEM,
3029
&screen::CLEAR_ITEM,
3130
&screen::BENCH_ITEM,

0 commit comments

Comments
 (0)