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 }} args: --examples --target=${{ matrix.target }}
# Verify the example output with run-pass tests # Verify the example output with run-pass tests
testexamples: testexamplesqemu:
name: testexamples name: testexamplesqemu
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
@ -157,13 +157,6 @@ jobs:
override: true override: true
components: llvm-tools-preview 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 - name: Cache Dependencies
uses: Swatinem/rust-cache@v1 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 run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs macros/src/lib.rs
- name: Run-pass tests - name: Run-pass tests
run: run: |
cargo xtask --target ${{ matrix.target }} 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 # Check the correctness of macros/ crate
checkmacros: checkmacros:
@ -373,7 +407,8 @@ jobs:
- check - check
- clippy - clippy
- checkexamples - checkexamples
- testexamples - testexamplesqemu
- testexamplesembeddedci
- checkmacros - checkmacros
- testmacros - testmacros
- tests - tests
@ -555,7 +590,8 @@ jobs:
- check - check
- clippy - clippy
- checkexamples - checkexamples
- testexamples - testexamplesqemu
- testexamplesembeddedci
- checkmacros - checkmacros
- testmacros - testmacros
- tests - tests

View file

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

View file

@ -49,7 +49,9 @@ lto = true
[workspace] [workspace]
members = [ members = [
"macros", "macros",
"xtask", ]
exclude = [
"examples-runner",
] ]
# do not optimize proc-macro deps or build scripts # 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: Yields this output:
``` console ``` 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. In the following sections we will go through each feature in detail.
``` rust ``` 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`. The example below shows that `idle` runs after `init`.
``` rust ``` rust
{{#include ../../../../examples/idle.rs}} {{#include ../../../../examples-runner/src/bin/idle.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example idle $ 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. 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 [NOP]: https://developer.arm.com/documentation/dui0662/b/The-Cortex-M0--Instruction-Set/Miscellaneous-instructions/NOP
``` rust ``` rust
{{#include ../../../../examples/idle-wfi.rs}} {{#include ../../../../examples-runner/src/bin/idle-wfi.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example idle-wfi $ 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`. In the rare case you want to implement an ultra-slim application you can explicitly set `peripherals` to `false`.
``` rust ``` 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. Running the example will print `init` to the console and then exit the QEMU process.
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example init $ 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 > **NOTE**: You can choose target device by passing a target

View file

@ -3,5 +3,5 @@
This is the smallest possible RTIC application: This is the smallest possible RTIC application:
``` rust ``` 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: The following example showcases the priority based scheduling of tasks:
``` rust ``` rust
{{#include ../../../../examples/preempt.rs}} {{#include ../../../../examples-runner/src/bin/preempt.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example preempt $ 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 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. hardware task bound to an interrupt handler.
``` rust ``` rust
{{#include ../../../../examples/hardware.rs}} {{#include ../../../../examples-runner/src/bin/hardware.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example hardware $ 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: The number of arguments to a task is not limited:
``` rust ``` rust
{{#include ../../../../examples/message_passing.rs}} {{#include ../../../../examples-runner/src/bin/message_passing.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example message_passing $ 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: See the following example:
``` rust ``` rust
{{#include ../../../../examples/schedule.rs}} {{#include ../../../../examples-runner/src/bin/schedule.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example schedule $ 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 ## 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: too late and that the task is already sent for execution. The following example shows this in action:
``` rust ``` rust
{{#include ../../../../examples/cancel-reschedule.rs}} {{#include ../../../../examples-runner/src/bin/cancel-reschedule.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example cancel-reschedule $ 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. `#[local]` resource, plus that the `idle` task has its own `#[local]` as well.
``` rust ``` rust
{{#include ../../../../examples/locals.rs}} {{#include ../../../../examples-runner/src/bin/locals.rs}}
``` ```
Running the example: Running the example:
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example locals $ cargo run --target thumbv7m-none-eabi --example locals
{{#include ../../../../ci/expected/locals.run}} {{#include ../../../../examples-runner/ci/expected/locals.run}}
``` ```
### Task local initialized resources ### 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: In the example below the different uses and lifetimes are shown:
``` rust ``` rust
{{#include ../../../../examples/declared_locals.rs}} {{#include ../../../../examples-runner/src/bin/declared_locals.rs}}
``` ```
<!-- ``` console <!-- ``` console
$ cargo run --target thumbv7m-none-eabi --example declared_locals $ 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` ## `#[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. resource, is free to preempt the critical section created by the lowest priority handler.
``` rust ``` rust
{{#include ../../../../examples/lock.rs}} {{#include ../../../../examples-runner/src/bin/lock.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example lock $ 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`]. 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: following examples show this in use:
``` rust ``` rust
{{#include ../../../../examples/multilock.rs}} {{#include ../../../../examples-runner/src/bin/multilock.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example multilock $ cargo run --target thumbv7m-none-eabi --example multilock
{{#include ../../../../ci/expected/multilock.run}} {{#include ../../../../examples-runner/ci/expected/multilock.run}}
``` ```
## Only shared (`&-`) access ## 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. used from two tasks that run at different priorities without any kind of lock.
``` rust ``` rust
{{#include ../../../../examples/only-shared-access.rs}} {{#include ../../../../examples-runner/src/bin/only-shared-access.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example only-shared-access $ 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 ## 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. API would be a data race in that case.
``` rust ``` rust
{{#include ../../../../examples/lock-free.rs}} {{#include ../../../../examples-runner/src/bin/lock-free.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example lock-free $ 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: See the following example:
``` rust ``` rust
{{#include ../../../../examples/spawn.rs}} {{#include ../../../../examples-runner/src/bin/spawn.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example spawn $ 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: Here are two examples on how to split up the resource struct:
``` rust ``` rust
{{#include ../../../../examples/destructure.rs}} {{#include ../../../../examples-runner/src/bin/destructure.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example destructure $ 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. The example below shows how to place the higher priority task, `bar`, in RAM.
``` rust ``` rust
{{#include ../../../../examples/ramfunc.rs}} {{#include ../../../../examples-runner/src/bin/ramfunc.rs}}
``` ```
Running this program produces the expected output. Running this program produces the expected output.
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example ramfunc $ 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 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 ``` console
$ cargo nm --example ramfunc --release | grep ' foo::' $ cargo nm --example ramfunc --release | grep ' foo::'
{{#include ../../../../ci/expected/ramfunc.run.grep.foo}} {{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.foo}}
``` ```
``` console ``` console
$ cargo nm --example ramfunc --release | grep ' bar::' $ 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. Here's an example where `heapless::Pool` is used to "box" buffers of 128 bytes.
``` rust ``` rust
{{#include ../../../../examples/pool.rs}} {{#include ../../../../examples-runner/src/bin/pool.rs}}
``` ```
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example pool $ 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 [`heapless::spsc::Queue`]: https://docs.rs/heapless/0.7.5/heapless/spsc/struct.Queue.html
``` rust ``` rust
{{#include ../../../../examples/static.rs}} {{#include ../../../../examples-runner/src/bin/static.rs}}
``` ```
Running this program produces the expected output. Running this program produces the expected output.
``` console ``` console
$ cargo run --target thumbv7m-none-eabi --example static $ 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 ``` console
$ cargo run --example init $ cargo run --example init
{{#include ../../../../ci/expected/init.run}} {{#include ../../../../examples-runner/ci/expected/init.run}}
``` ```
> **ПРИМЕЧАНИЕ**: Не забывайте указывать выбранное вами целевое устройство, передавая параметр target > **ПРИМЕЧАНИЕ**: Не забывайте указывать выбранное вами целевое устройство, передавая параметр target
@ -87,7 +87,7 @@ $ cargo run --example init
``` console ``` console
$ cargo run --example idle $ cargo run --example idle
{{#include ../../../../ci/expected/idle.run}} {{#include ../../../../examples-runner/ci/expected/idle.run}}
``` ```
## Аппаратные задачи ## Аппаратные задачи
@ -109,7 +109,7 @@ mut` переменные безопасны для использования
``` console ``` console
$ cargo run --example hardware $ cargo run --example hardware
{{#include ../../../../ci/expected/hardware.run}} {{#include ../../../../examples-runner/ci/expected/hardware.run}}
``` ```
До сих пор все программы на RTIC, которые мы видели, не отличались от программ, До сих пор все программы на RTIC, которые мы видели, не отличались от программ,
@ -145,7 +145,7 @@ $ cargo run --example hardware
``` console ``` console
$ cargo run --example preempt $ cargo run --example preempt
{{#include ../../../../ci/expected/preempt.run}} {{#include ../../../../examples-runner/ci/expected/preempt.run}}
``` ```
Заметьте, что задача `gpiob` *не* вытесняет задачу `gpioc`, потому что ее приоритет Заметьте, что задача `gpiob` *не* вытесняет задачу `gpioc`, потому что ее приоритет

View file

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

View file

@ -34,7 +34,7 @@
``` console ``` console
$ cargo run --example resource $ cargo run --example resource
{{#include ../../../../ci/expected/resource.run}} {{#include ../../../../examples-runner/ci/expected/resource.run}}
``` ```
К ресурсу `#[local]` нельзя получить доступ извне задачи к которой он К ресурсу `#[local]` нельзя получить доступ извне задачи к которой он
@ -76,7 +76,7 @@ $ cargo run --example resource
``` console ``` console
$ cargo run --example lock $ 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 ``` console
$ cargo run --example only-shared-access $ 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 ``` console
$ cargo run --example lock-free $ 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 ``` console
$ cargo run --example task $ 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 ``` console
$ cargo run --example message $ cargo run --example message
{{#include ../../../../ci/expected/message.run}} {{#include ../../../../examples-runner/ci/expected/message.run}}
``` ```
## Вместимость ## Вместимость
@ -63,7 +63,7 @@ RTIC *не* производит никакого рода аллокаций п
``` console ``` console
$ cargo run --example capacity $ cargo run --example capacity
{{#include ../../../../ci/expected/capacity.run}} {{#include ../../../../examples-runner/ci/expected/capacity.run}}
``` ```
## Обработка ошибок ## Обработка ошибок

View file

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

View file

@ -22,7 +22,7 @@
``` console ``` console
$ cargo run --example generics $ 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 --release
$ cargo run --example cfg $ 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 ``` console
$ cargo run --example ramfunc $ cargo run --example ramfunc
{{#include ../../../../ci/expected/ramfunc.run}} {{#include ../../../../examples-runner/ci/expected/ramfunc.run}}
``` ```
Можно посмотреть на вывод `cargo-nm`, чтобы убедиться, что `bar` расположен в ОЗУ Можно посмотреть на вывод `cargo-nm`, чтобы убедиться, что `bar` расположен в ОЗУ
@ -83,12 +83,12 @@ $ cargo run --example ramfunc
``` console ``` console
$ cargo nm --example ramfunc --release | grep ' foo::' $ cargo nm --example ramfunc --release | grep ' foo::'
{{#include ../../../../ci/expected/ramfunc.run.grep.foo}} {{#include ../../../../examples-runner/ci/expected/ramfunc.run.grep.foo}}
``` ```
``` console ``` console
$ cargo nm --example ramfunc --release | grep ' bar::' $ 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 ``` console
$ cargo run --example pool $ 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_main]
#![no_std] #![no_std]
use panic_semihosting as _; use examples_runner as _;
/// Some big struct /// Some big struct
pub struct BigStruct { pub struct BigStruct {
@ -20,11 +20,11 @@ impl BigStruct {
} }
} }
#[rtic::app(device = lm3s6965)] #[rtic::app(device = examples_runner::pac)]
mod app { mod app {
use super::BigStruct; use super::BigStruct;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use cortex_m_semihosting::debug; use examples_runner::exit;
#[shared] #[shared]
struct Shared { struct Shared {
@ -42,8 +42,6 @@ mod app {
&mut *cx.local.bs.as_mut_ptr() &mut *cx.local.bs.as_mut_ptr()
}; };
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
( (
Shared { Shared {
// assign the reference so we can use the resource // 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])] #[task(binds = UART0, shared = [big_struct])]
fn task(_: task::Context) {} fn task(_: task::Context) {}
} }

View file

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

View file

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

View file

@ -5,12 +5,12 @@
#![no_main] #![no_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
use lm3s6965::Interrupt; use examples_runner::pac::Interrupt;
#[shared] #[shared]
struct Shared {} struct Shared {}
@ -37,13 +37,13 @@ mod app {
#[task(capacity = 4)] #[task(capacity = 4)]
fn foo(_: foo::Context, x: u32) { fn foo(_: foo::Context, x: u32) {
hprintln!("foo({})", x).unwrap(); println!("foo({})", x);
} }
#[task] #[task]
fn bar(_: bar::Context) { 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_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::debug; use examples_runner::exit;
#[cfg(debug_assertions)]
use cortex_m_semihosting::hprintln;
#[shared] #[shared]
struct Shared { struct Shared {
@ -41,11 +39,11 @@ mod app {
#[idle] #[idle]
fn idle(_: idle::Context) -> ! { fn idle(_: idle::Context) -> ! {
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator exit();
loop { // loop {
cortex_m::asm::nop(); // cortex_m::asm::nop();
} // }
} }
#[task(capacity = 2, shared = [count])] #[task(capacity = 2, shared = [count])]
@ -84,11 +82,10 @@ mod app {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
#[task(capacity = 2)] #[task(capacity = 2)]
fn log(_: log::Context, n: u32) { fn log(_: log::Context, n: u32) {
hprintln!( println!(
"foo has been called {} time{}", "foo has been called {} time{}",
n, n,
if n == 1 { "" } else { "s" } if n == 1 { "" } else { "s" }
) );
.ok();
} }
} }

View file

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

View file

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

View file

@ -5,11 +5,11 @@
#![no_main] #![no_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::debug; use examples_runner::exit;
#[shared] #[shared]
struct Shared {} struct Shared {}
@ -22,9 +22,9 @@ mod app {
// Locals in `#[init]` have 'static lifetime // Locals in `#[init]` have 'static lifetime
let _a: &'static mut u32 = cx.local.a; 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])] #[idle(local = [a: u32 = 0])]

View file

@ -5,11 +5,11 @@
#![no_main] #![no_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
#[shared] #[shared]
struct Shared { struct Shared {
@ -31,8 +31,8 @@ mod app {
#[idle] #[idle]
fn idle(_: idle::Context) -> ! { fn idle(_: idle::Context) -> ! {
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator exit();
loop {} // loop {}
} }
// Direct destructure // Direct destructure
@ -42,7 +42,7 @@ mod app {
let b = cx.shared.b; let b = cx.shared.b;
let c = cx.shared.c; 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 // De-structure-ing syntax
@ -50,6 +50,6 @@ mod app {
fn bar(cx: bar::Context) { fn bar(cx: bar::Context) {
let bar::SharedResources { a, b, c } = cx.shared; 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_main]
#![no_std] #![no_std]
use cortex_m_semihosting::hprintln; use examples_runner as _;
use panic_semihosting as _; use examples_runner::println;
// Free function implementing the interrupt bound task `foo`. // Free function implementing the interrupt bound task `foo`.
fn foo(_: app::foo::Context) { fn foo(_: app::foo::Context) {
hprintln!("foo called").ok(); println!("foo called");
} }
#[rtic::app(device = lm3s6965)] #[rtic::app(device = examples_runner::pac)]
mod app { mod app {
use crate::foo; use crate::foo;
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::pac::Interrupt;
use lm3s6965::Interrupt; use examples_runner::{exit, println};
#[shared] #[shared]
struct Shared {} struct Shared {}
@ -29,22 +29,22 @@ mod app {
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(Interrupt::UART0); rtic::pend(Interrupt::UART0);
hprintln!("init").unwrap(); println!("init");
(Shared {}, Local {}, init::Monotonics()) (Shared {}, Local {}, init::Monotonics())
} }
#[idle] #[idle]
fn idle(_: idle::Context) -> ! { fn idle(_: idle::Context) -> ! {
hprintln!("idle").unwrap(); println!("idle");
rtic::pend(Interrupt::UART0); rtic::pend(Interrupt::UART0);
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator exit();
loop { // loop {
cortex_m::asm::nop(); // cortex_m::asm::nop();
} // }
} }
extern "Rust" { extern "Rust" {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,11 +5,11 @@
#![no_main] #![no_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
#[shared] #[shared]
struct Shared {} struct Shared {}
@ -23,7 +23,7 @@ mod app {
let _core: cortex_m::Peripherals = cx.core; let _core: cortex_m::Peripherals = cx.core;
// Device specific peripherals // Device specific peripherals
let _device: lm3s6965::Peripherals = cx.device; let _device: examples_runner::pac::Peripherals = cx.device;
// Locals in `init` have 'static lifetime // Locals in `init` have 'static lifetime
let _x: &'static mut u32 = cx.local.x; let _x: &'static mut u32 = cx.local.x;
@ -32,10 +32,10 @@ mod app {
// to indicate that this is a critical seciton // to indicate that this is a critical seciton
let _cs_token: bare_metal::CriticalSection = cx.cs; 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_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
#[shared] #[shared]
struct Shared {} struct Shared {}
@ -45,9 +45,9 @@ mod app {
let local_to_idle = cx.local.local_to_idle; let local_to_idle = cx.local.local_to_idle;
*local_to_idle += 1; *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` // error: no `local_to_foo` field in `idle::LocalResources`
// _cx.local.local_to_foo += 1; // _cx.local.local_to_foo += 1;
@ -55,9 +55,9 @@ mod app {
// error: no `local_to_bar` field in `idle::LocalResources` // error: no `local_to_bar` field in `idle::LocalResources`
// _cx.local.local_to_bar += 1; // _cx.local.local_to_bar += 1;
loop { // loop {
cortex_m::asm::nop(); // cortex_m::asm::nop();
} // }
} }
// `local_to_foo` can only be accessed from this context // `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` // error: no `local_to_bar` field in `foo::LocalResources`
// cx.local.local_to_bar += 1; // 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 // `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` // error: no `local_to_foo` field in `bar::LocalResources`
// cx.local.local_to_foo += 1; // 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_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
#[shared] #[shared]
struct Shared { struct Shared {
@ -33,7 +33,7 @@ mod app {
*c.shared.counter += 1; // <- no lock API required *c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter; let counter = *c.shared.counter;
hprintln!(" foo = {}", counter).unwrap(); println!(" foo = {}", counter);
} }
#[task(shared = [counter])] // <- same priority #[task(shared = [counter])] // <- same priority
@ -42,8 +42,8 @@ mod app {
*c.shared.counter += 1; // <- no lock API required *c.shared.counter += 1; // <- no lock API required
let counter = *c.shared.counter; 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_main]
#![no_std] #![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 { mod app {
use cortex_m_semihosting::{debug, hprintln}; use examples_runner::{println, exit};
#[shared] #[shared]
struct Shared { struct Shared {
@ -29,7 +29,7 @@ mod app {
// when omitted priority is assumed to be `1` // when omitted priority is assumed to be `1`
#[task(shared = [shared])] #[task(shared = [shared])]
fn foo(mut c: foo::Context) { fn foo(mut c: foo::Context) {
hprintln!("A").unwrap(); println!("A");
// the lower priority task requires a critical section to access the data // the lower priority task requires a critical section to access the data
c.shared.shared.lock(|shared| { c.shared.shared.lock(|shared| {
@ -39,7 +39,7 @@ mod app {
// bar will *not* run right now due to the critical section // bar will *not* run right now due to the critical section
bar::spawn().unwrap(); 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 does not contend for `shared` so it's allowed to run now
baz::spawn().unwrap(); baz::spawn().unwrap();
@ -47,9 +47,9 @@ mod app {
// critical section is over: bar can now start // 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])] #[task(priority = 2, shared = [shared])]
@ -61,11 +61,11 @@ mod app {
*shared *shared
}); });
hprintln!("D - shared = {}", shared).unwrap(); println!("D - shared = {}", shared);
} }
#[task(priority = 3)] #[task(priority = 3)]
fn baz(_: baz::Context) { 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