Boot and init

boot.ik is the entry point. @main initialises each subsystem in order, seeds and runs the /init script, starts the shell as process 0, arms the watchdog, enables interrupts, and hands control to the scheduler, which never returns.

@main {
    %WDT_STATUS_REG & 0xF7 -> %WDT_STATUS_REG   # clear the WDT reset flag
    @wdt_disable()                   # disable the watchdog for slow init
    @uart_init(UART_UBRR)            # console up
    @kbanner()                       # print the banner
    @sched_init()                    # mark every process slot free
    @timer_init()                    # start the Timer0 tick
    ? @fs_blank(DEV_ROOT) == 1 { @fs_format(DEV_ROOT) }
    @_seed_init()                    # create /init if missing
    @proc_start(0, &@shell_main)     # admit the shell as pid 0
    @wdt_enable(0x07)                # arm the ~2 s hang-recovery watchdog
    @sei()                           # enable interrupts
    @scheduler()                     # run forever
}

Order matters. The root filesystem is formatted only if the EEPROM does not already hold a valid tree, so data survives a reset. The watchdog is disabled across the slow boot-time init (an EEPROM format is many ~8 ms writes) and armed only just before the scheduler, which kicks it every pass (see Scheduler and processes).

The kernel does not clear SRAM itself: the compiler emits a crt0-style routine that zeroes the whole SRAM before @main runs (the AVR does not reset RAM), so every global starts from a known state. See Memory maps.

@kbanner()

Print the boot banner — the name, version codename, copyright and license — to the UART. It is intentionally compact to save flash.

Per-target timer

arch/timer.ik is a small hardware abstraction layer. Each supported device gets a ? target == ... block that programs Timer0 in CTC mode with a 1024 prescaler and enables the compare-match interrupt:

@timer_init()

Configure Timer0 for a periodic compare-match interrupt. The matching ISR, TIMER0_COMPA, increments the global tick counter read by up.

Adding another AVR is mostly a matter of adding its timer block here.