Writing to eeprom with a hard-coded value.

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

Writing to eeprom with a hard-coded value.

Jump to solution
890 Views
gvisser
Contributor II

Hello,

I am working on a project which uses the eeporm of the LPC1837JET100.

At some point our code has stopped working.
I have check our version control and could not find a change.
So I started experimenting and found a problem when writing to the eeprom with a hard-coded value.

#include "board.h"

typedef struct
{
    volatile unsigned value_a;
    volatile unsigned value_b;
    volatile unsigned value_c;
    volatile unsigned value_d;
    volatile unsigned value_e;
} __attribute__((aligned(1),packed)) TMemory_structure;

int main(void)
{
    //init eeprom
    Chip_Clock_Enable(CLK_MX_EEPROM);
    Chip_EEPROM_Init(LPC_EEPROM);
    Chip_EEPROM_SetAutoProg(LPC_EEPROM, EEPROM_AUTOPROG_AFT_1WORDWRITTEN);

    //get pointer to eeprom
    volatile TMemory_structure* data = (TMemory_structure*)EEPROM_ADDRESS(0,0);

    //prepare values
    static const unsigned value_in_program = 0x12345678;
    unsigned value_in_ram = 0x87654321;

    //write value in ram to eeprom
    data->value_d = value_in_ram;

    //wait for operation to compete
    while( (LPC_EEPROM->INTSTAT & EEPROM_INT_ENDOFPROG) == 0);
    LPC_EEPROM->INTSTATCLR = EEPROM_INT_ENDOFPROG;

    //write value in program to eeprom
    data->value_d = value_in_program;


    volatile static int i = 0 ;
    while(1) {
        i++ ;
    }
    return 0 ;
}

In this example line 34 will not write data to the eeprom.
For this to fail you have to have the following situation.

  • If you have the current compiler. (I am convinced the code has worked a year ago.)
  • Do not have the compiler set to optimize. (For debugging)

If you have this situation the compiler will generate 4 strb instructions to write to the eeprom.
Instead of a single str instruction.

24            unsigned value_in_ram = 0x87654321;
1a00042a:   ldr     r3, [pc, #104]  ; (0x1a000494 <main()+136>)
1a00042c:   str     r3, [r7, #0]
27            data->value_d = value_in_ram;
1a00042e:   ldr     r3, [r7, #4]
1a000430:   ldr     r2, [r7, #0]
1a000432:   str     r2, [r3, #12]

// skip some lines //

34            data->value_d = value_in_program;
1a000456:   ldr     r3, [r7, #4]
1a000458:   ldrb    r2, [r3, #12]
1a00045a:   movs    r2, #0
1a00045c:   orr.w   r2, r2, #120    ; 0x78
1a000460:   strb    r2, [r3, #12]
1a000462:   ldrb    r2, [r3, #13]
1a000464:   movs    r2, #0
1a000466:   orr.w   r2, r2, #86     ; 0x56
1a00046a:   strb    r2, [r3, #13]
1a00046c:   ldrb    r2, [r3, #14]
1a00046e:   movs    r2, #0
1a000470:   orr.w   r2, r2, #52     ; 0x34
1a000474:   strb    r2, [r3, #14]
1a000476:   ldrb    r2, [r3, #15]
1a000478:   movs    r2, #0
1a00047a:   orr.w   r2, r2, #18
1a00047e:   strb    r2, [r3, #15]

While the assembly will write the value to the address of the eeprom. The eeprom will not save the data.

In the user manual of the LPC18xx I found the reason this would not work. 

The first step is writing a minimum of 1 word (4 bytes) to a maximum of 32 words (128 bytes)
to the desired page in the 16 kB EEPROM address space at address 0x2004 0000.

I assume writing a byte at a time does not count.

My question is why does the compiler use the strb instruction 4 times instead of 1 str instruction.
There are 5 asm instructions to copy a value from program to ram to eeprom.
And 17 instructions to copy a value from program to eeprom.
Skipping ram uses 12 instructions more.
It could have loaded the value from program in r2 and then stored it in eeprom, using 2 instructions. (3 instructions if we include loading r3 with a pointer to the eeprom.)

While I do not mind using a few instructions more while optimization is turned off for debugging.
In this case the eeprom peripheral will not save the data because it needs a write of 4 bytes instead of 4 writes of a byte.

I found a few way to get the code to work.

  • Coping a value to ram and then writing to eeprom.
    This would add an extra step which could easily be forgotten why it is required.
  • Or enabling optimization.
    This would make debugging a large project very difficult.

However I would like to know if there is a way to make sure the str instruction is used.
Because the ways I have found feel like they should not be needed.

Labels (1)
0 Kudos
1 Solution
883 Views
converse
Senior Contributor V

You asked:

My question is why does the compiler use the strb instruction 4 times instead of 1 str instruction.

Answer:

To write a 4 byte value in a single write, it MUST be 4-byte aligned, and the compiler must KNOW that it is guaranteed to be 4-byte aligned. You can do this by declaring a value as 

int x __attribute__ ((aligned (4))) = 0;

View solution in original post

0 Kudos
1 Reply
884 Views
converse
Senior Contributor V

You asked:

My question is why does the compiler use the strb instruction 4 times instead of 1 str instruction.

Answer:

To write a 4 byte value in a single write, it MUST be 4-byte aligned, and the compiler must KNOW that it is guaranteed to be 4-byte aligned. You can do this by declaring a value as 

int x __attribute__ ((aligned (4))) = 0;
0 Kudos