Important notes

Passing by reference can be more efficient than passing by value for moving large data structures around, but several things need  to be kept in mind:

  •  Keep the datatypes straight: Because the argument to a queue is of the void* data type, the compiler won't be able to warn you that you're supplying an address to a struct instead of to a pointer.
  • Keep the queued data around: Unlike passing data by value, when a queue holds pointers to the data, the underlying data passed to the queue needs to stay until it is used. This has the following implications:
    • The data must not live on the stackā€”no local function variables! Although this can be made to work, it is generally a bad idea to define variables on a stack in the middle of a call chain and then push a pointer onto a queue. By the time the receiving task pulls the pointer off of the queue, the stack of the sending task is likely to have changed. Even if you do get this to work under some circumstances (such as when the receiving task has a higher priority than the sending task), you'll have created a very brittle system that is likely to break in a very subtle way in the future.
    • A stable storage location for the underlying variable is a must. Global and statically allocated variables are both acceptable.  If you'd like to limit access to a variable, use static allocation inside a function.  This will keep the variable in memory, just as if it was a global, but limit access to it:
void func( void ) 
{
static struct MyBigStruct myVar;
    • You should dynamically allocate space for the variable (if dynamic allocation is acceptable in your application).  See Chapter 15, FreeRTOS Memory Management, for details on memory management, including dynamic allocation.
  • Who owns the data? When a queue has a copy of a struct, the queue owns that copy. As soon as the item is removed from the queue, it disappears. Contrast this with a queue holding a pointer to data. When the pointer is removed from the queue, the data is still present in its previous location. Data ownership needs to be made very clear. Will the task receiving the pointer from the queue become the new owner (and be responsible for freeing dynamically allocated memory if it was used)? Will the original task that sent the pointer still maintain ownership? These are all important questions to consider up front.

Now that we've discussed passing around huge amounts of data (avoid it whenever possible!), let's talk about an efficient way of passing around small amounts of data.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.236.62