Can't resolve C warning in STM32CubeIDE - c

Facing a a warning which I am not able to get rid of. I am using stm32 MCU and STM32CubeIDE with a standard C11 compiler. Array gpioOutPins is used by in a function call gpio.c file. This function which contains this function call is called from inOut.c file.
Please note that the inOut.c file is in User Application layer while the gpio.c file is in the Kernel (Core) section of the project tree as can be seen below. I was not able to accommodate the whole project tree in the snapshot.
I don't understand why this warning is generated.
Any help is appreciated. Thank you.
An array is deifned in a header file gpio.h:
static uint16_t gpioOutPins[GPIO_OUT_CH_NR] =
{
DOUT_OD_OUT4_Pin,
DOUT_OD_OUT6_Pin,
DOUT_OD_OUT5_Pin,
DOUT_OD_OUT7_Pin,
DOUT_LED_DISABLE_Pin,
DOUT_BUZZ_Pin,
DOUT_OD_OUT8_Pin,
DOUT_OD_OUT3_Pin,
DOUT_OD_OUT2_Pin,
DOUT_OD_OUT1_Pin,
DOUT_ALARM_Pin,
DOUT_12V_PWR_Pin,
DOUT_12V_PWR_Pin
};
The directory structure looks like this:
The warning generated by the compiler is this:
warning: 'gpioOutPins' defined but not used [-Wunused-variable]

Header (.h) files are not a good place to define global variables, because when they are included in source (.c) files, multiple independent copies of them come to existence. They share the same name, but they are actually different variables. And if they are not static, the linker rejects them because of multiple definitions.
Your inOutTask.c probably includes gpio.h header directly or indirectly, so another copy of gpioOutPins comes into existence, which is distinct from the one used in gpio.c. Because you don't use gpioOutPins in inOutTask.c, you get the warning.
The proper way is to move the definition into gpio.c, remove the static keyword, and add extern uint16_t gpioOutPins[GPIO_OUT_CH_NR]; to gpio.h

Related

Including .h and .c files to project on the IAR

I am programming stm8s and sht20 from sensirion company with I2C on the IAR. I'm using sht20 sample code: this link
I edited this sample code to my mcu. Then, for example I included i2c_hal.h to my main.c, but functions not working in my main.c file and IAR error is
ERROR LI005 no defition for I2c_Init()
Linking error
For example:
main.c
#include "stm8s.h"
#include "i2c_hal.h"
I2c_Init();
i2c_hal.h
#ifndef I2C_HAL_H
#define I2C_HAL_H
void I2c_Init ();
#endif
i2c_hal.c
#include "I2C_HAL.h"
void I2c_Init ()
{
SDA=LOW;
SCL=LOW;
SDA_CONF=LOW;
SCL_CONF=LOW;
SDA=HIGH;
SCL=HIGH;
}
I copied sht20 files to my project directory. What should I do for this error?
The header file is read by the preprocessor not the linker; if you get as far as linking, it is not a header file issue. The three basic build steps for C code are:
preprocess
compile
link
Your build is failing at the link state. The linker requires all compiled object files and any necessary libraries that constitute your application as input. In your case the most likely issue is that you have not compiled and linked i2c_hal.c (or strictly compiled i2c_hal.c and linked i2c_hal.obj). In the IAR IDE you simply explicitly add i2c_hal.c to your project along with main.c, and all should be good (all other dependencies being satisfied).
I suspect that i2c_hal.c will infact fail compilation since it is missing any declaration of SDA, SCL etc. - you probably need to include stm8s.h there also.
In general the process looks like this (this diagram actually omits pre-processing - i.e. expansion of headers, macros and conditional compilation etc. - but it was the otherwise clearest example I found; the original page does however mention the pre-processor stage, and the preprocessor is normally run automatically when you invoke the compiler in any case):
I have also the same issue with the spi. I got hal_spi_init() linking problem. To resolve the issue you need to enable the I2C in your stm32 hal drivers. In stm32xx_hal_conf.h file we have different #define modules. There you can enable the I2C module or just include the defined symbol in your IAR tool. Then Issue resolved
You need to add the C source files to the project. Header files shall not have any code or data, only the declarations of types , extern variables, macros, static inline functions and function prototypes.

Including source files in C files

I am very new to C, so I apologize for this newby question.
I would like to use this source code in my project: http://base64.sourceforge.net/b64.c.
So, I include it in my test file:
#include <stdio.h>
#include "b64.c"
int main()
{
return 0;
}
However, main() is defined in b64.c as well, so upon compiling, I get:
test.c:4:5: error: redefinition of ‘main’
b64.c:495:5: note: previous definition of ‘main’ was here
test.c: In function ‘main’:
test.c:5:1: error: number of arguments doesn’t match prototype
b64.c:495:5: error: prototype declaration
What is the correct usage of this source file, or any? How do we correctly use it, or use functions defined in that file?
Edit: I understand that the problem is due to the duplicate definitions of main. I know there can only be one. My question is rather, won't every meaningful project need it's main method? Then why is there a main method defined in b64.c? Are we just supposed to delete this method from the source code? It seems odd that the source code doesn't just come ready to be included and used.
It is never a good idea to #include a C source file into your code. You can either copy the code from the other C source file into your code, or include the needed prototypes in your code and make a call to the functions, linking those after compiling them separately.
you should use one of the two main functions.
If you want a new main, write your main method in your file and remove it from the 'b64.c' file, if you want to use it from the 'b64.c' file remove your (empty) main.
If main is defined in b64.c either you cannot simply redefine it in your main source file.
What do you want is to use several functions from b64.c in your program. Delete the main function from it and create a header file where you protoype all of the functions in b64.c. After that, include this header file in your main program. Have a look at this short Wikipedia entry. It should give you an overview of the topic.
Besides this: It seems that you aren't very familar with C. Try out some tutorials and go on reading about C.
First of all, you must redeclare the .c file as a .h, and then you have to go through the source code and rename any duplicate methods or global variable names. The main method is the starting point of a program so there can only be one.
(Usualy you dont include .c files, only .h)
if you want the functions inside the "b64.c" you should delete the main function from "b54.c"!
A C application needs one main() function. Your file b64.c looks like a self-sufficient C program so you don't need your test.c. Just compile and run b64.c.
When you are including that source file you are getting 2 main() declaration which is incorrect. So you have redefined "main" in this case.
Including .c into another .c file doesn't make sense. C files compile to .obj files, which are linked by the linker into the executable code , so there is no need to include one .C file into another. Instead, you can make a .h file that lists the functions and include that .h file

Can't compile multiple files for Arduino

I'm having an issue with compiling code for Arduino if the code is in multiple files. What I have been doing in the past is have a script concatenate the files in another directory and make the project there. I would like to be able to compile directly from my build folder without having to jump through hoops of making sure everything is defined in the right order, etc.
I'm using avrdude to compile from Linux command line, because the Arduino IDE doesn't work very well with my window manager. When I make with multiple files (with appropriate #include statements, I get errors of the following nature, but for all of my methods and variables.
./../lib/motor.ino:3:21: error: redefinition of ‘const long unsigned int MOVE_DELAY’
./../lib/motor.ino:3:21: error: ‘const long unsigned int MOVE_DELAY’ previously defined here
The only other place that MOVE_DELAY is used is inside the void loop() function, and it doesn't redefine it there. The code also compiles fine if concatenate it into one file and run make in that directory, but not if they are in separate files with includes.
I believe your problem is solvable by declaring the objects with the "extern" prefix or external. For example. I often use the SdFat library, in which it is included in both my main sketch and instanced in other libraries.
/**
* \file test.ino
*/
#include <SdFat.h>
#include <foo.h>
SdFat sd;
...
Where I also use the same object in other libraries, such as foo.h.
/**
* \file foo.h
*/
#include <SdFat.h>
extern SdFat sd;
...
If it was not for the prefix of "extern" it would error like yours, as "sd" can not exist twice. Where the extern prefix tells the linker don't make a new instantiation, rather link to the externally instance elsewhere.

multiple definiton of function-error in kernel-file

Hey guys.
What I'm currently trying to do is to port the tool DigSig to a CentOS-Kernel which seems to lack a few important crypto-functions for DigSig.
So the port this I just a newer /linux/crypto.h which has the functionality I need plus I added this little code:
void kzfree(const void *p) {
size_t ks;
void *mem = (void *)p;
if (unlikely(ZONP(mem)))
return;
ks = ksize(mem);
memset(mem, 0, ks);
kfree(mem);
}
because my kernel I'm working on does not have kzfree yet.
Now, when I try to compile DigSig, this is the output:
/home/Chris/dsTest/dsi_sysfs.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/digsig_cache.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/digsig_revocation.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
/home/Chris/dsTest/dsi_sig_verify.o: In function `kzfree':
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: multiple definition of `kzfree'
/home/Chris/dsTest/digsig.o:/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h:114: first defined here
Of course, all is covered by #ifndef-Guards, so I just cannot understand why he is defining this function multiple times...
Any ideas?
Your include file gets included in multiple places.
This is not compile time error. But rather a linked time error.
Each of your file got compiled and produced following .o files
/home/Chris/dsTest/dsi_sysfs.o
/home/Chris/dsTest/digsig_cache.o
/home/Chris/dsTest/digsig_revocation.o
/home/Chris/dsTest/dsi_sig_verify.o
Now while linking them together it finds multiple definition of kzfreez, one each in above .o files because their corresponding c files included
/usr/src/kernels/2.6.18-194.32.1.el5-i686/include/linux/crypto.h
You have ifdef guarded the file, but that only prevents inclusion of .h file in same c file (translation units) not across different c files.
You should write the function in c file and add in in make files, so that it gets compiled separately and linked. And only add declaration in crypto.h . (For testing you can add definition in crypto.c and declaration in crypto.h).

How can I keep doxygen from documenting #defines in a C file?

I have #define values in headers that I certainly want Doxygen to document but I have others in C files that I treat as static constants and I don't want Doxygen to document them. Something as simple and stupid as
#define NUMBER_OF(a) (sizeof((a))/sizeof((a)[0]))
#define MSTR(e) #e
How can I keep Doxygen from putting those #defines in the documentation it creates? I've tried marking it with #internal but that didn't seem to help.
A somewhat-related question on Doxygen and #define, how can I get:
#define SOME_CONSTANT 1234 /**< An explanation */
to put "SOME_CONSTANT" and "An explanation" but not "1234" in the output?
There is no need to use the \cond and \endcond commands. You can hide the initializer by simply using the \hideinitializer command:
#define SOME_CONSTANT 1234 /**< An explanation #hideinitializer */
Regarding the first question, you may set HIDE_UNDOC_MEMBERS = YES and only the macros having a Doxygen documentation block will be shown in the output.
You can set MAX_INITIALIZER_LINES = 0 in your doxyfile to hide the values of your defines.
You can exclude any part of code from Doxygen parsing with \cond ... \endcond tags.
edit: Some related questions:
How can Doxygen exclude a C++ class?
Exclude some classes from doxygen documentation
You only want to document what is declared in the .h files. I'm assuming you declare all static functions and variables as static in your .c files. All the remaining are declared in .h corresponding files also. These are your "public" members.
What I like to do in this case, and I believe doxygen was more designed to be used this way is:
in your Doxyfile, set EXTRACT_ALL = NO and add the directory where your .h files are to INPUT
add /** \file */ to all your .h files (but not your .c files).
This will index only what is contained in your .h files. You can still add the directory containing your .c files to INPUT at your Doxyfile, and they will be scanned for additional documentation for your "public" members...
It will no doubt still seem noisy and unnatural, but to address your other question, try:
/** An explanation */
#define SOME_CONSTANT /** #cond */ 1234 /** #endcond */
I solved this problem by moving my documentation from the .c file to the .h file. Then run doxygen only on the .h file.
Then the items that I want to document (the 'public' items) are intrinsically what doxygen picks up.
Because I have been previously careful to put 'public' items in the .h file and 'private' items in the .c file this works very well.
This technique came to mind when I noticed that doxygen was pulling in the includes. It struck me that if I were to also move the subset of includes that the calling module would need to use my module, then that list would be documented as well.
This technique has an additional benefit: I can put the documentation in one terminal window and the source in a different terminal window while updating the documentation.
Sometimes you may have a define which you want to document, but want doxygen to treat it differently (or even ignore it completely to avoid parsing errors).
For this you can define the #define in doxygen differently than in your sourcecode.
Example:
Some compilers allow variable linkage to specific segments, i.e.:
const int myvar # "segment_of_myvar_in_memory"=123;
=> doxygen would parse the "segment_of_myvar_in_memory" part as variable name which is not desired.
We could use a define for it:
#define __link_to_segment(name) # name
const int myvar __link_to_segment("segment_of_myvar_in_memory")=123;
If Preprocessing is active, Doxygen interprets our variable now as a function because of the function-like define using brackets..
But if we redefine our define within the Doxyfile, behaviour changes:
PREDEFINED = __link_to_segment(a)=
now the variable is parsed correctly as variable - also all types or keywords in front are correctly shown as keywords.
A nice side effekt:
In case you use 2 different IDEs with your code (one IDE for compiling&debugging, one for editing), you will also discover that some IDEs (i.e. Eclipse) have problems parsing variables with #"segment name". Using the approach above, you can redefine the __link_to_segment(name) there too:
#define __link_to_segment(name)
i.e. Eclipse will then show and parse the variable correctly, whereas the "compiling&debugging" IDE can still link the variable to its segment name.

Resources