mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 23:14:34 +01:00
209 lines
5.5 KiB
Markdown
209 lines
5.5 KiB
Markdown
|
# Миграция с v0.5.x на v0.6.0
|
|||
|
|
|||
|
Этот раздел описывает как обновиться с версии v0.5.x на v0.6.0 фреймворка RTIC.
|
|||
|
|
|||
|
## `Cargo.toml` - увеличьте версию
|
|||
|
|
|||
|
Измените версию `cortex-m-rtic` на `"0.6.0"`.
|
|||
|
|
|||
|
## `mod` вместо `const`
|
|||
|
|
|||
|
С поддержкой атрибутов над модулями трюк с `const APP` теперь не нужен.
|
|||
|
|
|||
|
Измените
|
|||
|
|
|||
|
``` rust
|
|||
|
#[rtic::app(/* .. */)]
|
|||
|
const APP: () = {
|
|||
|
[код здесь]
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
на
|
|||
|
|
|||
|
``` rust
|
|||
|
#[rtic::app(/* .. */)]
|
|||
|
mod app {
|
|||
|
[код здесь]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Так как теперь используется обычный модуль Rust, это значит, что можно использовать
|
|||
|
обычный пользовательский код в этом модуле.
|
|||
|
Также жто значит, что `use`-выражения для ресурсов (и т.п.) могут понадобиться.
|
|||
|
|
|||
|
## Перенос диспетчеров из `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
|
|||
|
|
|||
|
|
|||
|
## Init всегда возвращает поздние ресурсы
|
|||
|
|
|||
|
С целью сделать API более симметричным задача #[init] всегда возвращает поздние ресурсы.
|
|||
|
|
|||
|
С этого:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[rtic::app(device = lm3s6965)]
|
|||
|
mod app {
|
|||
|
#[init]
|
|||
|
fn init(_: init::Context) {
|
|||
|
rtic::pend(Interrupt::UART0);
|
|||
|
}
|
|||
|
|
|||
|
// [еще код]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
на это:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[rtic::app(device = lm3s6965)]
|
|||
|
mod app {
|
|||
|
#[init]
|
|||
|
fn init(_: init::Context) -> init::LateResources {
|
|||
|
rtic::pend(Interrupt::UART0);
|
|||
|
|
|||
|
init::LateResources {}
|
|||
|
}
|
|||
|
|
|||
|
// [еще код]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## Структура Resources - `#[resources]`
|
|||
|
|
|||
|
Ранее ресурсы RTIC должны были располагаться в структуре с именем "Resources":
|
|||
|
|
|||
|
``` rust
|
|||
|
struct Resources {
|
|||
|
// Ресурсы определены здесь
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
В RTIC v0.6.0 структура ресурсов аннотируется также, как и
|
|||
|
`#[task]`, `#[init]`, `#[idle]`: атрибутом `#[resources]`
|
|||
|
|
|||
|
``` rust
|
|||
|
#[resources]
|
|||
|
struct Resources {
|
|||
|
// Ресурсы определены здесь
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
На самом деле, имя структуры предоставлено на усмотрение разработчика:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[resources]
|
|||
|
struct Whateveryouwant {
|
|||
|
// Ресурсы определены здесь
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
будет работать так же хороршо.
|
|||
|
|
|||
|
## Вызов/планирование откуда угодно
|
|||
|
|
|||
|
С этой новой возвожностью, старый код, такой как:
|
|||
|
|
|||
|
|
|||
|
``` rust
|
|||
|
#[task(spawn = [bar])]
|
|||
|
fn foo(cx: foo::Context) {
|
|||
|
cx.spawn.bar().unwrap();
|
|||
|
}
|
|||
|
|
|||
|
#[task(schedule = [bar])]
|
|||
|
fn bar(cx: bar::Context) {
|
|||
|
cx.schedule.foo(/* ... */).unwrap();
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Теперь будет выглядеть так:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[task]
|
|||
|
fn foo(_c: foo::Context) {
|
|||
|
bar::spawn().unwrap();
|
|||
|
}
|
|||
|
|
|||
|
#[task]
|
|||
|
fn bar(_c: bar::Context) {
|
|||
|
foo::schedule(/* ... */).unwrap();
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Заметьте, что атрибуты `spawn` и `schedule` больше не нужны.
|
|||
|
|
|||
|
## Симметричные блокировки
|
|||
|
|
|||
|
Теперь RTIC использует симметричные блокировки, это значит, что метод `lock` нужно использовать для
|
|||
|
всех доступов к ресурсам. Поскольку высокоприоритетные задачи имеют эксклюзивный доступ к ресурсу,
|
|||
|
в старом коде можно было следующее:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[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 = /* ... */);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
С симметричными блокировками нужно вызывать `lock` для обоих задач:
|
|||
|
|
|||
|
``` rust
|
|||
|
#[task(priority = 2, resources = [r])]
|
|||
|
fn foo(cx: foo::Context) {
|
|||
|
cx.resources.r.lock(|r| r = /* ... */);
|
|||
|
}
|
|||
|
|
|||
|
#[task(resources = [r])]
|
|||
|
fn bar(cx: bar::Context) {
|
|||
|
cx.resources.r.lock(|r| r = /* ... */);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Заметьте, что скорость работы не изменяется благодаря оптимизациям LLVM, которые убирают ненужные блокировки.
|
|||
|
|
|||
|
---
|
|||
|
|
|||
|
## Дополнительно
|
|||
|
|
|||
|
### Внешние задачи
|
|||
|
|
|||
|
Как программные, так и аппаратные задачи теперь можно определять вне модуля `mod app`.
|
|||
|
Ранее это было возможно только путем реализации обертки, вызывающей реализацию задачи.
|
|||
|
|
|||
|
Смотреть примеры `examples/extern_binds.rs` и `examples/extern_spawn.rs`.
|
|||
|
|