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 byup.
Adding another AVR is mostly a matter of adding its timer block here.