-
Notifications
You must be signed in to change notification settings - Fork 2k
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
kinetis: Implement low power modes #7897
Conversation
6ad088b
to
5b00fc7
Compare
22b9865
to
09407f6
Compare
aaf73f1
to
1ec64ba
Compare
1ec64ba
to
47fd25a
Compare
47fd25a
to
58693b7
Compare
58693b7
to
3d5448d
Compare
Updated and rebased. Tested on frdm-kw41z, mulle |
dfb92b9
to
7b85f8c
Compare
Is this the same behaviour using another UART as STDIO? I have a gut feeling that it's maybe related to the debugger... I'll try with an external USB-UART converter to see what happens. |
Hi, I played around with pr/kinetis-pm on a Kinetix KW2xD custom board At first attempt, the MCU was not going to LLS mode and was consuming >10 mA while idle. https://github.com/gebart/RIOT/blob/7ab0e94f2aaa6240fb30a963498e9238c9631b7f/cpu/kinetis/periph/uart.c#L213 Now the power consumption dropped to <1mA when idle. Line 213 PM_BLOCK happens because KW2xD has no LPUART but a defined rx_cb. But I have no idea why the second 'PM_BLOCK(KINETIS_PM_STOP);' (uart.c line 432) is never unlocked.. Beyond this minor problems, this PR works fine and is really stable on my setup. Thanks for this feature Joakim, looking forward the merge ! Olivier |
Does anyone still have bugs with this? I'm using it in practice for a long time and it's working well for me. |
I think it's because you didn't define a pin for
I can't explain that either. Possibly a side effect of manually forcing LLS mode? Are you certain that the transmitting device is returning the bus to idle state after transmitting? I don't have a Kinetis board with a UART (only LPUART) so I can't easily test that. |
I've taken some current measurements with kw41z-mini, which is like frdm-kw41z but with no onboard peripherals and no DC-DC. The only thing consuming power other than the microcontroller is the LDO which adds 1.8 uA typical under all load conditions. This means that the numbers from other boards may not compare well, but this is nearly the ideal test case for current measurement purposes. Other boards may need special handling to get onboard peripherals into their lowest power states, and the minimum current may still be higher. After programming, the board is power cycled before taking measurements. This is necessary to reset the debug hardware to prevent it from blocking PM_VLPS (it does this internally) and from adding current consumption in >PM_VLPS. (Perhaps counterintuitively, PM_LLS is the one mode unaffected by debug hardware.) Additionally, it is necessary to assert reset (or some other means of increasing power consumption) while power cycling in the event that the board is running with low enough power to continue operating from SWD/UART pin leakage and/or bypass capacitance even with main power removed. It is therefore imperative to confirm that the board actually resets when you power cycle it. At these current levels there is significant measurement error in leakage from UART, SWD, or other connected pins. It is necessary to either disconnect all pins, or tristate them and then confirm that the measurement is the same as when the pins are disconnected. Using a Raspberry Pi as the UART and SWD host, I was able to achieve tristated leakage levels lower than my measurement resolution of 10 nA on all pins except UART TX (pi->riot) which leaks 0.5 uA in my particular case. Using LLWU is necessary to retain UART RX functionality in PM_LLS with the default clock configuration. This requires a lower baud rate than 115200 or else the UART begins sampling too late after waiting ~6 us for MCGIRCLK to start. I found that 19200 works. I haven't tried to optimize this yet. All of these measurements (except for the "undefined behavior") agree well with what I'm expecting to see without specifically checking the datasheet, except perhaps the lowest one (mode 0; 5 uA) which might have room for ~50% reduction. But I didn't investigate yet so it could be normal for kw41z. All numbers below include LDO quiescent current, so subtract 1.8 uA to get the real value. tests/periph_pm:
tests/periph_pm: (with
examples/gnrc_networking:
examples/gnrc_networking: (with riotboot
examples/gnrc_networking_mac: (using LWMAC - still a work in progress on this platform)
LWMAC toggles the radio between sleep and idle fairly rapidly. With a fast enough multimeter (oscilloscope preferably, or use multimeter min/max mode) the current can be seen toggling between 5 uA and some much higher reading that will depend on the meter's ability to resolve small moments in time and especially the amount of bypass capacitance on the board. However, a good multimeter's averaging mode will give an accurate average here and I'm getting 0.59 mA average current. The reason this number is not very impressive is only that LWMAC hasn't been tuned to oblige us with an impressive number yet. Actually, what's very impressive is the fact that 0.59 mA average current agrees very well with LWMAC's reported achieved radio duty-cycle of 5% of 14 mA 🎉 |
I attempted to calculate these current consumption values from the frdm-kw41z schematic, however, as is common for low-power boards, the LEDs are being run at much lower current than the LED datasheets show on the I/V graph. Therefore the practical way to obtain the values is empirically. The calculations below are based on extrapolation of the curve, at exactly the point in the curve where it's known to turn nonlinear, which is a really bad idea. The schematic gives part number CLV1A-FKB-CJ1M1F1BB7R4S3 for LED 1-3 and LED0 = (3.30 V - 1.8 V) / 220 ohm = 6.8 mA But these values would be best obtained by measuring the voltage across each 220 ohm resistor. Then you can get a nice precise value of
That is probably explained by a combination of LED current as well as possibly having the debug circuitry active as I mentioned in the previous post. Kinetis (in hardware) will translate a PM_VLPS request to a PM_STOP request whenever the debug circuitry is active, however it does not interfere with a PM_LLS request (it just powers off the debug hardware until
That's just what happens when you unblock a mode that wasn't blocked. There's an assertion to check for that: Line 83 in 968e53b
|
I rebased this so I could clean up my branch and make sure I wasn't hiding any necessary bugfixes there. master...benemorius:pr/kinetis-pm-rebase This also includes a fix for the issue that @MichelRottleuthner found where |
Hi Benemorius, I just noticed that "llwu_rx" was not defined ('llwu_rx = LLWU_WAKEUP_PIN_UNDEF,') on my board definition. You were right ! And it's probably the cause of my UART problems. You can see here how my board is configured: I'll try to rebuild my project over your rebased branch to see if everything works properly now. Thanks again Olivier |
Hi. I could successuly build my sensor application on top of your branch
Anyway, I'm happy with this pull request and I hope It'll be merged soon ! Thanks |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
@MichelRottleuthner @benpicco anyone of you maybe want to take this over? |
@benemorius already did in #11789 |
Ah, then let's close this. |
Based on #7882Depends on
#10320,#9930Low power modes using pm_layered with automatic blocking of modes depending on what peripherals are in use.
The UART peripheral driver has been enhanced with checking of error indication flags in the RX interrupt.
TODO
Tested on FRDM-K22F, both with PIT and with LPTMR for xtimer.
The UART on the FRDM-K22F seem to collect some garbage during boot when using low power modes, resulting in the first one or two commands entered over pyterm to return error messages about command not found. Typing the same command again (by hitting enter again in pyterm) always seem to work. It does not seem to be dependent on how long we wait after boot, but rather there's some junk being collected in the internal stdio_uart RX buffer and the buffer being flushed when the first newline is received.
Tested with pyterm, picocom, and minicom to ensure that the UART is working properly both with long RX sequences (pyterm) and with single keystroke transmissions (minicom).
Example terminal output with boot garbage after flashing: