Real-Time Interrupt-driven Concurrency — страница 13 из 23

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) {

// ..

}

};

}

Миграция с RTFM на RTIC

В этом разделе описано, как обновить приложение, написанное на RTFM v0.5.x на RTIC той же версии. Это необходимо из-за переименования фреймворка в соответствии с RFC #33.

Примечание: Между RTFM v0.5.3 и RTIC v0.5.3 нет разниц в коде, это исключительно изменение имен.

Cargo.toml

Во-первых, зависимость cortex-m-rtfm должна быть изменена на cortex-m-rtic.

[dependencies]

# измените это

cortex-m-rtfm = "0.5.3"


# на это

cortex-m-rtic = "0.5.3"

Изменения в коде

Единственное изменение в коде, которое нужно сделать - поменять все ссылки на rtfm, чтобы они указывали на rtic:


#![allow(unused)]

fn main() {

//

// Измените это

//


#[rtfm::app(/* .. */, monotonic = rtfm::cyccnt::CYCCNT)]

const APP: () = {

// ...


};


//

// На это

//


#[rtic::app(/* .. */, monotonic = rtic::cyccnt::CYCCNT)]

const APP: () = {

// ...


};

}

Под капотом

Этот раздел в настоящий момент находится в разработке, он появится снова, когда будет завершен

Этот раздел описывает внутренности фреймворка RTIC на высоком уровне. Низкоуровневые детали, такие как парсинг и генерация кода, выполняемые процедурным макросом (#[app]) объясняться не будут. Внимание будет сосредоточено на анализе спецификации пользователя и структурах данных, используемых на этапе выполнения.

Мы настоятельно рекомендуем вам прочитать раздел о конкуренции в embedonomicon перед тем, как погружаться в материал.

Настройка прерываний

Прерывания - это основа работы программ на RTIC. Правильно настроить приоритеты прерываний и убедиться, что они не изменяются во время выполнения обязательно для безопасной работы программы.

Фреймворк RTIC представляет приоритеты прерываний, как нечто, что должно быть определено на этапе компиляции. Однако, статическая настройка должна быть зашита в соответствующие регистры в процессе инициализации программы. Настройка прерываний происходит до запуска функции init.