Victor

Using FreeRtos C++ wrapper with uGFX

6 posts in this topic

I use C++ wrapper for FreeRTOS. uGFX implements some inner functions ( like gfxSleepMilliseconds, gfxSemInit, gfxYield, etc) wrapping pure C FreeRTOS functions in gos_freertos.h/c files. 

How I can use my C++ FreeRTOS wrapper with uGFX? 

Share this post


Link to post
Share on other sites

Hello Victor,

If it's a true C++ wrapper then that means that the C interface should still be accessible. Therefore, the current FreeRTOS support should still work perfectly fine for you and you'd probably just encounter a build issue.

If the C functions are not accessible then the easiest way would be to create a new GOS port for FreeRTOS C++ (so you'd create gos_freertos_cpp.h/c) and use the FreeRTOS C++ interface in there. Optionally you could keep using the existing gos_freertos.h/c file and just add a macro to the configuration file which is something like GFX_FREERTOS_USE_CPP and in the existing port you'd use #if and #else to add your new FreeRTOS C++ wrapper code along the existing C one.

I hope that helps.

Share this post


Link to post
Share on other sites

Hello Joel,

Yes. C interface is accessible, but don't correlate with C++ instance of FreeRTOS. Build without problems but when uGFX using FreeRTOS functions HardFaultHandler occurs as was expected.

I tryed to replace original gos_freertos.h/c to my gos_freertos.h/cpp. It seems to me, builder apply C compiler to them. C compeler don't know these keywords like class, etc. I don't know, can I use functions declared as C functions and defined with C++, if I have correctly explained.

As the result files, are something like these ( please excuse me for barbarism) :

P.S. At the begining I compiled these files isolated with C++ compiler, and had been build well. But when I tryed to replace(and embed) original uGFX files, compiler began to sware to C++ lexis in my FreeRTOS wrapper. (excuse me for my english)

my gos_freertos.h

/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */

/**
 * @file    src/gos/gos_freertos.h
 * @brief   GOS - Operating System Support header file for FreeRTOS.
 */

#ifndef _GOS_FREERTOS_H
#define _GOS_FREERTOS_H

#if GFX_USE_OS_FREERTOS

//#include "FreeRTOS.h"
//#include "FreeRTOSConfig.h"
//#include "semphr.h"
//#include "task.h"

#include "frtosWrapper.h"


/*===========================================================================*/
/* Type definitions                                                          */
/*===========================================================================*/

/* Additional types are required when FreeRTOS 7.x is used */
#if !defined(tskKERNEL_VERSION_MAJOR) && !tskKERNEL_VERSION_MAJOR == 8
	typedef signed char					int8_t
	typedef unsigned char				uint8_t
	typedef signed int					int16_t
	typedef unsigned int				uint16_t
	typedef signed long int				int32_t
	typedef unsigned long int			uint32_t
	typedef signed long long int		int64_t
	typedef unsigned long long int		uint64_t
#endif

/**
 * bool_t,
 * int8_t, uint8_t,
 * int16_t, uint16_t,
 * int32_t, uint32_t,
 * size_t
 * TRUE, FALSE
 * are already defined by FreeRTOS
 */
#define TIME_IMMEDIATE		0
#define TIME_INFINITE		((delaytime_t)-1)
typedef int8_t				bool_t;
typedef uint32_t			delaytime_t;
typedef portTickType		systemticks_t;
typedef int32_t				semcount_t;
typedef void				threadreturn_t;
typedef portBASE_TYPE		threadpriority_t;

#define MAX_SEMAPHORE_COUNT	((semcount_t)(((unsigned long)((semcount_t)(-1))) >> 1))
#define LOW_PRIORITY		0
#define NORMAL_PRIORITY		configMAX_PRIORITIES/2
#define HIGH_PRIORITY		configMAX_PRIORITIES-1

/* FreeRTOS will allocate the stack when creating the thread, so pass the size instead of a working area */
#define DECLARE_THREAD_STACK(name, sz)			size_t *name = (size_t *)sz
#define DECLARE_THREAD_FUNCTION(fnName, param)	threadreturn_t fnName(void *param)
#define THREAD_RETURN(retval)

portTickType MS2ST(portTickType ms);  //Ok

//typedef struct {
//	xSemaphoreHandle	sem;
//	semcount_t			limit;
//	semcount_t  		counter;
//} gfxSem;

typedef struct {
  tSemaphoreHandle  sem;  //  xSemaphoreHandle  sem;
  semcount_t      limit;
  semcount_t      counter;
} gfxSem;

//typedef xSemaphoreHandle    gfxMutex;
//typedef xTaskHandle*        gfxThreadHandle;

typedef tSemaphoreHandle    gfxMutex;     //typedef xSemaphoreHandle    gfxMutex;
typedef tTaskHandle*        gfxThreadHandle;   //typedef xTaskHandle*        gfxThreadHandle;

/*===========================================================================*/
/* Function declarations.                                                    */
/*===========================================================================*/

//#ifdef __cplusplus
//extern "C" {
//#endif

//#define gfxHalt(msg)				{}
//#define gfxExit()					{}
//#define gfxAlloc(sz)				pvPortMalloc(sz)
//#define gfxFree(ptr)				vPortFree(ptr)
//#define gfxYield()					taskYIELD()
//#define gfxSystemTicks()			xTaskGetTickCount()
//#define gfxMillisecondsToTicks(ms)	MS2ST(ms)
//#define gfxSystemLock()				{}
//#define gfxSystemUnlock()			{}


#define gfxHalt(msg)        {}
#define gfxExit()         {}
//#define gfxAlloc(sz)       oRTOS.Malloc(sz)  //pvPortMalloc(sz)
//#define gfxFree(ptr)       oRTOS.Free(ptr) //vPortFree(ptr)
//#define gfxYield()         oRTOS.TaskYield() //taskYIELD()
//#define gfxSystemTicks()   oRTOS.TaskGetTickCount() //xTaskGetTickCount()

void* gfxAlloc(size_t size);
void gfxFree( void* p );
void gfxYield(void);
TickType_t gfxSystemTicks(void);


#define gfxMillisecondsToTicks(ms)  MS2ST(ms)
#define gfxSystemLock()       {}
#define gfxSystemUnlock()     {}

//void gfxMutexInit(xSemaphoreHandle* s);
//#define gfxMutexDestroy(pmutex)		vSemaphoreDelete(*pmutex)
//#define gfxMutexEnter(pmutex)		xSemaphoreTake(*pmutex,portMAX_DELAY)
//#define gfxMutexExit(pmutex)		xSemaphoreGive(*pmutex)

void gfxMutexInit(tSemaphoreHandle* s);//Ok
void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz); //Ok
void gfxSleepMilliseconds(delaytime_t ms); //Ok
void gfxSleepMicroseconds(delaytime_t ms); //Ok

void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit); //Ok
void gfxSemDestroy(gfxSem* psem);  //Ok
bool_t gfxSemWait(gfxSem* psem, delaytime_t ms); //Ok
bool_t gfxSemWaitI(gfxSem* psem);  //Ok
void gfxSemSignal(gfxSem* psem);  //Ok
void gfxSemSignalI(gfxSem* psem); //Ok
#define gfxSemCounterI(psem)		((psem)->counter)
#define gfxSemCounter(psem)			((psem)->counter)
gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param);//Ok

#define gfxThreadWait(thread)		{} // never used, not imlpemented
#define gfxThreadMe()				{} // never used, not implemented
#define gfxThreadClose(thread)		{}

//#ifdef __cplusplus
//}
//#endif

#endif /* GFX_USE_OS_FREERTOS */
#endif /* _GOS_FREERTOS_H */

 

my gos_freertos.cpp

/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */
#include "../../gfx.h"
#include <string.h>

#if GFX_USE_OS_FREERTOS

extern cRTOS oRTOS;   //global instance of FreeRTOS


#if INCLUDE_vTaskDelay != 1
	#error "GOS: INCLUDE_vTaskDelay must be defined in FreeRTOSConfig.h"
#endif

#if configUSE_MUTEXES != 1
	#error "GOS: configUSE_MUTEXES must be defined in FreeRTOSConfig.h"
#endif

#if configUSE_COUNTING_SEMAPHORES != 1
	#error "GOS: configUSE_COUNTING_SEMAPHORES must be defined in FreeRTOSConfig.h"
#endif

void _gosInit(void)
{
	#if !GFX_OS_NO_INIT
		#error "GOS: Operating System initialization for FreeRTOS is not yet implemented in uGFX. Please set GFX_OS_NO_INIT to TRUE in your gfxconf.h"
	#endif
	#if !GFX_OS_INIT_NO_WARNING
		#warning "GOS: Operating System initialization has been turned off. Make sure you call vTaskStartScheduler() before gfxInit() in your application!"
	#endif
}

void _gosDeinit(void)
{
}

void* gfxRealloc(void *ptr, size_t oldsz, size_t newsz)
{
	void *np;

	if (newsz <= oldsz)
		return ptr;

	np = gfxAlloc(newsz);
	if (!np)
		return 0;

	if (oldsz) {
		memcpy(np, ptr, oldsz);
		oRTOS.Free(ptr);//vPortFree(ptr);
	}

	return np;
}

//#define gfxAlloc(sz)       oRTOS.Malloc(sz)  //pvPortMalloc(sz)
//#define gfxFree(ptr)       oRTOS.Free(ptr) //vPortFree(ptr)
//#define gfxYield()         oRTOS.TaskYield() //taskYIELD()
//#define gfxSystemTicks()   oRTOS.TaskGetTickCount() //xTaskGetTickCount()

void* gfxAlloc(size_t size)
{
  return oRTOS.Malloc(size);
}

void gfxFree( void* p )
{
  oRTOS.Free(p);
}

void gfxYield(void)
{
  oRTOS.TaskYield();
}

TickType_t gfxSystemTicks(void)
{
  return oRTOS.TaskGetTickCount();
}

void gfxSleepMilliseconds(delaytime_t ms)
{
	const portTickType ticks = ms / portTICK_PERIOD_MS;
	oRTOS.taskDelay(ticks); //vTaskDelay(ticks);
}

void gfxSleepMicroseconds(delaytime_t ms)
{
	const portTickType ticks = (ms / 1000) / portTICK_PERIOD_MS;

	// delay milli seconds
	oRTOS.taskDelay(ticks); //vTaskDelay(ticks);

	// microsecond resolution delay is not supported in FreeRTOS
	// vUsDelay(ms%1000);
}

portTickType MS2ST(portTickType ms)
{
	return (ms / portTICK_PERIOD_MS);
}

void gfxMutexInit(tSemaphoreHandle *s)
{
	//*s = xSemaphoreCreateMutex();
	*s = oRTOS.SemaphoreCreateMutex();
	#if GFX_FREERTOS_USE_TRACE
	//	vTraceSetMutexName(*s,"uGFXMutex"); // for FreeRTOS+Trace debug
  #warning "FreeRTO + Trace not wrapped"
	#endif
}

void gfxSemInit(gfxSem* psem, semcount_t val, semcount_t limit)
{
	if (val > limit)
		val = limit;

	psem->counter = val;
	psem->limit = limit;
	psem->sem = oRTOS.CountingSemCreate(limit,val);//psem->sem = xSemaphoreCreateCounting(limit,val);

	#if GFX_FREERTOS_USE_TRACE
	//	vTraceSetSemaphoreName(psem->sem, "uGFXSema"); // for FreeRTOS+Trace debug
    #warning "FreeRTO + Trace not wrapped"
	#endif
}

void gfxSemDestroy(gfxSem* psem)
{
  oRTOS.SemaphoreDelete(psem->sem);//vSemaphoreDelete(psem->sem);
}

bool_t gfxSemWait(gfxSem* psem, delaytime_t ms)
{
	psem->counter--;

	if (oRTOS.SemTake(psem->sem, MS2ST(ms)) == pdPASS) //if (xSemaphoreTake(psem->sem, MS2ST(ms)) == pdPASS)
		return TRUE;

	psem->counter++;

	return FALSE;
}

bool_t gfxSemWaitI(gfxSem* psem)
{
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	psem->counter--;

	if (oRTOS.SemTakeFromISR(psem->sem,&xHigherPriorityTaskWoken) == pdTRUE)//if (xSemaphoreTakeFromISR(psem->sem,&xHigherPriorityTaskWoken) == pdTRUE)
		return TRUE;

	psem->counter++;

	return FALSE;
}

void gfxSemSignal(gfxSem* psem)
{
  oRTOS.EnterCritical();//taskENTER_CRITICAL();

	if (psem->counter < psem->limit) {
		psem->counter++;
		oRTOS.SemGive(psem->sem);//xSemaphoreGive(psem->sem);
	}

	oRTOS.BranchToSheduler();//taskYIELD();
	oRTOS.ExitCritical();//taskEXIT_CRITICAL();
}

void gfxSemSignalI(gfxSem* psem)
{
	portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

	if (psem->counter < psem->limit) {
		psem->counter++;

		oRTOS.SemGiveFromISR(psem->sem,&xHigherPriorityTaskWoken);//xSemaphoreGiveFromISR(psem->sem,&xHigherPriorityTaskWoken);
	}
}

gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param)
{
 // xTaskHandle task = NULL;
  tTaskHandle* task = NULL;
	stacksz = (size_t)stackarea;

	if (stacksz < configMINIMAL_STACK_SIZE)
		stacksz = configMINIMAL_STACK_SIZE;

	//if (xTaskCreate(fn, "uGFX_TASK", stacksz, param, prio, &task )!= pdPASS) {
	if (oRTOS.TaskCreate(fn, "uGFX_TASK", stacksz, param, prio, task )!= pdPASS) {
		for (;;);
	}

	return  task;
}

#endif /* GFX_USE_OS_FREERTOS */

 

Share this post


Link to post
Share on other sites

Hello Victor,

Mixing C++ and C code is not always as trivial as it looks. There are always some nasty things to keep in mind like not including C headers after C++ headers and similar things. Inclusion order matters here.
You indeed have to create a C++ file for your FreeRTOS port. In that, you can declare your C functions (the ones required by GOS) and the linker will be able to link them properly. There are other things you have to keep in mind like encapsulating your function prototypes in the extern "C" blocks:

#ifdef __cplusplus
extern "C" {
#endif

  ...

#ifdef __cplusplus
}
#endif

I can't have a closer look at your files right now (and I can't try it) but I've attached a GOS port that I wrote some time ago that allows using µGFX inside of a Qt application. The Qt stuff is all C++ as well just like your FreeRTOS C++ wrapper. Have a look at those files. Maybe that helps:

Note that I wrote a simple wrapper class around the QThread class because the QThread class doesn't offer certain things that are required. I assume that the FreeRTOS C++ wrapper won't require that workaround.

Please don't hesitate to ask if you have any other questions. We're happy to help where ever we can. Just currently on the road so not much I can do right now.

Share this post


Link to post
Share on other sites

If the c freerros functions are available then it should all just work when you use the c++ wrapper for other freertos calls. The hardfault that you got is likely related to something else. Debug that first before going to the trouble of writing a probably unneeded cpp freertos gos port.

Share this post


Link to post
Share on other sites

Yes indeed. Otherwise it's just not a wrapper. A C++ wrapper wouldn't do anything other than calling the equivalent C functions.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now