From 0cc9b0a8bdf774ee376937d5a6767ccdced51245 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 18 Jul 2026 10:10:04 +0200 Subject: kernel: a real timer source (64 Hz tick IRQ) + uptime(1) The kernel had no clock: TimerISR was a reti stub, IEF_TIMER masked, and IME was never enabled - the vectors were decorative. sys_sleep just polls DIV deltas per-process; nothing counted globally. Now: TAC runs the hardware timer at 16384 Hz with TMA=0, so TIMA overflows at exactly 64 Hz; TimerISR increments a monotonic 32-bit wTicks (wraps after ~2.1 years). Scheduling stays cooperative - the ISR is transparent. Enabling IME in a kernel written for zero interrupts needs care wherever SP points into memory whose bank is being switched (an IRQ pushes onto SP): - read_block/write_block map the disk bank over the $A000 window that holds the caller's stack -> di/ei around the transfer (~2ms, well under the 15.6ms tick period, so no tick is ever lost) - hSwitchTo switches SVBK + cart-RAM banks under the outgoing stack -> di on entry, ei once the incoming stack is mapped - fork already runs on KSTACK_TOP2 (fixed WRAM) - safe as-is - term_putc's SVBK switch only remaps $Dxxx, stacks live in $Axxx/$Cxxx SYS_UPTIME (36) copies the counter (4B LE, di/ei so the read can't tear) to a user buffer; libc gticks(); usr/uptime.c formats 'up [Nd] H:MM:SS'. uptime avoids SDCC long div/shift entirely: sm83.lib modules link into their own areas that land in the $A000 RAM window (latent build.sh trap, documented there) - bytewise >>6 plus bounded subtraction loops instead. --- include/gbos.inc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/gbos.inc b/include/gbos.inc index 92d8732..246628c 100644 --- a/include/gbos.inc +++ b/include/gbos.inc @@ -10,6 +10,10 @@ DEF GBOS_INC EQU 1 ; ----------------------------------------------------------------------------- DEF rIF EQU $FF0F ; interrupt flags DEF rIE EQU $FFFF ; interrupt enable +DEF rTIMA EQU $FF05 ; timer counter +DEF rTMA EQU $FF06 ; timer modulo (reload) +DEF rTAC EQU $FF07 ; timer control (bit2 = enable, bits1-0 = clock) +DEF IEF_TIMER EQU %00000100 DEF rDIV EQU $FF04 ; divider register: free-running 8-bit @ 16384 Hz DEF rSVBK EQU $FF70 ; CGB WRAM bank select ($D000-$DFFF): 1..7 DEF wCurMask EQU $D589 ; term/osk: cursor underline bits OR'd into a tile's last row @@ -134,7 +138,8 @@ DEF SYS_POLLIN EQU 32 ; poll OSK for a typed char (-> A=char or 0) DEF SYS_NET EQU 33 ; socket layer (DE=&netreq -> A=result) DEF SYS_SLEEP EQU 34 ; cooperative delay (B = 1/64-second units) DEF SYS_POLLCON EQU 35 ; poll console ring (link-injected -> A=byte or 0) -DEF SYS_MAX EQU 36 +DEF SYS_UPTIME EQU 36 ; copy the 64 Hz tick counter (4B LE) to [DE] +DEF SYS_MAX EQU 37 ; ---- socket layer (SYS_NET) -------------------------------------------------- ; netreq struct (in caller RAM; DE points to it): @@ -259,5 +264,6 @@ DEF PROG_PING EQU 27 DEF PROG_NSLOOKUP EQU 28 DEF PROG_DHCP EQU 29 DEF PROG_IRC EQU 30 +DEF PROG_UPTIME EQU 31 ENDC -- cgit v1.3.1-sl0p