2019-02-08 21:18:51 +01:00
|
|
|
|
## Ресурсы
|
|
|
|
|
|
|
|
|
|
Одно из ограничений атрибутов, предоставляемых библиотекой `cortex-m-rt` является
|
|
|
|
|
то, что совместное использование данных (или периферии) между прерываниями,
|
|
|
|
|
или прерыванием и функцией `init`, требуют `cortex_m::interrupt::Mutex`, который
|
|
|
|
|
*всегда* требует отключения *всех* прерываний для доступа к данным. Отключение всех
|
|
|
|
|
прерываний не всегда необходимо для безопасности памяти, но компилятор не имеет
|
|
|
|
|
достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
|
|
|
|
|
|
|
|
|
|
Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
|
2020-06-11 19:18:29 +02:00
|
|
|
|
`static`-переменным. В RTIC мы обращаемся к `static`-переменным, объявленным внутри
|
2019-02-08 21:18:51 +01:00
|
|
|
|
псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
|
|
|
|
|
(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
|
|
|
|
|
аргумент `resources` в соответствующем атрибуте.
|
|
|
|
|
|
|
|
|
|
В примере ниже два обработчика прерываний имеют доступ к одному и тому же ресурсу.
|
|
|
|
|
Никакого `Mutex` в этом случае не требуется, потому что оба обработчика запускаются
|
2019-02-09 06:48:12 +01:00
|
|
|
|
с одним приоритетом и никакого вытеснения быть не может.
|
2019-02-08 21:18:51 +01:00
|
|
|
|
К ресурсу `SHARED` можно получить доступ только из этих двух прерываний.
|
|
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../examples/resource.rs}}
|
2019-02-08 21:18:51 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
``` console
|
|
|
|
|
$ cargo run --example resource
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../ci/expected/resource.run}}
|
2019-02-08 21:18:51 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Приоритеты
|
|
|
|
|
|
|
|
|
|
Приоритет каждого прерывания можно определить в атрибутах `interrupt` и `exception`.
|
|
|
|
|
Невозможно установить приоритет любым другим способом, потому что рантайм
|
|
|
|
|
забирает владение прерыванием `NVIC`; также невозможно изменить приоритет
|
|
|
|
|
обработчика / задачи в рантайме. Благодаря этому ограничению у фреймворка
|
|
|
|
|
есть знание о *статических* приоритетах всех обработчиков прерываний и исключений.
|
|
|
|
|
|
|
|
|
|
Прерывания и исключения могут иметь приоритеты в интервале `1..=(1 << NVIC_PRIO_BITS)`,
|
|
|
|
|
где `NVIC_PRIO_BITS` - константа, определённая в библиотеке `device`.
|
|
|
|
|
Задача `idle` имеет приоритет `0`, наименьший.
|
|
|
|
|
|
|
|
|
|
Ресурсы, совместно используемые обработчиками, работающими на разных приоритетах,
|
|
|
|
|
требуют критических секций для безопасности памяти. Фреймворк проверяет, что
|
|
|
|
|
критические секции используются, но *только где необходимы*: например,
|
|
|
|
|
критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
|
|
|
|
|
доступ к ресурсу.
|
|
|
|
|
|
2020-06-11 19:18:29 +02:00
|
|
|
|
API критической секции, предоставляемое фреймворком RTIC (см. [`Mutex`]),
|
2019-02-08 21:18:51 +01:00
|
|
|
|
основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
|
|
|
|
|
что критические секции не будут допускать *запуск некоторых* обработчиков,
|
|
|
|
|
включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
|
|
|
|
|
большим приоритетом не соперничащих за ресурс.
|
|
|
|
|
|
2020-06-11 19:18:29 +02:00
|
|
|
|
[`Mutex`]: ../../../api/rtic/trait.Mutex.html
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
|
|
|
|
|
до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
|
|
|
|
|
Обработчик с низшим приоритетом должен заблокировать ([`lock`]) ресурс
|
|
|
|
|
`SHARED`, чтобы получить доступ к его данным, в то время как обработчик со
|
|
|
|
|
средним приоритетом может напрямую получать доступ к его данным. Обработчик
|
|
|
|
|
с наивысшим приоритетом может свободно вытеснять критическую секцию,
|
|
|
|
|
созданную обработчиком с низшим приоритетом.
|
|
|
|
|
|
2020-06-11 19:18:29 +02:00
|
|
|
|
[`lock`]: ../../../api/rtic/trait.Mutex.html#method.lock
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../examples/lock.rs}}
|
2019-02-08 21:18:51 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
``` console
|
|
|
|
|
$ cargo run --example lock
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../ci/expected/lock.run}}```
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
## Поздние ресурсы
|
|
|
|
|
|
|
|
|
|
В отличие от обычных `static`-переменных, к которым должно быть присвоено
|
|
|
|
|
начальное значение, ресурсы можно инициализировать в рантайме.
|
|
|
|
|
Мы называем ресурсы, инициализируемые в рантайме *поздними*. Поздние ресурсы
|
|
|
|
|
полезны для *переноса* (как при передаче владения) периферии из `init` в
|
|
|
|
|
обработчики прерываний и исключений.
|
|
|
|
|
|
|
|
|
|
Поздние ресурсы определяются как обычные ресурсы, но им присваивается начальное
|
2019-02-12 17:12:08 +01:00
|
|
|
|
значение `()` (the unit value). `init` должен вернуть начальные значения для
|
|
|
|
|
всех поздних ресурсов, упакованные в структуру типа `init::LateResources`.
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
В примере ниже использованы поздние ресурсы, чтобы установить неблокированный,
|
|
|
|
|
односторонний канал между обработчиком прерывания `UART0` и функцией `idle`.
|
|
|
|
|
Очередь типа один производитель-один потребитель [`Queue`] использована как канал.
|
|
|
|
|
Очередь разделена на элементы потребителя и поизводителя в `init` и каждый элемент
|
|
|
|
|
расположен в отдельном ресурсе; `UART0` владеет ресурсом произодителя, а `idle`
|
|
|
|
|
владеет ресурсом потребителя.
|
|
|
|
|
|
2019-09-17 19:55:55 +02:00
|
|
|
|
[`Queue`]: ../../../api/heapless/spsc/struct.Queue.html
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../examples/late.rs}}
|
2019-02-08 21:18:51 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
``` console
|
|
|
|
|
$ cargo run --example late
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../ci/expected/late.run}}```
|
2019-02-08 21:18:51 +01:00
|
|
|
|
|
|
|
|
|
## `static`-ресурсы
|
|
|
|
|
|
|
|
|
|
Переменные типа `static` также можно использовать в качестве ресурсов. Задачи
|
|
|
|
|
могут получать только (разделяемые) `&` ссылки на ресурсы, но блокировки не
|
|
|
|
|
нужны для доступа к данным. Вы можете думать о `static`-ресурсах как о простых
|
|
|
|
|
`static`-переменных, которые можно инициализировать в рантайме и иметь лучшие
|
|
|
|
|
правила видимости: Вы можете контролировать, какие задачи получают доступ к
|
|
|
|
|
переменной, чтобы переменная не была видна всем фунциям в область видимости,
|
|
|
|
|
где она была объявлена.
|
|
|
|
|
|
|
|
|
|
В примере ниже ключ загружен (или создан) в рантайме, а затем использован в двух
|
|
|
|
|
задачах, запущенных на разных приоритетах.
|
|
|
|
|
|
|
|
|
|
``` rust
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../examples/static.rs}}
|
2019-02-08 21:18:51 +01:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
``` console
|
|
|
|
|
$ cargo run --example static
|
2019-02-11 21:40:53 +01:00
|
|
|
|
{{#include ../../../../ci/expected/static.run}}```
|