View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
ADDRESS ERROR TRAP INTERRUPT PIC24H |
Posted: Fri Oct 03, 2014 7:20 am |
|
|
Compiler: 5.026
Device: PIC24HJ256GP206
Hi guys,
I am getting on occasion an address error interrupt. I can almost have the error occur every time I run the code but I don't know when or where it happens nor what is causing it (of course or I wouldn't be writing here!).
I can't put code examples in here because my code is a monster (on a 256KB device, I am using 61% of the ROM and 78% of the RAM so that's huge).
Basically, the MCU runs off interrupts (Timer, DMA, UART RX). Data is being processed in real-time into time slices so it is very difficult to troubleshoot.
I am using my MCU's second UART to print stuff on a serial console. When I catch the address interrupt, at the moment I simply print "ADD_ERR" on my screen and when I get that error, it just prints non-stop.
Is there a way I can retrieve the state of *whatever* registers on the MCU and print the info on the screen so that it shows perhaps some information as to *what* is causing the interrupt?
Thanks for any help,
Benoit |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Oct 03, 2014 7:42 am |
|
|
When the interrupt occurs, the address is on the stack.
You want to be looking just in front of this (the error is the instruction before).
Look at:
<http://www.ccsinfo.com/forum/viewtopic.php?t=48332&highlight=address+error+trap>
Common cause, would be using a pointer to a variable used as an int16, and then using this to access a variable that is not on a word boundary.
So if you had an array of bytes, took the address of the third byte, then passed this to a function that expected a pointer to an int16....
You can also trigger this if you use malloc/calloc, and give it an odd address. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Oct 03, 2014 7:51 am |
|
|
Hi Ttelmah,
Thanks for the info... I have seen this post but I'm not too sure what to do with the assembly code. How can I use it in my C code?
I realize that the #asm uses that section for assembly, but then, how can I print the details to my serial console?
If you have an example of how I can display the data that I am looking for, it would be greatly appreciated.
Thanks again,
Benoit |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Oct 03, 2014 8:01 am |
|
|
Oh and in that code you referred to, what's the <trapaddr>? If I simply take the assembly code and try to compile it, the compiler complains it doesn't know what <trapaddr> is... is it an unsigned long? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Oct 03, 2014 8:07 am |
|
|
It's just a global int32 variable you declare.
The address is then written into it, and can be printed, or looked at in an ICD. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Oct 15, 2014 8:14 am |
|
|
So I've added a bit of code to capture the CPU control registers upon an ADDRESS ERROR trap and here are three instances of the crash (register followed by the value):
CRASH 1:
WREG0: 09
WREG1: 0A
WREG2: 3A
WREG3: 5910
WREG4: 250
WREG5: 4BBE
WREG6: 25A6
WREG7: 03
WREG8: FF
WREG9: 7F
WREG10: B0
WREG11: 00
WREG12: 00
WREG13: 00
WREG14: 00
WREG15: 3E3E
SPLIM: 3FFE
PCL: CB64
PCH: 00
TBLPAG: 00
PSVPAG: 00
CRASH 2:
WREG0: 09
WREG1: 0A
WREG2: 3A
WREG3: 5924
WREG4: 220
WREG5: 4BC1
WREG6: 2254
WREG7: 03
WREG8: FF
WREG9: 7F
WREG10: 80
WREG11: 00
WREG12: 00
WREG13: 00
WREG14: 00
WREG15: 3E3E
SPLIM: 3FFE
PCL: CC1A
PCH: 00
TBLPAG: 00
PSVPAG: 00
CRASH 3:
WREG0: 09
WREG1: 0A
WREG2: 3A
WREG3: 5924
WREG4: 200
WREG5: 4BC1
WREG6: 20AA
WREG7: 03
WREG8: FF
WREG9: 7F
WREG10: 60
WREG11: 00
WREG12: 00
WREG13: 00
WREG14: 00
WREG15: 3E3E
SPLIM: 3FFE
PCL: CC1A
PCH: 00
TBLPAG: 00
PSVPAG: 00
Does this indicate anything?? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Oct 15, 2014 9:32 am |
|
|
Not really. Except that you haven't had a stack overflow.
The point is that when the interrupt routine is called, the address from which it is called is pushed onto the stack. It is this address that the code retrieves, which then allows you to look in the assembly listing _just before_ this address to see what code was being run, to cause the problem.
The standard CCS interrupt hander uses 36 bytes of stack, and this is the '36' in the assembler routine, which then retrieves the first bytes put onto the stack by the interrupt, which are the return address.
Put the routine into the interrupt, read the address it gives, and look here for the code. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Oct 15, 2014 10:30 am |
|
|
Hi Ttelmah,
Thanks for the reply but I think that your explanation is beyond my capabilities. I can do lots of code but when it gets to stacks and assembly, I have no idea.
"Put the routine into the interrupt, read the address it gives, and look here for the code."
What routine, which address and what code?
Sorry (and thanks). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Oct 15, 2014 10:48 am |
|
|
The routine from the thread linked in my first reply.
As I've already said, you just declare an int32 variable called 'trapaddr', put this code into the interrupt handler for the trap, and then the address is written to this variable when the interrupt is called. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Wed Oct 15, 2014 11:37 am |
|
|
Ah ok, sorry, then that's what I did. Now I'm just waiting for the error to occur again.
Thanks! |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Dec 05, 2014 7:05 am |
|
|
I know its been like 2 months but I had other tasks to do. So I am still getting this Address error trap. In my code, the stack size is 512 but not sure if it will help if I increase it.
I've left my code running all night and I've gotten the address interrupt non-stop since yesterday (around every 20 minutes but I've seen it happen twice in a few minutes and on other occasions at 35-40 minutes interval). But from yesterday at 4PM since this morning at 7AM, I got over 50 of these error traps, *always* with the same address.
I have this code running:
Code: | #INT_ADDRERR
void ADDRERR_isr(void)
{
unsigned long trapaddr;
#asm
mov w15, w0
sub #36, w0
mov [w0++], w1
mov w1, trapaddr
mov [w0], w1
and #0x7f, w1
mov w1, trapaddr+2
#endasm
fprintf( MONITOR_SERIAL, "\n\rTRAP ADDRESS: %d", trapaddr );
}
|
And on *every* occasion, the address printed is 2097152 (0x200000). This is somewhat of a perfect HEX number. Now what do I do? Working the internals of the PIC and looking at stacks and memory dumps and stuff is not something I've done so I need help here. So where do I look next? What should be my next step now that I know what's the address that got caught? |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1355
|
|
Posted: Fri Dec 05, 2014 9:39 am |
|
|
Did you check the LST file to ensure no pushes/pops occurred in the beginning if the ISR so that you know the value of w15 you are saving is the actual address causing the error.
Without having my pic24 nearby, I don't recall if the address trap ISR does stack saving of all the registers at the beginning or not. I know other regular ISRs do though. You might be getting the value of the status register or another register which is the same every time. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Dec 05, 2014 10:19 am |
|
|
It does.
It's the later compiler.
CCS have changed how many registers are saved when an ISR is called. The offset in the routine needs to change from 36, to 38. Currently it is restoring the status register....
Annoying. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Dec 05, 2014 11:37 am |
|
|
So? What the suggestion here?
I've looked in my LST file and I cannot seem to be able to find address 0x20000... or am I not seeing it?
Based on the memory map in the Microchip specs FIGURE 4-1 (page 25), that's well within my user program flash memory...
Also, since I can print on my screen from inside the address trap the address, how would I go about printing , let's say, the contents of the 20 addresses previous to the problematic address?
Any suggestions of stuff I can try (with code examples please)?
Thanks again,
Benoit |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Dec 05, 2014 3:22 pm |
|
|
No.
You need to change the line:
sub #36, w0
to
sub #38, w0
CCS have changed how many registers are saved when a routine enters the interrupt handler, from when the code was written. It is currently restoring the next address 'up' the stack, which is the status register.
This will then show the correct address.
0x20000, if it was an address being read, is where the device ID is stored. However code can't be at this point. This is not where your problem is. |
|
|
|