Создание обработчика прерываний
Цель этого упражнения — обработать прерывание, которое срабатывает при нажатии кнопки BOOT.
Заготовку кода для этого упражнения можно найти в advanced/button-interrupt/src/main.rs.
Решение упражнения находится в advanced/button-interrupt/examples/solution.rs. Запустить его можно командой:
cargo run --example solution
✅ Задания
- Настройте кнопку BOOT (GPIO9) с помощью структуры
PinDriverсо следующими параметрами:- режим входа (Input mode);
- подтяжка к питанию (Pull up);
- прерывание по положительному фронту (Interrupt on positive edge).
- Создайте новое уведомление (notification) и notifier:
- см. документацию
hal::task::notification.
- см. документацию
- В блоке
unsafeсоздайте подписку и её функцию обратного вызова.- см.
PinDriver::subscribeиtask::notify_and_yield; - причины, по которым это
unsafe:- функция обратного вызова выполняется в ISR (Interrupt Service Routine), поэтому не следует вызывать в ней блокирующие функции; это относится к STD,
libcи API FreeRTOS (за исключением нескольких разрешённых); - замыкание обратного вызова захватывает своё окружение, и в него можно передать статические переменные. Захваченные переменные должны переживать подписку. Можно также использовать нестатические переменные, но для этого нужна дополнительная осторожность; подробнее см. документацию
esp_idf_hal::gpio::PinDriver::subscribe_nonstatic.
- функция обратного вызова выполняется в ISR (Interrupt Service Routine), поэтому не следует вызывать в ней блокирующие функции; это относится к STD,
- см.
- В цикле включите прерывание и дождитесь уведомления:
- прерывание нужно включать после каждого полученного уведомления, из контекста не-ISR;
- для ожидания можно использовать
esp_idf_svc::hal::delay::BLOCK.
- Запустите программу, нажмите кнопку
BOOTи посмотрите, как это работает!
🔎 В этом упражнении мы используем уведомления, которые передают только последнее значение. Если прерывание сработало несколько раз до того, как прочитано значение уведомления, вы сможете прочитать только последнее. Очереди, напротив, позволяют получить несколько значений. Подробнее см. esp_idf_hal::task::queue::Queue.