CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

ADDRESS ERROR TRAP INTERRUPT PIC24H
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

ADDRESS ERROR TRAP INTERRUPT PIC24H
PostPosted: Fri Oct 03, 2014 7:20 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 7:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 7:51 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 8:01 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 8:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 15, 2014 8:14 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Wed Oct 15, 2014 9:32 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 15, 2014 10:30 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Wed Oct 15, 2014 10:48 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 15, 2014 11:37 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 7:05 am     Reply with quote

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: 1354

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 9:39 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 10:19 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 11:37 am     Reply with quote

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: 19538

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 3:22 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group