diff options
| author | Andrey Zgarbul <zgarbul.andrey@gmail.com> | 2021-04-04 08:15:13 +0300 |
|---|---|---|
| committer | Andrey Zgarbul <zgarbul.andrey@gmail.com> | 2021-04-08 12:22:43 +0300 |
| commit | 05bda2b1bd2e15f5a20cda1444992eb9b6c8887e (patch) | |
| tree | 25330724d4e6d9ea3a62b592c07bfc5799c7da57 /book/ru/src/by-example/app.md | |
| parent | 83cdf00eecb0f14857b5e0f28e884b2120eabb18 (diff) | |
update russian translation of the book
Diffstat (limited to 'book/ru/src/by-example/app.md')
| -rw-r--r-- | book/ru/src/by-example/app.md | 159 |
1 files changed, 109 insertions, 50 deletions
diff --git a/book/ru/src/by-example/app.md b/book/ru/src/by-example/app.md index 04dd5b2..628819a 100644 --- a/book/ru/src/by-example/app.md +++ b/book/ru/src/by-example/app.md @@ -1,77 +1,84 @@ -# The `app` attribute +# Атрибут `app` -Это наименьшая возможная программа на RTIC: +Это простейшая из возможных программ на RTIC: ``` rust {{#include ../../../../examples/smallest.rs}} ``` Все программы на RTIC используют атрибут [`app`] (`#[app(..)]`). Этот атрибут -нужно применять к `const`-элементам, содержащим элементы. Атрибут `app` имеет -обязательный аргумент `device`, в качестве значения которому передается *путь*. -Этот путь должен указывать на библиотеку *устройства*, сгенерированную с помощью -[`svd2rust`] **v0.14.x**. Атрибут `app` развернется в удобную точку входа, -поэтому нет необходимости использовать атрибут [`cortex_m_rt::entry`]. +должен применяться к элементу `mod`. Атрибут `app` имеет обязательный аргумент `device`, +который принимает *путь* как значение. Это должен быть полный путь, указывающий на +*крейт доступа к периферии* (PAC), сгенерированный с помощью [`svd2rust`] версии **v0.14.x** +или новее. Более подробно в разделе [Создание нового проекта](./new.md). + +Атрибут `app` будет раскрыт в подходящую точку входа программы, поэтому +атрибут [`cortex_m_rt::entry`] не нужен. [`app`]: ../../../api/cortex_m_rtic_macros/attr.app.html [`svd2rust`]: https://crates.io/crates/svd2rust [`cortex_m_rt::entry`]: ../../../api/cortex_m_rt_macros/attr.entry.html -> **ОТСТУПЛЕНИЕ**: Некоторые из вас удивятся, почему мы используем ключевое слово `const` как -> модуль, а не правильное `mod`. Причина в том, что использование атрибутов на -> модулях требует feature gate, который требует ночную сборку. Чтобы заставить -> RTIC работать на стабильной сборке, мы используем вместо него слово `const`. -> Когда большая часть макросов 1.2 стабилизируются, мы прейдем от `const` к `mod` и в конце концов в атрибуту уровне приложения (`#![app]`). - ## `init` -Внутри псевдо-модуля атрибут `app` ожидает найти функцию инициализации, обозначенную -атрибутом `init`. Эта функция должна иметь сигнатуру `[unsafe] fn()`. +Внутри модуля `app` атрибут ожидает найти функцию инициализации, помеченную +атрибутом `init`. Эта функция должна иметь сигнатуру +`fn(init::Context) [-> init::LateResources]` (возвращаемый тип нужен не всегда). -Эта функция инициализации будет первой частью запускаемого приложения. -Функция `init` запустится *с отключенными прерываниями* и будет иметь эксклюзивный -доступ к периферии Cortex-M и специфичной для устройства периферии через переменные -`core` and `device`, которые внедряются в область видимости `init` атрибутом `app`. -Не вся периферия Cortex-M доступна в `core`, потому что рантайм RTIC принимает владение -частью из неё -- более подробно см. структуру [`rtic::Peripherals`]. +Эта функция инициализации будет первой частью программы, выполняемой при запуске. +Функция `init` будет запущена *с отключенными прерываниями* и будет иметь эксклюзивный доступ +к Cortex-M, в котором токен `bare_metal::CriticalSection` доступен как `cs`. +Опционально, устройство-специфичные периферия доступна через поля `core` и `device` структуры +`init::Context`. -Переменные `static mut`, определённые в начале `init` будут преобразованы -в ссылки `&'static mut` с безопасным доступом. +`static mut` переменные, определенные в начале `init` будут преобразованы в +`&'static mut` ссылки, безопасные для доступа. Обратите внимание, данная возможность может +быть удалена в следующем релизе, см. `task_local` ресурсы. [`rtic::Peripherals`]: ../../api/rtic/struct.Peripherals.html -Пример ниже показывает типы переменных `core` и `device` и -демонстрирует безопасный доступ к переменной `static mut`. +Пример ниже показывает типы полей `core`, `device` и `cs`, и демонстрирует +безопасный доступ к `static mut` переменной. Поле `device` доступно только +когда аргумент `peripherals` установлен в `true` (по умолчанию). +В редких случаях, когда вы захотите создать приложение с минимальным потреблением ресурсов, +можно явно установить `peripherals` в `false`. ``` rust {{#include ../../../../examples/init.rs}} ``` -Запуск примера напечатает `init` в консоли и завершит процесс QEMU. +Запуск примера напечатате `init` в консоли, а затем завершит процесс QEMU. ``` console $ cargo run --example init -{{#include ../../../../ci/expected/init.run}}``` +{{#include ../../../../ci/expected/init.run}} +``` ## `idle` -Функция, помеченная атрибутом `idle` может присутствовать в псевдо-модуле -опционально. Эта функция используется как специальная *задача ожидания* и должна иметь -сигнатуру `[unsafe] fn() - > !`. +Функцию, помеченную атрибутом `idle` может опционально добавить в модуль. +Эта функция используется как специальная *задача ожидания* и должна иметь сигнатуру +`fn(idle::Context) - > !`. -Когда она присутствует, рантайм запустит задачу `idle` после `init`. В отличие от -`init`, `idle` запустится *с включенными прерываниями* и не может завершиться, -поэтому будет работать бесконечно. +Если она присутствует, задача `idle` будет запущена после `init`. В отличие от +`init`, `idle` будет запущена *с включенными прерываниями* и она не может вернуть результат, +а значит должна работать вечно. -Когда функция `idle` не определена, рантайм устанавливает бит [SLEEPONEXIT], после чего -отправляет микроконтроллер в состояние сна после выполнения `init`. +Если функция `idle` не определена, среда вполнения устанавливает бит [SLEEPONEXIT], а затем +отправляет микроконтроллер в сон после запуска `init`. [SLEEPONEXIT]: https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit -Как и в `init`, переменные `static mut`будут преобразованы в ссылки `&'static mut` -с безопасным доступом. +Как и в `init`, `static mut` переменные будут трансформированы в `&'static mut` ссылки, +безопасные для доступа. Обратите внимание, данная возможность может +быть удалена в следующем релизе, см. `task_local` ресурсы. -В примере ниже показан запуск `idle` после `init`. +Пример ниже показывает, что `idle` запускается после `init`. + +**Примечание:** Цикл `loop {}` в функци ожидания не может быть пустым, так как это сломает +микроконтроллер, из-за того, что LLVM компилирует пустые циклы в инструкцию `UDF` в release mode. +Чтобы избежать неопределенного поведения, цикл должен включать "side-effect" +путем вставки ассемблерной инструкции (например, `WFI`) или ключевого слова `continue`. ``` rust {{#include ../../../../examples/idle.rs}} @@ -79,23 +86,75 @@ $ cargo run --example init ``` console $ cargo run --example idle -{{#include ../../../../ci/expected/idle.run}}``` +{{#include ../../../../ci/expected/idle.run}} +``` -## `interrupt` / `exception` +## Аппаратные задачи -Как Вы бы сделали с помощью библиотеки `cortex-m-rt`, Вы можете использовать атрибуты -`interrupt` и `exception` внутри псевдо-модуля `app`, чтобы определить обработчики -прерываний и исключений. В RTIC, мы называем обработчики прерываний и исключений -*аппаратными* задачами. +Чтобы объявить обработчик прерывания, фреймворк предоставляет атрибут `#[task]`, +который можно применять к функциям. Этот атрибут берет аргумент `binds`, чье значение - +это имя прерывания, которому будет назначен обработчик; +функция, декорированная этим атрибутом становится обработчиком прерывания. +В фреймворке такие типы задач именуются *аппаратными*, потому что они начинают +выполняться в ответ на аппаратное событие. + +Пример ниже демонстрирует использование атрибута `#[task]`, чтобы объявить +обработчик прерывания. Как и в случае с `#[init]` и `#[idle]` локальные `static +mut` переменные безопасны для использования с аппаратной задачей. ``` rust -{{#include ../../../../examples/interrupt.rs}} +{{#include ../../../../examples/hardware.rs}} ``` ``` console -$ cargo run --example interrupt -{{#include ../../../../ci/expected/interrupt.run}}``` +$ cargo run --example hardware +{{#include ../../../../ci/expected/hardware.run}} +``` + +До сих пор все программы на RTIC, которые мы видели, не отличались от программ, +которые можно написать, используя лишь крейт `cortex-m-rt`. С этого момента мы +начинаем представлять возможности, уникальные для RTIC. + +## Приоритеты + +Статический приоритет каждого обработчика можно оределить в атрибуте `task`, используя +аргумент `priority`. Задачи могут иметь приоритет в диапазоне `1..=(1 << NVIC_PRIO_BITS)`, +где `NVIC_PRIO_BITS` - это константа, определенная в крейте `устройства`. +Когда аргумент `priority` не указан, предполагается, что приоритет равен `1`. +Задача `idle` имеет ненастраиваемый приоритет `0`, наименьший из возможных. + +> Более высокое значение означает более высокий приоритет в RTIC, что противоположно тому, +> что указано в периферии NVIC Cortex-M. +> Точнее, это значит, что число `10` обозначает приоритет **выше**, чем число `9`. + +Когда несколько задач готовы к запуску, задача с самым большим статическим +приоритетом будет запущена первой. Приоритезацию задач можно рассматривать по +такому сценарию: сигнал прерывания приходит во время выполнения задачи с низким приоритетом; +сигнал переключает задачу с высоким приоритетом в режим ожидания. +Разница в приоритетах приводи к тому, что задача с высоким приоритетом вытесняет задачу с низким: +выполнение задачи с низким приоритетом замораживается и задача с высоким приоритетом выполняется, +пока не будет завершена. Как только задача с высоким приоритетом будет остановлена, +продолжится выполнение задачи с низким приоритетом. + +Следующий пример демонстрирует диспетчеризацию на основе приоритетов задач. + +``` rust +{{#include ../../../../examples/preempt.rs}} +``` + +``` console +$ cargo run --example preempt +{{#include ../../../../ci/expected/preempt.run}} +``` -До сих пор программы RTIC, которые мы видели не отличались от программ, которые -можно написать, используя только библиотеку `cortex-m-rt`. В следующем разделе -мы начнем знакомиться с функционалом, присущим только RTIC. +Заметьте, что задача `gpiob` *не* вытесняет задачу `gpioc`, потому что ее приоритет +*такой же*, как и у `gpioc`. Однако, как только `gpioc` возвращает результат, +выполненяется задача `gpiob`, как более приоритетная по сравнению с `gpioa`. +Выполнение `gpioa` возобновляется только после выхода из `gpiob`. + +Еще одно замечание по поводу приоритетов: выбор приоритета большего, чем поддерживает устройство +(а именно `1 << NVIC_PRIO_BITS`) приведет к ошибке компиляции. +Из-за ограничений языка, сообщение об ошибке далеко от понимания: +вам скажут что-то похожее на "evaluation of constant value failed", а указатель на ошибку +*не* покажет на проблемное значение прерывания -- +мы извиняемся за это! |
