When compiling code for the ARM Cortex-M1 using the Keil compiler, you may encounter an error saying “Symbol ferror multiply defined”. This error occurs when there are multiple conflicting definitions for the ferror symbol, resulting in a compile-time error. The ferror symbol refers to the standard C library function ferror(), which returns the error status of a file stream. This article will explain what causes this error and how to resolve it when using Keil and Cortex-M1.
What Causes the ferror Multiply Defined Error
The main reason you see the “ferror multiply defined” error is because the ferror symbol is defined in both the Keil RTX library and the standard C library. When you include both RTX.h and stdio.h headers in your code, you end up with two conflicting definitions of ferror().
Specifically, the Keil RTX real-time OS provides its own minimal implementation of some common C library functions, including ferror(). This is contained in the RTX_CM_lib.h header included by RTX.h. At the same time, the standard ferror() implementation resides in stdio.h.
So when the Keil compiler processes the two headers, it sees two incompatible versions of ferror() and rightly flags it as an error. You cannot have two different functions with the same name compiled into your program.
Solutions to Resolve the Multiply Defined Symbol Error
There are a couple ways to solve the “ferror multiply defined” problem when compiling with Keil:
1. Include Only One Header
The simplest solution is to include only one of the headers that defines ferror(). For example, you could remove the #include line, and only keep #include . This will eliminate the dual definition conflict. However, you would lose access to some other standard C library functions by removing stdio.h.
2. Use #define to Select Implementation
A cleaner approach is to use a #define macro to control which ferror() version is compiled into your program: #define USE_RTX_CM_LIB #include #include
Adding the #define before including the headers will make sure only the RTX version of ferror() gets compiled, avoiding the multiply defined error. Just remember to consistently #define USE_RTX_CM_LIB in all your code files.
3. Modify RTX_CM_lib.h Header
Alternatively, you can edit the Keil CMSIS RTX header file RTX_CM_lib.h directly. Look for the ferror() prototype and modify it to something like ferror_rtx() to avoid the naming clash with stdio.h’s ferror().
This will allow you to keep both headers, but you’ll have to update any calls to ferror() in your code to the new ferror_rtx() name.
Finding the Conflicting Declarations
When you get the “symbol multiply defined” error, it can be tricky to locate exactly where the two conflicting declarations are coming from in your sprawling project codebase.
One method is to do a recursive search through all header and source files for “ferror” to identify the locations. Alternatively, you can use the Keil compiler’s detailed error messages to pinpoint the specific files and line numbers involved in the redefinition. Knowing the exact conflicting declarations helps in resolving the issue cleanly.
Preventing Duplicate Symbol Errors
To avoid “multiply defined symbol” errors proactively when using Keil and Cortex-M:
- Be judicious about mixing RTX.h and stdio.h includes in source files
- Use header guards in your own headers to prevent double includes
- Declare functions and variables static when you want module-local scope
- Minimize global variables/functions and shared headers between files
- Include headers only in .c files, avoid header includes in other headers
Following best practices for C programming hygiene helps minimize the chance of duplicate symbol definitions cropping up and causing problems down the line.
Conclusion
“Symbol ferror multiply defined” errors when using Keil and Cortex-M1 stems from the conflict between the RTX and standard C library versions of ferror(). You can resolve it by selectively including only one header, using a macro to choose the implementation, or modifying the RTX header itself. Identifying the exact duplicate symbol declarations also helps in addressing the problem. With a bit of awareness around header file usage, you can avoid these frustrating multiply defined symbol issues during Cortex-M development.