mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-24 19:09:33 +01:00
commit
6e233bec02
129 changed files with 454 additions and 454 deletions
58
CHANGELOG.md
58
CHANGELOG.md
|
@ -34,12 +34,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
- [breaking-change][] [RFC 155] "explicit `Context` parameter" has been
|
- [breaking-change][] [RFC 155] "explicit `Context` parameter" has been
|
||||||
implemented.
|
implemented.
|
||||||
|
|
||||||
[RFC 155]: https://github.com/rtfm-rs/cortex-m-rtfm/issues/155
|
[RFC 155]: https://github.com/rtic-rs/cortex-m-rtic/issues/155
|
||||||
|
|
||||||
- [breaking-change][] [RFC 147] "all functions must be safe" has been
|
- [breaking-change][] [RFC 147] "all functions must be safe" has been
|
||||||
implemented.
|
implemented.
|
||||||
|
|
||||||
[RFC 147]: https://github.com/rtfm-rs/cortex-m-rtfm/issues/147
|
[RFC 147]: https://github.com/rtic-rs/cortex-m-rtic/issues/147
|
||||||
|
|
||||||
- All the queues internally used by the framework now use `AtomicU8` indices
|
- All the queues internally used by the framework now use `AtomicU8` indices
|
||||||
instead of `AtomicUsize`; this reduces the static memory used by the
|
instead of `AtomicUsize`; this reduces the static memory used by the
|
||||||
|
@ -57,7 +57,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
- [breaking-change][] when the `schedule` API is used the type of
|
- [breaking-change][] when the `schedule` API is used the type of
|
||||||
`init::Context.core` changes from `cortex_m::Peripherals` to
|
`init::Context.core` changes from `cortex_m::Peripherals` to
|
||||||
`rtfm::Peripherals`. The fields of `rtfm::Peripherals` do not change when
|
`rtic::Peripherals`. The fields of `rtic::Peripherals` do not change when
|
||||||
Cargo features are enabled.
|
Cargo features are enabled.
|
||||||
|
|
||||||
- [breaking-change][] the monotonic timer used to implement the `schedule` API
|
- [breaking-change][] the monotonic timer used to implement the `schedule` API
|
||||||
|
@ -85,7 +85,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
syntax. `init::LateResources` is the only method to initialize late resources.
|
syntax. `init::LateResources` is the only method to initialize late resources.
|
||||||
See [PR #140] for more details.
|
See [PR #140] for more details.
|
||||||
|
|
||||||
[PR #140]: https://github.com/rtfm-rs/cortex-m-rtfm/pull/140
|
[PR #140]: https://github.com/rtic-rs/cortex-m-rtic/pull/140
|
||||||
|
|
||||||
## [v0.4.3] - 2019-04-21
|
## [v0.4.3] - 2019-04-21
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
`binds` argument that lets you give the handler an arbitrary name. For
|
`binds` argument that lets you give the handler an arbitrary name. For
|
||||||
example:
|
example:
|
||||||
|
|
||||||
[RFC 128]: https://github.com/rtfm-rs/cortex-m-rtfm/issues/128
|
[RFC 128]: https://github.com/rtic-rs/cortex-m-rtic/issues/128
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
// on v0.4.1 you had to write
|
// on v0.4.1 you had to write
|
||||||
|
@ -146,8 +146,8 @@ fn on_new_frame() { .. }
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- The RTFM book has been translated to Russian. You can find the translation
|
- The RTIC book has been translated to Russian. You can find the translation
|
||||||
online at https://japaric.github.io/cortex-m-rtfm/book/ru/
|
online at https://japaric.github.io/cortex-m-rtic/book/ru/
|
||||||
|
|
||||||
- `Duration` now implements the `Default` trait.
|
- `Duration` now implements the `Default` trait.
|
||||||
|
|
||||||
|
@ -187,11 +187,11 @@ Yanked due to a soundness issue in `init`; the issue has been mostly fixed in v0
|
||||||
`Resource.claim_mut` has been renamed to `Mutex.lock` and its signature has
|
`Resource.claim_mut` has been renamed to `Mutex.lock` and its signature has
|
||||||
changed (no `Threshold` token is required).
|
changed (no `Threshold` token is required).
|
||||||
|
|
||||||
- [breaking-change] The name of the library has changed to `rtfm`. The package
|
- [breaking-change] The name of the library has changed to `rtic`. The package
|
||||||
name is still `cortex-m-rtfm`.
|
name is still `cortex-m-rtic`.
|
||||||
|
|
||||||
- [breaking-change] `cortex_m_rtfm::set_pending` has been renamed to
|
- [breaking-change] `cortex_m_rtic::set_pending` has been renamed to
|
||||||
`rtfm::pend`.
|
`rtic::pend`.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ Yanked due to a soundness issue in `init`; the issue has been mostly fixed in v0
|
||||||
|
|
||||||
- [breaking-change] The `bkpt` and `wfi` re-exports have been removed.
|
- [breaking-change] The `bkpt` and `wfi` re-exports have been removed.
|
||||||
|
|
||||||
- [breaking-change] `rtfm::atomic` has been removed.
|
- [breaking-change] `rtic::atomic` has been removed.
|
||||||
|
|
||||||
## [v0.3.4] - 2018-08-27
|
## [v0.3.4] - 2018-08-27
|
||||||
|
|
||||||
|
@ -313,20 +313,20 @@ Yanked due to a soundness issue in `init`; the issue has been mostly fixed in v0
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
||||||
[Unreleased]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.5.2...HEAD
|
[Unreleased]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.5.2...HEAD
|
||||||
[v0.5.2]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.5.1...v0.5.2
|
[v0.5.2]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.5.1...v0.5.2
|
||||||
[v0.5.1]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.5.0...v0.5.1
|
[v0.5.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.5.0...v0.5.1
|
||||||
[v0.5.0]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.4.3...v0.5.0
|
[v0.5.0]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.4.3...v0.5.0
|
||||||
[v0.4.3]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.4.2...v0.4.3
|
[v0.4.3]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.4.2...v0.4.3
|
||||||
[v0.4.2]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.4.1...v0.4.2
|
[v0.4.2]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.4.1...v0.4.2
|
||||||
[v0.4.1]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.4.0...v0.4.1
|
[v0.4.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.4.0...v0.4.1
|
||||||
[v0.4.0]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.3.4...v0.4.0
|
[v0.4.0]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.3.4...v0.4.0
|
||||||
[v0.3.4]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.3.3...v0.3.4
|
[v0.3.4]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.3.3...v0.3.4
|
||||||
[v0.3.3]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.3.2...v0.3.3
|
[v0.3.3]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.3.2...v0.3.3
|
||||||
[v0.3.2]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.3.1...v0.3.2
|
[v0.3.2]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.3.1...v0.3.2
|
||||||
[v0.3.1]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.3.0...v0.3.1
|
[v0.3.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.3.0...v0.3.1
|
||||||
[v0.3.0]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.2.2...v0.3.0
|
[v0.3.0]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.2.2...v0.3.0
|
||||||
[v0.2.2]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.2.1...v0.2.2
|
[v0.2.2]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.2.1...v0.2.2
|
||||||
[v0.2.1]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.2.0...v0.2.1
|
[v0.2.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.2.0...v0.2.1
|
||||||
[v0.2.0]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.1.1...v0.2.0
|
[v0.2.0]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.1.1...v0.2.0
|
||||||
[v0.1.1]: https://github.com/rtfm-rs/cortex-m-rtfm/compare/v0.1.0...v0.1.1
|
[v0.1.1]: https://github.com/rtic-rs/cortex-m-rtic/compare/v0.1.0...v0.1.1
|
||||||
|
|
2
CNAME
2
CNAME
|
@ -1 +1 @@
|
||||||
rtfm.rs
|
rtic.rs
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
## New features
|
## New features
|
||||||
New features should go through the [RFC process][rfcs] before a Pull Request is made to this repository.
|
New features should go through the [RFC process][rfcs] before a Pull Request is made to this repository.
|
||||||
|
|
||||||
[rfcs](https://github.com/rtfm-rs/rfcs)
|
[rfcs](https://github.com/rtic-rs/rfcs)
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
Report bugs by creating an issue in this repository.
|
Report bugs by creating an issue in this repository.
|
||||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -1,22 +1,22 @@
|
||||||
[package]
|
[package]
|
||||||
authors = [
|
authors = [
|
||||||
"The Real Time For the Masses developers",
|
"The Real-Time Interrupt-driven Concurrency developers",
|
||||||
"Jorge Aparicio <jorge@japaric.io>",
|
"Jorge Aparicio <jorge@japaric.io>",
|
||||||
"Per Lindgren <per.lindgren@ltu.se>",
|
"Per Lindgren <per.lindgren@ltu.se>",
|
||||||
]
|
]
|
||||||
categories = ["concurrency", "embedded", "no-std"]
|
categories = ["concurrency", "embedded", "no-std"]
|
||||||
description = "Real Time For the Masses (RTFM): a concurrency framework for building real time systems"
|
description = "Real-Time Interrupt-driven Concurrency (RTIC): a concurrency framework for building real time systems"
|
||||||
documentation = "https://rtfm.rs/"
|
documentation = "https://rtic.rs/"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
keywords = ["arm", "cortex-m"]
|
keywords = ["arm", "cortex-m"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "cortex-m-rtfm"
|
name = "cortex-m-rtic"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/rtfm-rs/cortex-m-rtfm"
|
repository = "https://github.com/rtic-rs/cortex-m-rtic"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "rtfm"
|
name = "rtic"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "baseline"
|
name = "baseline"
|
||||||
|
@ -52,8 +52,8 @@ required-features = ["__v7"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m = "0.6.2"
|
cortex-m = "0.6.2"
|
||||||
cortex-m-rtfm-macros = { path = "macros", version = "0.5.0" }
|
cortex-m-rtic-macros = { path = "macros", version = "0.5.0" }
|
||||||
rtfm-core = "0.3.0"
|
rtic-core = "0.3.0"
|
||||||
cortex-m-rt = "0.6.9"
|
cortex-m-rt = "0.6.9"
|
||||||
heapless = "0.5.0"
|
heapless = "0.5.0"
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ version = "0.5.2"
|
||||||
trybuild = "1"
|
trybuild = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
heterogeneous = ["cortex-m-rtfm-macros/heterogeneous", "microamp"]
|
heterogeneous = ["cortex-m-rtic-macros/heterogeneous", "microamp"]
|
||||||
homogeneous = ["cortex-m-rtfm-macros/homogeneous"]
|
homogeneous = ["cortex-m-rtic-macros/homogeneous"]
|
||||||
# used for testing this crate; do not use in applications
|
# used for testing this crate; do not use in applications
|
||||||
__v7 =[]
|
__v7 =[]
|
||||||
__min_r1_43 =[]
|
__min_r1_43 =[]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2017-2019 The Real Time For the Masses developers
|
Copyright (c) 2017-2019 The Real-Time Interrupt-driven Concurrency developers
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
Permission is hereby granted, free of charge, to any
|
||||||
person obtaining a copy of this software and associated
|
person obtaining a copy of this software and associated
|
||||||
|
|
16
README.md
16
README.md
|
@ -1,4 +1,4 @@
|
||||||
# Real Time For the Masses
|
# Real-Time Interrupt-driven Concurrency
|
||||||
|
|
||||||
A concurrency framework for building real time systems.
|
A concurrency framework for building real time systems.
|
||||||
|
|
||||||
|
@ -43,27 +43,27 @@ A concurrency framework for building real time systems.
|
||||||
|
|
||||||
- Applications must be written using the 2018 edition.
|
- Applications must be written using the 2018 edition.
|
||||||
|
|
||||||
## [User documentation](https://rtfm.rs)
|
## [User documentation](https://rtic.rs)
|
||||||
|
|
||||||
## [API reference](https://rtfm.rs/0.5/api)
|
## [API reference](https://rtic.rs/0.5/api)
|
||||||
|
|
||||||
## Chat
|
## Chat
|
||||||
Join us and talk about RTFM in the [Matrix room][matrix-room].
|
Join us and talk about RTIC in the [Matrix room][matrix-room].
|
||||||
|
|
||||||
[matrix-room]: https://matrix.to/#/#rtfm-rs:matrix.org
|
[matrix-room]: https://matrix.to/#/#rtic-rs:matrix.org
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
New features and big changes should go through the RFC process in the [dedicated RFC repository][rfcs].
|
New features and big changes should go through the RFC process in the [dedicated RFC repository][rfcs].
|
||||||
|
|
||||||
[rfcs]: https://github.com/rtfm-rs/rfcs
|
[rfcs]: https://github.com/rtic-rs/rfcs
|
||||||
|
|
||||||
## Acknowledgments
|
## Acknowledgments
|
||||||
|
|
||||||
This crate is based on [the RTFM language][rtfm-lang] created by the Embedded
|
This crate is based on [the RTIC language][rtic-lang] created by the Embedded
|
||||||
Systems group at [Luleå University of Technology][ltu], led by [Prof. Per
|
Systems group at [Luleå University of Technology][ltu], led by [Prof. Per
|
||||||
Lindgren][per].
|
Lindgren][per].
|
||||||
|
|
||||||
[rtfm-lang]: http://www.rtfm-lang.org/
|
[rtic-lang]: http://www.rtic-lang.org/
|
||||||
[ltu]: https://www.ltu.se/?l=en
|
[ltu]: https://www.ltu.se/?l=en
|
||||||
[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
|
[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
authors = ["Jorge Aparicio"]
|
authors = ["Jorge Aparicio"]
|
||||||
multilingual = false
|
multilingual = false
|
||||||
src = "src"
|
src = "src"
|
||||||
title = "Real Time For the Masses"
|
title = "Real-Time Interrupt-driven Concurrency"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
[Preface](./preface.md)
|
[Preface](./preface.md)
|
||||||
- [RTFM by example](./by-example.md)
|
- [RTIC by example](./by-example.md)
|
||||||
- [The `app` attribute](./by-example/app.md)
|
- [The `app` attribute](./by-example/app.md)
|
||||||
- [Resources](./by-example/resources.md)
|
- [Resources](./by-example/resources.md)
|
||||||
- [Software tasks](./by-example/tasks.md)
|
- [Software tasks](./by-example/tasks.md)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# RTFM by example
|
# RTIC by example
|
||||||
|
|
||||||
This part of the book introduces the Real Time For the Masses (RTFM) framework
|
This part of the book introduces the Real-Time Interrupt-driven Concurrency (RTIC) framework
|
||||||
to new users by walking them through examples of increasing complexity.
|
to new users by walking them through examples of increasing complexity.
|
||||||
|
|
||||||
All examples in this part of the book can be found in the GitHub [repository] of
|
All examples in this part of the book can be found in the GitHub [repository] of
|
||||||
the project, and most of the examples can be run on QEMU so no special hardware
|
the project, and most of the examples can be run on QEMU so no special hardware
|
||||||
is required to follow along.
|
is required to follow along.
|
||||||
|
|
||||||
[repository]: https://github.com/rtfm-rs/cortex-m-rtfm
|
[repository]: https://github.com/rtic-rs/cortex-m-rtic
|
||||||
|
|
||||||
To run the examples on your laptop / PC you'll need the `qemu-system-arm`
|
To run the examples on your laptop / PC you'll need the `qemu-system-arm`
|
||||||
program. Check [the embedded Rust book] for instructions on how to set up an
|
program. Check [the embedded Rust book] for instructions on how to set up an
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
# The `app` attribute
|
# The `app` attribute
|
||||||
|
|
||||||
This is the smallest possible RTFM application:
|
This is the smallest possible RTIC application:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
{{#include ../../../../examples/smallest.rs}}
|
{{#include ../../../../examples/smallest.rs}}
|
||||||
```
|
```
|
||||||
|
|
||||||
All RTFM applications use the [`app`] attribute (`#[app(..)]`). This attribute
|
All RTIC applications use the [`app`] attribute (`#[app(..)]`). This attribute
|
||||||
must be applied to a `const` item that contains items. The `app` attribute has
|
must be applied to a `const` item that contains items. The `app` attribute has
|
||||||
a mandatory `device` argument that takes a *path* as a value. This path must
|
a mandatory `device` argument that takes a *path* as a value. This path must
|
||||||
point to a *peripheral access crate* (PAC) generated using [`svd2rust`]
|
point to a *peripheral access crate* (PAC) generated using [`svd2rust`]
|
||||||
**v0.14.x** or newer. The `app` attribute will expand into a suitable entry
|
**v0.14.x** or newer. The `app` attribute will expand into a suitable entry
|
||||||
point so it's not required to use the [`cortex_m_rt::entry`] attribute.
|
point so it's not required to use the [`cortex_m_rt::entry`] attribute.
|
||||||
|
|
||||||
[`app`]: ../../../api/cortex_m_rtfm_macros/attr.app.html
|
[`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html
|
||||||
[`svd2rust`]: https://crates.io/crates/svd2rust
|
[`svd2rust`]: https://crates.io/crates/svd2rust
|
||||||
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
||||||
|
|
||||||
> **ASIDE**: Some of you may be wondering why we are using a `const` item as a
|
> **ASIDE**: Some of you may be wondering why we are using a `const` item as a
|
||||||
> module and not a proper `mod` item. The reason is that using attributes on
|
> module and not a proper `mod` item. The reason is that using attributes on
|
||||||
> modules requires a feature gate, which requires a nightly toolchain. To make
|
> modules requires a feature gate, which requires a nightly toolchain. To make
|
||||||
> RTFM work on stable we use the `const` item instead. When more parts of macros
|
> RTIC work on stable we use the `const` item instead. When more parts of macros
|
||||||
> 1.2 are stabilized we'll move from a `const` item to a `mod` item and
|
> 1.2 are stabilized we'll move from a `const` item to a `mod` item and
|
||||||
> eventually to a crate level attribute (`#![app]`).
|
> eventually to a crate level attribute (`#![app]`).
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ to Cortex-M and, optionally, device specific peripherals through the `core` and
|
||||||
`static mut` variables declared at the beginning of `init` will be transformed
|
`static mut` variables declared at the beginning of `init` will be transformed
|
||||||
into `&'static mut` references that are safe to access.
|
into `&'static mut` references that are safe to access.
|
||||||
|
|
||||||
[`rtfm::Peripherals`]: ../../api/rtfm/struct.Peripherals.html
|
[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
|
||||||
|
|
||||||
The example below shows the types of the `core` and `device` fields and
|
The example below shows the types of the `core` and `device` fields and
|
||||||
showcases safe access to a `static mut` variable. The `device` field is only
|
showcases safe access to a `static mut` variable. The `device` field is only
|
||||||
|
@ -106,9 +106,9 @@ mut` variables are safe to use within a hardware task.
|
||||||
$ cargo run --example hardware
|
$ cargo run --example hardware
|
||||||
{{#include ../../../../ci/expected/hardware.run}}```
|
{{#include ../../../../ci/expected/hardware.run}}```
|
||||||
|
|
||||||
So far all the RTFM applications we have seen look no different than the
|
So far all the RTIC applications we have seen look no different than the
|
||||||
applications one can write using only the `cortex-m-rt` crate. From this point
|
applications one can write using only the `cortex-m-rt` crate. From this point
|
||||||
we start introducing features unique to RTFM.
|
we start introducing features unique to RTIC.
|
||||||
|
|
||||||
## Priorities
|
## Priorities
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Starting a new project
|
# Starting a new project
|
||||||
|
|
||||||
Now that you have learned about the main features of the RTFM framework you can
|
Now that you have learned about the main features of the RTIC framework you can
|
||||||
try it out on your hardware by following these instructions.
|
try it out on your hardware by following these instructions.
|
||||||
|
|
||||||
1. Instantiate the [`cortex-m-quickstart`] template.
|
1. Instantiate the [`cortex-m-quickstart`] template.
|
||||||
|
@ -36,19 +36,19 @@ $ cargo add lm3s6965 --vers 0.1.3
|
||||||
$ rm memory.x build.rs
|
$ rm memory.x build.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Add the `cortex-m-rtfm` crate as a dependency.
|
3. Add the `cortex-m-rtic` crate as a dependency.
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ cargo add cortex-m-rtfm --allow-prerelease
|
$ cargo add cortex-m-rtic --allow-prerelease
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Write your RTFM application.
|
4. Write your RTIC application.
|
||||||
|
|
||||||
Here I'll use the `init` example from the `cortex-m-rtfm` crate.
|
Here I'll use the `init` example from the `cortex-m-rtic` crate.
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ curl \
|
$ curl \
|
||||||
-L https://github.com/rtfm-rs/cortex-m-rtfm/raw/v0.5.0/examples/init.rs \
|
-L https://github.com/rtic-rs/cortex-m-rtic/raw/v0.5.0/examples/init.rs \
|
||||||
> src/main.rs
|
> src/main.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ instead of a reference. This resource proxy is a structure that implements the
|
||||||
[`Mutex`] trait. The only method on this trait, [`lock`], runs its closure
|
[`Mutex`] trait. The only method on this trait, [`lock`], runs its closure
|
||||||
argument in a critical section.
|
argument in a critical section.
|
||||||
|
|
||||||
[`Mutex`]: ../../../api/rtfm/trait.Mutex.html
|
[`Mutex`]: ../../../api/rtic/trait.Mutex.html
|
||||||
[`lock`]: ../../../api/rtfm/trait.Mutex.html#method.lock
|
[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
|
||||||
|
|
||||||
The critical section created by the `lock` API is based on dynamic priorities:
|
The critical section created by the `lock` API is based on dynamic priorities:
|
||||||
it temporarily raises the dynamic priority of the context to a *ceiling*
|
it temporarily raises the dynamic priority of the context to a *ceiling*
|
||||||
|
@ -113,7 +113,7 @@ shared reference (`&-`) to the resource, limiting the operations it can perform
|
||||||
on it, but where a shared reference is enough this approach reduces the number
|
on it, but where a shared reference is enough this approach reduces the number
|
||||||
of required locks.
|
of required locks.
|
||||||
|
|
||||||
Note that in this release of RTFM it is not possible to request both exclusive
|
Note that in this release of RTIC it is not possible to request both exclusive
|
||||||
access (`&mut-`) and shared access (`&-`) to the *same* resource from different
|
access (`&mut-`) and shared access (`&-`) to the *same* resource from different
|
||||||
tasks. Attempting to do so will result in a compile error.
|
tasks. Attempting to do so will result in a compile error.
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# Software tasks
|
# Software tasks
|
||||||
|
|
||||||
In addition to hardware tasks, which are invoked by the hardware in response to
|
In addition to hardware tasks, which are invoked by the hardware in response to
|
||||||
hardware events, RTFM also supports *software* tasks which can be spawned by the
|
hardware events, RTIC also supports *software* tasks which can be spawned by the
|
||||||
application from any execution context.
|
application from any execution context.
|
||||||
|
|
||||||
Software tasks can also be assigned priorities and, under the hood, are
|
Software tasks can also be assigned priorities and, under the hood, are
|
||||||
dispatched from interrupt handlers. RTFM requires that free interrupts are
|
dispatched from interrupt handlers. RTIC requires that free interrupts are
|
||||||
declared in an `extern` block when using software tasks; some of these free
|
declared in an `extern` block when using software tasks; some of these free
|
||||||
interrupts will be used to dispatch the software tasks. An advantage of software
|
interrupts will be used to dispatch the software tasks. An advantage of software
|
||||||
tasks over hardware tasks is that many tasks can be mapped to a single interrupt
|
tasks over hardware tasks is that many tasks can be mapped to a single interrupt
|
||||||
|
@ -45,7 +45,7 @@ $ cargo run --example message
|
||||||
|
|
||||||
## Capacity
|
## Capacity
|
||||||
|
|
||||||
RTFM does *not* perform any form of heap-based memory allocation. The memory
|
RTIC does *not* perform any form of heap-based memory allocation. The memory
|
||||||
required to store messages is statically reserved. By default the framework
|
required to store messages is statically reserved. By default the framework
|
||||||
minimizes the memory footprint of the application so each task has a message
|
minimizes the memory footprint of the application so each task has a message
|
||||||
"capacity" of 1: meaning that at most one message can be posted to the task
|
"capacity" of 1: meaning that at most one message can be posted to the task
|
||||||
|
@ -91,7 +91,7 @@ its message buffer will never be emptied. This situation is depicted in the
|
||||||
following snippet:
|
following snippet:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(..)]
|
#[rtic::app(..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [foo, bar])]
|
#[init(spawn = [foo, bar])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
|
|
|
@ -20,11 +20,11 @@ type (see [`core::time::Duration`]) and this `Duration` type must implement the
|
||||||
integer. If the result of the conversion doesn't fit in a 32-bit number then the
|
integer. If the result of the conversion doesn't fit in a 32-bit number then the
|
||||||
operation must return an error, any error type.
|
operation must return an error, any error type.
|
||||||
|
|
||||||
[`Monotonic`]: ../../../api/rtfm/trait.Monotonic.html
|
[`Monotonic`]: ../../../api/rtic/trait.Monotonic.html
|
||||||
[std-instant]: https://doc.rust-lang.org/std/time/struct.Instant.html
|
[std-instant]: https://doc.rust-lang.org/std/time/struct.Instant.html
|
||||||
[`core::time::Duration`]: https://doc.rust-lang.org/core/time/struct.Duration.html
|
[`core::time::Duration`]: https://doc.rust-lang.org/core/time/struct.Duration.html
|
||||||
|
|
||||||
For ARMv7+ targets the `rtfm` crate provides a `Monotonic` implementation based
|
For ARMv7+ targets the `rtic` crate provides a `Monotonic` implementation based
|
||||||
on the built-in CYCle CouNTer (CYCCNT). Note that this is a 32-bit timer clocked
|
on the built-in CYCle CouNTer (CYCCNT). Note that this is a 32-bit timer clocked
|
||||||
at the frequency of the CPU and as such it is not suitable for tracking time
|
at the frequency of the CPU and as such it is not suitable for tracking time
|
||||||
spans in the order of seconds.
|
spans in the order of seconds.
|
||||||
|
@ -36,7 +36,7 @@ executed must be passed as the first argument of the `schedule` invocation.
|
||||||
|
|
||||||
Additionally, the chosen `monotonic` timer must be configured and initialized
|
Additionally, the chosen `monotonic` timer must be configured and initialized
|
||||||
during the `#[init]` phase. Note that this is *also* the case if you choose to
|
during the `#[init]` phase. Note that this is *also* the case if you choose to
|
||||||
use the `CYCCNT` provided by the `cortex-m-rtfm` crate.
|
use the `CYCCNT` provided by the `cortex-m-rtic` crate.
|
||||||
|
|
||||||
The example below schedules two tasks from `init`: `foo` and `bar`. `foo` is
|
The example below schedules two tasks from `init`: `foo` and `bar`. `foo` is
|
||||||
scheduled to run 8 million clock cycles in the future. Next, `bar` is scheduled
|
scheduled to run 8 million clock cycles in the future. Next, `bar` is scheduled
|
||||||
|
@ -61,7 +61,7 @@ console:
|
||||||
When the `schedule` API is being used the runtime internally uses the `SysTick`
|
When the `schedule` API is being used the runtime internally uses the `SysTick`
|
||||||
interrupt handler and the system timer peripheral (`SYST`) so neither can be
|
interrupt handler and the system timer peripheral (`SYST`) so neither can be
|
||||||
used by the application. This is accomplished by changing the type of
|
used by the application. This is accomplished by changing the type of
|
||||||
`init::Context.core` from `cortex_m::Peripherals` to `rtfm::Peripherals`. The
|
`init::Context.core` from `cortex_m::Peripherals` to `rtic::Peripherals`. The
|
||||||
latter structure contains all the fields of the former minus the `SYST` one.
|
latter structure contains all the fields of the former minus the `SYST` one.
|
||||||
|
|
||||||
## Periodic tasks
|
## Periodic tasks
|
||||||
|
|
|
@ -8,15 +8,15 @@ appear as *different* types in different contexts one cannot refactor a common
|
||||||
operation that uses resources into a plain function; however, such refactor is
|
operation that uses resources into a plain function; however, such refactor is
|
||||||
possible using *generics*.
|
possible using *generics*.
|
||||||
|
|
||||||
All resource proxies implement the `rtfm::Mutex` trait. On the other hand,
|
All resource proxies implement the `rtic::Mutex` trait. On the other hand,
|
||||||
unique references (`&mut-`) do *not* implement this trait (due to limitations in
|
unique references (`&mut-`) do *not* implement this trait (due to limitations in
|
||||||
the trait system) but one can wrap these references in the [`rtfm::Exclusive`]
|
the trait system) but one can wrap these references in the [`rtic::Exclusive`]
|
||||||
newtype which does implement the `Mutex` trait. With the help of this newtype
|
newtype which does implement the `Mutex` trait. With the help of this newtype
|
||||||
one can write a generic function that operates on generic resources and call it
|
one can write a generic function that operates on generic resources and call it
|
||||||
from different tasks to perform some operation on the same set of resources.
|
from different tasks to perform some operation on the same set of resources.
|
||||||
Here's one such example:
|
Here's one such example:
|
||||||
|
|
||||||
[`rtfm::Exclusive`]: ../../../api/rtfm/struct.Exclusive.html
|
[`rtic::Exclusive`]: ../../../api/rtic/struct.Exclusive.html
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
{{#include ../../../../examples/generics.rs}}
|
{{#include ../../../../examples/generics.rs}}
|
||||||
|
@ -51,8 +51,8 @@ $ cargo run --example cfg
|
||||||
|
|
||||||
## Running tasks from RAM
|
## Running tasks from RAM
|
||||||
|
|
||||||
The main goal of moving the specification of RTFM applications to attributes in
|
The main goal of moving the specification of RTIC applications to attributes in
|
||||||
RTFM v0.4.0 was to allow inter-operation with other attributes. For example, the
|
RTIC v0.4.0 was to allow inter-operation with other attributes. For example, the
|
||||||
`link_section` attribute can be applied to tasks to place them in RAM; this can
|
`link_section` attribute can be applied to tasks to place them in RAM; this can
|
||||||
improve performance in some cases.
|
improve performance in some cases.
|
||||||
|
|
||||||
|
@ -119,22 +119,22 @@ $ cargo run --example pool
|
||||||
|
|
||||||
## Inspecting the expanded code
|
## Inspecting the expanded code
|
||||||
|
|
||||||
`#[rtfm::app]` is a procedural macro that produces support code. If for some
|
`#[rtic::app]` is a procedural macro that produces support code. If for some
|
||||||
reason you need to inspect the code generated by this macro you have two
|
reason you need to inspect the code generated by this macro you have two
|
||||||
options:
|
options:
|
||||||
|
|
||||||
You can inspect the file `rtfm-expansion.rs` inside the `target` directory. This
|
You can inspect the file `rtic-expansion.rs` inside the `target` directory. This
|
||||||
file contains the expansion of the `#[rtfm::app]` item (not your whole program!)
|
file contains the expansion of the `#[rtic::app]` item (not your whole program!)
|
||||||
of the *last built* (via `cargo build` or `cargo check`) RTFM application. The
|
of the *last built* (via `cargo build` or `cargo check`) RTIC application. The
|
||||||
expanded code is not pretty printed by default so you'll want to run `rustfmt`
|
expanded code is not pretty printed by default so you'll want to run `rustfmt`
|
||||||
over it before you read it.
|
over it before you read it.
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ cargo build --example foo
|
$ cargo build --example foo
|
||||||
|
|
||||||
$ rustfmt target/rtfm-expansion.rs
|
$ rustfmt target/rtic-expansion.rs
|
||||||
|
|
||||||
$ tail target/rtfm-expansion.rs
|
$ tail target/rtic-expansion.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
|
@ -144,19 +144,19 @@ const APP: () = {
|
||||||
use lm3s6965 as _;
|
use lm3s6965 as _;
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn main() -> ! {
|
unsafe extern "C" fn main() -> ! {
|
||||||
rtfm::export::interrupt::disable();
|
rtic::export::interrupt::disable();
|
||||||
let mut core: rtfm::export::Peripherals = core::mem::transmute(());
|
let mut core: rtic::export::Peripherals = core::mem::transmute(());
|
||||||
core.SCB.scr.modify(|r| r | 1 << 1);
|
core.SCB.scr.modify(|r| r | 1 << 1);
|
||||||
rtfm::export::interrupt::enable();
|
rtic::export::interrupt::enable();
|
||||||
loop {
|
loop {
|
||||||
rtfm::export::wfi()
|
rtic::export::wfi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, you can use the [`cargo-expand`] subcommand. This subcommand will expand
|
Or, you can use the [`cargo-expand`] subcommand. This subcommand will expand
|
||||||
*all* the macros, including the `#[rtfm::app]` attribute, and modules in your
|
*all* the macros, including the `#[rtic::app]` attribute, and modules in your
|
||||||
crate and print the output to the console.
|
crate and print the output to the console.
|
||||||
|
|
||||||
[`cargo-expand`]: https://crates.io/crates/cargo-expand
|
[`cargo-expand`]: https://crates.io/crates/cargo-expand
|
||||||
|
|
|
@ -18,7 +18,7 @@ The example below shows the different types generates by the `app` attribute.
|
||||||
## `Send`
|
## `Send`
|
||||||
|
|
||||||
[`Send`] is a marker trait for "types that can be transferred across thread
|
[`Send`] is a marker trait for "types that can be transferred across thread
|
||||||
boundaries", according to its definition in `core`. In the context of RTFM the
|
boundaries", according to its definition in `core`. In the context of RTIC the
|
||||||
`Send` trait is only required where it's possible to transfer a value between
|
`Send` trait is only required where it's possible to transfer a value between
|
||||||
tasks that run at *different* priorities. This occurs in a few places: in
|
tasks that run at *different* priorities. This occurs in a few places: in
|
||||||
message passing, in shared resources and in the initialization of late
|
message passing, in shared resources and in the initialization of late
|
||||||
|
@ -57,7 +57,7 @@ the `Send` trait.
|
||||||
|
|
||||||
Similarly, [`Sync`] is a marker trait for "types for which it is safe to share
|
Similarly, [`Sync`] is a marker trait for "types for which it is safe to share
|
||||||
references between threads", according to its definition in `core`. In the
|
references between threads", according to its definition in `core`. In the
|
||||||
context of RTFM the `Sync` trait is only required where it's possible for two,
|
context of RTIC the `Sync` trait is only required where it's possible for two,
|
||||||
or more, tasks that run at different priorities and may get a shared reference
|
or more, tasks that run at different priorities and may get a shared reference
|
||||||
(`&-`) to a resource. This only occurs with shared access (`&-`) resources.
|
(`&-`) to a resource. This only occurs with shared access (`&-`) resources.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Heterogeneous multi-core support
|
# Heterogeneous multi-core support
|
||||||
|
|
||||||
This section covers the *experimental* heterogeneous multi-core support provided
|
This section covers the *experimental* heterogeneous multi-core support provided
|
||||||
by RTFM behind the `heterogeneous` Cargo feature.
|
by RTIC behind the `heterogeneous` Cargo feature.
|
||||||
|
|
||||||
**Content coming soon**
|
**Content coming soon**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Homogeneous multi-core support
|
# Homogeneous multi-core support
|
||||||
|
|
||||||
This section covers the *experimental* homogeneous multi-core support provided
|
This section covers the *experimental* homogeneous multi-core support provided
|
||||||
by RTFM behind the `homogeneous` Cargo feature.
|
by RTIC behind the `homogeneous` Cargo feature.
|
||||||
|
|
||||||
**Content coming soon**
|
**Content coming soon**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Under the hood
|
# Under the hood
|
||||||
|
|
||||||
This section describes the internals of the RTFM framework at a *high level*.
|
This section describes the internals of the RTIC framework at a *high level*.
|
||||||
Low level details like the parsing and code generation done by the procedural
|
Low level details like the parsing and code generation done by the procedural
|
||||||
macro (`#[app]`) will not be explained here. The focus will be the analysis of
|
macro (`#[app]`) will not be explained here. The focus will be the analysis of
|
||||||
the user specification and the data structures used by the runtime.
|
the user specification and the data structures used by the runtime.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Access control
|
# Access control
|
||||||
|
|
||||||
One of the core foundations of RTFM is access control. Controlling which parts
|
One of the core foundations of RTIC is access control. Controlling which parts
|
||||||
of the program can access which static variables is instrumental to enforcing
|
of the program can access which static variables is instrumental to enforcing
|
||||||
memory safety.
|
memory safety.
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ resides in the same scope in which they are declared. Modules give some control
|
||||||
over how a static variable can be accessed by they are not flexible enough.
|
over how a static variable can be accessed by they are not flexible enough.
|
||||||
|
|
||||||
To achieve the fine-grained access control where tasks can only access the
|
To achieve the fine-grained access control where tasks can only access the
|
||||||
static variables (resources) that they have specified in their RTFM attribute
|
static variables (resources) that they have specified in their RTIC attribute
|
||||||
the RTFM framework performs a source code level transformation. This
|
the RTIC framework performs a source code level transformation. This
|
||||||
transformation consists of placing the resources (static variables) specified by
|
transformation consists of placing the resources (static variables) specified by
|
||||||
the user *inside* a `const` item and the user code *outside* the `const` item.
|
the user *inside* a `const` item and the user code *outside* the `const` item.
|
||||||
This makes it impossible for the user code to refer to these static variables.
|
This makes it impossible for the user code to refer to these static variables.
|
||||||
|
@ -28,7 +28,7 @@ The code below is an example of the kind of source level transformation that
|
||||||
happens behind the scenes:
|
happens behind the scenes:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
static mut X: u64: 0;
|
static mut X: u64: 0;
|
||||||
static mut Y: bool: 0;
|
static mut Y: bool: 0;
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
A resource *priority ceiling*, or just *ceiling*, is the dynamic priority that
|
A resource *priority ceiling*, or just *ceiling*, is the dynamic priority that
|
||||||
any task must have to safely access the resource memory. Ceiling analysis is
|
any task must have to safely access the resource memory. Ceiling analysis is
|
||||||
relatively simple but critical to the memory safety of RTFM applications.
|
relatively simple but critical to the memory safety of RTIC applications.
|
||||||
|
|
||||||
To compute the ceiling of a resource we must first collect a list of tasks that
|
To compute the ceiling of a resource we must first collect a list of tasks that
|
||||||
have access to the resource -- as the RTFM framework enforces access control to
|
have access to the resource -- as the RTIC framework enforces access control to
|
||||||
resources at compile time it also has access to this information at compile
|
resources at compile time it also has access to this information at compile
|
||||||
time. The ceiling of the resource is simply the highest logical priority among
|
time. The ceiling of the resource is simply the highest logical priority among
|
||||||
those tasks.
|
those tasks.
|
||||||
|
@ -27,7 +27,7 @@ gets a unique reference (`&mut-`) to resources.
|
||||||
An example to illustrate the ceiling analysis:
|
An example to illustrate the ceiling analysis:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
// accessed by `foo` (prio = 1) and `bar` (prio = 2)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
When a resource (static variable) is shared between two, or more, tasks that run
|
When a resource (static variable) is shared between two, or more, tasks that run
|
||||||
at different priorities some form of mutual exclusion is required to mutate the
|
at different priorities some form of mutual exclusion is required to mutate the
|
||||||
memory in a data race free manner. In RTFM we use priority-based critical
|
memory in a data race free manner. In RTIC we use priority-based critical
|
||||||
sections to guarantee mutual exclusion (see the [Immediate Ceiling Priority
|
sections to guarantee mutual exclusion (see the [Immediate Ceiling Priority
|
||||||
Protocol][icpp]).
|
Protocol][icpp]).
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ task we give it a *resource proxy*, whereas we give a unique reference
|
||||||
The example below shows the different types handed out to each task:
|
The example below shows the different types handed out to each task:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -102,7 +102,7 @@ pub mod bar {
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
static mut x: u64 = 0;
|
static mut x: u64 = 0;
|
||||||
|
|
||||||
impl rtfm::Mutex for resources::x {
|
impl rtic::Mutex for resources::x {
|
||||||
type T = u64;
|
type T = u64;
|
||||||
|
|
||||||
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
||||||
|
@ -161,7 +161,7 @@ In this particular example we could implement the critical section as follows:
|
||||||
> **NOTE:** this is a simplified implementation
|
> **NOTE:** this is a simplified implementation
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
impl rtfm::Mutex for resources::x {
|
impl rtic::Mutex for resources::x {
|
||||||
type T = u64;
|
type T = u64;
|
||||||
|
|
||||||
fn lock<R, F>(&mut self, f: F) -> R
|
fn lock<R, F>(&mut self, f: F) -> R
|
||||||
|
@ -224,7 +224,7 @@ provides extra information to the compiler.
|
||||||
Consider this program:
|
Consider this program:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -235,7 +235,7 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init() {
|
fn init() {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(binds = UART0, priority = 1, resources = [x, y])]
|
#[interrupt(binds = UART0, priority = 1, resources = [x, y])]
|
||||||
|
@ -338,7 +338,7 @@ const APP: () = {
|
||||||
|
|
||||||
// similarly for `UART0` / `foo` and `UART2` / `baz`
|
// similarly for `UART0` / `foo` and `UART2` / `baz`
|
||||||
|
|
||||||
impl<'a> rtfm::Mutex for resources::x<'a> {
|
impl<'a> rtic::Mutex for resources::x<'a> {
|
||||||
type T = u64;
|
type T = u64;
|
||||||
|
|
||||||
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
fn lock<R>(&mut self, f: impl FnOnce(&mut u64) -> R) -> R {
|
||||||
|
@ -419,7 +419,7 @@ fn foo(c: foo::Context) {
|
||||||
|
|
||||||
## The BASEPRI invariant
|
## The BASEPRI invariant
|
||||||
|
|
||||||
An invariant that the RTFM framework has to preserve is that the value of the
|
An invariant that the RTIC framework has to preserve is that the value of the
|
||||||
BASEPRI at the start of an *interrupt* handler must be the same value it has
|
BASEPRI at the start of an *interrupt* handler must be the same value it has
|
||||||
when the interrupt handler returns. BASEPRI may change during the execution of
|
when the interrupt handler returns. BASEPRI may change during the execution of
|
||||||
the interrupt handler but running an interrupt handler from start to finish
|
the interrupt handler but running an interrupt handler from start to finish
|
||||||
|
@ -429,7 +429,7 @@ This invariant needs to be preserved to avoid raising the dynamic priority of a
|
||||||
handler through preemption. This is best observed in the following example:
|
handler through preemption. This is best observed in the following example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -439,7 +439,7 @@ const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init() {
|
fn init() {
|
||||||
// `foo` will run right after `init` returns
|
// `foo` will run right after `init` returns
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, priority = 1)]
|
#[task(binds = UART0, priority = 1)]
|
||||||
|
@ -447,7 +447,7 @@ const APP: () = {
|
||||||
// BASEPRI is `0` at this point; the dynamic priority is currently `1`
|
// BASEPRI is `0` at this point; the dynamic priority is currently `1`
|
||||||
|
|
||||||
// `bar` will preempt `foo` at this point
|
// `bar` will preempt `foo` at this point
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
// BASEPRI is `192` at this point (due to a bug); the dynamic priority is now `2`
|
// BASEPRI is `192` at this point (due to a bug); the dynamic priority is now `2`
|
||||||
// this function returns to `idle`
|
// this function returns to `idle`
|
||||||
|
@ -472,7 +472,7 @@ const APP: () = {
|
||||||
|
|
||||||
// this has no effect due to the BASEPRI value
|
// this has no effect due to the BASEPRI value
|
||||||
// the task `foo` will never be executed again
|
// the task `foo` will never be executed again
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// ..
|
// ..
|
||||||
|
@ -488,10 +488,10 @@ const APP: () = {
|
||||||
```
|
```
|
||||||
|
|
||||||
IMPORTANT: let's say we *forget* to roll back `BASEPRI` in `UART1` -- this would
|
IMPORTANT: let's say we *forget* to roll back `BASEPRI` in `UART1` -- this would
|
||||||
be a bug in the RTFM code generator.
|
be a bug in the RTIC code generator.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
// code generated by RTFM
|
// code generated by RTIC
|
||||||
|
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Interrupt configuration
|
# Interrupt configuration
|
||||||
|
|
||||||
Interrupts are core to the operation of RTFM applications. Correctly setting
|
Interrupts are core to the operation of RTIC applications. Correctly setting
|
||||||
interrupt priorities and ensuring they remain fixed at runtime is a requisite
|
interrupt priorities and ensuring they remain fixed at runtime is a requisite
|
||||||
for the memory safety of the application.
|
for the memory safety of the application.
|
||||||
|
|
||||||
The RTFM framework exposes interrupt priorities as something that is declared at
|
The RTIC framework exposes interrupt priorities as something that is declared at
|
||||||
compile time. However, this static configuration must be programmed into the
|
compile time. However, this static configuration must be programmed into the
|
||||||
relevant registers during the initialization of the application. The interrupt
|
relevant registers during the initialization of the application. The interrupt
|
||||||
configuration is done before the `init` function runs.
|
configuration is done before the `init` function runs.
|
||||||
|
|
||||||
This example gives you an idea of the code that the RTFM framework runs:
|
This example gives you an idea of the code that the RTIC framework runs:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ The example below shows the kind of code that the framework generates to
|
||||||
initialize late resources.
|
initialize late resources.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: Thing,
|
x: Thing,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Non-reentrancy
|
# Non-reentrancy
|
||||||
|
|
||||||
In RTFM, tasks handlers are *not* reentrant. Reentering a task handler can break
|
In RTIC, tasks handlers are *not* reentrant. Reentering a task handler can break
|
||||||
Rust aliasing rules and lead to *undefined behavior*. A task handler can be
|
Rust aliasing rules and lead to *undefined behavior*. A task handler can be
|
||||||
reentered in one of two ways: in software or by hardware.
|
reentered in one of two ways: in software or by hardware.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ invoked using FFI (see example below). FFI requires `unsafe` code so end users
|
||||||
are discouraged from directly invoking an interrupt handler.
|
are discouraged from directly invoking an interrupt handler.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(c: init::Context) { .. }
|
fn init(c: init::Context) { .. }
|
||||||
|
@ -42,7 +42,7 @@ const APP: () = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The RTFM framework must generate the interrupt handler code that calls the user
|
The RTIC framework must generate the interrupt handler code that calls the user
|
||||||
defined task handlers. We are careful in making these handlers impossible to
|
defined task handlers. We are careful in making these handlers impossible to
|
||||||
call from user code.
|
call from user code.
|
||||||
|
|
||||||
|
@ -76,5 +76,5 @@ const APP: () = {
|
||||||
|
|
||||||
A task handler can also be reentered without software intervention. This can
|
A task handler can also be reentered without software intervention. This can
|
||||||
occur if the same handler is assigned to two or more interrupts in the vector
|
occur if the same handler is assigned to two or more interrupts in the vector
|
||||||
table but there's no syntax for this kind of configuration in the RTFM
|
table but there's no syntax for this kind of configuration in the RTIC
|
||||||
framework.
|
framework.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Software tasks
|
# Software tasks
|
||||||
|
|
||||||
RTFM supports software tasks and hardware tasks. Each hardware task is bound to
|
RTIC supports software tasks and hardware tasks. Each hardware task is bound to
|
||||||
a different interrupt handler. On the other hand, several software tasks may be
|
a different interrupt handler. On the other hand, several software tasks may be
|
||||||
dispatched by the same interrupt handler -- this is done to minimize the number
|
dispatched by the same interrupt handler -- this is done to minimize the number
|
||||||
of interrupts handlers used by the framework.
|
of interrupts handlers used by the framework.
|
||||||
|
@ -27,7 +27,7 @@ Let's first take a look the code generated by the framework to dispatch tasks.
|
||||||
Consider this example:
|
Consider this example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ const APP: () = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// pend the interrupt that runs the task dispatcher
|
// pend the interrupt that runs the task dispatcher
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
|
@ -252,7 +252,7 @@ const APP: () = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// pend the interrupt that runs the task dispatcher
|
// pend the interrupt that runs the task dispatcher
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
|
@ -315,7 +315,7 @@ lock-free.
|
||||||
|
|
||||||
## Queue capacity
|
## Queue capacity
|
||||||
|
|
||||||
The RTFM framework uses several queues like ready queues and free queues. When
|
The RTIC framework uses several queues like ready queues and free queues. When
|
||||||
the free queue is empty trying to `spawn` a task results in an error; this
|
the free queue is empty trying to `spawn` a task results in an error; this
|
||||||
condition is checked at runtime. Not all the operations performed by the
|
condition is checked at runtime. Not all the operations performed by the
|
||||||
framework on these queues check if the queue is empty / full. For example,
|
framework on these queues check if the queue is empty / full. For example,
|
||||||
|
@ -356,7 +356,7 @@ endpoint is owned by a task dispatcher.
|
||||||
Consider the following example:
|
Consider the following example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[idle(spawn = [foo, bar])]
|
#[idle(spawn = [foo, bar])]
|
||||||
fn idle(c: idle::Context) -> ! {
|
fn idle(c: idle::Context) -> ! {
|
||||||
|
|
|
@ -11,7 +11,7 @@ appropriate ready queue.
|
||||||
Let's see how this in implemented in code. Consider the following program:
|
Let's see how this in implemented in code. Consider the following program:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// ..
|
// ..
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ mod foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
type Instant = <path::to::user::monotonic::timer as rtfm::Monotonic>::Instant;
|
type Instant = <path::to::user::monotonic::timer as rtic::Monotonic>::Instant;
|
||||||
|
|
||||||
// all tasks that can be `schedule`-d
|
// all tasks that can be `schedule`-d
|
||||||
enum T {
|
enum T {
|
||||||
|
@ -141,7 +141,7 @@ const APP: () = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// pend the task dispatcher
|
// pend the task dispatcher
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ timeout interrupt to the `SysTick` handler.
|
||||||
|
|
||||||
## Resolution and range of `cyccnt::Instant` and `cyccnt::Duration`
|
## Resolution and range of `cyccnt::Instant` and `cyccnt::Duration`
|
||||||
|
|
||||||
RTFM provides a `Monotonic` implementation based on the `DWT`'s (Data Watchpoint
|
RTIC provides a `Monotonic` implementation based on the `DWT`'s (Data Watchpoint
|
||||||
and Trace) cycle counter. `Instant::now` returns a snapshot of this timer; these
|
and Trace) cycle counter. `Instant::now` returns a snapshot of this timer; these
|
||||||
DWT snapshots (`Instant`s) are used to sort entries in the timer queue. The
|
DWT snapshots (`Instant`s) are used to sort entries in the timer queue. The
|
||||||
cycle counter is a 32-bit counter clocked at the core clock frequency. This
|
cycle counter is a 32-bit counter clocked at the core clock frequency. This
|
||||||
|
@ -221,7 +221,7 @@ analysis.
|
||||||
To illustrate, consider the following example:
|
To illustrate, consider the following example:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(device = ..)]
|
#[rtic::app(device = ..)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[task(priority = 3, spawn = [baz])]
|
#[task(priority = 3, spawn = [baz])]
|
||||||
fn foo(c: foo::Context) {
|
fn foo(c: foo::Context) {
|
||||||
|
@ -353,7 +353,7 @@ const APP: () = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
# Migrating from v0.4.x to v0.5.0
|
# Migrating from v0.4.x to v0.5.0
|
||||||
|
|
||||||
This section covers how to upgrade an application written against RTFM v0.4.x to
|
This section covers how to upgrade an application written against RTIC v0.4.x to
|
||||||
the version v0.5.0 of the framework.
|
the version v0.5.0 of the framework.
|
||||||
|
|
||||||
## `Cargo.toml`
|
## `Cargo.toml`
|
||||||
|
|
||||||
First, the version of the `cortex-m-rtfm` dependency needs to be updated to
|
First, the version of the `cortex-m-rtic` dependency needs to be updated to
|
||||||
`"0.5.0"`. The `timer-queue` feature needs to be removed.
|
`"0.5.0"`. The `timer-queue` feature needs to be removed.
|
||||||
|
|
||||||
|
|
||||||
``` toml
|
``` toml
|
||||||
[dependencies.cortex-m-rtfm]
|
[dependencies.cortex-m-rtic]
|
||||||
# change this
|
# change this
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
|
||||||
|
@ -24,15 +24,15 @@ features = ["timer-queue"]
|
||||||
|
|
||||||
## `Context` argument
|
## `Context` argument
|
||||||
|
|
||||||
All functions inside the `#[rtfm::app]` item need to take as first argument a
|
All functions inside the `#[rtic::app]` item need to take as first argument a
|
||||||
`Context` structure. This `Context` type will contain the variables that were
|
`Context` structure. This `Context` type will contain the variables that were
|
||||||
magically injected into the scope of the function by version v0.4.x of the
|
magically injected into the scope of the function by version v0.4.x of the
|
||||||
framework: `resources`, `spawn`, `schedule` -- these variables will become
|
framework: `resources`, `spawn`, `schedule` -- these variables will become
|
||||||
fields of the `Context` structure. Each function within the `#[rtfm::app]` item
|
fields of the `Context` structure. Each function within the `#[rtic::app]` item
|
||||||
gets a different `Context` type.
|
gets a different `Context` type.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// change this
|
// change this
|
||||||
#[task(resources = [x], spawn = [a], schedule = [b])]
|
#[task(resources = [x], spawn = [a], schedule = [b])]
|
||||||
|
@ -80,7 +80,7 @@ The syntax used to declare resources has been changed from `static mut`
|
||||||
variables to a `struct Resources`.
|
variables to a `struct Resources`.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// change this
|
// change this
|
||||||
static mut X: u32 = 0;
|
static mut X: u32 = 0;
|
||||||
|
@ -102,13 +102,13 @@ const APP: () = {
|
||||||
|
|
||||||
If your application was accessing the device peripherals in `#[init]` through
|
If your application was accessing the device peripherals in `#[init]` through
|
||||||
the `device` variable then you'll need to add `peripherals = true` to the
|
the `device` variable then you'll need to add `peripherals = true` to the
|
||||||
`#[rtfm::app]` attribute to continue to access the device peripherals through
|
`#[rtic::app]` attribute to continue to access the device peripherals through
|
||||||
the `device` field of the `init::Context` structure.
|
the `device` field of the `init::Context` structure.
|
||||||
|
|
||||||
Change this:
|
Change this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init() {
|
fn init() {
|
||||||
|
@ -122,7 +122,7 @@ const APP: () = {
|
||||||
Into this:
|
Into this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */, peripherals = true)]
|
#[rtic::app(/* .. */, peripherals = true)]
|
||||||
// ^^^^^^^^^^^^^^^^^^
|
// ^^^^^^^^^^^^^^^^^^
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
|
@ -144,7 +144,7 @@ hardware tasks in v0.5.x use the `#[task]` attribute with the `binds` argument.
|
||||||
Change this:
|
Change this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// hardware tasks
|
// hardware tasks
|
||||||
#[exception]
|
#[exception]
|
||||||
|
@ -164,7 +164,7 @@ const APP: () = {
|
||||||
Into this:
|
Into this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[task(binds = SVCall)]
|
#[task(binds = SVCall)]
|
||||||
// ^^^^^^^^^^^^^^
|
// ^^^^^^^^^^^^^^
|
||||||
|
@ -186,12 +186,12 @@ const APP: () = {
|
||||||
|
|
||||||
The `timer-queue` feature has been removed. To use the `schedule` API one must
|
The `timer-queue` feature has been removed. To use the `schedule` API one must
|
||||||
first define the monotonic timer the runtime will use using the `monotonic`
|
first define the monotonic timer the runtime will use using the `monotonic`
|
||||||
argument of the `#[rtfm::app]` attribute. To continue using the cycle counter
|
argument of the `#[rtic::app]` attribute. To continue using the cycle counter
|
||||||
(CYCCNT) as the monotonic timer, and match the behavior of version v0.4.x, add
|
(CYCCNT) as the monotonic timer, and match the behavior of version v0.4.x, add
|
||||||
the `monotonic = rtfm::cyccnt::CYCCNT` argument to the `#[rtfm::app]` attribute.
|
the `monotonic = rtic::cyccnt::CYCCNT` argument to the `#[rtic::app]` attribute.
|
||||||
|
|
||||||
Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
|
Also, the `Duration` and `Instant` types and the `U32Ext` trait have been moved
|
||||||
into the `rtfm::cyccnt` module. This module is only available on ARMv7-M+
|
into the `rtic::cyccnt` module. This module is only available on ARMv7-M+
|
||||||
devices. The removal of the `timer-queue` also brings back the `DWT` peripheral
|
devices. The removal of the `timer-queue` also brings back the `DWT` peripheral
|
||||||
inside the core peripherals struct, this will need to be enabled by the application
|
inside the core peripherals struct, this will need to be enabled by the application
|
||||||
inside `init`.
|
inside `init`.
|
||||||
|
@ -199,9 +199,9 @@ inside `init`.
|
||||||
Change this:
|
Change this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
use rtfm::{Duration, Instant, U32Ext};
|
use rtic::{Duration, Instant, U32Ext};
|
||||||
|
|
||||||
#[rtfm::app(/* .. */)]
|
#[rtic::app(/* .. */)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[task(schedule = [b])]
|
#[task(schedule = [b])]
|
||||||
fn a() {
|
fn a() {
|
||||||
|
@ -213,10 +213,10 @@ const APP: () = {
|
||||||
Into this:
|
Into this:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
use rtfm::cyccnt::{Duration, Instant, U32Ext};
|
use rtic::cyccnt::{Duration, Instant, U32Ext};
|
||||||
// ^^^^^^^^
|
// ^^^^^^^^
|
||||||
|
|
||||||
#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<h1 align="center">Real Time For the Masses</h1>
|
<h1 align="center">Real-Time Interrupt-driven Concurrency</h1>
|
||||||
|
|
||||||
<p align="center">A concurrency framework for building real time systems</p>
|
<p align="center">A concurrency framework for building real time systems</p>
|
||||||
|
|
||||||
# Preface
|
# Preface
|
||||||
|
|
||||||
This book contains user level documentation for the Real Time For the Masses
|
This book contains user level documentation for the Real-Time Interrupt-driven Concurrency
|
||||||
(RTFM) framework. The API reference can be found [here](../../api/).
|
(RTIC) framework. The API reference can be found [here](../../api/).
|
||||||
|
|
||||||
There is a translation of this book in [Russian].
|
There is a translation of this book in [Russian].
|
||||||
|
|
||||||
[Russian]: ../ru/index.html
|
[Russian]: ../ru/index.html
|
||||||
|
|
||||||
This is the documentation of v0.5.x of RTFM; for the documentation of version
|
This is the documentation of v0.5.x of RTIC; for the documentation of version
|
||||||
v0.4.x go [here](/0.4).
|
v0.4.x go [here](/0.4).
|
||||||
|
|
||||||
{{#include ../../../README.md:5:44}}
|
{{#include ../../../README.md:5:44}}
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
authors = ["Jorge Aparicio"]
|
authors = ["Jorge Aparicio"]
|
||||||
multilingual = false
|
multilingual = false
|
||||||
src = "src"
|
src = "src"
|
||||||
title = "Real Time For the Masses"
|
title = "Real-Time Interrupt-driven Concurrency"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Real Time For the Masses
|
# Real-Time Interrupt-driven Concurrency
|
||||||
|
|
||||||
Конкурентный фреймворк для создания систем реального времени.
|
Конкурентный фреймворк для создания систем реального времени.
|
||||||
|
|
||||||
|
@ -43,17 +43,17 @@
|
||||||
|
|
||||||
- Программы нужно писать используя 2018 edition.
|
- Программы нужно писать используя 2018 edition.
|
||||||
|
|
||||||
## [User documentation](https://japaric.github.io/cortex-m-rtfm/book)
|
## [User documentation](https://japaric.github.io/cortex-m-rtic/book)
|
||||||
|
|
||||||
## [API reference](https://japaric.github.io/cortex-m-rtfm/api/rtfm/index.html)
|
## [API reference](https://japaric.github.io/cortex-m-rtic/api/rtic/index.html)
|
||||||
|
|
||||||
## Благодарности
|
## Благодарности
|
||||||
|
|
||||||
Эта библиотека основана на [языке RTFM][rtfm-lang], созданном Embedded
|
Эта библиотека основана на [языке RTIC][rtic-lang], созданном Embedded
|
||||||
Systems group в [Техническом Университете Luleå][ltu], под рук.
|
Systems group в [Техническом Университете Luleå][ltu], под рук.
|
||||||
[Prof. Per Lindgren][per].
|
[Prof. Per Lindgren][per].
|
||||||
|
|
||||||
[rtfm-lang]: http://www.rtfm-lang.org/
|
[rtic-lang]: http://www.rtic-lang.org/
|
||||||
[ltu]: https://www.ltu.se/?l=en
|
[ltu]: https://www.ltu.se/?l=en
|
||||||
[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
|
[per]: https://www.ltu.se/staff/p/pln-1.11258?l=en
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
[Введение](./preface.md)
|
[Введение](./preface.md)
|
||||||
- [RTFM в примерах](./by-example.md)
|
- [RTIC в примерах](./by-example.md)
|
||||||
- [Атрибут `app`](./by-example/app.md)
|
- [Атрибут `app`](./by-example/app.md)
|
||||||
- [Ресурсы](./by-example/resources.md)
|
- [Ресурсы](./by-example/resources.md)
|
||||||
- [Задачи](./by-example/tasks.md)
|
- [Задачи](./by-example/tasks.md)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# RTFM в примерах
|
# RTIC в примерах
|
||||||
|
|
||||||
Эта часть книги представляет фреймворк Real Time For the Masses (RTFM)
|
Эта часть книги представляет фреймворк Real-Time Interrupt-driven Concurrency (RTIC)
|
||||||
новым пользователям через примеры с растущей сложностью.
|
новым пользователям через примеры с растущей сложностью.
|
||||||
|
|
||||||
Все примеры в этой книге можно найти в [репозитории] проекта на GitHub,
|
Все примеры в этой книге можно найти в [репозитории] проекта на GitHub,
|
||||||
и большинство примеров можно запустить на эмуляторе QEMU, поэтому никакого
|
и большинство примеров можно запустить на эмуляторе QEMU, поэтому никакого
|
||||||
специального оборудования не требуется их выполнять.
|
специального оборудования не требуется их выполнять.
|
||||||
|
|
||||||
[репозитории]: https://github.com/japaric/cortex-m-rtfm
|
[репозитории]: https://github.com/japaric/cortex-m-rtic
|
||||||
|
|
||||||
Чтобы запустить примеры на Вашем ноутбуке / ПК, Вам нужна программа
|
Чтобы запустить примеры на Вашем ноутбуке / ПК, Вам нужна программа
|
||||||
`qemu-system-arm`. Инструкции по настройке окружения для разработки
|
`qemu-system-arm`. Инструкции по настройке окружения для разработки
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
# The `app` attribute
|
# The `app` attribute
|
||||||
|
|
||||||
Это наименьшая возможная программа на RTFM:
|
Это наименьшая возможная программа на RTIC:
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
{{#include ../../../../examples/smallest.rs}}
|
{{#include ../../../../examples/smallest.rs}}
|
||||||
```
|
```
|
||||||
|
|
||||||
Все программы на RTFM используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
|
Все программы на RTIC используют атрибут [`app`] (`#[app(..)]`). Этот атрибут
|
||||||
нужно применять к `const`-элементам, содержащим элементы. Атрибут `app` имеет
|
нужно применять к `const`-элементам, содержащим элементы. Атрибут `app` имеет
|
||||||
обязательный аргумент `device`, в качестве значения которому передается *путь*.
|
обязательный аргумент `device`, в качестве значения которому передается *путь*.
|
||||||
Этот путь должен указывать на библиотеку *устройства*, сгенерированную с помощью
|
Этот путь должен указывать на библиотеку *устройства*, сгенерированную с помощью
|
||||||
[`svd2rust`] **v0.14.x**. Атрибут `app` развернется в удобную точку входа,
|
[`svd2rust`] **v0.14.x**. Атрибут `app` развернется в удобную точку входа,
|
||||||
поэтому нет необходимости использовать атрибут [`cortex_m_rt::entry`].
|
поэтому нет необходимости использовать атрибут [`cortex_m_rt::entry`].
|
||||||
|
|
||||||
[`app`]: ../../../api/cortex_m_rtfm_macros/attr.app.html
|
[`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html
|
||||||
[`svd2rust`]: https://crates.io/crates/svd2rust
|
[`svd2rust`]: https://crates.io/crates/svd2rust
|
||||||
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
[`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html
|
||||||
|
|
||||||
> **ОТСТУПЛЕНИЕ**: Некоторые из вас удивятся, почему мы используем ключевое слово `const` как
|
> **ОТСТУПЛЕНИЕ**: Некоторые из вас удивятся, почему мы используем ключевое слово `const` как
|
||||||
> модуль, а не правильное `mod`. Причина в том, что использование атрибутов на
|
> модуль, а не правильное `mod`. Причина в том, что использование атрибутов на
|
||||||
> модулях требует feature gate, который требует ночную сборку. Чтобы заставить
|
> модулях требует feature gate, который требует ночную сборку. Чтобы заставить
|
||||||
> RTFM работать на стабильной сборке, мы используем вместо него слово `const`.
|
> RTIC работать на стабильной сборке, мы используем вместо него слово `const`.
|
||||||
> Когда большая часть макросов 1.2 стабилизируются, мы прейдем от `const` к `mod` и в конце концов в атрибуту уровне приложения (`#![app]`).
|
> Когда большая часть макросов 1.2 стабилизируются, мы прейдем от `const` к `mod` и в конце концов в атрибуту уровне приложения (`#![app]`).
|
||||||
|
|
||||||
## `init`
|
## `init`
|
||||||
|
@ -32,13 +32,13 @@
|
||||||
Функция `init` запустится *с отключенными прерываниями* и будет иметь эксклюзивный
|
Функция `init` запустится *с отключенными прерываниями* и будет иметь эксклюзивный
|
||||||
доступ к периферии Cortex-M и специфичной для устройства периферии через переменные
|
доступ к периферии Cortex-M и специфичной для устройства периферии через переменные
|
||||||
`core` and `device`, которые внедряются в область видимости `init` атрибутом `app`.
|
`core` and `device`, которые внедряются в область видимости `init` атрибутом `app`.
|
||||||
Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTFM принимает владение
|
Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTIC принимает владение
|
||||||
частью из неё -- более подробно см. структуру [`rtfm::Peripherals`].
|
частью из неё -- более подробно см. структуру [`rtic::Peripherals`].
|
||||||
|
|
||||||
Переменные `static mut`, определённые в начале `init` будут преобразованы
|
Переменные `static mut`, определённые в начале `init` будут преобразованы
|
||||||
в ссылки `&'static mut` с безопасным доступом.
|
в ссылки `&'static mut` с безопасным доступом.
|
||||||
|
|
||||||
[`rtfm::Peripherals`]: ../../api/rtfm/struct.Peripherals.html
|
[`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html
|
||||||
|
|
||||||
Пример ниже показывает типы переменных `core` и `device` и
|
Пример ниже показывает типы переменных `core` и `device` и
|
||||||
демонстрирует безопасный доступ к переменной `static mut`.
|
демонстрирует безопасный доступ к переменной `static mut`.
|
||||||
|
@ -85,7 +85,7 @@ $ cargo run --example idle
|
||||||
|
|
||||||
Как Вы бы сделали с помощью библиотеки `cortex-m-rt`, Вы можете использовать атрибуты
|
Как Вы бы сделали с помощью библиотеки `cortex-m-rt`, Вы можете использовать атрибуты
|
||||||
`interrupt` и `exception` внутри псевдо-модуля `app`, чтобы определить обработчики
|
`interrupt` и `exception` внутри псевдо-модуля `app`, чтобы определить обработчики
|
||||||
прерываний и исключений. В RTFM, мы называем обработчики прерываний и исключений
|
прерываний и исключений. В RTIC, мы называем обработчики прерываний и исключений
|
||||||
*аппаратными* задачами.
|
*аппаратными* задачами.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
|
@ -96,6 +96,6 @@ $ cargo run --example idle
|
||||||
$ cargo run --example interrupt
|
$ cargo run --example interrupt
|
||||||
{{#include ../../../../ci/expected/interrupt.run}}```
|
{{#include ../../../../ci/expected/interrupt.run}}```
|
||||||
|
|
||||||
До сих пор программы RTFM, которые мы видели не отличались от программ, которые
|
До сих пор программы RTIC, которые мы видели не отличались от программ, которые
|
||||||
можно написать, используя только библиотеку `cortex-m-rt`. В следующем разделе
|
можно написать, используя только библиотеку `cortex-m-rt`. В следующем разделе
|
||||||
мы начнем знакомиться с функционалом, присущим только RTFM.
|
мы начнем знакомиться с функционалом, присущим только RTIC.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Создание нового проекта
|
# Создание нового проекта
|
||||||
|
|
||||||
Теперь, когда Вы изучили основные возможности фреймворка RTFM, Вы можете
|
Теперь, когда Вы изучили основные возможности фреймворка RTIC, Вы можете
|
||||||
попробовать его использовать на Вашем оборудовании следуя этим инструкциям.
|
попробовать его использовать на Вашем оборудовании следуя этим инструкциям.
|
||||||
|
|
||||||
1. Создайте экземпляр из шаблона [`cortex-m-quickstart`].
|
1. Создайте экземпляр из шаблона [`cortex-m-quickstart`].
|
||||||
|
@ -36,20 +36,20 @@ $ cargo add lm3s6965 --vers 0.1.3
|
||||||
$ rm memory.x build.rs
|
$ rm memory.x build.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Добавьте библиотеку `cortex-m-rtfm` как зависимость, и если необходимо,
|
3. Добавьте библиотеку `cortex-m-rtic` как зависимость, и если необходимо,
|
||||||
включите опцию `timer-queue`.
|
включите опцию `timer-queue`.
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ cargo add cortex-m-rtfm --allow-prerelease --upgrade=none
|
$ cargo add cortex-m-rtic --allow-prerelease --upgrade=none
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Напишите программу RTFM.
|
4. Напишите программу RTIC.
|
||||||
|
|
||||||
Здесь я буду использовать пример `init` из библиотеки `cortex-m-rtfm`.
|
Здесь я буду использовать пример `init` из библиотеки `cortex-m-rtic`.
|
||||||
|
|
||||||
``` console
|
``` console
|
||||||
$ curl \
|
$ curl \
|
||||||
-L https://github.com/japaric/cortex-m-rtfm/raw/v0.4.0-beta.1/examples/init.rs \
|
-L https://github.com/japaric/cortex-m-rtic/raw/v0.4.0-beta.1/examples/init.rs \
|
||||||
> src/main.rs
|
> src/main.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
|
достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
|
||||||
|
|
||||||
Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
|
Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
|
||||||
`static`-переменным. В RTFM мы обращаемся к `static`-переменным, объявленным внутри
|
`static`-переменным. В RTIC мы обращаемся к `static`-переменным, объявленным внутри
|
||||||
псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
|
псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
|
||||||
(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
|
(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
|
||||||
аргумент `resources` в соответствующем атрибуте.
|
аргумент `resources` в соответствующем атрибуте.
|
||||||
|
@ -45,13 +45,13 @@ $ cargo run --example resource
|
||||||
критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
|
критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
|
||||||
доступ к ресурсу.
|
доступ к ресурсу.
|
||||||
|
|
||||||
API критической секции, предоставляемое фреймворком RTFM (см. [`Mutex`]),
|
API критической секции, предоставляемое фреймворком RTIC (см. [`Mutex`]),
|
||||||
основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
|
основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
|
||||||
что критические секции не будут допускать *запуск некоторых* обработчиков,
|
что критические секции не будут допускать *запуск некоторых* обработчиков,
|
||||||
включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
|
включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
|
||||||
большим приоритетом не соперничащих за ресурс.
|
большим приоритетом не соперничащих за ресурс.
|
||||||
|
|
||||||
[`Mutex`]: ../../../api/rtfm/trait.Mutex.html
|
[`Mutex`]: ../../../api/rtic/trait.Mutex.html
|
||||||
|
|
||||||
В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
|
В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
|
||||||
до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
|
до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
|
||||||
|
@ -61,7 +61,7 @@ API критической секции, предоставляемое фрей
|
||||||
с наивысшим приоритетом может свободно вытеснять критическую секцию,
|
с наивысшим приоритетом может свободно вытеснять критическую секцию,
|
||||||
созданную обработчиком с низшим приоритетом.
|
созданную обработчиком с низшим приоритетом.
|
||||||
|
|
||||||
[`lock`]: ../../../api/rtfm/trait.Mutex.html#method.lock
|
[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
{{#include ../../../../examples/lock.rs}}
|
{{#include ../../../../examples/lock.rs}}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# Программные задачи
|
# Программные задачи
|
||||||
|
|
||||||
RTFM обрабатывает прерывания и исключения как *аппаратные* задачи. Аппаратные
|
RTIC обрабатывает прерывания и исключения как *аппаратные* задачи. Аппаратные
|
||||||
задачи могут вызываться устройством в ответ на события, такие как нажатие кнопки.
|
задачи могут вызываться устройством в ответ на события, такие как нажатие кнопки.
|
||||||
RTFM также поддерживает *программные* задачи, порождаемые программой из любого
|
RTIC также поддерживает *программные* задачи, порождаемые программой из любого
|
||||||
контекста выполнения.
|
контекста выполнения.
|
||||||
|
|
||||||
Программным задачам также можно назначать приоритет и диспетчеризовать из
|
Программным задачам также можно назначать приоритет и диспетчеризовать из
|
||||||
обработчиков прерываний. RTFM требует определения свободных прерываний в блоке
|
обработчиков прерываний. RTIC требует определения свободных прерываний в блоке
|
||||||
`extern`, когда используются программные задачи; эти свободные прерывания будут использованы, чтобы диспетчеризовать программные задачи. Преимущество программных
|
`extern`, когда используются программные задачи; эти свободные прерывания будут использованы, чтобы диспетчеризовать программные задачи. Преимущество программных
|
||||||
задач перед аппаратными в том, что на один обработчик прерывания можно назначить
|
задач перед аппаратными в том, что на один обработчик прерывания можно назначить
|
||||||
множество задач.
|
множество задач.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Очередь таймера
|
# Очередь таймера
|
||||||
|
|
||||||
Когда включена опция `timer-queue`, фреймворк RTFM включает
|
Когда включена опция `timer-queue`, фреймворк RTIC включает
|
||||||
*глобальную очередь таймера*, которую приложения могут использовать, чтобы
|
*глобальную очередь таймера*, которую приложения могут использовать, чтобы
|
||||||
*планировать* программные задачи на запуск через некоторое время в будущем.
|
*планировать* программные задачи на запуск через некоторое время в будущем.
|
||||||
|
|
||||||
|
@ -9,16 +9,16 @@
|
||||||
планируется, момент ([`Instant`]), в который задачу нужно запустить, нужно передать
|
планируется, момент ([`Instant`]), в который задачу нужно запустить, нужно передать
|
||||||
как первый аргумент вызова `schedule`.
|
как первый аргумент вызова `schedule`.
|
||||||
|
|
||||||
[`Instant`]: ../../../api/rtfm/struct.Instant.html
|
[`Instant`]: ../../../api/rtic/struct.Instant.html
|
||||||
|
|
||||||
Рантайм RTFM включает монотонный, растущий только вверх, 32-битный таймер,
|
Рантайм RTIC включает монотонный, растущий только вверх, 32-битный таймер,
|
||||||
значение которого можно запросить конструктором `Instant::now`. Время ([`Duration`])
|
значение которого можно запросить конструктором `Instant::now`. Время ([`Duration`])
|
||||||
можно передать в `Instant::now()`, чтобы получить `Instant` в будущем. Монотонный
|
можно передать в `Instant::now()`, чтобы получить `Instant` в будущем. Монотонный
|
||||||
таймер отключен пока запущен `init`, поэтому `Instant::now()` всегда возвращает
|
таймер отключен пока запущен `init`, поэтому `Instant::now()` всегда возвращает
|
||||||
значение `Instant(0 /* циклов тактовой частоты */)`; таймер включается сразу перед
|
значение `Instant(0 /* циклов тактовой частоты */)`; таймер включается сразу перед
|
||||||
включением прерываний и запуском `idle`.
|
включением прерываний и запуском `idle`.
|
||||||
|
|
||||||
[`Duration`]: ../../../api/rtfm/struct.Duration.html
|
[`Duration`]: ../../../api/rtic/struct.Duration.html
|
||||||
|
|
||||||
В примере ниже две задачи планируются из `init`: `foo` и `bar`. `foo` -
|
В примере ниже две задачи планируются из `init`: `foo` и `bar`. `foo` -
|
||||||
запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, `bar`
|
запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, `bar`
|
||||||
|
|
|
@ -22,8 +22,8 @@ $ cargo run --example generics
|
||||||
|
|
||||||
## Запуск задач из ОЗУ
|
## Запуск задач из ОЗУ
|
||||||
|
|
||||||
Главной целью переноса описания программы на RTFM в атрибуты в
|
Главной целью переноса описания программы на RTIC в атрибуты в
|
||||||
RTFM v0.4.x была возможность взаимодействия с другими атрибутами.
|
RTIC v0.4.x была возможность взаимодействия с другими атрибутами.
|
||||||
Напримерe, атрибут `link_section` можно применять к задачам, чтобы разместить
|
Напримерe, атрибут `link_section` можно применять к задачам, чтобы разместить
|
||||||
их в ОЗУ; это может улучшить производительность в некоторых случаях.
|
их в ОЗУ; это может улучшить производительность в некоторых случаях.
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ $ cargo nm --example ramfunc --release | grep ' bar::'
|
||||||
|
|
||||||
## `binds`
|
## `binds`
|
||||||
|
|
||||||
**ПРИМЕЧАНИЕ**: Требуется RTFM не ниже 0.4.2
|
**ПРИМЕЧАНИЕ**: Требуется RTIC не ниже 0.4.2
|
||||||
|
|
||||||
Вы можете давать аппаратным задачам имена похожие на имена обычных задач.
|
Вы можете давать аппаратным задачам имена похожие на имена обычных задач.
|
||||||
Для этого нужно использовать аргумент `binds`: Вы называете функцию
|
Для этого нужно использовать аргумент `binds`: Вы называете функцию
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
## `Send`
|
## `Send`
|
||||||
|
|
||||||
[`Send`] - маркерный типаж (trait) для "типов, которые можно передавать через границы
|
[`Send`] - маркерный типаж (trait) для "типов, которые можно передавать через границы
|
||||||
потоков", как это определено в `core`. В контексте RTFM типаж `Send` необходим
|
потоков", как это определено в `core`. В контексте RTIC типаж `Send` необходим
|
||||||
только там, где возможна передача значения между задачами, запускаемыми на
|
только там, где возможна передача значения между задачами, запускаемыми на
|
||||||
*разных* приоритетах. Это возникает в нескольких случаях: при передаче сообщений,
|
*разных* приоритетах. Это возникает в нескольких случаях: при передаче сообщений,
|
||||||
в совместно используемых `static mut` ресурсах и инициализации поздних ресурсов.
|
в совместно используемых `static mut` ресурсах и инициализации поздних ресурсов.
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
## `Sync`
|
## `Sync`
|
||||||
|
|
||||||
Похожая ситуация, [`Sync`] - маркерный типаж для "типов, на которых можно
|
Похожая ситуация, [`Sync`] - маркерный типаж для "типов, на которых можно
|
||||||
ссылаться в разных потоках", как это определено в `core`. В контексте RTFM
|
ссылаться в разных потоках", как это определено в `core`. В контексте RTIC
|
||||||
типаж `Sync` необходим только там, где возможны две или более задачи,
|
типаж `Sync` необходим только там, где возможны две или более задачи,
|
||||||
запускаемые на разных приоритетах, чтобы захватить разделяемую ссылку на
|
запускаемые на разных приоритетах, чтобы захватить разделяемую ссылку на
|
||||||
ресурс. Это возникает только совместно используемых `static`-ресурсах.
|
ресурс. Это возникает только совместно используемых `static`-ресурсах.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<h1 align="center">Real Time For the Masses</h1>
|
<h1 align="center">Real-Time Interrupt-driven Concurrency</h1>
|
||||||
|
|
||||||
<p align="center">Конкурентный фреймворк для создания систем реального времени</p>
|
<p align="center">Конкурентный фреймворк для создания систем реального времени</p>
|
||||||
|
|
||||||
# Введение
|
# Введение
|
||||||
|
|
||||||
Эта книга содержит документацию уровня пользователя фреймворком Real Time For the Masses
|
Эта книга содержит документацию уровня пользователя фреймворком Real-Time Interrupt-driven Concurrency
|
||||||
(RTFM). Описание API можно найти [здесь](../../api/rtfm/index.html).
|
(RTIC). Описание API можно найти [здесь](../../api/rtic/index.html).
|
||||||
|
|
||||||
{{#include README_RU.md:5:44}}
|
{{#include README_RU.md:5:44}}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ main() {
|
||||||
# build latest docs
|
# build latest docs
|
||||||
mkdir -p $td/$latest/book/
|
mkdir -p $td/$latest/book/
|
||||||
cp -r target/doc $td/$latest/api
|
cp -r target/doc $td/$latest/api
|
||||||
sed 's|URL|rtfm/index.html|g' redirect.html > $td/$latest/api/index.html
|
sed 's|URL|rtic/index.html|g' redirect.html > $td/$latest/api/index.html
|
||||||
|
|
||||||
sed 's|URL|0.5|g' redirect.html > $td/index.html
|
sed 's|URL|0.5|g' redirect.html > $td/index.html
|
||||||
sed 's|URL|book/en|g' redirect.html > $td/$latest/index.html
|
sed 's|URL|book/en|g' redirect.html > $td/$latest/index.html
|
||||||
|
@ -30,13 +30,13 @@ main() {
|
||||||
|
|
||||||
mkdir -p $td/$prefix/book
|
mkdir -p $td/$prefix/book
|
||||||
local src=$(mktemp -d)
|
local src=$(mktemp -d)
|
||||||
curl -L https://github.com/rtfm-rs/cortex-m-rtfm/archive/v${ver}.tar.gz | tar xz --strip-components 1 -C $src
|
curl -L https://github.com/rtic-rs/cortex-m-rtic/archive/v${ver}.tar.gz | tar xz --strip-components 1 -C $src
|
||||||
|
|
||||||
pushd $src
|
pushd $src
|
||||||
rm -f .cargo/config
|
rm -f .cargo/config
|
||||||
cargo doc || cargo doc --features timer-queue
|
cargo doc || cargo doc --features timer-queue
|
||||||
cp -r target/doc $td/$prefix/api
|
cp -r target/doc $td/$prefix/api
|
||||||
sed 's|URL|rtfm/index.html|g' $root/redirect.html > $td/$prefix/api/index.html
|
sed 's|URL|rtic/index.html|g' $root/redirect.html > $td/$prefix/api/index.html
|
||||||
for lang in ${langs[@]}; do
|
for lang in ${langs[@]}; do
|
||||||
( cd book/$lang && mdbook build )
|
( cd book/$lang && mdbook build )
|
||||||
cp -r book/$lang/book $td/$prefix/book/$lang
|
cp -r book/$lang/book $td/$prefix/book/$lang
|
||||||
|
@ -58,7 +58,7 @@ main() {
|
||||||
./ghp-import/ghp_import.py $td
|
./ghp-import/ghp_import.py $td
|
||||||
|
|
||||||
set +x
|
set +x
|
||||||
git push -fq https://$GH_TOKEN@github.com/rtfm-rs/cortex-m-rtfm.git gh-pages && echo OK
|
git push -fq https://$GH_TOKEN@github.com/rtic-rs/cortex-m-rtic.git gh-pages && echo OK
|
||||||
|
|
||||||
rm -rf $td
|
rm -rf $td
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,8 +89,8 @@ main() {
|
||||||
|
|
||||||
linkchecker $td/book/en/
|
linkchecker $td/book/en/
|
||||||
linkchecker $td/book/ru/
|
linkchecker $td/book/ru/
|
||||||
linkchecker $td/api/rtfm/
|
linkchecker $td/api/rtic/
|
||||||
linkchecker $td/api/cortex_m_rtfm_macros/
|
linkchecker $td/api/cortex_m_rtic_macros/
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
// NOTE: does NOT properly work on QEMU
|
// NOTE: does NOT properly work on QEMU
|
||||||
#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
|
@ -31,7 +31,7 @@ const APP: () = {
|
||||||
if *ONCE {
|
if *ONCE {
|
||||||
*ONCE = false;
|
*ONCE = false;
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
} else {
|
} else {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,11 @@ use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
// `examples/interrupt.rs` rewritten to use `binds`
|
// `examples/interrupt.rs` rewritten to use `binds`
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ const APP: () = {
|
||||||
fn idle(_: idle::Context) -> ! {
|
fn idle(_: idle::Context) -> ! {
|
||||||
hprintln!("idle").unwrap();
|
hprintln!("idle").unwrap();
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, spawn = [foo, bar])]
|
#[task(binds = UART0, spawn = [foo, bar])]
|
||||||
|
|
|
@ -10,7 +10,7 @@ use cortex_m_semihosting::debug;
|
||||||
use cortex_m_semihosting::hprintln;
|
use cortex_m_semihosting::hprintln;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[cfg(debug_assertions)] // <- `true` when using the `dev` profile
|
#[cfg(debug_assertions)] // <- `true` when using the `dev` profile
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::hprintln;
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// Some resources to work with
|
// Some resources to work with
|
||||||
|
@ -23,8 +23,8 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct destructure
|
// Direct destructure
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
use rtfm::{Exclusive, Mutex};
|
use rtic::{Exclusive, Mutex};
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -19,8 +19,8 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, resources = [shared])]
|
#[task(binds = UART0, resources = [shared])]
|
||||||
|
@ -32,7 +32,7 @@ const APP: () = {
|
||||||
// second argument has type `resources::shared`
|
// second argument has type `resources::shared`
|
||||||
advance(STATE, c.resources.shared);
|
advance(STATE, c.resources.shared);
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||||
// `init` returns because interrupts are disabled
|
// `init` returns because interrupts are disabled
|
||||||
rtfm::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
||||||
|
|
||||||
hprintln!("init").unwrap();
|
hprintln!("init").unwrap();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ const APP: () = {
|
||||||
|
|
||||||
hprintln!("idle").unwrap();
|
hprintln!("idle").unwrap();
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965, peripherals = true)]
|
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use heapless::{
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
// Late resources
|
// Late resources
|
||||||
struct Resources {
|
struct Resources {
|
||||||
|
@ -40,7 +40,7 @@ const APP: () = {
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -18,7 +18,7 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::GPIOA);
|
rtic::pend(Interrupt::GPIOA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when omitted priority is assumed to be `1`
|
// when omitted priority is assumed to be `1`
|
||||||
|
@ -32,12 +32,12 @@ const APP: () = {
|
||||||
*shared += 1;
|
*shared += 1;
|
||||||
|
|
||||||
// GPIOB will *not* run right now due to the critical section
|
// GPIOB will *not* run right now due to the critical section
|
||||||
rtfm::pend(Interrupt::GPIOB);
|
rtic::pend(Interrupt::GPIOB);
|
||||||
|
|
||||||
hprintln!("B - shared = {}", *shared).unwrap();
|
hprintln!("B - shared = {}", *shared).unwrap();
|
||||||
|
|
||||||
// GPIOC does not contend for `shared` so it's allowed to run now
|
// GPIOC does not contend for `shared` so it's allowed to run now
|
||||||
rtfm::pend(Interrupt::GPIOC);
|
rtic::pend(Interrupt::GPIOC);
|
||||||
});
|
});
|
||||||
|
|
||||||
// critical section is over: GPIOB can now start
|
// critical section is over: GPIOB can now start
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use core::marker::PhantomData;
|
||||||
|
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use rtfm::app;
|
use rtic::app;
|
||||||
|
|
||||||
pub struct NotSend {
|
pub struct NotSend {
|
||||||
_0: PhantomData<*const ()>,
|
_0: PhantomData<*const ()>,
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub struct NotSync {
|
||||||
_0: PhantomData<*const ()>,
|
_0: PhantomData<*const ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(NotSync { _0: PhantomData })]
|
#[init(NotSync { _0: PhantomData })]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
key: u32,
|
key: u32,
|
||||||
|
@ -17,8 +17,8 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) -> init::LateResources {
|
fn init(_: init::Context) -> init::LateResources {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
|
|
||||||
init::LateResources { key: 0xdeadbeef }
|
init::LateResources { key: 0xdeadbeef }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
|
|
||||||
use cortex_m_semihosting::hprintln;
|
use cortex_m_semihosting::hprintln;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
use rtfm::cyccnt::{Instant, U32Ext};
|
use rtic::cyccnt::{Instant, U32Ext};
|
||||||
|
|
||||||
const PERIOD: u32 = 8_000_000;
|
const PERIOD: u32 = 8_000_000;
|
||||||
|
|
||||||
// NOTE: does NOT work on QEMU!
|
// NOTE: does NOT work on QEMU!
|
||||||
#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(schedule = [foo])]
|
#[init(schedule = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use heapless::{
|
||||||
};
|
};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
use rtfm::app;
|
use rtic::app;
|
||||||
|
|
||||||
// Declare a pool of 128-byte memory blocks
|
// Declare a pool of 128-byte memory blocks
|
||||||
pool!(P: [u8; 128]);
|
pool!(P: [u8; 128]);
|
||||||
|
@ -26,7 +26,7 @@ const APP: () = {
|
||||||
// Increase the capacity of the memory pool by ~4
|
// Increase the capacity of the memory pool by ~4
|
||||||
P::grow(MEMORY);
|
P::grow(MEMORY);
|
||||||
|
|
||||||
rtfm::pend(Interrupt::I2C0);
|
rtic::pend(Interrupt::I2C0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
|
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
|
||||||
|
|
|
@ -6,19 +6,19 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
use rtfm::app;
|
use rtic::app;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::GPIOA);
|
rtic::pend(Interrupt::GPIOA);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = GPIOA, priority = 1)]
|
#[task(binds = GPIOA, priority = 1)]
|
||||||
fn gpioa(_: gpioa::Context) {
|
fn gpioa(_: gpioa::Context) {
|
||||||
hprintln!("GPIOA - start").unwrap();
|
hprintln!("GPIOA - start").unwrap();
|
||||||
rtfm::pend(Interrupt::GPIOC);
|
rtic::pend(Interrupt::GPIOC);
|
||||||
hprintln!("GPIOA - end").unwrap();
|
hprintln!("GPIOA - end").unwrap();
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ const APP: () = {
|
||||||
#[task(binds = GPIOC, priority = 2)]
|
#[task(binds = GPIOC, priority = 2)]
|
||||||
fn gpioc(_: gpioc::Context) {
|
fn gpioc(_: gpioc::Context) {
|
||||||
hprintln!(" GPIOC - start").unwrap();
|
hprintln!(" GPIOC - start").unwrap();
|
||||||
rtfm::pend(Interrupt::GPIOB);
|
rtic::pend(Interrupt::GPIOB);
|
||||||
hprintln!(" GPIOC - end").unwrap();
|
hprintln!(" GPIOC - end").unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [bar])]
|
#[init(spawn = [bar])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln};
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// A resource
|
// A resource
|
||||||
|
@ -19,8 +19,8 @@ const APP: () = {
|
||||||
|
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtic::pend(Interrupt::UART1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `shared` cannot be accessed from this context
|
// `shared` cannot be accessed from this context
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
use cortex_m::peripheral::DWT;
|
use cortex_m::peripheral::DWT;
|
||||||
use cortex_m_semihosting::hprintln;
|
use cortex_m_semihosting::hprintln;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use rtfm::cyccnt::{Instant, U32Ext as _};
|
use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
|
|
||||||
// NOTE: does NOT work on QEMU!
|
// NOTE: does NOT work on QEMU!
|
||||||
#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(schedule = [foo, bar])]
|
#[init(schedule = [foo, bar])]
|
||||||
fn init(mut cx: init::Context) {
|
fn init(mut cx: init::Context) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use lm3s6965::Interrupt;
|
use lm3s6965::Interrupt;
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use rtfm::app;
|
use rtic::app;
|
||||||
|
|
||||||
pub struct MustBeSend;
|
pub struct MustBeSend;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ const APP: () = {
|
||||||
let message = MustBeSend;
|
let message = MustBeSend;
|
||||||
*c.resources.shared = Some(message);
|
*c.resources.shared = Some(message);
|
||||||
|
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtic::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0, resources = [shared])]
|
#[task(binds = UART0, resources = [shared])]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use panic_semihosting as _; // panic handler
|
use panic_semihosting as _; // panic handler
|
||||||
use rtfm::app;
|
use rtic::app;
|
||||||
|
|
||||||
#[app(device = lm3s6965)]
|
#[app(device = lm3s6965)]
|
||||||
const APP: () = {};
|
const APP: () = {};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// A resource
|
// A resource
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {
|
fn init(_: init::Context) {
|
||||||
rtfm::pend(lm3s6965::Interrupt::UART0)
|
rtic::pend(lm3s6965::Interrupt::UART0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn main(_: main::Context) {
|
fn main(_: main::Context) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct NotSend {
|
||||||
_0: PhantomData<*const ()>,
|
_0: PhantomData<*const ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: NotSend,
|
x: NotSend,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
use rtfm::cyccnt::{Instant, U32Ext as _};
|
use rtic::cyccnt::{Instant, U32Ext as _};
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(schedule = [foo, bar, baz])]
|
#[init(schedule = [foo, bar, baz])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [foo, bar, baz])]
|
#[init(spawn = [foo, bar, baz])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [main])]
|
#[init(spawn = [main])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtic::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(spawn = [foo])]
|
#[init(spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use panic_semihosting as _;
|
use panic_semihosting as _;
|
||||||
use rtfm::cyccnt;
|
use rtic::cyccnt;
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965, peripherals = true, monotonic = rtfm::cyccnt::CYCCNT)]
|
#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
#[init(0)]
|
#[init(0)]
|
||||||
|
@ -19,7 +19,7 @@ const APP: () = {
|
||||||
#[init(schedule = [foo], spawn = [foo])]
|
#[init(schedule = [foo], spawn = [foo])]
|
||||||
fn init(cx: init::Context) {
|
fn init(cx: init::Context) {
|
||||||
let _: cyccnt::Instant = cx.start;
|
let _: cyccnt::Instant = cx.start;
|
||||||
let _: rtfm::Peripherals = cx.core;
|
let _: rtic::Peripherals = cx.core;
|
||||||
let _: lm3s6965::Peripherals = cx.device;
|
let _: lm3s6965::Peripherals = cx.device;
|
||||||
let _: init::Schedule = cx.schedule;
|
let _: init::Schedule = cx.schedule;
|
||||||
let _: init::Spawn = cx.spawn;
|
let _: init::Spawn = cx.spawn;
|
||||||
|
|
|
@ -9,7 +9,7 @@ version = "0.0.0-alpha.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bare-metal = "0.2.4"
|
bare-metal = "0.2.4"
|
||||||
|
|
||||||
[dependencies.cortex-m-rtfm]
|
[dependencies.cortex-m-rtic]
|
||||||
path = ".."
|
path = ".."
|
||||||
features = ["heterogeneous"]
|
features = ["heterogeneous"]
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = heterogeneous)]
|
#[rtic::app(cores = 2, device = heterogeneous)]
|
||||||
const APP: () = {};
|
const APP: () = {};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = heterogeneous)]
|
#[rtic::app(cores = 2, device = heterogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// owned by core #1 but initialized by core #0
|
// owned by core #1 but initialized by core #0
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = heterogeneous)]
|
#[rtic::app(cores = 2, device = heterogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: u32,
|
x: u32,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = heterogeneous, monotonic = heterogeneous::MT)]
|
#[rtic::app(cores = 2, device = heterogeneous, monotonic = heterogeneous::MT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(core = 0, spawn = [ping])]
|
#[init(core = 0, spawn = [ping])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = heterogeneous)]
|
#[rtic::app(cores = 2, device = heterogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(core = 0, spawn = [foo])]
|
#[init(core = 0, spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use bare_metal::Nr;
|
use bare_metal::Nr;
|
||||||
use rtfm::{Fraction, Monotonic, MultiCore};
|
use rtic::{Fraction, Monotonic, MultiCore};
|
||||||
|
|
||||||
// both cores have the exact same interrupts
|
// both cores have the exact same interrupts
|
||||||
pub use Interrupt_0 as Interrupt_1;
|
pub use Interrupt_0 as Interrupt_1;
|
||||||
|
|
|
@ -9,7 +9,7 @@ version = "0.0.0-alpha.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bare-metal = "0.2.4"
|
bare-metal = "0.2.4"
|
||||||
|
|
||||||
[dependencies.cortex-m-rtfm]
|
[dependencies.cortex-m-rtic]
|
||||||
path = ".."
|
path = ".."
|
||||||
features = ["homogeneous"]
|
features = ["homogeneous"]
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = homogeneous)]
|
#[rtic::app(cores = 2, device = homogeneous)]
|
||||||
const APP: () = {};
|
const APP: () = {};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = homogeneous)]
|
#[rtic::app(cores = 2, device = homogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
// owned by core #1 but initialized by core #0
|
// owned by core #1 but initialized by core #0
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = homogeneous)]
|
#[rtic::app(cores = 2, device = homogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
struct Resources {
|
struct Resources {
|
||||||
x: u32,
|
x: u32,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = homogeneous, monotonic = homogeneous::MT)]
|
#[rtic::app(cores = 2, device = homogeneous, monotonic = homogeneous::MT)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(core = 0, spawn = [ping])]
|
#[init(core = 0, spawn = [ping])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use panic_halt as _;
|
use panic_halt as _;
|
||||||
|
|
||||||
#[rtfm::app(cores = 2, device = homogeneous)]
|
#[rtic::app(cores = 2, device = homogeneous)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[init(core = 0, spawn = [foo])]
|
#[init(core = 0, spawn = [foo])]
|
||||||
fn init(c: init::Context) {
|
fn init(c: init::Context) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use core::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use bare_metal::Nr;
|
use bare_metal::Nr;
|
||||||
use rtfm::{Fraction, Monotonic, MultiCore};
|
use rtic::{Fraction, Monotonic, MultiCore};
|
||||||
|
|
||||||
// both cores have the exact same interrupts
|
// both cores have the exact same interrupts
|
||||||
pub use Interrupt_0 as Interrupt_1;
|
pub use Interrupt_0 as Interrupt_1;
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
[package]
|
[package]
|
||||||
authors = [
|
authors = [
|
||||||
"The Real Time For the Masses developers",
|
"The Real-Time Interrupt-driven Concurrency developers",
|
||||||
"Jorge Aparicio <jorge@japaric.io>",
|
"Jorge Aparicio <jorge@japaric.io>",
|
||||||
]
|
]
|
||||||
categories = ["concurrency", "embedded", "no-std"]
|
categories = ["concurrency", "embedded", "no-std"]
|
||||||
description = "Procedural macros of the cortex-m-rtfm crate"
|
description = "Procedural macros of the cortex-m-rtic crate"
|
||||||
documentation = "https://rtfm-rs.github.io/cortex-m-rtfm/api/cortex_m_rtfm"
|
documentation = "https://rtic-rs.github.io/cortex-m-rtic/api/cortex_m_rtic"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
keywords = ["arm", "cortex-m"]
|
keywords = ["arm", "cortex-m"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
name = "cortex-m-rtfm-macros"
|
name = "cortex-m-rtic-macros"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
repository = "https://github.com/rtfm-rs/cortex-m-rtfm"
|
repository = "https://github.com/rtic-rs/cortex-m-rtic"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -21,7 +21,7 @@ proc-macro = true
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
rtfm-syntax = "0.4.0"
|
rtic-syntax = "0.4.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
heterogeneous = []
|
heterogeneous = []
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use core::ops;
|
use core::ops;
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
use rtfm_syntax::{
|
use rtic_syntax::{
|
||||||
analyze::{self, Priority},
|
analyze::{self, Priority},
|
||||||
ast::App,
|
ast::App,
|
||||||
Core, P,
|
Core, P,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use rtfm_syntax::{
|
use rtic_syntax::{
|
||||||
analyze::Analysis,
|
analyze::Analysis,
|
||||||
ast::{App, CustomArg},
|
ast::{App, CustomArg},
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@ impl<'a> Extra<'a> {
|
||||||
|
|
||||||
pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
if cfg!(feature = "homogeneous") {
|
if cfg!(feature = "homogeneous") {
|
||||||
// this RTFM mode uses the same namespace for all cores so we need to check that the
|
// this RTIC mode uses the same namespace for all cores so we need to check that the
|
||||||
// identifiers used for each core `#[init]` and `#[idle]` functions don't collide
|
// identifiers used for each core `#[init]` and `#[idle]` functions don't collide
|
||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
} else {
|
} else {
|
||||||
Err(parse::Error::new(
|
Err(parse::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
"a `device` argument must be specified in `#[rtfm::app]`",
|
"a `device` argument must be specified in `#[rtic::app]`",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtfm_syntax::ast::App;
|
use rtic_syntax::ast::App;
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra};
|
use crate::{analyze::Analysis, check::Extra};
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ mod spawn_body;
|
||||||
mod timer_queue;
|
mod timer_queue;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
// TODO document the syntax here or in `rtfm-syntax`
|
// TODO document the syntax here or in `rtic-syntax`
|
||||||
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let mut const_app = vec![];
|
let mut const_app = vec![];
|
||||||
let mut mains = vec![];
|
let mut mains = vec![];
|
||||||
|
|
|
@ -12,13 +12,13 @@ pub fn codegen(core: u8, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2
|
||||||
|
|
||||||
if let Some(types) = analysis.send_types.get(&core) {
|
if let Some(types) = analysis.send_types.get(&core) {
|
||||||
for ty in types {
|
for ty in types {
|
||||||
stmts.push(quote!(rtfm::export::assert_send::<#ty>();));
|
stmts.push(quote!(rtic::export::assert_send::<#ty>();));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(types) = analysis.sync_types.get(&core) {
|
if let Some(types) = analysis.sync_types.get(&core) {
|
||||||
for ty in types {
|
for ty in types {
|
||||||
stmts.push(quote!(rtfm::export::assert_sync::<#ty>();));
|
stmts.push(quote!(rtic::export::assert_sync::<#ty>();));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ pub fn codegen(core: u8, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2
|
||||||
// `monotonic` timer can be used in multi-core context
|
// `monotonic` timer can be used in multi-core context
|
||||||
if analysis.timer_queues.len() > 1 && analysis.timer_queues.contains_key(&core) {
|
if analysis.timer_queues.len() > 1 && analysis.timer_queues.contains_key(&core) {
|
||||||
let monotonic = extra.monotonic();
|
let monotonic = extra.monotonic();
|
||||||
stmts.push(quote!(rtfm::export::assert_multicore::<#monotonic>();));
|
stmts.push(quote!(rtic::export::assert_multicore::<#monotonic>();));
|
||||||
}
|
}
|
||||||
|
|
||||||
stmts
|
stmts
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtfm_syntax::ast::App;
|
use rtic_syntax::ast::App;
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||||
|
|
||||||
|
@ -49,23 +49,23 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
let (rq_attr, rq_ty, rq_expr, section) = if sender == receiver {
|
let (rq_attr, rq_ty, rq_expr, section) = if sender == receiver {
|
||||||
(
|
(
|
||||||
cfg_sender.clone(),
|
cfg_sender.clone(),
|
||||||
quote!(rtfm::export::SCRQ<#t, #n>),
|
quote!(rtic::export::SCRQ<#t, #n>),
|
||||||
quote!(rtfm::export::Queue(unsafe {
|
quote!(rtic::export::Queue(unsafe {
|
||||||
rtfm::export::iQueue::u8_sc()
|
rtic::export::iQueue::u8_sc()
|
||||||
})),
|
})),
|
||||||
util::link_section("bss", sender),
|
util::link_section("bss", sender),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let shared = if cfg!(feature = "heterogeneous") {
|
let shared = if cfg!(feature = "heterogeneous") {
|
||||||
Some(quote!(#[rtfm::export::shared]))
|
Some(quote!(#[rtic::export::shared]))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
shared,
|
shared,
|
||||||
quote!(rtfm::export::MCRQ<#t, #n>),
|
quote!(rtic::export::MCRQ<#t, #n>),
|
||||||
quote!(rtfm::export::Queue(rtfm::export::iQueue::u8())),
|
quote!(rtic::export::Queue(rtic::export::iQueue::u8())),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -87,7 +87,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
#cfg_sender
|
#cfg_sender
|
||||||
struct #rq<'a> {
|
struct #rq<'a> {
|
||||||
priority: &'a rtfm::export::Priority,
|
priority: &'a rtic::export::Priority,
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
#inputs.get_unchecked(usize::from(index)).as_ptr().read();
|
#inputs.get_unchecked(usize::from(index)).as_ptr().read();
|
||||||
#let_instant
|
#let_instant
|
||||||
#fq.split().0.enqueue_unchecked(index);
|
#fq.split().0.enqueue_unchecked(index);
|
||||||
let priority = &rtfm::export::Priority::new(PRIORITY);
|
let priority = &rtic::export::Priority::new(PRIORITY);
|
||||||
crate::#name(
|
crate::#name(
|
||||||
#locals_new
|
#locals_new
|
||||||
#name::Context::new(priority #instant)
|
#name::Context::new(priority #instant)
|
||||||
|
@ -177,7 +177,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream
|
||||||
/// The priority of this interrupt handler
|
/// The priority of this interrupt handler
|
||||||
const PRIORITY: u8 = #level;
|
const PRIORITY: u8 = #level;
|
||||||
|
|
||||||
rtfm::export::run(PRIORITY, || {
|
rtic::export::run(PRIORITY, || {
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtfm_syntax::{ast::App, Context};
|
use rtic_syntax::{ast::App, Context};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
analyze::Analysis,
|
analyze::Analysis,
|
||||||
|
@ -36,7 +36,7 @@ pub fn codegen(
|
||||||
let m = extra.monotonic();
|
let m = extra.monotonic();
|
||||||
|
|
||||||
(
|
(
|
||||||
Some(quote!(let instant = <#m as rtfm::Monotonic>::now();)),
|
Some(quote!(let instant = <#m as rtic::Monotonic>::now();)),
|
||||||
Some(quote!(, instant)),
|
Some(quote!(, instant)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,10 +67,10 @@ pub fn codegen(
|
||||||
|
|
||||||
#let_instant
|
#let_instant
|
||||||
|
|
||||||
rtfm::export::run(PRIORITY, || {
|
rtic::export::run(PRIORITY, || {
|
||||||
crate::#name(
|
crate::#name(
|
||||||
#locals_new
|
#locals_new
|
||||||
#name::Context::new(&rtfm::export::Priority::new(PRIORITY) #instant)
|
#name::Context::new(&rtic::export::Priority::new(PRIORITY) #instant)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ pub fn codegen(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#section
|
#section
|
||||||
fn #name(#(#locals_pat,)* #context: #name::Context) {
|
fn #name(#(#locals_pat,)* #context: #name::Context) {
|
||||||
use rtfm::Mutex as _;
|
use rtic::Mutex as _;
|
||||||
|
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue