Does the rtccmpip cause an interrupt

    .equ AONBASE,       0x10000000
    .equ rtccfg,        0x040
    .equ rtccountlo,    0x048
    .equ rtccounthi,    0x04C
    .equ rtcs,          0x050
    .equ rtccmp0,       0x060

    .globl _set_rccmp
    _set_rccmp:
        li t0, AONBASE          # loads the AON base address
        lw t1, rtccfg(t0)       # loads the config address which is rtcscale
        ori t2, t1, 15         # andi the rtcscale to seconds in t1.
        sw t1, rtccfg(t0)       # store the new rtcscale

        lw t1, rtcs(t0)         # loads the current clock time
        addi t1, t1, 0x03       # adds 3 seconds to the current clock time
        sw t1, rtccmp0(t0)      # sets the time to compare 3 seconds higher

I have this code, but reading the documentation on 16.3 of the SiFive FE310-G002 Manual v19p04
It says that it only sets the interrupt pending bit on rtccmpip.
Here is my mtvec initialization that I would guess would be triggered after 3 seconds.

    _set_mtvec:
        csrrci t0, mstatus, 3                   # disable interrupts
        la a0, _fail_handler                    # loads fail handler
        csrrw t2, 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:
        ...

With a breakpoint on my _fail_handler I never see it hit.
Is there another way to trap rtc interrupts I might be missing?

I made a slight adjustment here. My logic was incorrect.

 li t0, AONBASE          # loads the AON base address
 lw t1, rtccfg(t0)       # loads the config address which is rtcscale
 li t2, 0x100F
 or t2, t1, t2           # or the rtcscale to seconds in t1, and enable

    sw t2, rtccfg(t0)       # store the new rtcscale
    lw t1, rtcs(t0)         # loads the current clock time
    addi t1, t1, 0x03       # adds 3 seconds to the current clock time
    sw t1, rtccmp0(t0)      # sets the time to compare 3 seconds higher

Probably you need to enable RTC interrupt in PLIC

Hmm. I’m not seeing what I did wrong I am still not seeing any indication that an interrupt is happening.

.equ ENABLE_0, 0x0C001000
.globl _set_plic
_set_plic:
	li t2, ENABLE_0
    lw t1, 0(t2)
    ori t1, t1, 0x2
    sw t1, 0(t2)
    ret

From the documentation it shows in table 26 PLIC Interrupt Source Mapping that AON RTC is at bit 2.
And at table 30, bit 2 should interrupt 2 enable. I’m not sure where I’m getting confused.

Interrupt enables reside in registers starting from 0x0C002000, you will also need to change a priority of the interrupt to something non-zero and set global priority threshold in a way that unmasks your interrupt.

Thank you, good catch. I am pretty sure in the same chapter I set priority at 0x0C000000 + 4 * interrupt.
So i tried… and still no avail.

.equ PLIC_BASE,     0x0C000000
.equ PLIC_PRIORITY, 0x00
.equ PLIC_ENABLE,   0x0C002000

.globl _set_plic
_set_plic:
    li t0, PLIC_ENABLE
    lw t1, 0(t0)
    ori t1, t1, 0x2
    sw t1, 0(t0)
	li t0, PLIC_BASE
    lw t1, PLIC_PRIORITY(t0)
    ori t1, t1, 0x8
    sw t1, PLIC_PRIORITY(t0)
    ret

Here you’re setting a priority for interrupt source 0 (which doesn’t exist) to >=8 (which is invalid value). You need to set priority for interrupt source 2 to something between 1 and 7. In short,
*(uint32_t*)0x0C000008 = 7;

Bugs all around! Thank you for pointing that out. I tried explicitly loading and setting that address. At this point, I think I’ll just paste all my code. As you can see i changed plic_base to 0x0c000008 just for this test.

.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
    # wait for interupt.
	wfi
    j .
.align 4
.equ GPIO_CTRL_ADDR,    0x10012000
.equ GPIO_OUTPUT_EN,    0x008
.equ GPIO_OUTPUT_VAL,   0x00C
.equ GPIO_OUTPUT_XOR,   0x040
.equ GPIO_RGB_PINS,     0x680000
.equ GPIO_RED_LED,      0x400000
.equ GPIO_BLUE_LED,     0x200000
.equ GPIO_GREEN_LED,    0x080000

.macro set_gpio color
    li t0, GPIO_CTRL_ADDR       # Load the base GPIO address
    sw x0, GPIO_OUTPUT_VAL(t0)  # Set the current value to 0
    li a0, \color               # Load the requested color
    sw a0, GPIO_OUTPUT_VAL(t0)  # Set gpio to requested color
.endm

.globl _gpio_init
_gpio_init:
    li t0, GPIO_CTRL_ADDR       # Load the base GPIO address
    li t1, GPIO_RGB_PINS        # Get the RGP Pins offset
    sw t1, GPIO_OUTPUT_EN(t0)   # Enable RGB pins as output pins
    sw t1, GPIO_OUTPUT_XOR(t0)  # Set the XOR to that the pins are Active High
    sw x0, GPIO_OUTPUT_VAL(t0)  # Set all writable GPIO pins to zero

    li t1, GPIO_BLUE_LED        # Load blue to indicate ready
    sw t1, GPIO_OUTPUT_VAL(t0)  # Write the new output so we turn on the requested LED
    ret
.globl _gpio_red
_gpio_red:
    set_gpio GPIO_RED_LED
    ret
.globl _gpio_green
_gpio_green:
    set_gpio GPIO_GREEN_LED
    ret
.globl _gpio_blue
_gpio_blue:
    set_gpio GPIO_BLUE_LED
    ret

.equ AONBASE,       0x10000000
.equ wdogcfg,       0x000
.equ wdogcount,     0x008
.equ wdogs,         0x010
.equ wdogfeed,      0x018
.equ wdogkey,       0x01C
.equ wdogcmp0,      0x020
.equ rtccfg,        0x040
.equ rtccountlo,    0x048
.equ rtccounthi,    0x04C
.equ rtcs,          0x050
.equ rtccmp0,       0x060
.equ lfrosccfg,     0x070
.equ lfclkmux,      0x07C
.equ AONCFG,        0x300

.globl _set_rccmp
_set_rccmp:
    li t0, AONBASE          # loads the AON base address
    lw t1, rtccfg(t0)       # loads the config address 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

    lw t1, rtcs(t0)         # loads the current clock time
    addi t1, t1, 0x03       # adds 3 seconds to the current clock time
    sw t1, rtccmp0(t0)      # sets the time to compare 3 seconds higher
    ret
.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
    csrrs t1, mcause, x0
    la t2, 0xFFFFFFFD
    or t2, t2, t1
    bne t2, t0, _red
    jal ra, _gpio_blue
    mret
_red:
    jal ra, _gpio_red
    mret

.equ PLIC_BASE,     0x0C000008
.equ PLIC_PRIORITY, 0x00
.equ PLIC_ENABLE,   0x0C002000

.globl _set_plic
_set_plic:
    li t0, PLIC_ENABLE
    lw t1, 0(t0)
    ori t1, t1, 0x2
    sw t1, 0(t0)
	li t0, PLIC_BASE
    lw t1, PLIC_PRIORITY(t0)
    ori t1, t1, 0x7
    sw t1, PLIC_PRIORITY(t0)
    ret

I still can’t get it to work. but I learned what you meant about manipulation the bits of the plic enable a bit better. I modified the plic code to be.

.equ PLIC_BASE,     0x0C000008
.equ PLIC_PRIORITY, 0x00
.equ PLIC_ENABLE,   0x0C002000
.globl _set_plic

_set_plic:
    la t0, PLIC_ENABLE
    lw t1, 0(t0)
    ori t1, t1, 0x4
    sw t1, 0(t0)
    la t0, PLIC_BASE
    lw t1, PLIC_PRIORITY(t0)
    ori t1, t1, 0x7
    sw t1, PLIC_PRIORITY(t0)
    ret

You’re still missing something :slight_smile:

Looks like there is even more magic I need to know after that one @Disasm . I was able to set the threshold, it was already 0, when I debugged it…

.equ PLIC_BASE,         0x0C000008
.equ PLIC_ENABLE,       0x0C002000
.equ PLIC_THRESHOLD,    0x0C200000
.globl _set_plic
_set_plic:
    la t0, PLIC_BASE
    lw t1, 0(t0)
    ori t1, t1, 0x4
    sw t1, 0(t0)
    la t0, PLIC_ENABLE
    lw t1, 0(t0)
    ori t1, t1, 0x4
    sw t1, 0(t0)
    la t0, PLIC_THRESHOLD
    lw t1, 0(t0)
    and t1, t1, x0
    sw t1, 0(t0)
    ret

@Disasm

After reading the rtc section again. I don’t think I’m setting the rtc configuration I’m going for correctly as well.

.globl _set_rccmp
_set_rccmp:
    li t0, AONBASE          # loads the AON base address
    lw t1, rtccfg(t0)       # loads the config address 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

    lw t1, rtcs(t0)         # loads the current clock time
    addi t1, t1, 0x3        # adds 3 seconds to the current clock time
    sw t1, rtccmp0(t0)      # sets the time to compare 3 seconds higher

I attempted to add several nops incase the rtcscale needs to take time to affect the rtcs. This also didn’t work.