Hallo zusammen,
hat hier jemand vielleicht Erfahrung mit der Erstellung von Tasks in
C++?
Leider bekomme ich das selbst nicht auf die Reihe...
Hier mal mein Code:
ioCtrl.cpp
1
/* INCLUDE FILES **************************************************************/
2
3
/* IMPORT */
4
#include"common.h"
5
//#include "TaskWrapper.h"
6
/* FreeRTOS */
7
8
#if defined(__cplusplus)
9
extern"C"{/* Make sure we have C-declarations in C++ programs */
10
#endif
11
12
#include"FreeRTOS.h"
13
#include"task.h"
14
#include"queue.h"
15
#include"timers.h"
16
17
#include"ioCtrl.h"
18
19
#if defined(__cplusplus)
20
}/* Make sure we have C-declarations in C++ programs */
21
#endif
22
23
/* EXPORT */
24
25
26
27
voidioCtrl::task(void)
28
{
29
vErrorMessage("Task is starting!",0,RADIX_NO_VALUE,0);
30
portTickTypexLastWakeTime;
31
xLastWakeTime=xTaskGetTickCount();
32
33
for(;;){
34
//debug_printf("TestTask[%d]\n", this->xtest);
35
vErrorMessage("Task is running!",0,RADIX_NO_VALUE,0);
Manuel Simmerl schrieb:> extern "C" void taskwrapper(void* parm) {> (static_cast<ioCtrl*>(parm))->task();> }
extern "C" inline void taskwrapper(void* parm) {
(static_cast<ioCtrl*>(parm))->task();
}
Das inline ist wichtig. Denn sonst erzeugst du in jedem Cpp-File,
welches dieses Header File includiert eine neue Funktion taskwrapper und
es setzt einen ....
> Bei dem extern "C" Aufruf bekomme ich folgende Fehlermeldung:> multiple definition of 'taskwrapper'
Edit:
Oder aber du ziehst die Funktion überhaupt in ioCtl.cpp hinein. Es gibt
ja so wie es aussieht, sowieso keinen Grund, warum die im Header File
sein sollte. Ist wahrscheinlich sowieso die bessere Lösung.
Super, danke für deine schnell Antwort.
Der Fehler ist weg.
Nur leider läuft der Task immer noch nicht...
Siehst du vielleicht einen weiteren Fehler im Code?
Viele Grüße
msimmerl
Hast du denn schon mal eine der mitgelieferten Demos probiert, studiert
und ein wenig abgeändert?
In der Demo-Übersicht seh ich zum Beispiel, dass man
vTaskStartScheduler();
aufrufen muss - erst dann laufen die Tasks.
Machst du das?
http://www.freertos.org/a00102.html
Mich macht zum Beispiel stutzig, dass du eine 0 für den Pointer zum
TaskHandle übergibst. Die Doku erwähnt nicht, dass dies zulässig ist.
Auch solltest du dir angewöhnen, ReturnCodes der Funktion aufzufangen
und auszuwerten. xTaskCreate liefert einen Code, ob die Funktion
geklappt hat oder nicht.
Und deine letzten beiden Parameter im Aufruf sind mir da ehrlich gesagt
etwas zuviel gecastet. Das sollte eigentlich nicht notwendig sein.
Die Funktionssignatur
http://www.freertos.org/a00125.html
lautet
1
portBASE_TYPE xTaskCreate(
2
pdTASK_CODE pvTaskCode,
3
const portCHAR * const pcName,
4
unsigned portSHORT usStackDepth,
5
void *pvParameters,
6
unsigned portBASE_TYPE uxPriority,
7
xTaskHandle *pvCreatedTask
8
);
da jetzt einfach eine 1 bzw eine 0 zu casten, ist meiner Meinung nach
etwas gewagt. Und wie gesagt: ob die 0 überhaupt zulässig ist .....
Manuel Simmerl schrieb:> xTaskCreate(&taskwrapper, (const signed char*)"Task", 240, NULL,> CONTROL_TASK_PRIORITY, &xHandle);
Wieso NULL?
Dieses Argument hier
xTaskCreate(&taskwrapper, (const signed char*)"Task", 240, NULL,
****
das ist das, welches die Funktion taskwrapper hier
extern "C" void taskwrapper(void* parm) {
*******
wieder bekommt!
Wie willst du denn einen NULL Pointer vernünftig
(static_cast<ioCtrl*>(parm))->task();
auf einen ioCtrl Pointer umcasten um damit dann die Memberfunktion
dieses Objektes aufzurufen?
(Hast du eigentlich schon mal probiert, ob diese Verteiler-Funktion
überhaupt aufgerufen wird?)
Aber abgesehen davon: Ich hab kein FreeRTOS da und auch keine Hardware
auf der ich das probieren könnte. D.h. ich muss mich da jetzt sowieso
verabschieden.
Erstmal vielen Dank für eure Hilfe.
Ich hätte schon versucht ob die Verteilerfunktion aufgerufen wird.
Leider wird der Wrapper nie aufgerufen.
Das mit NULL als Parameterübergabe beim Task erstellen müsste eigentlich
funktionieren. Zumindest wird das in der Doku, bei den Beispielen, auch
so gemacht.
Irgendwas muss noch am dem Wrapper falsch sein denke ich...
Manuel Simmerl schrieb:> Das mit NULL als Parameterübergabe beim Task erstellen müsste eigentlich> funktionieren.
Nein. Du dereferenzierst einen Nullzeiger. Wie Karl Heinz schon
geschrieben hat, wird das, was du da an xTaskCreate übergibst, als
Parameter an taskwrapper übergeben. Das heißt, param ist in taskwrapper
NULL und das dereferenzierst du dann hier:
1
(static_cast<ioCtrl*>(parm))->task();
> Zumindest wird das in der Doku, bei den Beispielen, auch so gemacht.
Wird da der Zeiger denn nacher auch benutzt, so wie bei dir?
Oder warum sollte das
Jetzt noch ein anderer Ansatz.
Den wrapper brauch ich ja nur wenn ich auf eine Methode der Klasse
verweisen möchte.
Jetzt mal für einen Versuch kann ich ja auch auf eine andere Methode
verweisen.
void test(void *parm)
{
vErrorMessage( "Task is starting!", 0, RADIX_NO_VALUE, 0 );
portTickType xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
for(;;) {
vErrorMessage( "Task is running!", 0, RADIX_NO_VALUE, 0 );
//Delay für 1000ms
vTaskDelayUntil(&xLastWakeTime, ( 1000 / portTICK_RATE_MS
) );
}
}
Nur komischerweise funktioniert nicht mal das....
Manuel Simmerl schrieb:> Jetzt noch ein anderer Ansatz.> Den wrapper brauch ich ja nur wenn ich auf eine Methode der Klasse> verweisen möchte.
Genau.
Weil du irgendwie die Kurve von der C Welt in die Welt der Objekte
kratzen musst. Und das geht halt nur dann, wenn man irgendeinen Verweis
auf ein Objekt hat.
> Jetzt mal für einen Versuch kann ich ja auch auf eine andere Methode> verweisen.
Weise Entscheidung.
Genau so macht man das: Wenn nichts geht - abspecken, vereinfachen - bis
man zum Kern des Problems vorstösst.
> Nur komischerweise funktioniert nicht mal das....
Womit wir wieder bei den Demos wären, die ja laut deiner Aussage
funktionieren.
Also: Was ist bei den Demos anders?
Das können durchaus auch irgendwelche Compiler-Einstellungen sein!
Was mir noch aufgefallen ist, dass ich lauter Warnungen bekomme:
Phase Linker starting
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0x10): warning: _close is not implemented and
will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x12): warning: _fstat is not implemented and
will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-signalr.o): In function `_getpid_r':
signalr.c:(.text._getpid_r+0x1): warning: _getpid is not implemented and
will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0x10): warning: _isatty is not implemented
and will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-signalr.o): In function `_kill_r':
signalr.c:(.text._kill_r+0x12): warning: _kill is not implemented and
will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x14): warning: _lseek is not implemented and
will always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libc.a(lib_
a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x14): warning: _read is not implemented and will
always fail
c:\renesas\hew\tools\kpit\gnurx-elf\v12.03\rx-elf\rx-elf\lib\libstdc++.a
(pure.o): In function `__cxa_pure_virtual':
pure.cc:(.text.__cxa_pure_virtual+0xc): warning: _write is not
implemented and will always fail
kann damit vielleicht jemand etwas anfangen?
Wieder mal ein klassischer Fall von: am Symptom 'rumgedoktort ;-)
Karl Heinz ist sicherlich davon ausgegangen, dass Du solche fatalen
Fehlermeldungen ganz sicher nicht (mehr) bekommst!
Eine Lösung habe ich da jetzt auch nicht zu, aber evtl. hilft die
Compiler, oder genauer: die libc-Doku dabei, diese Fehler zu beheben.
Dir fehlen die gesamten "reentrant functions", wie das bei der newlib in
der Regel auch der Fall ist. Aber evtl. hilft da auch irgend ein
Schalter, der die Verwendung abschaltet. Der newlib-Port für WinARM ist
lange her...
Viel Erfolg!