Re: [sw-dev] Problem with working with timer interrupts

36 views
Skip to first unread message

Valentin Nechayev

unread,
May 8, 2024, 7:16:03 AMMay 8
to Xavier Barreto Tomeo, RISC-V SW Dev
Tue, May 07, 2024 at 08:49:08, sw-dev wrote about "[sw-dev] Problem with working with timer interrupts":

> From: 'Xavier Barreto Tomeo' via RISC-V SW Dev <sw-...@groups.riscv.org>

> Im doing a project in RISC-V and im trying to enable timer interrupts and
> make a simple code running on it. I have this code that is called from a .c
> file and it returns to it and stays in while(1)
>
> timern:
> la t0, timer_handler
> csrw mtvec, t0
> csrs mstatus, 0x8
> li t0, 0x80
> csrs mie, t0
> li t0, 500000
> li t1, 0x2004000 #mtimecmp address
> sd t0, 0(t1)
> mret

1. If `timern` is a code to configure timer interrupt (as I deduce
from your code), it is unlikely to have been finished with `mret`.
MRET is for return from an interrupt handled in M-mode.
2. The opposite, timer_handler shall be finished with an instruction
to return from an interrupt: MRET if handled in M-mode, SRET if
handled in S-mode.
3. In a correct interrupt handler, you should save and restore all
registers modified in the handler. You don't do this so affect the
interrupted program with spontaneous unpredictable register change. No
program can survive this.
4. Also, it's very unlikely you may call `writehello` in an interrupt
handler, unlike this is a special utility to write to serial console,
kernel buffer or any other similar target. Instead, you may provide a
message into a buffer that a code out of interrupt handler checks for
additions.

All this suggests before solving the task you should have got
acquainted with the basic principles. They are well described in OS
design books, let you start reading respective chapters from: M.Bach
for Unix architecture, A.Tanenbaum with its handbook, and so on.


-netch-

Xavier Barreto Tomeo

unread,
May 8, 2024, 5:20:34 PMMay 8
to RISC-V SW Dev, ne...@netch.kiev.ua, RISC-V SW Dev, Xavier Barreto Tomeo
Hi! 
First, thanks for answering. 
timern is a function called from main to enable interrupts and say which handler take in case of the interruption, and timer handler is the handler i expect to do to the timer interrupt. I have changed what you said from the returns, you are totally right.
As for now it's just a test mode I hadn't added the save_all and recover_all macros, but now I have.
What you say about writing hello is just a way to test if it is working ok or not and what does is write by uart the hello, simply that. 
For now, the interrupt and all the program process are in machine mode.

Now I'm stacked in making the interrupt work more than once, i have added to my timer_handler a reset to the mip bit but is still working. I don't know if you could help me. 

I add the code I have rn here:

timern:
la t0, timer_handler
csrw mtvec, t0
csrw stvec, t0
csrs mstatus, 0x8
li t0, 0x80
csrs mie, t0
li t0, 500000
li t1, 0x2004000 #mtimecmp address
sd t0, 0(t1)

ret

timer_handler:
save_all
li t1, 0x2004000 #mtimecmp address
ld t0, 0(t1)
li t2, 500000
add t0, t0, t2
sd t0, 0(t1)
j writehello

li t0, 0x00
csrw mip, t0
recover_all
mret

Thanks, Xavier
El dia dimecres, 8 de maig del 2024 a les 13:16:03 UTC+2, ne...@netch.kiev.ua va escriure:

Valentin Nechayev

unread,
May 9, 2024, 11:42:55 AMMay 9
to Xavier Barreto Tomeo, RISC-V SW Dev
hi,

> From: 'Xavier Barreto Tomeo' via RISC-V SW Dev <sw-...@groups.riscv.org>

> Hi!
> First, thanks for answering.
> timern is a function called from main to enable interrupts and say which
> handler take in case of the interruption, and timer handler is the handler
> i expect to do to the timer interrupt. I have changed what you said from
> the returns, you are totally right.
> As for now it's just a test mode I hadn't added the save_all and
> recover_all macros, but now I have.
> What you say about writing hello is just a way to test if it is working ok
> or not and what does is write by uart the hello, simply that.

If you try to test it with a main program interrupted by timer events,
its gets mandatory to fulfil all requirements I listed in the previous
message.

> For now, the interrupt and all the program process are in machine mode.
>
> Now I'm stacked in making the interrupt work more than once, i have added
> to my timer_handler a reset to the mip bit but is still working. I don't
> know if you could help me.
>
> I add the code I have rn here:
>
> timern:
> la t0, timer_handler
> csrw mtvec, t0
> csrw stvec, t0
Looks excessive if you don't use supervisor mode.
> csrs mstatus, 0x8
> li t0, 0x80
> csrs mie, t0
> li t0, 500000
> li t1, 0x2004000 #mtimecmp address
> sd t0, 0(t1)
>
> ret
>
> timer_handler:
> save_all
> li t1, 0x2004000 #mtimecmp address
> ld t0, 0(t1)
> li t2, 500000
> add t0, t0, t2
> sd t0, 0(t1)
> j writehello
So you unconditionally jump (without return!) to `writehello` which
doesn't return properly as from interrupt, does it?
If you use a subroutine, you should call it using `jal`. But before
this you should have configured stack for the interrupt handler.
>
> li t0, 0x00
> csrw mip, t0
I'd suggest `csrc` for a single flag.
> recover_all
> mret

Anyway, I'd strictly suggest running all this under an emulator that
allows single-instruction step with visualization of emulated
processor state (at least, all registers and marked memory areas).
With such an emulator you could already have passed most problems
discussed here by your own.
Only after final success on an emulator, running under something less
detailed gets productive.


-netch-
Reply all
Reply to author
Forward
0 new messages