cancel
Showing results for 
Search instead for 
Did you mean: 

STM8S - 32bit atomic access

Posted on January 02, 2017 at 09:12

Hi,

I'm stm8 newbie, and i wonder if i can do assumption, that reading uint32 variable will be atomic.

There is simple function returning system time measured in ms using uint32_t variable, and it's looks like following

 207                     ; 109 uint32_t systemGetBootTime(void)

 207                     ; 110 {

 208                     .text:    section    .text,new

 209  0000               _systemGetBootTime:

 211                     ; 111     return systemBootTime;

 212  0000 ae0000            ldw    x,♯_systemBootTime

 215  0003 cc0000            jp    c_ltor

so i wonder how it works, because ldw instruction is described as 16 bit transferring...

what is c_ltor?

Thank you in advance.

Krzysiek

#stm8 #atomic
6 REPLIES 6
Philipp Krause
Senior II
Posted on January 02, 2017 at 11:25

To me, the asm code looks like _systemBootTime is a 16-bit variable and c_ltor might be some compiler-specific internal function for casts from 16 bit to 32 bit.

However it is hard to tell without knowing more. Compileable source for the function, including all declarations might help. Which compiler did you use?

But in general, there is no instruction for an atomic 32-bit read in the STM8. You'd have to disable interrupts during the read to do a reliable 32-bit atomic read.

Philipp

Posted on January 02, 2017 at 11:59

Than you Philipp for quick answer .

I use cosmic free compiler, and variable is declared as

__IO uint32_t systemBootTime = 0;

I just did additional 8 bit flag to disable bootTime increase during reading instead of switching interrupts off

__IO uint8_t sytemDontIncBootTime = 0;

uint32_t systemGetBootTime(void)

{

    volatile uint32_t tmpBootTime;

    sytemDontIncBootTime = 1;

    tmpBootTime = systemBootTime;

    sytemDontIncBootTime = 0;

    return tmpBootTime;

}

and timer code ...

void systemTIM4IRQ(void)

{

    // called at 1000Hz

    if (sytemDontIncBootTime == 0)

    {

        systemBootTime++;

    }

...

I know that some ms will be not counted, but it's acceptable

Have a nice day.

Krzysiek

luca239955_stm1_st
Senior II
Posted on January 03, 2017 at 09:32

Hello,

generally speaking access to 32 bits variables is not atomic in the stm8 because the core does not have the kind of instructions that would allow to implement this easily: if you want to make sure access to some variables is atomic you should implement that yourself, usually disabling interrupts.

In your specific case, c_lreg is a Cosmic-specifc 32-bits pseudo register (4 bytes in page 0 that the compilers reserves to manage 32 bits calculations): in the assembler you posted the address of the variable systemBootTime is put into X, and than the library function c_ltor is called to copy the content of this variable in the 32bit c_lreg pseudo register, that is used as return value. Note that if you want to make sure that c_lreg is saved under interrupt (something that you should always do if your interrut routines use long or floats) you must specify the keyword @svlreg on the interrupt function.

Regards,

Luca

Posted on January 03, 2017 at 09:38

Thank you Luca,

I didn't know about c_lreg pseudo register. Now need to review my coding

Krzysiek

Posted on January 03, 2017 at 09:52

Btw, is it any simply way to disable all the Cosmic-specifc optimilizations like zero page registers. My project does not required speed but it should be stable, and i'm not sure if i will find out all the tricks compiler can do...

Posted on January 16, 2017 at 16:39

you don't need to review your code or to disable anything: I gave some details on the question you asked because you seemed curious about that, but the best way to use the compiler is just to concentrate on your application and let the tools do their job.