聯系方式

您當前位置:首頁 >> OS作業OS作業

日期:2018-10-28 09:51

As a member of software engineering team, you are tasked to design a timer management system for the Real Time Operating System that is being developed in house for use in an embedded communication device. The following describes the high level design document.  

The figure below shows the state diagram of a timer.

Tasks can call RTOSTmrStateGet()to find out the state of a timer. Also, at any time during the countdown process, the application code can call?RTOSTmrRemainGet()to find out how much time remains before the timer reaches zero (0). The value returned is expressed in “timer ticks.” If timers are decremented at a rate of 10 Hz then a count of 50 corresponds to 5 seconds. If the timer is in the stop state, the time remaining will correspond to either the initial delay (one shot or periodic with initial delay), or the period if the timer is configured for periodic without initial delay.


Figure - Timer State Diagram

(1)

The “Unused” state is a timer that has not been created or has been “deleted.”

(2)

When creating a timer or calling?RTOSTmrStop(), the timer is placed in the “stopped” state.

(3)

A timer is placed in running state when calling RTOSTmrStart(). The timer stays in that state unless it’s stopped, deleted, or completes its one shot.

(4)

The “Completed” state is the state a one-shot timer is in when its delay expires.


A timer is a kernel object as defined by the?RTOS_TMR?data type as shown in the listing below:


typedef struct os_tmr {

 INT8U RTOSTmrType;      /* Should always be set to RTOS_TMR_TYPE for timers */

RTOS_TMR_CALLBACK RTOSTmrCallback;  /* Function to call when timer expires */

void *RTOSTmrCallbackArg; /* Argument to callback function */

void  *RTOSTmrNext; /* Double link list pointers */

void *RTOSTmrPrev;

INT32U RTOSTmrMatch; /* Timer expires when RTOSTmrTickCtr= RTOSTmrMatch*/

INT32U RTOSTmrDly; /* Delay time before periodic update starts */

INT32U RTOSTmrPeriod;/* Period to repeat timer */

 INT8U *RTOSTmrName;/* Name to give the timer */

INT8U RTOSTmrOpt;  /* Options (see RTOS_TMR_OPT_xxx) */

INT8U RTOSTmrState; /* Indicates the state of the timer:*/

/*RTOS_TMR_STATE_UNUSED */

/*RTOS_TMR_STATE_RUNNING */

/*RTOS_TMR_STATE_STOPPED */

} RTOS_TMR;



The structure starts with a “RTOSTmrType” field, which allows it to be recognized by OS as a timer. Other kernel objects will also have a “Type” as the first member of the structure. If a function is passed a kernel object, OS is able to confirm that it is passed the proper data type. For example, if passing a message queue to a timer service (for example RTOSTmrStart()) then OS will be able to recognize that an invalid object was passed, and return an error code accordingly.

Each kernel object can be given a name (RTOSTmrName) for easier recognition by debuggers. This member is simply a pointer to an ASCII string which is assumed to be NUL terminated.

The. RTOSTmrCallback member is a pointer to a function that is called when the timer expires. If a timer is created and passed a NULL pointer, a callback would not be called when the timer expires.

If there is a non-NULL. RTOSTmrCallback then the application code could have also specified that the callback be called with an argument when the timer expires. This is the argument that would be passed in this call.

RTOSTmrNext and?RTOSTmrPrev are pointers used to link a timer in a doubly linked list. These are described later.

The RTOSTmrDly field contains the one-shot time when the timer is configured (i.e., created) as a one-shot timer and the initial delay when the timer is created as a periodic timer. The value is expressed in multiples of 1/RTOS_CFG_TMR_TASK_RATE_HZ?of a second.

The RTOSTmrPeriod field is the timer period when the timer is created to operate in periodic mode. The value is expressed in multiples of 1/RTOS_CFG_TMR_TASK_RATE_HZ?of a second.

The RTOSTmrOpt field contains options that are passed to RTOSTmrCreate().

The RTOSTmrState field represents the current state of the timer (see the figure in Timers States).

Even if the internals of the RTOS_TMR data type are understood, the application code should never access any of the fields in this data structure directly. Instead, you should always use the Application Programming Interfaces (APIs) provided.



RTOS_TmrTask() is a task created by OS (i.e.  you) and its priority is configurable by the user.RTOS_TmrTask()is typically set to a medium priority.

RTOS_TmrTask()is a periodic task and uses the same interrupt source used to generate clock ticks. However, timers are generally updated at a slower rate (i.e., typically 10 Hz or so) and thus, the timer tick rate is divided down in software. If the tick rate is 1000 Hz and the desired timer rate is 10 Hz then the timer task will be signaled every 100th tick interrupt as shown in the figure below.


1) The tick ISR occurs and assumes interrupts are enabled and executes.

(2)The tick ISR signals the tick task that it is time for it to update timers.

(3)The tick ISR terminates, however there might be higher priority tasks that need to execute (assuming the timer task has a lower priority). Therefore, OS runs the higher priority task(s).

(4)When all higher priority tasks have executed, OS switches to the timer task and determines that there are three timers that expired.

(5)The callback for the first timer is executed.

(6)The callback for the second expired timer is executed.

(7)The callback for the third expired timer is executed.


There are a few interesting things to notice:

Execution of the callback functions is performed within the context of the timer task. This means that the application code will need to make sure there is sufficient stack space for the timer task to handle these callbacks.

The callback functions are executed one after the other based on the order they are found in the timer list.

The execution time of the timer task greatly depends on how many timers expire and how long each of the callback functions takes to execute. Since the callbacks are provided by the application code they have a large influence on the execution time of the timer task.

The timer callback functions must never wait on events because this would delay the timer task for excessive amounts of time, if not forever.

Callbacks should execute as quickly as possible.


Timer List - Timer Management Internals Design Options

μC/OS-III applications may require many timers. The timer manager implements a simple linear list where each timer is linked in a doubly linked list as shown in the figure below.


Figure - Empty Timer List

(1)

RTOSTmrListEntries contains the current number of entries in the list. This variable is updated whenever timers are added or removed from the list.

(2)

RTOSTmrListPtr contains a pointer to a doubly linked list of timers that the timer manager will need to update.

(3)

RTOSTmrTickCtr is incremented by RTOS_TmrTask()every time the tick ISR signals the task. This counter basically keeps track of the number of times the timer task has been signaled.


Timers are inserted in the timer list by calling?RTOSTmrStart()and, a timer must be created before it can be used. Newly created timers are always inserted at the beginning of the list as shown in the figure following the code listing below?and the code listing itself.

RTOS_TMR MyTmr1;

RTOS_TMR MyTmr2;

void MyTmrCallbackFnct1 (void*p_arg)

{/* Do something when timer #1 expires */

}

void MyTmrCallbackFnct2 (void *p_arg)

{

/* Do something when timer #2 expires */

}

void MyTask (void *p_arg)

{ RTOS_ERR err;

while(DEF_ON) {:RTOSTmrCreate((RTOS_TMR*)&MyTmr1,(RTOS_CHAR*)“My Timer #1”,

(RTOS_TICK)1,(RTOS_TICK)0,

(RTOS_OPT)RTOS_OPT_TMR_ONE_SHOT,

(RTOS_TMR_CALLBACK_PTR)MyTmrCallbackFnct1,

(void*)0,(RTOS_ERR*)&err);

/* Check ’err” */

RTOSTmrStart ((RTOS_TMR *)&MyTmr1,

(RTOS_ERR *)&err);

/* Check “err” */

// Continues in the next code listing!

Listing - Creating and Starting a timer

Since this is the first timer inserted in the timer list, the.NextPtr and .PrevPtr both point to NULL.


Figure - Inserting a timer in the timer list

The code below shows creating and starting another timer. This is performed “before” the timer task is signaled.

// Continuation of code from previous code listing.

RTOSTmrCreate((RTOS_TMR*)&MyTmr2,

(RTOS_CHAR *)“My Timer #2”,

(RTOS_TICK)10,

(RTOS_TICK)0,

(RTOS_OPT)RTOS_OPT_TMR_ONE_SHOT,

(RTOS_TMR_CALLBACK_PTR)MyTmrCallbackFnct2,

(void*)0,(RTOS_ERR*)&err);

/* Check ’err” */

RTOSTmrStart ((RTOS_TMR?*)&MyTmr,

(RTOS_ERR?*)&err);/* Check ’err” */

}

}

Listing - Creating and Starting a timer - continued

The “second timer” is inserted at the head of the list as shown in the figure below.


Figure - Inserting a second timer in the tick list

When the timer task executes, it starts by incrementing?RTOSTmrTickCtr?and goes through the list (linearly) and checks each of the RTOSTmrMatch?fields is equal the OSTmtTickCtr. When equal, the timer manager executes the callback function associated with the timer.

When inserting the timer in the link list RTOSTmrMatch field is calculated as OSTmtTickCtr + RTOSTmrDly. If the timer is set to periodic, reloads the?RTOSTmrMatch?is calculated as OSTmtTickCtr + RTOSTmrPeriod. If the timer is configured as a one-shot timer, the timer is removed from the list upon expiration.

Timer management occurs at the task level. The list must be protected using an internal mutual exclusion semaphore (mutex) or, by locking the scheduler. It’s?recommend that you use (and thus enable) mutexes because locking the scheduler impacts task responsiveness of other, higher priority tasks in your application.

Your timer management module might need to literally maintain hundreds of timers, so it needs to be implemented such that it does not take too much of CPU time to update the timers. So you may need to design a hash table of link lists to keep the length of the link lists short. You may want to use the value of (OSTmtTickCtr + RTOSTmrDly) % N to calculate the index of the hash table.


RTOSTmrTickCtr is incremented by RTOSTmrTask() every time the tick ISR signal the task.

Timers are inserted in the timer list by calling RTOSTmrSTart().


You need to implement the following Timer APIs for the tasks that you’re the kernel timer:


/*CREATE A TIMER

*

* Description: This function is called by your application code to create a timer.

*

* Arguments : dly Initial delay.

*If the timer is configured for ONE-SHOT mode, this is the timeout used

* If the timer is configured for PERIODIC mode, this is the first timeout to wait for

* before the timer starts entering periodic mode

period The 'period' being repeated for the timer.

If you specified 'RTOS_TMR_OPT_PERIODIC' as an option, when the timer expires, it will automatically restart with the same period.

Specifies either:RTOS_TMR_OPT_ONE_SHOT The timer counts down only once

*RTOS_TMR_OPT_PERIODIC The timer counts down and then reloads itself

*

*callback Is a pointer to a callback function that will be called when the timer expires. The callback function must be declared as follows: void MyCallback (RTOS_TMR *ptmr, void *p_arg);callback_arg ?Is an argument (a pointer) that is passed to the callback function when it is called.Is a pointer to an ASCII string that is used to name the timer. Names are useful for debugging.

*perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID_DLY you specified an invalid delay

* RTOS_ERR_TMR_INVALID_PERIOD you specified an invalid period

*RTOS_ERR_TMR_INVALID_OPT you specified an invalid option

*RTOS_ERR_TMR_NON_AVAIL if there are no free timers from the timer pool

*

* Returns : A pointer to an RTOS_TMR data structure.

* This is the 'handle' that your application will use to reference the timer created.

************************************************************************************************************************

*/


RTOS_TMR ?*RTOSTmrCreate (INT32U dly,

INT32U period,

INT8U opt,

RTOS_TMR_CALLBACK callback,

void *callback_arg,

INT8U *pname,INT8U *perr)

/*DELETE A TIMER

*

* Description: This function is called by your application code to delete a timer.

*

* Arguments : ptmr Is a pointer to the timer to stop and delete.

*perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID 'ptmr' is a NULL pointer

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE if the timer was not created

*RTOS_ERR_TMR_INVALID_STATE the timer is in an invalid state

*

* Returns : RTOS_TRUE If the call was successful

* RTOS_FALSE If not/

BOOLEAN RTOSTmrDel (RTOS_TMR *ptmr,

INT8U *perr)

/* GET THE NAME OF A TIMER

*

* Description: This function is called to obtain the name of a timer.

*

* Arguments : ptmr Is a pointer to the timer to obtain the name for

*

*pdest Is a pointer to pointer to where the name of the timer will be placed.

*

* perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE The call was successful

*RTOS_ERR_TMR_INVALID_DEST  'pdest' is a NULL pointer

*  RTOS_ERR_TMR_INVALID'ptmr' is a NULL pointer

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE  'ptmr' points to a timer that is not active

* RTOS_ERR_TMR_INVALID_STATE ?the timer is in an invalid state

*

* Returns : The length of the string or 0 if the timer does not exist.

************************************************************************************************************************

*/


INT8U RTOSTmrNameGet (RTOS_TMR *ptmr,

INT8U **pdest,

INT8U *perr)

/*GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES

*

* Description: This function is called to get the number of ticks before a timer times out.

*

* Arguments : ptmr Is a pointer to the timer to obtain the remaining time from.

*

* perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID 'ptmr' is a NULL pointer

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active

* RTOS_ERR_TMR_INVALID_STATE the timer is in an invalid state

*

* Returns : The time remaining for the timer to expire. The time represents 'timer' increments. In other words, if

* RTOSTmr_Task() is signaled every 1/10 of a second then the returned value represents the number of 1/10 of

* a second remaining before the timer expires.

*/

INT32U RTOSTmrRemainGet (RTOS_TMR *ptmr,

INT8U *perr)

/*FIND OUT WHAT STATE A TIMER IS IN

*

* Description: This function is called to determine what state the timer is in:RTOS_TMR_STATE_UNUSED the timer has not been created

* RTOS_TMR_STATE_STOPPED the timer has been created but has not been started or has been stopped

* RTOS_TMR_COMPLETED the timer is in ONE-SHOT mode and has completed it's timeout

* RTOS_TMR_RUNNING the timer is currently running

*

* Arguments : ptmr Is a pointer to the desired timer

*

* perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID 'ptmr' is a NULL pointer

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active

* RTOS_ERR_TMR_INVALID_STATE ?if the timer is not in a valid state

*

* Returns : The current state of the timer (see description).

*/


INT8U RTOSTmrStateGet (RTOS_TMR *ptmr,

INT8U *perr)

/*START A TIMER

*

* Description: This function is called by your application code to start a timer.

*

* Arguments : ptmr Is a pointer to an RTOS_TMR

*perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE if the timer was not created

* RTOS_ERR_TMR_INVALID_STATE the timer is in an invalid state

*

* Returns : RTOS_TRUE if the timer was started

* RTOS_FALSE if an error was detected

*/

BOOLEAN RTOSTmrStart (RTOS_TMR *ptmr,

INT8U *perr)

/*STOP A TIMER

*

* Description: This function is called by your application code to stop a timer.

*

* Arguments : ptmr Is a pointer to the timer to stop.

*

* opt Allows you to specify an option to this functions which can be:

*RTOS_TMR_OPT_NONE Do nothing special but stop the timer

* RTOS_TMR_OPT_CALLBACK Execute the callback function, pass it the callback argument

* specified when the timer was created.

* RTOS_TMR_OPT_CALLBACK_ARG Execute the callback function, pass it the callback argument

* specified in THIS function call

*

* callback_arg Is a pointer to a 'new' callback argument that can be passed to the callback function

* instead of the timer's callback argument. In other words, use 'callback_arg' passed in

* THIS function INSTEAD of ptmr->RTOSTmrCallbackArg

*

* perr Is a pointer to an error code. '*perr' will contain one of the following:

* RTOS_ERR_NONE

* RTOS_ERR_TMR_INVALID 'ptmr' is a NULL pointer

* RTOS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an RTOS_TMR

* RTOS_ERR_TMR_INACTIVE if the timer was not created

* RTOS_ERR_TMR_INVALID_OPT if you specified an invalid option for 'opt'

* RTOS_ERR_TMR_STOPPED if the timer was already stopped

* RTOS_ERR_TMR_INVALID_STATE the timer is in an invalid state

* RTOS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined

*

* Returns : RTOS_TRUE If we stopped the timer (if the timer is already stopped, we also return RTOS_TRUE)

* RTOS_FALSE If not

************************************************************************************************************************

*/

BOOLEAN RTOSTmrStop (RTOS_TMR ?*ptmr,

INT8U opt, void *callback_arg,INT8U *perr)

/*SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS

*

* Description: This function is typically called by the ISR that occurs at the timer tick rate and is used to signal to RTOSTmr_Task() that it's time to update the timers.

*

* Arguments : none

*

* Returns : RTOS_ERR_NONE The call was successful and the timer task was signaled.

*/

INT8U RTOSTmrSignal (void)


You need to demonstrate how you implement the above mentioned APIs. That means, when implementing the above APIs, there are other internal functions which are not publicly available to the users, but nonetheless, they are required for the timer management and API implementation.

a)The timer task , RTOSTmr_Task(),

b)Any supporting functions you may need for initialization of free list RTOSTmr_init()  and start of the RTOSTmr_Task(),  The OS will call this timer initialization function as part of OSInit() during the start up.

c)Any supporting functions and all link list management required to support your design.


You may assume the following kernel functions available to you by the kernel. Use the Pthread library to simulate the RTOS functions as described below:

I.RTOSTaskCreate() creates a task. You may use pthread library pthreat_create().

II.RTOSSemCreate(0u) initializes a semaphore to have the value of 0. Semaphores are used when a task wants exclusive access to a resource, needs to synchronize its activities with an ISR or a task, or is waiting until an event occurs. You would use a semaphore to signal the occurrence of an event to one or multiple tasks, and use mutexes to guard share resources. However, technically, semaphores allow for both. Example:

RTOS_SEM  RTOSTmrSignal;

RTOSTmrSemSignal ? ? ?= RTOSSemCreate(0u);

You can use pthread_mutex_init() to implement this. (If you use pthread_cond_wait() or pthread_cond_signal () to implement the RTOSSemPend and RTOSSemPost, you don’t need to implement this function and can be left blank (see below).

 

III.RTOSSemPend (RTOS_SEM *timerSemPtr); ? ? ? ? ? ? ? ?

This is a semaphore Pend. If semaphore is taken it will wait for signal indicating time to update timers. Example:

     RTOSSemPend (RTOSSemSignal , &err);


You can use either pthread_mutex_lock() or alternatively pthread_cond_wait() to implement this.

IV.RTOSSemPost (RTOS_SEM *timerSemPtr);

This is the semaphore post operation. It will send a signal to the task that is waiting (pending) indicating that semaphore is released.Example:

      RTOSSemPost (RTOSSemSignal);

You can use either pthread_mutex_lock() or alternatively pthread_cond_signal () to implement this.

V.RTOSShedLock()

This is used to prevent OS from context switching.  In pthread library this can be left blank. You don’t need to prevent scheduling.

VI.RTOSShedUnlock()

This is used to resume the OS context switching which was previously halted by RTOSShedLock(). In pthread library this can be left blank. You don’t need to prevent scheduling.



To test your project, you need to write a program that prints the current time when timers are created. Then it creates 3 timers that register handles “function1”, “function2” and “function3”, respectively.

Timer 1 gets invoked every 5 seconds and runs function1 which prints “this is is function 1 and time is = <print current time>

Timer 2 gets invoked every 3 seconds and runs function1 which prints “this is is function 2 and time is = <print current time>

Timer 3 gets invoked only once 10 seconds after it was created and runs function3 which prints “this is is function 3 and time is = <print current time>


相關文章

【上一篇】:到頭了
【下一篇】:沒有了

版權所有:編程輔導網 2018 All Rights Reserved 聯系方式:QQ:99515681 電子信箱:[email protected]
免責聲明:本站部分內容從網絡整理而來,只供參考!如有版權問題可聯系本站刪除。

25选5一等奖多少钱