Hello,
I'm using RTX and I'm porting my C code tot C++. Now I have a problem with os_tsk_create_user. I want to use a class method as the function for os_tsk_create_user :
Example::Example(void) {
mExampleTask = os_tsk_create_user (exampleTask, PRIORITY, mTaskStack, sizeof(mTaskStack)); }
__task void Example:: exampleTask(void) { ... }
error: #167: argument of type "void (Example::*)()" is incompatible with parameter of type "void (*)() C"
Casting the method:
mExampleTask = os_tsk_create_user ((void(*)())exampleTask, PRIORITY, mTaskStack, sizeof(mTaskStack)); error: #171: invalid type conversion
The only way to get it working is when I make my method static. But I'm using class variables in my task, so this is not what I want...
How do I get this working?
Regards,
Roland Beuker
Hi Roland,
yes, I also solved with static methods for initialization but... this is source of some concern. Something under the hood is going on and could lead to other problems later... (?)
Hello Marco,
I have similar problems with static variables... A work around possibility is to initialize these statics from your main with a static init() method...
I my own project I'll try to remove all dynamic content (never use new()). In this situation the the task start has to be moved from the constructor to it's own method (startTask()).
Roland
Hi,
I'm also using singleton technique (each singleton is a wrapper for a task) but I have a strange problem:
for SOME singleton classes (not all!) the mInstance static member is not NULL when the main begins (even if they are all correctly initialized like in the example above) As a result, the returned pointer is meaningless and the exceution goes into hardfault handler (even before creating the task, I have a ->Setup() method to launch). The linker map file seems ok, each one of them has allocated 4 bytes, is of Data type and there are no overlapping variables. Any idea ?
Like this :
Display.h
class Display { public: static Display *getInstance(void); protected: Display(void); private: static Display *mInstance; static void displayTaskEntry(Display *pDisplayPtr); OS_TID mDisplayTask; U64 mDisplayTaskStack[DISPLAY_TASK_STACK_SIZE]; void displayTask (void); };
Display.cpp
/*-----------------------------------------------------------*/ Display *Display::mInstance = NULL; /*-----------------------------------------------------------*/ Display::Display(void) { mDisplayTask = os_tsk_create_user_ex((void (*)(void *)) displayTaskEntry, DISPLAY_TASK_PRIORITY, mDisplayTaskStack, sizeof(mDisplayTaskStack), this); } /*-----------------------------------------------------------*/ Display *Display::getInstance() { if (!mInstance) { mInstance = new Display(); } return mInstance; } /*-----------------------------------------------------------*/ __task void Display::displayTaskEntry(Display *pDisplay) { pDisplay->displayTask(); } /*-----------------------------------------------------------*/ void Display::displayTask (void) { for (;;) { os_dly_wait (10); } } /*-----------------------------------------------------------*/
Robert Thanks!
Instead of the global function I'll use a static member variant (to hold the object oriented idea ;-)
The object is created using the singleton pattern (with lazy instantiation) so the OS is running before the call to tsk_create
Global function
void cpp_task_entry(Ctask_base *baseTask) { baseTask->run(); os_tsk_delete_self(); }
To create task (maybe in constructor, but it is not wise to call tsk_create before the OS is running) call os_tsk_create_user_ex
tid = os_tsk_create_user_ex( (void (*)(void *)) cpp_task_entry, prio, &stack, sizeof(stack), this);
example:
www.xs4all.nl/.../vxw_pt5.html
View all questions in Keil forum