402: Extern task r=AfoHT a=perlindgren

Allows hardware and software task to be externally declared.

CI test, don't merge yet (squash needed).

Co-authored-by: Per Lindgren <per.lindgren@ltu.se>
This commit is contained in:
bors[bot] 2020-10-29 18:34:35 +00:00 committed by GitHub
commit ad50b54530
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 125 additions and 31 deletions

View file

@ -13,6 +13,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- `#[task_local]`, there must be only one task, similar to a task local - `#[task_local]`, there must be only one task, similar to a task local
resource, but (optionally) set-up by init. This is similar to move. resource, but (optionally) set-up by init. This is similar to move.
- Improved ergonomics allowing separation of task signatures to actual implementation in extern block `extern "Rust" { #[task(..)] fn t(..); }`.
### Changed ### Changed
- [breaking-change] [PR 400] Move dispatchers from extern block to app argument. - [breaking-change] [PR 400] Move dispatchers from extern block to app argument.

View file

@ -36,7 +36,6 @@ mod app {
This works also for ram functions, see examples/ramfunc.rs This works also for ram functions, see examples/ramfunc.rs
## Module instead of Const ## Module instead of Const
With the support of attributes on modules the `const APP` workaround is not needed. With the support of attributes on modules the `const APP` workaround is not needed.
@ -125,3 +124,13 @@ struct whateveryouwant {
``` ```
would work equally well. would work equally well.
---
## Additions
### Extern tasks
Both software and hardware tasks can now be defined external to the `mod app`. Previously this was possible only by implementing a trampoline calling out the task implementation.
See examples `examples/extern_binds.rs` and `examples/extern_spawn.rs`.

48
examples/extern_binds.rs Normal file
View file

@ -0,0 +1,48 @@
//! examples/extern_binds.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
// Free function implementing the interrupt bound task `foo`.
fn foo(_: app::foo::Context) {
hprintln!("foo called").ok();
}
#[rtic::app(device = lm3s6965)]
mod app {
use crate::foo;
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
#[init]
fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
init::LateResources {}
}
#[idle]
fn idle(_: idle::Context) -> ! {
hprintln!("idle").unwrap();
rtic::pend(Interrupt::UART0);
debug::exit(debug::EXIT_SUCCESS);
loop {
cortex_m::asm::nop();
}
}
extern "Rust" {
#[task(binds = UART0)]
fn foo(_: foo::Context);
}
}

35
examples/extern_spawn.rs Normal file
View file

@ -0,0 +1,35 @@
//! examples/extern_spawn.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::{debug, hprintln};
use panic_semihosting as _;
// Free function implementing the spawnable task `foo`.
fn foo(_c: app::foo::Context, x: i32, y: u32) {
hprintln!("foo {}, {}", x, y).unwrap();
if x == 2 {
debug::exit(debug::EXIT_SUCCESS);
}
app::foo::spawn(2, 3).unwrap();
}
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
mod app {
use crate::foo;
#[init]
fn init(_c: init::Context) -> init::LateResources {
foo::spawn(1, 2).unwrap();
init::LateResources {}
}
extern "Rust" {
#[task()]
fn foo(_c: foo::Context, _x: i32, _y: u32);
}
}

View file

@ -95,19 +95,21 @@ pub fn codegen(
locals_pat = Some(pat); locals_pat = Some(pat);
} }
let attrs = &task.attrs; if !&task.is_extern {
let context = &task.context; let attrs = &task.attrs;
let stmts = &task.stmts; let context = &task.context;
let locals_pat = locals_pat.iter(); let stmts = &task.stmts;
user_tasks.push(quote!( let locals_pat = locals_pat.iter();
#(#attrs)* user_tasks.push(quote!(
#[allow(non_snake_case)] #(#attrs)*
fn #name(#(#locals_pat,)* #context: #name::Context) { #[allow(non_snake_case)]
use rtic::Mutex as _; fn #name(#(#locals_pat,)* #context: #name::Context) {
use rtic::Mutex as _;
#(#stmts)* #(#stmts)*
} }
)); ));
}
} }
(mod_app, root, user_tasks) (mod_app, root, user_tasks)

View file

@ -99,21 +99,23 @@ pub fn codegen(
root.push(struct_); root.push(struct_);
} }
let context = &task.context; if !&task.is_extern {
let attrs = &task.attrs; let context = &task.context;
let cfgs = &task.cfgs; let attrs = &task.attrs;
let stmts = &task.stmts; let cfgs = &task.cfgs;
let locals_pat = locals_pat.iter(); let stmts = &task.stmts;
user_tasks.push(quote!( let locals_pat = locals_pat.iter();
#(#attrs)* user_tasks.push(quote!(
#(#cfgs)* #(#attrs)*
#[allow(non_snake_case)] #(#cfgs)*
fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) { #[allow(non_snake_case)]
use rtic::Mutex as _; fn #name(#(#locals_pat,)* #context: #name::Context #(,#inputs)*) {
use rtic::Mutex as _;
#(#stmts)* #(#stmts)*
} }
)); ));
}
root.push(module::codegen( root.push(module::codegen(
Context::SoftwareTask(name), Context::SoftwareTask(name),

View file

@ -4,8 +4,4 @@
mod app { mod app {
#[task(binds = UART0)] #[task(binds = UART0)]
fn a(_: a::Context) {} fn a(_: a::Context) {}
extern "C" {
fn UART0();
}
} }