Defining task in C++ compiles but doesn...

sven-de wrote on Tuesday, May 17, 2011:

My setup: The GCC/Eclipse-Demo running on AT91SAM7X259

My aim: Using C++ within my tasks

My approach:
1. Rename main.c in main.cpp
2. add manual typecasting für the task-name in xTaskCreate by (const signed char*)
3. add extern “C” in front of vApplicationTickHook and the includes of my own header-files, which declare the task I’ve created
4. alter makefile to compile main.cpp with g++, the rest with gcc and link both with g++
So far so good, this compiles and runs as fine as before. My problems begin when trying to transform those files containing the tasks (used by by xTaskCreate in main.cpp) into C++ by moving the in the makefile from gcc to g++. The header-file (sandbox.h) looks like this.

#ifdef __cplusplus
extern "C" {
#endif
void vTaskLED(void *pvParameters);
#ifdef __cplusplus
}
#endif

While the definition in sandbox.cpp remains unchanged

void vTaskLED(void *pvParameters)
{
	for(;;)
	{
		// some PIN-toggling
		vTaskDelay(500);
	}
	vTaskDelete( NULL );
}

That’s all I did. Compiling works fine without warnings or errors, but the code just doesn’t run (no blinking LED ;-(. To get it working again I just move sandbox.cpp in my makefile back to gcc (though there are warnings about the file ending).

So apparently xTaskCreate has trouble digesting my task-functions when those are compiled with g++. I’m afraid I once again missed something obvious about making my C+±functions available to othe C-code. Can someone please give me a kick into the right direction.
And while we’re at it: Why don’t I get any hints from the compiler that something is wrong?

sven-de wrote on Tuesday, May 17, 2011:

I have to add, that after including the ifdef __cplusplus to my headers I removed the aforementioned extern “C” in front of the includes. This reduces my changes to the makefile and the header-file. Creating the task looks like this btw:

xTaskCreate(vTaskLED, (const signed char*)"SvenLED", 50, NULL, 1, NULL);

sven-de wrote on Wednesday, May 18, 2011:

Okay, I haven’t completely understodd how, but I managed to get it working with a dirty workaround. I wrote C-wrappers calling the C++ funtions. So xTaskCreate() now calls the Wrapper, defined in C, which in turn calls the real function/task, written in C++. The wrapper has void *pvParameters while the real function just has void. So I assume there’s the problem also mentioned in these two discussions, C++ being picky about the void*:
https://sourceforge.net/projects/freertos/forums/forum/382005/topic/3650507
https://sourceforge.net/projects/freertos/forums/forum/382005/topic/2502218

But the way I understand those threads I’m already doing what’s required to resolve this by using extern “C”. The wrappers shouldn’t be neccessary, also in those threads everbody gets nice compiler errors helping to identify the issue.

Since I don’t want to mess my project with all those wrappers (doubling the amount of files), I’d be really thankful for some hints on how to resolve this. I also refreshed my knowledge about void-pointers in C++, but don’t see what should be causing issues there.

richard_damon wrote on Thursday, May 19, 2011:

Technically, to pass a function pointer to a C function, the function should be declared extern “C”, note that does NOT require the wrapper header that you have been describing, but you can just declare the function like:

extern “C” void vTaskLed(void * parm) {
    for(;;){
    /* code goes here */
    }
}

sven-de wrote on Wednesday, May 25, 2011:

Hi Richard, many thanks for your reply.
Unfortunately it didn’t get me any further. Basically I had already done what you proposed but with separate declaration and definition. Now I’ve also merged those the way you suggested resulting in thise very bare example code which still doesn’t work.

extern "C" void vTaskDummy(void * param)
{
	AT91C_BASE_PIOA->PIO_PER = 1 << 9;
	AT91C_BASE_PIOA->PIO_OER = 1 << 9;
	for(;;)
	{
		AT91C_BASE_PIOA->PIO_CODR = 1 << 9;	// Einschalten
		vTaskDelay(100);
		AT91C_BASE_PIOA->PIO_SODR = 1 << 9;	// Ausschalten
		vTaskDelay(400);
	}
	vTaskDelete( NULL );
}
int main( void )
{
	prvSetupHardware();
	 xTaskCreate(vTaskDummy, (const signed char*)"Dummy", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
   
	vTaskStartScheduler();
  	return 0;
}

Keep in mind that this compiles fine but just doesn’t run on the target.  Unfortunately I’m not able to get my debugger running (which certainly isn’t related to this specific problem) but with the help of some LEDs I could figure out, that everything’s fine until vTaskStartScheduler() is called. From then on even interrupts aren’t working. That’s either because the global interrupts enable fails (within StartScheduler) or the target goes into some very deep limbo.

I’d still appreciate every help, those wrappers I’m using in the meantime are rather ugly.

richard_damon wrote on Wednesday, May 25, 2011:

One thing to check is that vTaskStartScheduler isn’t just returning due to a failure to set up the Idle task.

If you can’t get the debugger running, you may need to edit the FreeRTOS files to flag LEDs to see where things are dying.

stabilitronas wrote on Sunday, February 12, 2012:

Hello everyone.

Sorry for reviving an old thread, but it seems I have exactly the same problem. I am trying to weld together FreeRTOS, C++ and NXP Arm Cortex-M3 LPC1768 — with no success so far. I’ve got LPCXpresso4 IDE (so that’s GCC) and LPC-Link debugger.

FreeRTOS in a C project works just fine. Classes and other OO stuff in a C++ project also work just fine. However, FreeRTOs in a C++ project compiles succesfully, but simply does not work. Since I am a happy owner of the LPC-Link debugger, I was able to track the problem to:

void vPortStartFirstTask( void )
{
	__asm volatile(
					" ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */
					" ldr r0, [r0] 			\n"
					" ldr r0, [r0] 			\n"
					" msr msp, r0			\n" /* Set the msp back to the start of the stack. */
					" svc 0					\n" /* System call to start first task. */
				);
}

After that I immediately end up in SVCall_Handler exception handler. Any ideas?..

I’ve been seaching the internet for a few days now, but all I find is usually “I know a few guys using FreeRTOs in their C++ projects” or “In theory, it should work”. Not very helpful :slight_smile:

Thanks in advance.

rtel wrote on Sunday, February 12, 2012:

After that I immediately end up in SVCall_Handler exception handler. Any ideas?..

Well, that is exactly what is supposed to happen after you call SVC 0, question is, is it the FreeRTOS exception handler or the default one?  If it is not the FreeRTOS one, then it sounds like you have not populated the vector table.  If it is the FreeRTOS one, then what happens from there?

Regards.

stabilitronas wrote on Sunday, February 12, 2012:

Well, that is exactly what is supposed to happen after you call SVC 0, question is, is it the FreeRTOS exception handler or the default one? If it is not the FreeRTOS one, then it sounds like you have not populated the vector table. If it is the FreeRTOS one, then what happens from there?

It was the default one. I just changed default SVCall, PendSV and SysTick handlers to vPortSVCHandler, xPortPendSVHandler and xPortSysTickHandler and now it works! No wrappers, no workarounds, just FreeRTOs in C++ project.

That was such a trivial problem and solution. How did I missed it in documentation? It should be emphasized somehow…

Anyway, thanks, Richard!

vicharshunya wrote on Wednesday, January 01, 2014:

I am also trying to make FreeRTOS with main.cpp file.

First step where I stuck is how to compile FreeRTOS using gcc and main.cpp using g++ with Makefile. It would be of great help if someone has already made makefile which does this task.