smartx_logo.JPG

Users manual



uSmartX is a non-preemptive, multitasking, priority based RTOS. It features mechanisms for inter-task communication and basic task and time control functions.

Main features:

Scheduling policy

On system initialization the uSmartX kernel builds a table of tasks to be executed. Task are scheduled on a priority based fashion. The scheduling policy can be reduced to a simple round robin scheme if tasks have equal priorities. Each time a task is run a system event is passed to it signaling the task what action to take. Beeing a non-preemptive kernel context switching is performed only when a task returns. This is very important as a task can block the system if it never returns. When a task exits it passes a control event to the kernel.

The uSmartX kernel ensures that the current running task has the highest priority and is in the ready state. If there are no ready tasks to run the scheduler returns with the idle code. It is up to the user to act on this event. A task could be suspended or delayed from execution. It could be explicitely delayed via a dedicated system call or it could be indirectly delayed due to a resource pending.

Each time the task is run the kernel passes a event to it. Events are usualy responses to previous task's actions. With the current kernel version the task could receive up to seven different events:

System initialisation

On system startup the task table must be passed to the kernel. The kernel then builds a task table and initialises its internal strctures. The task table consist of three members:

Taks's name. Note this string must be null terminated.

Please note the table must be ended with a NULL entry. In this way the kernel figuers out the number of tasks.

Before running the scheduler the tasks table must be passed to the uSMARTX_Init() function. Also interrupts should be enabled if needed. Please see the example below.

    #include <uSMARTX.h>
    
    TSK_CREATE(TSK1_tcb);
    TSK_CREATE(TSK3_tcb);
    TSK_CREATE(TSK2_tcb);
    
    STATUS TSK1(STATUS evt) {
        return SYS_OK;
    }
    STATUS TSK1(STATUS evt) {
        return SYS_OK;
    }
    STATUS TSK1(STATUS evt) {
        return SYS_OK;
    }
    
    task_entry_t task_tbl[] = { {&TSK1, &TSK1_tcb, 1, "TASK1"},
                                {&TSK2, &TSK2_tcb, 1, "TASK2"},
                                {&TSK3, &TSK3_tcb, 1, "TASK3"},
                                {0, 0} };
    
    int main(void) {
                
        uSMARTX_Init(task_tbl);
        .
        .
        .
        INT_Enable();
        .
        .
        .
    } 

Calling the scheduler

The kernel is run by calling the uSMARTX_Scheduler() function. The scheduler always runs the task with the highest priority. When a task exits an event code is passed back to the kernel. It is up to the user to pass this code. This code will be then returned by the uSMARTX_Scheduler() function. In this way the user can act upon the event code by examining the returned value. Such an example could be resetting the system by passing SYS_ERROR, signalling a fatal error to the main loop.
    
    while(1) {      
        if(uSMARTX_Scheduler() == SYS_ERROR)
            break;
    }   
    SystemReset();

System timer tick

System calls dealing with timmed pending on resources need a system timer tick. The uSmartX kernel features an advanced system timer tick which allows system calls to be time dependant. Beside system calls, software timers relay on system timer tick too. All timers in the system are evaluated when the uSMARTX_Tick() function is executed. It is up to the user from where the function will be called. The only constraint is that the function must be executed with interrupts disabled. Usually this function is placed in an interrupt service rutine which is triggered by a timer or by an external event. The system timer tick resolution is determined by the frequency the function is called.

All timers (pending system calls incorporate a timer) are enqueued in a relative timer queue. This means only one timer is evaluated. All others are relative to the first one which has the shortest expiration time. This increases performance drasticaly when dealing with multiple software timers.

Warning:
If the system timer tick functionality is not needed, pending system calls musn't be called with a timeout value. NO_WAIT should be used for specifying the timeout.

Porting guide

uSmartX RTOS is highly portable. Most of the code is platform indipendant. The only functions needs to be ported are functions that controls enabling and disabling of interrupts. The function INT_Disable() returns the status of the global interrupt flag(s) just before the interrupts are disabled. These flags are used later when calling INT_Restore() to restore the status of interrupts before disabling them.

INT_Restore() Restores the state of interrupts to the value passed to it.

ARM7TDMI

The ARM7TDI architecture has two bits in the CPSR register that controls interrupts. This is the F and I bit. Functions dealing with interrupts should manage these two bits accordingly to the interrupt usage. For example in fast interrupts aren't used there is no need to handle the F bit in the CPSR.

AVR

The AVR architecture disables/enables interrupts by clearing/setting the I bit in the SREG register.

H8

The H8 architecture disables/enables interrupts by clearing/setting the I bit in the CCR register.

Sample applications

Plase see the related pages for some sample applications. The examples are to be used with an ATmega64 device running at 16 Mhz, but can be simply modified for some other CPU. In particular just the timer tick interrupt must be modified to suit the CPU in question.
Generated on Sun Oct 16 22:23:55 2005 for uSmartX by  doxygen 1.4.3