Skip to content

Commit b52d1a6

Browse files
committed
Initial commit
0 parents  commit b52d1a6

File tree

11 files changed

+1865
-0
lines changed

11 files changed

+1865
-0
lines changed

Diff for: .github/workflows/render-documentation.yml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Render Documentation
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- ".github/workflows/render-documentation.ya?ml"
9+
- "examples/**"
10+
- "src/**"
11+
pull_request:
12+
branches:
13+
- main
14+
paths:
15+
- ".github/workflows/render-documentation.ya?ml"
16+
- "examples/**"
17+
- "src/**"
18+
workflow_dispatch:
19+
20+
jobs:
21+
render-docs:
22+
permissions:
23+
contents: write
24+
uses: sebromero/render-docs-github-action/.github/workflows/render-docs.yml@main
25+
with:
26+
source-path: './src'
27+
target-path: './docs/api.md'
28+
fail-on-warnings: false

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
.DS_Store

Diff for: LICENSE

+374
Large diffs are not rendered by default.

Diff for: docs/README.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Arduino Portenta H7 Low Power Libray
2+
3+
[![License](https://img.shields.io/badge/License-MPL_2.0-blue)](http://mozilla.org/MPL/2.0/)
4+
5+
The Arduino Portenta H7 Low Power library provides functionality to enable, get information about, and debug low-power modes on the Portenta H7 board.
6+
7+
## Features
8+
9+
- Functionality related to Deep Sleep
10+
- Functionality related to Standby Mode
11+
12+
## Technical Background
13+
14+
There are three different low-power modes available:
15+
16+
- Sleep Mode
17+
- Deep Sleep Mode
18+
- Standby Mode
19+
20+
### Sleep Mode
21+
22+
Sleep Mode is entered automatically in certain situations when you use the standard Arduino Mbed Core, for example, when you call delay(). But it's also the mode that saves the least power, which is why this library exists.
23+
24+
### Deep Sleep Mode
25+
26+
Deep Sleep Mode is a deeper kind of sleep that saves more power, but it's blocked by something called Deep Sleep Locks. By default, two or three such locks are held at all times. One of them is periodically acquired and then quickly released again. The other two are held continuously but can be released by calling the LowPower.allowDeepSleep() function. When no Deep Sleep Locks are held anymore, Mbed automatically replaces Sleep Mode with Deep Sleep Mode. This saves more power and is the best option if your application is meant to run all the time but you still wish to save as much power as possible.
27+
28+
In addition to the three Deep Sleep Locks already mentioned, additional locks may be held depending on the functionality you use:
29+
30+
- During I2C transfers
31+
- While some timers are running
32+
- Continuously when you use Ethernet
33+
- During SPI transfers
34+
- Continuously when you use PWM
35+
- When a callback is attached for CAN receives
36+
- Continuously when WiFi is used
37+
- Continuously when BLE is used (more than one lock may be held in this case)
38+
- At certain times, when using various serial connections
39+
40+
### Standby Mode
41+
42+
In Standby Mode, both the sketch and Mbed are entirely stopped by the library, and it asks the microcontroller to turn off almost all functionality to save power. You can wake it up from this mode in two ways: pulling the GPIO 0 pin low on the Portenta Breakout Board (no external pull-up resistor is necessary) or asking the library to wake up after a certain amount of time. The delay can be set anywhere from 1 second up to 36 hours, 24 minutes, and 32 seconds. When the board wakes up again, it's more or less in the same state as it would have been if you had pressed the reset button. You can ask the library what the board was doing before it started by calling one or a combination of the functions: modeWasD1Standby(), modeWasD2Standby(), modeWasStandby(), and modeWasStop().
43+
44+
## Usage
45+
46+
Start by including the library header file:
47+
48+
```cpp
49+
#include "Arduino_LowPowerPortentaH7.h"
50+
```
51+
52+
What you do next depends on what you want to achieve. Using only one of Deep Sleep Mode and Standby Mode might be sufficient, or you might want to combine them. If you combine them, start by enabling Deep Sleep Mode, perform any necessary work, and let the board go into Standby Mode until you need to perform more work.
53+
54+
### Deep Sleep Mode
55+
56+
The only function necessary to enable automatic Deep Sleep Mode is allowDeepSleep(). You might also find the following functions helpful: canDeepSleep(), timeSinceBoot(), timeSpentIdle(), timeSpentInSleep(), and timeSpentInDeepSleep(). Another function that can be useful when debugging Deep Sleep Locks, but not for production code, is numberOfDeepSleepLocks().
57+
58+
> [!CAUTION]
59+
> The numberOfDeepSleepLocks() function should never be used in production code because it relies on undocumented functionality in Mbed.
60+
61+
### Standby Mode
62+
63+
To use Standby Mode, you need the following functions: checkOptionBytes(), prepareOptionBytes(), standbyM7(), and standbyM4(). The option byte functions are necessary to ensure that the flash option bytes in the microcontroller are correctly set for going into Standby Mode. Additionally, you can use the following functions to check what the board was doing before it started: modeWasD1Standby(), modeWasD2Standby(), modeWasStandby(), and modeWasStop(). Only modeWasStandby() should return true if Standby Mode was entered correctly. The other functions can be handy for troubleshooting. Remember to clear the mode flags by calling resetPreviousMode() when you are done checking them.
64+
65+
The microcontroller has three power domains: one for the M7 core (D1), one for the M4 core (D2), and a separate third domain (D3) for some other functionality. modeWasD1Standby() returns true if D1 was in standby, but all three weren't at the same time, while modeWasD2Standby() returns true if D2 was in standby, but all three weren't at the same time. Both functions can return true simultaneously if D1 and D2 were in standby mode while D3 was still awake. When all three domains are in standby mode simultaneously, the microcontroller as a whole enters Standby Mode automatically, and only modeWasStandby() returns true when it wakes up again. The modeWasStop() function should never return true but can be helpful for further troubleshooting if you contact Arduino support.
66+
67+
All configuration of Standby Mode is done when calling standbyM7(). It takes one or two parameters, depending on the conditions you want to set for waking up. The first parameter is one of the flags LowPowerStandbyType::untilPinActivity and LowPowerStandbyType::untilTimeElapsed. If you want to wake up from either type of event, you can combine the flags like so: LowPowerStandbyType::untilPinActivity | LowPowerStandbyType::untilTimeElapsed. If LowPowerStandbyType::untilTimeElapsed is present, the function takes a second parameter. This parameter's preferred format is 2_h + 30_min + 45_s. You can use any combination of hours, minutes, and seconds. For example, 15_h, or 1_h + 30_min, or just 90_s. If you first have to calculate the delay in your sketch, you can also pass something like this: RTCWakeupDelay(1, 20, 30). The first number is hours, the second minutes, and the third seconds. But, the preferred option is to use _h, _min, and _s since that's more explicit.
68+
69+
> [!NOTE]
70+
> You must always upload a sketch to the M4 core, in which you call standbyM4(), even if you don't intend to use the M4 core. If you don't, the microcontroller won't enter Standby Mode as a whole, even if you call standbyM7().
71+
72+
## Examples
73+
74+
- **Standby_Example:** This example demonstrates how to enter Standby Mode for a few seconds and then wake up again. It's also possible to wake up early by pulling the GPIO 0 pin low on the Portenta Breakout Board.
75+
- **AllowDeepSleep_Example:** This example demonstrates how to enable Deep Sleep Mode.
76+
- **DeepSleepLockDebug_Example:** This example demonstrates how to debug Deep Sleep Lock problems.
77+
78+
## API
79+
80+
The API documentation can be found [here](./api.md).
81+
82+
## License
83+
84+
This library is released under the [MPL-2.0 license](http://mozilla.org/MPL/2.0/).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
********************************************************************************
3+
*
4+
* This example shows how to allow Deep Sleep on the Portenta H7.
5+
*
6+
* The blue LED turns on first, for 5 seconds. The delay is performed with a call
7+
* to delay(), which will trigger Sleep Mode automatically. Then, the red LED is
8+
* turned on for an amount of time that equals the time spent in Sleep Mode. The
9+
* expected behavior is that these two delays should be roughly equal.
10+
*
11+
* Next, the sketch makes a call to allow Deep Sleep Mode. It then turns the blue
12+
* LED on for 5 seconds again, using a delay() call exactly as last time. Next,
13+
* the green LED is turned on for an amount of time that equals the time spent in
14+
* Deep Sleep Mode. The expected behavior is that these two delays should be
15+
* roughly equal.
16+
*
17+
* Original author: A. Vidstrom (http://arduino.cc)
18+
*
19+
* This code is in the public domain
20+
*
21+
********************************************************************************
22+
*/
23+
24+
#include "Arduino_LowPowerPortentaH7.h"
25+
26+
void setup() {
27+
pinMode(LEDR, OUTPUT);
28+
pinMode(LEDB, OUTPUT);
29+
digitalWrite(LEDR, HIGH);
30+
digitalWrite(LEDG, HIGH);
31+
// Turn on the blue LED and call delay(5000) to
32+
// trigger some automatic Sleep
33+
digitalWrite(LEDB, LOW);
34+
delay(5000);
35+
digitalWrite(LEDB, HIGH);
36+
// Turn on the red LED instead, for an equal amount
37+
// of time as was spent in Sleep
38+
digitalWrite(LEDR, LOW);
39+
delayMicroseconds(LowPower.timeSpentInSleep());
40+
digitalWrite(LEDR, HIGH);
41+
// Now allow Deep Sleep
42+
LowPower.allowDeepSleep();
43+
// Turn on the blue LED and call delay(5000) to
44+
// trigger some automatic Deep Sleep
45+
digitalWrite(LEDB, LOW);
46+
delay(5000);
47+
digitalWrite(LEDB, HIGH);
48+
// Turn on the green LED instead, for an equal amount
49+
// of time as was spent in Deep Sleep
50+
digitalWrite(LEDG, LOW);
51+
delayMicroseconds(LowPower.timeSpentInDeepSleep());
52+
digitalWrite(LEDG, HIGH);
53+
}
54+
55+
void loop() {
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
********************************************************************************
3+
*
4+
* This example shows how to debug Deep Sleep Locks on the Portenta H7.
5+
*
6+
* The sketch prints a line that tells if Deep Sleep Mode is possible or not. It
7+
* also prints a line with the number of currently active Deep Sleep Locks. This
8+
* number should (in this default case) be either 2 or 3. Which of these is
9+
* printed can vary from run to run.
10+
*
11+
* Original author: A. Vidstrom (http://arduino.cc)
12+
*
13+
* This code is in the public domain
14+
*
15+
********************************************************************************
16+
*/
17+
18+
#include "Arduino_LowPowerPortentaH7.h"
19+
20+
void setup() {
21+
Serial.begin(9600);
22+
while (!Serial)
23+
;
24+
Serial.print("Deep Sleep is possible: ");
25+
LowPower.canDeepSleep() ? Serial.println("Yes") : Serial.println("No");
26+
// The expected number here is 2 or 3 (can vary from run to run)
27+
Serial.print("Number of Deep Sleep Locks currently active: ");
28+
Serial.println(LowPower.numberOfDeepSleepLocks());
29+
}
30+
31+
void loop() {
32+
}

Diff for: examples/Standby_Example/Standby_Example.ino

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
********************************************************************************
3+
*
4+
* This example shows how to get the microcontroller of the Portenta H7 into
5+
* standby mode for 10 seconds.
6+
*
7+
* Upload the same sketch to both the M7 and the M4 core.
8+
*
9+
* The LED light should follow this sequence:
10+
*
11+
* - Cyan = Both cores are running
12+
* - Yellow = The last state will follow
13+
* - Green = The microcontroller was in standby mode (not the first time)
14+
* - Yellow = The last state was just reported
15+
* - White = Standby Mode will be entered soon
16+
*
17+
* This sequence repeats indefinitely.
18+
*
19+
* Original author: A. Vidstrom (http://arduino.cc)
20+
*
21+
* This code is in the public domain
22+
*
23+
********************************************************************************
24+
*/
25+
26+
#include "Arduino_LowPowerPortentaH7.h"
27+
28+
void setup() {
29+
30+
#if defined CORE_CM7
31+
pinMode(LEDR, OUTPUT);
32+
pinMode(LEDG, OUTPUT);
33+
pinMode(LEDB, OUTPUT);
34+
if (LowPowerReturnCode::success != LowPower.checkOptionBytes())
35+
{
36+
LowPower.prepareOptionBytes();
37+
}
38+
bootM4();
39+
#endif
40+
41+
// Blue when M7 is starting and green when M4 is starting, which
42+
// gives cyan when both are starting at the same time
43+
#if defined CORE_CM7
44+
digitalWrite(LEDB, LOW);
45+
digitalWrite(LEDR, HIGH);
46+
#else
47+
digitalWrite(LEDR, HIGH);
48+
digitalWrite(LEDG, LOW);
49+
#endif
50+
delay(2500);
51+
52+
// Go silent for a second to separate the next step
53+
digitalWrite(LEDG, HIGH);
54+
digitalWrite(LEDB, HIGH);
55+
digitalWrite(LEDR, HIGH);
56+
delay(1000);
57+
58+
// Signal the previous standby mode with colors
59+
//
60+
// First, a yellow blink, then, any combination of these
61+
// in the following order:
62+
//
63+
// Green = The whole microcontroller was in standby mode
64+
// Blue = Domain 1 was in standby mode
65+
// Red = Domain 2 was in standby mode
66+
// Purple = The whole microcontroller was in stop mode
67+
//
68+
// Last, a yellow blink
69+
// -->
70+
#if defined CORE_CM7
71+
digitalWrite(LEDB, HIGH);
72+
digitalWrite(LEDR, LOW);
73+
digitalWrite(LEDG, LOW);
74+
delay(500);
75+
if (LowPower.modeWasStandby())
76+
{
77+
digitalWrite(LEDB, HIGH);
78+
digitalWrite(LEDR, HIGH);
79+
digitalWrite(LEDG, LOW);
80+
delay(2500);
81+
}
82+
if (LowPower.modeWasD1Standby())
83+
{
84+
digitalWrite(LEDB, LOW);
85+
digitalWrite(LEDR, HIGH);
86+
digitalWrite(LEDG, HIGH);
87+
delay(2500);
88+
}
89+
if (LowPower.modeWasD2Standby())
90+
{
91+
digitalWrite(LEDB, HIGH);
92+
digitalWrite(LEDR, LOW);
93+
digitalWrite(LEDG, HIGH);
94+
delay(2500);
95+
}
96+
if (LowPower.modeWasStop())
97+
{
98+
digitalWrite(LEDB, LOW);
99+
digitalWrite(LEDR, LOW);
100+
digitalWrite(LEDG, HIGH);
101+
delay(2500);
102+
}
103+
digitalWrite(LEDB, HIGH);
104+
digitalWrite(LEDR, HIGH);
105+
digitalWrite(LEDG, HIGH);
106+
delay(500);
107+
digitalWrite(LEDB, HIGH);
108+
digitalWrite(LEDR, LOW);
109+
digitalWrite(LEDG, LOW);
110+
delay(500);
111+
LowPower.resetPreviousMode();
112+
#endif
113+
// <--
114+
115+
// White to signal that sleep will happen soon
116+
#if defined CORE_CM7
117+
digitalWrite(LEDG, LOW);
118+
digitalWrite(LEDB, LOW);
119+
digitalWrite(LEDR, LOW);
120+
delay(2500);
121+
#endif
122+
123+
#if defined CORE_CM7
124+
LowPower.standbyM7(LowPowerStandbyType::untilPinActivity | LowPowerStandbyType::untilTimeElapsed, 2_s);
125+
// The following is an alternative way to go into standby for 10 seconds
126+
// LowPower.standbyM7(LowPowerStandbyType::untilTimeElapsed, RTCWakeupDelay(0, 0, 10));
127+
#else
128+
LowPower.standbyM4();
129+
#endif
130+
}
131+
132+
void loop() {
133+
}

0 commit comments

Comments
 (0)