I have to program an ISR for the Serial Interface. My Problem is, that I don’t know how to specify an absolute adress for the ISR. Some Compilers have the funktion via #pragma. Or do I have to program the complete function in assember?
Am I the only one with this Problem? Nobody wants to use Interrupts?
Whatever, here is my code which solves my problem:
. = 0x500
#-----Save Register-----
stwu %r1, -96(%r1) #New Stack-Frame
stw %r0, 0(%r1) #save register r0
mflr %r0 #save link register
stw %r0, 8(%r1) #put lr on stack
mfcr %r0 #save condition reg.
stw %r0, 4(%r1) #put cr on stack
stw %r13,12(%r1)
#--End save register---
bl extern_interrupt_ISR #jump to ISR
#-----recover register-----
lwz %r13, 12(%r1)
lwz %r0, 4(%r1)
mtcr %r0
lwz %r0, 8(%r1)
mtlr %r0
lwz %r0, 0(%r1)
addi %r1,%r1,96 #recover stack
#---End recover register--
rfi
I can’t even figure out what you are asking. Why would you need to specify an absolute address for an ISR? ISR’s get pointed to by the vector table, so you never need to know where they are unless you are setting them up. If you are setting them up, you know where they are. The code above has the comment “jump to ISR”. You never jump to an ISR.
Of cause I jump to the ISR. I have a funktion in C with the name “extern_interrupt_ISR”. The interrupt vector has to jump in a subroutine because the size of 0x0100 is to small for it. Every extern interrupt causes a jump to 0x500. From there I jump into the “extern_interrupt_ISR”-Function where the source is beeing recognized. From there I jump to another function i.e. UART_ISR.
The problem is, that I can’t find anywhere which registers the GCC using. So maybe I have to save all registers. In this case it seems to be enough to put %0,%r9,%r11 and %r13 on stack but maybe later I get problems. We will see.
In most cases the compiler have some commands to do that automatically. But the GCC from QNX Momentics is apparent not able to do so. Maybe you know more than me
Momentics uses standard gcc, so you can use the standard in-line assembly stuff like the following…
static __inline unsigned attribute((unused)) interrupt_id(volatile unsigned cause, unsigned maskIn, unsigned *maskOut)
{
unsigned id;
__asm__ __volatile__("mov %2,%%ebx\n\t"
"bswap %%ebx\n\t"
"cmp $0,%%ebx\n\t"
"je 1f\n\t"
"bsf %%ebx,%0\n\t"
"mov %0,%%ecx\n\t"
"mov $1,%%edx\n\t"
"shl %%edx\n\t"
"bswap %%edx\n\t"
"mov %%edx,(%1)\n\t"
"jmp 2f\n"
"1:\n\t"
"mov $-1,%0\n"
"2:\n"
:"=a" (id), "=D" (maskOut)
:"r" (cause)
:"%ebx", "%ecx", "%edx");
return id;
}
Of course, your question about how to do an interrupt handler in the IPL, does beg the question… “Why would you want an interrupt handler in the IPL?”…
Hi, sorry for my late reaction but I didn’t get an mail notification.
The inline Assembler is horrible
I think I did in in the “normal” assembler.
And now “Why would you want an interrupt handler in the IPL?”…
I’m using the IPL for uploading and flashing the QNX image to the Flash. It will be send in srec format. The thing is, that later I don’t use only 115kbaud via the UART but over 1Mbit/s. The thing is that during the upload I have to erase the flash and write the data into it. If I don’t use the Interrupt I will get problems because I only have 8 MB of SRAM and the FIFO is only 5 MB. And as you know, the srecords have an large amount of overhead. Thats why I have to use it.