diff options
Diffstat (limited to '')
| -rw-r--r-- | src/blk.asm | 5 | ||||
| -rw-r--r-- | src/boot.asm | 14 | ||||
| -rw-r--r-- | src/hram.asm | 5 | ||||
| -rw-r--r-- | src/kdata.asm | 1 | ||||
| -rw-r--r-- | src/programs.asm | 7 | ||||
| -rw-r--r-- | src/sched.asm | 25 | ||||
| -rw-r--r-- | src/syscall.asm | 19 |
7 files changed, 70 insertions, 6 deletions
diff --git a/src/blk.asm b/src/blk.asm index 2be961e..76561da 100644 --- a/src/blk.asm +++ b/src/blk.asm @@ -34,6 +34,8 @@ ENDM ; ----------------------------------------------------------------------------- read_block:: ld c, a + di ; the tick ISR pushes on SP, which points into + ; the $A000 window we are about to remap srl a srl a srl a @@ -54,6 +56,7 @@ read_block:: dec b jr nz, .cp restore_bank ; inline - no stack while the disk bank is mapped + ei ret ; ----------------------------------------------------------------------------- @@ -61,6 +64,7 @@ read_block:: ; ----------------------------------------------------------------------------- write_block:: ld c, a + di ; see read_block srl a srl a srl a @@ -81,6 +85,7 @@ write_block:: dec b jr nz, .cp restore_bank + ei ret ; ============================================================================= diff --git a/src/boot.asm b/src/boot.asm index c2d461a..4049f9d 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -81,11 +81,19 @@ KernelInit: call SchedInit ; pick first task, set wCurProc - ; interrupts: enable timer for preemption + ; system tick: hardware timer at 16384 Hz input, TMA=0 -> TIMA overflow + ; IRQ at 64 Hz. TimerISR just counts (wTicks); scheduling stays + ; cooperative. Only the timer bit is enabled in IE. + xor a + ld [rTIMA], a + ld [rTMA], a + ld a, %00000111 ; enable | 16384 Hz + ld [rTAC], a xor a ld [rIF], a - ; ld a, IEF_TIMER ; (timer bit) - leave masked for cooperative demo - ; ld [rIE], a + ld a, IEF_TIMER + ld [rIE], a + ei ; hand control to the first task via a context switch-in jp SchedRunFirst diff --git a/src/hram.asm b/src/hram.asm index 7c1910c..9e65982 100644 --- a/src/hram.asm +++ b/src/hram.asm @@ -31,6 +31,9 @@ LOAD "hram_code", HRAM ; Runs from HRAM. Saves/restores full context. Clobbers everything. ; --------------------------------------------------------------------------- hSwitchTo:: + di ; no tick ISR while SP and the banks under it + ; are out of sync (pushes would hit the wrong + ; bank); ei below once the incoming stack is up ; stash target while DE is still valid ld a, e ld [hSwitchTgt], a @@ -114,6 +117,8 @@ hSwitchTo:: ld sp, hl ; --- pop incoming context and resume it --- + ei ; SP + banks consistent again (takes effect + ; after the next instruction) pop hl pop de pop bc diff --git a/src/kdata.asm b/src/kdata.asm index 65a059a..b0cd71b 100644 --- a/src/kdata.asm +++ b/src/kdata.asm @@ -65,3 +65,4 @@ wPnStart:: DS 2 ; scratch for sys_progname wBootA:: DS 1 ; A at entry: console model from the boot ROM wBootB:: DS 1 ; B at entry: bit0 set = AGB (GBA in CGB mode) wBootFsFresh::DS 1 ; fs_init formatted a blank disk this boot +wTicks:: DS 4 ; monotonic 64 Hz system tick (TimerISR), LE diff --git a/src/programs.asm b/src/programs.asm index 6dbc584..7c17fb5 100644 --- a/src/programs.asm +++ b/src/programs.asm @@ -133,6 +133,9 @@ ProgDhcp: SECTION "prog_irc", ROMX[$4000], BANK[32] ProgIrc: INCBIN "build/usr/irc.bin" +SECTION "prog_uptime", ROMX[$4000], BANK[33] +ProgUptime: + INCBIN "build/usr/uptime.bin" ; ----------------------------------------------------------------------------- ; PROG_SH (bank 3) - the shell, now written in C (usr/sh.c): parses >/</| and @@ -237,6 +240,8 @@ ProgramTable:: dw ProgDhcp db LOW(BANK(ProgIrc)), HIGH(BANK(ProgIrc)) dw ProgIrc + db LOW(BANK(ProgUptime)), HIGH(BANK(ProgUptime)) + dw ProgUptime ProgramTableEnd:: ; ----------------------------------------------------------------------------- @@ -306,4 +311,6 @@ NameTable:: db PROG_DHCP db "irc", 0 db PROG_IRC + db "uptime", 0 + db PROG_UPTIME db 0 diff --git a/src/sched.asm b/src/sched.asm index a540c49..0369ff4 100644 --- a/src/sched.asm +++ b/src/sched.asm @@ -67,9 +67,28 @@ FindNextReady:: ret ; ----------------------------------------------------------------------------- -; TimerISR - preemption hook (TODO). A real preemptive switch must save the -; interrupted context and call hSwitchTo from here. For now the demo is -; cooperative (tasks call SYS_YIELD), so we just acknowledge and return. +; TimerISR - the system tick. TAC runs the timer at 16384 Hz with TMA=0, so +; TIMA overflows (and this fires) at 64 Hz: wTicks is a monotonic 32-bit +; 1/64-second counter (SYS_UPTIME reads it; wraps after ~2.1 years). +; Scheduling stays cooperative - this ISR is deliberately transparent (all +; registers preserved, fixed-WRAM only), so it can interrupt anything, +; including kernel code mid-syscall. Preemption would hook in here later. ; ----------------------------------------------------------------------------- TimerISR:: + push af + push hl + ld hl, wTicks + inc [hl] + jr nz, .done ; no carry out of byte 0 + inc hl + inc [hl] + jr nz, .done + inc hl + inc [hl] + jr nz, .done + inc hl + inc [hl] +.done + pop hl + pop af reti diff --git a/src/syscall.asm b/src/syscall.asm index bd58cc2..e3f0b1b 100644 --- a/src/syscall.asm +++ b/src/syscall.asm @@ -70,6 +70,7 @@ SyscallTable: dw sys_net ; 33 NET dw sys_sleep ; 34 SLEEP dw sys_pollcon ; 35 POLLCON + dw sys_uptime ; 36 UPTIME ; ----------------------------------------------------------------------------- sys_nosys: @@ -257,6 +258,24 @@ sys_yield: ret ; ----------------------------------------------------------------------------- +; sys_uptime(buf=DE) - copy the monotonic 64 Hz tick counter (4 bytes, LE) +; into the caller's buffer. di/ei so the ISR can't split the 32-bit read. +; ----------------------------------------------------------------------------- +sys_uptime: + di + ld hl, wTicks +REPT 3 + ld a, [hl+] + ld [de], a + inc de +ENDR + ld a, [hl] + ld [de], a + ei + xor a + ret + +; ----------------------------------------------------------------------------- ; sys_sleep(B = 1/64-second units) - cooperative delay driven by the DIV timer. ; DIV (FF04) free-runs at 16384 Hz, so 256 ticks = 1/64 s. We accumulate DIV ; deltas across SchedYields (other procs run) until enough units have elapsed. |
