Skip to main content
jgnoss
Associate III
April 1, 2013
Question

problem map a struct to Backup registers

  • April 1, 2013
  • 7 replies
  • 2427 views
Posted on April 01, 2013 at 11:06

I got a problem map a struct to Backup registers

what I do is:

/******************************************************************************************/

typedef struct {

    uint16_t actPageNo;

    uint16_t sollQTY;

    uint16_t lcd_BackLight;

    uint16_t lcd_Contrast;

    uint16_t rpm_Ticks;

    uint8_t actProfile;

    uint8_t dummy;

} processData_t;

#define ProcessData        ((processData_t *)(RTC_BASE + 0x50))

void init_ProcessData(void){

    init_RTC();

}

void processData_SetDefaultValues(void){

    ProcessData->actPageNo = 1;

    ProcessData->sollQTY = 200;

    ProcessData->lcd_BackLight = 5000;

    ProcessData->lcd_Contrast = 750;

    ProcessData->rpm_Ticks = 512;

    ProcessData->actProfile = 16;

    ProcessData->dummy = 0;

};

    processData_SetDefaultValues();

uint32_t r = 0;

uint8_t t = 0;

    for (t = 0; t < 5; t++) {

        r = RTC_ReadBackupRegister(t);

        tfp_sprintf(ss,''\r\nbefore  %d = %u %X\r\n'', t,r, r);

        uart1_puts(ss);

    }

    tfp_sprintf(ss,''\r\nbefore   aPro %d aPa %u sPa %u B %u C %u \r\n'',

    ProcessData->actProfile,

    ProcessData->actPageNo,

    ProcessData->sollQTY,

    ProcessData->lcd_BackLight,

    ProcessData->lcd_Contrast

    );

    uart1_puts(ss);

    r = (5000 << 16) | 750;

    RTC_WriteBackupRegister(RTC_BKP_DR1, r);

    for (t = 0; t < 5; t++) {

        r = RTC_ReadBackupRegister(t);

        tfp_sprintf(ss,''\r\nafter  %d = %u %X\r\n'', t,r, r);

        uart1_puts(ss);

    }

    tfp_sprintf(ss,''\r\nafter  aPro %d aPa %u sPa %u B %u C %u \r\n'',

          ProcessData->actProfile,

          ProcessData->actPageNo,

          ProcessData->sollQTY,

          ProcessData->lcd_BackLight,

          ProcessData->lcd_Contrast );

    uart1_puts(ss);        

 

/******************************************************************************************/

but result while setting values using the struct is not as expected:

before  0 = 13107400 C800C8

before  1 = 49152750 2EE02EE

before  2 = 0 0

before  3 = 0 0

before  4 = 0 0

before   aPro 0 aPa 200 sPa 200 B 750 C 750

while building my own 32Bit value and writing it to the register

using StdPerphLib function and read the data back using struct works just fine

after  0 = 13107400 C800C8

after  1 = 327680750 138802EE

after  2 = 0 0

after  3 = 0 0

after  4 = 0 0

after  aPro 0 aPa 200 sPa 200 B 750 C 5000

I use codesourcery toolchain

Any idea what's happening there?

    This topic has been closed for replies.

    7 replies

    Tesla DeLorean
    Guru
    April 1, 2013
    Posted on April 01, 2013 at 13:42

    What packing is being used here? Does the sizeof() match your expectation? Look at how it works on a RAM address, in the debugger. Look at the assembler code generated.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    jgnoss
    jgnossAuthor
    Associate III
    April 1, 2013
    Posted on April 01, 2013 at 15:40

    Thank's clive1,

    Packing is off, and sizeof() returns the correct size.

    On another place in the same program I use another structure to write page aligned in an eeprom. 

    I didn't go in and learn about the ARM assembler instructions yet, assembler I'm not the hero, but as far as I can go with it, it seams to be correct.

    08001230 <processData_SetDefaultValues>:

     8001230:    4b08          ldr    r3, [pc, #32]    ; (8001254 <processData_SetDefaultValues+0x24>)

     8001232:    2201          movs    r2, #1

     8001234:    801a          strh    r2, [r3, #0]

     8001236:    20c8          movs    r0, #200    ; 0xc8

     8001238:    4907          ldr    r1, [pc, #28]    ; (8001258 <processData_SetDefaultValues+0x28>)

     800123a:    4a08          ldr    r2, [pc, #32]    ; (800125c <processData_SetDefaultValues+0x2c>)

     800123c:    8058          strh    r0, [r3, #2]

     800123e:    2080          movs    r0, #128    ; 0x80

     8001240:    8099          strh    r1, [r3, #4]

     8001242:    80da          strh    r2, [r3, #6]

     8001244:    0081          lsls    r1, r0, #2

     8001246:    2210          movs    r2, #16

     8001248:    2000          movs    r0, #0

     800124a:    8119          strh    r1, [r3, #8]

     800124c:    729a          strb    r2, [r3, #10]

     800124e:    72d8          strb    r0, [r3, #11]

     8001250:    4770          bx    lr

     8001252:    46c0          nop            ; (mov r8, r8)

     8001254:    40002850     .word    0x40002850

     8001258:    00001388     .word    0x00001388

     800125c:    000002ee     .word    0x000002ee

    Tesla DeLorean
    Guru
    April 1, 2013
    Posted on April 01, 2013 at 16:15

    While not explicitly stated, I'd be concerned that the memory doesn't perform write granularity below 32-bits. ie It's a register, not a memory with selective byte write lanes/selects.

    Try this approach:

    void processData_SetDefaultValues(void)
    {
    processData_t pd;
    uint32_t *src, *dst;
    int i = (sizeof(pd) + 3) / 4; // Size rounded to 32-bit words
    // Perform localized initialization, and do a 32-bit wide copy
    pd.actPageNo = 1;
    pd.sollQTY = 200;
    pd.lcd_BackLight = 5000;
    pd.lcd_Contrast = 750;
    pd.rpm_Ticks = 512;
    pd.actProfile = 16;
    pd.dummy = 0;
    src = (uint32_t *)&pd;
    dst = (uint32_t *)(RTC_BASE + 0x50); // RTC_BKPxR
    while(i--)
    *dst++ = *src++;
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    dthedens23
    Associate
    April 1, 2013
    Posted on April 01, 2013 at 16:31

    perhaps Printf is confused about what it is being asked to print because of the #define.

    and because of things like actProfile being a char and being told to print like a 32bit %d

    I use ''placement new'' in C++ but I think this should work in C

    processData_t * ProcessData    =    ((processData_t *)(RTC_BASE + 0x50));

    forgive my stupidity, it's Monday.  But it may still be a type related issue caused by the define.
    jgnoss
    jgnossAuthor
    Associate III
    April 1, 2013
    Posted on April 01, 2013 at 17:05

    @rocketdawg

    printf is not the problem, see second part of  my example from first post.

    The problem doesn't appear on reading the regs using a struct,

    just on writing it goes wrong.

    @clive1

    Sorry I didn't say what controller it is. It's a STM32F051.

    Yes writing the 32Bit regs entirely works perfect.

    I tried to make the access to this regs more elegant, because I like to hold process critical data in it, which I like to have present also  after a power fail.  And that registers are heavily accessed. 

    So I have to do it by hand again.

    Thank's   clive1

    Ju

    jgnoss
    jgnossAuthor
    Associate III
    April 1, 2013
    Posted on April 01, 2013 at 17:10

    @rocketdawg

    just read the edit in your post.

    We accept the Monday-excuse   ;)

    Ju

    Tesla DeLorean
    Guru
    April 1, 2013
    Posted on April 01, 2013 at 17:55

    A reasonable abstraction might be to hold the current/working data in a copy of the registers, and then a routine to flush to the NV memory of choice when you change the copy. A RAM based copy should also be faster.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..