Uninitialized variable put into program memory area. AVR programming - c

In xxx.h file I have declaration:
const struct MenuItem MenuItemA;
in xxx.c file I have definition:
const struct MenuItem MenuItemA PROGMEM = {textA, MenuItemAFunction, &MenuItemB, 0};
I also include xxx.h file in my main.c file.
While building the project i get this warning:
uninitialized variable 'MenuItemA' put into program memory area [-Wuninitialized]
When I had declaration and definition in the same .c file everything was OK, I have no idea what is wrong now.

Joachim is correct, ALL definitions in header files need an extern - otherwise every time you use the header (in a different source file) you'll create another copy of the variable.
To answer your original question, I suspect the variable is in the code section because it is constant, if you remove the const it'll go into the BSS or DATA section depending on how it's defined.
But you're main problem is the lack of an extern

As you say, it is not an error, but merely a warning about wasting precious flash memory for uninitialized variables.
If it is indeed uninitialized, there seems to be no need to put it explicity into progmem as it is constant there and cannot be overwritten (easily) during program run.
The way you use it - have a tentative definition in all files which include the header file and define it in one file will make the compilation of the other files complain about exacly this. (This would better be a link time warning instead of a compile time warning...)
(BEGIN of long BLAH)
I just ran into the same issue: I want to create a "plugin" framework where the user of my library can choose whether to add a certain function pointer as a "plugin": in my library's header file, I have a
extern some_type * const PROGMEM my_array[];
and a
#define enable_my_stuff() some_type * const PROGMEM my_array[2] = {something_of_some_type, NULL}
while my library's C file has a
// Tentative definition which is used when nothing else is there.
some_type * const PROGMEM my_array[2];
This way I have two cases: either no one uses enable_my_stuff() and my array is empty (that's ok, but 4 bytes are wasted) or enable_my_stuff() is used, the extended functionality is activated and the array content reflects this.
It works, but I get exactly the warning as above. As it annoys me, I'm probably going to implement it in a different way.
(END of long BLAH)

Related

Variable defined but not used message in kernel module

In my Kernel module, I have two very short C source files (the main file and a daq.c and daq.h file). The header file contains a number of variables and functions. When I compile the functions normally, by declaring the variable in the daq.h file:
volatile uint32_t *gpio;
I receive the following error:
error In function `.LANCHOR1':
daq.c:(.bss+0x50): multiple definition of `gpio'
This error is only solved by declaring the variable as static, as follows:
static volatile uint32_t *gpio;
The kernel module works fine but in this case I receive the following warning as a static declaration creates a separated copy on every file in which it is included:
warning: ‘gpio’ defined but not used [-Wunused-variable]: static volatile uint32_t *gpio;
I've tried to declare it extern or just simply declaring the variable as uint32_t *gpio instead of declaring it static but then I get a:
WARNING: "gpio" undefined!
followed by an "out-of-tree definition" message in the dmesg log when the module is inserted (and the module is not loaded).
So, in this case, how is the best way to proceed in order to declare the variable? Is it correct to declare it as:
static volatile uint32_t *gpio;
and just omit the "defined but not used" warning given by the compiler? I don't think just "omitting" the warnings is a good practice, especially when it comes to kernel modules.
Thanks in advance.
Your question is not very clear because a full context is missing; but anyway I think some advice can be given.
First, your sources will be used together with other files; those files define things you have to be aware of, otherwise things like multiple definition of 'gpio' come out. In this case (gpio), you must decide if you want to interact with the "other" gpio variable - if not, you must use another name (it is not mandatory, but it is better).
Second, you must understand how the C compiler works, especially if you interface with the kernel, which adds some mechanisms. In general, you don't want to define variables in a header (.h) file; instead, you do declare them, together with data types, macros, and function prototypes. In the source files (.c) you #include headers in order to use the declarations found in them.
Variables are defined in .c files, and made available to other modules through header files, if this is wanted. Otherwise, make them static and do not mention them in the header.
The difference between declaration and definition is this: a declaration tells the compiler "you will encounter (perhaps) this name, somewhere, which has the following properties"; a definition instead means "I create this name, with these properties, and this thing is exactly here.".
When more than a single piece of software are used together, often happens that one piece does something needed in another one... declaration are the way to let these pieces work together.
Hope this helps a little.

Pointer to a global static variable - not safe?

I have file in which I have a global array
static char name[6];
and a function
static char* gen_name(char* dest, const size_t len) {
for (int i = 0; i < len - 1; ++i)
dest[i] = 'A' + (genrand_uint32() % ('Z' - 'A'));
dest[len - 1] = '\0';
return dest;
}
The pointer to the name is then stored in a global variable in different header file, this variable is not static.
this_name = gen_name(name, sizeof name);
When a function in another file uses this pointer, it works well on Linux, but when I run the same code on a microcontroller, it prints garbage.
When I remove the static keyword, it works fine.
Why is this happening?
When should I use static?
I thought I should declare all variables and functions that are not used outside of a file as static, is this wrong?
When you declared the variable in the header, did you remember to mark it extern? You need to do that, otherwise what happens is that you just get a new variable in each file that includes the header. Remember that #include is just a copy&paste job; the preprocessor just inserts the text from the header file in the location where the include happens. If the text in the header file is char name[6], then that's just what you get; text in your source that says char name[6], resulting in a variable name that has nothing to do with the variable that you have in your other source file.
If you mark it as extern, the linker will then complain that the symbol was not found. That means the definition of name can't be static, as that causes the linker not being able to find it.
So, in your header file, you need this declaration:
extern char name[6];
and in your source file, you need this definition:
char name[6];
And to answer the actual question: yes, it's perfectly safe.
It turned out to be caused by a stack overflow in a different thread, marking it static would put it in the bss section, just behind the stack that would overflow.
Static keyword means different things to functions and variables.
Functions are by default 'extern', i.e. their entry points are made public by the compiler so the linker can find them and they can be called from any compiled module.
If you put 'static' in front of a function's declaration, the function will stop being public, i.e. it will only be known inside the same source module.
'static' keyword has very different meaning when used for variables(*). It makes them non-changeable.
When you say 'static char name[6]', you are telling the compiler that you have no intention of changing value of 'name'.
On Linux running on a PC, this doesn't mean much. You tell the compiler that you won't change the value and then you change it. You lied. No big deal.
Some microcontrollers have internal flash that they can use to run code from, and keep fixed (constant!) data in.
The compiler and linker use your promise that 'name' will not change and leave the variable in the flash memory.
You can imagine what (doesn't) happen when you try to change it.
More precisely, the compiler will place all your static variables in something like .const section, and linker will then place that section in flash memory.
(*) There is a way to look at 'const' that makes it having the same meaning when used for variables as for functions. Not important here.

Static struct declaration and initialization in c header file

I develop an embedded application which uses the MindTree Bluetooth SDK.
I have the following in a header file:
typedef struct {
UCHAR outputDir;
UCHAR reset;
UCHAR nack;
UCHAR startCondition;
UCHAR stopCondition;
UCHAR busy;
} USCI_ConfigurationFlags;
static USCI_ConfigurationFlags usciConfigFlags = { UCTR, UCSWRST, UCNACKIFG, UCTXSTT, UCTXSTP, UCBBUSY };
Later in two .c files I include the above header and use the usciConfigFlags on different occasions sometimes from within an interrupt.
Is this legal?
I'm trying to understand why(and if it is related to the question) the values of the struct change at runtime, after calling the BT_bluetooth_on method in the SDK.
Thanks,
Adam.
static here doesn't mean what you think it means. It means that the declaration and variable will only be visible in one compilation unit. That is, you have two independent instances of usciConfigFlags.
If you want a global variable, you need to use extern not static and make the actual declaration (without extern) with the initial value in one of your c files.
Also be weary of changing the values in the struct without proper locking. Read-only concurrent access is usually fine.
There is no problem you include the header in two .c file. The static modifier limits the accessible scope of the variable in the file including the header only. The two usciConfigFlags in two different files are not identical.
Also static does not mean constant. So you can modify the value of the structure in whatever way you want.
The following is from wikipedia
In computer programming, a static variable is a variable that has been
allocated statically — whose lifetime extends across the entire run of
the program. This is in contrast to the more ephemeral automatic
variables (local variables), whose storage is allocated and
deallocated on the call stack; and in contrast to objects whose
storage is dynamically allocated.
Prepending a static keyword to a variable makes it visible only in the current translation unit (i.e. if within a function, only that function and if within a file, only that file).
It is never a good idea to define a variable in a header file. Even if you need two static variables in two different files with the same name, it is better that you put in the .c file itself as it helps in better maintaince and readability as you will be clear in which all files it is actually present and is being used.
If you add it in a header file, then at a later point, if some other .c file includes this header, then unneccessarily this variable will included for that translation unit.
Epsalon had suggested other good points which you can consider.

global constants without using #define

Ok, I'm looking to define a set of memory addresses as constants in a .h file that's used by a bunch of .c files (we're in C, not C++). I want to be able to see the name of the variable instead of just seeing the hex address in the debugger... so I want to convert the #defines I currently have into constants that are global in scope. The problem is, if I define them like this:
const short int SOME_ADDRESS = 0x0010
then I get the dreaded "multiple declarations" error since I have multiple .c files using this same .h. I would like to use an enum, but that won't work since it defaults to type integer (which is 16 bits on my system... and I need to have finer control over the type).
I thought about putting all the addresses in a struct... but I have no way (that I know of) of setting the default values of the instance of the structure in the header file (I don't want to assume that a particular .c file uses the structure first and fills it elsewhere.. I'd really like to have the constants defined in the .h file)
It seemed so simple when I started, but I don't see a good way of defining a globally available short int constant in a header file... anyone know a way to do this?
thanks!
Declare the constants in the header file using extern:
extern const short int SOME_ADDRESS;
then in any, but only one, .c file provide the definition:
const short int SOME_ADDRESS = 0x0010;
If you're compiling with gcc, you can add the -ggdb3 switch, which will tell gcc to store macro information (i.e. #defines) so that they can be used inside gdb.

Extern array of function pointers in C on a fixed memory address

I'm working on a embedded application where I need to declare an array of function pointers on a fixed memory address and then use it in different .c files. What I came up with is this:
typedef void(__irq __arm * p_intr_handler_t)(void);
p_intr_handler_t * IntTable = (p_intr_handler_t *)&VIM_RAM_BASE;
p_intr_handler_t IntTable[95];
VIM_RAM_BASE is the address. I delcare this in main.f file and I need to use it in various .c files, so I declared it like this:
extern p_intr_handler_t IntTable[95];
But whilst trying to compile I get an error message:
"declaration is incompatible with "p_intr_handler_t *IntTable" (declared at line 3)"
that message goes for both the normal and the extern declaration.
Any ideas what's wrong?
Thanks
Depending on what you're trying to do, it may make more sense to do this with the linker rather than the compiler. In that case you just declare the symbol as extern in the C file (with no definition at all), and tell the linker where it is. So your header would contain:
extern p_intr_handler_t IntTable[95];
and then you'd add a link-time option (GNU gcc/ld syntax here -- other linkers are different)
-Wl,--defsym=_IntTable=0x8000000
where you set the address to whatever you like. Check out the documentation for your linker to see what the equivalent option is.
Why are you redeclaring IntTable with a different type?
Just jeep the first definition in a single .c, and create an extern for it in a .h to be included in the other .c, like this:
extern p_intr_handler_t * IntTable;
Obviously this works only if VIM_RAM_BASE is already somehow reserved for your data (i.e. the compiler won't try to put there other data), otherwise you should check out your compiler's documentation to see if there's a way to tell it to put a variable at a specific place in memory.
You've defined IntTable twice, shouldn't you rename that to something else?

Resources