aboutsummaryrefslogtreecommitdiff
path: root/book/ru/src/by-example/resources.md
diff options
context:
space:
mode:
Diffstat (limited to 'book/ru/src/by-example/resources.md')
-rw-r--r--book/ru/src/by-example/resources.md122
1 files changed, 122 insertions, 0 deletions
diff --git a/book/ru/src/by-example/resources.md b/book/ru/src/by-example/resources.md
new file mode 100644
index 0000000..3e8a606
--- /dev/null
+++ b/book/ru/src/by-example/resources.md
@@ -0,0 +1,122 @@
+## Ресурсы
+
+Одно из ограничений атрибутов, предоставляемых библиотекой `cortex-m-rt` является
+то, что совместное использование данных (или периферии) между прерываниями,
+или прерыванием и функцией `init`, требуют `cortex_m::interrupt::Mutex`, который
+*всегда* требует отключения *всех* прерываний для доступа к данным. Отключение всех
+прерываний не всегда необходимо для безопасности памяти, но компилятор не имеет
+достаточно информации, чтобы оптимизировать доступ к разделяемым данным.
+
+Атрибут `app` имеет полную картину приложения, поэтому может оптимизировать доступ к
+`static`-переменным. В RTFM мы обращаемся к `static`-переменным, объявленным внутри
+псевдо-модуля `app` как к *ресурсам*. Чтобы получить доступ к ресурсу, контекст
+(`init`, `idle`, `interrupt` или `exception`) должен сначала определить
+аргумент `resources` в соответствующем атрибуте.
+
+В примере ниже два обработчика прерываний имеют доступ к одному и тому же ресурсу.
+Никакого `Mutex` в этом случае не требуется, потому что оба обработчика запускаются
+с одним приоритетом и никакого вытеснения быть не может.
+К ресурсу `SHARED` можно получить доступ только из этих двух прерываний.
+
+``` rust
+{{#include ../../../../examples/resource.rs}}
+```
+
+``` console
+$ cargo run --example resource
+{{#include ../../../../ci/expected/resource.run}}
+```
+
+## Приоритеты
+
+Приоритет каждого прерывания можно определить в атрибутах `interrupt` и `exception`.
+Невозможно установить приоритет любым другим способом, потому что рантайм
+забирает владение прерыванием `NVIC`; также невозможно изменить приоритет
+обработчика / задачи в рантайме. Благодаря этому ограничению у фреймворка
+есть знание о *статических* приоритетах всех обработчиков прерываний и исключений.
+
+Прерывания и исключения могут иметь приоритеты в интервале `1..=(1 << NVIC_PRIO_BITS)`,
+где `NVIC_PRIO_BITS` - константа, определённая в библиотеке `device`.
+Задача `idle` имеет приоритет `0`, наименьший.
+
+Ресурсы, совместно используемые обработчиками, работающими на разных приоритетах,
+требуют критических секций для безопасности памяти. Фреймворк проверяет, что
+критические секции используются, но *только где необходимы*: например,
+критические секции не нужны для обработчика с наивысшим приоритетом, имеющим
+доступ к ресурсу.
+
+API критической секции, предоставляемое фреймворком RTFM (см. [`Mutex`]),
+основано на динамических приоритетах вместо отключения прерываний. Из этого следует,
+что критические секции не будут допускать *запуск некоторых* обработчиков,
+включая все соперничающие за ресурс, но будут позволять запуск обработчиков с
+большим приоритетом не соперничащих за ресурс.
+
+[`Mutex`]: ../../api/rtfm/trait.Mutex.html
+
+В примере ниже у нас есть 3 обработчика прерываний с приоритетами от одного
+до трех. Два обработчика с низким приоритетом соперничают за ресурс `SHARED`.
+Обработчик с низшим приоритетом должен заблокировать ([`lock`]) ресурс
+`SHARED`, чтобы получить доступ к его данным, в то время как обработчик со
+средним приоритетом может напрямую получать доступ к его данным. Обработчик
+с наивысшим приоритетом может свободно вытеснять критическую секцию,
+созданную обработчиком с низшим приоритетом.
+
+[`lock`]: ../../api/rtfm/trait.Mutex.html#method.lock
+
+``` rust
+{{#include ../../../../examples/lock.rs}}
+```
+
+``` console
+$ cargo run --example lock
+{{#include ../../../../ci/expected/lock.run}}```
+
+## Поздние ресурсы
+
+В отличие от обычных `static`-переменных, к которым должно быть присвоено
+начальное значение, ресурсы можно инициализировать в рантайме.
+Мы называем ресурсы, инициализируемые в рантайме *поздними*. Поздние ресурсы
+полезны для *переноса* (как при передаче владения) периферии из `init` в
+обработчики прерываний и исключений.
+
+Поздние ресурсы определяются как обычные ресурсы, но им присваивается начальное
+значение `()` (the unit value). Поздние ресурсы необходимо инициализировать в конце
+функции `init` используя обычное присвоение (например `FOO = 1`).
+
+В примере ниже использованы поздние ресурсы, чтобы установить неблокированный,
+односторонний канал между обработчиком прерывания `UART0` и функцией `idle`.
+Очередь типа один производитель-один потребитель [`Queue`] использована как канал.
+Очередь разделена на элементы потребителя и поизводителя в `init` и каждый элемент
+расположен в отдельном ресурсе; `UART0` владеет ресурсом произодителя, а `idle`
+владеет ресурсом потребителя.
+
+[`Queue`]: ../../api/heapless/spsc/struct.Queue.html
+
+``` rust
+{{#include ../../../../examples/late.rs}}
+```
+
+``` console
+$ cargo run --example late
+{{#include ../../../../ci/expected/late.run}}```
+
+## `static`-ресурсы
+
+Переменные типа `static` также можно использовать в качестве ресурсов. Задачи
+могут получать только (разделяемые) `&` ссылки на ресурсы, но блокировки не
+нужны для доступа к данным. Вы можете думать о `static`-ресурсах как о простых
+`static`-переменных, которые можно инициализировать в рантайме и иметь лучшие
+правила видимости: Вы можете контролировать, какие задачи получают доступ к
+переменной, чтобы переменная не была видна всем фунциям в область видимости,
+где она была объявлена.
+
+В примере ниже ключ загружен (или создан) в рантайме, а затем использован в двух
+задачах, запущенных на разных приоритетах.
+
+``` rust
+{{#include ../../../../examples/static.rs}}
+```
+
+``` console
+$ cargo run --example static
+{{#include ../../../../ci/expected/static.run}}```