Record structures generate problematic STRB's on unaligned boundaries.
Original Reporter info from Mantis: smiggles
-
Reporter name: Bob Jones
Original Reporter info from Mantis: smiggles
- Reporter name: Bob Jones
Description:
If you pass a routine a structure mapped to an absolute address the compiler generates assembler that references each byte of the stucture individually using LDRB/STRB combinations. On ARM processors this causes memory corruption when saving bytes using STRB that are not word or dword aligned.
ie:
Record declaration:
TIM_TimeBaseInitTypeDef = record
TIM_Prescaler :word;
TIM_CounterMode :word;
TIM_Period :word;
TIM_ClockDivision :word;
TIM_RepetitionCounter :byte;
end;
record instantiation:
TIM2 :TIM_TypeDef absolute TIM2_BASE;
assignment:
TIM2.ARR := TIM_TimeBaseInitStruct.TIM_Period;
results in:
ldr r1,[r11, #-44]
ldrb r0,[r11, #-56]
strb r0,[r1, #40] <- byte 1 (ok)
ldrb r0,[r11, #-55]
strb r0,[r1, #41] <- byte 2 not word aligned - ARM processor will corrupt memory.
If you do the following (save to the same address using a value not from a record):
PWord(($40000000)+44)^:=1000;
you get:
ldr r0,[r11, #-44]
mov r1,#1000
strh r1,[r0, #44]
Which is a correct half word properly aligned operation.
The problem occurs despite the record member explicitly being declared as a 'word'.
Whlst I was typing this I suddenly had the thought that the mention of the R11 register might be a bit of a clue - Is it in any way due to the way the compiler is stacking the record into the frame as a parameter when the routine is being called?
The problematic procedure is declared as follows:
procedure TIM_TimeBaseInit(var TIMx :TIM_TypeDef; TIM_TimeBaseInitStruct :TIM_TimeBaseInitTypeDef);
- with TIMx being the record that causes problems.
Hope that was vaguely understandable. :-)
Mantis conversion info:
- Mantis ID: 19355
- OS: embedded
- Platform: ARM
- Version: 2.4.3
- Fixed in version: 2.6.0
- Fixed in revision: 17468 (#f1b13dca)