2016-04-13 5 views
1

Ich möchte eine Mitgliedsfunktion einer CPP-Klasse für eine FreeRTOS taskFunction verwenden.FreeRTOS CPP Function Pointer

Hier ist meine erste Lösung

#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 
} 

Jetzt ist mein Problem iSt, dass der Kontext in der Run-Funktion nicht das gleiche ist. Drucken der Speicherplatz von taskName unterscheidet innerhalb listen(...) und run(...)

Meine böse Verdacht besteht, dass ein static_cast der Run-Funktion macht die Klasse Kontext verliert? Liege ich falsch?

Gibt es eine andere Idee, einen statischen Funktionszeiger auf freeRTOS einer Klassenmitgliedsfunktion bereitzustellen?

Hier sind die fehlenden Funktionen. Die main und die sys_thread_new, die nur ein Wrapper ist.

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; 
} 
+0

Was ist mit dem Code werfen, wo Sie vermutlich das Objekt erstellen und rufen 'xTaskCreate() 'damit irgendwie? – Notlikethat

+0

Können Sie ein minimales Beispiel extrahieren? Insbesondere sind das Template-Zeug und die mehreren Dateien nicht notwendig. Fügen Sie auch nicht mehrere Bearbeitungsabsätze hinzu und überlassen Sie sie anderen, um die relevanten Informationen aus ihnen auszuwählen. Bereinigen Sie stattdessen Ihre Frage gemäß den Regeln der Website und machen Sie das Relevante offensichtlich. –

+0

Sry, aber ich wurde nach den fehlenden Abschnitten gefragt (wo das Objekt erstellt wurde und der xTaskCreate) und ich denke nicht, dass es viele Linien außerhalb des Bereichs gibt. – Pascal

Antwort

1

ich so etwas wie folgt verwenden:

class MyClass{ 
public: 
    static void run(void* pvParams){ 
     ((MyClass*)pcParams)->runInner(); 
    } 
    void runInner(){ 
     while (true){ 
      // TODO code here 
     } 
    } 
}; 

dann Zeiger auf ein Objekt übergeben, wenn Task erstellen

MyClass* x = new MyClass; 
xTaskCreate(MyClass::run, taskName, stackDepth, (void*) x, taskPrio, taskHandle); 

edit:

Angenommen, Sie möchten Vorlagen verwenden:

template<typename T> 
void run (T* p){ 
    ((T*)p)->run(); 
} 

class MyClass{ 
public: 
    void run(){ 
     while (true){ 
      // task code 
     } 
    } 
} 

dann die Aufgabe, die Schaffung

MyClass* x = new MyClass; 
xTaskCreate(run<MyClass>, taskName, stackDepth, x, taskPrio, taskHandle); 

Edit:

Sie müssen run zu (void (*)(void*))

xTaskCreate((void (*)(void*))run<MyClass>, taskName, stackDepth, x, taskPrio, taskHandle); 
+0

Ich werde versuchen, Ihre Lösung, aber warum xCreateTask sollte ein HttpServer-Objekt erwarten? Es ist meine Entscheidung etwas zu spezifizieren? Und das würde zu einem Argument von 'void run (void * httpServerObject) führen, oder? – Pascal

+0

Ich kann nicht bekommen, wonach Sie fragen, können Sie bitte versuchen, es noch einmal zu erklären oder ein Beispiel zu geben? – mausik