Dispint Irq


rixed

Member
Joined
Dec 31, 2005
Messages
206
Age
48
Location
Paris (fr)
Website
happyleptic.org
Hi all !

The specs says that all IRQs can be routed toward the 920 or the 940.

I cannot find any register to choose the target of the IRQs, so I assumed that in fact they were routed toward both the 920 and the 940.

But after a few tests, I didn't manage to get the single IRQ (nor FIRQ) on the 940. So I suspect it can be routed toward the 920 or the 940, in hardware, at the manufacturer convenience, and that GPH choose to link them only to the 920.

Am I right ?
 
Have a look at undocumented register 0xC0004500

It's the interrupt controller register for the 940 :)

A typical example of usage can be found in the release source code for the uboot of firmware 2.0.

Look at "mes_iomap.h" :

#define INTCON_BASE (0x0800+IO_BASE) // A920T interrupt controller
#define A940T_INTCON_BASE (0x4500+IO_BASE) // A940T interrupt controller

The 920 one is documented (addr 0xC0000800), and I wouldn't be suprised if the 940 one behaves in exactly the same way.

It seems GPH use it for playing the bootup sound via interrupt on the 940.
 
Squidge posted on May 22 2006 at 07:17 PM said:
Have a look at undocumented register 0xC0004500

It's the interrupt controller register for the 940 :)

A typical example of usage can be found in the release source code for the uboot of firmware 2.0.

Look at "mes_iomap.h" :

#define INTCON_BASE (0x0800+IO_BASE) // A920T interrupt controller
#define A940T_INTCON_BASE (0x4500+IO_BASE) // A940T interrupt controller

The 920 one is documented (addr 0xC0000800), and I wouldn't be suprised if the 940 one behaves in exactly the same way.

It seems GPH use it for playing the bootup sound via interrupt on the 940.
Nice catch, i've spent all day, on and off inbetween work to get this going using the 0xc0000800 address. Would explain why it was not working. Doh! Which docs did you find this in? I'm looking at the MP2505F manual and I can't find it there.
 
Last edited by a moderator:
Read my post again, specially the part where I say "Have a look at undocumented register 0xC0004500". Yes, it's not in the datasheet, like lots of other registers.

I originally spotted the 4500 register being used in 940 video code, was discussing it on IRC, and someone grepped the GPH sources and found it being used in the uboot code :)

Unfortunately, we can't find any references to any of the other undocumented registers, so we are just guessing at them for now.
 
LoL, I read "Take a look at the documented register 0xC0004500" Note to self, read slower. ;)

The devkits you can get from the chip manufacturer must come with more detailed 'insider' information. :(
 
The chip is standard, but you have to license the parts you are interested in using, and you only get docs for those parts.

We only have the standard docs.
 
Yes, but like I say, there are seperate levels you can buy that development kit at. The standard level just describes the basics and doesn't include any documentation or code about the camera interface, mpeg decoder, etc. You can then either license the additional modules or buy them in binary form.

We have been quoted the standard development kit is £10,000, which includes hardware, software, documentation, and tech support.
 
Outch, 10k!!! ps2 devkits were that price when they first came out!

Ok, back on topic now. I've been banging my head trying to get this interupt stuff working. Got the bootloader source to look at. This what I have....

Tweeked the start of the 940 boot code too
"b .CodeEntryPoint \n" //Reset
"b .CodeEntryPoint \n" //Undefined instuction
"b .CodeEntryPoint \n" //Software interrupt
"b .CodeEntryPoint \n" //Prefetch abort
"b .CodeEntryPoint \n" //Data abort
"b .CodeEntryPoint \n" //Obsolete (Address Exception)
"b IRQ \n" //IRQ (interupt)
"b .CodeEntryPoint \n" //FIQ (fast interupt)
""//Code to handle an IRQ interupt
""//I've asummed the only interupt will be the vblank
"IRQ: \n"
"b IRQ \n" //crap test but at least should let me know I got the interrupt.

Tagged on the end of the 940 boot code i've got
""//Enable irq interrupts
"mrs r0,cpsr \n"//Make sure irq interrupts are enabled for the CPU.
"bic r0,r0,#0x80 \n"//Clear the I bit
"msr cpsr_c,r0 \n"
"");

Then to set the regs I do...

struct REG_IRQController
{
u32 srcpend;
u32 intmode;
u32 intmask;
u32 priorit;
u32 intpend;
u32 intoffset;
};

struct REG_IRQController *irq = (struct REG_IRQController*)(0xc0004500 - 0x02000000);//offset by 32megs because my base address has moved.
irq->intmode = 0x0;
irq->intmask = 0xfffffffe;
irq->srcpend = 0xffffffff;

From what I can see and have read its all I need to do, but no joy. :(
The handler just spins in a loop so it should lock up the 940, bad test I know.
 
MadDog posted on May 25 2006 at 02:42 PM said:
irq->intmode = 0x0;
irq->intmask = 0xfffffffe;
irq->srcpend = 0xffffffff;

The kernel also does this, although Im not sure its usefull :

irq->intpend = -1;
irq->priorit = 0;

Then you need to activate vsync interrupt in register 0x2846
 
Last edited by a moderator:
Yes, all working. Main bug was my interruprt routine. Seems that one should reset the HW before dealing with the interrupt, if you do it as the last thing then it may reenter, well thats what the books says, if I read it correct. Here are the fragments of my code for it all, a bit later i'll release the source to my engine.

On the 940 I have....
asm volatile(
"b CodeEntryPoint \n" //Reset
"b CodeEntryPoint \n" //Undefined instuction
"b CodeEntryPoint \n" //Software interrupt
"b CodeEntryPoint \n" //Prefetch abort
"b CodeEntryPoint \n" //Data abort
"b CodeEntryPoint \n" //Obsolete (Address Exception)
"b IRQ \n" //IRQ (interupt)
"b CodeEntryPoint \n" //FIQ (fast interupt)
""
"IRQ:"//IRQ interrupt handler.
"stmfd sp!,{r0-r3} \n"
""//Reset the interrupt so we can get another one when its done.
"ldr r0,=0xbe004500 \n"
"ldr r1,[r0] \n"
"orr r1,r1,#1 \n"
"str r1,[r0] \n"
"ldr r0,=0xbe004510 \n"
"ldr r1,[r0] \n"
"orr r1,r1,#1 \n"
"str r1,[r0] \n"
""//Inc our frame count var.
"mov r0,#0x00800000 \n"
"ldr r1,[r0] \n"
"add r1,r1,#1 \n"
"str r1,[r0] \n"
""//And done, return.
"ldmfd sp!,{r0-r3} \n"
"subs pc,r14,#4 \n"
""//All unhandle interupts end up here, could be intresting.
"CodeEntryPoint: \n"
then usual stuff.

//Setup the interupts on the hardware, default to NONE.
reg.irq->intmode = 0x0;
reg.irq->intmask = 0xffffffff;
reg.irq->srcpend = 0xffffffff;
reg.irq->intpend = 0xffffffff;
reg.irq->priorit = 0;
Init my GPU stuff, display etc.. then

//Start the vblank interrupt.
reg.regs16[0x2846>>1] &= ~(1<<5);
reg.regs16[0x2846>>1] |= (1<<5);

//Enable the display vblank interrupt
REG_ENABLE_INTERRUPT(reg.irq,IRQ_DISPINT);

And
//Enable irq interrupts
asm(
"stmfd sp!,{r0} \n"
"mrs r0,cpsr \n"//Make sure irq interrupts are enabled for the CPU.
"bic r0,r0,#0x80 \n"//Clear the I bit
"msr cpsr_c,r0 \n"
"ldmfd sp!,{r0} \n");

I use this struct mapped to 0xbe004500 (offset by 32megs)
struct REG_IRQController
{
u32 srcpend;
u32 intmode;
u32 intmask;
u32 priorit;
u32 intpend;
u32 intoffset;
};
#define IRQ_DISPINT 0
//pRegs points to the hardware address, not hardcoded as the 940 is dependant on its address translation.
//example:
//struct REG_IRQController *irq = (struct REG_IRQController*)(0xbe004500);//940 offset by 32megs
//REG_ENABLE_INTERRUPT(irq,IRQ_DISPINT);
#define REG_ENABLE_INTERRUPT(__pRegs__,__pInterupt__) (__pRegs__)->intmask = (__pRegs__)->intmask & (~(1<<(__pInterupt__)));
#define REG_DISABLE_INTERRUPT(__pRegs__,__pInterupt__) (__pRegs__)->intmask = (__pRegs__)->intmask | (1<<(__pInterupt__));


To wait for an vblank I do the following, not sure if the volatile memory bit is needed.

u32 vbl = reg.cmd.cmd_buf->vbl;
asm volatile("":::"memory");
while( vbl == reg.cmd.cmd_buf->vbl )
{};
 
How strange : you do not setup r13_irq (or do you in another part of your code ?)

I had to init SP in the irq handler because r13_irq was initialized with garbage after reset.

Perhaps it would be safer to do the same : find a little place somewhere in memory and put your sp onto it (and keep irq disabled while in irq mode of course).
 
Yes, R13 & R14 is banked in IRQ, so you should either set R13 to a known value each time in the IRQ, or manually change to irq mode in your initialisation and set R13 there. Otherwise you could stand the chance of overwriting your code, and that's a real nasty bug to to try and find.

Shouldn't be a need to worry about the irq enable, as the current CPSR is copied to SPSR, and then the I bit is set before the IRQ routine is called. The subsequent "subs pc, lr, #4" or similar will move the SPSR back to CPSR, and thus re-enable interrupts after that instruction.
 
Ah that explanes the code in the FW2.0 bootloader I saw, could not workout why they needed a stack. I keep getting confused with r13 and r14. So, is r13 also the sp? Whats r14, in the diagram in front of me the pc is seperate to r14. Is r14 a special register or just used by everyone as the return address?

I could use FIQ mode then i've got r8 -> 13 to play with and not use a stack. Ok, better give myself an IRQ stack. Whats the best way? Init it on every interrupt or change to irq mode and set it once at start up?

Thanks for the catch on that bug, might explane my semephore probs.
 
Back
Top