Skip to content

task + async misc #67

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

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ jobs:
working-directory: zephyr-lang-rust
run: |
# Note that the above build doesn't set Zephyrbase, so we'll need to do that here.
west build -t rustdoc -b qemu_cortex_m3 docgen
west build -b qemu_cortex_m3 docgen
west build -t rustdoc
mkdir rustdocs
mv build/rust/target/thumbv7m-none-eabi/doc rustdocs/nostd

Expand Down
3 changes: 3 additions & 0 deletions docgen/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ CONFIG_GPIO=y
CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT=y
CONFIG_PRINTK=y
CONFIG_POLL=y
CONFIG_I2C=y
CONFIG_I2C_RTIO=y
CONFIG_RTIO=y
92 changes: 50 additions & 42 deletions dt-rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
# few instances were we can actually just match on a property.
- name: gpio-controller
rules:
- type: has_prop
value: gpio-controller
- !HasProp gpio-controller
actions:
- type: instance
value:
raw:
type: myself
- !Instance
raw: !Myself
device: crate::device::gpio::Gpio
static_type: crate::device::gpio::GpioStatic

Expand All @@ -22,68 +19,79 @@
# with each gpio.
- name: gpio-leds
rules:
- type: compatible
value:
- !Compatible
names: [gpio-leds]
level: 1
actions:
- !Instance
raw: !Phandle gpios
device: crate::device::gpio::GpioPin

# Hook up the gpio-keys as gpio pins as well
- name: gpio-keys
rules:
- !Compatible
names:
- gpio-leds
- gpio-keys
level: 1
actions:
- type: instance
value:
raw:
type: phandle
value: gpios
- !Instance
raw: !Phandle gpios
device: crate::device::gpio::GpioPin

# Flash controllers don't have any particular property to identify them, so we need a list of
# compatible values that should match.
- name: flash-controller
rules:
- type: compatible
value:
- !Compatible
names:
- "nordic,nrf52-flash-controller"
- "nordic,nrf51-flash-controller"
- "raspberrypi,pico-flash-controller"
- "zephyr,sim-flash"
- "nordic,nrf52-flash-controller"
- "nordic,nrf51-flash-controller"
- "raspberrypi,pico-flash-controller"
- "st,stm32g4-flash-controller"
- "st,stm32l5-flash-controller"
- "zephyr,sim-flash"
level: 0
actions:
- type: instance
value:
raw:
type: myself
- !Instance
raw: !Myself
device: crate::device::flash::FlashController

# Flash partitions exist as children of a node compatible with "soc-nv-flash" that itself is a child
# of the controller itself.
# TODO: Get the write and erase property from the DT if present.
- name: flash-partition
rules:
- type: compatible
value:
- !Compatible
names:
- "fixed-partitions"
- "fixed-partitions"
level: 1
- type: compatible
value:
- !Compatible
names:
- "soc-nv-flash"
- "soc-nv-flash"
level: 2
actions:
- type: instance
value:
raw:
type: parent
value:
level: 3
args:
- type: reg
- !Instance
raw: !Parent
level: 3
args:
- !Reg
device: "crate::device::flash::FlashPartition"

# Generate a pseudo node that matches all of the labels across the tree with their nodes.
- name: labels
# I2C.
- name: i2c
rules:
- type: root
- !Compatible
names:
- "snps,designware-i2c"
level: 0
actions:
- type: labels
- !Instance
raw: !Myself
device: crate::device::i2c::I2C

# Generate a pseudo node that matches all of the labels across the tree with their nodes.
- name: labels
rules: !Root
actions:
- !Labels
44 changes: 17 additions & 27 deletions samples/bench/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ use alloc::collections::vec_deque::VecDeque;
use alloc::vec;
use executor::AsyncTests;
use static_cell::StaticCell;
use zephyr::kobj_define;
use zephyr::define_work_queue;
use zephyr::raw::k_yield;
use zephyr::sync::{PinWeak, SpinMutex};
use zephyr::time::NoWait;
use zephyr::work::{SimpleAction, Work, WorkQueueBuilder};
use zephyr::work::{SimpleAction, Work};
use zephyr::{
kconfig::CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
printkln,
Expand Down Expand Up @@ -80,7 +80,7 @@ extern "C" fn rust_main() {
spin_bench();
sem_bench();

let simple = Simple::new(tester.workq.clone());
let simple = Simple::new(tester.workq);
let mut num = 6;
while num < 250 {
simple.run(num, TOTAL_ITERS / num);
Expand Down Expand Up @@ -147,7 +147,7 @@ struct ThreadTests {
high_command: Sender<Command>,

/// A work queue for the main runners.
workq: Arc<WorkQueue>,
workq: &'static WorkQueue,

/// The test also all return their result to the main. The threads Send, the main running
/// receives.
Expand All @@ -163,15 +163,7 @@ impl ThreadTests {
let (low_send, low_recv) = bounded(1);
let (high_send, high_recv) = bounded(1);

let workq = Arc::new(
WorkQueueBuilder::new()
.set_priority(5)
.set_no_yield(true)
.start(WORK_STACK.init_once(()).unwrap()),
);

// Leak the workqueue so it doesn't get dropped.
let _ = Arc::into_raw(workq.clone());
let workq = WORKQ.start();

let mut result = Self {
sems: &SEMS,
Expand Down Expand Up @@ -581,20 +573,20 @@ enum TestResult {

/// The Simple test just does a ping pong test using manually submitted work.
struct Simple {
workq: Arc<WorkQueue>,
workq: &'static WorkQueue,
}

impl Simple {
fn new(workq: Arc<WorkQueue>) -> Self {
fn new(workq: &'static WorkQueue) -> Self {
Self { workq }
}

fn run(&self, workers: usize, iterations: usize) {
// printkln!("Running Simple");
let main = Work::new(SimpleMain::new(workers * iterations, self.workq.clone()));
let main = Work::new(SimpleMain::new(workers * iterations, self.workq));

let children: VecDeque<_> = (0..workers)
.map(|n| Work::new(SimpleWorker::new(main.clone(), self.workq.clone(), n)))
.map(|n| Work::new(SimpleWorker::new(main.clone(), self.workq, n)))
.collect();

let mut locked = main.action().locked.lock().unwrap();
Expand All @@ -603,7 +595,7 @@ impl Simple {

let start = now();
// Fire off main, which will run everything.
Work::submit_to_queue(main.clone(), &self.workq).unwrap();
Work::submit_to_queue(main.clone(), self.workq).unwrap();

// And wait for the completion semaphore.
main.action().done.take(Forever).unwrap();
Expand Down Expand Up @@ -642,12 +634,12 @@ impl Simple {
/// A simple worker. When run, it submits the main worker to do the next work.
struct SimpleWorker {
main: PinWeak<Work<SimpleMain>>,
workq: Arc<WorkQueue>,
workq: &'static WorkQueue,
_id: usize,
}

impl SimpleWorker {
fn new(main: Pin<Arc<Work<SimpleMain>>>, workq: Arc<WorkQueue>, id: usize) -> Self {
fn new(main: Pin<Arc<Work<SimpleMain>>>, workq: &'static WorkQueue, id: usize) -> Self {
Self {
main: PinWeak::downgrade(main),
workq,
Expand All @@ -660,7 +652,7 @@ impl SimpleAction for SimpleWorker {
fn act(self: Pin<&Self>) {
// Each time we are run, fire the main worker back up.
let main = self.main.upgrade().unwrap();
Work::submit_to_queue(main.clone(), &self.workq).unwrap();
Work::submit_to_queue(main.clone(), self.workq).unwrap();
}
}

Expand All @@ -670,7 +662,7 @@ impl SimpleAction for SimpleWorker {
struct SimpleMain {
/// All of the work items.
locked: SpinMutex<Locked>,
workq: Arc<WorkQueue>,
workq: &'static WorkQueue,
done: Semaphore,
}

Expand All @@ -690,12 +682,12 @@ impl SimpleAction for SimpleMain {
lock.count -= 1;
drop(lock);

Work::submit_to_queue(worker.clone(), &self.workq).unwrap();
Work::submit_to_queue(worker.clone(), self.workq).unwrap();
}
}

impl SimpleMain {
fn new(count: usize, workq: Arc<WorkQueue>) -> Self {
fn new(count: usize, workq: &'static WorkQueue) -> Self {
Self {
locked: SpinMutex::new(Locked::new(count)),
done: Semaphore::new(0, 1),
Expand Down Expand Up @@ -812,9 +804,7 @@ impl<'a> BenchTimer<'a> {
}
}

kobj_define! {
static WORK_STACK: ThreadStack<WORK_STACK_SIZE>;
}
define_work_queue!(WORKQ, WORK_STACK_SIZE, priority = 5, no_yield = true);

static SEMS: [Semaphore; NUM_THREADS] = [const { Semaphore::new(0, u32::MAX) }; NUM_THREADS];
static BACK_SEMS: [Semaphore; NUM_THREADS] = [const { Semaphore::new(0, u32::MAX) }; NUM_THREADS];
9 changes: 4 additions & 5 deletions samples/embassy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,16 @@ features = [

[dependencies.embassy-futures]
version = "0.1.1"
# path = "../../embassy/embassy-futures"

[dependencies.embassy-sync]
version = "0.6.2"
# path = "../../embassy/embassy-sync"

[dependencies.embassy-time]
version = "0.4.0"
# path = "../../embassy/embassy-time"
# This is board specific.
features = ["tick-hz-10_000"]
# For real builds, you should figure out your target's tick rate and set the appropriate feature,
# like in these examples. Without this, embassy-time will assume a 1Mhz tick rate, and every time
# operation will involve a conversion.
#features = ["tick-hz-10_000"]

[dependencies.critical-section]
version = "1.2"
Expand Down
6 changes: 6 additions & 0 deletions tests/drivers/gpio-async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Async gpio

This demo makes use of the GPIO `wait_for_high()` and `wait_for_low()` async operations.

Unfortunately, not all GPIO controllers support level triggered interrupts. Notably, most of the
stm32 line does not support level triggered interrupts.
6 changes: 5 additions & 1 deletion tests/drivers/gpio-async/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ CONFIG_RUST_ALLOC=y
CONFIG_GPIO=y
CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT=y

CONFIG_LOG_BACKEND_RTT=n
# CONFIG_LOG_BACKEND_RTT=n

CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
5 changes: 5 additions & 0 deletions tests/drivers/gpio-async/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,18 @@ async fn main(spawner: Spawner) {
info!("Hello world");
let _ = spawner;

/*
let mut col0 = zephyr::devicetree::labels::col0::get_instance().unwrap();
let mut row0 = zephyr::devicetree::labels::row0::get_instance().unwrap();
*/
let mut row0 = zephyr::devicetree::aliases::sw0::get_instance().unwrap();
let mut gpio_token = unsafe { zephyr::device::gpio::GpioToken::get_instance().unwrap() };

unsafe {
/*
col0.configure(&mut gpio_token, GPIO_OUTPUT_ACTIVE);
col0.set(&mut gpio_token, true);
*/
row0.configure(&mut gpio_token, GPIO_INPUT | GPIO_PULL_DOWN);
}

Expand Down
10 changes: 6 additions & 4 deletions zephyr-build/src/devicetree/augment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ pub trait Augment {
/// The default implementation checks if this node matches and calls a generator if it does, or
/// does nothing if not.
fn augment(&self, node: &Node, tree: &DeviceTree) -> TokenStream {
// If there is a status field present, and it is not set to "okay", don't augment this node.
if let Some(status) = node.get_single_string("status") {
if status != "okay" {
return TokenStream::new();
}
}
if self.is_compatible(node) {
self.generate(node, tree)
} else {
Expand Down Expand Up @@ -75,7 +81,6 @@ impl Augment for Augmentation {

/// A matching rule.
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case", content = "value")]
pub enum Rule {
/// A set of "or" matches.
Or(Vec<Rule>),
Expand Down Expand Up @@ -121,7 +126,6 @@ fn parent_compatible(node: &Node, names: &[String], level: usize) -> bool {

/// An action to perform
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case", content = "value")]
pub enum Action {
/// Generate an "instance" with a specific device name.
Instance {
Expand Down Expand Up @@ -171,7 +175,6 @@ impl Action {
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case", content = "value")]
pub enum RawInfo {
/// Get the raw device directly from this node.
Myself,
Expand Down Expand Up @@ -270,7 +273,6 @@ impl RawInfo {
///
/// At this point, we assume these all come from the current node.
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case", content = "value")]
pub enum ArgInfo {
/// The arguments come from a 'reg' property.
Reg,
Expand Down
Loading