How to use 'flag' variables other than using as global? - c

I'm using several no of flags for setting the flags in a mini embedded project.I would like to know what is the best method to use these variables which indicate certain states in the project.I'm using c18 compiler and pic18f controller.
flag1..flag 2..flag3..denote state1, state2,state3..and corresponding
actions were performed.
Making global is an option.
But what is most preferred method through which i can handle the 'flags' well in the embedded system?

First of all, whenever you have lots of "flags", tread carefully. In embedded systems, it is easy to get "flag spaghetti", which consists of a lot of complex dependencies. So examine what flags you have: are they related, can they co-exist etc. If so, it is usually better to merge them into an enum. If the flags specify states, then for better program stability, consider writing your whole program as a state machine. And set the flags in a consistent manner, at specific places in the program. Rather than doing so all over the place.
As for how to store them: there is never a reason in a C program to use a global variable, where the definition of a global variable is a variable declared at file scope, which is visible to the whole program.
If you are using a single-threaded/single-process program, then declaring a variable at file scope is fine. But you must declare it as static, so that it is a private file scope variable rather than a global one.
volatile has nothing to do with scope or program design. To prevent incorrect compiler optimizations, you should always declare a variable volatile if it is shared between the main program and the ISR.
(Please note that volatile does not guarantee any atomic access, it does not protect against race conditions between the ISR and the main program.)

Related

Do i really needed accessor functions to access global variable from another file?

In my code (game engine code) there are multiple source (.c) files which maintain the status of the game, status like
START
CONFIGURE
STOP
END
DEFAULT
RUNNING
for maintaining state, one global variable gameStatus used which shared between multiple source files using extern keyword. now I have read that the global variable is bad to use and it allows the outside module to change it and as the number of components using global variable increases, the complexity of the interactions can also increase.
So I have limited scope that variable to one file using static keyword and added accessor methods like get or set APIs in the same file. So other files only access that variable using accessor APIs.
I have removed the global variable that is good but now every other file which used that global variable have to call accessor APIs which seems to add the overhead of function calls,
so now I am confused which is better? any C standard about how efficiently share the data between different source files?
The fact that global variables are "bad practice" is entirely opinion based and 100% dependent on the context. It is impossible to say whether you are applying such "bad practice" or not without looking at your code. Global variables are not bad practice per se, using them in the wrong way is. Global variables are often necessary in C. Take as an example the C standard library: errno is a global variable that is used basically everywhere in both library code and user code to check for errors. Is that bad practice? Could they have defined a function get_errno() instead (well to be honest they actually did it's just hidden... but that's for complex concurrency reasons)? I'll let you decide.
In your specific case, changing a globally visible variable to static and then creating two functions only to get and set its value is totally unnecessary. Any part of the code can still modify the variable, but now it's just more annoying to do so, and it could also lead to slower code if not optimized correctly. All in all, by creating those functions you just stripped the variable of the static qualifier.

volatile variables in C

What happens if I declare all variables in my C code to be volatile?
As far as I know the implementation of how volatile is honored is implementation specific and the bottom-line is that the compiler cannot trust any copies of the variable it might have . Consequently, the program might be larger in size and run slower if I am to declare all variables as volatile.
Are there any other problems if I do that?
You should concern if you are developing drivers that read flags from control registers or pointing to that location.
Some of these register has special properties, as clearing or setting other flags just by reading them. Then using volatile would just destroy your code.
I don't think it is a good idea to declare all variables as volatile. Two of the reasons were already given: bigger code and running slower.
Worse than that is not thinking. You will be last and final professional who will look at some place and making proper programming to prevent running conditions to destroy your code. Declaring all as volatile will only postpone this to a bug you won't be able to track in the future.
Declare volatile for:
Shared variables
Optimizing your code via compilers (for old compilers... Nowadays they are pretty good already for not allowing bugs when optimizing.. But need to be explicit anyway)
Multithreading shared variables

Are there any pitfalls when passing function pointers between compilation units?

I ask because i am using a PIC microcontroller to asynchronously operate hardware and implementing function pointers as a callback mechanism would be of benefit.
An example would be whereby an i2C library accepts read and write 'jobs' and sequentially executes each 'job' as the hardware resource becomes available (and as the user ticks the i2C software state machine). Depending on the implementers use of the i2C library, they may wish to manipulate the data prior to returning it, (bitmasking, setting flags etc) this is where i'm thinking of adding an i2C callback mechanism.
The user would pass a job, which includes a callback function pointing to the calling compilation unit. Is this allowed? and are there any cases that i need to be careful of if it is allowed?
Passing pointers between compilation units is done all the time. For example, free() in the standard library is certainly compiled separately and yet takes a pointer as its argument.
Within many projects, including the Linux kernel, callbacks between compilation units are used often.
The main key is to use common header files for defining shared variables, making function definitions, and such. If you define a function using a long pointer, but call it using a declaration that specifies a char pointer, you're entering Undefined Behavior territory.
Also watch out for compiler flags that may change variables sizes, default packing, and such.

Is it possible to instruct C to not zero-initialize global arrays?

I'm writing an embedded application and almost all of my RAM is used by global byte-arrays. When my firmware boots it starts by overwriting the whole BSS section in RAM with zeroes, which is completely unnecessary in my case.
Is there some way I can instruct the compiler that it doesn't need to zero-initialize certain arrays? I know this can also be solved by declaring them as pointers, and using malloc(), but there are several reasons I want to avoid that.
The problem is that standard C enforces zero initialization of static objects. If the compiler skips it, it wouldn't conform to the C standard.
On embedded systems compilers there is usually a non-standard option "compact startup" or similar. When enabled, no initialization of static/global objects will occur at all, anywhere in the program. How to do this depends on your compiler, or in this case, on your gcc port.
If you mention which system you are using, someone might be able to provide a solution for that particular compiler port.
This means that any static/global (static storage duration) variable that you initialize explicitly will no longer be initialized. You will have to initialize it in runtime, that is, instead of static int x=1; you will have to write static int x; x=1;. It is rather common to write embedded C programs in this manner, to make them compatible with compilers where the static initialization is disabled.
It turned out that the linker-script included in my toolchain has a special "noinit" section.
__attribute__ ((section (".noinit")))
/** Forces the compiler to not automatically zero the given global
variable on startup, so that the current RAM contents is retained.
Under most conditions this value will be random due to the
behaviour of volatile memory once power is removed, but may be used in some specific
circumstances, like the passing of values back after a system watchdog reset.
So all global variabeles marked with that attribute will not be zero-initialised during boot.
The C standard REQUIRES global data to be initialized to zero.
It is possible that SOME embedded system manufacturers provide a way to bypass this option, but there are certainly many typical applications that would simply fail if the "initialize to zero" wasn't done.
Some compilers also allow you to have further sections, which may have other characteristics than the 'bss' section.
The other alternative is of course to "make your own allocation". Since it's an embedded system, I suppose you have control over how the application and data is loaded into RAM, in particular, what addresses are used for that.
So, you could use a pointer, and simply use your own mechanism for assigning the pointer to a memory region that is reserved for whatever you need large arrays for. This avoids the rather complex usage of malloc - and it gives you a more or less permanent address, so you don't have to worry about trying to find where your data is later on. This will of course have a small effect on performance, since it adds another level of indirection, but in most cases, that disappears as soon as the array is used as an argument to a function, as it decays to a pointer at that point anyways.
There are a few workarounds like:
Deleting the BSS section from the binary or setting its size to 0 or 1. This will not work if the loader must explicitly allocate memory for all sections. This will work if the loader simply copies data to the RAM.
Declaring your arrays as extern in C code and defining the symbols (along with their addresses) either in assembly code in separate assembly files or in the linker script. Again, if memory must be explicitly allocated, this won't work.
Patching or removing the relevant BSS-zeroing code either in the loader or in the startup code that is executed in your program before main().
All embedded compilers should allow a noinit segment. With the IAR AVR compiler the variables you don't want to be initialised are simply declared as follows:
__no_init uint16_t foo;
The most useful reason for this is to allow variables to maintain their values over a watchdog or brown-out reset, which of course doesn't happen in computer-based C programs, hence its omission from standard C.
Just search you compiler manual for "noinit" or something similar.
Are you sure the binary format actually includes a BSS section in the binary? In the binary formats I've worked with BSS is simply a integer that tells the kernel/loader how much memory to allocate and zero out.
There definitely is no general way in C to get uninitialized global variables. This would be a function of your compiler/linker/runtime system and highly specific to that.
with gcc, -fno-zero-initialized-in-bss

Static vs global in terms of speed and space consumption in C

I would like to know difference between static variables and global variables in terms of access speed and space consumption. (If you want to know my platform: gcc compiler on Windows. (I am using Cygwin with Triton IDE for ARM7 embedded programming on windows. Triton comes with gcc compiler on Java platform which can be run on Windows.))
(Obviously I know in terms of file and function scope from this question)
Edit: OK give me an answer on any micro controller / processor environment.
There is no difference for the space, they take the same amount.
But there is a speed difference: static is faster.
Of course the memory access to the variable is for global and static the same. But the compiler can optimize when you have static. When it compiles a module it knows that no function call to a function outside the module can change a static variable. So it knows exactly what happens and can e.g. keep it in a register over function calls. When it is global and you call a function from a different module, the compiler can't know what it does. Hence he must assume that the function accesses the variable and changes it, resulting in a store and reload.
With gcc you can pass all .c sources at the same time, so it can then also see what happens in function calls to functions from different modules. To make it work you have to pass besides all .c files at once -combine and -fwhole-program. The -fwhole-program makes all globals static (not module static but compilation unit static, i.e. all the given .c files together). The -combine makes the intermodule analysis.
Space consumption: basically no difference. The only time there'd be a space issue is if you manage to get the same chunk of static data hidden in N object files, then you get a multiplication factor of N where you might have just 1 copy if it was a single global piece of data. However, that's a mis-design issue. Information hiding is good - unless the information should not be hidden.
Access speed: no difference.
It's hard to guess, or to estimate. It would probably take time, but I would make a sample project and test for speed. Testing both access speed and space with a loop. Test the sample project with an emulator for that architecture.
I would expect any difference would come from packing (for space) and caching (for speed) issues. Both those could also arise from just about anything else as well.
There is no difference in the env you describe when it comes to space. The static or global var consume just the same amount of memory.
For speed considerations (but not good practice) you could prefer global vars, if you need access to the var outside the one file.
(ref use of external char my_global_char_placed_else_where;)
For better practice you use get/set functions instead but they are slower. So then you could use macros for get/set of a var that is global to hide from the reader of the code that the var is in fact global, but that is kind'a like cheating. But it can make the code more readable.
If you compare hiding a var inside a function, then it has no difference compared with placing it outside the function and more functions could have access to the var.
I myself use MSP430, ARM7(just for tests) and AVR32 micros for development
What Jonathan says is not exactly correct. Both static and global variables will be (has to be) saved in the ZI (or RW data) regions. The compiler cant "keep" it over the register strictly - what it might do is load the value into the register, use that register for all operations and than save that value back - thats a compiler specific optimization. And even then, there is no reason why the compiler wont do that also for global variables : unless of course u make it volatile. But then, technically you can also make a static variable volatile, so again no difference.
Edit : oh yeah - space : no difference.

Resources