Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Dynamic Tick Mode is a power-saving feature that was first introduced in μC/OS-III V3.05.00 and later revised in µC/OS-III V3.07.00. It is a compromise between the approaches outlined in the sections on Tickless Mode and Periodic Tick Mode in that it gives low power applications the option to utilize timing services, without the drawback of waking the system up periodically.

Benefits

  • The full set of time services is available for use.
  • Power consumption is reduced by allowing the system to stay asleep through idle periods.

Implications

  • Support for this mode is more involved than for Periodic Tick Mode.
  • Round-robin scheduling cannot be used. A build error will be generated if it is enabled.

System Behavior

Compared to Periodic Tick Mode, the system behavior changes drastically while using dynamic tick. It more closely resembles an application using tickless mode with a hardware timer, as was shown in that section. The major difference between the two cases is that dynamic tick operates alongside the kernel's timing API. For code making use of those APIs, there should be no difference between a properly-implemented Dynamic Tick BSP and the simpler Periodic Tick BSP.

Dynamic Tick

Requirements

Dynamic Tick requires a programmable hardware timer. A down-counting timer can be used, but we will assume an up-counter for the remainder of this document.

The timer must have the following characteristics:

  • A programmable ceiling value which:
    • Generates an interrupt on match
    • Sets a status bit on match
  • A counter that can be read while the timer is running
  • A frequency that is an integer multiple of the OS Tick rate

For an optimal implementation of Dynamic Tick, the following constraints should be added:

  • A timer frequency which matches the OS Tick frequency.
  • A register width with matches the width of the OS_TICK type (32-bit by default).

Dynamic Tick Model

The details of dynamic tick mode will be laid out function shown above, OSTimeDynTick(), is only a small part of the dynamic tick API. There are many more details to cover, so we've decided to lay out the rest through a number of different cases. An important detail to keep in mind is that One of the details is fundamental to the remainder of the examples, so we state it here: the Dynamic Tick Service API is always invoked either with interrupts disabled or from interrupt context. This prevents race conditions on the kernel's data structures and the hardware timer.

Case 1 - Requesting a Timeout

Dynamic tick is a best-effort service which fulfills timeout requests from the kernel. The service can only handle one request at any given time, so the kernel must ensure that the current request is valid for the nearest task delay or pend timeout.

Case 2 - Overriding the Current Request

There are situations where the current request must be overridden before it completes. For example, assume Task1 delays for 50 ticks, then Task2 runs for 10 ticks and delays for 20 ticks. This situation is illustrated below.
One final note on this case: there are situations where an override is required because we've removed a task from the tick list prematurely. This usually happens when a task pending with timeout receives the object before time is up, but it may also be due to a PendAbort or call to OSTimeDlyResume(). In any case, the situation is handled in a similar fashion. If, after the task is removed, the current timeout is too short the kernel will override it with a longer timeout request.

Case 3 - Indefinite Timeouts

Up until this point, we've been ignoring one of the services provided by One function in the dynamic tick API has been left out of the discussion until it was relevantOS_DynTickGet(). The reason it was ignored is that this function's importance becomes more evident once we delve into implementation details. The purpose of OS_DynTickGet() is to tell  allows the kernel how many of to read the ticks from our current request have been counted so farcounted towards the current request. For example, if a 50 tick timeout request is issued, OS_DynTickGet() would return 0 at the start of the request and 50 at the end of the request. It should never return a value greater than 50.

The simplest use for OS_DynTickGet() is to read the System Time. In periodic tick mode, the current system time was represented by a global variable, OSTickCtr. As its name suggests, it is a count of the number of ticks that the OS has processed since it started running. Dynamic Tick Mode throws us a curveball wrench into this because we can now have ticks that have elapsed (i.e. been counted by the timer) but have not been processed by the ISR. To remedy this situation, OSTimeGet() reads the number of ticks in this in-between state by calling OS_DynTickGet(). The value it reads is added to OSTickCtr to give the correct system time.However, OS_DynTickGet() is not only used for reading the System Time; it's primary purpose is to maintain it. Internally, the system's tick counter is updated whenever we process the tick ISR.  If we look at the scenario outlined in Case 2 once again, we'll realize that the 10 ticks which elapsed before Task2 requested a delay were never added to our tick counter because overriding the first delay request meant that OSTickUpdate() was never called by the ISR to process those ticks. You can confirm this by counting the ticks reported by the ISR, which only add up to 40 when we should see 50. To ensure that the system time is properly maintained, the kernel ensures that uses OS_DynTickGet() is used to  to make up the difference whenever a request override scenario occurs.

There is one more case to consider which is the culmination of our discussion surrounding OS_DynTickGet(). How does our model handle the case when no tasks are waiting for a timeout (i.e. the tick list is empty)? Since we don't have any tasks requesting a timeout, we need some way to keep track of time while waiting for some task to request timing services. The kernel handles this case by sending an indefinite timeout request to the Dynamic Tick Service; this is accomplished by passing 0 to OS_DynTickSet(). Since it is impossible for a real timer to count indefinitely, there will be an limit to the length of the "indefinite" timeout. The BSP handles this by programming the timer to count as many ticks as it is able. In this case, the kernel will continue to issue indefinite timeout requests until a task is added to the tick list.

The ISR only needs to worry about reporting the number of ticks elapsed. However,

Counting the ticks reported by the ISR itself, we only see 40 as opposed to the 50 which we should see.

Dynamic Tick Control Flow

Dynamic tick is most easily understood as a best-effort service which fulfills timeout requests from the kernel. The service can only handle one request at any given time, so the kernel must ensure that the current request is valid for the nearest task delay or pend timeout. For simplicity, let us assume that we have two tasks in our system which are delayed; T1 should wake up in N ticks and T2 should wake up in N+1 ticks.

 

 

Description

Dynamic Tick Mode is a power-saving feature that was first introduced in μC/OS-III V3.05.00 and later revised in µC/OS-III V3.07.00. It is a compromise between the approaches outlined in the sections on Tickless Mode and Periodic Tick Mode in that it gives low power applications the option to utilize timing services, without the drawback of waking the system up periodically.

Benefits

  • The full set of time services is available for use.
  • Power consumption is reduced by allowing the system to stay asleep through idle periods.

Implications

  • Support for this mode is more involved than for Periodic Tick Mode.
  • Round-robin scheduling cannot be used. A build error will be generated if it is enabled.

System Behavior

Compared to Periodic Tick Mode, the system behavior changes drastically while using dynamic tick. It more closely resembles an application using tickless mode with a hardware timer, as was shown in that section. The major difference between the two cases is that dynamic tick operates alongside the kernel's timing API. For code making use of those APIs, there should be no difference between a properly-implemented Dynamic Tick BSP and the simpler Periodic Tick BSP.

Dynamic Tick

Requirements

Dynamic Tick requires a programmable hardware timer. A down-counting timer can be used, but we will assume an up-counter for the remainder of this document.

The timer must have the following characteristics:

  • A programmable ceiling value which:
    • Generates an interrupt on match
    • Sets a status bit on match
  • A counter that can be read while the timer is running
  • A frequency that is an integer multiple of the OS Tick rate

For an optimal implementation of Dynamic Tick, the following constraints should be added:

  • A timer frequency which matches the OS Tick frequency.
  • A register width with matches the width of the OS_TICK type (32-bit by default).

Dynamic Tick Model

The details of dynamic tick mode will be laid out through a number of different cases. An important detail to keep in mind is that the Dynamic Tick Service is always invoked either with interrupts disabled or from interrupt context. This prevents race conditions on the kernel's data structures and the hardware timer.

Case 1 - Requesting a Timeout

Dynamic tick is a best-effort service which fulfills timeout requests from the kernel. The service can only handle one request at any given time, so the kernel must ensure that the current request is valid for the nearest task delay or pend timeout.

Case 2 - Overriding the Current Request

There are situations where the current request must be overridden before it completes. For example, assume Task1 delays for 50 ticks, then Task2 runs for 10 ticks and delays for 20 ticks. This situation is illustrated below.Up until this point, we've ignored one of the services provided by the dynamic tick API: OS_DynTickGet(). The reason is that this function's importance only becomes evident once we start exploring the implementation details. The purpose of it is to 

One final note on this case: there are situations where an override is required because we've removed a task from the tick list prematurely. This usually happens when a task pending with timeout receives the object before time is up, but it may also be due to a PendAbort or call to OSTimeDlyResume(). In any case, the situation is handled in a similar fashion. If, after the task is removed, the current timeout is too short the kernel will override it with a longer timeout request.

Case 3 - Indefinite Timeouts

When no tasks are waiting for a timeout (i.e. the tick list is empty), we don't know when the next timeout event should be generated. We need some way to postpone timeout events until a task has requested a definite timeout. The kernel handles this case by sending an indefinite timeout request to the Dynamic Tick Service; this is accomplished by passing 0 to OS_DynTickSet(). Since it is impossible for a real timer to count indefinitely, there will be an limit to the length of the "indefinite" timeout. The BSP handles this by programming the timer to count as many ticks as it is able. In this case, the kernel will continue to issue indefinite timeout requests until a task is added to the tick list.

The ISR only needs to worry about reporting the number of ticks elapsed. However,

Dynamic Tick Control Flow

Dynamic tick is most easily understood as a best-effort service which fulfills timeout requests from the kernel. The service can only handle one request at any given time, so the kernel must ensure that the current request is valid for the nearest task delay or pend timeout. For simplicity, let us assume that we have two tasks in our system which are delayed; T1 should wake up in N ticks and T2 should wake up in N+1 ticks.

 

 

Description