2021-12-25 16:18:28 +01:00
|
|
|
|
# Миграция с v0.5.x на v1.0.0
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
Этот раздел описывает как обновиться с версии v0.5.x на v1.0.0 фреймворка RTIC.
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
## `Cargo.toml` - увеличьте версию
|
|
|
|
|
|
|
|
|
|
Измените версию `cortex-m-rtic` на `"0.6.0"`.
|
|
|
|
|
|
|
|
|
|
## `mod` вместо `const`
|
|
|
|
|
|
|
|
|
|
С поддержкой атрибутов над модулями трюк с `const APP` теперь не нужен.
|
|
|
|
|
|
|
|
|
|
Измените
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
const APP: () = {
|
|
|
|
|
[код здесь]
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
на
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
mod app {
|
|
|
|
|
[код здесь]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Так как теперь используется обычный модуль Rust, это значит, что можно использовать
|
|
|
|
|
обычный пользовательский код в этом модуле.
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Также это значит, что `use`-выражения для ресурсов, используемые
|
|
|
|
|
в пользовательском коде должны быть перемещены внутрь `mod app`,
|
|
|
|
|
либо на них можно сослаться с помощью `super`. Например, измените:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
use some_crate::some_func;
|
|
|
|
|
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
const APP: () = {
|
|
|
|
|
fn func() {
|
|
|
|
|
some_crate::some_func();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
на
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
mod app {
|
|
|
|
|
use some_crate::some_func;
|
|
|
|
|
|
|
|
|
|
fn func() {
|
|
|
|
|
some_crate::some_func();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
или
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
use some_crate::some_func;
|
|
|
|
|
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
mod app {
|
|
|
|
|
fn func() {
|
|
|
|
|
super::some_crate::some_func();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
## Перенос диспетчеров из `extern "C"` в аргументы app.
|
|
|
|
|
|
|
|
|
|
Измените
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[rtic::app(/* .. */)]
|
|
|
|
|
const APP: () = {
|
|
|
|
|
[код здесь]
|
|
|
|
|
|
|
|
|
|
// RTIC требует, чтобы неиспользуемые прерывания были задекларированы в блоке extern, когда
|
|
|
|
|
// используются программные задачи; эти свободные прерывания будут использованы для управления
|
|
|
|
|
// программными задачами.
|
|
|
|
|
extern "C" {
|
|
|
|
|
fn SSI0();
|
|
|
|
|
fn QEI0();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
на
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])]
|
|
|
|
|
mod app {
|
|
|
|
|
[код здесь]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Это работает и для ОЗУ-функций, см. examples/ramfunc.rs
|
|
|
|
|
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
## Структуры ресурсов - `#[shared]`, `#[local]`
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Ранее ресурсы RTIC должны были размещаться в структуре с именем "Resources":
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
``` rust
|
|
|
|
|
struct Resources {
|
|
|
|
|
// Ресурсы определяются здесь
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
Начиная с RTIC v1.0.0 структуры ресурсов аннотируются подобно
|
2021-08-03 21:40:33 +02:00
|
|
|
|
`#[task]`, `#[init]`, `#[idle]`: аттрибутами `#[shared]` и `#[local]`
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[shared]
|
|
|
|
|
struct MySharedResources {
|
|
|
|
|
// Разделяемые задачами ресурсы определены здесь
|
|
|
|
|
}
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[local]
|
|
|
|
|
struct MyLocalResources {
|
|
|
|
|
// Ресурсы, определенные здесь нельзя передавать между задачами; каждый из них локальный для единственной задачи
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Эти структуры разработчик может называть по своему желанию.
|
|
|
|
|
|
|
|
|
|
## `shared` и `local` аргументы в `#[task]`'ах
|
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
В v1.0.0 ресурсы разделены на `shared` ресурсы и `local` ресурсы.
|
2021-08-03 21:40:33 +02:00
|
|
|
|
`#[task]`, `#[init]` и `#[idle]` больше не имеют аргумента `resources`;
|
|
|
|
|
они должны использовать аргументы `shared` и `local`.
|
|
|
|
|
|
|
|
|
|
В v0.5.x:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
struct Resources {
|
|
|
|
|
local_to_b: i64,
|
|
|
|
|
shared_by_a_and_b: i64,
|
|
|
|
|
}
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(resources = [shared_by_a_and_b])]
|
|
|
|
|
fn a(_: a::Context) {}
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(resources = [shared_by_a_and_b, local_to_b])]
|
|
|
|
|
fn b(_: b::Context) {}
|
|
|
|
|
```
|
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
В v1.0.0:
|
2021-08-03 21:40:33 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[shared]
|
|
|
|
|
struct Shared {
|
|
|
|
|
shared_by_a_and_b: i64,
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
2021-08-03 21:40:33 +02:00
|
|
|
|
|
|
|
|
|
#[local]
|
|
|
|
|
struct Local {
|
|
|
|
|
local_to_b: i64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(shared = [shared_by_a_and_b])]
|
|
|
|
|
fn a(_: a::Context) {}
|
|
|
|
|
|
|
|
|
|
#[task(shared = [shared_by_a_and_b], local = [local_to_b])]
|
|
|
|
|
fn b(_: b::Context) {}
|
2021-04-04 07:15:13 +02:00
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
## Симметричные блокировки
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для
|
|
|
|
|
всех доступов к `shared` ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу,
|
|
|
|
|
в старом коде можно было следующее:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(priority = 2, resources = [r])]
|
|
|
|
|
fn foo(cx: foo::Context) {
|
|
|
|
|
cx.resources.r = /* ... */;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(resources = [r])]
|
|
|
|
|
fn bar(cx: bar::Context) {
|
|
|
|
|
cx.resources.r.lock(|r| r = /* ... */);
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
С симметричными блокировками нужно вызывать `lock` для обоих задач:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(priority = 2, shared = [r])]
|
|
|
|
|
fn foo(cx: foo::Context) {
|
|
|
|
|
cx.shared.r.lock(|r| r = /* ... */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(shared = [r])]
|
|
|
|
|
fn bar(cx: bar::Context) {
|
|
|
|
|
cx.shared.r.lock(|r| r = /* ... */);
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Заметьте, что скорость работы не изменяется благодаря оптимизациям LLVM, которые убирают ненужные блокировки.
|
|
|
|
|
|
|
|
|
|
## Неблокирующий доступ к ресурсам
|
|
|
|
|
|
|
|
|
|
В RTIC 0.5 к ресурсам разделяемым задачами, запускаемыми с одинаковым
|
|
|
|
|
приоритетом, можно получить доступ *без* `lock` API.
|
|
|
|
|
Это все еще возможно в 0.6: ресурс `#[shared]` должен быть аннотирован
|
|
|
|
|
аттрибутом поля `#[lock_free]`.
|
|
|
|
|
|
|
|
|
|
v0.5 код:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
struct Resources {
|
|
|
|
|
counter: u64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(resources = [counter])]
|
|
|
|
|
fn a(cx: a::Context) {
|
|
|
|
|
*cx.resources.counter += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(resources = [counter])]
|
|
|
|
|
fn b(cx: b::Context) {
|
|
|
|
|
*cx.resources.counter += 1;
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
v1.0 код:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
``` rust
|
|
|
|
|
#[shared]
|
|
|
|
|
struct Shared {
|
|
|
|
|
#[lock_free]
|
|
|
|
|
counter: u64,
|
|
|
|
|
}
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(shared = [counter])]
|
|
|
|
|
fn a(cx: a::Context) {
|
|
|
|
|
*cx.shared.counter += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[task(shared = [counter])]
|
|
|
|
|
fn b(cx: b::Context) {
|
|
|
|
|
*cx.shared.counter += 1;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## нет преобразования `static mut`
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
`static mut` переменные больше не преобразуются в безопасные `&'static mut` ссылки.
|
|
|
|
|
Вместо этого синтаксиса используйте аргумент `local` в `#[init]`.
|
|
|
|
|
|
|
|
|
|
v0.5.x code:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[init]
|
|
|
|
|
fn init(_: init::Context) {
|
|
|
|
|
static mut BUFFER: [u8; 1024] = [0; 1024];
|
|
|
|
|
let buffer: &'static mut [u8; 1024] = BUFFER;
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
2021-08-03 21:40:33 +02:00
|
|
|
|
```
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-12-25 16:18:28 +01:00
|
|
|
|
v1.0.0 code:
|
2021-08-03 21:40:33 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[init(local = [
|
|
|
|
|
buffer: [u8; 1024] = [0; 1024]
|
|
|
|
|
// type ^^^^^^^^^^^^ ^^^^^^^^^ initial value
|
|
|
|
|
])]
|
|
|
|
|
fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
|
|
|
|
|
let buffer: &'static mut [u8; 1024] = cx.local.buffer;
|
|
|
|
|
|
|
|
|
|
(Shared {}, Local {}, init::Monotonics())
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
## Init всегда возвращает поздние ресурсы
|
|
|
|
|
|
|
|
|
|
С целью сделать API более симметричным задача #[init] всегда возвращает поздние ресурсы.
|
|
|
|
|
|
|
|
|
|
С этого:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[rtic::app(device = lm3s6965)]
|
|
|
|
|
mod app {
|
|
|
|
|
#[init]
|
|
|
|
|
fn init(_: init::Context) {
|
|
|
|
|
rtic::pend(Interrupt::UART0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [еще код]
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
2021-08-03 21:40:33 +02:00
|
|
|
|
```
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
на это:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``` rust
|
|
|
|
|
#[rtic::app(device = lm3s6965)]
|
|
|
|
|
mod app {
|
|
|
|
|
#[shared]
|
|
|
|
|
struct MySharedResources {}
|
|
|
|
|
|
|
|
|
|
#[local]
|
|
|
|
|
struct MyLocalResources {}
|
|
|
|
|
|
|
|
|
|
#[init]
|
|
|
|
|
fn init(_: init::Context) -> (MySharedResources, MyLocalResources, init::Monotonics) {
|
|
|
|
|
rtic::pend(Interrupt::UART0);
|
|
|
|
|
|
|
|
|
|
(MySharedResources, MyLocalResources, init::Monotonics())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// [more code]
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
## Вызов/планирование откуда угодно
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
С этой новой возвожностью, старый код, такой как:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(spawn = [bar])]
|
2021-04-04 07:15:13 +02:00
|
|
|
|
fn foo(cx: foo::Context) {
|
2021-08-03 21:40:33 +02:00
|
|
|
|
cx.spawn.bar().unwrap();
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task(schedule = [bar])]
|
2021-04-04 07:15:13 +02:00
|
|
|
|
fn bar(cx: bar::Context) {
|
2021-08-03 21:40:33 +02:00
|
|
|
|
cx.schedule.foo(/* ... */).unwrap();
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Теперь будет выглядеть так:
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
``` rust
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task]
|
|
|
|
|
fn foo(_c: foo::Context) {
|
|
|
|
|
bar::spawn().unwrap();
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
#[task]
|
|
|
|
|
fn bar(_c: bar::Context) {
|
|
|
|
|
foo::schedule(/* ... */).unwrap();
|
2021-04-04 07:15:13 +02:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2021-08-03 21:40:33 +02:00
|
|
|
|
Заметьте, что атрибуты `spawn` и `schedule` больше не нужны.
|
2021-04-04 07:15:13 +02:00
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Дополнительно
|
|
|
|
|
|
|
|
|
|
### Внешние задачи
|
|
|
|
|
|
|
|
|
|
Как программные, так и аппаратные задачи теперь можно определять вне модуля `mod app`.
|
|
|
|
|
Ранее это было возможно только путем реализации обертки, вызывающей реализацию задачи.
|
|
|
|
|
|
|
|
|
|
Смотреть примеры `examples/extern_binds.rs` и `examples/extern_spawn.rs`.
|
|
|
|
|
|