Jump to content
Sign in to follow this  
Dave

How To Share Resources Between Tasks

Recommended Posts

Hi all,

 

Here is an example of how a resource can be shared between tasks, using a common access function that yields when busy.

 

// Example of resource sharing between tasks using a common function that yields.
//
// When using the Novo RTOS it is dangerous to call a function that yields in more 
// than one task because the software call stack can be corrupted.
//
// This code shows the how a function that yields can be safely called from more 
// than one task. It does this by treating the function as a shared resource, using
// a semaphore to signal its availability.
//
// Author: David Hobday
// Date: 12/05/2005 
// Target: PIC16
// 

#include <novocfg_pic16t3e5ts1.h>
#include <novo.h>

#define hTask0 0
#define hTask1 1
#define hTask2 2

#define hSemPutsResource 0

void puts( unsigned char c )
{
    // This routine doesn't actually do anything other than yield once before
    // loading the txchar variable.
    //
    // The code in this function could be accessing a hardware uart.
    bool busy = 1;
    while( busy )
    {
        Sys_Yield();
        busy = 0;
    }
        
    unsigned char txchar = c;
}

void Task0()
{
    while( 1 )
    {    
        if( SysTrySemaphore( hSemPutsResource ) ) // see if we can get the resource, might never get it as we are not in the queue
        {
            puts( '0' );
            puts( '0' );
            puts( '0' );
            SysSignalSemaphore( hSemPutsResource ); // release the resource
        }
        // do other continous stuff
        Sys_Yield();
    }
}

void Task1()
{
    while( 1 )
    {
        Sys_WaitSemaphore( hSemPutsResource, EVENT_NO_TIMEOUT ); // wait for then lock the resource
        puts( '1' );
        puts( '1' );
        puts( '1' );
        SysSignalSemaphore( hSemPutsResource ); // release the resource
        Sys_Sleep( 10 );
    }
}

void Task2()
{
    while( 1 )
    {
        Sys_WaitSemaphore( hSemPutsResource, EVENT_NO_TIMEOUT ); // wait for then lock the resource
        puts( '2' );
        puts( '2' );
        puts( '2' );
        SysSignalSemaphore( hSemPutsResource ); // release the resource
        Sys_Sleep( 10 );
    }
}

void main()
{
    SysInit();
    SysCreateTask( hTask0, 2, Task0 );
    SysCreateTask( hTask1, 2, Task1 );
    SysCreateTask( hTask2, 2, Task2 );
    
    SysStartTask( hTask0 );
    SysStartTask( hTask1 );
    SysStartTask( hTask2 );
    
    SysSignalSemaphore( hSemPutsResource );
    
    while( 1 )
    {
        Sys_Yield();
        SysTimerUpdate(); // generate a tick
    }
}

 

The way this code works is to only allow one task to call the function that accesses the shared resource at a time.

We need to do this for two reasons

1) To prevent overlapped access of the resource by two different tasks.

2) To prevent corruption of the software stack - re-enterancy would cause corruption.

 

If the function that accessed the resource did not call a yielding function, then there is not chance of overlapped access, so you wouldn't need to use the semaphore.

 

I hope that all makes sense :)

 

Regards

Dave

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...