I want to use a member function of a CPP Class for a FreeRTOS taskFunction.
Here is my initial solution
#ifndef TaskCPP_H
#define TaskCPP_H
#include "FreeRTOS.h"
#include "task.h"
template<typename T>
class TaskBase {
protected:
xTaskHandle handle;
void run() {};
public:
static void taskfun(void* parm) {
static_cast<T*>(parm)->run();
#if INCLUDE_vTaskDelete
vTaskDelete(static_cast<T*>(parm)->handle);
#else
while(1)
vTaskDelay(10000);
#endif
}
virtual ~TaskBase() {
#if INCLUDE_vTaskDelete
vTaskDelete(handle);
#endif
return;
}
};
#endif /* __TaskCPP_H__ */
#ifndef HTTPSERVER_H_
#define HTTPSERVER_H_
#include "TaskBase.h"
#include <string.h>
#include "lwip/opt.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "lwip/api.h"
#include "lwip/ip_addr.h"
class HttpServer;
class HttpServer : public TaskBase<HttpServer> {
public:
HttpServer();
virtual ~HttpServer();
void run();
void listen(ip_addr *address, uint8_t port);
void print();
protected:
char taskName[50];
ip_addr address;
uint8_t port;
};
#endif /* HTTPSERVER_H_ */
#include "HttpServer.h"
HttpServer::HttpServer()
{
}
void HttpServer::listen(ip_addr *address, uint8_t port) {
char buf[16];
sprintf(taskName, "%s_%d\r\n", ipaddr_ntoa_r(address, buf, 16), port);
DEBUGOUT("ADDRESS Listen: %x\r\n", &taskName);
this->handle = sys_thread_new(this->taskName, &taskfun, NULL, DEFAULT_THREAD_STACKSIZE + 128, DEFAULT_THREAD_PRIO);
}
void HttpServer::run() {
while(1) {
print();
Board_LED_Toggle(LEDS_LED2);
vTaskDelay(configTICK_RATE_HZ / 14);
}
}
void HttpServer::print() {
DEBUGOUT("ADDRESS Listen: %x\r\n", &taskName);
}
HttpServer::~HttpServer() {
// TODO Auto-generated destructor stub
}
Now my Problem ist that the context is not the same inside the run function. Printing the memory location of taskName
is different inside listen(...)
and run(...)
My nasty suspicion is that doing a static_cast of the run function looses the class context? Am I wrong?
Is there any other idea to provide a static function pointer to freeRTOS of a Class member function?
Here are the missing functions. The main
and the sys_thread_new
which is a wrapper only.
int main(void) {
prvSetupHardware();
HttpServer server;
server.listen(IP_ADDR_ANY, 80);
/* Start the scheduler */
vTaskStartScheduler();
/* Should never arrive here */
return 1;
}
sys_thread_t sys_thread_new( const char *pcName, void( *pxThread )( void *pvParameters ), void *pvArg, int iStackSize, int iPriority )
{
xTaskHandle xCreatedTask;
portBASE_TYPE xResult;
sys_thread_t xReturn;
xResult = xTaskCreate( pxThread, ( signed char * ) pcName, iStackSize, pvArg, iPriority, &xCreatedTask );
if( xResult == pdPASS )
{
xReturn = xCreatedTask;
}
else
{
xReturn = NULL;
}
return xReturn;
}