| |||||
Technical Support Support Resources
Product Information | RTX51 TINY: ADDING SEMAPHORE SUPPORTInformation in this article applies to:
SYMPTOMRTX51 Tiny Version 2 does not include binary semaphore or counting semaphore support. However, with a little work, you can add support for semaphores using the existing functions in the kernel. RESOLUTIONBasically, you need a structure for each semaphore as well as a setup, get, and put function. You must define the maximum number of semaphores in MAX_SEMAPHORES.
/*---------------------------------------------------------
---------------------------------------------------------*/
#include <rtx51tny.h>
#define MAX_SEMAPHORES 4
struct sem_st
{
unsigned char max_count;
unsigned char count;
unsigned waiting_task_bits;
};
static struct sem_st sem_tab[MAX_SEMAPHORES];
/*---------------------------------------------------------
---------------------------------------------------------*/
#pragma disable
void init_semaphore (
unsigned char semaphore_id,
unsigned char max_count,
unsigned char count)
{
if (semaphore_id >= MAX_SEMAPHORES) return;
sem_tab[semaphore_id].max_count = max_count;
sem_tab[semaphore_id].count = count;
sem_tab[semaphore_id].waiting_task_bits = 0;
}
/*---------------------------------------------------------
---------------------------------------------------------*/
#pragma disable
static char _Xget_semaphore (
unsigned char semaphore_id)
{
if (sem_tab[semaphore_id].count > 0)
{
--sem_tab[semaphore_id].count;
return (-1);
}
sem_tab[semaphore_id].waiting_task_bits |=
(1 << os_running_task_id());
return (0);
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void get_semaphore (
unsigned char semaphore_id)
{
if (semaphore_id >= MAX_SEMAPHORES) return;
if (_Xget_semaphore (semaphore_id) == 0)
{
while (os_wait (K_TMO, 255, 0) != RDY_EVENT);
}
}
/*---------------------------------------------------------
---------------------------------------------------------*/
#pragma disable
static char _Xput_semaphore (
unsigned char semaphore_id)
{
unsigned char i;
if ((sem_tab[semaphore_id].count > 0) ||
(sem_tab[semaphore_id].waiting_task_bits == 0))
{
++sem_tab[semaphore_id].count;
return (-1);
}
for (i = 0; i < (sizeof(sem_tab[0].waiting_task_bits)*8); i++)
{
if (sem_tab[semaphore_id].waiting_task_bits & (1 << i))
{
sem_tab[semaphore_id].waiting_task_bits &= ~(1 << i);
return (i);
}
}
return (-1); /*** This should NEVER happen ***/
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void put_semaphore (
unsigned char semaphore_id)
{
unsigned char i;
if (semaphore_id >= MAX_SEMAPHORES) return;
if ((i=_Xput_semaphore (semaphore_id)) != -1)
{
os_set_ready (i);
os_switch_task ();
}
}
/*---------------------------------------------------------
---------------------------------------------------------*/
In your RTX51 Tiny program, you must initialize each semaphore with a maximum count and a starting count. Then, call get_semaphore to get the semaphore--your task will be blocked if no semaphore is available. Call put_semaphore when you are done with a semaphore--tasks waiting on a semaphore will be readied. The following example shows how multiple tasks in an RTX51 Tiny program can share the 8051 on-chip UART.
/*---------------------------------------------------------
---------------------------------------------------------*/
#define USE_SEMAPHORES 1
#include <rtx51tny.h>
#include <stdio.h>
#include <reg51.h>
/*---------------------------------------------------------
---------------------------------------------------------*/
extern void get_semaphore (unsigned char);
extern void put_semaphore (unsigned char);
extern void init_semaphore (
unsigned char semaphore_id,
unsigned char max_count,
unsigned char count);
/*---------------------------------------------------------
---------------------------------------------------------*/
void task_0 (void) _task_ 0
{
SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
TH1 = 221; /* TH1: reload value for 1200 baud @ 16MHz */
TR1 = 1; /* TR1: timer 1 run */
TI = 1; /* TI: set TI to send first char of UART */
#if USE_SEMAPHORES
init_semaphore (0, 1, 1); /*** Semaphore ID 0, Max 1, Count 1 ***/
#endif
os_create_task (1);
while (1)
{
#if USE_SEMAPHORES
get_semaphore (0);
#endif
puts ("This is task 0");
#if USE_SEMAPHORES
put_semaphore (0);
#endif
}
}
/*---------------------------------------------------------
---------------------------------------------------------*/
void task_1 (void) _task_ 1
{
while (1)
{
#if USE_SEMAPHORES
get_semaphore (0);
#endif
puts ("This is task 1");
#if USE_SEMAPHORES
put_semaphore (0);
#endif
}
}
/*---------------------------------------------------------
---------------------------------------------------------*/
Change the USE_SEMAPHORES macro to a value of 0 to see what happens when semaphores are not used. Additionally, you'll have to specify the following overlay information to the BL51 Linker. ?PR?__XPUT_SEMAPHORE?SEMAPHORE ! * MORE INFORMATION
SEE ALSOFORUM THREADSThe following Discussion Forum threads may provide information related to this topic. Last Reviewed: Sunday, October 29, 2006 | ||||
| |||||