Skip to content

Commit d60e365

Browse files
bors[bot]Woytentorfmaster
authored
Merge #164
164: Split libtock into core and high level library r=Woyten a=torfmaster # Summary In order to address #160 we decided to do a first draft of splitting the library into parts. The idea is that there are two layers: * libtock-core * libtock-rs (names tbd). Libtock-core contains the panic handler, the entry point, the allocator and the syscall interfaces. libtock-rs uses libtock-core and the interface stays as usual. # Possible Extensions We deleted the "blink" code from the panic handler. This saves more than 1kbytes in the text segment. If this feature is still wanted we could implement the following: * provide a feature in libtock-core to opt-out the panic handler in libtock-core * provide a feature for libtock-rs to opt-out the panic handler in libtock-core and using a blinking panic handler. In the long run the (default) panic handler could exit the app and send debug information to the kernel which could print it for example. This could be implemented once the kernel functionality is in place. # Open questions The current implementation of the panic handler more or less silently fails if there is a panic. Panics can be identified by enabling the "trace_syscall" option in the kernel. How should this be tackled? Should there be a default panic handling or should it be customizable and if yes how should it be customized? Co-authored-by: Woyten <[email protected]> Co-authored-by: torfmaster <[email protected]>
2 parents 4d27d24 + 76f96bb commit d60e365

36 files changed

+236
-196
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Cargo.lock
22
layout.ld
3+
platform
34
target

Cargo.toml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ license = "MIT/Apache-2.0"
66
edition = "2018"
77

88
[features]
9-
alloc = [ "linked_list_allocator" ]
9+
alloc = ["libtock-core/alloc"]
10+
custom_panic_handler = ["libtock-core/custom_panic_handler"]
11+
custom_alloc_error_handler = ["libtock-core/custom_alloc_error_handler"]
1012

1113
[dependencies]
1214
core = { package = "async-support", path = "async-support" }
15+
libtock-core = { path = "core" }
1316
libtock_codegen = { path = "codegen" }
14-
linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false }
1517
futures = { version = "0.3.1", default-features = false, features = ["unstable", "cfg-target-has-atomic"] }
1618

1719
[dev-dependencies]
@@ -22,22 +24,27 @@ serde = { version = "=1.0.84", default-features = false, features = ["derive"] }
2224

2325
[[example]]
2426
name = "alloc_error"
25-
path = "examples-alloc/alloc_error.rs"
26-
required-features = ["alloc"]
27+
path = "examples-features/alloc_error.rs"
28+
required-features = ["alloc", "custom_alloc_error_handler"]
2729

2830
[[example]]
2931
name = "ble_scanning"
30-
path = "examples-alloc/ble_scanning.rs"
32+
path = "examples-features/ble_scanning.rs"
3133
required-features = ["alloc"]
3234

3335
[[example]]
3436
name = "libtock_test"
35-
path = "examples-alloc/libtock_test.rs"
37+
path = "examples-features/libtock_test.rs"
3638
required-features = ["alloc"]
3739

40+
[[example]]
41+
name = "panic"
42+
path = "examples-features/panic.rs"
43+
required-features = ["custom_panic_handler"]
44+
3845
[[example]]
3946
name = "simple_ble"
40-
path = "examples-alloc/simple_ble.rs"
47+
path = "examples-features/simple_ble.rs"
4148
required-features = ["alloc"]
4249

4350
[profile.dev]
@@ -52,4 +59,5 @@ lto = true
5259
members = [
5360
"async-support",
5461
"codegen",
62+
"core"
5563
]

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ setup:
4242
examples:
4343
PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples
4444
PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples --features=alloc
45-
PLATFORM=opentitan cargo build --release --target=riscv32imc-unknown-none-elf --examples
45+
PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --example panic --features=custom_panic_handler,custom_alloc_error_handler
46+
PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --example alloc_error --features=alloc,custom_alloc_error_handler
47+
PLATFORM=opentitan cargo build --release --target=riscv32imc-unknown-none-elf --examples # Important: This is testing a platform without atomics support
4648

4749
.PHONY: test
4850
test:

core/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "libtock-core"
3+
version = "0.1.0"
4+
authors = ["Tock Project Developers <[email protected]>"]
5+
edition = "2018"
6+
7+
[features]
8+
alloc = [ "linked_list_allocator" ]
9+
custom_panic_handler = []
10+
custom_alloc_error_handler = []
11+
12+
[dependencies]
13+
linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false }

core/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# libtock-core
2+
3+
Core crate of `libtock-rs`. It contains the architecture specific code of `libtock-rs`. In particular:
4+
5+
* the entry point
6+
* `panic` and `alloc_error` handlers
7+
* the syscalls
8+
* the allocator (optional)
9+
10+
It has three important feature flags
11+
12+
* `alloc` - allow for heap. Enables a linked list allocator.
13+
* `custom_panic_handler` - disable the default panic handler and allow definition of a custom one using `#[panic_handler]`
14+
* `custom_alloc_error_handler` - disable the default alloc error handler and allow definition of a custom one using `#[alloc_error_handler]`
15+
16+
## License
17+
18+
Licensed under either of
19+
20+
- Apache License, Version 2.0
21+
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
22+
- MIT license
23+
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
24+
25+
at your option.
26+
27+
### Contribution
28+
29+
Unless you explicitly state otherwise, any contribution intentionally submitted
30+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
31+
dual licensed as above, without any additional terms or conditions.
32+
33+
The contribution guidelines are identical to those of `libtock-rs` and can be found here: [contribution guidelines](../CONTRIBUTING.md)

core/src/alloc.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use core::alloc::GlobalAlloc;
2+
use core::alloc::Layout;
3+
use core::ptr;
4+
use core::ptr::NonNull;
5+
use linked_list_allocator::Heap;
6+
7+
pub static mut HEAP: Heap = Heap::empty();
8+
9+
struct TockAllocator;
10+
11+
unsafe impl GlobalAlloc for TockAllocator {
12+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
13+
HEAP.allocate_first_fit(layout)
14+
.ok()
15+
.map_or(ptr::null_mut(), NonNull::as_ptr)
16+
}
17+
18+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
19+
HEAP.deallocate(NonNull::new_unchecked(ptr), layout)
20+
}
21+
}
22+
23+
#[global_allocator]
24+
static ALLOCATOR: TockAllocator = TockAllocator;
25+
26+
#[cfg(not(feature = "custom_alloc_error_handler"))]
27+
#[alloc_error_handler]
28+
unsafe fn alloc_error_handler(_: Layout) -> ! {
29+
use crate::syscalls;
30+
31+
// Print 0x01 using the LowLevelDebug capsule (if available).
32+
let _ = syscalls::command1_insecure(8, 2, 0x01);
33+
34+
// Signal a panic using the LowLevelDebug capsule (if available).
35+
let _ = syscalls::command1_insecure(8, 1, 0x01);
36+
37+
loop {
38+
syscalls::raw::yieldk();
39+
}
40+
}
File renamed without changes.

core/src/debug/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#[cfg_attr(target_arch = "arm", path = "platform_arm.rs")]
2+
#[cfg_attr(target_arch = "riscv32", path = "platform_riscv32.rs")]
3+
mod platform;
4+
5+
pub use platform::*;

core/src/debug/platform.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn get_stack_pointer() -> usize {
2+
panic!("No generic implementation.")
3+
}

core/src/debug/platform_arm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn get_stack_pointer() -> usize {
2+
let stack_pointer;
3+
unsafe { asm!("mov $0, sp" : "=r"(stack_pointer) : : : "volatile") };
4+
stack_pointer
5+
}

core/src/debug/platform_riscv32.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn get_stack_pointer() -> usize {
2+
let stack_pointer;
3+
unsafe { asm!("mv $0, sp" : "=r"(stack_pointer) : : : "volatile") };
4+
stack_pointer
5+
}

src/entry_point/mod.rs renamed to core/src/entry_point/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ use core::ptr;
5757

5858
#[cfg_attr(target_arch = "riscv32", path = "start_item_riscv32.rs")]
5959
#[cfg_attr(target_arch = "arm", path = "start_item_arm.rs")]
60-
#[cfg_attr(
61-
not(any(target_arch = "arm", target_arch = "riscv32")),
62-
path = "start_item_mock.rs"
63-
)]
6460
mod start_item;
6561

6662
/// The header encoded at the beginning of .text by the linker script. It is

src/lang_items.rs renamed to core/src/lang_items.rs

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,7 @@
1818
//! `rustc_main`. That's covered by the `_start` function in the root of this
1919
//! crate.
2020
21-
use crate::drivers;
22-
use crate::leds::LedsDriver;
23-
use crate::result::TockResult;
24-
use crate::timer::Duration;
25-
use crate::timer::ParallelSleepDriver;
26-
use core::executor;
27-
use core::panic::PanicInfo;
28-
use futures::future;
21+
use crate::syscalls;
2922

3023
#[lang = "start"]
3124
extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8) -> bool
@@ -45,52 +38,25 @@ impl Termination for () {
4538
fn check_result(self) {}
4639
}
4740

48-
impl Termination for TockResult<()> {
41+
impl<S, T> Termination for Result<S, T> {
4942
fn check_result(self) {
5043
if self.is_err() {
5144
unsafe { report_panic() };
5245
}
5346
}
5447
}
5548

49+
#[cfg(not(feature = "custom_panic_handler"))]
5650
#[panic_handler]
57-
unsafe fn panic_handler(_info: &PanicInfo) -> ! {
51+
unsafe fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
5852
report_panic()
5953
}
6054

6155
unsafe fn report_panic() -> ! {
6256
// Signal a panic using the LowLevelDebug capsule (if available).
63-
super::debug::low_level_status_code(1);
57+
let _ = syscalls::command1_insecure(8, 1, 1);
6458

65-
// Flash all LEDs (if available).
66-
executor::block_on(async {
67-
let mut drivers = drivers::retrieve_drivers_unsafe();
68-
69-
let leds_driver = drivers.leds.init_driver();
70-
let mut timer_driver = drivers.timer.create_timer_driver();
71-
let timer_driver = timer_driver.activate();
72-
73-
if let (Ok(leds_driver), Ok(timer_driver)) = (leds_driver, timer_driver) {
74-
let _ = blink_all_leds(&leds_driver, &timer_driver).await;
75-
} else {
76-
future::pending::<()>().await
77-
}
78-
loop {}
79-
})
80-
}
81-
82-
async fn blink_all_leds(
83-
leds_driver: &LedsDriver<'_>,
84-
timer_driver: &ParallelSleepDriver<'_>,
85-
) -> TockResult<()> {
8659
loop {
87-
for led in leds_driver.leds() {
88-
led.on()?;
89-
}
90-
timer_driver.sleep(Duration::from_ms(100)).await?;
91-
for led in leds_driver.leds() {
92-
led.off()?;
93-
}
94-
timer_driver.sleep(Duration::from_ms(100)).await?;
60+
syscalls::raw::yieldk();
9561
}
9662
}

core/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(asm, lang_items, naked_functions)]
2+
#![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)]
3+
#![cfg_attr(feature = "alloc", feature(alloc_error_handler))]
4+
5+
#[cfg(feature = "alloc")]
6+
mod alloc;
7+
mod entry_point;
8+
#[cfg(any(target_arch = "arm", target_arch = "riscv32"))]
9+
mod lang_items;
10+
11+
pub mod callback;
12+
pub mod debug;
13+
pub mod memop;
14+
pub mod result;
15+
pub mod shared_memory;
16+
pub mod syscalls;
17+
pub mod unwind_symbols;
File renamed without changes.

core/src/result.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#[derive(Copy, Clone)]
2+
pub struct SubscribeError {
3+
pub driver_number: usize,
4+
pub subscribe_number: usize,
5+
pub return_code: isize,
6+
}
7+
8+
#[derive(Copy, Clone)]
9+
pub struct CommandError {
10+
pub driver_number: usize,
11+
pub command_number: usize,
12+
pub arg1: usize,
13+
pub arg2: usize,
14+
pub return_code: isize,
15+
}
16+
17+
#[derive(Copy, Clone)]
18+
pub struct AllowError {
19+
pub driver_number: usize,
20+
pub allow_number: usize,
21+
pub return_code: isize,
22+
}
23+
24+
pub const SUCCESS: isize = 0;
25+
pub const FAIL: isize = -1;
26+
pub const EBUSY: isize = -2;
27+
pub const EALREADY: isize = -3;
28+
pub const EINVAL: isize = -6;
29+
pub const ESIZE: isize = -7;
30+
pub const ENOMEM: isize = -9;
File renamed without changes.

src/syscalls/mod.rs renamed to core/src/syscalls/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
#[cfg_attr(target_arch = "riscv32", path = "platform_riscv32.rs")]
22
#[cfg_attr(target_arch = "arm", path = "platform_arm.rs")]
3-
#[cfg_attr(
4-
not(any(target_arch = "arm", target_arch = "riscv32")),
5-
path = "platform_mock.rs"
6-
)]
73
mod platform;
84

95
use crate::callback::CallbackSubscription;
File renamed without changes.
File renamed without changes.
File renamed without changes.

examples-alloc/alloc_error.rs

Lines changed: 0 additions & 16 deletions
This file was deleted.

examples-features/alloc_error.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Triggers the out-of-memory handler. Should print an error message.
2+
3+
#![no_std]
4+
#![feature(alloc_error_handler)]
5+
6+
extern crate alloc;
7+
8+
use alloc::vec::Vec;
9+
use core::alloc::Layout;
10+
use core::fmt::Write;
11+
use libtock::result::TockResult;
12+
use libtock::syscalls;
13+
14+
#[libtock::main]
15+
fn main() -> TockResult<()> {
16+
let mut vec = Vec::new();
17+
loop {
18+
vec.push(0);
19+
}
20+
}
21+
22+
#[alloc_error_handler]
23+
unsafe fn alloc_error_handler(_: Layout) -> ! {
24+
if let Ok(drivers) = libtock::retrieve_drivers() {
25+
let mut console = drivers.console.create_console();
26+
let _ = writeln!(console, "alloc_error_handler called");
27+
}
28+
loop {
29+
syscalls::raw::yieldk();
30+
}
31+
}
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)