Aligned memory access

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Aligned memory access

668 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rodrigo.such on Tue Dec 06 05:18:03 MST 2011
Hi guys,
  
  I´m using the LPCXpresso [COLOR=red][FONT=&quot]v4.1.0 [Build 190] [27/09/2011] [/FONT][/COLOR][FONT=&quot]and a LPC1768 LPCXpresso Board.[/FONT]
  [FONT=&quot] [/FONT]
  My problem, I guess, is related with a non-aligned access to register.
  First of all, I´m not using CMSIS. Because of some internal reasons we decide to develop our own hardware access library.
  So let me try to describe my issue;
  
  I`u describe my problem based in the clock configuration because It was the first thing I had to do, and so, the first place I´ve noticed the problem. However, I this is not a clock problem.
  According to LPC1768 User manual, I have several registers to configure the system clock. The PLL0CFG is one of them and it is described as follow:
  [COLOR=#1F497D] [/COLOR]
  [B][COLOR=red][FONT=&quot]14:0 MSEL0[/FONT][/COLOR][/B]
  [B][COLOR=red][FONT=&quot]15 Reserved[/FONT][/COLOR][/B]
  [B][COLOR=red][FONT=&quot]23:16 NSEL0[/FONT][/COLOR][/B]
  [B][COLOR=red][FONT=&quot]31:24 Reserved[/FONT][/COLOR][/B][B][COLOR=red][/COLOR][/B]
  [COLOR=#1F497D] [/COLOR]
  
  In order to access the PLL0CFG, bits I´ve declared this struct type:
  [COLOR=#1F497D] [/COLOR]
  [B][COLOR=#7F0055][FONT=&quot]typedef[/FONT][/COLOR][/B][COLOR=black][FONT=&quot] [/FONT][/COLOR][B][COLOR=#7F0055][FONT=&quot]union[/FONT][/COLOR][/B][FONT=&quot][/FONT]
  [COLOR=black][FONT=&quot]{[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=#005032][FONT=&quot]UInt32[/FONT][/COLOR][COLOR=black][FONT=&quot] [/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]Value[/FONT][/COLOR][COLOR=black][FONT=&quot];[/FONT][/COLOR][FONT=&quot][/FONT]
  [B][COLOR=#7F0055][FONT=&quot]struct[/FONT][/COLOR][/B][FONT=&quot][/FONT]
  [COLOR=black][FONT=&quot]{[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=#005032][FONT=&quot]UBitField32[/FONT][/COLOR][COLOR=black][FONT=&quot] [/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]MSEL[/FONT][/COLOR][COLOR=black][FONT=&quot] :15;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=#005032][FONT=&quot]UBitField32[/FONT][/COLOR][COLOR=black][FONT=&quot] [/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]Reserved[/FONT][/COLOR][COLOR=black][FONT=&quot] : 1;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=#005032][FONT=&quot]UBitField32[/FONT][/COLOR][COLOR=black][FONT=&quot] [/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]NSEL[/FONT][/COLOR][COLOR=black][FONT=&quot] : 8;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=#005032][FONT=&quot]UBitField32[/FONT][/COLOR][COLOR=black][FONT=&quot] [/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]Reserved1[/FONT][/COLOR][COLOR=black][FONT=&quot] : 8;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=black][FONT=&quot]}Bits;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=black][FONT=&quot]}[/FONT][/COLOR][COLOR=#005032][FONT=&quot]TClkPllCfg[/FONT][/COLOR][COLOR=black][FONT=&quot];[/FONT][/COLOR]
  [COLOR=#1F497D] [/COLOR]
  And I´m using this define:
  [B][COLOR=red][FONT=&quot] [/FONT][/COLOR][/B]
  [COLOR=#1F497D] [/COLOR]
  [B][COLOR=#7F0055][FONT=&quot]#define[/FONT][/COLOR][/B][COLOR=black][FONT=&quot] PLL0CFG (*(TClkPllCfg *)0x400FC084)[/FONT][/COLOR]
  [COLOR=black][FONT=&quot] [/FONT][/COLOR]
   “0x400FC084” is the register address.[FONT=&quot][/FONT]
  
                 In some time I try to configure this register just writing it as follow.
  [COLOR=#1F497D] [/COLOR]
  [COLOR=black][FONT=&quot]PLL0CFG[/FONT][/COLOR][COLOR=black][FONT=&quot].[/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]MSEL[/FONT][/COLOR][COLOR=black][FONT=&quot] = p_m;[/FONT][/COLOR][FONT=&quot][/FONT]
  [COLOR=black][FONT=&quot]PLL0CFG[/FONT][/COLOR][COLOR=black][FONT=&quot].[/FONT][/COLOR][COLOR=#0000C0][FONT=&quot]NSEL[/FONT][/COLOR][COLOR=black][FONT=&quot] = p_n;[/FONT][/COLOR]
  [COLOR=#1F497D][FONT=&quot] [/FONT][/COLOR]
  Using the debugger I see that the first line works fine. However when I run the second line, all the register is written with the same value, and therefore, I lost the MSEL value.
  This same .c code had been successfully used with EWARM (IAR embedded workbench) and works fine. The problem only occurs when using LPCXpresso.
  
  Based in these behaivor, I had some guesses:
  
  According to LPC17XX User Manual[COLOR=#1F497D], [/COLOR][B][COLOR=red][FONT=&quot]Unaligned accesses are usually slower than aligned accesses. In addition, some memory[/FONT][/COLOR][/B]
  [B][COLOR=red][FONT=&quot]regions might not support unaligned accesses[/FONT][/COLOR][/B][B][COLOR=red][FONT=&quot]. Therefore, ARM recommends that[/FONT][/COLOR][/B]
  [B][COLOR=red][FONT=&quot]programmers ensure that accesses are aligned.[/FONT][/COLOR][/B]
  [COLOR=#1F497D] [/COLOR]
  There is no specification of what memory regions I cannot have unaligned accesses but, I think, the registers works this way; I mean, I cannot access registers using non-aligned instructions.
  
  Seeing the disassembly I´ve noticed that EWARM (IAR embedded workbench), uses only aligned instructions to write the register, (STR instruction). At the same time the LPCXpresso uses STRB instruction that is non-aligned. Furthermore, using the “instruction step mode” I can see that everything is fine until the STRB instruction. The address and the data are correct, but the STRB instruction doesn’t write only one byte but all register, reinforcing my guess.
  [FONT=&quot] [/FONT]
  The disassembly code can be seen attached:
  [COLOR=#1F497D] [/COLOR]
  [CENTER][CENTER][COLOR=#1F497D] [/COLOR][/CENTER][/CENTER]

Does anyone know how to solve this problem without changing my C code? I do not want to use masks to access the register because I´d have to change a lot of C code that has already been tested and approved with others compilers. I was thinking about some compiler flag to avoid the using of non-aligned instructions by the compiler, but I don’t know if it exists.
  
  Tks in advance.
0 Kudos
2 Replies

561 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rodrigo.such on Tue Dec 06 11:12:36 MST 2011
Ok Rob!
So it confirm what I was thinking! Tks!
Do you know a way to handle this?
  Something like to force GCC to do not use unaligned instructions in some or in all memory access?


Tks!
0 Kudos

561 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Tue Dec 06 06:48:36 MST 2011

Quote: rodrigo.such

  According to LPC17XX User Manual[COLOR=#1F497D], [/COLOR][COLOR=Black][B][FONT=&quot]Unaligned accesses are usually slower than aligned accesses. [COLOR=Red]In addition, some memory[/COLOR][/FONT][/B][COLOR=Red]
[B][FONT=&quot]regions might not support unaligned accesses[/FONT][/B][/COLOR][/COLOR]   [COLOR=Black][B][FONT=&quot]. Therefore, ARM recommends that[/FONT][/B]
[B][FONT=&quot]programmers ensure that accesses are aligned.[/FONT][/B][/COLOR]  
 



And guess what ... the memory region where all the peripheral registers are placed does not support unaligned access.
The PLL0CFG register is located at address 0x400FC084, if I do an 8-bit access to any of the addresses (0x400Fc084/85/86 or 87) the byte is written to all bytes the same.
I.e: writing 0x12 to any of the byte pointers results in the content 0x00121212  in the register (the upper byte is always zero in this register).

The reason for this is in hardware: unaligned access is done by providing separate write-enable signals for each byte in a 32 bits word and when writing one byte to a byte address, the databus gets the value 0x12121212 (4 copies of the same data) plus the enable for the right byte-lane active.
This is supported by the on chip RAM but not by the register access.

Regards,

[INDENT]Rob
[/INDENT]
0 Kudos