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.
Related
I am just starting out with Segger Embedded Studio. Right now trying to call a function of a included header file. The file seems to be included since it shows up in the dependencies. For now I simply included the header and C-File in the project directory.
The included Header- and C-Files are simply:
//##### Header-File ######
#ifndef TEST_H_
#define TEST_H_
void printText(void);
#endif //TEST_H_
and:
//###### C-File #########
#include <test.h>
#include <stdio.h>
#include <stdlib.h>
void printText(void)
{
printf("Hello");
}
But when I try to call the printText Function in my main I get the error:
"Undefined Symbol: printText".
Why is the function not recognized?
"Undefined symbol" is a linker error. You are not linking the object code containing the definition of printText().
It is not an issue with the header file; including a header file does not cause the associated code to be linked - that is just the declaration so the compiler knows what the interface looks like. It is the linker than combines the separately compiled object code to form a program. You have not told the linker to use the object code containing printText(), and you have not told your IDE project to compile it to generate that object code.
The project tree clearly shows that only main.c is included in your project; you need to add the C file containing printText() too.
The concept of separate compilation and linking is what you need to grasp here.
Thank you Clifford for your answer. You are right I had some miss-conceptions about which files will be linked while building the project. In the special case of segger embedded studio there are, as I know by now, two ways to reference extern files.
Adding the files to the sources files folder is straight forward, but must be done separately for each project you want to use the respective files.
For frequently used files it is beneficial to create a dedicated library solution. Such a library can then be imported to any solution by choosing "add existing project". This will add all files of the library to your current solution (and show them in the project-tree). Now click the tab project -> dependencies. Your library should show up here. By acitivating the check box the linker will compile the referenced project upon builing your solution, allowing for the usage of your library functions.
Adding and linking library-project to a current solution
I'm facing a problem that I don't know how to solve.
Suppose the following typedef struct into a test.h header file:
typedef struct example_struct {
#ifdef CONFIG_A
int A;
#endif;
int B;
} example_struct_t;
I am compiling the code using this header file passing CONFIG_A to the GCC with -D option. This way I am able to include A member to the struct or remove if not needed for a given use case.
Now suppose I generate a shared library (.so) and I would like to distribute it. So, I have the .so library and the headers with precompiler directives. The problem is that I would like not to include the -DCONFIG_A in the program using the library, I mean, I would need to hold the options employed at the library compilation time not only in the source files (.c) but also in the header. That is to say, if a compile the library with -DCONFIG_A option I suppose that program using the library shouldn't include that option in compilation time.
Are the precompiled headers the solution for this problem or is there any other alternative (avoiding include a config.h header in every files defining precompiler directives)?
Thank you so much for the guidance.
You can "generate" the code for the structure definition and ship the generated definition alongside the corresponding library. One idea is to keep your structures in a header with no #includes, in which case you can run the C preprocessor on them to get a file with no #ifdefs (which you can then use to build and ship).
Another way is to do something special in your build system. For example CMake has #cmakedefine which you can use inside a C or C++ source file and then generate code from that.
I'm using the MPLAB IDE and the XC8 compiler for a C project for PIC18 devices. I'm building a project with multiple source files and don't know how to make the structure.
In the project, I have the following things:
A file main.c where the main code is located. From here, several files are included:
xc.h: to define chip-specific variables and so
stdlib.h, stdio.h, plib.h, delays.h: for the compiler's functions
enc28j60.h: a homebrew file with definitions and prototypes
A file enc28j60.c, where the functions of the prototypes in enc28j60.h go
I cannot compile enc28j60.c as standalone file because it depends on definitions in main.c.
I have a few questions on how to set this project up:
Should I add enc28j60.c to the source files of my MPLAB project? If I do this, MPLAB tries to compile the file, which fails. If I don't do this, the linker cannot find the symbols that are defined in enc28j60.c and prototyped in enc28j60.h.
Should I #include enc28j60.c from somewhere? If not, how does MPLAB know where to get the file?
Should I add enc28j60.h to the header files of my MPLAB project?
Should I #include enc28j60.h from somewhere? Right now, I do this in main.c, after the definitions enc28j60.h needs in order to run (and not throw #errors).
I managed to get this working by modifying my library and header files a bit.
At first, I added a file main.h where all the prototypes, #defines and #includes would go. Then, in every .h, file, I added this on top:
#ifndef SOME_LIB_IDENTIFIER // makes sure the lib only gets included once,
#define SOME_LIB_IDENTIFIER // has to be specific for every lib
#include "main.h" // to make sure everything's initialized (this line of course not in main.h)
And the last line of every .h file would be:
#endif
I added #include "enc28j60.h" to the top of the enc28j60.c file. This file now can be compiled.
In main.h, I added includes for xc.h, plib.h, stdlib.h, stdio.h and enc28j60.h. I nowhere included .c files.
I added both the main and enc28j60 header and source files to my MPLAB project. The source files get compiled well, both. The result is linked together.
In short
Add a main.h where all prototypes, #defines and #includes go
Add a header and footer to all your header file to make sure they're only included once. Also include main.h from these headers, to make sure every file uses the same definitions
Include a source file's corresponding .h file at the very first line of your source file. Do not include .c files
Add all header and source files (that are not built into the compiler) to your MPLAB project
Build (F10) should compile all files and link them together correctly
Don't include .c files. Include headers only. If you have declarations to be shared between files, put them in a separate header, and include that header whenever you need it.
After compiling each individual source file, link the resulting object files together. This involves the invocation of the compiler on all of the source files, then a one-time invocation of the linker on the object files (with supplemental libraries, etc.).
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.
I have a C project I'm importing to eclipse to work with. It was prewritten but not a C program, so I imported it as a C Makefile program. Actually for some reason the program was written with shell scripts which called the make in the appropriate directories, I added a Makefile that called the shell script, though I'll probably change it to use only make files.
Anyways the unusual thing is that I get exceptions on all the #define variables used in my C code. The variables are defined in a .h file which is included on the top of the C code, and the #include doesn't haev a warning. I can compile the code and run it without exception. Yet I still get dozens of errors where the #define values are used in the editor. The .h which defines the variables is in a different folder then the C code that throws the excception, but adding the folder with the .h into the C include path didn't do any good. Anyone know how I can get the editor to play nice with my #define variables?
Are you actually typing #DEFINE? It's supposed to be #define. C is case sensitive.
Here are some options to investigate the issue further:
Right-click your project in Eclipse, go to Properties -> C/C++ General -> Paths and Symbols -> Symbols. You can check the symbols defined there, maybe something is messing up the preprocessor there.
Add to your g++ command line the following option: -save-temps. This will output some intermediate compilation files. Check the .i or .ii files - these contain the preprocessed output. More information on this g++ option is here.
Also, it would be nice if you could give some more information about the actual errors/warnings.
How is the .h file included in the .c file?
#include <file.h>
or
#include "file.h"
These have different meanings in the preprocessor.
What is the error that you are getting? Is the .h file not found, causing the other errors?