Читаем Real-Time Interrupt-driven Concurrency полностью

   • Игнорирование результата. В программах реального времени, как и в обычных, может быть нормальным иногда терять данные, или не получать ответ на некоторые события в пиковых ситуациях. В таких сценариях может быть допустимо игнорирование ошибки вызова spawn.

Следует отметить, что повторная попытка вызова spawn обычно неверный подход, поскольку такая операция на практике вероятно никогда не завершится успешно. Так как у нас есть только переключения контекста на задачи с более высоким приоритетом, повторение вызова spawn на задаче с низким приоритом никогда не позволит планировщику вызвать задачу, что значит, что буфер никогда не будет очищен. Такая ситуация отражена в следующем наброске:

#![allow(unused)]

fn main() {

#[rtic::app(..)]

mod app {

#[init(spawn = [foo, bar])]

fn init(cx: init::Context) {

cx.spawn.foo().unwrap();

cx.spawn.bar().unwrap();

}

#[task(priority = 2, spawn = [bar])]

fn foo(cx: foo::Context) {

// ..

// программа зависнет здесь

while cx.spawn.bar(payload).is_err() {

// повтор попытки вызова spawn, если произошла ошибка

}

}

#[task(priority = 1)]

fn bar(cx: bar::Context, payload: i32) {

// ..

}

}

}

<p id="Очередь_таймера"><strong><a l:href="#Очередь_таймера">Очередь таймера</a></strong></p>

В отличие от интерфейса spawn, который немедленно передает программную задачу планировщику для немедленного запуска, интерфейс schedule можно использовать для планирования задачи к запуске через какое-то время в будущем.

Чтобы использовать интерфейс schedule, предварительно должен быть определен монотонный таймер с помощью аргумента monotonic атрибута #[app]. Этот аргумент принимает путь к типу, реализующему трейт Monotonic. Ассоциированный тип, Instant, этого трейта представляет метку времени в соответствущих единицах измерения и широко используется в интерфейсе schedule -- предлагается смоделировать этот тип позднее один из таких есть в стандартной библиотеке.

Хотя это не отражено в определении трейта (из-за ограничений системы типов / трейтов), разница двух Instantов должна возвращать какой-то тип Duration (см. core::time::Duration) и этот Duration должен реализовывать трейт TryInto. Реализация этого трейта должна конвертировать значение Duration, которое использует какую-то определенную единицу измерения времени, в единицы измерения "тактов системного таймера (SYST)". Результат преобразований должен быть 32-битным целым. Если результат не соответствует 32-битному целому, тогда операция должна возвращать ошибку любого типа.

Для целевых платформ ARMv7+ крейт rtic предоставляет реализацию Monotonic, основанную на встроенном CYCle CouNTer (CYCCNT). Заметьте, что это 32-битный таймер, работающий на частоте центрального процессора, и поэтому не подходит для отслеживания интервалов времени в секундах.

Когда планируется задача, (определенный пользователем) Instant, в который задача должна быть выполнена, должен передаваться в качестве первого аргумента вызова schedule.

К тому же, выбранный monotonic таймер, необходимо сконфигурировать и инициализировать в фазе работы #[init]. Заметьте, что также касается случая использования CYCCNT, предоставляемого крейтом cortex-m-rtic.

Пример ниже планирует к выполнению две задачи из init: foo и bar. foo запланирована к запуску через 8 миллионов циклов в будущем. Далее, bar запланировано запустить через 4 миллиона циклов в будущем. Таким образом, bar запустится до foo, так как и запланировано.

DF:YJ: Примеры, использующие интерфейс schedule или абстракцию Instant не будут правильно работать на эмуляторе QEMU, поскольку счетчик циклов Cortex-M функционально не был реализован в qemu-system-arm.

#![allow(unused)]

fn main() {

//! examples/schedule.rs

#![deny(unsafe_code)]

#![deny(warnings)]

#![no_main]

#![no_std]

use panic_semihosting as _;

// NOTE: does NOT work on QEMU!

#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]

mod app {

Перейти на страницу:

Похожие книги

Компьютерные сети. 6-е изд.
Компьютерные сети. 6-е изд.

Перед вами шестое издание самой авторитетной книги по современным сетевым технологиям, написанное признанным экспертом Эндрю Таненбаумом в соавторстве со специалистом компании Google Дэвидом Уэзероллом и профессором Чикагского университета Ником Фимстером. Первая версия этого классического труда появилась на свет в далеком 1980 году, и с тех пор каждое издание книги неизменно становилось бестселлером. В книге последовательно изложены основные концепции, определяющие современное состояние компьютерных сетей и тенденции их развития. Авторы подробно объясняют устройство и принципы работы аппаратного и программного обеспечения, рассматривают все аспекты и уровни организации сетей — от физического до прикладного. Изложение теоретических принципов дополняется яркими, показательными примерами функционирования интернета и компьютерных сетей различного типа. Большое внимание уделяется сетевой безопасности. Шестое издание полностью переработано с учетом изменений, произошедших в сфере сетевых технологий за последние годы, и, в частности, освещает такие технологии, как DOCSIS, 4G и 5G, беспроводные сети стандарта 802.11ax, 100-гигабитные сети Ethernet, интернет вещей, современные транспортные протоколы CUBIC TCP, QUIC и BBR, программно-конфигурируемые сети и многое другое.

Дэвид Уэзеролл , Ник Фимстер , Эндрю Таненбаум

Учебные пособия, самоучители