We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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!