2023-01-17 10:16 AM
Hello all....
Firstly I will say I am a hardware engineer so forgive the firmware ignorance.....
I have a main.c and a main.h.....main.c includes main.h
If I place
const uint16_t dacValues[NUMBER_MSMNTS] = {273, 769, 1390, 2631};
in main.h and try and use it in main.c, I get an error which is extremely cryptic and doesn't put any error flags on any code.....What is this error trying to tell me and why can't main.c see this declared variable as main.c includes main.h???
./Core/Src/stm32l4xx_hal_msp.o:D:/STM32_FW/SWS-SIPM-01/Debug/../Core/Inc/main.h:93: multiple definition of `dacValues'; ./Core/Src/main.o:D:/STM32_FW/SWS-SIPM-01/Debug/../Core/Inc/main.h:93: first defined here
Certainly moving this variable to main.c removes the error....but it being a constant and all I figured the best place to put this is in main.h....
Thanks
2023-01-17 10:37 AM
A short answer: the line that you wrote above is a definition of some data (array).
Such things should be in .c files, not in .h.
A declaration (that can be put in a .h file) looks like:
extern const uint16_t dacValues[NUMBER_MSMNTS];
2023-01-17 10:42 AM
That is a fair response and I will do that moving forward....Can you tell me why the compiler errors and what it means?
As an experiment if I place the following line in main.h in Code Composer Studio
const uint8_t test = 5;
I can then use it in main.c (recall main.h is included)
if (test == 5)
__delay_cycles(45);
it compiles and gives no errors
It must be a compiler setting or something in CubeMX
2023-01-17 11:15 AM
Think about it in this way: the compiler compiles the single source text stream obtained by catenating the .h file and .c file. If it sees two definitions of the same object, it triggers an error. It's just a convention, but a very important one, NOT to put definitions in a .h file. The compiler may process multiple declarations of an object in a single source stream, but only one definition.
extern const uint_8 t x; is a declaration - it tells the compile that x exists, but it doesn't create x. Thats what should appear in .h file
const uint_8 t x = 5; is a definition - it creates x constant. It should only appear in a .c file.
2023-01-17 11:22 AM
Yes it is kind of compiler setting. CubeIDE has a newer ARM gcc compiler version, where what you did is no longer acceptable (at least without warnings).
2023-01-17 12:37 PM
so it seems the code will get pretty unwieldy and hard to read if I place a lot of const types in main.c???
For instance I have the following (now albeit in MSP430 CCS world) in an h file
typedef struct D_A_t
{
uint8_t add;
uint8_t ub;
uint8_t lb;
}D_A_t;
const D_A_t vref = {DAC_VREF_WRITE, 0, 0};
const D_A_t pwrDwn = {DAC_PWR_DOWN_WRITE, 0, 0};
const D_A_t gain2 = {DAC_GAIN_CFG_WRITE, 3, 0};
Then in main.c I have a definition as such:
const D_A_t *cnfgDA[2] = {&vref, &pwrDwn};
My point is placing all these const for different hw into main seems very cumbersome....what is a better way to do this kind of thing?
2023-01-17 01:22 PM
Well, the reasoning behind this convention is that .h files (especially main.h in stm32 projects) get included in a lot of .c files - not only in main.c. This creates a lot of duplicate object definition.
In plain C, "const uint8_t test" is not a constant, it is a variable. C is not C++.
But rules are there so we can break them )) Create a very private .h file that is included by only one .c file, and this won't make duplicate definitions.