-
Notifications
You must be signed in to change notification settings - Fork 501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Loopless / low power examples. #262
base: master
Are you sure you want to change the base?
Conversation
A set of examples that demonstrate basic use of timers, interrupts, and tasks. Based on and tested on the nRF52840, but also compiles on the nRF52832 -- although you'll need an external button there.
91daf73
to
63b43fc
Compare
Great job. I've had good luck after alot of trial and error with loop, but this is so much more elegant. I should have time to port over my "loop" low power application to this next week and will let you know how it goes. Question, I'm changing the FreeRtos default tick rate from 1024 to 4 ticks per second. Any issues here besides needing to rescale? Doing this gave me a substantial power savings as others discussed. |
As I've mentioned in #165 (comment), doing so may very well prevent the device from ever entering its tickless sleep mode. Also, I believe it'll tank the accuracy of the software timers, deferred interrupts (unless you explicitly tell the scheduler to run when a higher priority task wakes), as well as starving same-priority tasks for CPU time; but those are all functional issues, not energy issues. Unfortunately, I do not have the hardware to measure actual power consumption, I've mostly been going off toggling an LED in the idle task callback (which gets run once right before the system decides to sleep, afaict). |
It was a substantial power savings going to 4 ticks even from 16. Around
4.5 ua average with a 4dBm beacon once every 2000ms reading a sht31 once
every 30 second. I did notice the timer inaccuracy you mentioned
I’ll give it a try and look at your other comment. Thanks.
…On Sun, May 5, 2019 at 3:19 PM Pol Van Aubel ***@***.***> wrote:
Question, I'm changing the FreeRtos default tick rate from 1024 to 4 ticks
per second. Any issues here besides needing to rescale? Doing this gave me
a substantial power savings as others discussed.
As I've mentioned in #165 (comment)
<#165 (comment)>,
doing so may very well prevent the device from ever entering it's tickless
sleep mode. Also, I believe it'll tank the accuracy of the software timers,
deferred interrupts (unless you explicitly tell the scheduler to run when a
higher priority task wakes), as well as starving same-priority tasks for
CPU time; but those are all functional issues, not energy issues.
Unfortunately, I do not have the hardware to measure actual power
consumption, I've mostly been going off toggling an LED in the idle task
callback (which gets run once right before the system decides to sleep,
afaict).
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#262 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABQKNA4L5PKHXQRLGPXACSDPT4XKPANCNFSM4HKX54AA>
.
|
This comment is not relevant to this PR, and we should move subsequent discussion to either the power-issue or to the Adafruit forum, but I feel it's important to provide context here.
Why that saving happens is going to depend a lot on what code you're actually running. Simplifying the mechanism a bit, freeRTOS runs "tasks" in a similar way that a desktop operating system runs processes. These tasks have priorities. There is a scheduler dividing processor time between the tasks, and the rule is basically that higher priority tasks are always serviced before lower priority tasks. Furthermore, if there are multiple same-priority tasks runnable, and no higher-priority task is runnable, then the scheduler divides the processor time between tasks. However, the scheduler is not some magical thing that is always running parallel to your tasks, that's impossible. That's where the systick comes in. Whenever the systick ticks, it fires an interrupt that invokes the scheduler, and this makes the decision what to give the next "slice" of CPU time to. (Unless a task yields explicitly, or requests a scheduler invocation explicitly, or an interrupt happens... It's a bit more complex but this is the basic idea.) Hence, if you lower the systick frequency, what you're really doing is lowering the number of times the scheduler gets to take a look and see it should actually give CPU time to another task, or resume executing the current task, or sleep the system altogether. Of course, all this isn't free -- if the scheduler decides the same task that was already running gets the next CPU timeslice, then it just returns. But if not, it has to do a context switch. Still, that's not as expensive as one might think. But lowering the tick rate on a system that only ever runs one task will reduce the number of scheduler interrupts. The problem with this is that hardly any system is ever really running just one task - there will often be some background task that needs to run once every 5 minutes, or some deferred ISR, or somesuch, and then the inaccuracy of a 4Hz tickrate is going to be annoying. Note that if the system has nothing to do (i.e. is just waiting for an interrupt or timer to fire), it will just stop the system tick entirely by itself, and then go to sleep -- but only if at least 2 tick periods of idleness is expected. So on a 4Hz tick rate, it'd have to expect to sleep for at least half a second. On a 1024Hz tick rate, only 2ms -- much easier to achieve. And it will go to sleep potentially for a lot longer than the 250ms that a 4Hz systick will cause. This is why I expect, and believe, that properly designing our systems to make use of this mechanism can lead to way better power savings than lowering the tick rate. |
Great examples. they are quite useful Thanks |
@@ -0,0 +1,60 @@ | |||
/* | |||
Blink_loopless |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change name to Blink2_loopless?
*/ | ||
|
||
// On the nRF52840, pin 7 is the UserSW/DFU switch. | ||
int interruptPin = 7; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probs can just use the defined PIN_BUTTON1
|
||
// the setup function runs once when you press reset or power the board | ||
void setup(void) { | ||
pinMode(LED_RED, OUTPUT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already defined as per your other examples
*/ | ||
|
||
// On the nRF52840, pin 7 is the UserSW/DFU switch. | ||
int interruptPin = 7; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PIN_BUTTON1
A set of examples that demonstrate basic use of timers, interrupts, and
tasks. Based on and tested on the nRF52840, but also compiles on the
nRF52832 -- although you'll need an external button there.
They're not necessarily all finished -- especially Button_interrupt_direct_to_task uses freeRTOS API directly, which on the one hand is nice to demonstrate what is possible, but on the other hand might be undesirable from a consistency point of view. But in that case, there's clearly functionality missing that I think we'd like to have. So I don't know what your standard practice is w.r.t. new examples, maybe this needs to go in develop first?