Embedded ci works

This commit is contained in:
Emil Fresk 2022-03-04 13:26:33 +01:00
parent a765f3fffa
commit ca2577e3b8
131 changed files with 792 additions and 490 deletions

View file

@ -135,8 +135,8 @@ jobs:
args: --examples --target=${{ matrix.target }}
# Verify the example output with run-pass tests
testexamples:
name: testexamples
testexamplesqemu:
name: testexamplesqemu
runs-on: ubuntu-20.04
strategy:
matrix:
@ -157,13 +157,6 @@ jobs:
override: true
components: llvm-tools-preview
# Use precompiled binutils
- name: cargo install cargo-binutils
uses: actions-rs/install@v0.1
with:
crate: cargo-binutils
version: latest
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1
@ -176,8 +169,49 @@ jobs:
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs macros/src/lib.rs
- name: Run-pass tests
run:
cargo xtask --target ${{ matrix.target }}
run: |
cd examples-runner
cargo xtask --target ${{ matrix.target }} --runner qemu
testexamplesembeddedci:
name: testexamplesembeddedci
runs-on: ubuntu-20.04
strategy:
matrix:
target:
- thumbv7m-none-eabi
- thumbv6m-none-eabi
toolchain:
- stable
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }})
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
target: ${{ matrix.target }}
override: true
components: llvm-tools-preview
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1
- name: Install embedded-ci-client
run: |
cargo install --git https://github.com/korken89/embedded-ci.git embedded-ci-client
- name: Fail on warnings
run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs macros/src/lib.rs
- name: Run-pass tests
env:
EMBEDDED_CI_TOKEN: ${{ secrets.EMBEDDED_CI_TOKEN }}
EMBEDDED_CI_SERVER: ${{ secrets.EMBEDDED_CI_SERVER }}
run: |
cd examples-runner
cargo xtask --target ${{ matrix.target }} --runner embedded-ci
# Check the correctness of macros/ crate
checkmacros:
@ -373,7 +407,8 @@ jobs:
- check
- clippy
- checkexamples
- testexamples
- testexamplesqemu
- testexamplesembeddedci
- checkmacros
- testmacros
- tests
@ -555,7 +590,8 @@ jobs:
- check
- clippy
- checkexamples
- testexamples
- testexamplesqemu
- testexamplesembeddedci
- checkmacros
- testmacros
- tests

View file

@ -9,6 +9,7 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
### Added
- HIL tests (embedded-ci)
- Improve how CHANGELOG.md merges are handled
- If current $stable and master version matches, dev-book redirects to $stable book
- During deploy stage, merge master branch into current stable IFF cargo package version matches

View file

@ -49,7 +49,9 @@ lto = true
[workspace]
members = [
"macros",
"xtask",
]
exclude = [
"examples-runner",
]
# do not optimize proc-macro deps or build scripts

View file

@ -28,5 +28,5 @@ $ cargo run --target thumbv7m-none-eabi --example locals
Yields this output:
``` console
{{#include ../../../ci/expected/locals.run}}
{{#include ../../../examples-runner/ci/expected/locals.run}}
```

View file

@ -22,5 +22,5 @@ To give a flavour of RTIC, the following example contains commonly used features
In the following sections we will go through each feature in detail.
``` rust
{{#include ../../../../examples/common.rs}}
{{#include ../../../../examples-runner/src/bin/common.rs}}
```

View file

@ -17,12 +17,12 @@ are safe to access.
The example below shows that `idle` runs after `init`.
``` rust
{{#include ../../../../examples/idle.rs}}
{{#include ../../../../examples-runner/src/bin/idle.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example idle
{{#include ../../../../ci/expected/idle.run}}
{{#include ../../../../examples-runner/ci/expected/idle.run}}
```
By default, the RTIC `idle` task does not try to optimize for any specific targets.
@ -43,10 +43,10 @@ default [`nop()`][NOP] with [`wfi()`][WFI].
[NOP]: https://developer.arm.com/documentation/dui0662/b/The-Cortex-M0--Instruction-Set/Miscellaneous-instructions/NOP
``` rust
{{#include ../../../../examples/idle-wfi.rs}}
{{#include ../../../../examples-runner/src/bin/idle-wfi.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example idle-wfi
{{#include ../../../../ci/expected/idle-wfi.run}}
{{#include ../../../../examples-runner/ci/expected/idle-wfi.run}}
```

View file

@ -19,14 +19,14 @@ The `device` field is available when the `peripherals` argument is set to the de
In the rare case you want to implement an ultra-slim application you can explicitly set `peripherals` to `false`.
``` rust
{{#include ../../../../examples/init.rs}}
{{#include ../../../../examples-runner/src/bin/init.rs}}
```
Running the example will print `init` to the console and then exit the QEMU process.
``` console
$ cargo run --target thumbv7m-none-eabi --example init
{{#include ../../../../ci/expected/init.run}}
{{#include ../../../../examples-runner/ci/expected/init.run}}
```
> **NOTE**: You can choose target device by passing a target

View file

@ -3,5 +3,5 @@
This is the smallest possible RTIC application:
``` rust
{{#include ../../../../examples/smallest.rs}}
{{#include ../../../../examples-runner/src/bin/smallest.rs}}
```

View file

@ -39,12 +39,12 @@ Task Priority
The following example showcases the priority based scheduling of tasks:
``` rust
{{#include ../../../../examples/preempt.rs}}
{{#include ../../../../examples-runner/src/bin/preempt.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example preempt
{{#include ../../../../ci/expected/preempt.run}}
{{#include ../../../../examples-runner/ci/expected/preempt.run}}
```
Note that the task `bar` does *not* preempt task `baz` because its priority

View file

@ -28,10 +28,10 @@ The example below demonstrates the use of the `#[task(binds = InterruptName)]` a
hardware task bound to an interrupt handler.
``` rust
{{#include ../../../../examples/hardware.rs}}
{{#include ../../../../examples-runner/src/bin/hardware.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example hardware
{{#include ../../../../ci/expected/hardware.run}}
{{#include ../../../../examples-runner/ci/expected/hardware.run}}
```

View file

@ -11,10 +11,10 @@ pending spawns of `foo`. Exceeding this capacity is an `Error`.
The number of arguments to a task is not limited:
``` rust
{{#include ../../../../examples/message_passing.rs}}
{{#include ../../../../examples-runner/src/bin/message_passing.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example message_passing
{{#include ../../../../ci/expected/message_passing.run}}
{{#include ../../../../examples-runner/ci/expected/message_passing.run}}
```

View file

@ -35,12 +35,12 @@ This activates the monotonics making it possible to use them.
See the following example:
``` rust
{{#include ../../../../examples/schedule.rs}}
{{#include ../../../../examples-runner/src/bin/schedule.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example schedule
{{#include ../../../../ci/expected/schedule.run}}
{{#include ../../../../examples-runner/ci/expected/schedule.run}}
```
## Canceling or rescheduling a scheduled task
@ -51,10 +51,10 @@ If `cancel` or `reschedule_at`/`reschedule_after` returns an `Err` it means that
too late and that the task is already sent for execution. The following example shows this in action:
``` rust
{{#include ../../../../examples/cancel-reschedule.rs}}
{{#include ../../../../examples-runner/src/bin/cancel-reschedule.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example cancel-reschedule
{{#include ../../../../ci/expected/cancel-reschedule.run}}
{{#include ../../../../examples-runner/ci/expected/cancel-reschedule.run}}
```

View file

@ -39,14 +39,14 @@ The example application shown below contains two tasks where each task has acces
`#[local]` resource, plus that the `idle` task has its own `#[local]` as well.
``` rust
{{#include ../../../../examples/locals.rs}}
{{#include ../../../../examples-runner/src/bin/locals.rs}}
```
Running the example:
``` console
$ cargo run --target thumbv7m-none-eabi --example locals
{{#include ../../../../ci/expected/locals.run}}
{{#include ../../../../examples-runner/ci/expected/locals.run}}
```
### Task local initialized resources
@ -64,12 +64,12 @@ are not crossing any thread boundary.
In the example below the different uses and lifetimes are shown:
``` rust
{{#include ../../../../examples/declared_locals.rs}}
{{#include ../../../../examples-runner/src/bin/declared_locals.rs}}
```
<!-- ``` console
$ cargo run --target thumbv7m-none-eabi --example declared_locals
{{#include ../../../../ci/expected/declared_locals.run}}
{{#include ../../../../examples-runner/ci/expected/declared_locals.run}}
``` -->
## `#[shared]` resources and `lock`
@ -97,12 +97,12 @@ resource for accessing the data. The highest priority handler, which do not acce
resource, is free to preempt the critical section created by the lowest priority handler.
``` rust
{{#include ../../../../examples/lock.rs}}
{{#include ../../../../examples-runner/src/bin/lock.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example lock
{{#include ../../../../ci/expected/lock.run}}
{{#include ../../../../examples-runner/ci/expected/lock.run}}
```
Types of `#[shared]` resources have to be both [`Send`] and [`Sync`].
@ -113,12 +113,12 @@ As an extension to `lock`, and to reduce rightward drift, locks can be taken as
following examples show this in use:
``` rust
{{#include ../../../../examples/multilock.rs}}
{{#include ../../../../examples-runner/src/bin/multilock.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example multilock
{{#include ../../../../ci/expected/multilock.run}}
{{#include ../../../../examples-runner/ci/expected/multilock.run}}
```
## Only shared (`&-`) access
@ -143,12 +143,12 @@ In the example below a key (e.g. a cryptographic key) is loaded (or created) at
used from two tasks that run at different priorities without any kind of lock.
``` rust
{{#include ../../../../examples/only-shared-access.rs}}
{{#include ../../../../examples-runner/src/bin/only-shared-access.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example only-shared-access
{{#include ../../../../ci/expected/only-shared-access.run}}
{{#include ../../../../examples-runner/ci/expected/only-shared-access.run}}
```
## Lock-free resource access of shared resources
@ -165,10 +165,10 @@ tasks running at different priorities will result in a *compile-time* error -- n
API would be a data race in that case.
``` rust
{{#include ../../../../examples/lock-free.rs}}
{{#include ../../../../examples-runner/src/bin/lock-free.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example lock-free
{{#include ../../../../ci/expected/lock-free.run}}
{{#include ../../../../examples-runner/ci/expected/lock-free.run}}
```

View file

@ -34,10 +34,10 @@ The framework will give a compilation error if there are not enough dispatchers
See the following example:
``` rust
{{#include ../../../../examples/spawn.rs}}
{{#include ../../../../examples-runner/src/bin/spawn.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example spawn
{{#include ../../../../ci/expected/spawn.run}}
{{#include ../../../../examples-runner/ci/expected/spawn.run}}
```

View file

@ -5,10 +5,10 @@ resources.
Here are two examples on how to split up the resource struct:
``` rust
{{#include ../../../../examples/destructure.rs}}
{{#include ../../../../examples-runner/src/bin/destructure.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example destructure
{{#include ../../../../ci/expected/destructure.run}}
{{#include ../../../../examples-runner/ci/expected/destructure.run}}
```

View file

@ -20,14 +20,14 @@ improve performance in some cases.
The example below shows how to place the higher priority task, `bar`, in RAM.
``` rust
{{#include ../../../../examples/ramfunc.rs}}
{{#include ../../../../examples-runner/src/bin/ramfunc.rs}}
```
Running this program produces the expected output.
``` console
$ cargo run --target thumbv7m-none-eabi --example ramfunc
{{#include ../../../../ci/expected/ramfunc.run}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run}}
```
One can look at the output of `cargo-nm` to confirm that `bar` ended in RAM
@ -35,10 +35,10 @@ One can look at the output of `cargo-nm` to confirm that `bar` ended in RAM
``` console
$ cargo nm --example ramfunc --release | grep ' foo::'
{{#include ../../../../ci/expected/ramfunc.run.grep.foo}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.foo}}
```
``` console
$ cargo nm --example ramfunc --release | grep ' bar::'
{{#include ../../../../ci/expected/ramfunc.run.grep.bar}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.bar}}
```

View file

@ -18,10 +18,10 @@ or one can use a statically allocated memory pool like [`heapless::Pool`].
Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
``` rust
{{#include ../../../../examples/pool.rs}}
{{#include ../../../../examples-runner/src/bin/pool.rs}}
```
``` console
$ cargo run --target thumbv7m-none-eabi --example pool
{{#include ../../../../ci/expected/pool.run}}
{{#include ../../../../examples-runner/ci/expected/pool.run}}
```

View file

@ -13,12 +13,12 @@ for lock-free access to the shared queue.
[`heapless::spsc::Queue`]: https://docs.rs/heapless/0.7.5/heapless/spsc/struct.Queue.html
``` rust
{{#include ../../../../examples/static.rs}}
{{#include ../../../../examples-runner/src/bin/static.rs}}
```
Running this program produces the expected output.
``` console
$ cargo run --target thumbv7m-none-eabi --example static
{{#include ../../../../ci/expected/static.run}}
{{#include ../../../../examples-runner/ci/expected/static.run}}
```

View file

@ -51,7 +51,7 @@
``` console
$ cargo run --example init
{{#include ../../../../ci/expected/init.run}}
{{#include ../../../../examples-runner/ci/expected/init.run}}
```
> **ПРИМЕЧАНИЕ**: Не забывайте указывать выбранное вами целевое устройство, передавая параметр target
@ -87,7 +87,7 @@ $ cargo run --example init
``` console
$ cargo run --example idle
{{#include ../../../../ci/expected/idle.run}}
{{#include ../../../../examples-runner/ci/expected/idle.run}}
```
## Аппаратные задачи
@ -109,7 +109,7 @@ mut` переменные безопасны для использования
``` console
$ cargo run --example hardware
{{#include ../../../../ci/expected/hardware.run}}
{{#include ../../../../examples-runner/ci/expected/hardware.run}}
```
До сих пор все программы на RTIC, которые мы видели, не отличались от программ,
@ -145,7 +145,7 @@ $ cargo run --example hardware
``` console
$ cargo run --example preempt
{{#include ../../../../ci/expected/preempt.run}}
{{#include ../../../../examples-runner/ci/expected/preempt.run}}
```
Заметьте, что задача `gpiob` *не* вытесняет задачу `gpioc`, потому что ее приоритет

View file

@ -80,5 +80,5 @@ $ cargo add panic-semihosting
``` console
$ # ПРИМЕЧАНИЕ: Я раскомментировал опцию `runner` в `.cargo/config`
$ cargo run
{{#include ../../../../ci/expected/init.run}}
{{#include ../../../../examples-runner/ci/expected/init.run}}
```

View file

@ -34,7 +34,7 @@
``` console
$ cargo run --example resource
{{#include ../../../../ci/expected/resource.run}}
{{#include ../../../../examples-runner/ci/expected/resource.run}}
```
К ресурсу `#[local]` нельзя получить доступ извне задачи к которой он
@ -76,7 +76,7 @@ $ cargo run --example resource
``` console
$ cargo run --example lock
{{#include ../../../../ci/expected/lock.run}}
{{#include ../../../../examples-runner/ci/expected/lock.run}}
```
## Множественное блокировка
@ -115,7 +115,7 @@ $ cargo run --example lock
``` console
$ cargo run --example only-shared-access
{{#include ../../../../ci/expected/only-shared-access.run}}
{{#include ../../../../examples-runner/ci/expected/only-shared-access.run}}
```
## Неблокируемый доступ к изменяемым ресурсам
@ -136,5 +136,5 @@ $ cargo run --example only-shared-access
``` console
$ cargo run --example lock-free
{{#include ../../../../ci/expected/lock-free.run}}
{{#include ../../../../examples-runner/ci/expected/lock-free.run}}
```

View file

@ -22,7 +22,7 @@ RTIC также поддерживает *программные* задачи,
``` console
$ cargo run --example task
{{#include ../../../../ci/expected/task.run}}
{{#include ../../../../examples-runner/ci/expected/task.run}}
```
## Передача сообщений
@ -39,7 +39,7 @@ $ cargo run --example task
``` console
$ cargo run --example message
{{#include ../../../../ci/expected/message.run}}
{{#include ../../../../examples-runner/ci/expected/message.run}}
```
## Вместимость
@ -63,7 +63,7 @@ RTIC *не* производит никакого рода аллокаций п
``` console
$ cargo run --example capacity
{{#include ../../../../ci/expected/capacity.run}}
{{#include ../../../../examples-runner/ci/expected/capacity.run}}
```
## Обработка ошибок

View file

@ -49,7 +49,7 @@
Запусе программы на реальном оборудовании создает следующий вывод в консоли:
``` text
{{#include ../../../../ci/expected/schedule.run}}
{{#include ../../../../examples-runner/ci/expected/schedule.run}}
```
Когда интерфейс `schedule` используется, среда исполнения использует внутри
@ -73,7 +73,7 @@
`Instant::now` вместо `scheduled` вызвало бы дрейф / колебания.
``` text
{{#include ../../../../ci/expected/periodic.run}}
{{#include ../../../../examples-runner/ci/expected/periodic.run}}
```
## Базовое время
@ -104,5 +104,5 @@
Запуск программы на реальном оборудовании приведет к следующему выводу в консоли:
``` text
{{#include ../../../../ci/expected/baseline.run}}
{{#include ../../../../examples-runner/ci/expected/baseline.run}}
```

View file

@ -22,7 +22,7 @@
``` console
$ cargo run --example generics
{{#include ../../../../ci/expected/generics.run}}
{{#include ../../../../examples-runner/ci/expected/generics.run}}
```
## Условная компиляция
@ -43,7 +43,7 @@ $ cargo run --example generics
$ cargo run --example cfg --release
$ cargo run --example cfg
{{#include ../../../../ci/expected/cfg.run}}
{{#include ../../../../examples-runner/ci/expected/cfg.run}}
```
## Запуск задач из ОЗУ
@ -75,7 +75,7 @@ RTIC v0.4.x была возможность взаимодействия с др
``` console
$ cargo run --example ramfunc
{{#include ../../../../ci/expected/ramfunc.run}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run}}
```
Можно посмотреть на вывод `cargo-nm`, чтобы убедиться, что `bar` расположен в ОЗУ
@ -83,12 +83,12 @@ $ cargo run --example ramfunc
``` console
$ cargo nm --example ramfunc --release | grep ' foo::'
{{#include ../../../../ci/expected/ramfunc.run.grep.foo}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.foo}}
```
``` console
$ cargo nm --example ramfunc --release | grep ' bar::'
{{#include ../../../../ci/expected/ramfunc.run.grep.bar}}
{{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.bar}}
```
## Обходной путь для быстрой передачи сообщений
@ -113,7 +113,7 @@ $ cargo nm --example ramfunc --release | grep ' bar::'
``` console
$ cargo run --example pool
{{#include ../../../../ci/expected/pool.run}}
{{#include ../../../../examples-runner/ci/expected/pool.run}}
```
## Инспектирование раскрываемого кода

View file

@ -1,4 +0,0 @@
foo Instant { ticks: 0 }
foo Instant { ticks: 100 }
foo Instant { ticks: 200 }
foo Instant { ticks: 300 }

View file

@ -1,7 +0,0 @@
foo Instant { ticks: 0 }
bar Instant { ticks: 10 }
foo Instant { ticks: 110 }
bar Instant { ticks: 120 }
foo Instant { ticks: 220 }
bar Instant { ticks: 230 }
foo Instant { ticks: 330 }

View file

@ -1,2 +0,0 @@
bar(0x20000088)
foo(0x2000010c)

View file

@ -0,0 +1,22 @@
[target.thumbv6m-none-eabi]
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.thumbv7m-none-eabi]
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = [
#"-C", "link-arg=-Tlink.x",
"-C", "link-arg=-Tdefmt.x",
"-C", "link-arg=--nmagic",
]
[build]
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
# target = "thumbv7m-none-eabi" # Cortex-M3
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
# target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
[alias]
rrb = "run --release --bin"
brb = "build --release --bin"

2
examples-runner/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target
Cargo.lock

View file

@ -0,0 +1,79 @@
[package]
# TODO(1) fix `authors` and `name` if you didn't use `cargo-generate`
authors = ["Emil Fresk <emil.fresk@gmail.com>"]
name = "examples-runner"
edition = "2018"
version = "0.1.0"
[dependencies]
defmt = { version = "0.3.0", optional = true }
defmt-rtt = { version = "0.3.0", optional = true }
panic-probe = { version = "0.3.0", optional = true }
cortex-m-rtic = { path = ".." }
cortex-m = "0.7"
systick-monotonic = "1"
fugit = { version = "0.3", features = ["defmt"] }
cortex-m-semihosting = { version = "0.3.7", optional = true }
panic-semihosting = { version = "0.5.6", optional = true }
heapless = "0.7"
rtic-monotonic = "1"
bare-metal = "1"
[dependencies.embedded-ci-pac]
version = "0.1.0"
git = "https://github.com/korken89/embedded-ci-pac.git"
[workspace]
members = [
"xtask",
]
[features]
embedded-ci = ["defmt", "defmt-rtt", "panic-probe/print-defmt"]
qemu = ["cortex-m-semihosting", "panic-semihosting/exit"]
# cargo build/run
[profile.dev]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = "s" # <-
overflow-checks = true # <-
# cargo test
[profile.test]
codegen-units = 1
debug = 2
debug-assertions = true # <-
incremental = false
opt-level = "s" # <-
overflow-checks = true # <-
# cargo build/run --release
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = "s" # <-
overflow-checks = false # <-
# cargo test --release
[profile.bench]
codegen-units = 1
debug = 2
debug-assertions = false # <-
incremental = false
lto = 'fat'
opt-level = "s" # <-
overflow-checks = false # <-
# uncomment this to switch from the crates.io version of defmt to its git version
# check app-template's README for instructions
# [patch.crates-io]
# defmt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" }
# defmt-rtt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" }
# defmt-test = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" }
# panic-probe = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version reported by `probe-run --version`" }

38
examples-runner/build.rs Normal file
View file

@ -0,0 +1,38 @@
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put the linker script somewhere the linker can find it
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
#[cfg(feature = "embedded-ci")]
let bytes = include_bytes!("embedded-ci.x");
#[cfg(feature = "qemu")]
let bytes = include_bytes!("qemu.x");
// If running in test mode, use the memory layout that can be flashed
// onto the chip directly
File::create(out.join("memory.x"))
.unwrap()
.write_all(bytes)
.unwrap();
#[cfg(feature = "qemu")]
File::create(out.join("defmt.x"))
.unwrap()
.write_all(b"")
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// Only re-run the build script when memory.x is changed,
// instead of when any part of the source code changes.
println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rerun-if-changed=embedded-ci.x");
println!("cargo:rerun-if-changed=qemu.x");
println!("cargo:rerun-if-changed=link.x");
println!("cargo:rerun-if-changed=build.rs");
}

View file

@ -0,0 +1,4 @@
foo ticks: 0
foo ticks: 100
foo ticks: 200
foo ticks: 300

View file

@ -0,0 +1,7 @@
foo ticks: 0
bar ticks: 10
foo ticks: 110
bar ticks: 120
foo ticks: 220
bar ticks: 230
foo ticks: 330

View file

@ -0,0 +1,2 @@
bar
foo

View file

@ -0,0 +1,10 @@
MEMORY
{
FLASH : ORIGIN = 0x20000000, LENGTH = 22K
RAM : ORIGIN = 0x20000000+22K, LENGTH = 10K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);

View file

@ -0,0 +1,9 @@
# Convert old examples to CI runner
cp ../examples/* ./src/bin/
sd "use panic_semihosting as _;" "use examples_runner as _;" src/bin/*
sd "lm3s6965" "examples_runner::pac" src/bin/*
sd "use cortex_m_semihosting::.*" "use examples_runner::{println, exit};" src/bin/*
sd "debug::exit.*" "exit();" src/bin/*
sd "hprintln" "println" src/bin/*
sd "\"\).unwrap\(\)" "\")" src/bin/*

13
examples-runner/qemu.x Normal file
View file

@ -0,0 +1,13 @@
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 32K
RAM : ORIGIN = 0x20000000, LENGTH = 32K
# RAM only runner
# FLASH : ORIGIN = 0x20000000, LENGTH = 22K
# RAM : ORIGIN = 0x20000000+22K, LENGTH = 10K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);

View file

@ -6,7 +6,7 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
/// Some big struct
pub struct BigStruct {
@ -20,11 +20,11 @@ impl BigStruct {
}
}
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use super::BigStruct;
use core::mem::MaybeUninit;
use cortex_m_semihosting::debug;
use examples_runner::exit;
#[shared]
struct Shared {
@ -42,8 +42,6 @@ mod app {
&mut *cx.local.bs.as_mut_ptr()
};
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
(
Shared {
// assign the reference so we can use the resource
@ -54,6 +52,11 @@ mod app {
)
}
#[idle]
fn idle(_: idle::Context) -> ! {
exit();
}
#[task(binds = UART0, shared = [big_struct])]
fn task(_: task::Context) {}
}

View file

@ -5,13 +5,13 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
// `examples/interrupt.rs` rewritten to use `binds`
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::{println, exit};
use examples_runner::pac::Interrupt;
#[shared]
struct Shared {}
@ -23,33 +23,28 @@ mod app {
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
println!("init");
(Shared {}, Local {}, init::Monotonics())
}
#[idle]
fn idle(_: idle::Context) -> ! {
hprintln!("idle").unwrap();
println!("idle");
rtic::pend(Interrupt::UART0);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
loop {
cortex_m::asm::nop();
}
exit();
}
#[task(binds = UART0, local = [times: u32 = 0])]
fn foo(cx: foo::Context) {
*cx.local.times += 1;
hprintln!(
println!(
"foo called {} time{}",
*cx.local.times,
if *cx.local.times > 1 { "s" } else { "" }
)
.unwrap();
);
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [SSI0])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
use systick_monotonic::*;
#[monotonic(binds = SysTick, default = true)]
@ -28,7 +28,7 @@ mod app {
// Initialize the monotonic (SysTick rate in QEMU is 12 MHz)
let mono = Systick::new(systick, 12_000_000);
hprintln!("init").ok();
println!("init");
// Schedule `foo` to run 1 second in the future
foo::spawn_after(1.secs()).unwrap();
@ -42,7 +42,7 @@ mod app {
#[task]
fn foo(_: foo::Context) {
hprintln!("foo").ok();
println!("foo");
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
let spawn_handle = baz::spawn_after(2.secs()).unwrap();
@ -51,7 +51,7 @@ mod app {
#[task]
fn bar(_: bar::Context, baz_handle: baz::SpawnHandle, do_reschedule: bool) {
hprintln!("bar").ok();
println!("bar");
if do_reschedule {
// Reschedule baz 2 seconds from now, instead of the original 1 second
@ -61,13 +61,13 @@ mod app {
} else {
// Or cancel it
baz_handle.cancel().unwrap();
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
}
#[task]
fn baz(_: baz::Context) {
hprintln!("baz").ok();
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
println!("baz");
exit();
}
}

View file

@ -5,12 +5,12 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [SSI0])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::{println, exit};
use examples_runner::pac::Interrupt;
#[shared]
struct Shared {}
@ -37,13 +37,13 @@ mod app {
#[task(capacity = 4)]
fn foo(_: foo::Context, x: u32) {
hprintln!("foo({})", x).unwrap();
println!("foo({})", x);
}
#[task]
fn bar(_: bar::Context) {
hprintln!("bar").unwrap();
println!("bar");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
}

View file

@ -5,13 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [SSI0, QEI0])]
mod app {
use cortex_m_semihosting::debug;
#[cfg(debug_assertions)]
use cortex_m_semihosting::hprintln;
use examples_runner::exit;
#[shared]
struct Shared {
@ -41,11 +39,11 @@ mod app {
#[idle]
fn idle(_: idle::Context) -> ! {
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
#[task(capacity = 2, shared = [count])]
@ -84,11 +82,10 @@ mod app {
#[cfg(debug_assertions)]
#[task(capacity = 2)]
fn log(_: log::Context, n: u32) {
hprintln!(
println!(
"foo has been called {} time{}",
n,
if n == 1 { "" } else { "s" }
)
.ok();
);
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [SSI0, QEI0])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
use systick_monotonic::*; // Implements the `Monotonic` trait
// A monotonic timer to enable scheduling in RTIC
@ -31,12 +31,7 @@ mod app {
}
#[init]
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
let systick = cx.core.SYST;
// Initialize the monotonic (SysTick rate in QEMU is 12 MHz)
let mono = Systick::new(systick, 12_000_000);
fn init(_cx: init::Context) -> (Shared, Local, init::Monotonics) {
// Spawn the task `foo` directly after `init` finishes
foo::spawn().unwrap();
@ -44,17 +39,17 @@ mod app {
// by the `#[monotonic(..)]` above
bar::spawn_after(1.secs()).unwrap();
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
(
// Initialization of shared resources
Shared { s1: 0, s2: 1 },
// Initialization of task local resources
Local { l1: 2, l2: 3 },
// Move the monotonic timer to the RTIC run-time, this enables
// scheduling
init::Monotonics(mono),
)
// (
// // Initialization of shared resources
// Shared { s1: 0, s2: 1 },
// // Initialization of task local resources
// Local { l1: 2, l2: 3 },
// // Move the monotonic timer to the RTIC run-time, this enables
// // scheduling
// init::Monotonics(mono),
// )
}
// Background task, runs whenever no other tasks are running
@ -73,7 +68,7 @@ mod app {
// This task is only spawned once in `init`, hence this task will run
// only once
hprintln!("foo").ok();
println!("foo");
}
// Software task, also not bound to a hardware interrupt
@ -81,7 +76,7 @@ mod app {
// The resources `s1` and `s2` are shared between all other tasks.
#[task(shared = [s1, s2], local = [l2])]
fn bar(_: bar::Context) {
hprintln!("bar").ok();
println!("bar");
// Run `bar` once per second
bar::spawn_after(1.secs()).unwrap();
@ -97,6 +92,6 @@ mod app {
// Note that RTIC does NOT clear the interrupt flag, this is up to the
// user
hprintln!("UART0 interrupt!").ok();
println!("UART0 interrupt!");
}
}

View file

@ -5,13 +5,13 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::pac::Interrupt;
use examples_runner::{exit, println};
#[shared]
struct Shared {
@ -25,7 +25,7 @@ mod app {
#[init]
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
hprintln!("init").unwrap();
println!("init");
(
Shared {
@ -40,37 +40,37 @@ mod app {
#[idle(shared = [s2, s3])]
fn idle(mut cx: idle::Context) -> ! {
hprintln!("idle p0 started").ok();
println!("idle p0 started");
rtic::pend(Interrupt::GPIOC);
cx.shared.s3.lock(|s| {
hprintln!("idle enter lock s3 {}", s).ok();
hprintln!("idle pend t0").ok();
println!("idle enter lock s3 {}", s);
println!("idle pend t0");
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 3
hprintln!("idle pend t1").ok();
println!("idle pend t1");
rtic::pend(Interrupt::GPIOB); // t1 p3, with shared ceiling 3
hprintln!("idle pend t2").ok();
println!("idle pend t2");
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
hprintln!("idle still in lock s3 {}", s).ok();
println!("idle still in lock s3 {}", s);
});
hprintln!("\nback in idle").ok();
println!("\nback in idle");
cx.shared.s2.lock(|s| {
hprintln!("enter lock s2 {}", s).ok();
hprintln!("idle pend t0").ok();
println!("enter lock s2 {}", s);
println!("idle pend t0");
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
hprintln!("idle pend t1").ok();
println!("idle pend t1");
rtic::pend(Interrupt::GPIOB); // t1 p3, no sharing
hprintln!("idle pend t2").ok();
println!("idle pend t2");
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
hprintln!("idle still in lock s2 {}", s).ok();
println!("idle still in lock s2 {}", s);
});
hprintln!("\nidle exit").ok();
println!("\nidle exit");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
#[task(binds = GPIOA, priority = 2, local = [times: u32 = 0], shared = [s2, s3])]
@ -78,13 +78,12 @@ mod app {
// Safe access to local `static mut` variable
*cx.local.times += 1;
hprintln!(
println!(
"t0 p2 called {} time{}",
*cx.local.times,
if *cx.local.times > 1 { "s" } else { "" }
)
.ok();
hprintln!("t0 p2 exit").ok();
);
println!("t0 p2 exit");
}
#[task(binds = GPIOB, priority = 3, local = [times: u32 = 0], shared = [s3, s4])]
@ -92,23 +91,22 @@ mod app {
// Safe access to local `static mut` variable
*cx.local.times += 1;
hprintln!(
println!(
"t1 p3 called {} time{}",
*cx.local.times,
if *cx.local.times > 1 { "s" } else { "" }
)
.ok();
);
cx.shared.s4.lock(|s| {
hprintln!("t1 enter lock s4 {}", s).ok();
hprintln!("t1 pend t0").ok();
println!("t1 enter lock s4 {}", s);
println!("t1 pend t0");
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
hprintln!("t1 pend t2").ok();
println!("t1 pend t2");
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
hprintln!("t1 still in lock s4 {}", s).ok();
println!("t1 still in lock s4 {}", s);
});
hprintln!("t1 p3 exit").ok();
println!("t1 p3 exit");
}
#[task(binds = GPIOC, priority = 4, local = [times: u32 = 0], shared = [s4])]
@ -116,17 +114,16 @@ mod app {
// Safe access to local `static mut` variable
*cx.local.times += 1;
hprintln!(
println!(
"t2 p4 called {} time{}",
*cx.local.times,
if *cx.local.times > 1 { "s" } else { "" }
)
.unwrap();
);
cx.shared.s4.lock(|s| {
hprintln!("enter lock s4 {}", s).ok();
println!("enter lock s4 {}", s);
*s += 1;
});
hprintln!("t3 p4 exit").ok();
println!("t3 p4 exit");
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [UART0])]
mod app {
use cortex_m_semihosting::debug;
use examples_runner::exit;
#[shared]
struct Shared {}
@ -22,9 +22,9 @@ mod app {
// Locals in `#[init]` have 'static lifetime
let _a: &'static mut u32 = cx.local.a;
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
(Shared {}, Local {}, init::Monotonics())
// (Shared {}, Local {}, init::Monotonics())
}
#[idle(local = [a: u32 = 0])]

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [UART0])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {
@ -31,8 +31,8 @@ mod app {
#[idle]
fn idle(_: idle::Context) -> ! {
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
loop {}
exit();
// loop {}
}
// Direct destructure
@ -42,7 +42,7 @@ mod app {
let b = cx.shared.b;
let c = cx.shared.c;
hprintln!("foo: a = {}, b = {}, c = {}", a, b, c).unwrap();
println!("foo: a = {}, b = {}, c = {}", a, b, c);
}
// De-structure-ing syntax
@ -50,6 +50,6 @@ mod app {
fn bar(cx: bar::Context) {
let bar::SharedResources { a, b, c } = cx.shared;
hprintln!("bar: a = {}, b = {}, c = {}", a, b, c).unwrap();
println!("bar: a = {}, b = {}, c = {}", a, b, c);
}
}

View file

@ -5,19 +5,19 @@
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use examples_runner as _;
use examples_runner::println;
// Free function implementing the interrupt bound task `foo`.
fn foo(_: app::foo::Context) {
hprintln!("foo called").ok();
println!("foo called");
}
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use crate::foo;
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::pac::Interrupt;
use examples_runner::{exit, println};
#[shared]
struct Shared {}
@ -29,22 +29,22 @@ mod app {
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap();
println!("init");
(Shared {}, Local {}, init::Monotonics())
}
#[idle]
fn idle(_: idle::Context) -> ! {
hprintln!("idle").unwrap();
println!("idle");
rtic::pend(Interrupt::UART0);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
extern "Rust" {

View file

@ -5,19 +5,19 @@
#![no_main]
#![no_std]
use cortex_m_semihosting::{debug, hprintln};
use panic_semihosting as _;
use examples_runner::{println, exit};
use examples_runner as _;
// Free function implementing the spawnable task `foo`.
fn foo(_c: app::foo::Context, x: i32, y: u32) {
hprintln!("foo {}, {}", x, y).unwrap();
println!("foo {}, {}", x, y);
if x == 2 {
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
app::foo::spawn(2, 3).unwrap();
}
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
#[rtic::app(device = examples_runner::pac, dispatchers = [SSI0])]
mod app {
use crate::foo;

View file

@ -5,14 +5,14 @@
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use examples_runner as _;
use examples_runner::println;
use rtic::Mutex;
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::pac::Interrupt;
use examples_runner::{exit, println};
#[shared]
struct Shared {
@ -32,19 +32,19 @@ mod app {
#[task(binds = UART0, shared = [shared], local = [state: u32 = 0])]
fn uart0(c: uart0::Context) {
hprintln!("UART0(STATE = {})", *c.local.state).unwrap();
println!("UART0(STATE = {})", *c.local.state);
// second argument has type `shared::shared`
super::advance(c.local.state, c.shared.shared);
rtic::pend(Interrupt::UART1);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
#[task(binds = UART1, priority = 2, shared = [shared], local = [state: u32 = 0])]
fn uart1(c: uart1::Context) {
hprintln!("UART1(STATE = {})", *c.local.state).unwrap();
println!("UART1(STATE = {})", *c.local.state);
// second argument has type `shared::shared`
super::advance(c.local.state, c.shared.shared);
@ -61,5 +61,5 @@ fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
(old, *shared)
});
hprintln!("shared: {} -> {}", old, new).unwrap();
println!("shared: {} -> {}", old, new);
}

View file

@ -5,12 +5,12 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use examples_runner::pac::Interrupt;
use examples_runner::{exit, println};
#[shared]
struct Shared {}
@ -24,7 +24,7 @@ mod app {
// `init` returns because interrupts are disabled
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
hprintln!("init").unwrap();
println!("init");
(Shared {}, Local {}, init::Monotonics())
}
@ -33,15 +33,15 @@ mod app {
fn idle(_: idle::Context) -> ! {
// interrupts are enabled again; the `UART0` handler runs at this point
hprintln!("idle").unwrap();
println!("idle");
rtic::pend(Interrupt::UART0);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
#[task(binds = UART0, local = [times: u32 = 0])]
@ -49,11 +49,10 @@ mod app {
// Safe access to local `static mut` variable
*cx.local.times += 1;
hprintln!(
println!(
"UART0 called {} time{}",
*cx.local.times,
if *cx.local.times > 1 { "s" } else { "" }
)
.unwrap();
);
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {}
@ -19,7 +19,7 @@ mod app {
#[init]
fn init(mut cx: init::Context) -> (Shared, Local, init::Monotonics) {
hprintln!("init").unwrap();
println!("init");
// Set the ARM SLEEPONEXIT bit to go to sleep after handling interrupts
// See https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
@ -33,15 +33,15 @@ mod app {
// Locals in idle have lifetime 'static
let _x: &'static mut u32 = cx.local.x;
hprintln!("idle").unwrap();
println!("idle");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
// Now Wait For Interrupt is used instead of a busy-wait loop
// to allow MCU to sleep between interrupts
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/WFI
rtic::export::wfi()
}
// loop {
// // Now Wait For Interrupt is used instead of a busy-wait loop
// // to allow MCU to sleep between interrupts
// // https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/WFI
// rtic::export::wfi()
// }
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965)]
#[rtic::app(device = examples_runner::pac)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {}
@ -19,7 +19,7 @@ mod app {
#[init]
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
hprintln!("init").unwrap();
println!("init");
(Shared {}, Local {}, init::Monotonics())
}
@ -29,12 +29,12 @@ mod app {
// Locals in idle have lifetime 'static
let _x: &'static mut u32 = cx.local.x;
hprintln!("idle").unwrap();
println!("idle");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, peripherals = true)]
#[rtic::app(device = examples_runner::pac, peripherals = true)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {}
@ -23,7 +23,7 @@ mod app {
let _core: cortex_m::Peripherals = cx.core;
// Device specific peripherals
let _device: lm3s6965::Peripherals = cx.device;
let _device: examples_runner::pac::Peripherals = cx.device;
// Locals in `init` have 'static lifetime
let _x: &'static mut u32 = cx.local.x;
@ -32,10 +32,10 @@ mod app {
// to indicate that this is a critical seciton
let _cs_token: bare_metal::CriticalSection = cx.cs;
hprintln!("init").unwrap();
println!("init");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
(Shared {}, Local {}, init::Monotonics())
// (Shared {}, Local {}, init::Monotonics())
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
#[rtic::app(device = examples_runner::pac, dispatchers = [UART0, UART1])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {}
@ -45,9 +45,9 @@ mod app {
let local_to_idle = cx.local.local_to_idle;
*local_to_idle += 1;
hprintln!("idle: local_to_idle = {}", local_to_idle).unwrap();
println!("idle: local_to_idle = {}", local_to_idle);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
// error: no `local_to_foo` field in `idle::LocalResources`
// _cx.local.local_to_foo += 1;
@ -55,9 +55,9 @@ mod app {
// error: no `local_to_bar` field in `idle::LocalResources`
// _cx.local.local_to_bar += 1;
loop {
cortex_m::asm::nop();
}
// loop {
// cortex_m::asm::nop();
// }
}
// `local_to_foo` can only be accessed from this context
@ -69,7 +69,7 @@ mod app {
// error: no `local_to_bar` field in `foo::LocalResources`
// cx.local.local_to_bar += 1;
hprintln!("foo: local_to_foo = {}", local_to_foo).unwrap();
println!("foo: local_to_foo = {}", local_to_foo);
}
// `local_to_bar` can only be accessed from this context
@ -81,6 +81,6 @@ mod app {
// error: no `local_to_foo` field in `bar::LocalResources`
// cx.local.local_to_foo += 1;
hprintln!("bar: local_to_bar = {}", local_to_bar).unwrap();
println!("bar: local_to_bar = {}", local_to_bar);
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA])]
#[rtic::app(device = examples_runner::pac, dispatchers = [GPIOA])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {
@ -33,7 +33,7 @@ mod app {
*c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter;
hprintln!(" foo = {}", counter).unwrap();
println!(" foo = {}", counter);
}
#[task(shared = [counter])] // <- same priority
@ -42,8 +42,8 @@ mod app {
*c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter;
hprintln!(" bar = {}", counter).unwrap();
println!(" bar = {}", counter);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
}

View file

@ -5,11 +5,11 @@
#![no_main]
#![no_std]
use panic_semihosting as _;
use examples_runner as _;
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA, GPIOB, GPIOC])]
#[rtic::app(device = examples_runner::pac, dispatchers = [GPIOA, GPIOB, GPIOC])]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use examples_runner::{println, exit};
#[shared]
struct Shared {
@ -29,7 +29,7 @@ mod app {
// when omitted priority is assumed to be `1`
#[task(shared = [shared])]
fn foo(mut c: foo::Context) {
hprintln!("A").unwrap();
println!("A");
// the lower priority task requires a critical section to access the data
c.shared.shared.lock(|shared| {
@ -39,7 +39,7 @@ mod app {
// bar will *not* run right now due to the critical section
bar::spawn().unwrap();
hprintln!("B - shared = {}", *shared).unwrap();
println!("B - shared = {}", *shared);
// baz does not contend for `shared` so it's allowed to run now
baz::spawn().unwrap();
@ -47,9 +47,9 @@ mod app {
// critical section is over: bar can now start
hprintln!("E").unwrap();
println!("E");
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
exit();
}
#[task(priority = 2, shared = [shared])]
@ -61,11 +61,11 @@ mod app {
*shared
});
hprintln!("D - shared = {}", shared).unwrap();
println!("D - shared = {}", shared);
}
#[task(priority = 3)]
fn baz(_: baz::Context) {
hprintln!("C").unwrap();
println!("C");
}
}

Some files were not shown because too many files have changed in this diff Show more