In systems based on Micrium's µC/OS-II or µC/OS-III, the procedure that must be followed to put the MCU into a low-power mode and subsequently return from that mode is largely shaped by hardware and application requirements, not the kernels.
Although increasing importance has been placed on power efficiency in the embedded space in recent years, this topic is already a very familiar one for many developers who have a background in Micriµm's µC/OS-II and µC/OS-III kernels. Micrium's engineers have long considered usage of an MCU's low-power, or "sleep," modes a common practice in kernel-based systems, and evidence of their viewpoint is clear in the original µC/OS-II book, which provides descriptions of how that kernel's idle task hook can be used as a transition point to sleep mode. Nonetheless, questions about how to leverage MCU sleep modes are not infrequent amongst kernel users, and in the post that follows we'll attempt to shed some light on a few of the confusing aspects of this essential power management technique.
Going to Sleep
Sleep modes are not, in and of themselves, typically a problem for developers. It seems that most questions on sleeping focus on the procedures for enabling and disabling such modes. In both cases, kernel providers like Micriµm can have difficulty giving a complete picture of the steps involved because the interface for configuring and controlling sleep modes is seldom identical across different hardware platforms. Further complicating the matter is the high degree of variability that exists in the sleep mode requirements of different applications. Simply put, there is no one-size-fits-all procedure for entering sleep mode.
One common question relating to sleep mode is that of where to place the code that initiates low-power operation. The answer to this question is—as the above description would suggest—highly dependent on application requirements. Perhaps the most obvious location for code that enables sleep mode in a system designed around µC/OS-II or µC/OS-III would be in the idle task, since this task, by definition, executes only when the kernel is idle, or has no application tasks to run. Thus, Micrium provides hook functions for customizing the idle task in µC/OS-II and µC/OS-III, and has traditionally described these functions as ideal locations for power-management code.
Convenient though it may be, the idle task is not always the best location for initiating a sleep mode. In certain applications, entry into such a mode, rather than depending solely on the inactivity of application tasks, might be triggered by a confluence of different events. One possible implementation for this case is illustrated in the figure below and involves a sleep-mode task that would pend on a set of event flags to wait for the various triggers. In a somewhat similar manner, the task responsible for initiating sleep mode could treat the expiration of a timer as its indication to begin low-power operation. This approach is taken in the first example project described in the NXP version of Micrium's µC/OS-III book. (The code needed to run the book's projects can be downloaded from the NXP page of Micriµm's Download Center.)
Another frequent question concerning entry into sleep mode centers on peripheral devices: What must be done to each of the devices being utilized by an application prior to sleeping? Here, again, the answer is shaped in part by application requirements. Typically, a subset of peripherals will maintain at least a reduced level of activity during sleep mode, if for no reason other than to have a means of returning from the low-power state. A particular application, however, may have additional requirements for peripherals in sleep mode; it might, in other words, need to accomplish more in its low-power state than to simply wait for a wake-up signal. Of course, what is actually possible in this respect is highly dependent on hardware, since some MCUs provide more flexibility than others in the area of sleep-mode peripheral capability.
For the most part, the answers to questions on sleep-mode exit depend on the steps that were taken to enter low-power operation. The location for the wake-up code, for example, will often be dictated by the mechanism selected at the start of low-power operation for the sleep-mode exit. In many cases, an interrupt will trigger the transition out of sleep mode and, accordingly, the exit code will be located in an ISR.
The appropriate actions to take toward peripheral devices upon waking up from sleep mode likewise depend on the details of sleep entry. Typically, devices that were disabled should simply be re-enabled—although, with the availability of numerous different sleep modes in the latest MCUs, there are certainly applications in which a return from one mode might not necessarily entail a resumption of full-power operation. In any case, the kernel imposes few burdens here, as in other aspects of low-power entry and exit. µC/OS-II and µC/OS-III do utilize a periodic interrupt source, or tick, to implement time-based services, so any application leveraging these services would need to enable the tick upon waking up from sleep mode (assuming that it was previously disabled). Otherwise, though, the choice of which peripherals to enable and disable during sleep mode transitions is largely unrelated to the kernel.
One issue that is kernel-related and that often confuses developers new to µC/OS-II and µC/OS-III is that of initialization. The kernels are typically initialized in main(), and new users are often tempted to repeat the initialization sequence upon exit from a low-power mode. However, this step is generally not needed for the same reason that re-initialization of application variables is unnecessary after sleep-mode exit. As long as RAM is persistent throughout any low-power operation, all of a system's data—kernel and application variables alike—should remain initialized.
Kernels in Power Management
For users of µC/OS-II and µC/OS-III, then, there often is not any code required by the kernel in sleep mode entry and exit, outside of that associated with the tick interrupt. However, this is not to say that kernels have no impact on power management. Both of Micrium's kernels have been used in numerous products with demanding power requirements, and the development team is at work now adding features to µC/OS-III that will enhance its low-power capabilities. These new features will likely be covered in a future blog, and they'll certainly make their way into Micrium's online documentation. You can consult this documentation now for detailed descriptions of all current µC/OS-II and µC/OS-III features, including the idle task hooks described in this post.