| name | wire-task |
| description | Create or modify a FreeRTOS task in the Rexio flight controller. Handles task creation, core pinning, priority, stack sizing, topic pub/sub wiring, and watchdog registration. Use when adding a new RTOS task or modifying task architecture, or when the user says /wire-task. |
Create a new FreeRTOS task or modify an existing one. Validates all parameters against the architecture before writing code.
Input
Gather these parameters (ask user if not provided):
- Task name (e.g.,
flight_ctrl, commander, telemetry_tx)
- Core — 0 (comms/ops) or 1 (flight-critical)
- Priority — integer (higher = more important). Check
references/task_table.md for existing allocations.
- Stack size — bytes (minimum 2048, must be multiple of 4)
- Rate — Hz (or "event-driven")
- Trigger mechanism:
hw_timer — hardware timer ISR → vTaskNotifyGiveFromISR() → ulTaskNotifyTake() in task
vtaskdelay — vTaskDelay(pdMS_TO_TICKS(period_ms)) loop
event — blocks on queue or notification (UART data, etc.)
- Topics produced — list of TOPIC_* this task publishes
- Topics consumed — list of TOPIC_* this task reads via topic_copy()
- Watchdog — whether to register with TWDT (Task Watchdog Timer)
Validation
Before writing any code, validate:
-
Priority conflict: Read references/task_table.md. No two tasks on the same core should share a priority unless explicitly intended. Warn if conflict detected.
-
Core assignment: Flight-critical tasks (flight_ctrl, commander) MUST be on Core 1. Communication/ops tasks MUST be on Core 0. This is per ADR-011.
-
Stack size: Minimum 2048. flight_ctrl needs 8192 (deep call chain). Tasks using printf/logging need at least 4096.
-
Rate feasibility: Tasks on Core 1 must not exceed 500 Hz total. Tasks on Core 0 have more budget but beware of BLE jitter.
Code Generation
Task Function
Read references/task_patterns.md for the correct pattern. Generate the task function in the appropriate component's source file.
For hw_timer trigger:
static void {name}_task(void *arg) {
(void)arg;
TickType_t last_wake = xTaskGetTickCount();
while (1) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
uint64_t t0 = g_hal_time->get_time_us();
uint64_t elapsed = g_hal_time->get_time_us() - t0;
(void)elapsed;
}
}
For vtaskdelay trigger:
static void {name}_task(void *arg) {
(void)arg;
const TickType_t period = pdMS_TO_TICKS({1000 / rate_hz});
while (1) {
uint64_t t0 = g_hal_time->get_time_us();
vTaskDelay(period);
}
}
For event trigger:
static void {name}_task(void *arg) {
(void)arg;
while (1) {
}
}
HW Timer ISR (if hw_timer trigger)
static void IRAM_ATTR {name}_timer_isr(void *arg) {
BaseType_t higher_prio_woken = pdFALSE;
vTaskNotifyGiveFromISR((TaskHandle_t)arg, &higher_prio_woken);
portYIELD_FROM_ISR(higher_prio_woken);
}
Task Creation in app_main()
Add the xTaskCreatePinnedToCore() call in main/main.c → app_main():
static TaskHandle_t {name}_handle;
xTaskCreatePinnedToCore(
{name}_task,
"{name}",
{stack_size},
NULL,
{priority},
&{name}_handle,
{core}
);
Place it in the correct position in the init sequence (see architecture.md section 7.3):
- HAL init
- topics_init()
- Sensor init
- Algorithm init (AHRS, estimator, controller)
- commander_init()
- blackbox_init()
- Telemetry init
- Create tasks (here)
- Subscribe to TWDT
Watchdog Registration
If watchdog is enabled, add after task creation:
esp_task_wdt_add(NULL);
esp_task_wdt_reset();
Architecture Documentation
Update the task table in docs/architecture.md section 7.1 with the new task's parameters.
Scope Boundaries
- Generate task SHELL only — business logic is implemented via
/tdd-cycle
- Do NOT create components (that's
/new-component)
- Do NOT modify the topic bus or HAL
- Do NOT implement sensor reading, PID computation, etc. — just wire the task skeleton
- DO wire topic_copy/topic_publish calls as scaffolding comments showing which topics flow through this task