I have a struct containing several word8, word16 and word32. Writing a full 32-bits value causes mis-writing to the previous 32-bits value. 2 bytes go to the correct place, and 2 bytes to the previous. Having 8 or 16 bits entities in the same struct works fine and they align correctly. I don't use __packed. Some times I don't see the overwritten data, when I assume it's written to padded cells. We have 16 bits external ram for this. Little endian. Keil tool, ARM compiler.
Øyvind Teig home.no.net/.../work.html
The strange things is that a static 32 bits variable also residing in external ram, not inside the struct, indeed writes and reads flawlessly! The bytes/word8 and word16 in the struct are fine, but not the word32 values inside the struct. I have two boards, they both behave the same.
Can you show us the code? Be default, the compiler/linker should place structs and 32-bit words within structs on 32-bit boundaries. If you try to access a struct using a pointer that is not aligned to a 32-bit boundary, things like what you described can happen.
- mike
It's pointers as well as other word32 entities:
typedef struct { ... ... word8_a Byte_1; word8_a Byte_2; word16_a Word_1; word8_a Byte_3; size_t Fence_1; size_t Fence_2; size_t* Address_1; size_t* Address_2; word16_a Word_2; word8_a Byte_4; word8_a Byte_5; ApplCtx_a* ApplCtxPtr; // Application context // } Context_a; { ContextPtr->Byte_1 = 1; ContextPtr->Byte_2 = 2; ContextPtr->Byte_3 = 3; ContextPtr->Byte_4 = 4; ContextPtr->Word_1 = 0xAA22; ContextPtr->Word_2 = 0xBB33; ContextPtr->Fence_1 = 0x12345678; ContextPtr->Fence_2 = 0x55AA6677; ContextPtr->Address_1 = &(ContextPtr->Fence_1); ContextPtr->Address_2 = &(ContextPtr->Fence_2); ExternalApplCtxPtr = (ApplCtx_a*) MEM_ALLOC_F(sizeof(ApplCtx_a)); ContextPtr->ApplCtxPtr = ExternalApplCtxPtr; }
Here is the aseembly code:
0x0004DD30 E5C4B0F0 STRB R11,[R4,#0x00F0] 735: ContextPtr->Byte_1 = 1; 0x0004DD34 E5C4030C STRB R0,[R4,#0x030C] 736: ContextPtr->Byte_2 = 2; 0x0004DD38 E3A00002 MOV R0,#0x00000002 0x0004DD3C E5C4030D STRB R0,[R4,#0x030D] 737: ContextPtr->Byte_3 = 3; 0x0004DD40 E3A00003 MOV R0,#0x00000003 0x0004DD44 E5C40310 STRB R0,[R4,#0x0310] 738: ContextPtr->Byte_4 = 4; 0x0004DD48 E3A00004 MOV R0,#0x00000004 739: ContextPtr->Word_1 = 0xAA22; 0x0004DD4C E59F1AA4 LDR R1,[PC,#0x0AA4] 0x0004DD50 E5C40326 STRB R0,[R4,#0x0326] 0x0004DD54 E2840C03 ADD R0,R4,#0x00000300 0x0004DD58 E1C010BE STRH R1,[R0,#0x0E] 740: ContextPtr->Word_2 = 0xBB33; 0x0004DD5C E59F1A98 LDR R1,[PC,#0x0A98] 0x0004DD60 E1C012B4 STRH R1,[R0,#0x24] 741: ContextPtr->Fence_1 = 0x12345678; 0x0004DD64 E59F0A94 LDR R0,[PC,#0x0A94] 0x0004DD68 E5840314 STR R0,[R4,#0x0314] 742: ContextPtr->Fence_2 = 0x55AA6677; 0x0004DD6C E59F0A90 LDR R0,[PC,#0x0A90] 0x0004DD70 E5840318 STR R0,[R4,#0x0318] 743: ContextPtr->Address_1 = &(ContextPtr->Fence_1); 0x0004DD74 E2840FC5 ADD R0,R4,#0x00000314 0x0004DD78 E584031C STR R0,[R4,#0x031C] 744: ContextPtr->Address_2 = &(ContextPtr->Fence_2); 0x0004DD7C E2840FC6 ADD R0,R4,#0x00000318 0x0004DD80 E5840320 STR R0,[R4,#0x0320] 745: ExternalApplCtxPtr = (ApplCtx_a*) MEM_ALLOC_F(sizeof(ApplCtx_a)); 0x0004DD84 E3A00084 MOV R0,#0x00000084 0x0004DD88 EB001661 BL MemAlloc(0x00053714) 0x0004DD8C E51F11C0 LDR R1,[PC,#-0x01C0] 746: ContextPtr->ApplCtxPtr = ExternalApplCtxPtr;
What about ContextPtr? Is it aligned to a 4-byte boundary?
ContextPtr 0x3c012d46 is 1006710086 and divided by 4 is 251677521,5 --- NO! ---
So, I'd have to look at our malloc! Ported from AVR ATMega256 application! I have the code available!
Thank you! I'll keep the list posted with the result!
Case closed!
Our local "malloc" reimplemented to align on 4-byte boundary!
Thank you very much!