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}}