Manual CubeMX C to C++ project conversion fails when including FreeRTOS - c++

Toolchain is the SW4STM32, gcc, processor is STM32F303K8 (Nucleo 303K8), minimal test project with no actual user code at all.
The process how to convert a project generated by ST CubeMX is well documented and apparently works. However, when i specify FreeRTOS in Cube, linker fails to find the init function MX_FREERTOS_Init(). The function prototype is included in main.cpp and the definition exists in another source file (freertos.c). This works in C but when converting the project to C++ the linker fails to link the function.
The C2C++ conversion i did as follows:
add ccnature to the .project file
copy main.c to main.cpp (& remove main.c from the build)
duplicate gcc compiler settings over to g++ in project properties
point linker script to the one in the project directory
The above enable Eclipse to compile main using g++ and to link using G++ linker. However linking consistently fails in ...\Debug/../Src/main.cpp:97: undefined reference to `MX_FREERTOS_Init()'
What is remarkable is that even when i delete all references to MX_FREERTOS_Init() from main.cpp so that the text simply does not exist anywhere, linker STILL fails exactly the same. It even reports the same line number even though the text is completely different. This behavior does not change never mind if i clean the project, rebuild and refresh all indexes etc etc.
Any suggestions anyone? Or do i have to skip specifying FreeRTOS in Cube and do it all manually?

I have the same question using atollic for stm32,
solved by adding extern "C" to main.cpp
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config();
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
#ifdef __cplusplus
}
#endif
/* USER CODE END PFP */

I have faced with the same issue.
So, I would like to suggest renaming freertos.c file to freertos.cpp.

I would suggest a C++ RTOS for example the free disortos. (Google it)

Related

Why use preprocessor #if statements instead of if() else?

I see this being done all the time for example in the Linux Kernel. What is the purpose of using the preprocessor commands vs just normal C++ if else block? Is there a speed advantage or something?
A preprocessor changes the C/C++ code before it gets compiled (hence pre processor).
Preprocessor ifs are evaluated at compile-time.
C/C++ ifs are evaluated at run-time.
You can do things that can't be done at run-time.
Adjust code for different platforms or different compilers:
#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif
Ensure header file definitions are included only once (equivalent of #pragma once, but more portable):
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example { ... };
#endif
You can make things faster than at run-time.
void some_debug_function() {
#ifdef DEBUG
printf("Debug!\n");
#endif
}
Now, when compiling with DEBUG not defined (likely a command line parameter to your compiler), any calls to some_debug_function can be optimized away by the compiler.
Preprocessor is run before the compilation pass, so the compiler won't even see anything that was in the not-taken #if branch.
#if DEBUG
int a;
#else
double b;
#endif
gcc -c -DDEBUG=1 file.c will see "int a"
gcc -c file.c will see "double b"
Preprocessor allows you to actually cut out or paste in to your source file, code to be compiled. If its cut out, its gone, its like a comment, does nothing, is not compiled, produces no code in the binary. Devs will often use this technique to add code only in debug build for debugging purposes or for adding or excluding code for specific operating systems.

Chain of C libraries into C++

I have a very trivial problem including a chain of C libraries into a C++ main project. I've experience with C but it's the first time that I'm programming in C++.
The structure of the project is a single folder with inside:
main.cpp
Mylib_1.c
Mylib_1.h
Mylib_2.c
Mylib_2.h
main calls -> Mylib_1.h that calls -> My_lib2.h
//main.cpp
#include "Mylib_1.h"
//Mylib_1.h
#include "Mylib_2.h"
main contains both Mylib_1 and Mylib_2 functions and typedef structs
Mylib_1 uses typedef structs and functions of Mylib_2
Everything inside each Mylib_x.h is wrapped between extern "C", like this:
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
#ifdef __cplusplus
extern "C" {
#endif
mycode
#ifdef __cplusplus
}
#endif
#endif
But when I try to compile it with eclipse kepler on Ubuntu 12.04 x64, I get:
Mylib_1.h error: Mylib_2_type_t does not name a type
main.cpp error: Mylib_2_function1 was not declared in this scope
...
Only the above sections are marked as error in eclipse, the header looks included fine.
Furthermore according to eclipse, the __cplusplus flag is false into Mylib_2.h but true into Mylib_1.h
Thinking of some eclipse error, I've tried to manually build the project via g++ (v4.6.3) but I got the same exact problem when I've tried to link the libraries .o with the main.cpp
Seems stupid but I can't figure out what could it be. Any suggestion?
Thank you
Have you checked that your lines
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
are really different for the two files,
e.g. _MYLIB1_H and _MYLIB2_H?

Creating shared and static libraries using g++ (under Windows)

How do I create static and dynamic libraries for Windows using g++?
I've found a few commands for Linux for creating .so files and I've tried to apply them on a Windows shell, but they build .dll files that my applications fail to link with at runtime.
I've only managed to build .dll files using Visual C++ but I would like to build them manually on the command line, preferably using g++. I would also like to know how to build static libraries too for Windows.
You need to prefix with the attribute :
__declspec(dllexport)...
all the features you want to expose.
See this.
Example for a C function:
__declspec(dllexport) int __cdecl Add(int a, int b)
{
return (a + b);
}
This can be simplified using MACROS: everything is explained on this helpful page.
For C++ classes, you only need to prefix each class (not every single method)
I usually do it that way :
Note : The following also ensures portability...
Include File :
// my_macros.h
//
// Stuffs required under Windoz to export classes properly
// from the shared library...
// USAGE :
// - Add "-DBUILD_LIB" to the compiler options
//
#ifdef __WIN32__
#ifdef BUILD_LIB
#define LIB_CLASS __declspec(dllexport)
#else
#define LIB_CLASS __declspec(dllimport)
#endif
#else
#define LIB_CLASS // Linux & other Unices : leave it blank !
#endif
Usage :
#include "my_macros.h"
class LIB_CLASS MyClass {
}
Then, to build, simply :
Pass the option -DBUILD_LIB to the usual compiler command line
Pass the option -shared to the usual linker command line

GCC cross-compiler for VxWorks can't compile C++

I'm trying to port a Linux library to run on VxWorks. I have successfully built binutils and gcc to target i486-wrs-vxworks and I can successfully build a simple C program. However, when I try to compile C++, things break.
I have a simple Hello World program:
#include <string>
#include <iostream>
int main()
{
std::string s = "Hello World";
std::cout << s << std::endl;
return 0;
}
To build it, I call:
i486-wrs-vxworks-gcc -I/home/kyle/vxworks-6.9/target/usr/h -I/home/kyle/vxworks-6.9/target/usr/h/c++ hello.cpp
This always fails with the message:
In file included from /home/kyle/vxworks-6.9/target/usr/h/c++/cerrno:4:0,
from /home/kyle/vxworks-6.9/target/usr/h/c++/xlocnum:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ios:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/ostream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/istream:4,
from /home/kyle/vxworks-6.9/target/usr/h/c++/string:4,
from hello.cpp:1:
/usr/local/lib/gcc/i486-wrs-vxworks/4.6.4/../../../../i486-wrs-vxworks/include/yvals.h:4:24: fatal error: yvals.h: No such file or directory
If I go look inside /usr/local/i486-wrs-vxworks/include/yvals.h, this is what I see:
/* yvals.h values header for conforming compilers on various systems */
#if (defined(__cplusplus) && defined(__GNUC__))
/* GCC C++ has it's own yvals.h */
#include_next <yvals.h>
#else /* __cplusplus && __GNUC__ */
#ifndef _YVALS
#define _YVALS
#ifdef _NO_WINDRIVER_MODIFICATIONS
#include <stdarg.h>
#endif
...
It appears that there is another yvals.h that needs to be included, but I can't find it anywhere. Did I just fail at building gcc correctly, or is there a way to fix this?
Which version of VxWorks are you using for this?
I have a fuzzy recollection that when upgrading VxWorks versions in the past there was a syntax error in yvals.h that was I needed to work around and it was fixed in a subsequent version.
Also, you can get the gcc cross compiler pre-built from WindRiver. Just login to windriver.com/support with your licence number and head to "Downloads" for your product version.
I went through a recent cross compiling nightmare myself (not VxWorks related) except that instead of yvals.h, I was having grief with stddef.h. The problem turned out to be that I needed to specify the include paths for the system header files.
Here are the steps it took me to solve my error messages. Feel free to modify as appropriate.
Create a file foo.c
#include <stddef.h> /* The problem header file (yvals.h for you?) */
int main (void) {
return 0;
}
Compile it with your compiler of choice
$(CC) foo.c -E
Note the include paths it uses and set them as your system header file list using the
-isystem <include path>
option.
Hope this helps.

Error with bc++ and glut

This code compiles fine in Vc++ but in borland c++ gives me this error.. The code has no syntax errors and works fine.. Seems like there is a problem with the header.. But these are the standard headers and library files
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
main.c:
Error E2337 c:\Borland\Bcc55\include\glut\glut.h 146: Only one of a set of verloadedfunctions can be "C"
The error is due to overloaded functions being treated like C-language functions. Because the language "C" has no overloading it can only have one function of a given name. Apparently GLUT has a function that has the same name as some other function in the program. This may be your own function (just check the glut.h line (146 or thereabouts) to see if you've duplicated a name. Your main.c is a "C" program so this will force C-language compilation (unless you've forced C++ compilation with a command line switch). You might try renaming your code to "main.cpp" and recompiling.
Another possibility is the DEFINES are not set up to include GLUT properly and GLUT itself is trying to define overloaded functions with the same name. This is probably pretty unlikely as I think that GLUT is compile-able in "C".
Here's a piece of code that will force the error so you can see why it happens. Just switch the commenting around on the second "somefunc" subroutine. Save this code as C++ (ie. myfile.cpp).
//
// Program myfile.cpp
//
#include <stdio.h>
extern "C" float somefunc(int a) { return(a); };
// Un-comment one of the following two lines.
extern "C" float somefunc(float a) { return(a); }; // This line should produce the error.
// float somefunc(float a) { return(a); }; // This line should compile.
void main(void){
printf("Hello World!\n");
}
Good luck,
/Alan