platform/xtensa
skip to the library navigationImportable on every target; it declares its items only where compiler.arch == xtensa.
Windowed Xtensa interrupt masking, enabled and pending CPU lines, the cycle counter, waiting and memory barriers, declared on xtensa alone.
Save the PS from disable_interrupts or mask_level_one and restore it in reverse order, including on early returns. mask_level_one leaves higher-priority interrupts enabled; it may only raise the current level from zero or one. Masking does not stop exceptions, NMI or the debugger. Device descriptions route peripheral sources through the interrupt matrix to the CPU lines that set_enabled_lines selects.
wait_for_interrupt enables ordinary interrupts and may wake spuriously. Recheck the condition after waking. Barriers order accesses; they do not prove a peripheral operation completed.
Items
When compiler.arch == xtensa
public compiler_barrier: () -> none
Prevent compiler memory knowledge from crossing this point.
When compiler.arch == xtensa
public completion_barrier: () -> none
Complete preceding explicit memory accesses as MEMW specifies.
When compiler.arch == xtensa
public cycles: () -> (ticks: u32)
Read the cycle counter; arithmetic across wrapping uses +% and -%.
When compiler.arch == xtensa
public device_barrier: () -> none
Order memory and peripheral accesses. The peripheral's completion status must still be checked separately.
When compiler.arch == xtensa
public disable_interrupts: () -> (previous: u32)
Mask ordinary interrupts and return the preceding PS.
When compiler.arch == xtensa
public enabled_lines: () -> (lines: u32)
Read the CPU interrupt enables.
When compiler.arch == xtensa
public interrupt_mask: () -> (current: u32)
The current PS.INTLEVEL: zero permits every enabled interrupt.
When compiler.arch == xtensa
public mask_level_one: () -> (previous: u32)
Mask level-one interrupts, leaving higher-priority interrupts able to run. Call only when raising the current level from zero or one.
When compiler.arch == xtensa
public pending_lines: () -> (lines: u32)
Read the CPU interrupt-pending bits, before interrupt masking.
When compiler.arch == xtensa
public restore_interrupts: (previous: u32) -> none
Restore the PS that disable_interrupts or mask_level_one returned.
When compiler.arch == xtensa
public set_enabled_lines: (lines: u32) -> none
Replace INTENABLE with the selected CPU interrupt lines. The device's interrupt matrix routes its sources to these lines.
When compiler.arch == xtensa
public wait_for_interrupt: () -> none
Complete earlier accesses and wait with ordinary interrupts enabled. WAITI sets INTLEVEL to zero. Recheck the condition after waking; a wakeup need not mean the awaited device completed.
Example program
This complete program is one of the compiler's runtime tests. View source.
The program, 31 lines
import platform/xtensa fixed if compiler.arch == xtensa then nested_masks_restore: () -> (ok: bool) = before := xtensa.interrupt_mask() enabled := xtensa.enabled_lines() outer := xtensa.disable_interrupts() inner := xtensa.disable_interrupts() masked := xtensa.interrupt_mask() xtensa.compiler_barrier() xtensa.restore_interrupts(inner) still := xtensa.interrupt_mask() xtensa.restore_interrupts(outer) after := xtensa.interrupt_mask() low := xtensa.mask_level_one() only_low := xtensa.interrupt_mask() xtensa.restore_interrupts(low) xtensa.set_enabled_lines(enabled) xtensa.device_barrier() xtensa.completion_barrier() ok = masked == 15 and still == 15 and after == before and only_low == 1 and xtensa.enabled_lines() == enabled end nested_masks_restore else nested_masks_restore: () -> (ok: bool) = ok = true end nested_masks_restore end if public main: () -> (code: i32) = code = 1 if nested_masks_restore() then code = 42 end if end main