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/timer-queue.md | |
| parent | 83cdf00eecb0f14857b5e0f28e884b2120eabb18 (diff) | |
update russian translation of the book
Diffstat (limited to 'book/ru/src/by-example/timer-queue.md')
| -rw-r--r-- | book/ru/src/by-example/timer-queue.md | 122 |
1 files changed, 70 insertions, 52 deletions
diff --git a/book/ru/src/by-example/timer-queue.md b/book/ru/src/by-example/timer-queue.md index 3c35e29..c8818d7 100644 --- a/book/ru/src/by-example/timer-queue.md +++ b/book/ru/src/by-example/timer-queue.md @@ -1,57 +1,76 @@ # Очередь таймера -Когда включена опция `timer-queue`, фреймворк RTIC включает -*глобальную очередь таймера*, которую приложения могут использовать, чтобы -*планировать* программные задачи на запуск через некоторое время в будущем. - -Чтобы была возможность планировать программную задачу, имя задачи должно -присутствовать в аргументе `schedule` контекста атрибута. Когда задача -планируется, момент ([`Instant`]), в который задачу нужно запустить, нужно передать -как первый аргумент вызова `schedule`. - -[`Instant`]: ../../../api/rtic/struct.Instant.html - -Рантайм RTIC включает монотонный, растущий только вверх, 32-битный таймер, -значение которого можно запросить конструктором `Instant::now`. Время ([`Duration`]) -можно передать в `Instant::now()`, чтобы получить `Instant` в будущем. Монотонный -таймер отключен пока запущен `init`, поэтому `Instant::now()` всегда возвращает -значение `Instant(0 /* циклов тактовой частоты */)`; таймер включается сразу перед -включением прерываний и запуском `idle`. - -[`Duration`]: ../../../api/rtic/struct.Duration.html - -В примере ниже две задачи планируются из `init`: `foo` и `bar`. `foo` - -запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, `bar` -запланирован на запуск через 4 миллиона тактов в будущем. `bar` запустится раньше -`foo`, т.к. он запланирован на запуск первым. - -> **ВАЖНО**: Примеры, использующие API `schedule` или абстракцию `Instant` -> **не** будут правильно работать на QEMU, потому что функциональность счетчика -> тактов Cortex-M не реализована в `qemu-system-arm`. +В отличие от интерфейса `spawn`, который немедленно передает программную задачу +планировщику для немедленного запуска, интерфейс `schedule` можно использовать +для планирования задачи к запуске через какое-то время в будущем. + +Чтобы использовать интерфейс `schedule`, предварительно должен быть определен +монотонный таймер с помощью аргумента `monotonic` атрибута `#[app]`. +Этот аргумент принимает путь к типу, реализующему трейт [`Monotonic`]. +Ассоциированный тип, `Instant`, этого трейта представляет метку времени в соответствущих +единицах измерения и широко используется в интерфейсе `schedule` -- предлагается смоделировать +этот тип позднее [один из таких есть в стандартной библиотеке][std-instant]. + +Хотя это не отражено в определении трейта (из-за ограничений системы типов / трейтов), +разница двух `Instant`ов должна возвращать какой-то тип `Duration` (см. [`core::time::Duration`]) +и этот `Duration` должен реализовывать трейт `TryInto<u32>`. +Реализация этого трейта должна конвертировать значение `Duration`, которое +использует какую-то определенную единицу измерения времени, в единицы измерения "тактов системного таймера +(SYST)". Результат преобразований должен быть 32-битным целым. +Если результат не соответствует 32-битному целому, тогда операция должна возвращать ошибку любого типа. + +[`Monotonic`]: ../../../api/rtic/trait.Monotonic.html +[std-instant]: https://doc.rust-lang.org/std/time/struct.Instant.html +[`core::time::Duration`]: https://doc.rust-lang.org/core/time/struct.Duration.html + +Для целевых платформ ARMv7+ крейт `rtic` предоставляет реализацию `Monotonic`, основанную на +встроенном CYCle CouNTer (CYCCNT). Заметьте, что это 32-битный таймер, работающий на +частоте центрального процессора, и поэтому не подходит для отслеживания интервалов времени в секундах. + +Когда планируется задача, (определенный пользователем) `Instant`, в который задача должна быть +выполнена, должен передаваться в качестве первого аргумента вызова `schedule`. + +К тому же, выбранный `monotonic` таймер, необходимо сконфигурировать и инициализировать в +фазе работы `#[init]`. Заметьте, что *также* касается случая использования `CYCCNT`, +предоставляемого крейтом `cortex-m-rtic`. + +Пример ниже планирует к выполнению две задачи из `init`: `foo` и `bar`. `foo` запланирована +к запуску через 8 миллионов циклов в будущем. Далее, `bar` запланировано запустить через +4 миллиона циклов в будущем. Таким образом, `bar` запустится до `foo`, так как и запланировано. + +> **DF:YJ**: Примеры, использующие интерфейс `schedule` или абстракцию `Instant` +> **не будут** правильно работать на эмуляторе QEMU, поскольку счетчик циклов Cortex-M +> функционально не был реализован в `qemu-system-arm`. ``` rust {{#include ../../../../examples/schedule.rs}} ``` -Запуск программы на реальном оборудовании производит следующий вывод в консоли: +Запусе программы на реальном оборудовании создает следующий вывод в консоли: ``` text {{#include ../../../../ci/expected/schedule.run}} ``` +Когда интерфейс `schedule` используется, среда исполнения использует внутри +обработчик прерываний `SysTick` и периферию системного таймера (`SYST`), поэтому ни +тот ни другой нельзя использовать в программе. Это гарантируется изменением типа +`init::Context.core` с `cortex_m::Peripherals` на `rtic::Peripherals`. +Последняя структура содержит все поля из предыдущей кроме `SYST`. + ## Периодические задачи -Программные задачи имеют доступ к `Instant` в момент, когда были запланированы -на запуск через переменную `scheduled`. Эта информация и API `schedule` могут -быть использованы для реализации периодических задач, как показано в примере ниже. +Программные задачи имеют доступ к моменту времени `Instant`, в который они были запланированы +на выполнение переменной `scheduled`. Эта информация и интерфейс `schedule` можно использовать, +чтобы реализовать периодические задачи, как показано ниже. ``` rust {{#include ../../../../examples/periodic.rs}} ``` -Это вывод, произведенный примером. Заметьте, что есть смещение / колебание нуля -даже если `schedule.foo` была вызвана в *конце* `foo`. Использование -`Instant::now` вместо `scheduled` имело бы влияние на смещение / колебание. +Это вывод, создаваемый примером. Заметьте, что здесь пристствует небольшой дрейф / колебания +даже несмотря на то, что `schedule.foo` была вызвана в *конце* `foo`. Использование +`Instant::now` вместо `scheduled` вызвало бы дрейф / колебания. ``` text {{#include ../../../../ci/expected/periodic.run}} @@ -59,31 +78,30 @@ ## Базовое время -Для задач, планируемых из `init` мы имеем точную информацию о их планируемом -(`scheduled`) времени. Для аппаратных задач нет `scheduled` времени, потому -что эти задачи асинхронны по природе. Для аппаратных задач рантайм предоставляет -время старта (`start`), которе отражает время, в которое обработчик прерывания -был запущен. +Для задач, вызываемых из `init` мы имеем точную информацию о их `scheduled` времени. +Для аппаратных задач такого времени нет, поскольку они асинхронны по природе. +Для аппаратных задач среда исполнения предоставляет время запуска (`start`), которое отражает +время, в которое обработчик прерывания будет запущен. -Заметьте, что `start` **не** равен времени возникновения события, вызвавшего -задачу. В зависимости от приоритета задачи и загрузки системы время -`start` может быть сильно отдалено от времени возникновения события. +Заметьте, что `start` **не** равно времени прихода события, которое вызывает задачу. +В зависимости от приоритета задачи и загрузки системы, время `start` может сильно отдалиться от +времени прихода события. -Какое по Вашему мнению будет значение `scheduled` для программных задач которые -*вызываются*, вместо того чтобы планироваться? Ответ в том, что вызываемые -задачи наследуют *базовое* время контекста, в котором вызваны. Бызовым для -аппаратных задач является `start`, базовым для программных задач - `scheduled` -и базовым для `init` - `start = Instant(0)`. `idle` на сомом деле не имеет -базового времени но задачи, вызванные из него будут использовать `Instant::now()` -как их базовое время. +Какое по вашему мнению будет значение `scheduled` для программных задач, которые вызываются через +`spawn` вместо планирования? Ответ в том, что вызываемые задачи наследуют +*базовое* время того контекста, который их вызывает. Базовое время аппаратных задач - +это их время `start`, базовое время программных задач - их время `scheduled`, а +базовое время `init` - время старта системы, или нулевое +(`Instant::zero()`). `idle` на самом деле не имеет базового времени, но задачи вызываемые из нее, +используют `Instant::now()` в качестве базового. -Пример ниже демонстрирует разное значение *базового времени*. +Пример ниже демонстрирует разные смыслы *базового времени*. ``` rust {{#include ../../../../examples/baseline.rs}} ``` -Запуск программы на реальном оборудовании произведет следующий вывод в консоли: +Запуск программы на реальном оборудовании приведет к следующему выводу в консоли: ``` text {{#include ../../../../ci/expected/baseline.run}} |
