Основы RTOS: потоки и таймеры для управления логикой
Материал носит ознакомительный характер. Работа с электроникой и микроконтроллерами требует соблюдения техники безопасности; автор не несет ответственности за возможные повреждения оборудования или иной ущерб, возникший в ходе обучения.
Ранее вы управляли «железом» напрямую: мигали светодиодами через GPIO и считывали ADC. В мире Arduino код обычно выполняется в одном бесконечном цикле loop(). Это создает проблему: если добавить в цикл длинную задержку delay() или тяжелое вычисление, всё устройство «замрет» и перестанет реагировать на внешние события.
Для профессиональной разработки на nRF52840 мы используем Zephyr RTOS (операционную систему реального времени). Она позволяет процессору выполнять несколько задач одновременно, переключаясь между ними за доли микросекунд.
Что такое поток (Thread)
В Zephyr мы отказываемся от одного большого цикла. Программа разделяется на Thread (потоки). Поток — это независимый фрагмент кода, который «думает», что у него есть собственный процессор и своя память.
У каждого потока есть свой бюджет памяти — стек.
Осторожно: Если поток выйдет за пределы выделенного стека, произойдет ошибка Stack Overflow, и система уйдет в перезагрузку.
Как это работает
Ядро у nRF52840 одно, поэтому физически задачи выполняются по очереди. За переключение отвечает Планировщик (Scheduler). Он меняет активный поток так быстро, что создается полная иллюзия параллельной работы.
Приоритеты: кто важнее?
Планировщик ориентируется на приоритеты, которые вы назначаете при создании потока:
- Высокий приоритет: Для критических задач (например, мгновенная остановка мотора при срабатывании датчика).
- Низкий приоритет: Для фоновых процессов (например, отправка логов в консоль).
Если поток с высоким приоритетом готов к работе, планировщик немедленно прерывает текущую задачу и отдает ресурсы ему.
Синхронизация потоков
Когда несколько задач работают с общим ресурсом (например, одним портом UART), они могут конфликтовать. Если два потока начнут писать в UART одновременно, данные перемешаются в нечитаемую «кашу».
Для защиты ресурсов используйте:
- Мьютекс (Mutex): Своеобразный «ключ» от комнаты. Пока один поток держит мьютекс, остальные ждут под дверью.
- Семафор (Semaphore): Сигнальный флаг. Используется, чтобы один поток мог «разбудить» другой при наступлении события.
Пример с мьютексом
// Потоки будут ждать своей очереди перед этим блоком
k_mutex_lock(&my_uart_mutex, K_FOREVER);
// Безопасно работаем с периферией
print_uart_data("Важные данные");
k_mutex_unlock(&my_uart_mutex);
Обмен данными через Очереди сообщений
Если нужно передать данные из одного потока в другой, используйте Очередь сообщений (Message Queue). Это защищенный буфер, куда один поток «складывает» пакеты данных, а другой — забирает их.
Это надежнее глобальных переменных-флагов, которые в Arduino часто становились причиной трудноуловимых багов.
Практика: Таймеры и многозадачность
Сравним два подхода на задаче: мигать светодиодом и мгновенно реагировать на кнопку.
Линейный подход (Arduino-style):
while (1) {
led_on();
k_msleep(1000); // Процессор "тупит", кнопка не опрашивается!
led_off();
k_msleep(1000);
check_button();
}
Подход Zephyr RTOS: Мы создаем два независимых потока. Один мигает светодиодом, второй — следит за кнопкой.
// Создаем потоки макросом: имя, размер стека, функция, приоритет
K_THREAD_DEFINE(led_tid, 1024, led_blink_fn, NULL, NULL, NULL, 7, 0, 0);
K_THREAD_DEFINE(btn_tid, 1024, btn_monitor_fn, NULL, NULL, NULL, 5, 0, 0);
Обратите внимание: Приоритет кнопки (5) выше, чем у светодиода (7). Реакция на нажатие будет мгновенной, даже если светодиод в этот момент «спит».
Системные таймеры и энергосбережение
В RTOS функция k_msleep() не просто сжигает такты процессора. Она сообщает планировщику: «Этот поток спит 100 мс, займись другими делами». Если все потоки спят, nRF52840 автоматически переходит в режим пониженного энергопотребления, экономя заряд батареи.
Вы освоили фундамент управления логикой современного чипа. Теперь ваше устройство может выполнять десятки задач параллельно. Это критически важно для следующего шага: работы с Bluetooth. Стек протоколов BLE — это тоже набор высокоприоритетных потоков, и теперь вы понимаете, как не мешать их работе.
В следующем уроке разберем иерархию Bluetooth и роли, которые может принимать nRF52840 в беспроводной сети.