It is not exciting to read a lot of general stuff about software API's, so let's code our first real-life application right now.

Jump start example - Heart Beat Blinky LED

This example aims to show how straightfoward it is to code a "heart beat" LED task with YasK. An complex blink pattern is not so easy to program from scratch. See how clean and linear this code looks. This code is so strange: it contains neither while(), nor for() loops, and just one if-then-else statement.

This piece of code implements the most important concepts of YasK, so look at it carefully, please.

The hear_beat task drives the LED as follows :

while(true) {
    ON: 30 ms
    OFF: 150 ms
    ON: 30 ms
    OFF: 700 ms 
}

The code of the heart_beat task:

short heart_beat( YASK_MSG_T *msg)
{

static char mbx = YASK_NONE; // mailbox handle

if( msg)
{
	switch( msg->idn)
	{
		case 1: // LED On 1
		    IOSset_bit( LED_PORT, LED_BIT);
		    // Start the first timer (30 ms) and execute case 2 when done
		    YASKpost( mbx,             // mailbox
                                2,             // message identifier
                                0,             // optional indentifier
                                30,            // time out
                                YASK_PRI_TSK); // message priority
		    break;
		
		case 2: // LED Off 1
		    IOSreset_bit( LED_PORT, LED_BIT);
		    // Start the second timer (150 ms) and execute case 3 when done
		    YASKpost( mbx, 3, 0, 150, YASK_PRI_TSK);
		    break;		

		case 3: // LED On 2
		    IOSset_bit( LED_PORT, LED_BIT);
		    // Start the third timer (30 ms) and execute case 4 when done
		    YASKpost( mbx, 4, 0, 30, YASK_PRI_TSK);
		    break;	

		case 4: // LED Off 2
		    IOSreset_bit( LED_PORT, LED_BIT);
		    // Start the fourth timer (700 ms) and execute case 1 when done
		    YASKpost( mbx, 1, 0, 700, YASK_PRI_TSK);
		    break;	
		
		default: // Warn if an unknown message is received
		    printf("heart_beat: Unknowkn message %d\r\n", msg->idn);
		    break;

	} // End of switch on received message identifier
} 
else // come here if I am called with a NULL message
{

	// get a mailbox handle on myself (this task) and give it a friendly name
	mbx = YASKregister( heart_beat,   // Recipient task
                            "HeartBeat"); // Friendly mailbox name
	
	// Start blinking immediately: execute case 1 as soon as possible
        // YASKpost( mailbox, identifier, option, delay, priority)
	YASKpost( mbx, 1, 0, 0, YASK_PRI_TSK);
	
} // End of if/else on message 

return 0;

} // End of heart_beat()

Explanations:

short heart_beat( YASK_MSG_T *msg) 

The heart_beat task is a regular C function with only one input parameter: YASK_MSG_T *msg. This input contains the message sent to the task. The task returns a short integer upon completion.

static char mbx = YASK_NONE; // mailbox handle

The variable mbx contains a mailbox handle. This handle is simply an index of an internal array of YasK. This handle is provided by YasK when I register the mailbox. The variable must be static in order to keep this handle between two activations of the task.

if( msg)
{

This test checks if the received message is not NULL. YasK never sends NULL messages to a task, so when a task receives a NULL message, that generally means that the task needs to be started. This occurs once during program start up.

switch( msg->idn)
	{

Once I have checked that the received message contains information, I start a switch/case statement based on the identifier contained in the message. The identifier is an unsigned char.

case 1: // LED On
	IOSset_bit( LED_PORT, LED_BIT);

In case 1, I first set the output port wired to my LED in order to light it. IOSset_bit is a macro that does this job. This macro does not belong to YasK. In your implementation, you will put here your own code.

YASKpost( mbx,           // mailbox
          2,             // message identifier
          0,             // optional indentifier
          30,            // time out (ms)
          YASK_PRI_TSK); // message priority
  break;
Once the led is lighted, I need to wait 30 ms before I turn it off. The YASKpost call does this job.

The YASKpost call is the most important routine of YasK's API. It simply puts a message in a recipient's mailbox and returns. YasK will then struggle to deliver the message to the recipient task in time.

The 5 input parameters of the YASKpost call are the following:

Keep in mind that the YASKpost call does not wait during 30 ms. It puts the message in the mailbox and returns immediately an integer telling whether the message has been succesffully posted or not.

after the YASKpost call, we can break.

case 2: // LED Off 1
    IOSreset_bit( LED_PORT, LED_BIT);
    // Start the second timer (150 ms) and execute case 3 when done
     YASKpost( mbx, 3, 0, 150, YASK_PRI_TSK);
    break;

Once the 30 ms time out triggered in case 1 is done, YasK delivers the message to me. The identifier of this message is 2, so case 2 will be selected in the switch/case statement.

In case 2, I turn the LED off and call YASKpost with a identifier set to 3 and a time out set to 150 milliseconds. YasK will wake me up in 150 ms with a message identifier of 3.

case 3: // LED On 2
    IOSset_bit( LED_PORT, LED_BIT);
    // Start the third timer (30 ms) and execute case 4 when done
    YASKpost( mbx, 4, 0, 30, YASK_PRI_TSK);
    break;

When YasK delivers message identifer 3, I must light the LED again and sleep during 30 ms before executing case 4.

case 4: // LED Off 2
    IOSreset_bit( LED_PORT, LED_BIT);
    // Start the fourth timer (700 ms) and execute case 1 when done
    YASKpost( mbx, 1, 0, 700, YASK_PRI_TSK);
    break;	

when I receive message identifier 4, I turn the LED off and sleep during 700 ms. YasK will then wake me up with message identifer 1 and the whole process will start again.

Now we need to see what happens if the task is called with a NULL message:

else // come here if I am called with a NULL message
{
	// get a mailbox handle on myself (this task) and give it a friendly name
	mbx = YASKregister( heart_beat, // Recipient task
                            "HeartBeat"); // Friendly mailbox name
The heart_beat routine is called with a NULL message once during start-up. During this first call, the task gets a mailbox from YasK and saves it in the local static mbx variable.

This is simply done by the YASKregister call. The first parameter is the recipient task associated to the mailbox, the second parameter is a friendly name. Here the recipient of the messages will be myself (heart_beat).

Once I have got a mailbox, the task needs to start cycling:

    YASKpost( mbx,                 // maiblox hande: me
                1,                 // Identifier
                0,                 // Optionnal identifier
                0,                 // Send message immediately
                YASK_PRI_TSK);    // Standard priority
	
} // End of if/else on message 

return 0;

} // End of heart_beat()

To start the task, call YASKpost with a message identifier set to 1 and a time out set to 0. YasK will send it as soon as possible.


Jump start example - Use Heart Beat Blinky LED

To use your brand new heart_beat task, create a function called app_main like the one below:

// My main routine must be called "app_main" 
void app_main( void)
{

    // Initialize my hardware
    board_hw_init();

    // Start blinking the LED
    heart_beat( NULL);

} // End off app_main()

Your routine cannot be called "main" because, main is part of YasK. Your startup routine is called by YasK during the program startup.

After board initialization, just call your heart_beat task with a NULL parameter, and it will start.