Helpful ReplyHot!Address Error Traps caused by rand() and Best Practices?

Page: 12 > Showing page 1 of 2
Author
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
2018/08/22 10:33:25 (permalink)
0

Address Error Traps caused by rand() and Best Practices?

Hello,
 
I am using a PIC24FJ256GA606, and I am having a hard time figuring out the exact cause of Address Error Trap.
 
I managed to find out the function that is causing the traps to occur. All this function does is to generate a random number that is within a specified range.
 
uint64_t GenerateRandomNumber(uint64_t min, uint64_t max){
   
    
    uint64_t RandomValue = 100; //this works all the time, but it is not pseudorandom
// uint64_t RandomValue = (uint64_t) rand(); //this causes traps to occur

    uint64_t RandomDelay = (RandomValue + min) % (max + 1 - min);

    return RandomDelay;
}

 
I think I understand the concept of address misalignment, but I don't think I am very cautious about it during implementation. I have read the PIC24 FRM about interrupts so I know the different scenarios that can cause traps to happen, but C-programming wise I would like to know how to write my code so that the scenarios mentioned will not occur. 
 
At this point I am guessing that type-casting can be a big contributor to this error trap? In the past I was messing around with pointer casting (i.e. void* -> uint16_t* -> uint8_t*) and that caused the error trap to happen as well.
 
Again, it would be nice if there is a list of rules/best practices to follow in the future. 
 
Really appreciate you guys' help.
 
post edited by olochua - 2018/08/22 10:50:39
#1
jtemples
Super Member
  • Total Posts : 11019
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 10:51:00 (permalink) ☄ Helpfulby olochua 2018/08/22 10:55:08
5 (1)
I'm not aware of anything that will cause an address trap other than dereferencing inappropriate pointer conversions.  I believe recent versions of XC16 will generate correct code to deal with pointers into packed structs that have misaligned words.
 
There's nothing in your snippet that should cause a trap.  Are you sure the trap is coming from that function?  Changing the code can move RAM objects around and cause traps elsewhere in the code.
#2
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 10:59:25 (permalink)
0
jtemples
There's nothing in your snippet that should cause a trap.  Are you sure the trap is coming from that function?  Changing the code can move RAM objects around and cause traps elsewhere in the code.




Oh I actually didn't know moving RAM objects can cause traps elsewhere, thanks for pointing that out. 
 
I was using a global variable to keep track of my location in different function calls:
 
uint64_t SetRandomDelay(uint64_t min, uint64_t max){
   
    FunctionLocation = 9999;

    uint64_t RandomValue = (uint64_t)rand();

    FunctionLocation = 9998;
    uint64_t RandomDelay = RandomValue + min % (max + 1 - min);

    FunctionLocation = 9997;
    
    return RandomDelay;

 
Whenever the trap happens, it always printed out 9999. So I am assuming that it didn't make it to the next line of code?
 
Now that I think about it, I might have to look into my TMR and UART interrupt functions too. Maybe those are the ones that are actually giving me the issues?
 
Thanks for your help!
 
 
 
#3
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 11:04:49 (permalink)
0
Quick update: I assigned different function locator values at the beginning and end of interrupt handling routines, but those values never got printed out, so I think they are probably fine.
 
 
post edited by olochua - 2018/08/22 11:06:35
#4
jtemples
Super Member
  • Total Posts : 11019
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 11:09:41 (permalink) ☄ Helpfulby olochua 2018/08/22 11:28:01
5 (1)
If you've got an inappropriate pointer somewhere, there's a 50% chance that it will cause a trap, depending on whether the thing it's pointing at is evenly aligned or not.  If you make changes to unrelated parts of the code, that object might happen to move from an even alignment to an odd alignment, and cause a trap.
 
There's code somewhere in the XC16 package that shows you how to trap traps.
#5
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 11:27:19 (permalink)
0
jtemples
If you've got an inappropriate pointer somewhere, there's a 50% chance that it will cause a trap, depending on whether the thing it's pointing at is evenly aligned or not. 
...
There's code somewhere in the XC16 package that shows you how to trap traps.

Can you give me a few examples of inappropriate pointers? Do you mean like casting pointer to stricter ones? For my case, all my pointers are of type uint8_t*, and they are used to dereference uint8_t arrays (i.e., *(pointer+2)). Is that okay?
 
I am using the generated interrupt routines to print out my function locator:

void ERROR_HANDLER_NORETURN _AddressError(void)
{
INTCON1bits.ADDRERR = 0; //Clear the trap flag
printf("Address Trap at %d\r\n", FunctionLocation);
TRAPS_halt_on_error(TRAPS_ADDRESS_ERR);
}

 
Thanks again!
#6
jtemples
Super Member
  • Total Posts : 11019
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 11:33:45 (permalink) ☄ Helpfulby olochua 2018/08/22 11:39:26
5 (1)
For my case, all my pointers are of type uint8_t*, and they are used to dereference uint8_t arrays (i.e., *(pointer+2)). Is that okay?

 
As long as you're using uint8_t * pointers to uint8_t objects, you're fine.  What's not safe is having a uint8_t array and pointing at it with a uint16_t *, for example.
#7
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 11:39:21 (permalink)
0
Thanks again for the input, I really appreciate your time.
 
By the way, I am not sure if this matters, but can large/small code models cause address error traps? Because for this project I am using a large code model.
#8
qhb
Superb Member
  • Total Posts : 7928
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: online
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 15:00:07 (permalink)
0
Just a small side issue, is your "FunctionLocation" variable declared as "volatile" ?
If not, some of the writes to it could be discarded by the compiler, muddying the issue.
 
#9
HowardSchlunder
MCU16 Applications
  • Total Posts : 744
  • Reward points : 0
  • Joined: 2007/06/14 16:26:19
  • Location: Chandler, AZ
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 20:25:32 (permalink)
4.67 (3)
Large vs small code models will not cause an Address Error Trap. You'll just get a build-time link failure when your code or referenced library functions are compiled against the Small Code model while the Large Code model is required. Using the Large Code model always works, but wastes flash when your target device or project size doesn't need it. The difference is that the compiler emits 48-bit CALL and GOTO instructions to branch around under the Large Code model, whereas the Small Code model generates 24-bit RCALL and BRA instructions, which can only branch +/-32 K instructions (+/- 96KB) relative to the absolute position of the RCALL/BRA instruction in flash. The linker terminates when it encounters an RCALL/BRA instruction having a target address that is impossible to reach with the opcode.
 
I agree with jtemples, your GenerateRandomNumber() function does not contain code that can generate an Address Error Trap.
 
Are you using XC16 v1.32 though v1.35 and optimization level -O1, -O2, or -Os? If so, you've likely encountered a compiler bug related to the use of 64-bit integers. Using -O0, -O3, XC16 v1.31, or the next XC16 version (v1.36?) would make the problem go away. I encountered and reported a problem to the compiler group earlier this week, so it will be fixed in the next release, but for now, uint64_t's can't be trusted with those compiler version/optimization combinations.
 
If the trap occurs with an unaffected tool/optimization combination, an interrupt or code elsewhere is likely responsible. To find the exact location, I would run the code in the debugger and put Software Breakpoints or __builtin_software_breakpoint() calls before and after the suspected regions, then use the Run command to observe what code is reached. Interrupts and traps are masked while one-stepping, so you may not see the offending event happen until the next Run command (or step command against a sufficiently complex statement that causes the debugger to internally use a breakpoint after the statement to rehalt).
#10
NKurzman
A Guy on the Net
  • Total Posts : 16670
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: online
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 21:02:29 (permalink)
4 (1)
I would make sure you have the trap handler code in your project. If you single step out of the trap it will go to the line causing the trap.
#11
JPortici
Super Member
  • Total Posts : 454
  • Reward points : 0
  • Joined: 2012/11/17 06:27:45
  • Location: Grappaland
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/22 23:10:42 (permalink)
5 (2)
jtemples
I'm not aware of anything that will cause an address trap other than dereferencing inappropriate pointer conversions. 


dereferencing a pointer to an unimplemented area of memory will also cause an address trap
 
 
 
@OP Have you tried to create a new project with just the bare minimum to test your function?
post edited by JPortici - 2018/08/22 23:15:11
#12
Aussie Susan
Super Member
  • Total Posts : 3367
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/23 20:54:33 (permalink)
5 (1)
Have you tried not typecasting the return value from the 'rand()' function?
Typecasting is not the same as value promotion - it simply tells the compiler that the source value is to be treated as the specified type which can cause it to just include other bits at the top of the required ones, or (although I don't think this is the case here) bad address alignment.
(I recall somewhere that this was discussed in relation to the XC16 compiler and it can do some unexpected things with typecasting.)
Susan
#13
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/27 11:09:46 (permalink)
0
qhb
Just a small side issue, is your "FunctionLocation" variable declared as "volatile" ?
If not, some of the writes to it could be discarded by the compiler, muddying the issue.
 


Do I still need to declare volatile if I am not using optimization (level 0)?
 
#14
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/27 11:16:43 (permalink)
0
HowardSchlunder
Large vs small code models will not cause an Address Error Trap. You'll just get a build-time link failure when your code or referenced library functions are compiled against the Small Code model while the Large Code model is required. Using the Large Code model always works, but wastes flash when your target device or project size doesn't need it. The difference is that the compiler emits 48-bit CALL and GOTO instructions to branch around under the Large Code model, whereas the Small Code model generates 24-bit RCALL and BRA instructions, which can only branch +/-32 K instructions (+/- 96KB) relative to the absolute position of the RCALL/BRA instruction in flash. The linker terminates when it encounters an RCALL/BRA instruction having a target address that is impossible to reach with the opcode.

 
Sounds good, thanks for the info!
 
HowardSchlunder
 
Are you using XC16 v1.32 though v1.35 and optimization level -O1, -O2, or -Os? If so, you've likely encountered a compiler bug related to the use of 64-bit integers. Using -O0, -O3, XC16 v1.31, or the next XC16 version (v1.36?) would make the problem go away. I encountered and reported a problem to the compiler group earlier this week, so it will be fixed in the next release, but for now, uint64_t's can't be trusted with those compiler version/optimization combinations.

 
I am currently using v1.33 with level 0 optimization. I will keep this in mind, thanks for clarifying.
 
HowardSchlunder
 
If the trap occurs with an unaffected tool/optimization combination, an interrupt or code elsewhere is likely responsible. To find the exact location, I would run the code in the debugger and put Software Breakpoints or __builtin_software_breakpoint() calls before and after the suspected regions, then use the Run command to observe what code is reached. Interrupts and traps are masked while one-stepping, so you may not see the offending event happen until the next Run command (or step command against a sufficiently complex statement that causes the debugger to internally use a breakpoint after the statement to rehalt).




MCC's generated trap handling functions have the breakpoints implemented in debug mode, so I get to make use of them without issues. 
 
#15
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/27 11:57:45 (permalink)
0
Thank you guys for your feedback! I really appreciate your time.
 
Quick update:
Like you guys pointed out, the random number generator function itself doesn't seem to be causing any address error traps. I extracted the function to make it run on its own, and I was not able to replicate the problem.
 
Here is a little background information that might be helpful for you guys. I initially had this project working as a PIC24FJ128GA306 library. But recently I decided to use a different micro (PIC24FJ256GA606) for my application. I thought the transition process would be straightforward: all I had to do was to change the target microcontroller in Properties and rebuild the library project. Besides, I thought the library is pretty independent, because it does not have any configuration words defined, and all of the peripheral-related items are assigned using the macros in xc.h (IFS0bits.T1IF, PR1, U3BRG, etc). Therefore, rebuilding the project should be able to reassign the macros easily. 
 
Since I was not really able to figure out the problem, I tried creating an identical PIC24FJ256GA606 project from scratch instead of transitioning from the one for PIC24FJ128GA306, and it turned out that I was not able to replicate the address error trap issue. I probably messed up somewhere during the transition process?
 
I am still looking into this issue, and I will keep you all posted.
 
Thanks again!
 
 
#16
qhb
Superb Member
  • Total Posts : 7928
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: online
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/27 14:59:30 (permalink)
4 (1)
olochua
qhb
Just a small side issue, is your "FunctionLocation" variable declared as "volatile" ?
If not, some of the writes to it could be discarded by the compiler, muddying the issue.
 


Do I still need to declare volatile if I am not using optimization (level 0)?

The higher the optimisation, the more likely it is the lack of "volatile" will cause problems.
 
#17
Aussie Susan
Super Member
  • Total Posts : 3367
  • Reward points : 0
  • Joined: 2008/08/18 22:20:40
  • Location: Melbourne, Australia
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/08/27 19:39:59 (permalink)
4 (1)
What 'volatile' tells the compiler is that the value in the variable can change without the compiler knowing about it.
No matter what the level of optimisation, the compiler generally makes an assumption that the code it can see is all that is happening with the variables. This means that it can copy a variable into a register, do something and 'know' that the value in the register is still the same as the value in the variable.
However if an ISR (or DMA or something) can change the value of the variable, then the compiler needs to be told - and that is what the 'volatile' keyword does.
If the compiler copies a volatile variable value into a register, then it cannot assume that the value in the register will stay the same as the value in the variable. Therefore, it will need to use the variable value directly (as much as it can).
Susan
#18
olochua
Starting Member
  • Total Posts : 46
  • Reward points : 0
  • Joined: 2017/06/06 10:38:42
  • Location: 0
  • Status: offline
Re: Address Error Traps caused by rand() and Best Practices? 2018/09/05 13:44:45 (permalink)
0
Thanks again for the input. I tried using volatile global variable to track the trap, but I was not able to replicate the issue. jtemples mentioned that adding code can move the RAM objects around, so could that deceptively fix the issue?
 
I also looked into my code further, and I was able to summarize my pointer usage to the following:

uint8_t SomeArray[100] = {...};
uint8_t* SomeArrayPtr = SomeArray;
uint8_t Var1, Var2;
 
SomeArrayPtr += 10;
if(*(SomeArrayPtr + 4) == 0xFF){
Var1 = *(SomeArrayPtr + 1);
Var2 = *(SomeArrayPtr - 2);
*(SomeArrayPtr + 3) = Var1;
}
 

 
Is the code above safe? Can it cause address error traps?
 
#19
qhb
Superb Member
  • Total Posts : 7928
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: online
Re: Address Error Traps caused by rand() and Best Practices? 2018/09/05 13:49:15 (permalink)
4 (1)
That code looks extremely likely to generate a pointer outside the bounds of your array.
Do you have any sort of test after adding 10 to the pointer to make sure that (SomeArrayPtr + 4) is not past the end of your array?
 
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2018 APG vNext Commercial Version 4.5