# K15 — Explicit FromISR, UART and GPIO wrappers K15 routes a real Hazard3 machine-external interrupt through the official FreeRTOS RISC-V trap path. The C++ layer keeps task and ISR views explicit: UartTaskView/GpioTaskView contain configuration and output operations, while UartIsrView/GpioIsrView expose only bounded register reads and clears. One IsrContext accumulates wake requests from two primitives: UART RX bytes: 0x41, 0x42 static queue capacity: 1 accepted: 0x41 overflow policy: drop-newest -> 0x42 dropped GPIO edge: task notification higherPriorityTaskWoken: true yield_if_needed calls: exactly 1 The high-priority receiver consumes byte 0x41 and notification count 1, then drives GPIO output high. It runs before the interrupted stimulus continues, which proves the ISR-requested context switch. ## Build make check The gate includes a host contract test, freestanding ABI/storage checks and a real external-IRQ simulation on Hazard3. ## Debug riscv64-unknown-elf-gdb build/task01_isr_drivers/prog.elf b isr_drivers_debug_checkpoint p/x g_mcause p g_rx_queued p g_rx_dropped p/x g_receiver_byte p/x g_dropped_byte p g_higher_priority_task_woken p g_isr_yield_calls p g_stimulus_after_seen_by_receiver p g_receiver_done_at_stimulus_resume p g_isr_drivers_pass ## Scope boundary ISR code cannot call a blocking task API. Parsing, debounce and GPIO policy belong to a task. Backpressure is explicit: this exercise uses drop-newest and counts the dropped byte. The handler creates one IsrContext and calls yield_if_needed once, after all FromISR publications and peripheral clears.