ferroforge 0.1.0

Compose reusable RTIC tasks and project-owned initialization into a real RTIC firmware application
Documentation
  • Coverage
  • 100%
    1 out of 1 items documented0 out of 0 items with examples
  • Size
  • Source code size: 16.44 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 70.61 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 7s Average build duration of successful builds.
  • all releases: 6s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Eirik2020/ferroforge
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • Eirik2020

FerroForge

Reusable RTIC tasks, selected into firmware. This crate provides the two macros: #[ferroforge::task] marks a definition, and ferroforge::app! declares the application that selects it.

A task is an ordinary function in its own crate. It names what it needs, and compiles on its own without any firmware:

#[ferroforge::task(
    local = [count: u32],
    config = [period_ms: u32],
    monotonic = Mono,
)]
pub async fn heartbeat(cx: heartbeat::Context) -> ! {
    loop {
        *cx.local.count = cx.local.count.wrapping_add(1);
        defmt::info!("heartbeat {=u32}", *cx.local.count);
        Mono::delay(CONFIG.PERIOD_MS.millis()).await;
    }
}

A firmware writes an ordinary RTIC application - resources, init, native HAL calls - and declares each task instance by naming its definition and binding its needs to the firmware's own resources and values:

ferroforge::app! {
    device = stm32f4xx_hal::pac,
    dispatchers = [SPI1],
    monotonic = Mono,

    use my_tasks::heartbeat;

    #[shared]
    struct Shared {}

    #[local]
    struct Local { heartbeat_count: u32 }

    #[init]
    fn init(cx: init::Context) -> (Shared, Local) {
        // clocks, peripherals, Mono::start(..)
        status::spawn().unwrap();
        (Shared {}, Local { heartbeat_count: 0 })
    }

    #[task(
        from = heartbeat,
        priority = 1,
        local = [count = heartbeat_count],
        config = [period_ms: u32 = 1000],
    )]
    async fn status(cx: status::Context) -> !;
}

app! expands in place into #[rtic::app], and each declaration becomes a handler that calls the definition. Nothing is copied or generated into another project, so every mistake is an ordinary compile error at the line that made it, and checking is RTIC's and Rust's - FerroForge adds none of its own.

The quickest start is the ferroforge command, which writes a working project: see ferroforge-cli. The authoring model in full is in the architecture chapter.

Licensed under either of MIT or Apache-2.0, at your option.