• AVR Freaks

AnsweredHot!Exception on pointer inside a structure

Author
luk
Starting Member
  • Total Posts : 35
  • Reward points : 0
  • Joined: 2015/10/08 07:12:34
  • Location: 0
  • Status: offline
2021/03/03 22:46:12 (permalink)
0

Exception on pointer inside a structure

Hello,
 
My program should allow the user to choose the output to switch on/off and to check if that output is switched on/off thanks to UART commands.
The outputs are mapped to indexes (0 to 13) so that a simple call to a function with the output index as argument will be able to switch or read the right output.
 
    
typedef struct{
   volatile uint32_t *CLRptr;
   volatile uint32_t *SETptr;
   volatile uint32_t *LATptr;
   volatile uint32_t MASK;
}Portmap_out;
 
Portmap_out PORTS[14];
 
    PORTS[0].CLRptr = &LATBCLR;
    PORTS[0].SETptr = &LATBSET;
    PORTS[0].LATptr = &LATB;
    PORTS[0].MASK = _LATB_LATB8_MASK;
    
    PORTS[1].CLRptr = &LATCCLR;
    PORTS[1].SETptr = &LATCSET;
    PORTS[1].LATptr = &LATC;
    PORTS[1].MASK =  _LATC_LATC13_MASK;
    
    PORTS[2].CLRptr = &LATBCLR;
    PORTS[2].SETptr = &LATBSET;
    PORTS[2].LATptr = &LATB;
    PORTS[2].MASK = _LATB_LATB7_MASK;
...

 
Then, when the uart receives the command to switch or read any output index, these functions should do the job.
 

void setOutput(uint8_t index, uint8_t value)
{
    if(index >= 0 && index <= 13)
    {
        if(value)
            *PORTS[index].SETptr = PORTS[index].MASK; //switch the output ON
        else
            *PORTS[index].CLRptr = PORTS[index].MASK; //switch the output OFF
    }
}

/////////////////////////////////////////////////////////////////////////

uint8_t getOutput(uint8_t index)
{
    if(index >= 0 && index <= 13)
    {
        if(*PORTS[index].LATptr & PORTS[index].MASK) //read the value of the latch
            return 1;
        else
            return 0;
    }
    return 0;
}

 
It actually works but raise an exception from time to time randomly.
the Exception cause is EXCEP_AdEL = 4, // address error exception (load or ifetch)
with the exception address either:

 
*PORTS[index].SETptr = PORTS[index].MASK; //switch the output ON
// or
*PORTS[index].CLRptr = PORTS[index].MASK; //switch the output OFF
// or
if(*PORTS[index].LATptr & PORTS[index].MASK) //read the value of the latch

 
The getOutput() and setOutput() functions are placed in the Timer1 ISR with an IPL of 3.
 
I understand that I certainly don't use the structure pointers in a correct way, but I don't see where exactly the problem is.
Should I map the output directly inside the function with a switch statement, or can I keep the pointers ?
 
I attach the register values cached on the first line of _general_exception_handler(void);
 
Thank you !
 
 
post edited by luk - 2021/03/03 22:52:27

Attached Image(s)

#1
NKurzman
A Guy on the Net
  • Total Posts : 19185
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/03 23:47:54 (permalink)
4 (1)
Are you accessing a 16 bit variable that you told the compiler was 16 bit? (or 8 bit)
Either directly or via a pointer.
 
I assume all your pointers are pointing to valid memory in the correct memory space ( cached, non cached Physical)
#2
andersm
Super Member
  • Total Posts : 2901
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 03:07:13 (permalink)
4 (2)
Since the exception appears to occur randomly, the real problem might lie elsewhere, eg. memory corruption. Do all your interrupts match the ISR signature (IPL, shadow register)? Look in the map file at what's been allocated around the PORTS table. Is there anything that could over/underflow? When the exception triggers, does the contents of the table and surrounding memory look correct?
 
The BadVAddr register shows that the processor was trying to access address 0xE7, does that value look familiar?
#3
moser
Super Member
  • Total Posts : 637
  • Reward points : 0
  • Joined: 2015/06/16 02:53:47
  • Location: Germany
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 03:23:37 (permalink)
4 (1)
The struct and the pointers look OK to me. However, it doesn't make any sense to declare MASK as volatile and might only give you less efficient code, but it should not cause any harm.
 
You forgot to tell us your device. Verify, that your processor header file which is included by xc.h, defines all ports by using uint32_t.
 
The BadVAddr looks strange, and in particular is not a multiple of 4, as it should be for accessing uint32_t or pointers. And very likely it also is not a valid address at all for your processor.
 
When you said "It actually works", did you check all of set, clear and read for all 14 indices?
If not, then are you sure, your PORTS table is correct, and you didn't miss an & sign at index 7? Or at any other index, which you did not show? ;-)
 
The lines in question have 2 loads, and the one in getOutput() has 3 loads. PORTS[index].WHATEVERprt on the left side, and PORTS[index].MASK on the right side, and for the one in getOutput() the actual read. Maybe split up the instructions, and check at which line it really happens:
uint32_t const THEMASK = PORTS[index].MASK;
if(value) {
  uint32_t volatile * const PORTSETptr = PORTS[index].SETptr;
  *PORTSETptr = THEMASK; //switch the output ON
} else {
  uint32_t volatile * const PORTCLRptr = PORTS[index].CLRptr 
  *PORTCLRptr = THEMASK; //switch the output OFF
}

Or just check the assembly instructions around EPC (0x9D00918B) to find out.
 
 
If you verified all 3x14 use cases, then I join andersm: Maybe something else is corrupting your PORTS table. 
 
Btw: You can make that thing const:
Portmap_out const PORTS[14] = {
    { .CLRptr = &LATBCLR, .SETptr = &LATBSET, .LATptr = &LATB, .MASK = _LATB_LATB8_MASK  }, // 0
    { .CLRptr = &LATCCLR, .SETptr = &LATCSET, .LATptr = &LATC, .MASK = _LATC_LATC13_MASK }, // 1
    // ...
};

#4
luk
Starting Member
  • Total Posts : 35
  • Reward points : 0
  • Joined: 2015/10/08 07:12:34
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 04:10:39 (permalink)
0
However, it doesn't make any sense to declare MASK as volatile and might only give you less efficient code, but it should not cause any harm.

True, I actually added volatile to see if it will solve the problem, but will remove it.
You forgot to tell us your device. Verify, that your processor header file which is included by xc.h, defines all ports by using uint32_t.

Sorry, The device is a pic32mm0256gpm064 rev. 0xA3
xc.h is included
 
The BadVAddr looks strange, and in particular is not a multiple of 4, as it should be for accessing uint32_t or pointers. And very likely it also is not a valid address at all for your processor.

Indeed !
When you said "It actually works", did you check all of set, clear and read for all 14 indices?
If not, then are you sure, your PORTS table is correct, and you didn't miss an & sign at index 7? Or at any other index, which you did not show? ;-)

I checked that at least 10 times :) Actually all outputs are read every second so a mistake there would stop the program on the very first second of running.

The lines in question have 2 loads, and the one in getOutput() has 3 loads. PORTS[index].WHATEVERprt on the left side, and PORTS[index].MASK on the right side, and for the one in getOutput() the actual read. Maybe split up the instructions, and check at which line it really happens:

 
Good idea !
 
I realized that the exceptions start to happen after 3 hours of running +/- 15 minutes. I have also have a huge log table that takes 90% of the RAM. Maybe there is an overflow there... I will check this on the next exception.
Thanks for the advices, it helped a lot ! I will keep you informed ;)
#5
Mysil
Super Member
  • Total Posts : 4130
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 04:25:56 (permalink)
0
Hi,
Since the microcontroller is a PIC32MM...  device, it use micro-MIPS instructions and instruction addresses,
which shall have a bit set in the low order (unused) 2 address bits.
 
    Mysil
#6
luk
Starting Member
  • Total Posts : 35
  • Reward points : 0
  • Joined: 2015/10/08 07:12:34
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 04:45:57 (permalink)
0

Since the microcontroller is a PIC32MM...  device, it use micro-MIPS instructions and instruction addresses,
which shall have a bit set in the low order (unused) 2 address bits.

I don't understand...
 
I have more information:
The PORT table gets corrupted during runtime. I saw it happening live  :
0x63AC = 0xF2,
on next break 0x63B0 = 0xF3, 
on next break 0x63B4 = 0xF4, 
on next break 0x63B8 = 0xF5, 
on next break 0x63BC = 0xF6, 
then Exception.
(see picture attached)
 
 

Attached Image(s)

#7
andersm
Super Member
  • Total Posts : 2901
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/04 05:50:51 (permalink) ☄ Helpfulby luk 2021/03/10 11:43:04
4 (1)
If the corruption is deterministic (ie. always the same memory locations), try placing a watchpoint on one of the affected addresses.
#8
moser
Super Member
  • Total Posts : 637
  • Reward points : 0
  • Joined: 2015/06/16 02:53:47
  • Location: Germany
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/05 01:51:39 (permalink) ☼ Best Answerby luk 2021/03/10 11:32:46
4 (1)
A const PORTS table would be in program memory and protected from corruption. Also it would free up RAM and use program memory instead.
 
However, you should not change this now, because changing it would only cause some other memory to get corrupted. You should first follow the suggestion of andersm and find the issue.
 
 
If you work with arrays and from quickly looking at your code you can't create for every array access a simple formal proof, that your index can never overflow or underflow, then I always suggest to add range checks similar like the one, you already showed:
if(index >= 0 && index <= 13)
Even if you use pointers instead of indices, you can do the same and make sure they point at least to memory in the range from the first element to the last element:
if (ptr >= &my_array[0] && ptr <= &my_array[MY_ARRAY_MAX_INDEX - 1])

If it fails you can set some error flags or error code, or do something which you will notice during development. In most cases you can really afford these few CPU cycles. If not, then maybe you could still have them for assertion in the debug build.
 
 
#9
luk
Starting Member
  • Total Posts : 35
  • Reward points : 0
  • Joined: 2015/10/08 07:12:34
  • Location: 0
  • Status: offline
Re: Exception on pointer inside a structure 2021/03/10 11:42:52 (permalink)
0
Problem solved after a deep dive into the execution memory. It was simply an array overflow inside another function. It started to write data above the array limit after few hours of running because I failed to fix the index limit.
 
I'm used to work on visual studio with C#, and there is an "array out of bound exception" thrown on this kind of issue. It's always a challenge to switch to such low level programming mode pink: pink
 
Thank you all anyway ! Have a nice day/evening/night mr green: mr green
#10
ric
Super Member
  • Total Posts : 30223
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Exception on pointer inside a structure 2021/03/10 12:13:51 (permalink)
5 (1)
C# is a very different language to C.
They added a lot of features (and overhead) to the language precisely to allow it to protect the programmer from faulty code...
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#11
Jump to:
© 2021 APG vNext Commercial Version 4.5