Static variable doesn't initialize to given value - c

I have a static "init" variable to run a function once on startup, (RTOS) but it seems to initialize to a random value. If I remove the static tag, everything works great. (Except for the obvious issue of it running the init function every pass.) Could anyone give more insight as to why this isn't working or perhaps a better way to achieve this?
Example code:
void ManageStructures()
{
// Variable declarations/definitions
static uint8_t StructInitialized;
// Have also tried "static uint8_t StructInitialized = 0", neither worked
// Function prototypes
void InitStruct();
if (!StructInitialized)
{
StructInitialized= 1;
InitStruct();
}
Test = StructInitialized;
edit: I apologize for the lack of information. This is for a company and I am trying to stay within the bounds of our public information policy. The MCU is a STM32F7 series using the "Ac6 STM32 MCU GCC" toolchain. I am not well versed in compiler operations so it may take me longer to find answers to the compiler or makefile related questions.
edit: It has become clear that this is an issue with the compiler or linker scripts and not my code. That being said, it has also become abundantly clear that I need to learn more about toolchains, linker scripts, and compilers in general before getting to the root of this issue. I'll return to this question once I have become familiar enough to give valuable feedback or answer it myself. Thank you everyone for the feedback and direction!

It is common that embedded systems run with a "minimal startup" code, meaning that they never initialize .bss or .data during start-up. Meaning that if you write something like static int foo = 42;, the code will compile but the variable will never be set.
This isn't standard C compilant, so usually upon project creation you get an option from the IDE to have a "minimal" or "standard" startup.
This likely lies in the so-called "CRT" (C run-time) delivered with your tool chain and not in the RTOS. If you single step your program from where it actually starts (the reset vector) rather than from where main() starts, you'll be able to see exactly what the CRT does and doesn't.
Unfortunately debuggers often use a "dumbed-down mode", since embedded systems programmers are by default assumed to be completely incompetent nowadays. Meaning that they silently insert a breakpoint at main() and run until that point. You might have to "un-dumb" your debugger in order to debug the CRT.

Related

STM32 linkerscript initialization sections, are they needed when using C?

As far as I know, sections like .init, .preinit_array, .init_array, .finit, .fini_array... found in STM32CubeIDE linkerscripts are used in C++ for calling the static objects' constructors that need to be executed before main (and the fini versions for the destructors).
My assumption is that these sections are used by functions called implicitly by the compiler and the C/C++ runtime libraries, but if your firmware is written in C, are all these sections really needed? What does the compiler do behind the scenes?
You can live without many of them.
Other than C++, some of them may initialize things required by the standard library. If you only call pure functions from the standard library and you only have code in C or assembly then you could try taking them out.
If you are trying to do this as a learning exercise, then take them out and just see what doesn't work. Also search on google, there are loads of sites that explain this sort of thing in a way that is far too long to reproduce here.
If you are just trying to get your project finished, then leave them alone. They only add a tiny amount to your program size and it isn't worth your time to fight with them.
are used in C++ for calling the static objects' constructors that need
to be executed before main (and the fini versions for the
destructors).
It is not 100% truth. cubeIDE uses gcc based ARM toolchain which has some extensions which may use some of those sections. For example, you can use use attributes to make functions which will be executed before main and/or called after the main function return.
void __attribute__((constructor)) called_before_main(void)
{
/* some code */
}
void __attribute__((destructor)) called_after_main(void)
{
/* some code */
}
If you even not use any of those, external libraries may use them. Even if you do not use external libraries keeping those sections does not hurt as they will be discarded if they are empty.

STM32 HAL Library simple C coding error

I am using the STM32 HAL Library for a micro controller project. In the ADC section I found the following code:
uint32_t WaitLoopIndex = 0;
/...
.../
/* Delay for ADC stabilization time. */
/* Delay fixed to worst case: maximum CPU frequency */
while(WaitLoopIndex < ADC_STAB_DELAY_CPU_CYCLES)
{
WaitLoopIndex++;
}
It is my understanding that this code will most likely get optimized away since WaitLoopIndex isn't used anywhere else in the function and is not declared volatile, right?
Technically yes, though from my experiences with compilers for embedded targets, that loop will not get optimised out. If you think about it, having a pointless loop is not really a construct you are going to see in a program unless the programmer does it on purpose, so I doubt many compilers bothers to optimise for it.
The fact that you have to make assumptions about how it might be optimised though means it most certainly is a bug, and one of the worst types at that. More than likely ST wanted to only use C in their library, so did this instead of the inline assembler delay that they should have used. But since the problem they are trying to solve is heavily platform dependent, an annoying platform/compiler dependent solution is unavoidable, and all they have done here is try to hide that dependency.
Declaring the variable volatile will help, but you still really have no idea how long that loop is taking to execute without making assumptions about how the compiler is building it. This is still very bad practice, though if they added an assert reminding you to check the delay manually that might be passable.
This depends on the compiler and the optimization level. To confirm the result, just enter debug mode and check the disassembly code of the piece of code.

MpLab, ASM, C, Building To accommodate both

I have a large and substantial ASM project for a PIC24 chip. (The specific chip is the PIC24FJ256GB210)
I now have some other routines in C.
I want to incorporate these into my project.
The C routines are in a project of 5 or so files, one of which contains the int main(void) statement as the starting point. This was for the purpose of testing them and giving us the confidence that they work. We are now ready to move that code and incorporate it into the larger existing system.
The assembly language stuff starts with the __reset: instruction.
How do I arrange the project and build options so that I can do these next three things ?
Keep starting with my __reset instruction
(Or at least make sure that my existing __reset and the int main(void) at least cooperate with each other)
Call his routines from the ASM code
Use the same data buffers that the C code sets up
Interestingly enough, Microchip's User forums and sample code sections seem to miss this idea (or, more likely, I haven't figured out how to find them).
I would think this question has been asked a lot, and I hope I'm not duplicating a previous question, but I don't see it here nor on MicroChip's site. Links to helpful websites on this topic are welcome.
If I just need to learn how to search this and other sites better, that will be a useful and workable answer in and of itself. Again, hope I'm not asking a duplicate question.
I recommend you to read DS51284H ("MPLAB® C COMPILER FOR PIC24 MCUs AND dsPIC® DSCs USER’S GUIDE") (PDF).
In particular see section 4.4 STARTUP AND INITIALIZATION
"Two C run-time startup modules are included in the libpic30.a archive/library. The
entry point for both startup modules is __reset. The linker scripts construct a GOTO
__reset instruction at location 0 in program memory, which transfers control upon
device reset.
....
5. The function main is called with no parameters."
Your __reset label and the one in the CRT (C run-time) would appear to conflict. If you have the source for the CRT you could change that by renaming the __reset label in the CRT to something else so that your own __reset always is called first.
Another point is that it sounds like you want to take a stand-alone program and use it as a library from within your own program. Since stand-alone programs often are designed to perform one or more specific tasks and exit once that task is finished you might want to refactor your C code a bit to make it more library-ish (like getting rid of the main() function and perhaps replace it with some sort of init() function).
And section 4.11 FUNCTION CALL CONVENTIONS.
"The first eight working registers (W0-W7) are used for function parameters. Parameters
are allocated to registers in left-to-right order, and a parameter is assigned to the first
available register that is suitably aligned.
....
Function return values are returned in W0 for 8- or 16-bit scalars, W1:W0 for 32-bit
scalars, and W3:W2:W1:W0 for 64-bit scalars."
Michael gave you a good answer. The only thing I would like to add is that you should make the project in C and cut the assembly functions within it.
This way you keep the speedy and functional asm code and can mantain the project in C, which is much easier.
It is not in your interest to convert the C code into assembly and have a large assembly code to mantain, its the other way around.
Once you read the docs you will see it is not so hard to use an assembly function in C, but to get you started, you can take a look at this:
C:\ ...bla bla... \Microchip\MPLAB C30\src\dsp\include\dsp.h
contains function declaration in C for the actual assembly functions located in this folder:
C:\ ...bla bla... \Microchip\MPLAB C30\src\dsp\asm
You can begin with the function _VectorAdd: Vector Addition, file "vadd.s"
Note that the assembly function _VectorAdd is defined as VectorAdd in the header file.
This example files are for the dsp engine in the DSPIC, something the PIC24 does not feature. But it is still ilustrative enough to extract the principle.

hidden routines linked in c program

Hullo,
When one disasembly some win32 exe prog compiled by c compiler it
shows that some compilers links some 'hidden' routines in it -
i think even if c program is an empty one and has a 5 bytes or so.
I understand that such 5 bytes is enveloped in PE .exe format but
why to put some routines - it seem not necessary for me and even
somewhat annoys me. What is that? Can it be omitted? As i understand
c program (not speaking about c++ right now which i know has some
initial routines) should not need such complementary hidden functions..
Much tnx for answer, maybe even some extended info link, cause this
topic interests me much
//edit
ok here it is some disasembly Ive done way back then
(digital mars and old borland commandline (i have tested also)
both make much more code, (and Im specialli interested in bcc32)
but they do not include readable names/symbols in such dissassembly
so i will not post them here
thesse are somewhat readable - but i am not experienced in understending
what it is ;-)
https://dl.dropbox.com/u/42887985/prog_devcpp.htm
https://dl.dropbox.com/u/42887985/prog_lcc.htm
https://dl.dropbox.com/u/42887985/prog_mingw.htm
https://dl.dropbox.com/u/42887985/prog_pelles.htm
some explanatory comments whats that heere?
(I am afraid maybe there is some c++ sh*t here, I am
interested in pure c addons not c++ though,
but too tired now to assure that it was compiled in c
mode, extension of compiled empty-main prog was c
so I was thinking it will be output in c not c++)
tnx for longer explanations what it is
Since your win32 exe file is a dynamically linked object file, it will contain the necessary data needed by the dynamic linker to do its job, such as names of libraries to link to, and symbols that need resolving.
Even a program with an empty main() will link with the c-runtime and kernel32.dll libraries (and probably others? - a while since I last did Win32 dev).
You should also be aware that main() is only the entry point of your program - quite a bit has already gone on before this point such as retrieving and tokening the command-line, setting up the locale, creating stderr, stdin, and stdout and setting up the other mechanism required by the c-runtime library such a at_exit(). Similarly, when your main() returns, the runtime does some clean-up - and at the very least needs to call the kernel to tell it that you're done.
As to whether it's necessary? Yes, unless you fancy writing your own program prologue and epilogue each time. There are probably are ways of writing minimal, statically linked applications if you're sufficiently masochistic.
As for storage overhead, why are you getting so worked up? It's not enough to worry about.
There are several initialization functions that load whenever you run a program on Windows. These functions, among other things, call the main() function that you write - which is why you need either a main() or WinMain() function for your program to run. I'm not aware of other included functions though. Do you have some disassembly to show?
You don't have much detail to go on but I think most of what you're seeing is probably the routines of the specific C runtime library that your compiler works with.
For instance there will be code enabling it to run from the entry point 'main' which portable executable format understands to call the main(char ** args) that you wrote in your C program.

Find unused functions in a C project by static analysis

I am trying to run static analysis on a C project to identify dead code i.e functions or code lines that are never ever called. I can build this project with Visual Studio .Net for Windows or using gcc for Linux. I have been trying to find some reasonable tool that can do this for me but so far I have not succeeded. I have read related questions on Stack Overflow i.e this and this and I have tried to use -Wunreachable-code with gcc but the output in gcc is not very helpful. It is of the following format
/home/adnan/my_socket.c: In function ‘my_sockNtoH32’:
/home/adnan/my_socket.c:666: warning: will never be executed
but when I look at line 666 in my_socket.c, it's actually inside another function that is being called from function my_sockNtoH32() and will not be executed for this specific instance but will be executed when called from some other functions.
What I need is to find the code which will never be executed. Can someone plz help with this?
PS: I can't convince management to buy a tool for this task, so please stick to free/open source tools.
If GCC isn't cutting it for you, try clang (or more accurately, its static analyzer). It (generally, your mileage may vary of course) has a much better static analysis than GCC (and produces much better output). It's used in Apple's Xcode but it's open-source and can be used seperately.
When GCC says "will never be executed", it means it. You may have a bug that, in fact, does make that dead code. For example, something like:
if (a = 42) {
// some code
} else {
// warning: unreachable code
}
Without seeing the code it's not possible to be specific, of course.
Note that if there is a macro at line 666, it's possible GCC refers to a part of that macro as well.
GCC will help you find dead code within a compilation. I'd be surprised if it can find dead code across multiple compilation units. A file-level declaration of a function or variable in a compilation unit means that some other compilation unit might reference it. So anything declared at the top level of a file, GCC can't eliminate, as it arguably only sees one compilation unit at a time.
The problem gets get harder. Imagine that compilation unit A declares function a, and compilation unit B has a function b that calls a. Is a dead? On the face of it, no. But in fact, it depends; if b is dead, and the only reference to a is in b, then a is dead, too. We get the same problem if b merely takes &a and puts it into an array X. Now to decide if a is dead, we need a points-to analysis across the entire system, to see if that pointer to a is used anywhere.
To get this kind of accurate "dead" information, you need a global view of the entire set of compilation units, and need to compute a points-to analysis, followed by the construction of a call-graph based on that points-to analysis. Function a is dead only if the call graph (as a tree,
with main as the root) doesn't reference it somewhere.
(Some caveats are necessary: whatever the analysis is, as a practical matter it must be conservative, so even a full-points to analysis may not identify a function correctly as dead. You also have to worry about uses of a C artifact from outside the set of C functions, e.g., a call to a from some bit of assembler code).
Threading makes this worse; each thread has some root function which is probably at the top of the call DAG. Since how a thread gets started isn't defined by C compilers, it should be clear that to determine if a multithreaded C application has dead code, somehow the analysis has to be told the thread root functions, or be told how to discover them by looking for thread-initialization primitives.
You aren't getting a lot responses on how to get a correct answer. While it isn't open source, our DMS Software Reengineering Toolkit with its C Front End has all the machinery to do this, including C parsers, control- and dataflow- analysis, local and global points-to analysis, and global call graph construction. DMS is easily customized to include extra information such as external calls from assembler, and/or a list of thread roots or specific source-patterns that are thread initialization calls, and we've actually done that (easily) for some large embedded engine controllers with millions of lines of code. DMS has been applied to systems as large as 26 million lines of code (some 18,000 compilation units) for the purpose of building such calls graphs.
[An interesting aside: in processing individual comilation units, DMS for scaling reasons in effect deletes symbols and related code that aren't used in that compilation unit. Remarkably, this gets rid of about 95% of code by volume when you take into account the iceberg usually hiding in the include file nest. It says C software typically has poorly factored include files. I suspect you all know that already.]
Tools like GCC will remove dead code while compiling. That's helpful, but the dead code is still lying around in your compilation unit source code using up developer's attention (they have to figure out if it is dead, too!). DMS in its program transformation mode can be configured, modulo some preprocessor issues, to actually remove that dead code from the source. On very large software systems, you don't really want to do this by hand.

Resources