cancel
Showing results for 
Search instead for 
Did you mean: 

problem map a struct to Backup registers

jgnoss
Associate III
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?

7 REPLIES 7
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
Up vote any posts that you find helpful, it shows what's working..
jgnoss
Associate III
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

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
Up vote any posts that you find helpful, it shows what's working..
dthedens23
Associate II
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
Associate III
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
Associate III
Posted on April 01, 2013 at 17:10

@rocketdawg

just read the edit in your post.

We accept the Monday-excuse   😉

Ju

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
Up vote any posts that you find helpful, it shows what's working..