after few days of debugging a random crash/exception in a pretty big project, I finally reduced the code to a misaligned memory access. What makes it random is that adding or removing code, results in generating the exception or not. The code where the exception occurs assumes that it will work with aligned variables or constants. However, the linker does not keep track of variables and constants passed to this code, if they are aligned or not, so a misaligned var/const will trigger an exception.
The below code contains a 17-byte constant array (OddData), which makes allocation of another constant array (InputData) to be made at odd address. When working with the second array constant as a series of DWords (ProcessData procedure), it is assumed that this array is already aligned to a word boundary, so an exception occurs.
Code: Select all
program AddrException;
type
PDWord = ^DWord;
PWord = ^Word;
PByte = ^Byte;
var
DebugLED: sbit at LATB.0;
DebugLED_Direction: sbit at TRISB.0;
procedure InfiniteLedBlink1;
begin
repeat
DebugLED := 1;
Delay_ms(40);
DebugLED := 0;
Delay_ms(40);
until False;
end;
procedure AddressTrap; org 0x06; //if the addressing mode is wrong, the code jumps here
begin
INTCON1.3 := 0;
InfiniteLedBlink1;
end;
procedure Init_MCU;
begin
// Setting output frequency to 140MHz
PLLFBD := 68; // PLL multiplier M=70
CLKDIV := 0x0000; // PLL prescaler N1=2, PLL postscaler N2=2
ANSELA := 0x00; // Convert all I/O pins to digital
ANSELB := 0x00;
ANSELC := 0x00;
ANSELD := 0x00;
ANSELE := 0x00;
ANSELG := 0x00;
DebugLED_Direction := 0; //RB2
end;
procedure ProcessData(InData, OutData: PByte);
var
r: Word;//DWord;
aa: array[0..3] of array [0..3] of Byte;
begin
PDword(@aa[0][0])^ := PDword(InData)^;
PDword(@aa[1][0])^ := PDword(DWord(InData) + 4)^; //exception here, because InData is not word-aligned
PDword(@aa[2][0])^ := PDword(DWord(InData) + 8)^;
PDword(@aa[3][0])^ := PDword(DWord(InData) + 12)^;
//...
//do some math here
//...
PDWord(OutData)^ := PDWord(@aa[0][0])^;
PDWord(DWord(OutData) + 4)^ := PDWord(@aa[1][0])^;
PDWord(DWord(OutData) + 8)^ := PDWord(@aa[2][0])^;
PDWord(DWord(OutData) + 12)^ := PDWord(@aa[3][0])^;
end;
procedure DummyProc;
var
i: Integer;
const
OddData: array[0..16] of Byte = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); //org 0x237A4;
begin
for i := 0 to 2 do
LATA := OddData[i];
end;
procedure TestAddressException;
const
InputData: array[0..15] of Byte = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); //org 0x235A4;
var
ALocalVar: array[0..15] of Byte;
begin
ProcessData(PByte(@InputData), PByte(@ALocalVar));
end;
begin
Delay_ms(100);
Init_MCU;
DummyProc;
TestAddressException;
end.
Code: Select all
_ProcessData:
0x0200 0xFA0010 LNK #16
;AddrException.mpas,53 :: begin
;AddrException.mpas,54 :: PDword(@aa[0][0])^ := PDword(InData)^;
0x0202 0x470060 ADD W14, #0, W0
0x0204 0x78183A MOV [W10++], [W0++]
0x0206 0x78102A MOV [W10--], [W0--]
;AddrException.mpas,55 :: PDword(@aa[1][0])^ := PDword(DWord(InData) + 4)^;
0x0208 0x470264 ADD W14, #4, W4
0x020A 0x78000A MOV W10, W0
0x020C 0xEB0080 CLR W1
0x020E 0x400164 ADD W0, #4, W2
0x0210 0x4881E0 ADDC W1, #0, W3
0x0212 0xBE0012 MOV.D [W2], W0 ; Exception here, because W2 is an odd number
0x0214 0xBE8A00 MOV.D W0, [W4]
;AddrException.mpas,56 ::
Compiler mikroPascal for dsPIC, v7.0.1.
In the above example, the ProcessData procedure is called with a constant, because it is easier to reproduce allocation of that constant at an odd address without memory specifiers. However, when this is called with a variable, from another procedure, I'm not sure if that variable will always have an aligned address or I should use global vars with hardcoded addresses.
I there any way to make sure variables and constants are allocated at word-aligned addresses? I already have several 1KB arrays in this project, passed to this kind of code, so converting them to array of words is not an option. Also, manually allocating at aligned addresses is an extra maintenance that sooner or later will be impossible to do.
The problem may also be found in PIC32 under a different use case viewtopic.php?f=172&t=61287
Thank you