I will be as detailed as possible. I have tried and debugged everything I can possibly think of. Either RTC does not cause a machine level timer interrupt, or I’m missing something.
Here is the start of the code. _play
is called from main.c. This is all in sifive freedom studio, under a blank solution.
.equ .sys.high_mem, 0x80004000
.align 4
.text
.globl _play
_play:
lui sp, %pcrel_hi(.sys.high_mem)
jal ra, _set_mtvec
jal ra, _set_plic
jal ra, _gpio_init
jal ra, _gpio_green
jal ra, _set_rccmp
wfi
j .
First I enable machine level interrupts and define a global _fail_handler, this handler has a breakpoint. It never gets hit.
.align 4
.globl _set_mtvec
_set_mtvec:
csrrci t0, mstatus, 3 # disable interrupts
la a0, _fail_handler # loads fail handler
csrrw a1, mtvec, a0 # get address of fail handler
csrrci t1, mtvec, 1 # set to direct mode
csrrsi t0, mstatus, 3 # enable interrupts
ret
.align 8
_fail_handler:
addi t0, x0, 0xFFFFFFFF
...
I have confirmed it does get hit if i tried to write to ROM causing a synchronous machine exception.
Next is plic and aon.
.equ PLIC_BASE, 0x0C000008
.equ PLIC_ENABLE, 0x0C002000
.equ PLIC_THRESHOLD, 0x0C200000
.equ PLIC_CLAIM, 0x0C200004
.globl _set_plic
_set_plic:
la t0, PLIC_BASE
lw t1, 0(t0)
ori t1, t1, 0x7
sw t1, 0(t0)
la t0, PLIC_ENABLE
lw t1, 0(t0)
ori t1, t1, 0x4
sw t1, 0(t0) # right after doing this there appear to be some bits set in the PLIC_CLAIM, but not the 3rd bit. appears to be wdog
la t0, PLIC_THRESHOLD
lw t1, 0(t0)
and t1, t1, x0
sw t1, 0(t0)
la t0, PLIC_CLAIM #Set all claims to 0
lw t1, 0(t0)
sw t1, 0(t0)
ret
Next is setting up RTC.
.globl _set_rccmp
_set_rccmp:
li t0, AONBASE # gets the AON base address
lw t1, rtccfg(t0) # loads the data at config which is rtcscale
li t2, 0x100F
or t2, t1, t2 # ori the rtcscale to seconds in t1, and enable
sw t2, rtccfg(t0) # store the new rtcscale
.align 8 # do this just in case, rtcscale needs a few cycles. disassembly does show several nops inbetween.
lw t1, rtcs(t0) # loads the current clock time
addi t1, t1, 0x30 # set to 0x30 to ensure rtcs doesn't go above rtccmp until after this proc is exited.
sw t1, rtccmp0(t0) # sets the time to compare several seconds higher
ret
And through lots of debugging, i have confirmed that the rtccmp will eventually trigger the rtcip0 flag, every setup address/register seems to be set exactly how the riscv gods intended the docs to be interpreted, but control will never flow to the fail_handler. So I feel as though I have failed the riscv gods and misinterpreted their work.