• AVR Freaks

AnsweredHot!Default alignment of auto variables declared in a block

Author
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
2020/11/30 22:16:58 (permalink)
0

Default alignment of auto variables declared in a block

I am tracking down a bug that occurs very infrequently doing some maintenance on code written long ago, that creates an annoying error periodically. If an auto variable is declared in a block (and is the only variable declared):
 
while (....) {
   uint8_t  buf[1024];
 
}
 
is there any guarantee on the minimum alignment of the variable, even if it is byte type? This buf is eventually being used to write flash, so it needs to be aligned to a word boundary. It appears that the flash contents can get corrupted rather infrequently, and this routine might only get called once a week to once a month, so nearly impossible to reproduce on demand. If compiler behavior would always  align a byte array as the first element in a block as word aligned, then I need to probably keep looking elsewhere. If it can be aligned on any byte boundary, this is my most likely suspect, where I need to force the alignment to a word boundary. To do it purely speculatively means I might have to wait weeks or longer to verify success, so knowing how the compiler aligns the first auto variable in a block would be valuable information to feed the decision tree. I've pretty much ruled out other sources of error (interrupts during flash ops, invalid DSR and DSWPAG values, etc.). This is on a PIC24EP512GU810.
 
I can't find anything in the compiler manuals that speaks to this. The only reason I'm hesitant to say "aha. that' likely it" is the fact that it happens so infrequently given the number of units out there. Anyone know?
#1
NKurzman
A Guy on the Net
  • Total Posts : 19106
  • Reward points : 0
  • Joined: 2008/01/16 19:33:48
  • Location: 0
  • Status: online
Re: Default alignment of auto variables declared in a block 2020/11/30 22:27:22 (permalink)
0
 __attribute__ ((aligned (2)))
But it does not sound like the Issue. A misalignment would cause an exception every time.
Are you sure you are disabling the Interrupts during the Critical Section?
#2
BroadwellConsultingInc
Super Member
  • Total Posts : 97
  • Reward points : 0
  • Joined: 2020/06/09 06:07:55
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2020/12/01 06:48:24 (permalink)
+1 (3)
Is it possible you're exceeding your stack space?  Your pic has a pretty generous 52k of RAM, but 1024 bytes of auto-variable is still uncommon in most small embedded systems.  Stack related issues are often intermittent.  XC16 typically allocates the stack at the end of memory and it grows upwards.  
 
The PIC 24 series has a stack exception handler.  Have you implemented this handler?  Or does it cause a reset?
 
Can you take a look in your .map file and copy in the section that looks like this:
 
Dynamic Memory Usage

region address maximum length (dec)
------ ------- ---------------------
heap 0 0 (0)
stack 0x316e 0x1692 (5778)

                 Maximum dynamic memory (bytes): 0x1692 (5778)

#3
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2020/12/01 08:37:18 (permalink)
0
Thanks for the suggestions. Stack space is fine I believe. There is a stack exception handler and it is not trapping (but I haven't triggered it yet). But I do agree that 1024 is a lot to put on the stack. My theory on the automatic variables is: if it it aligned based on the underlying data types, it might be hit or based on whatever prior calls have affected the stack to this point. So if it is called from  routine A, it might have been aligned on a word boundary, however if the stack was on an odd boundary, when called by routine B, it might be odd aligned. I *suspect* the stack is always word aligned (even for byte type) when a new block is entered, but I haven't seen anything to confirm that. I've gone through and verified interrupts seem to be protected. I even used a spare timer to throw a flurry of 50us interrupts while running to try to provoke anything that might have been missed, to no avail so far. About 4500 bytes is allocated to the stack, and this software structure is not very deep, but I will go back and make sure there are no other big buffers that can be in the call stack based on the call graph. Thanks!
#4
NorthGuy
Super Member
  • Total Posts : 6464
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: Default alignment of auto variables declared in a block 2020/12/01 10:03:30 (permalink)
+2 (2)
Stack is word aligned. So, if this is the only variable, the compiler would have to do special work to make the variable non word-aligned. You can look at the dissasembly and see how it is allocated upon the entry into the function.
#5
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2020/12/03 15:10:50 (permalink)
+2 (2)
Thank you. All my tests showed it to be word aligned, but I never saw anything in the documentation that asserted this and wanted to get some confirmation. I confirmed in the assembly. The root cause turned out to be having the flash (unnecessarily and gratuitously) rewritten periodically even when the contents hadn't changed. Therefore it was creating many unnecessary opportunities for a power glitch or having someone unplug the device while flash operations were occurring, which was ultimately what was corrupting it. Thank you @NorthGuy.
post edited by dkark - 2020/12/03 15:35:38
#6
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 14:02:43 (permalink)
0
Doing some maintenance on another product, I found that the answer that it is always word aligned is not always true. This was with XC16 1.61 with optimization turned off. The first automatic variable in the function came in with an odd address and is not actually word aligned. The picture below shows the problem.
 
I was able to solve this by using the __attribute__ (( aligned(2) )) as in:
 
uint8_t  __attribute__(( aligned(2) )) util[AES_SW_KEY_SIZE_128_BIT];
 
 
post edited by dkark - 2021/01/09 14:05:49

Attached Image(s)

#7
NorthGuy
Super Member
  • Total Posts : 6464
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 14:25:37 (permalink)
+1 (1)
dkark
Doing some maintenance on another product, I found that the answer that it is always word aligned is not always true.



The stack is word aligned. Then the compiler packs all the variables into the stack according to their (variables') alignment requirements. Thus, individual variables within the stack may not be word aligned. For example, if you have two "char" variables, they probably will be fit into a single word, so one of them will be unaligned.
 
If you only have one variable (whether array or scalar), it's very unlikely to be unaligned because the compiler would have to shift it out of the alignment on purpose.
post edited by NorthGuy - 2021/01/09 14:27:34
#8
ric
Super Member
  • Total Posts : 29435
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Default alignment of auto variables declared in a block 2021/01/09 14:57:11 (permalink)
0
I'm going to take a wild guess that the 8 bit variable variable "i" is at the start of the stack frame (address 0x6072), and the byte array is placed immediately after it.
 

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!
#9
dan1138
Super Member
  • Total Posts : 4157
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 15:47:41 (permalink)
+1 (1)
What I do not understand about the OP issue is how can an array of uint8_t starting on an odd address be a problem? Half of the array elements will be at an odd addresses regardless of the alignment it starts at. Code that cares when a uint8_t array starts on an odd or even address is bad code.
#10
ric
Super Member
  • Total Posts : 29435
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: Default alignment of auto variables declared in a block 2021/01/09 16:08:53 (permalink)
+1 (1)
I think this new question comes down to an incorrect expectation that the variables will be assigned addresses in the same order they are defined/declared.
 

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
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 18:20:39 (permalink)
+1 (1)
dan1138
What I do not understand about the OP issue is how can an array of uint8_t starting on an odd address be a problem? Half of the array elements will be at an odd addresses regardless of the alignment it starts at. Code that cares when a uint8_t array starts on an odd or even address is bad code.


There are certain routines (such as the assembly  AES128 encryption routines provided by MicroChip) that have an expectation that the first byte of the arrays passed in will be word aligned. Since the assembly language uses double byte instructions, not having the proper buffer alignments will cause an address trap error. Even thought the buffers themselves are treated as "byte" buffers in their definition, sizing, and use by C.
post edited by dkark - 2021/01/09 18:31:25
#12
dkark
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2015/10/26 06:24:52
  • Location: 0
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 18:29:09 (permalink)
0
ric
I think this new question comes down to an incorrect expectation that the variables will be assigned addresses in the same order they are defined/declared.
 


Different compilers and architectures do things differently, the OP was simply to ask if there were any assumptions that could be made about XC16 stack alignment when entering a new routine or code block. I think I've got proof that no, you can't make any assumptions other than it is aligned with its base data type. I don't think you were able to designate alignment constraints on automatic variables in the early versions of the compilers, but thankfully now you can.


 
#13
NorthGuy
Super Member
  • Total Posts : 6464
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: Default alignment of auto variables declared in a block 2021/01/09 18:46:03 (permalink) ☼ Best Answerby dkark 2021/01/09 21:13:51
+3 (3)
dkark
Different compilers and architectures do things differently, the OP was simply to ask if there were any assumptions that could be made about XC16 stack alignment when entering a new routine or code block. I think I've got proof that no, you can't make any assumptions other than it is aligned with its base data type. I don't think you were able to designate alignment constraints on automatic variables in the early versions of the compilers, but thankfully now you can.



Stack alignment and variable alignment are two different things.
 
Stack pointer (w15) is always aligned to word boundary. Hence, when a function enters, the space designated to local variables will be aligned to word boundary as well. This is a physical constrain which cannot be broken.
 
How the compiler uses the space is up to the compiler. Nothing is guaranteed.
#14
Jump to:
© 2021 APG vNext Commercial Version 4.5