2017-01-02 12:12 AM
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_ltorso i wonder how it works, because ldw instruction is described as 16 bit transferring...
what is c_ltor?
Thank you in advance.
Krzysiek
#stm8 #atomic2017-01-02 02:25 AM
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
2017-01-02 03:59 AM
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
2017-01-03 12:32 AM
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
2017-01-03 01:38 AM
Thank you Luca,
I didn't know about c_lreg pseudo register. Now need to review my coding
Krzysiek
2017-01-03 01:52 AM
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...
2017-01-16 08:39 AM
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.