Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace task macro with trait #3

Merged
merged 14 commits into from
Apr 18, 2024
Merged
2 changes: 0 additions & 2 deletions .github/workflows/clippy_fmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@ jobs:
with:
cache-on-failure: "true"
- run: cargo test -p veecle-pxros --all-targets --all-features
- run: cargo test -p task-macro --all-targets --all-features

# This requires --no-default-features to prevent conflicts between std and veecle-pxros panic impl.
- run: cargo test -p veecle-pxros --doc --no-default-features
- run: cargo test -p task-macro --doc --all-features
fmt:
name: cargo fmt
runs-on: ubuntu-latest
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ pxros.workspace = true
static_cell.workspace = true
pin-project.workspace = true

task-macro = { path = "task-macro" }

[features]
default = ["rt"]
# Enable this to import veecle default implementation for
Expand All @@ -25,12 +23,11 @@ default = ["rt"]
# 3. Task autodeployment from Rust
#
# If disabled alternative implementation shall be provided
rt = ["task-macro/auto_spawn"]
rt = []

[workspace]
resolver = "2"
members = [
"task-macro",
"examples/example-*",
"xtask",
]
Expand Down
9 changes: 0 additions & 9 deletions app-tc37x/ld/tc37x_pxros_bsp_example.ld.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -415,15 +415,6 @@ SECTIONS

SECTIONS
{
/* Rust task list, collected in this section by the linker. See veecle-nox->pxros_rt->deploy.rs for more info */
.rust_auto_tasks :
{
__rust_auto_task_start = .;
KEEP(*(.rust_auto_tasks))
KEEP(*(.rust_auto_tasks.*))
__rust_auto_task_end = .;
} > RODATA

__DATA_START = ADDR(.data);
__DATA_END = ADDR(.data) + SIZEOF(.data);

Expand Down
57 changes: 35 additions & 22 deletions examples/example-async/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Hidden backend code for the exercise 3 to validate flags

use core::ffi::CStr;
use core::sync::atomic::AtomicU32;
use core::sync::atomic::Ordering::Relaxed;
use core::time::Duration;
Expand All @@ -9,6 +10,7 @@ use pxros::PxResult;
use veecle_pxros::pxros::events::{Receiver, Signaller};
use veecle_pxros::pxros::messages::MailSender;
use veecle_pxros::pxros::name_server::{NameServer, TaskName};
use veecle_pxros::pxros::task::PxrosTask;
use veecle_pxros::pxros::ticker::Ticker;
use veecle_pxros::pxros::time::time_since_boot;

Expand Down Expand Up @@ -137,34 +139,45 @@ bitflags::bitflags! {
}
}

#[veecle_pxros::pxros_task(task_name = VALIDATION_TASK_NAME, auto_spawn(core = 0, priority = 15))]
fn flag_message_task(mailbox: PxMbx_t) -> PxResult<()> {
// Get the user task
let user_task = NameServer::query(&MAIN_TASK_NAME, FlagEvents::Ticker)?;
pub(crate) struct FlagMessageTask;
impl PxrosTask for FlagMessageTask {
fn task_name() -> Option<TaskName> {
Some(VALIDATION_TASK_NAME)
}

fn debug_name() -> &'static CStr {
CStr::from_bytes_with_nul("FlagMessageTask\0".as_bytes())
.expect("The debug name should be a valid, zero-terminated C string.")
}

fn task_main(mailbox: PxMbx_t) -> PxResult<()> {
// Get the user task
let user_task = NameServer::query(&MAIN_TASK_NAME, FlagEvents::Ticker)?;

// Get a sender for the flag
let mut sender = MailSender::new(user_task)?;
let mut signaller = Signaller::new(FlagEvents::Terminate, user_task);
let mut start_signal = Receiver::new(mailbox, FlagEvents::StartTransmission);
// Get a sender for the flag
let mut sender = MailSender::new(user_task)?;
let mut signaller = Signaller::new(FlagEvents::Terminate, user_task);
let mut start_signal = Receiver::new(mailbox, FlagEvents::StartTransmission);

loop {
let (event, _) = start_signal.receive();
if event.contains(FlagEvents::StartTransmission) {
break;
loop {
let (event, _) = start_signal.receive();
if event.contains(FlagEvents::StartTransmission) {
break;
}
}
}

const FLAG: &[u8] = b"PdfADhtQnH";
let mut ticker = Ticker::every(FlagEvents::Ticker, Duration::from_millis(250))?;
const FLAG: &[u8] = b"PdfADhtQnH";
let mut ticker = Ticker::every(FlagEvents::Ticker, Duration::from_millis(250))?;

for &byte in FLAG {
sender.send_bytes(&[byte])?;
ticker.wait();
}
for &byte in FLAG {
sender.send_bytes(&[byte])?;
ticker.wait();
}

signaller.signal()?;
signaller.signal()?;

loop {
ticker.wait();
loop {
ticker.wait();
}
}
}
78 changes: 41 additions & 37 deletions examples/example-async/src/ex3_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use core::time::Duration;
use futures::StreamExt;
use pxros::bindings::*;
use pxros::PxResult;
use veecle_pxros::pxros::task::PxrosTask;
use veecle_pxros::pxros::ticker::AsyncTicker;
use veecle_pxros::pxros_run;

use crate::TickerEvents;
use crate::{AsyncExecutorTask, TickerEvents};

/// Invoke periodically with the correct timing: at a certain point this
/// will result in a flag being released.
Expand All @@ -27,44 +28,47 @@ fn call_ticker_2() -> Option<&'static str> {
unsafe { ffi_ex1_ticker_2() }
}

/// This is an example of a generic async function: in contrast to blocking code, async
/// allows to "generalize" a single complex implementation into a multitude of *isolated*
/// async function each `.awaiting` the blocking code.
///
/// The goal is to fill-up the code here so that the exercise 3.1 can be solved in a generic
/// manner.
pub async fn ex1_ticker<F>(mut ticker: AsyncTicker<TickerEvents>, callback: F) -> PxResult<()>
where
F: Fn() -> Option<&'static str>,
{
while (ticker.next().await).is_some() {
if let Some(flag) = callback() {
defmt::info!("The (3.1) flag is: {}", flag);
return Ok(());
impl AsyncExecutorTask {
/// This is an example of a generic async function: in contrast to blocking code, async
/// allows to "generalize" a single complex implementation into a multitude of *isolated*
/// async function each `.awaiting` the blocking code.
///
/// The goal is to fill-up the code here so that the exercise 3.1 can be solved in a generic
/// manner.
pub async fn ex1_ticker<F>(mut ticker: AsyncTicker<TickerEvents>, callback: F) -> PxResult<()>
where
F: Fn() -> Option<&'static str>,
{
let (task_debug_name, log_task_id) = <Self as PxrosTask>::log_id();
while (ticker.next().await).is_some() {
if let Some(flag) = callback() {
defmt::info!("[{}: {}] The (3.1) flag is: {}", task_debug_name, log_task_id, flag);
return Ok(());
}
}
}

defmt::panic!("Ticker terminated");
}
defmt::panic!("[{}: {}] Ticker terminated.", task_debug_name, log_task_id);
}

/// This function shall use the [pxros_run] macro to spawn two async tasks via
/// generic [ex1_ticker] function.
///
/// Each async task shall call either [call_ticker_1] & [call_ticker_2] and print the flag
/// when `Some(_)`.
///
/// When *done*, each async function shall return Ok(()).
///
/// Ticker timings shall be `150ms` for `Ticker1` and `220ms` for `Ticker2`.
pub fn ex3_1_solution(mailbox: PxMbx_t) {
let ticker_1 = AsyncTicker::every(TickerEvents::Ticker1, Duration::from_millis(150)).unwrap();
let ticker_2 = AsyncTicker::every(TickerEvents::Ticker2, Duration::from_millis(220)).unwrap();
/// This function shall use the [pxros_run] macro to spawn two async tasks via
/// generic [ex1_ticker] function.
///
/// Each async task shall call either [call_ticker_1] & [call_ticker_2] and print the flag
/// when `Some(_)`.
///
/// When *done*, each async function shall return Ok(()).
///
/// Ticker timings shall be `150ms` for `Ticker1` and `220ms` for `Ticker2`.
pub fn ex3_1_solution(mailbox: PxMbx_t) {
let ticker_1 = AsyncTicker::every(TickerEvents::Ticker1, Duration::from_millis(150)).unwrap();
let ticker_2 = AsyncTicker::every(TickerEvents::Ticker2, Duration::from_millis(220)).unwrap();

pxros_run!(
mailbox,
TickerEvents,
PxResult<()>,
ex1_ticker(ticker_1, call_ticker_1),
ex1_ticker(ticker_2, call_ticker_2)
);
pxros_run!(
mailbox,
TickerEvents,
PxResult<()>,
Self::ex1_ticker(ticker_1, call_ticker_1),
Self::ex1_ticker(ticker_2, call_ticker_2)
);
}
}
34 changes: 18 additions & 16 deletions examples/example-async/src/ex3_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use pxros::PxResult;
use veecle_pxros::pxros::ticker::AsyncTicker;
use veecle_pxros::pxros_run;

use crate::TickerEvents;
use crate::{AsyncExecutorTask, TickerEvents};

/// Invoke periodically with the correct timing to yield a specific sequence of numbers.
fn read_sensor_1() -> u32 {
Expand Down Expand Up @@ -79,21 +79,23 @@ async fn sensor_2(ticker: AsyncTicker<TickerEvents>) -> PxResult<u32> {
Ok(number)
}

/// This function shall use the [pxros_run] macro to spawn two async tasks via
/// [sensor_1] and [sensor_2] functions.
///
/// Each async task shall return a `u32` value to the executor, which can be then collected as
/// an array via `let = pxros_run!(...)`.
///
/// Each returned `u32` shall then be submit via [submit_result]: if correct the flag shall
/// be printed.
pub fn ex3_2_solution(mailbox: PxMbx_t) {
let ticker_1 = AsyncTicker::every(TickerEvents::Ticker1, Duration::from_millis(150)).unwrap();
let ticker_2 = AsyncTicker::every(TickerEvents::Ticker2, Duration::from_millis(220)).unwrap();
impl AsyncExecutorTask {
/// This function shall use the [pxros_run] macro to spawn two async tasks via
/// [sensor_1] and [sensor_2] functions.
///
/// Each async task shall return a `u32` value to the executor, which can be then collected as
/// an array via `let = pxros_run!(...)`.
///
/// Each returned `u32` shall then be submit via [submit_result]: if correct the flag shall
/// be printed.
pub fn ex3_2_solution(mailbox: PxMbx_t) {
let ticker_1 = AsyncTicker::every(TickerEvents::Ticker1, Duration::from_millis(150)).unwrap();
let ticker_2 = AsyncTicker::every(TickerEvents::Ticker2, Duration::from_millis(220)).unwrap();

let result = pxros_run!(mailbox, TickerEvents, PxResult<u32>, sensor_1(ticker_1), sensor_2(ticker_2));
let result = pxros_run!(mailbox, TickerEvents, PxResult<u32>, sensor_1(ticker_1), sensor_2(ticker_2));

let sensor_1 = result[0].unwrap().unwrap();
let sensor_2 = result[1].unwrap().unwrap();
submit_result(sensor_1, sensor_2);
let sensor_1 = result[0].unwrap().unwrap();
let sensor_2 = result[1].unwrap().unwrap();
submit_result(sensor_1, sensor_2);
}
}
Loading