Hi guys, I have a new problem developing for the VB, this time is about interrupts, some time ago I asked for how to measure time and got some responses… sadly I didn’t understand that much about interrupts and made somethings wrong… the time measurement. I was not calculating time based on the timer interrupt but with some fancy software method which in the end proved to not be that much accurate.
I have been all the weekend trying to figure it out why when
compiling with the latest version of gccvb, crt0.s and vb.ld, somehow,
the following VIP_REGS just don’t update its state:
INTPEN is allways 0x601F
This way I can’t get the timer interrupt to work, and all physics
simulations just can’t be done accurately.
Now, I have noticed a few things from the new crt0.s, it defines the
timer interrupt vector as follows:
/* INTTIM (7FFFE10h) – Timer Interrupt */
add -4, sp
st.w r1, 0[sp]
movhi hi(_tim_vector), r0, r1
movea lo(_tim_vector), r1, r1
jmp [r1]
now, the add -4, sp instructions as the VB development manual states
that has to be written in order to not loose the call records, but it obligates the programmer to put the following
instruction at the end of his tim_vector function:
add 4, sp
otherwise, the control flow is lost.
I’ve tried to compile using older versions of ctr0.s anb vb.ld, even one
from the gccvb for Windows but the result is the same.
This problem causes that even when the tim interrupt flag is raised in
TRC hardware registry, the interrupt it is not fired, but just the first time.
Any idea?
Thanks a lot for your time.
jorgeche
I haven’t used the interrupts on the new gccVB, but inside the ISR there should be an add 4, sp before the reti. Does the rest of the program still run, or does it lock up? If everything else runs, you’re probably getting out of the interrupt just fine, but the interrupt flag probably isn’t being cleared (I never really looked at it for the V810, but usually you have to clear the interrupt once it occurs or it’ll never occur again). I just took a quick look at the V810 manual and it looks like it may be the EP bit in the PSW (which I thought reti was supposed to take care of). I assume you’re testing this in the emulator? If so, dump the registers and check the flags. You may also want to make sure it’s actually calling reti and not jmp or another branch.
DogP
ok… here is how it goes:
first activate interrupts
//setup interrupts
VIP_REGS[INTCLR] = VIP_REGS[INTPND];
VIP_REGS[INTENB] = 0x0000;
setIntLevel(0);
INT_ENABLE;
//setup timer
timerFreq(TIMER_100US);
timerSet(TIME_MS(10));
timerClearStat();
timerInt(1);
timerEnable(1);
then the interrupt handler
void tim_vector() {
timerInt(0);
VIP_REGS[INTCLR] = VIP_REGS[INTPND];
timerEnable(0);
timerClearStat();
timerEnable(1);
count++; //global variable
timerInt(1);
setIntLevel(0);
asm(“add 4,r3”); //if not put, the sp will point to other call record
}
and in the machine code I get:
07002c02 <_tim_vector>:
7002c02: 5f 01 mov lp, r10
7002c04: 00 ac 68 82 jal 700ae6c <__save_r31>
7002c08: c0 40 mov 0, r6
.
.
.
.
7002c4a: 64 44 add 4, sp
7002c4c: 00 a8 2c 82 jr 700ae78 <__return_r31>
and for the interrupt vector:
0703fe00 <_int_table>:
703fe00: 7c 44 add -4, sp
703fe02: 23 dc 00 00 st.w r1, 0[sp]
703fe06: 20 bc 01 07 movhi 1793, r0, r1
703fe0a: 21 a0 8a 89 movea -30326, r1, r1
703fe0e: 01 18 jmp [r1]
703fe10: 7c 44 add -4, sp
703fe12: 23 dc 00 00 st.w r1, 0[sp]
703fe16: 20 bc 00 07 movhi 1792, r0, r1
703fe1a: 21 a0 02 2c movea 11266, r1, r1
703fe1e: 01 18 jmp [r1]
.
.
.
.
So, I guess I’m not getting the EP bit in the PSW be cleared?…
Later I used a code from Lameboyadvance wich includes a reti instruction:
asm(”
di /* Disable interrupts */
add 4, r3 /* Set sp back to previous value */
ei /* Re-enable interrrupts */
reti /* Return from interrupt */
“);
return;
but I get the same result:
VIP_REGS[INTPND] = 0x601E always
Thanks for your support
Hi, it definitively has to do with the new ctr0.s and vb.ld script, I have compiled the demo clock included in the old gccvb under the new one, using the ctr0.o, vb.ld and vb.hdr that came with the old gccvb and it works. the problem is that I think the old scripts and headers does not support multiple o files which my project is divided into.
If I compile the same clock demo, using the new script and crt0, the interrupts don’t get fired.
I haven’t used the setIntLevel function, so I don’t really know what it does, but it sounds like it just sets the interrupt mask. I believe reti is supposed to clear the interrupt. I thought the new gccVB was supposed to handle all the interrupt stuff for you though… is there a reason you need any inline asm? Have you tried making a simple app that just keeps causing the interrupt? Oh, and shouldn’t tim_vector() have a return; at the end? Possibly the compiler looks for the return and handles the stack and reti there, but gets confused if there’s no return… I dunno :-P.
DogP
Oh… you could try manually clearing the interrupt in the PSW, or manually restoring the saved PSW from the EIPSW.
DogP
I will try to manually restore PSW from the EIPSW. as you say tonight. It is very weird. Indeed, the asm statement is mandatory, otherwise the program restores the wrong call record from the stack on handler’s return. I be tried these:
asm(“add 4,r3”);
asm(“reti”);
return;
but nothing changes, I am begging to believe that there is something wrong with the linker, maybe linking multiples object files or with the ctr0.o file, because the clock demo works either with the new compiler, and with the new vb.ld script, but fails with the new ctr0.
Now, when I try to compile my project with the new compiler, new vb.ld script and old ctr0.o, it again doesn’t work.
Now, the old crt0.s does have at the end of the interrupt handler a reti instruction that the new one does not… maybe there is the key… I will experiment tonight, thanks DogP.
Hi, as I thought it was a problem with the crt0.s not being saving the contents of the registries at the moment of calling the interrupt, and as you pointed DogP, the reti instruction is which restores PSW, and the interrupt handler in the new crt0 wasn’t executing it. I will send David the crt0.s I fixed so he can put it in the gccvb source :-).
Thanks again for your help DogP.
jorgeche
Cool… could you send it to me too? My email address is in my profile. Thanks,
DogP
Do I still need to put the asm(“add 4,r3”); in my code when using this new crt0?
Also, I get a compiler error “multiple definition of ‘tim_vector’ ” after using the new one… How should I define my function now?
Thanks,
DanB
Edit:
Hmm, nevermind, I got it. And it seems like it works without any inline asm.
- This reply was modified 16 years, 9 months ago by DanB.
I can’t get this to work on the real hardware. In reality boy, it works but only without the asm line, but on hw it doesn’t work either with or without it. I am using the new crt0 and my code looks like in jorgeche’s post.
Any ideas would be appreciated.
Thanks
#define REG_SDLR *(volatile u8*)(0x02000010) #define REG_SDHR *(volatile u8*)(0x02000014) #define REG_SCR *(volatile u8*)(0x02000028) #define K_MASK 0xFFFC u16 __key_curr = 0, __key_prev = 0; void key_poll() { REG_SCR = (S_INTDIS | S_HW); while (REG_SCR & S_STAT); __key_prev= __key_curr; __key_curr= ((REG_SDHR << 8 ) | REG_SDLR) & K_MASK; }
Try this.
- This reply was modified 15 years, 8 months ago by dasi.
Thanks dasi, that works for reading the pad. And just for the record, it turned out my problems didn’t have anything to do with the interrupts.
Jorgeche: Why did you comment out the setcoltable code in the crt0.s? I was messing w/ interrupts a little bit tonight and your crt0 works in the emulator, but when I ran it on hardware, the columns were all messed up. Did you disable it because you set up the column table elsewhere in your code? Anyway, I uncommented that code out and rebuilt it and it works great for me, so thanks!
DogP