Enable heap only on demand
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd09bf1..26f3490 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md
@@ -35,7 +35,7 @@ - connect your device to your computer - open a console, e.g. `tockloader listen` -- run the tests: `PLATFORM=nrf52 cargo rtv7em hardware_test` +- run the tests: `PLATFORM=nrf52 cargo rtv7em hardware_test --features=alloc` The expected output on the UART console will be as follows.
diff --git a/Cargo.toml b/Cargo.toml index 53da413..2122490 100644 --- a/Cargo.toml +++ b/Cargo.toml
@@ -5,10 +5,13 @@ license = "MIT/Apache-2.0" edition = "2018" +[features] +alloc = [ "linked_list_allocator" ] + [dependencies] core = { package = "async-support", path = "async-support" } -linked_list_allocator = { version = "=0.6.5", default-features = false } libtock_codegen = { path = "codegen" } +linked_list_allocator = { optional = true, version = "=0.6.5", default-features = false } [dev-dependencies] corepack = { version = "0.4.0", default-features = false, features = ["alloc"] } @@ -17,6 +20,26 @@ serde = { version = "=1.0.84", default-features = false, features = ["derive"] } futures = { version = "0.3.1", default-features = false, features = ["unstable", "cfg-target-has-atomic"] } +[[example]] +name = "alloc_error" +path = "examples-alloc/alloc_error.rs" +required-features = ["alloc"] + +[[example]] +name = "ble_scanning" +path = "examples-alloc/ble_scanning.rs" +required-features = ["alloc"] + +[[example]] +name = "hardware_test" +path = "examples-alloc/hardware_test.rs" +required-features = ["alloc"] + +[[example]] +name = "simple_ble" +path = "examples-alloc/simple_ble.rs" +required-features = ["alloc"] + [profile.dev] panic = "abort" lto = true
diff --git a/build_examples.sh b/build_examples.sh index c094db9..fd67b75 100755 --- a/build_examples.sh +++ b/build_examples.sh
@@ -3,4 +3,5 @@ set -eux PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples +PLATFORM=nrf52 cargo build --release --target=thumbv7em-none-eabi --examples --features=alloc PLATFORM=riscv32 cargo build --release --target=riscv32imc-unknown-none-elf --examples # Important for testing: This target does not support atomics
diff --git a/examples/alloc_error.rs b/examples-alloc/alloc_error.rs similarity index 100% rename from examples/alloc_error.rs rename to examples-alloc/alloc_error.rs
diff --git a/examples/ble_scanning.rs b/examples-alloc/ble_scanning.rs similarity index 100% rename from examples/ble_scanning.rs rename to examples-alloc/ble_scanning.rs
diff --git a/examples/hardware_test.rs b/examples-alloc/hardware_test.rs similarity index 100% rename from examples/hardware_test.rs rename to examples-alloc/hardware_test.rs
diff --git a/examples/simple_ble.rs b/examples-alloc/simple_ble.rs similarity index 100% rename from examples/simple_ble.rs rename to examples-alloc/simple_ble.rs
diff --git a/src/alloc.rs b/src/alloc.rs new file mode 100644 index 0000000..ee3de18 --- /dev/null +++ b/src/alloc.rs
@@ -0,0 +1,59 @@ +use crate::drivers; +use crate::leds::LedsDriver; +use crate::result::TockResult; +use crate::timer::Duration; +use crate::timer::ParallelSleepDriver; +use core::alloc::GlobalAlloc; +use core::alloc::Layout; +use core::executor; +use core::ptr; +use core::ptr::NonNull; +use linked_list_allocator::Heap; + +pub static mut HEAP: Heap = Heap::empty(); + +struct TockAllocator; + +unsafe impl GlobalAlloc for TockAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + HEAP.allocate_first_fit(layout) + .ok() + .map_or(ptr::null_mut(), NonNull::as_ptr) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + HEAP.deallocate(NonNull::new_unchecked(ptr), layout) + } +} + +#[global_allocator] +static ALLOCATOR: TockAllocator = TockAllocator; + +#[alloc_error_handler] +unsafe fn alloc_error_handler(_: Layout) -> ! { + executor::block_on(async { + let mut drivers = drivers::retrieve_drivers_unsafe(); + + let leds_driver = drivers.leds.init_driver(); + let mut timer_driver = drivers.timer.create_timer_driver(); + let timer_driver = timer_driver.activate(); + + if let (Ok(leds_driver), Ok(timer_driver)) = (leds_driver, timer_driver) { + let _ = cycle_all_leds(&leds_driver, &timer_driver).await; + } + loop {} + }) +} + +async fn cycle_all_leds( + leds_driver: &LedsDriver<'_>, + timer_driver: &ParallelSleepDriver<'_>, +) -> TockResult<()> { + loop { + for led in leds_driver.leds() { + led.on()?; + timer_driver.sleep(Duration::from_ms(100)).await?; + led.off()?; + } + } +}
diff --git a/src/entry_point/mod.rs b/src/entry_point/mod.rs index cc5f402..ae43a19 100644 --- a/src/entry_point/mod.rs +++ b/src/entry_point/mod.rs
@@ -127,12 +127,13 @@ // we could have also bss_end for app_heap_start let app_heap_start = app_heap_break; - let app_heap_end = app_heap_break + HEAP_SIZE; + let app_heap_end = app_heap_start + HEAP_SIZE; // Tell the kernel the new app heap break. memop::set_brk(app_heap_end as *const u8); - HEAP.init(app_heap_start, HEAP_SIZE); + #[cfg(feature = "alloc")] + crate::alloc::HEAP.init(app_heap_start, HEAP_SIZE); main(0, ptr::null()); @@ -140,24 +141,3 @@ syscalls::raw::yieldk(); } } - -use core::alloc::GlobalAlloc; -use core::alloc::Layout; -use core::ptr::NonNull; -use linked_list_allocator::Heap; - -static mut HEAP: Heap = Heap::empty(); - -pub struct TockAllocator; - -unsafe impl GlobalAlloc for TockAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - HEAP.allocate_first_fit(layout) - .ok() - .map_or(ptr::null_mut(), NonNull::as_ptr) - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - HEAP.deallocate(NonNull::new_unchecked(ptr), layout) - } -}
diff --git a/src/lang_items.rs b/src/lang_items.rs index 69ddf85..bb4bd77 100644 --- a/src/lang_items.rs +++ b/src/lang_items.rs
@@ -19,12 +19,10 @@ //! crate. use crate::drivers; -use crate::entry_point::TockAllocator; use crate::leds::LedsDriver; use crate::result::TockResult; use crate::timer::Duration; use crate::timer::ParallelSleepDriver; -use core::alloc::Layout; use core::executor; use core::panic::PanicInfo; @@ -78,35 +76,3 @@ timer_driver.sleep(Duration::from_ms(100)).await?; } } - -#[global_allocator] -static ALLOCATOR: TockAllocator = TockAllocator; - -#[alloc_error_handler] -unsafe fn alloc_error_handler(_: Layout) -> ! { - executor::block_on(async { - let mut drivers = drivers::retrieve_drivers_unsafe(); - - let leds_driver = drivers.leds.init_driver(); - let mut timer_driver = drivers.timer.create_timer_driver(); - let timer_driver = timer_driver.activate(); - - if let (Ok(leds_driver), Ok(timer_driver)) = (leds_driver, timer_driver) { - let _ = cycle_all_leds(&leds_driver, &timer_driver).await; - } - loop {} - }) -} - -async fn cycle_all_leds( - leds_driver: &LedsDriver<'_>, - timer_driver: &ParallelSleepDriver<'_>, -) -> TockResult<()> { - loop { - for led in leds_driver.leds() { - led.on()?; - timer_driver.sleep(Duration::from_ms(100)).await?; - led.off()?; - } - } -}
diff --git a/src/lib.rs b/src/lib.rs index e7d9d63..0744a53 100644 --- a/src/lib.rs +++ b/src/lib.rs
@@ -1,6 +1,9 @@ -#![feature(asm, alloc_error_handler, lang_items, naked_functions)] +#![feature(asm, lang_items, naked_functions)] +#![cfg_attr(feature = "alloc", feature(alloc_error_handler))] #![cfg_attr(any(target_arch = "arm", target_arch = "riscv32"), no_std)] +#[cfg(feature = "alloc")] +mod alloc; mod entry_point; #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] mod lang_items;