首页 > > 详细

讲解RTOS Timer Managemen 调试、辅导R编程、R讲解、讲解R、R语言程序解析

Project 1: RTOS Timer Management
As a member of software engineering team, you are tasked to design a timer management system for the Real Time Operating Syst em 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.

Project 1: RTOS Timer Management
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
Project 1: RTOS Timer Management
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.

Project 1: RTOS Timer Management
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.

Project 1: RTOS Timer Management




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 d oubly
linked list as shown in the figure below.

(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.

(3) RTOSTmrTickCtr
(2) RTOSTmrListPtr
(1) RTOSTmrListEntries
0
Project 1: RTOS Timer Management
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” */
Project 1: RTOS Timer Management
32
33
34
35
36
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.
1
2
3
4
5
6
7
8
9
// 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,
0
RTOSTmrListEntries
RTOSTmrListPtr
RTOSTmrTickCtr
RTOSTmrNextPtr
RTOSTmrPrevPtr
RTOSTmrTickCtr 0
OS_TMR
Project 1: RTOS Timer Management
10
11
12
13
14
15
16
17
(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.
RTOSTmrListEntries
RTOSTmrListPtr
RTOSTmrTickCtr
RTOSTmrNextPtr
RTOSTmrPrevPtr
RTOSTmrTickCtr
0
OS_TMR
RTOSTmrNextPtr
RTOSTmrPrevPtr
RTOSTmrTickCtr
OS_TMR
Project 1: RTOS Timer Management
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.




Project 1: RTOS Timer Management

RTOSTmrTickCtr is incremented by RTOSTmrTask() every time the tick ISR signal the task.
Timers are inserted in the timer list by calling RTOSTmrSTart().

Project 1: RTOS Timer Management
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.
*
* opt 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.
*
* pname 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)



Project 1: RTOS Timer Management
/*
************************************************************************************************************************
* 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)

/*
***********************************************************************************************************************
Project 1: RTOS Timer Management
*
* 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)


Project 1: RTOS Timer Management

/*
***********************************************************************************************************************
*
* 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)


Project 1: RTOS Timer Management

/*
***********************************************************************************************************************
*
* 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)


Project 1: RTOS Timer Management


/*
***********************************************************************************************************************
*
* 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)



/*
Project 1: RTOS Timer Management
***********************************************************************************************************************
*
* 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:
Project 1: RTOS Timer Management
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 =
Timer 2 gets invoked every 3 seconds and runs function1 which prints “this is is function 2 and time is =
Project 1: RTOS Timer Management
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 =

联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!