# emcell
**emcell** (**EM**bedded **CELL**) - is a library, which make it very easy
to keep several binaries on a single microcontroller. You just need to create
a separate crate with *cells* definitions and create simple `build.rs`, specifying which *cell*
is a current crate for.
*Cell* is an abstract word for a binary or library, which have a specific region of
FLASH and RAM memory assigned. You can keep several *cells* on a single microcontroller,
and even define header for each of them to cross-call different functions.
*Emcell* also allow you to define a special function with signature `fn() -> !`, which will
perform vector table switch. For example, you can define function `run() -> !` in your main code,
and run it from bootloader cell.
## Usage
Example of `lib.rs` for cells definitions crate:
```rust
#![no_std]
#[macro_use]
extern crate emcell_macro;
emcell_configuration! {
device!{
initial_stack_ptr: 0x2000_6000,
ram_range_start: 0x2000_0000,
ram_range_end: 0x2001_8000, // 96Kb RAM
flash_range_start: 0x0800_0000,
flash_range_end: 0x0810_0000, // 1Mb flash
}
#[cell(primary)]
#[ram_region(0x6000, 0x6400)]
#[flash_region(0x0, 0x4000)]
pub struct Cell1 {
}
#[cell]
#[ram_region(0x6400, 0xA000)]
#[flash_region(0x0_4000, 0xF_1000)]
pub struct Cell2 {
#[switch_vectors]
pub run: fn() -> !,
pub a: u32,
pub print_some_value: fn(u32),
}
#[cell]
#[ram_region(0xA000, 0x1_0000)]
#[flash_region(0xF_1000, 0x10_0000)]
pub struct Cell3 {
pub b: u32,
pub run_some_code: fn(),
pub access_static: fn() -> u32,
}
}
```
In this example you define 3 cells: `Cell1`, `Cell2` and `Cell3`. Each of them have
separate crate and can call functions from other crates using safe wrapper, which is created automatically
with macro.
Example of `main.rs` for cell1 crate:
```rust
#![no_std]
#![no_main]
#![feature(const_refs_to_static)]
use emcell_macro::{define_primary_header, extern_header_forward};
use cells_defs::{Cell1, Cell2};
use cortex_m::asm::delay;
extern crate panic_halt;
define_primary_header!{
Cell1 {
}
}
extern_header_forward!(Cell2Wrapper: Cell2);
#[cortex_m_rt::entry]
unsafe fn main() -> ! {
gpio_cfgr();
led_on();
if let Some(cell2) = Cell2Wrapper::new() {
cell2.switch_vectors_and_run() // execute run() -> ! for cell2
}
else {
loop {
delay(1_000_000);
}
}
}
```
build.rs:
```rust
fn main() {
emcell::build_rs::<cells_defs::Cell1>();
}
```
`Cell2Wrapper::new()` is created automatically and perform additional checks to ensure, that header for cell2
was not modified (by comparing hash) and is compatible with current crate.
## Nightly toolchain
Currently, emcell requires nightly because of `const_refs_to_static` feature.
You can use `rustup override set nightly` to set nightly for the current directory.