aboutsummaryrefslogtreecommitdiff
path: root/book/ru/src/by-example/timer-queue.md
diff options
context:
space:
mode:
Diffstat (limited to 'book/ru/src/by-example/timer-queue.md')
-rw-r--r--book/ru/src/by-example/timer-queue.md122
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}}