Как и в других случаях, информация о задачах доступна с помощью команды "show":
Команда | Описание и примеры |
---|---|
show tasks |
Выводит список запущенных процессов, их ID, приоритет, имя и состояние: esp32#>show ta % # | Task ID | Name | Prio | State %----+------------+------------------+------+----------- % 1| 0x3fca300c | ESPShell | 5 | Running % 2| 0x3fca7264 | IDLE0 | 0 | Ready % 3| 0x3fca5f64 | pin | 0 | Ready % 4| 0x3fca783c | IDLE1 | 0 | Ready % 5| 0x3fcaace8 | loopTask | 1 | Waiting % 6| 0x3fca85f4 | Tmr Svc | 1 | Waiting % 7| 0x3fca1790 | ipc1 | 24 | Suspended % 8| 0x3fca11f8 | ipc0 | 24 | Suspended % 9| 0x3fca5484 | esp_timer | 22 | Suspended %----+------------+------------------+------+----------- % Total: 9 tasks esp32#> |
Управление процессами реализовано с помощью четырех команд: suspend, resume, priority и kill. Под процессами имеются в виду задачи FreeRTOS: например, основная функция Arduino loop() обрабатывается отдельной задачей FreeRTOS с именем "loop", то есть "loop()" - это процесс (в списке задач он находится под именем "loopTask").
Доступ к задачам и управление ими осуществляется по их TASK_ID (шестнадцатеричное число, например "0x3fca370c") или по имени, за исключением основной задачи loop() Arduino: выполнение основного скетча можно контролировать, опустив параметр TASK_ID в команде. То есть, чтобы приостановить скетч, вместо "suspend 0x12345678" можно использовать команду "suspend" без аргументов.
ВАЖНО: Несколько процессов могут иметь полностью одинаковые имена. Такое происходит, например, когда запускается несколько фоновых команд, скажем, "pin":
esp32#>pin 2 low delay 100 high delay 100 loop infinite & esp32#>pin 4 low delay 200 high delay 200 loop infinite &В списке процессов будет два процесса с одинаковым именем "pin". В таком случае следует использовать TASK_ID, а не имя. Если же использовать имя задачи, то операция будет производится над первой задачей с таким именем в списке. Порядковый номер задачи в списке постоянно меняется, на него нельзя полагаться.
Хорошо, но где взять эти task id и имена?
Например, можно воспользоваться командой "show tasks":
esp32#>show tasks % # | Task ID | Name | Prio | State %----+------------+------------------+------+----------- % 1| 0x3fca783c | IDLE1 | 0 | Ready % 2| 0x3fca7264 | IDLE0 | 0 | Ready % 3| 0x3fca300c | ESPShell | 0 | Running % 4| 0x3fca5f64 | pin | 0 | Ready % 5| 0x3fcaace8 | loopTask | 1 | Waiting % 6| 0x3fca1790 | ipc1 | 24 | Suspended % 7| 0x3fca11f8 | ipc0 | 24 | Suspended % 8| 0x3fca5484 | esp_timer | 22 | Suspended % 9| 0x3fca85f4 | Tmr Svc | 1 | Waiting %----+------------+------------------+------+----------- % Total: 9 tasks esp32#>
Так же, каждая команда ESPShell, которая запускается как процесс, всегда выводит свой TASK_ID. Допустим, мы запускаем команду "pin 2 delay 1000" в фоновом режиме:
esp32#>pin 2 delay 1000 & % Background task started % Copy/paste "kill 0x3ffb91dc" to abort esp32#>Эта простая команда ничего не делает, кроме как ждёт 1000 мс. После запуска она выводит свой task id и команду, которую можно скопировать и выполнить: "kill 0x3ffb91dc".
Другим источником TASK_ID является команда "show counters"
Команда | Описание и примеры |
---|---|
suspend |
Приостанавливает выполнение скетча: приостанавливает loop() Arduino. Задачи, которые были запущены из loop() и setup(), не приостанавливаются этой командой. Приостановка задачи вместе со всеми её дочерними задачами - запланированная, но пока не реализованная возможность. Комбинация клавиш Ctrl+C является горячей клавишей для команды "suspend" |
suspend TASK_ID |
suspend TASK_ID Приостанавливает произвольную задачу, если известен её идентификатор. Команда требует один аргумент - идентификатор задачи (в шестнадцатеричном формате) |
resume |
Возобновляет выполнение скетча |
resume TASK_ID |
resume TASK_ID Возобновляет произвольную задачу, если известен её идентификатор. Команда требует один аргумент - идентификатор задачи (в шестнадцатеричном формате) |
Чтобы остановить задачу ESPShell (ESPShell использует задачи для запуска фоновых команд) или произвольную задачу FreeRTOS, можно воспользоваться командой "kill":
Команда | Описание и примеры |
---|---|
kill TASK_ID | "kill [-TERM | -15 | -KILL | -9] TASK_ID" Останавливает выполнение задачи с TASK_ID. Этот идентификатор либо выводится при запуске фоновой команды, либо может быть произвольным идентификатором FreeRTOS-задачи. Если в конце команды используется символ "&", то ESPShell выполняет такую команду в фоновом режиме, создавая новую задачу:
esp32#>pin 2 delay 999 & % Background task started % Copy/paste "kill 0x3fca370c" command to stop execution ← обратите внимание на TASK_ID esp32#> В простейшем случае, когда используется только один параметр (TASK_ID), команда отправляет уведомление задаче, которую нужно завершить, чтобы она могла завершиться корректно. Команда старается имитировать классическую команду "kill" из Linux и принимает дополнительный параметр - сигнал, который нужно отправить: -9 или -KILL означает принудительное завершение задачи. Уведомление не отправляется, вместо этого задача приостанавливается и удаляется с помощью FreeRTOS API vTaskDelete(). При этом ресурсы, занятые задачей, не освобождаются. Завершение задачи, которая удерживает мьютекс, может привести к зависаниям. Все задачи, создаваемые ESPShell, должны завершаться таким образом - без указания дополнительных параметров. Однако есть примеры команд ESPShell, которые можно завершить только с помощью "kill -9", эти особые случаи описаны в описании команды "pin". Опция -15, -TERM или её отсутствие означает "корректное завершение": задача не удаляется, а получает возможность завершиться самостоятельно и освободить все используемые ресурсы (если таковые имеются). Опция -9 или -KILL приводит к приостановке задачи с её последующим удалением через API FreeRTOS vTaskDelete(). Эта опция эквивалентна команде Linux "kill -9", но в отличие от неё, ESPShell не освобождает ресурсы, которые могли быть выделены задачей. |
В ESP32 процессами (задачами) управляет модифицированная FreeRTOS, которая является одним из компонентов ESP-IDF.
Задачи, находящиеся под управлением FreeRTOS, получают управление в соответствии с присвоенными им приоритетами. Приоритет может принимать значение от 0 до 24: чем больше число, тем выше приоритет.
С максимальным приоритетом запускаются системные задачи межпроцессорного взаимодействия — ipc0 и ipc1. Высокий приоритет присвоен компонентам Bluetooth и Wi-Fi. Минимальный приоритет имеют так называемые idle-процессы: IDLE0 и IDLE1.
По умолчанию ESPShell запускается с приоритетом 0, что соответствует уровню системных idle-процессов. Все вспомогательные задачи, создаваемые шеллом, также запускаются с этим приоритетом. Приоритет задач, инициируемых шеллом (например, фоновых команд), наследуется от него.
Приоритет можно изменить с помощью команды priority NUM [TASK_ID]. Если второй параметр (ID задачи) опущен, новое значение устанавливается для самого шелла. Если указан — приоритет будет изменён у соответствующей задачи.
Пример: посмотреть, какой приоритет установлен у шелла, поменять его на 5
esp32#>sh ta % # | Task ID | Name | Prio | State %----+------------+------------------+------+----------- % 1| 0x3fca5f64 | pin | 0 | Ready % 2| 0x3fca7264 | IDLE0 | 0 | Ready % 3| 0x3fca300c | ESPShell | 0 | Running % 4| 0x3fca783c | IDLE1 | 0 | Ready % 5| 0x3fcaace8 | loopTask | 1 | Waiting % 6| 0x3fca11f8 | ipc0 | 24 | Suspended % 7| 0x3fca5484 | esp_timer | 22 | Suspended % 8| 0x3fca85f4 | Tmr Svc | 1 | Waiting % 9| 0x3fca1790 | ipc1 | 24 | Suspended %----+------------+------------------+------+----------- % Total: 9 tasks esp32#>prio 5 esp32#>sh ta % # | Task ID | Name | Prio | State %----+------------+------------------+------+----------- % 1| 0x3fca300c | ESPShell | 5 | Running % 2| 0x3fca7264 | IDLE0 | 0 | Ready % 3| 0x3fca783c | IDLE1 | 0 | Ready % 4| 0x3fca5f64 | pin | 0 | Ready % 5| 0x3fcaace8 | loopTask | 1 | Waiting % 6| 0x3fca5484 | esp_timer | 22 | Suspended % 7| 0x3fca85f4 | Tmr Svc | 1 | Waiting
Примечание о приоритетах задач:
Команда шелла pin 2 low high loop inf генерирует прямоугольный сигнал с частотой 150 кГц при запуске с приоритетом IDLE. Однако при повышении приоритета до 2 частота увеличивается до 560 кГц.
Это происходит потому, что команда pin никогда не уступает управление процессору, не позволяя задачам с более низким приоритетом выполняться.