Landin library reference discuss source

Importable 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

compiler_barrier

function platform/xtensa/xtensa.ldn:63 ↑ index

When compiler.arch == xtensa

public compiler_barrier: () -> none

Prevent compiler memory knowledge from crossing this point.

completion_barrier

function platform/xtensa/xtensa.ldn:60 ↑ index

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 -%.

device_barrier

function platform/xtensa/xtensa.ldn:57 ↑ index

When compiler.arch == xtensa

public device_barrier: () -> none

Order memory and peripheral accesses. The peripheral's completion status must still be checked separately.

disable_interrupts

function platform/xtensa/xtensa.ldn:6 ↑ index

When compiler.arch == xtensa

public disable_interrupts: () -> (previous: u32)

Mask ordinary interrupts and return the preceding PS.

enabled_lines

function platform/xtensa/xtensa.ldn:34 ↑ index

When compiler.arch == xtensa

public enabled_lines: () -> (lines: u32)

Read the CPU interrupt enables.

interrupt_mask

function platform/xtensa/xtensa.ldn:22 ↑ index

When compiler.arch == xtensa

public interrupt_mask: () -> (current: u32)

The current PS.INTLEVEL: zero permits every enabled interrupt.

mask_level_one

function platform/xtensa/xtensa.ldn:17 ↑ index

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.

pending_lines

function platform/xtensa/xtensa.ldn:39 ↑ index

When compiler.arch == xtensa

public pending_lines: () -> (lines: u32)

Read the CPU interrupt-pending bits, before interrupt masking.

restore_interrupts

function platform/xtensa/xtensa.ldn:11 ↑ index

When compiler.arch == xtensa

public restore_interrupts: (previous: u32) -> none

Restore the PS that disable_interrupts or mask_level_one returned.

set_enabled_lines

function platform/xtensa/xtensa.ldn:29 ↑ index

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.

wait_for_interrupt

function platform/xtensa/xtensa.ldn:51 ↑ index

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
compiler/tests/fixtures/runtime/library-platform-xtensa/main.ldn31 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