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.
Related
I have a header file. It contains the value of various constants(as pre-processor macro definitions---hash defines) that I use in my embedded systems project(IDE is Keil MicroVision, Microcontroller is STM32 and programming language is C).
I want to convert that header file to a hex file, so that I can separately write it to flash memory of the microcontroller.
Hence, for a single general software code, I wish to to change the constants and run it for specific (around 10-15 different types) hardware.
My approach: I am trying to find a way to convert the header file to a binary file first, and then use some utility(srecorder from sourceforge) to convert the .bin to .hex
Is this approach right?
Or can anyone please suggest an alternate and effective way to achieve my goal?
Thanks
Preprocessor defines aren't stored in data flash but in program flash (.text), together with the code using them, integrated in the machine code. They aren't stored at any specific or fixed address. So your request doesn't make any sense - you simply cannot program them to flash separately.
In order to achieve that you need const uint32_t or similar variables stored at fixed memory locations. These need to be declared in a .c file, though it is sometimes acceptable to expose read-only variables "globally" with extern references from a corresponding .h file.
To allocate a variable at a specific address you typically need to change the linker script and use non-standard compiler extensions.
Understanding where you're coming from, I would not recommend going down the road you suggested. Let me show you two ways to solve your problem which I believe are much better.
I'll assume your constants are macros, but, it should not be different if they are enums or something else.
First option is to use the preprocessor to select your platform. Something like:
#if defined(PLATFORM_A)
#define CONSTANT_X 111
#define CONSTANT_Y 222
#elif defined(PLATFORM_B)
#define CONSTANT_X 112
#define CONSTANT_Y 221
#else
#error Need to define a platform
#endif
Of course, if you have a lot of constants, maybe keeping each platform in its own header would be better (easier to read).
#if defined(PLATFORM_A)
#include "platform_a_constants.h"
#elif defined(PLATFORM_B)
#include "platform_b_constants.h"
#else
#error Need to define a platform
#endif
This option is the only way if you use these constants to, say, dimension an array.
I don't have experience with Keil IDE's, so, I'm not sure how to configure it to build different binaries with different macro definitions, but, it's a common C thing, there should be way to do it.
Another option would be to make these globals. In that case, you would have a single header like:
extern int const constant_x;
extern int const constant_y;
And then a separate source file for each platform:
// platform_a.c
int const constant_x = 111;
int const constant_y = 222;
// platform_b.c
int const constant_x = 112;
int const constant_y = 221;
Again, how to link in only the source file that you need for a particular target depends on your build system and I'm not familiar with Keil IDE, but it should not be hard to do.
In general, this option is a little easier to maintain, as it's just setting up the linker, you don't mess up with source code in any way (and defining a preprocessor constant is messing up with the source code in potentially ugly ways).
Also, with this option it's simple to turn a constant into a runtime parameter, which can be changed during the execution of the program, if need be - just drop the const from the declaration and definitions.
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.
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)
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?
I have a C project where all code is organized in *.c/*.h file pairs, and I need to define a constant value in one file, which will be however also be used in other files. How should I declare and define this value?
Should it be as static const ... in the *.h file? As extern const ... in the *.h file and defined in the *.c file? In what way does it matter if the value is not a primitive datatype (int, double, etc), but a char * or a struct? (Though in my case it is a double.)
Defining stuff inside *.h files doesn't seem like a good idea generally; one should declare things in the *.h file, but define them in the *.c file. However, the extern const ... approach seems inefficient, as the compiler wouldn't be able to inline the value, it instead having to be accessed via its address all the time.
I guess the essence of this question is: Should one define static const ... values in *.h files in C, in order to use them in more that one place?
The rule I follow is to only declare things in H files and define them in C files. You can declare and define in a single C file, assuming it will only be used in that file.
By declaration, I mean notify the compiler of its existence but don't allocate space for it. This includes #define, typedef, extern int x, and so on.
Definitions assign values to declarations and allocate space for them, such as int x and const int x. This includes function definitions; including these in header files frequently lead to wasted code space.
I've seen too many junior programmers get confused when they put const int x = 7; in a header file and then wonder why they get a link error for x being defined more than once. I think at a bare minimum, you would need static const int x so as to avoid this problem.
I wouldn't be too worried about the speed of the code. The main issue with computers (in terms of speed and cost) long ago shifted from execution speed to ease of development.
If you need constants (real, compile time constants) you can do that three ways, putting them into header files (there is nothing bad with that):
enum {
FOO_SIZE = 1234,
BAR_SIZE = 5678
};
#define FOO_SIZE 1234
#define BAR_SIZE 5678
static const int FOO_SIZE = 1234;
static const int BAR_SIZE = 5678;
In C++, i tend to use the enum way, since it can be scoped into a namespace. For C, i use the macro. This basicially comes down to a matter of taste though. If you need floating point constants, you can't use the enumeration anymore. In C++ i use the last way, the static const double, in that case (note in C++ static would be redundant then; they would become static automatically since they are const). In C, i would keep using the macros.
It's a myth that using the third method will slow down your program in any way. I just prefer the enumeration since the values you get are rvalues - you can't get their address, which i regard as an added safety. In addition, there is much less boiler-plate code written. The eye is concentrated on the constants.
Do you really have a need to worry about the advantage of inline? Unless you're writing embedded code, stick to readability. If it's really a magic number of something, I'd use a define; I think const is better for things like const version strings and modifying function call arguments. That said, the define in .c, declare in .h rule is definitely a fairly universally accepted convention, and I wouldn't break it just because you might save a memory lookup.
As a general rule, you do not define things as static in a header. If you do define static variables in a header, each file that uses the header gets its own private copy of whatever is declared static, which is the antithesis of DRY principle: don't repeat yourself.
So, you should use an alternative. For integer types, using enum (defined in a header) is very powerful; it works well with debuggers too (though the better debuggers may be able to help with #define macro values too). For non-integer types, an extern declaration (optionally qualified with const) in the header and a single definition in one C file is usually the best way to go.
I'd like to see more context for your question. The type of the value is critical, but you've left it out. The meaning of the const keyword in C is quite subtle; for example
const char *p;
does not mean that pointer p is a constant; you can write p all you like. What you cannot write is the memory that p points to, and this stays true even as p's value changes. This is about the only case I really understand; in general, the meaning of the subtle placement of const eludes me. But this special case is extremely useful for function parameters because it extracts a promise from the function that the memory the argument points to will not be mutated.
There is one other special case everyone should know: integers. Almost always, constant, named integers should be defined in a .h file as enumeration literals. enum types not only allow you to group related constants together in a natural way, but also allow you the names of those constants to be seen in the debugger, which is a huge advantage.
I've written tens of thousands of lines of C; probably hundreds if I try to track it down. (wc ~/src/c/*.c says 85 thousand, but some of that is generated, and of course there's a lot of C code lurking elsewhere). Aside from the two cases about, I've never found much use for const. I would be pleased to learn a new, useful example.
I can give you an indirect answer. In C++ (as opposed to C) const implies static. Thatis to say in C++ static const is the same thing as const. So that tells you how that C++ standards body feels about the issue i.e. all consts should be static.
for autoconf environment:
You can always define constants in the configure file as well. AC_DEFINE() i guess is the macro to define across the entire build.
To answer the essence of your question:
You generally do NOT want to define a static variable in a header file.
This would cause you to have duplicated variables in each translation units (C files) that include the header.
variables in a header should really be declared extern since that is the implied visibility.
See this question for a good explanation.
Actually, the situation might not be so dire, as the compiler would probably convert a const type to a literal value. But you might not want to rely on that behavior, especially if optimizations are turned off.
In C++, you should always use
const int SOME_CONST = 17;
for constants and never
#define SOME_CONST 17
Defines will almost always come back and bite you later. Consts are in the language, and are strongly typed, so you won't get weird errors because of some hidden interaction. I would put the const in the appropriate header file. As long as it's #pragma once (or #ifndef x / #define x / #endif), you won't ever get any compile errors.
In vanilla C, you might have compatibility problems where you must use #defines.