Transferring data between different tasks in MOD54415

Discussion to talk about software related topics only.
Post Reply
nicobari
Posts: 110
Joined: Mon Jan 30, 2012 12:15 pm

Transferring data between different tasks in MOD54415

Post by nicobari »

Hi,
Is there a way to transfer data between two separate task in MOD54415 without defining global variables?

Regards,
TM
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

Re: Transferring data between different tasks in MOD54415

Post by sulliwk06 »

Well since tasks operate on their own stack, I think the only way you could share anything between them is with a global.

Are you trying to avoid using global variables for any particular reason?


Edit:
On second thought, I suppose you could use GetUserParameters() and SaveUserParameters() in each task.
nicobari
Posts: 110
Joined: Mon Jan 30, 2012 12:15 pm

Re: Transferring data between different tasks in MOD54415

Post by nicobari »

Hi,
Thanks for the reply. The reason I want to avoid global variables is because my code is already huge and it might be difficult for me to track an error associated with global variable. Thanks for the updated reply. I will look into that too.

Thanks,
TM
User avatar
Chris Ruff
Posts: 222
Joined: Thu Apr 24, 2008 4:09 pm
Location: topsail island, nc
Contact:

Re: Transferring data between different tasks in MOD54415

Post by Chris Ruff »

I have used mailboxes. in the programmer's manual or the OS manual
In this manner you can synchronize as well as transfer information.
Chris
Real Programmers don't comment their code. If it was hard to write, it should be hard to understand
User avatar
dciliske
Posts: 624
Joined: Mon Feb 06, 2012 9:37 am
Location: San Diego, CA
Contact:

Re: Transferring data between different tasks in MOD54415

Post by dciliske »

Similar to Chris's suggestion, I would point you to OS_FIFO, OS_Q (os queue), or (as Chris said) OS_MBOX (mailbox). You probably want OS_Q or OS_MBOX, as those structures contain their own storage for the transferred data. OS_Q has the advantage that multiple items can be queued without overwriting the first one, while OS_MBOX can only store a single entry.

-Dan
Dan Ciliske
Project Engineer
Netburner, Inc
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Transferring data between different tasks in MOD54415

Post by tod »

I typically use the MailBox feature along with a semaphore to protect the data. I'm not sure what Dan means by
those structures contain their own storage for the transferred data.
I tend to send a pointer to a data buffer. There is storage for the pointer but AFAIK there is not storage for the buffer being pointed to. If there is storage for any of these OS features it isn't well documented and I don't see how it could even work given there is no information passed about the size of the structures pointed to. Maybe Dan can clarify as I'm sure he's much more knowledgeable about all this than I.

There are many types of global data and I think it's wise to avoid them all as much as possible. I would say from worst to less evil are:
Global variables in the global namespace
Global variables in a namespace
Static class variables.
All three make maintenance difficult and unit testing all but impossible. Even if you used global data to share data among tasks you would need to take precautions to protect the data to make it multi-task safe.
nicobari
Posts: 110
Joined: Mon Jan 30, 2012 12:15 pm

Re: Transferring data between different tasks in MOD54415

Post by nicobari »

Thanks a lot, these are really helpful suggestions.

Regards,
TM
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

Re: Transferring data between different tasks in MOD54415

Post by Ridgeglider »

One last data object that can coordinate sharing between tasks is OSFlags. These are really useful in situations where a tasks needs to wait on either the completion of several events, or on the the completion of one of several events (IE all or any), for example, involving the receipt of several mailboxes. This expands on Tod's comment about combining a mailbox with a semaphore to a scenario where you could wait on specific combinations of any or all of these events from several tasks.

Finally, in the event that you must use global data despite Tod's precautionary advice, it's worth taking stock of the various tools to lock and unlock "critical sections", usually non-atomic data that cannot be written or incremented in one CPU instruction. See Section 2.30 to 2.34 in the C:\nburn\docs\NetBurnerRuntimeLibrary\uCOSLibrary.pdf for descriptions, or Example 16.4 on circular buffers in the C:\nburn\docs\NetworkProgrammersGuide\NNDKProgMan.pdf. Last but not least, the OSCriticalSectionObj class is a great way to ensure you match every lock with an unlock automatically.

This following is a quote from Paul many years ago on the Yahoo forum that sums it all up really well. I wish this was actually in the NNDK (hint, hint):

My personal choice for critical sections is the OS_CRIT object.

First it only works for protecting resources between tasks, not between
tasks and interrupts.

If you need to protect between tasks and interrupts use USER_ENTER_CRITICAL
/USER_EXIT_CRITICAL

The problem with using USER_ENTER_CRITICAL is that is stops all task
switching and all interrupts.

An OS_CRIT only stops task switching if there was going to be a conflict.

The appropriate OS functions are:

BYTE OSCritInit( OS_CRIT *pCrit );

BYTE OSCritEnter( OS_CRIT *pCrit, WORD timeout );

BYTE OSCritLeave( OS_CRIT *pCrit );


My standard example is a linked list that will be manipulated by two different tasks.
If the tasks interrupt each other then the list can get corrupted.

So in the same place I store my linked list pointers I also put an OS_CRIT. (They can either be static or in a structure class etc...)

OS_CRIT my_list_crit;

Where I initialize the list I also initialize the the
OS_CRIT OSCritInit(&my_list_crit);

Before I manipulate the list I call OSCritEnter....


/* Try to acquire the critical section for the linked list, 0 waits forever */
OSCritEnter(&my_list_crit,0);

/* Manipulate the linked list */

/* Release the critical section */
OSCritLeave(&my_list_crit);


On first examination one could do this with a semaphore, but if you have complex manipulation functions that are multiple layers deep,
you can not use the semaphore more than once. The OS_CRIT is a counted object that keeps track of the task that is reserving it....

So you can have multiple layers...

OSCritEnter(&my_list_crit,0); /* First layer takes ownership of the OS_CRIT and assigns it to this task, task X */
OSCritEnter(&my_list_crit,0) ;/* Notices that it is already owned by X and is being called again by X so just increment the counter */
OSCritEnter(&my_list_crit,0); /* Notices that it is already owned by X and is being called again by X so just increment the counter */

OSCritLeave(&my_list_crit); /* decrement the counter, counter !=0 does nothing else */
OSCritLeave(&my_list_crit); /* decrement the counter, counter !=0 does nothing else */
OSCritLeave(&my_list_crit); /* decrement the counter, counter ==0 release the OS_CRIT and marks it as not belonging to any task */
/* At this any higher priority task that was waiting on the OS_CRIT will get it */


Lastly I use a bit of C++ trickery to help prevent mistakes....
Suppose I have a function that calls
OSCritEnter(&my_list_crit,0);

and then returns from different points in the function....
I must remember to call OSCritLeave once and only once for each return....


If I'm doing this in c++...

void MyListFunction()
{
OSCriticalSectionObj crit_obj(my_list_crit); /* The constructor will call OSCrit enter and it will not return until it owns the OS_CRIT */

return
/* No matter where in the function I return the crit_obj will go out of
scope when I return and the C++ destructor will
take care of Leaving the OS_CRIT so I can't forget and don't have to keep
track */

return
/* No matter where in the function I return the crit_obj will go out of scope when I return and the C++ destructor will
take care of Leaving the OS_CRIT so I can't forget and don't have to keep
track */

return
/* No matter where in the function I return the crit_obj will go out of scope when I return and the C++ destructor will take care of Leaving the OS_CRIT so I can't forget and don't have to keep
track */

}



Paul
nicobari
Posts: 110
Joined: Mon Jan 30, 2012 12:15 pm

Re: Transferring data between different tasks in MOD54415

Post by nicobari »

@Tod how do you protect the data to make it Multi-Task safe?

Regards,
TM
Post Reply