5.8 KiB
Очередь таймера
Когда включена опция timer-queue
, фреймворк RTFM включает
глобальную очередь таймера, которую приложения могут использовать, чтобы
планировать программные задачи на запуск через некоторое время в будущем.
Чтобы была возможность планировать программную задачу, имя задачи должно
присутствовать в аргументе schedule
контекста атрибута. Когда задача
планируется, момент (Instant
), в который задачу нужно запустить, нужно передать
как первый аргумент вызова schedule
.
Рантайм RTFM включает монотонный, растущий только вверх, 32-битный таймер,
значение которого можно запросить конструктором Instant::now
. Время (Duration
)
можно передать в Instant::now()
, чтобы получить Instant
в будущем. Монотонный
таймер отключен пока запущен init
, поэтому Instant::now()
всегда возвращает
значение Instant(0 /* циклов тактовой частоты */)
; таймер включается сразу перед
включением прерываний и запуском idle
.
В примере ниже две задачи планируются из init
: foo
и bar
. foo
-
запланирована на запуск через 8 миллионов тактов в будущем. Кроме того, bar
запланирован на запуск через 4 миллиона тактов в будущем. bar
запустится раньше
foo
, т.к. он запланирован на запуск первым.
ВАЖНО: Примеры, использующие API
schedule
или абстракциюInstant
не будут правильно работать на QEMU, потому что функциональность счетчика тактов Cortex-M не реализована вqemu-system-arm
.
{{#include ../../../../examples/schedule.rs}}
Запуск программы на реальном оборудовании производит следующий вывод в консоли:
{{#include ../../../../ci/expected/schedule.run}}
Периодические задачи
Программные задачи имеют доступ к Instant
в момент, когда были запланированы
на запуск через переменную scheduled
. Эта информация и API schedule
могут
быть использованы для реализации периодических задач, как показано в примере ниже.
{{#include ../../../../examples/periodic.rs}}
Это вывод, произведенный примером. Заметьте, что есть смещение / колебание нуля
даже если schedule.foo
была вызвана в конце foo
. Использование
Instant::now
вместо scheduled
имело бы влияние на смещение / колебание.
{{#include ../../../../ci/expected/periodic.run}}
Базовое время
Для задач, планируемых из init
мы имеем точную информацию о их планируемом
(scheduled
) времени. Для аппаратных задач нет scheduled
времени, потому
что эти задачи асинхронны по природе. Для аппаратных задач рантайм предоставляет
время старта (start
), которе отражает время, в которое обработчик прерывания
был запущен.
Заметьте, что start
не равен времени возникновения события, вызвавшего
задачу. В зависимости от приоритета задачи и загрузки системы время
start
может быть сильно отдалено от времени возникновения события.
Какое по Вашему мнению будет значение scheduled
для программных задач которые
вызываются, вместо того чтобы планироваться? Ответ в том, что вызываемые
задачи наследуют базовое время контекста, в котором вызваны. Бызовым для
аппаратных задач является start
, базовым для программных задач - scheduled
и базовым для init
- start = Instant(0)
. idle
на сомом деле не имеет
базового времени но задачи, вызванные из него будут использовать Instant::now()
как их базовое время.
Пример ниже демонстрирует разное значение базового времени.
{{#include ../../../../examples/baseline.rs}}
Запуск программы на реальном оборудовании произведет следующий вывод в консоли:
{{#include ../../../../ci/expected/baseline.run}}