Skip to content

Commit ca4f2a3

Browse files
authored
Merge pull request #3 from arduino-libraries/refactorings
Use enum to determine previous CPU mode
2 parents d70b7a0 + 5d7bd02 commit ca4f2a3

File tree

6 files changed

+70
-97
lines changed

6 files changed

+70
-97
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ In addition to the three Deep Sleep Locks already mentioned, additional locks ma
4343

4444
### 😴 Standby Mode
4545

46-
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()`.
46+
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 `wasInCPUMode()`. More information on this can be found [here](./docs).
4747

4848
## ⚖️ License
4949

Diff for: docs/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ The only function necessary to enable automatic Deep Sleep Mode is `allowDeepSle
1717
1818
### Standby Mode
1919

20-
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.
20+
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.
21+
Additionally, you can use `wasInCPUMode()` to check what the board was doing before it started:
22+
By passing one of the modes `d1DomainStandby`, `d2DomainStandby`, `standby` or `stop` as parameter you can determine in which of these modes the CPU was before it started. It's possible that the CPU was in more than one of these modes so you need to check for each mode separately to get the complete picture.
23+
Only if `wasInCPUMode(CPUMode::standby)` returns true, Standby Mode was entered correctly. The other functions can be handy for troubleshooting. Remember to clear the mode flags by calling `resetPreviousCPUModeFlags()` when you are done checking them.
2124

22-
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.
25+
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. `wasInCPUMode(CPUMode::d1DomainStandby)` returns true if D1 was in standby, but all three weren't at the same time, while `wasInCPUMode(CPUMode::d2DomainStandby)()` 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 `wasInCPUMode(CPUMode::standby)` returns true when it wakes up again. The `wasInCPUMode(CPUMode::stop)` function should never return true but can be helpful for further troubleshooting if you encounter any issues with this library.
2326

2427
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.
2528

Diff for: docs/api.md

+11-48
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ This class is specific to the Portenta H7 board.
2323
| [`allowDeepSleep`](#class_low_power_portenta_h7_1a7ed518f8205a0b7306d23b7e2a22e82b) | Make Deep Sleep possible in the default case. |
2424
| [`canDeepSleep`](#class_low_power_portenta_h7_1a07d9e0f356e40ac70655e279fbad87a9) | Check if Deep Sleep is possible or not at the moment. |
2525
| [`checkOptionBytes`](#class_low_power_portenta_h7_1a7519d3acf693f450af84312576d8e669) | Check if the option bytes are correct to enter Standby Mode. |
26-
| [`modeWasD1Standby`](#class_low_power_portenta_h7_1a4eb99fd03e8891f93d43aca4ea2329f9) | Check if the D1 domain was in Standby Mode or not. |
27-
| [`modeWasD2Standby`](#class_low_power_portenta_h7_1a81e1c97f6411de6c6df390f7cb1ef8dc) | Check if the D2 domain was in Standby Mode or not. |
28-
| [`modeWasStandby`](#class_low_power_portenta_h7_1afb2fc28d8a59bc34799e4c83a746f7c4) | Check if the whole microcontroller was in Standby Mode or not. |
29-
| [`modeWasStop`](#class_low_power_portenta_h7_1a8420caa1148e61bc4d40e9627866afe3) | Check if the whole microcontroller was in Stop Mode or not. |
26+
| [`wasInCPUMode`](#class_low_power_portenta_h7_1ae2059eb4fb01a30342b9fb6918b6ab4c) | Checks if the microcontroller was in the given standby mode before waking up. Note: It's possible that the microcontroller was in more than one of these modes during standby. Call this function multiple times to check for each mode. Important: When you're done checking, call resetStandbyModeFlags() to reset the flags so they are reported correctly the next time the microcontroller wakes up. |
27+
| [`resetPreviousCPUModeFlags`](#class_low_power_portenta_h7_1a1753e3c053b2b64b59da3cbb9b921d76) | Reset the flags that are used to determine the microcontroller's previous standby mode. This is necessary to get correct results from [wasInCPUMode()](#class_low_power_portenta_h7_1ae2059eb4fb01a30342b9fb6918b6ab4c). |
3028
| [`numberOfDeepSleepLocks`](#class_low_power_portenta_h7_1a9d2730d86abf42782261b0f03778c3bb) | Check how many Deep Sleep locks are held at the moment. |
3129
| [`prepareOptionBytes`](#class_low_power_portenta_h7_1abdc0ce13b68d3a2188702690997af2ae) | Prepare the option bytes for entry into Standby Mode. |
32-
| [`resetPreviousMode`](#class_low_power_portenta_h7_1a6f09b3ffe26355372f287ab90a451cc2) | Reset the flags behind the modeWas...() functions. |
3330
| [`standbyM4`](#class_low_power_portenta_h7_1a9e07fd4f7895a7753e7e28f99aca1ace) | Make the M4 core enter Standby Mode. |
3431
| [`standbyM7`](#class_low_power_portenta_h7_1a1eb5cec6e9604a48074f1c10ef5e7fb0) | Make the M7 core enter Standby Mode. |
3532
| [`timeSinceBoot`](#class_low_power_portenta_h7_1a4758c25574b6d099545ac8d55eff6f68) | Time since the board was booted. It reports the time since the last wake-up reset (after standby) or power-on depending on what happened last. |
@@ -73,52 +70,28 @@ Check if the option bytes are correct to enter Standby Mode.
7370
A constant from the LowPowerReturnCode enum.
7471
<hr />
7572

76-
### `modeWasD1Standby` <a id="class_low_power_portenta_h7_1a4eb99fd03e8891f93d43aca4ea2329f9" class="anchor"></a>
73+
### `wasInCPUMode` <a id="class_low_power_portenta_h7_1ae2059eb4fb01a30342b9fb6918b6ab4c" class="anchor"></a>
7774

7875
```cpp
79-
bool modeWasD1Standby() const
76+
bool wasInCPUMode( CPUMode mode) const
8077
```
8178
82-
Check if the D1 domain was in Standby Mode or not.
83-
84-
#### Returns
85-
Was: true. Was not: false;
86-
<hr />
87-
88-
### `modeWasD2Standby` <a id="class_low_power_portenta_h7_1a81e1c97f6411de6c6df390f7cb1ef8dc" class="anchor"></a>
89-
90-
```cpp
91-
bool modeWasD2Standby() const
92-
```
93-
94-
Check if the D2 domain was in Standby Mode or not.
95-
96-
#### Returns
97-
Was: true. Was not: false;
98-
<hr />
99-
100-
### `modeWasStandby` <a id="class_low_power_portenta_h7_1afb2fc28d8a59bc34799e4c83a746f7c4" class="anchor"></a>
101-
102-
```cpp
103-
bool modeWasStandby() const
104-
```
105-
106-
Check if the whole microcontroller was in Standby Mode or not.
79+
Checks if the microcontroller was in the given standby mode before waking up. Note: It's possible that the microcontroller was in more than one of these modes during standby. Call this function multiple times to check for each mode. Important: When you're done checking, call resetStandbyModeFlags() to reset the flags so they are reported correctly the next time the microcontroller wakes up.
80+
#### Parameters
81+
* `mode` The CPU mode to check.
10782
10883
#### Returns
109-
Was: true. Was not: false;
84+
True if the microcontroller was in the given mode, false otherwise.
11085
<hr />
11186
112-
### `modeWasStop` <a id="class_low_power_portenta_h7_1a8420caa1148e61bc4d40e9627866afe3" class="anchor"></a>
87+
### `resetPreviousCPUModeFlags` <a id="class_low_power_portenta_h7_1a1753e3c053b2b64b59da3cbb9b921d76" class="anchor"></a>
11388
11489
```cpp
115-
bool modeWasStop() const
90+
void resetPreviousCPUModeFlags() const
11691
```
11792

118-
Check if the whole microcontroller was in Stop Mode or not.
93+
Reset the flags that are used to determine the microcontroller's previous standby mode. This is necessary to get correct results from [wasInCPUMode()](#class_low_power_portenta_h7_1ae2059eb4fb01a30342b9fb6918b6ab4c).
11994

120-
#### Returns
121-
Was: true. Was not: false;
12295
<hr />
12396

12497
### `numberOfDeepSleepLocks` <a id="class_low_power_portenta_h7_1a9d2730d86abf42782261b0f03778c3bb" class="anchor"></a>
@@ -145,16 +118,6 @@ Prepare the option bytes for entry into Standby Mode.
145118
A constant from the LowPowerReturnCode enum.
146119
<hr />
147120

148-
### `resetPreviousMode` <a id="class_low_power_portenta_h7_1a6f09b3ffe26355372f287ab90a451cc2" class="anchor"></a>
149-
150-
```cpp
151-
void resetPreviousMode() const
152-
```
153-
154-
Reset the flags behind the modeWas...() functions.
155-
156-
<hr />
157-
158121
### `standbyM4` <a id="class_low_power_portenta_h7_1a9e07fd4f7895a7753e7e28f99aca1ace" class="anchor"></a>
159122

160123
```cpp

Diff for: examples/Standby/Standby.ino

+8-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* The microcontroller has three power domains: one for the M7 core (D1),
88
* one for the M4 core (D2), and a separate third domain (D3) for some other functionality.
99
* When all three domains are in standby mode simultaneously, the microcontroller as a whole
10-
* enters Standby Mode automatically, and `modeWasStandby()` only returns true when it wakes up again.
10+
* enters Standby Mode automatically, and `wasInCPUMode(CPUMode::standby)` returns true when it wakes up again.
1111
*
1212
* IMPORTANT: Upload the same sketch to both the M7 and the M4 core.
1313
*
@@ -75,28 +75,30 @@ void setup() {
7575
digitalWrite(LEDR, LOW);
7676
digitalWrite(LEDG, LOW);
7777
delay(500);
78-
if (LowPower.modeWasStandby())
78+
79+
80+
if (LowPower.wasInCPUMode(CPUMode::standby))
7981
{
8082
digitalWrite(LEDB, HIGH);
8183
digitalWrite(LEDR, HIGH);
8284
digitalWrite(LEDG, LOW);
8385
delay(2500);
8486
}
85-
if (LowPower.modeWasD1Standby())
87+
if (LowPower.wasInCPUMode(CPUMode::d1DomainStandby))
8688
{
8789
digitalWrite(LEDB, LOW);
8890
digitalWrite(LEDR, HIGH);
8991
digitalWrite(LEDG, HIGH);
9092
delay(2500);
9193
}
92-
if (LowPower.modeWasD2Standby())
94+
if (LowPower.wasInCPUMode(CPUMode::d2DomainStandby))
9395
{
9496
digitalWrite(LEDB, HIGH);
9597
digitalWrite(LEDR, LOW);
9698
digitalWrite(LEDG, HIGH);
9799
delay(2500);
98100
}
99-
if (LowPower.modeWasStop())
101+
if (LowPower.wasInCPUMode(CPUMode::stop))
100102
{
101103
digitalWrite(LEDB, LOW);
102104
digitalWrite(LEDR, LOW);
@@ -111,7 +113,7 @@ void setup() {
111113
digitalWrite(LEDR, LOW);
112114
digitalWrite(LEDG, LOW);
113115
delay(500);
114-
LowPower.resetPreviousMode();
116+
LowPower.resetPreviousCPUModeFlags();
115117
#endif
116118
// <--
117119

Diff for: src/Arduino_LowPowerPortentaH7.cpp

+18-17
Original file line numberDiff line numberDiff line change
@@ -210,24 +210,30 @@ LowPowerReturnCode LowPowerPortentaH7::checkOptionBytes() const
210210
return LowPowerReturnCode::success;
211211
}
212212

213-
bool LowPowerPortentaH7::modeWasD1Standby() const
213+
bool LowPowerPortentaH7::wasInCPUMode(CPUMode mode) const
214214
{
215-
return PWR->CPUCR & PWR_CPUCR_SBF_D1;
216-
}
215+
const auto registerValue = PWR->CPUCR;
217216

218-
bool LowPowerPortentaH7::modeWasD2Standby() const
219-
{
220-
return PWR->CPUCR & PWR_CPUCR_SBF_D2;
221-
}
217+
switch (mode)
218+
{
219+
case CPUMode::d1DomainStandby:
220+
return registerValue & PWR_CPUCR_SBF_D1;
221+
case CPUMode::d2DomainStandby:
222+
return registerValue & PWR_CPUCR_SBF_D2;
223+
case CPUMode::standby:
224+
return registerValue & PWR_CPUCR_SBF;
225+
case CPUMode::stop:
226+
return registerValue & PWR_CPUCR_STOPF;
227+
default:
228+
return false;
229+
}
222230

223-
bool LowPowerPortentaH7::modeWasStandby() const
224-
{
225-
return PWR->CPUCR & PWR_CPUCR_SBF;
231+
return false;
226232
}
227233

228-
bool LowPowerPortentaH7::modeWasStop() const
234+
void LowPowerPortentaH7::resetPreviousCPUModeFlags() const
229235
{
230-
return PWR->CPUCR & PWR_CPUCR_STOPF;
236+
PWR->CPUCR |= PWR_CPUCR_CSSF; // Clear standby flags
231237
}
232238

233239
uint16_t LowPowerPortentaH7::numberOfDeepSleepLocks() const
@@ -277,11 +283,6 @@ LowPowerReturnCode LowPowerPortentaH7::prepareOptionBytes() const
277283
return LowPowerReturnCode::obLaunchFailed;
278284
}
279285

280-
void LowPowerPortentaH7::resetPreviousMode() const
281-
{
282-
PWR->CPUCR |= PWR_CPUCR_CSSF;
283-
}
284-
285286
LowPowerReturnCode LowPowerPortentaH7::standbyM4() const
286287
{
287288
// Prevent Mbed from changing things

Diff for: src/Arduino_LowPowerPortentaH7.h

+27-23
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ enum class LowPowerReturnCode
5959
turningOffEthernetFailed ///< Unable to turn off Ethernet PHY chip
6060
};
6161

62+
/**
63+
* @enum CPUMode
64+
* @brief Provides the different modes of the CPU.
65+
* Those can be used to determine in which standby mode the CPU
66+
* was before waking up.
67+
*/
68+
enum class CPUMode
69+
{
70+
d1DomainStandby, ///< Standby mode for the D1 domain
71+
d2DomainStandby, ///< Standby mode for the D2 domain
72+
standby, ///< Standby mode for the whole microcontroller
73+
stop ///< Stop mode for the whole microcontroller
74+
};
75+
6276
/*
6377
********************************************************************************
6478
* Classes
@@ -273,28 +287,23 @@ class LowPowerPortentaH7 {
273287
LowPowerReturnCode checkOptionBytes() const;
274288

275289
/**
276-
* @brief Check if the D1 domain was in Standby Mode or not.
277-
* @return Was: true. Was not: false;
278-
*/
279-
bool modeWasD1Standby() const;
280-
281-
/**
282-
* @brief Check if the D2 domain was in Standby Mode or not.
283-
* @return Was: true. Was not: false;
284-
*/
285-
bool modeWasD2Standby() const;
290+
* Checks if the microcontroller was in the given CPU mode before starting.
291+
* Note: It's possible that the microcontroller was in more than one of these modes
292+
* before starting. Call this function multiple times to check for each mode.
293+
* Important: When you're done checking, call resetStandbyModeFlags() to reset the flags
294+
* so they are reported correctly the next time the microcontroller starts.
295+
* @param mode The CPU mode to check.
296+
* @return True if the microcontroller was in the given mode, false otherwise.
297+
*/
298+
bool wasInCPUMode(CPUMode mode) const;
286299

287300
/**
288-
* @brief Check if the whole microcontroller was in Standby Mode or not.
289-
* @return Was: true. Was not: false;
301+
* @brief Reset the flags that are used to determine the microcontroller's
302+
* previous CPU mode. This is necessary to get correct results from
303+
* wasInCPUMode().
290304
*/
291-
bool modeWasStandby() const;
305+
void resetPreviousCPUModeFlags() const;
292306

293-
/**
294-
* @brief Check if the whole microcontroller was in Stop Mode or not.
295-
* @return Was: true. Was not: false;
296-
*/
297-
bool modeWasStop() const;
298307

299308
// The deprecated attribute is used here because we only want this
300309
// warning to be shown if the user actually calls the function
@@ -311,11 +320,6 @@ class LowPowerPortentaH7 {
311320
*/
312321
LowPowerReturnCode prepareOptionBytes() const;
313322

314-
/**
315-
* @brief Reset the flags behind the modeWas...() functions.
316-
*/
317-
void resetPreviousMode() const;
318-
319323
/**
320324
* @brief Make the M4 core enter Standby Mode.
321325
* @return A constant from the LowPowerReturnCode enum.

0 commit comments

Comments
 (0)