diff options
Diffstat (limited to 'book/ru/src/by-example/resources.md')
| -rw-r--r-- | book/ru/src/by-example/resources.md | 122 |
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}}``` |
