Этот раздел описывает как обновить программы, написанные на RTIC v0.4.x на версию v0.5.0 фреймворка.
Cargo.toml
Во-первых, нужно обновить версию зависимости cortex-m-rtic до "0.5.0". Опцию timer-queue нужно удалить.
[dependencies.cortex-m-rtic]
# изменить это
version = "0.4.3"
# на это
version = "0.5.0"
# и удалить Cargo feature
features = ["timer-queue"]
# ^^^^^^^^^^^^^
Context
Все функции внутри элемента #[rtic::app] должны принимать первым аргументом структуру Context. Этот тип Context будет содержать переменные, которые были магически инъецированы в область видимости функции версией v0.4.x фреймворка: resources, spawn, schedule -- эти переменные станут полями структуры Context. Каждая функция элемента #[rtic::app] получит отдельный тип Context.
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */)]
const APP: () = {
// change this
#[task(resources = [x], spawn = [a], schedule = [b])]
fn foo() {
resources.x.lock(|x| /* .. */);
spawn.a(message);
schedule.b(baseline);
}
// into this
#[task(resources = [x], spawn = [a], schedule = [b])]
fn foo(mut cx: foo::Context) {
// ^^^^^^^^^^^^^^^^^^^^
cx.resources.x.lock(|x| /* .. */);
// ^^^
cx.spawn.a(message);
// ^^^
cx.schedule.b(message, baseline);
// ^^^
}
// change this
#[init]
fn init() {
// ..
}
// into this
#[init]
fn init(cx: init::Context) {
// ^^^^^^^^^^^^^^^^^
// ..
}
// ..
};
}
Синтаксис, используемый, для определения ресурсов был изменен с переменных static mut на структуру Resources.
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */)]
const APP: () = {
// измените это
static mut X: u32 = 0;
static mut Y: u32 = (); // поздний ресурс
// на это
struct Resources {
#[init(0)] // <- начальное значение
X: u32, // ПРИМЕЧАНИЕ: мы предлагаем изменить стиль именования на `snake_case`
Y: u32, // поздний ресурс
}
// ..
};
}
Если ваша программа получала доступ к периферии в #[init] через переменну device, вам нужно будет добавить peripherals = true в атрибут #[rtic::app], чтобы и дальше получать доступ к периферии через поле device структуры init::Context.
Измените это:
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */)]
const APP: () = {
#[init]
fn init() {
device.SOME_PERIPHERAL.write(something);
}
// ..
};
}
На это:
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */, peripherals = true)]
// ^^^^^^^^^^^^^^^^^^
const APP: () = {
#[init]
fn init(cx: init::Context) {
// ^^^^^^^^^^^^^^^^^
cx.device.SOME_PERIPHERAL.write(something);
// ^^^
}
// ..
};
}
#[interrupt]
и #[exception]
Атрибуты #[interrupt] и #[exception] были удалены. Чтобы определять аппаратные задачи в v0.5.x используте атрибут #[task] с аргументом binds.
Измените это:
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */)]
const APP: () = {
// аппаратные задачи
#[exception]
fn SVCall() { /* .. */ }
#[interrupt]
fn UART0() { /* .. */ }
// программные задачи
#[task]
fn foo() { /* .. */ }
// ..
};
}
На это:
#![allow(unused)]
fn main() {
#[rtic::app(/* .. */)]
const APP: () = {
#[task(binds = SVCall)]
// ^^^^^^^^^^^^^^
fn svcall(cx: svcall::Context) { /* .. */ }
// ^^^^^^ мы предлагаем использовать `snake_case` имя здесь
#[task(binds = UART0)]
// ^^^^^^^^^^^^^
fn uart0(cx: uart0::Context) { /* .. */ }
#[task]
fn foo(cx: foo::Context) { /* .. */ }
// ..
};
}
schedule
Интерфейс schedule больше не требует cargo опции timer-queue, которая была удалена. Чтобы использовать интерфес schedule, нужно сначала определить монотонный тамер, который будет использоваьт среды выполнения, с помощью аргумента monotonic атрибута #[rtic::app]. Чтобы продолжить использовать счетчик циклов (CYCCNT) в качестве монотонного таймера, как было в версии v0.4.x, добавьте аргумент monotonic = rtic::cyccnt::CYCCNT в атрибут #[rtic::app].
Также были добавлены типы Duration и Instant, а трейт U32Ext был перемещен в модуль rtic::cyccnt. Этот модуль доступен только на устройствах ARMv7-M+. Удаление timer-queue также возвращает периферию DWT в структуру периферии ядра, включить ее в работу можно внутри init.
Измените это:
#![allow(unused)]
fn main() {
use rtic::{Duration, Instant, U32Ext};
#[rtic::app(/* .. */)]
const APP: () = {
#[task(schedule = [b])]
fn a() {
// ..
}
};
}
На это:
#![allow(unused)]
fn main() {
use rtic::cyccnt::{Duration, Instant, U32Ext};
// ^^^^^^^^
#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const APP: () = {
#[init]
fn init(cx: init::Context) {
cx.core.DWT.enable_cycle_counter();
// опционально, настройка запуска DWT без подключенного отладчика
cx.core.DCB.enable_trace();
}
#[task(schedule = [b])]
fn a(cx: a::Context) {
// ..
}
};
}