 Welcome everyone. My name is Ramesh Thomas. I work at Intel in the open source technology center. I've been working on the Zephyr project for about a year now. A year is a good time to stop and think what you're doing, and I did that. I find this has been one of the most interesting project I have worked on. Primarily because of the open source, you can easily get hooked to open source. There's a lot of development going on in this project now, and it is in a stage where a lot of things are getting shaped, and power management is one of them, and that makes it very interesting. I think it is a right time to be involved here. I've been mostly working on power management. Recently, I also introduced file systems into the project. Today, we'll be going into details of the APIs and the infrastructure and how it's getting used. Before that, it'll be useful to talk about the design, the reasons we did via the wave. They'll be designed certain things, the goals and the motivations. What are the problems we saw in the IoT environment in the power management, and how the Zephyr design was designed to meet those challenges. IoT could mean different things to different people depending on from which angle you're looking at and what are your interests. For some it would be the collection of data for data analytics that can help provide better services in the future. There could be other use cases like the connected wearable devices, like for example, for use in medical purpose, that can enable low-cost applications in remote areas. But all these things has one element I see is in common, and those are the tiny devices and the edge. Those are the things in the IoT, in the Internet of Things. I think without them, the concept may not be even possible. It is one of the reasons why this technology has been so widely adopted in almost all industries. One of the reason is it is easily deployable, because the size, the low-cost and the ease of setup, we don't have to run power lines to it. Some places may not even have power supplies, and the important point, it can be left unattended for months and years without having to recharge the battery, at least that is what it's supposed to be. Sometimes extending the battery life for a few more hours, it becomes critical. We take it for granted, sometimes we don't think about power management, but that's what when we look at our phone and everything, that's what it is. Sometimes even the few hours makes a huge difference. And no matter how much good your battery technology does, there will always be this requirement to extend it a little bit more. And when we do this, keep doing this, and we also extend our limit of our expectations of the battery life. And that, as I see, is more very fascinating. It enables us to think more possibilities. We can think of small computers, computers getting tinier and running on tiny sources, power sources, that can be tiny enough to even be injected into the human body to diagnose diseases. You don't have to hesitate to add features because sometimes we'll be concerned about the new features, more features will consume more power. So when you have a good power saving scheme in place, you can add more features into your product, and that will add value to your product. We talk about connectivity and security. Power management makes it even more reliable, so that it makes sure that it is available when you really actually need them. Hardware manufacturers are taking it very seriously. They're putting it, I know they'll put a lot of resources in this area. They're adding a lot of advanced power saving features. The software needs to take advantage of it. Along with those features, also an operating system, especially compared to a bare metal loop, operating system can do more. It can take advantage of this forcing features as well as other features. So it'll be a really useful, when you can take advantage of all the advancements in the SOC in the technology. So that's where Zephyr comes into the picture. So there has been studies mainly centered around the year 2020 around the number of devices, that connected intelligent devices. There are different numbers. This one I've found is 200 billion, but other ones I've found 50 billion. Whatever it is the number, it is in billions. So when you think about this numbers, it is reasonable to expect that there will be a lot of diversity in the, I mean, there'll be a lot of different ways of doing things. There will be multiple architectures, people coming from different background in these areas and this is, it's already there and it's going to get more diverse. So the Zephyr power management like the Zephyr RTOS, the core, the design goal, the main design goal is to have multiple architecture support. You write a power management solution in one architecture, you should be able to move it to another very easily. I've worked on the power management in the PC area. I find this approach taken for the IoT and embedded systems, the power management is a little different. It's no longer driven by hardware, kernel or specifications. It is actually use case driven and their usages are so diverse, so dynamic and varying. Even in the same application, the application may want to use a device in different times in performance mode, power saving mode or turn it off when it requires. And the decisions to do the power management is no longer centered in one area. You can, it'll be in multiple components. We'll make a decision, some may be doing a decision specific to SOC features, some may do with device features. So the power management infrastructure should be enabled, should be able to enable this coordination between these components, as well as it should be able to be allowed this give features tools, means to do this dynamic power saving using strategies. One thing we see when we look for a power management solution, that is maybe already the solutions already existing somewhere and you may want to get it into Zephyr. So now, when we want to do that, you will be looking at okay, I am used to doing certain things in a certain way, are those interfaces, there's kind of things available in Zephyr. So for that reason we give, we try to make it very flexible, so it is, you can find some matching, something or you can, we will be able to implement your own very easily. So that flexibility along with the various variety of options and another thing is the Zephyr OS does not enforce any one way of doing things. They have free, we have implementation, there are a lot of ways to fit it into the Zephyr power management infrastructure. So we'll see how that is done. We also need to maintain architect independence as well as do this in flexibility. So it has to be both girls has to be met. I have shown some components that are relevant to power management. Mostly we'll be talking about the device management, power management subsystem and some to some level degree, the kernel scheduler it has. And then of course, we'll be touching on other components also. While I'm at this slide, I can talk, as we talked about the architecture, independent nature of the Zephyr autos and the power management. How do we do it? So some components, this API device management, power management, they are, they explore the interfaces to the applications and those interfaces are device, independent and architecture independent. So the reason for that is the application that sits on it, I mean uses them, wouldn't have to change when you change your underlying different devices and SOCs. So now it may sound very difficult sometimes. So if I have to implement, I have to go through a lot of general generic interfaces. I have to put some, so that is not true. So all this architecture independent nature it is built into it. So if you write a driver, it automatically will fit into those things. And we give a lot of this flexibility to add SOC specific implementation. And you can just put all your SSCs even including the flows and then you can implement HAL, there's some HAL to export interface, give an interface or interface into the existing infrastructure or to give an interface to the application. So similarly for the devices, you can have shim layers. And so there's a lot of flexibility in that. So when we, this is a rough layout, an example layout. When you implement power management, and then you will be dealing with three components, the application which knows the devices the best, which is the one is using it knows when to turn it on or off or set it to low power mode. And there are these device drivers which know about the features of those devices. So it can utilize those, it knows how to set those power features. And then similarly there will be this SOC interface which as the utilizes the power saving features of the SOCs. So there are different power states that the hardware supports. Some of them may save more power while they'll have also have higher wake latencies. Well, there'll be different characteristics. So depending upon the time on the available for saving, doing a power management operation and the other conditions. So these components can make these decisions. So this all these components like as we saw that this is everywhere, all these components are making decisions in their own area. So all these components have to interact should be easily. So the power management subsystem along coordinating with the device management and the kernel, kernel to some extent will give the, will export the power management interface. So we talked about now the problems in the IoT power management area and how Zephyr approaches them from the high level. Now we'll go into the, actually how we do it. The power management, it can be seen in a category, the power management support features. So some of them are some feature that is the first one is built into the kernel, into kernel idling logic. We'll look at that first and then we'll go and the other classification is based on which area of the SOC does the power management happens. We'll go into that in detail now. So for the, for to know the, to understand the features in the kernel power saving feature, we need to take a quick look at the scheduler. There was a presentation on Tuesday where the kernel in detail of how the scheduling is done. You can refer to the recording or talk to someone in the Zephyr booth. But for this discussion, I will be covering it very briefly and only the areas that are relevant for the power management, especially this idle thread that we see here. We want to see how it gets into, it gets active. So the Zephyr, the scheduling, it is priority based and also round robin based on the equal priority thread. But for our discussion, the current discussion, we don't have to look at the round robin because we are only dealing with high priority or the priority based scheduling. So, and they are scheduled. So the threads whenever they go and wait on a semaphore or yield, they are marked non-runnable. And the next lower priority thread is scheduled. When all the threads like that are going to a wait state, finally there is one thread remaining and that is the idle thread. So this idle thread is the thread that is a special thread that is created with the lowest priority. And so the system power management is run, is implemented inside this thread. The idle thread is basically a simple loop. It is started at the beginning of the boot and it goes and waits in a CPU wait event, it uses one of the CPU's low power state. Whenever an event happens, any timer or any interrupt happens, this wake will be, it will be woken up. And when it woken up wakes up, the ISR gets executed and one of the things that the ISR, the way the kernel scheduler works is the ISR, after that it will pass on the control to the scheduler. And the scheduler, what it does is it checks is that any thread now ready to run. If a thread is ready to run, it will schedule that thread and if not, it will go back and schedule the idle thread again, so then this thing will continue. We have to, the Zephyr scheduler kernel is now tick based. It may, it will change in the future, right now it is tick based. So the timer is set in the periodic mode and every tick period there is an event and that generates an interrupt. So now if we don't do any of this power saving feature that we are going to cover in the next slide, what will happen here? At every tick, this will be woken up, even and thus all this kernel checking will be happening and it will again go back to, if there is no thread ready to run, it will go back and do the same thing. So all those processing is wasted and consumes power. To avoid that, we should not wake up until there is a thread ready to run. So how is this done in Zephyr? Whenever a thread goes to wait on a semaphore or yields, it puts itself in a queue with the timeout period and that queue is ordered in the sending order. For example, the first thread here is waited for two seconds. The second thread is waiting for seven seconds, two plus five, seven, and then you offset the difference and you keep adding them to the queue. Now we go back to this idle thread. Now we add some more components here. So we don't want to have the periodic timer keep waking us up. So what we do, we turn off the periodic mode timer because we saw that there is some thread that is not, there is no thread ready to run within that periodic mode timer period. So we turn off that and then we set the one-shot timer for the first wait period that we have. In this example, it's two seconds. So for that period, we no longer do those waking up. We just wait and if there is any other event comes, some other interrupts, it'll wake up. So if there is no other event, the timer will not unnecessarily wake it up. So we save power by doing this. One thing to note is the ISR that gets invoked as part of the event handling. And before it starts the schedule, it also turns back the periodic mode timer. So you'll be wondering what happens after this one shot, after time it will, if you don't start the periodic mode timer again, the system will be dead. So it starts the periodic mode timer again and then the things continue to go back to what it was, the periodic scheduling. So now we'll go into the system power and as we mentioned earlier, as I mentioned earlier, it is done inside the idle thread. So how do we do it? Now we saw that we have so much time here to idle. There's nothing to run. And what we use here, we use a CPU, wait on a CPU power state, but usually in this one, this feature we call it a tickless idle or event-based idling. The CPU power state feature we use has short wake latency and usually any power state feature that has a low wake latency also saves less power. But the associates have other features such as lot of, can save considerably lot more power. And the wake latency will be higher, but they can do more. If there is enough time to use any of those features, we should be using that instead. So to do that, the kernel in Zephyr by itself does not do any of those parts. So it provides the interface, the power management system provides an interface to someone implementing someone with some component that has the knowledge of the associates that it supports. It knows about the features. For that to implement power management, we export a hook function, the syssoc called syssoc suspend. This hook function will be implemented by that component. And when the system is about to go to idle, we call this hook with idle time. And that component can take a lot of decisions. They can know based on the time, it can do several power management operations. And we'll see how, what are the fort is the flow in the coming slides. Similar to that is a corresponding syssoc resume hook function. This function is kind of many times it is optional and it is a SOC specific implementation, depending on how you implement the wake from the sleep state. So we go back to the idle thread again. We saw that we do the same thing. We turn off the periodic mode timer, set the one-shot timer and call the hook function here. Now when this hook function suspend function is called, it can do two things. One is it can handle it and do some, set some power state or it can just, if it says the idle time is not enough or some other condition is not met, just return not handled. So when it's returns not handled, the tickless idle logic will use its own weight and do its own idle processing. If it returns handled, yes then it will skip the weight because there was a weight already done here. And the wake from that weight and the way the ISR then kicks in with the periodic mode timer and the scheduler is the same. And not only this awake in the weight win, it is also, if any other event comes in between, that also will stop the wait and it'll do the same thing. So before we see just a quick introduction of the categories of the power management features that can be done. In a typical SOC there are, we can categorize the power features as two categories. One is the CPU low power state. In this state, what the way discuss the is the CPU is clocked and retain most of its states. And after it is woken up, it resumes after the next instruction, after the instruction that set it into the low power state. So, and peripherals don't lose power. And the other category is the SOC deep sleep in which the CPU is power gated, it loses all states. More devices also lose states. And then the RAM is depending upon the SOC feature and the RAM may be retained or not retained. And the main category classification is done with the way the resume happens. If the CPU loses all its context, then the resume happens from the boot from the again from the reset vector. There can be different implementation like there may be boot ROM support to have a resume vector to handle those circuits. But generally the classification is based on the way where the resume path goes after the week. And there is also the power savings are different. The CPU low power states usually have less power saving, but it is also very quick in recovery. So if you have a few microseconds and you want to save power, you can use that. And if you have a long time to sleep, you can deep sleep and can save considerable power. And states like hibernate is expected to make the batteries last for more than 10 years. So quick flow, we already talked about it, but that is what I wanted to touch on what goes on inside. So first you set a wake event whenever it goes, because you know the time that was you have to idle. So you can set a wake event using any of this. It's typically used as some always on timer or RTC, the set of a wake event. And so that you can ensure that you wake up well within the idle time, so that you have enough time to do the recovery any other restorations or anything that you do so that you don't go fall right in the edge of the idle time, disrupting any of the scheduling. And you can, and it decides on different policies. There are some other subtle details that is very implementations, I think like very detailed, that is the system is suspend is entered using with the interest disabled. One of the things it has to make sure, ensure that it is when it comes back, comes out, interrupts are enabled. I saw in the idle thread, it is called within the idle thread. So that when it comes out, it has to be able to process in the next interrupts. So this is the resume we talked briefly, that is like implementation dependent. Let's see how it is used when it comes from the deep sleep wake. The deep sleep wake it comes from the reset vector S. So there are implementations. Some implementations may would have a different flow using a boot rom and some may go through the actual same path as the cold boot and then decide in order to, the idea is to restore all the context that was saved when the suspend happened and to resume exactly after the suspend part, suspend by the suspend. So it should for the suspend code, it should be seamless. It should not, it should just for, like it is containing from the next instruction. There is another place that the resume is used and which is to notify the wake event, the ISR, we saw the ISR when it comes up, it will start the schedule and the scheduler will can switch to another task. So in some architectures and in sub power states, for example, C1, when you go to the power states, C1, you have to atomically enable interrupts and then go to that halt. And when the wake happens, the control first goes to the ISR. So it doesn't go to the instruction after following out. So what happens if you have any change in each state in the suspend, you need to be, before the scheduler schedules another task, you are given a chance to restore whatever. And this, but there are other CPU power states which may not need it because which can continue after the next instruction without enabling the interrupts. So it is optional. And if you don't want it to be called, you can call this API. So that will, you can save some cycles but not getting it getting called. So device management. This is the, there is the, between the last to Zephyr 1.5 and now the next, coming in the next 1.6, we made major enhancements in this area. So we found that this is one of the very important areas in the embedded system and IoT power management. So we've added, it's already in master. It's going to, will be in there in 1.6. So main per reason it was added because many times the power, before that, the device power management was done only when the system goes to idle in the CIS SOC suspension. But that is not a really practical use case. The devices, the applications may be running with the CPU may be active, but the devices you may have to, you can always save power by turning it or turning some devices off or putting them into low power state. So to give that, we created a new infrastructure that allows that to do that. As all APIs in Zephyr, we export architecture and device independent API. So these power states are a generic four levels of power states. And so the, and the device drivers which are knows about the device's specific features can map its own features to any of these power states. The classification is done based on what we saw the actual use cases from applications. The applications would look for what, when it wants to select which power state to do, it will look how much time will it take for it to how much power is saved and how much it takes to wake up how much of the latency. So this classifications done in the, in terms of order of the state it is returned. If the more state it loses, the more time it takes for it to recover and allow to do a lot of saves and restores that will take time and it will need to be done if you have more time. Device power management is integrated with the device management interfaces. So and the one of the main thing is that every device has a device structure in there. So the drivers in the maintain for the drivers that support is for each device they support, they maintain the device state in that context structure. And then there are APIs to set and get those power state. And one feature is one, another additional thing that we had was there is no restriction on which component calls this the application drivers or the interface that we saw earlier, they all can set driver the device's power states. So the history of this device power management. First we had this, only we had the central mode as I mentioned it was done only in the system. So now we have this other mode. So that opens up a lot of new possibilities here. And these are the, so the, as I mentioned, the device, every device is a, that's for every device that is a device structure. So whenever all APIs in the device management interface requires the device structure. So the first API gets all the device structure, the array of device structures in the system and the next two are straightforward. And the last ones are something that we added earlier, mainly for the central mode but can be used any other modes also. So the devices when they start a hardware transaction which does not, should not be interrupted by a deep sleep because deep sleep will turn off power to the devices. To be not interrupted, they can set for each device that is a bit. So we'll call the base is that, this set and we see clear. And the component that is doing the power trying to go to deep sleep, we'll check this, we'll check any device or check a specific device. And before deciding whether to go to deep sleep or not. And this is how the drivers implement this interface. They implement the set and get power state and we use a control function method. And that is, but the APIs all go through the device, the device management areas. And so which is, and the applications don't see this directly. So we can go through some examples now to see how some of these things are done. So first the distributed model, how to do it. So the application, now here in this example, we have a UART and the SPI device. The application, it finds that it is done with the UART, it doesn't want to use the UART for now. So it calls that state suspend. So it could do other, other power states also. In this example, we'll set it to, so that your device actually goes off. And it will save state and goes off. And then the applications goes and waits on some semaphore or yields. And we saw in the previous slides what happens when the threads yield. Assuming the application has one thread. All the threads in the system yields. This is marked runnable, not runnable. The kernel will schedule the idle thread. So it goes to the idle thread. And we saw in the idle thread, it will turn off the periodic mode timer and it'll go to the idling logic. So in that, at that time, it will call the SoC suspend. And now the component that knows about the SoC features will be implementing the SoC suspend. We'll get this call. Now this component, in this example, it is, it checks, it doesn't want to go to deep sleep or any power state. If it is, not all the devices are already off. So it checks every, all device, it has some way to check all the devices are off. And if it is off, then it'll go to deep sleep. But here it is not. So it just returns. It could also go to some CPU for low power state which will not turn off those devices. And then the application again goes to, then it sees that the SPI is also, it has done with it and it says it turns that off also. Now next time it goes to the yields, the now, the SoC interface sees that all the devices are off and also it sees that time is good to enough to go to a deep sleep or state. So it sets the deep sleep. And the second example is to show the central mode. Now here, the application doesn't do much. It just needs, it just does yield. I mean, in reality, there will be other interfaces between the application and the SoC interface. But in this example, for this flow, we'll see that it doesn't do any device permit by itself, it just yields. And the idle thread sees the calls as a suspend. And now here the SoC interface should have some way of knowing all the devices. And one thing it can do is call the busy check functions to check if any of the, any of these devices are busy or if not, it can just turn off all the devices one by one and set the call this and the devices will save the states and go to deep sleep depending upon is the time available. And when the resume happens, it has the responsibility to again turn active, turn the devices back on. So one problem with this, this component needs to have a lot of knowledge about all these devices. So it may not be really possible at that time but enough for it to know that which device it should turn it back on here. Maybe the what was not even, it's not even being used but in this model, unless there is a way for the application to tell this interface, there may, it can be designed. So it can, the application can always, there are several communication means in this affair, the message box, mailbox and other methods to communicate. So it can always keep that informed to make a informed decision. The last example is just to show that this can be, this device PM interface can be called from multiple components. For example, the flash is dependent on the SPI. Now the application turns off flash. Now the flash knows that it depends on the SPI. So it calls set state suspend on the SPI. Now the SPI driver can decide if there are any other devices that is using it. If not, then it can decide, it can go to off. Otherwise it'll ignore this call. Similarly, when the application turns it back on, the flash can turn SPI. So this is one way to use this model. There are others like the, if you have clock trees, you can have, when the devices are turned off, you can turn off the PLLs that feed common devices. So there's a lot of ways, lot of potential to use this infrastructure. So a quick way, this is how to add a new support if you have a new board or SSC. So this is like same as any application in the Zephyr. If you check whether your board, SOC, CPU arc is already configured, supported. If not, you can quickly add them. And then using the configuration mechanism, you can enable and disable features. So if you have multiple SOCs going on, some SOCs you don't want to enable some features as of now because you are in the middle of development. You can, you have the flexibility. You can turn off, for example, deep sleep, for instance. And then you implement this hooks in the SOC interface component. And then we add the drivers and the application and they all somehow, you should have the same, your bond management, the schemes. So before we go back to somebody, we just quickly touch on something, things that are coming up. There's a lot of development going on in the kernel, yes, you might have heard in that Tuesday presentation. One area thing is coming is the Nicholas kernel. And that will have had more power saving features. And along with that, there will be different time now. This is the past takes here in the Nicholas kernel, it could be possible to pass a wall time. Currently we have the samples that we have is kind of based on the old model of the central model. And we also put clubbed everything in one application, like it's called the power management application. We got a lot of feedback saying that that is very confusing because usually the, so the power management is handled in some component like the BSP or some component that is in the, which is deal to the SOCs that we just, so then we are planning to add new examples in that way, so removing from the application, putting in this and add for different architectures. Currently the one that is there is for Cork AC. So we're going to add more for these different architectures and the distributed device examples will be part of it. So to summarize, it is the multi architecture is the supporting goal is the main goal of the power management design and we provide the way to inside the kernels idling feature from there, you can, like when you implement the Hocus Ascotas, you are part of the kernel logic. And the device power management is the new thing that is added. And then I can ask, I take questions now. Yeah, so the second question I'll come, I need more clarification, but the first one, yeah, we did look at that the latencies that is involved in the particular side of switching the timers, right? But you are pointing at the switching timers between the periodic and one shot. Yes, we are trying to, we are looking at different timer using timers and some other logic improvements in that area, we are looking at that as well. And the second question, can I use that the CISOSI suspend needs to know about the, yeah, yeah, yeah, this one, yeah. Oh, yeah, right, right, yeah, so this is just an example. So as I mentioned, there could be interactions, usually in the real case, there will be interactions between the application and the component. There will be knowledge of what has happened, what it is, it'll keep updating some state of what are those devices. So there should be a way for it to know immediately what exactly is the state of all the devices at this point. So that is implementation dependent. So instead of calling get state of each of these devices, we want to some way of knowing that some devices, all the devices are ready to, yeah, so yeah, we'll look at that, something like that. Especially you're talking about not just any, okay, well, yeah, but we're abstraction, yes, I got the point, yeah. Thanks, any question, yes. Yeah, so that is also, yeah, it has to be, there are interfaces, we have clock control interface, there is a separate clock control in the Zephyr. So it provides those features to control the clocks. There is no, currently there's like a notification of, maybe I can get back to you, someone in the Zephyr booth can explain, get more into that. So, any question or any clarifications or any of the slides, I can go back and, we have got some time, so I can also, if you want any more clarification of any of slides, I can do that too. Right, depends on the SPR driver implementation. So it is an example to show that, so if the SPR driver implements a reference count, yes, that's way to know, you can, yeah, yeah, when you get the, so the drivers implement the setState function. So when the setState is called, they get the control and they can go around, go check all their clients or whoever is using them. And if any, it is up to the driver implementation, how it maintains this. Any questions? Okay, if you have no questions, thank you. Thank you for attending.