Skip to content

Commit dcdc66b

Browse files
committed
PmwOut: Add methods to suspend and resume PWM
It is now possible to temporarily suspend PWM and safely preserve the duty cycle set. This functionality is needed to allow a device to enter deep sleep as a PWM instance prevents deep sleep in order for the timer it relies on to run so its output can be modified. The duty cycle configuration can be restored upon resuming from deep sleep.
1 parent 7eb8807 commit dcdc66b

File tree

2 files changed

+82
-9
lines changed

2 files changed

+82
-9
lines changed

drivers/PwmOut.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,24 @@ class PwmOut {
118118
*/
119119
void pulsewidth_us(int us);
120120

121+
/** Suspend PWM operation
122+
*
123+
* Control the PWM state. This is primarily intended
124+
* for temporary power-saving; This call can
125+
* allow pwm to be temporarily disabled to permit power saving without
126+
* losing device state. The subsequent function call must be PwmOut::resume
127+
* for PWM to resume; any other calls prior to resuming are undefined behavior.
128+
*/
129+
void suspend();
130+
131+
/** Resume PWM operation
132+
*
133+
* Control the PWM state. This is primarily intended
134+
* to resume PWM operations after a previous Pwmout::suspend call;
135+
* This call restores the device state prior to suspension.
136+
*/
137+
void resume();
138+
121139
/** A operator shorthand for write()
122140
* \sa PwmOut::write()
123141
*/
@@ -155,8 +173,17 @@ class PwmOut {
155173
/** Unlock deep sleep in case it is locked */
156174
void unlock_deep_sleep();
157175

176+
/** Initialize this instance */
177+
void init();
178+
179+
/** Power down this instance */
180+
void deinit();
181+
158182
pwmout_t _pwm;
183+
PinName _pin;
159184
bool _deep_sleep_locked;
185+
bool _initialized;
186+
float _duty_cycle;
160187
#endif
161188
};
162189

drivers/source/PwmOut.cpp

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,28 @@
2222

2323
#include "platform/mbed_critical.h"
2424
#include "platform/mbed_power_mgmt.h"
25+
#include "platform/mbed_assert.h"
2526

2627
namespace mbed {
2728

28-
PwmOut::PwmOut(PinName pin) : _deep_sleep_locked(false)
29+
PwmOut::PwmOut(PinName pin) :
30+
_pin(pin),
31+
_deep_sleep_locked(false),
32+
_initialized(false),
33+
_duty_cycle(0)
2934
{
30-
core_util_critical_section_enter();
31-
pwmout_init(&_pwm, pin);
32-
core_util_critical_section_exit();
35+
PwmOut::init();
3336
}
3437

3538
PwmOut::~PwmOut()
3639
{
37-
core_util_critical_section_enter();
38-
pwmout_free(&_pwm);
39-
unlock_deep_sleep();
40-
core_util_critical_section_exit();
40+
MBED_ASSERT(!_initialized);
41+
PwmOut::deinit();
4142
}
4243

4344
void PwmOut::write(float value)
4445
{
4546
core_util_critical_section_enter();
46-
lock_deep_sleep();
4747
pwmout_write(&_pwm, value);
4848
core_util_critical_section_exit();
4949
}
@@ -98,6 +98,26 @@ void PwmOut::pulsewidth_us(int us)
9898
core_util_critical_section_exit();
9999
}
100100

101+
void PwmOut::suspend()
102+
{
103+
core_util_critical_section_enter();
104+
if (_initialized) {
105+
_duty_cycle = PwmOut::read();
106+
PwmOut::deinit();
107+
}
108+
core_util_critical_section_exit();
109+
}
110+
111+
void PwmOut::resume()
112+
{
113+
core_util_critical_section_enter();
114+
if (!_initialized) {
115+
PwmOut::init();
116+
PwmOut::write(_duty_cycle);
117+
}
118+
core_util_critical_section_exit();
119+
}
120+
101121
void PwmOut::lock_deep_sleep()
102122
{
103123
if (_deep_sleep_locked == false) {
@@ -114,6 +134,32 @@ void PwmOut::unlock_deep_sleep()
114134
}
115135
}
116136

137+
void PwmOut::init()
138+
{
139+
core_util_critical_section_enter();
140+
141+
if (!_initialized) {
142+
pwmout_init(&_pwm, _pin);
143+
lock_deep_sleep();
144+
_initialized = true;
145+
}
146+
147+
core_util_critical_section_exit();
148+
}
149+
150+
void PwmOut::deinit()
151+
{
152+
core_util_critical_section_enter();
153+
154+
if (_initialized) {
155+
pwmout_free(&_pwm);
156+
unlock_deep_sleep();
157+
_initialized = false;
158+
}
159+
160+
core_util_critical_section_exit();
161+
}
162+
117163
} // namespace mbed
118164

119165
#endif // #if DEVICE_PWMOUT

0 commit comments

Comments
 (0)