1

I'm developing an embedded application on stm8s microcontroller using STVD IDE and COSMIC compiler.

I'm trying to define a static bool variable to use it to execute a snippet of code only once. Unexpectedly, the variable once is not initialized to FALSE or 0. Although I explicitly initialized it. Here is the snippet of my code:

uint32_t crc32_buffer(void)
{
    static bool once = FALSE;
    uint32_t crc = 0;

    if(!once)
    {
        calcTable();
        crc = 10;
        once = TRUE;
    }

    return crc;
}

When I tried to check the physical memory location, I found that every time after entering a new debugging session (even after hardware restarting the controller) and before running the application itself, the memory address 0x80 has the same value 0x14.

If I modified the code to assign FALSE to once after the variable's initialization:

once = FALSE;

The memory location is changed to contain 0x00. Then if I exit this debugging session and then re-modified the code to delete this line of code and start a new debugging session, I find the memory location 0x80 has again 0x14 before running the application.

I don't understand what can prevent the compiler to initialize the variable to 0. I don't understand what can write 0x14 to the memory location even before running the application.

I tried setting a breakpoint if the memory location 0x80 was accessed (read/write) but the application didn't stop until it reached the if statement in the code snippet.

UPDATE-2

As many pointed out the startup procedure, I don’t use the default startup code. However, I'm using a custom one. When I used the standard startup code instead of the custom one I was using, the memory locations were set to 0 before main() function start execution. This is not the case with the custom startup code. So, when I define a new static variable and explicitly initialize it to FALSE, this initialization will only take place in the startup code before main(), right?

Salahuddin
  • 1,617
  • 3
  • 23
  • 37
  • 2
    Put the breakpoint at the first line of `main` and check then. It should be initialized by the startup code before main is entered. https://stackoverflow.com/questions/17783210/when-are-static-and-global-variables-initialized – stark Jul 16 '19 at 15:34
  • 1
    Most of the compilers add __main() at the beginning or before actual main() to initialize statics, so you have to let appliaction to start – Paweł Dymowski Jul 16 '19 at 16:05
  • Please check that in your map file contains entries for the .bss and/or .data sections. – MiCo Jul 16 '19 at 17:06
  • 1
    If you're using some custom or non-standard startup code then most likely you're missing a loop which zeroes out the .bss segment. – brhans Jul 16 '19 at 23:50
  • @brhans It looks like you are right. Please check `UPDATE-2` – Salahuddin Jul 17 '19 at 08:33
  • It is very common for embedded compilers to provide a "minimal" or "fast" startup code, which essentially does nothing but setting the stack pointer. From what I remember, Cosmic does this too (it's been ages since I used it). You would have to create a project as "standard", "ANSI" or whatever the compiler calls it. Only then will it initialize `.bss` and `.data`. You can see this for yourself if you single step the startup code from the reset vector and onward. It's common practice in embedded to avoid writing code that relies on static storage initialization because of this. – Lundin Jul 21 '19 at 22:58
  • You might find this helpful: [What resides in the different memory types of a microcontroller?](https://electronics.stackexchange.com/questions/237740/what-resides-in-the-different-memory-types-of-a-microcontroller/237759#237759) – Lundin Jul 21 '19 at 22:59

2 Answers2

3

If you read this storage duration reference you will see that for static storage duration

the value stored in the object is initialized only once, prior to main function

So you have to let the startup code running before main run first. Once the main function is called the value should have been initialized.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    @Clifford The OP says "**before** running the application itself" (emphasis mine), with together of some other wording make me think that the OP is using a hardware debugger or similar, and doesn't enter the C startup code which does the initialization. – Some programmer dude Jul 16 '19 at 18:52
  • 1
    Indeed - now I read more carefully. The important clue comes _way down_ the question. It does say that but it does not say that `crc32_buffer()` is being invoked them, merely that the value observed in is memory while at the reset vector - i.e.. the CRT is not performing initialisation. However later he says that it does break on a data access break-point, indicating _initialisation on first use_ so you are right, except this is not a CRT initialisation, but a local static initialise on first use. – Clifford Jul 17 '19 at 07:20
0

I find the memory location 0x80 has again 0x14 before running the application.

Initialisation requires code; the state of the memory after reset, before any code has executed is non-deterministic.

I tried setting a breakpoint if the memory location 0x80 was accessed (read/write) but the application didn't stop until it reached the if statement in the code snippet.

That sounds like the initialisation right there. What value did the variable acquire at that point? Local statics can be initialised on first use, rather than in the run-time start-up. It looks to me that in fact you do not have a problem at all other than understanding the semantics of static.

If for example you place a break-point on the static declaration itself, and run it, I expect you will observe that the break point is hit once on first use initialisation, and thereafter will not break on subsequent calls to the function.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • I think that when I define a new `static` variable and initialize it to `FALSE`, when I first check its value in the `if` statement, it should have the initial value of `FALSE`, right? This is not the case for me. When I check its value, I find `once` has the value of `0x14` instead of `0` – Salahuddin Jul 17 '19 at 08:17
  • @Salahuddin OK, but that is not clear in your question. Also if you have hit a data access breakpoint, something accessed it. You need to set it to a write access rather than read/write to be more selective re initialisation. Also inspect the code disassembly and register values. Some debuggers do not handle static variables well and may give misleading indications. – Clifford Jul 17 '19 at 08:35