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

#[task(binds = UART0, shared = [&key])]

fn uart0(cx: uart0::Context) {

let key: &u32 = cx.shared.key;

hprintln!("UART0(key = {:#x})", key).unwrap();

debug::exit(debug::EXIT_SUCCESS);

}

#[task(binds = UART1, priority = 2, shared = [&key])]

fn uart1(cx: uart1::Context) {

hprintln!("UART1(key = {:#x})", cx.shared.key).unwrap();

}

}

}

$ cargo run --example only-shared-access

UART1(key = 0xdeadbeef)

UART0(key = 0xdeadbeef)

<p id="Неблокируемый_доступ_к_изменяемым_ресурсам"><strong><a l:href="#Неблокируемый_доступ_к_изменяемым_ресурсам">Неблокируемый доступ к изменяемым ресурсам</a></strong></p>

Есть две других возможности доступа к ресурсам

   • #[lock_free]: могут быть несколько задач с одинаковым приоритетом, получающие доступ к ресурсу без критических секций. Так как задачи с одинаковым приоритетом никогда не могут вытеснить друг друга, это безопасно.

   • #[task_local]: в этом случае должна быть только одна задача, использующая этот ресурс, так же как локальный static mut ресурс задачи, но (опционально) устанавливаемая с в init.

<p id="Программные_задачи"><strong><a l:href="#Программные_задачи">Программные задачи</a></strong></p>

В дополнение к аппаратным задачам, вызываемым в ответ на аппаратные события, RTIC также поддерживает программные задачи, которые могут порождаться приложением из любого контекста выполнения.

Программным задачам можно также назначать приоритет и, под капотом, они диспетчеризуются обработчиками прерываний. RTIC требует, чтобы свободные прерывания, были указаны в аргументе dispatchers модуля app, если используются программные задачи; часть из этих свободных прерываний будут использованы для управления программными задачами. Преимущество программных задач над аппаратными в том, что множество задач можно назначить на один обработчик прерывания.

Программные задачи также определяются атрибутом task, но аргумент binds опускается.

Пример ниже демонстрирует три программные задачи, запускаемых 2-х разных приоритетах. Три программные задачи привязаны к 2-м обработчикам прерываний.

#![allow(unused)]

fn main() {

//! examples/task.rs

#![deny(unsafe_code)]

#![deny(warnings)]

#![no_main]

#![no_std]

use panic_semihosting as _;

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

mod app {

use cortex_m_semihosting::{debug, hprintln};

#[shared]

struct Shared {}

#[local]

struct Local {}

#[init]

fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {

foo::spawn().unwrap();

(Shared {}, Local {}, init::Monotonics())

}

#[task]

fn foo(_: foo::Context) {

hprintln!("foo - start").unwrap();

// spawns `bar` onto the task scheduler

// `foo` and `bar` have the same priority so `bar` will not run until

// after `foo` terminates

bar::spawn().unwrap();

hprintln!("foo - middle").unwrap();

// spawns `baz` onto the task scheduler

// `baz` has higher priority than `foo` so it immediately preempts `foo`

baz::spawn().unwrap();

hprintln!("foo - end").unwrap();

}

#[task]

fn bar(_: bar::Context) {

hprintln!("bar").unwrap();

debug::exit(debug::EXIT_SUCCESS);

}

#[task(priority = 2)]

fn baz(_: baz::Context) {

hprintln!("baz").unwrap();

}

}

}

$ cargo run --example task

foo - start

foo - middle

baz

foo - end

bar

<p id="Передача_сообщений"><strong><a l:href="#Передача_сообщений">Передача сообщений</a></strong></p>

Другое преимущество программной задачи в том, что задачам можно передать сообщения в момент их запуска. Тип передаваемого сообщения должен быть определен в сигнатуре задачи-обработчика.

Пример ниже демонстрирует три задачи, две из которых ожидают сообщение.

#![allow(unused)]

fn main() {

//! examples/message.rs

#![deny(unsafe_code)]

#![deny(warnings)]

#![no_main]

#![no_std]

use panic_semihosting as _;

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

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

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

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

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

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