Skip to content

Commit 468372e

Browse files
authored
Merge pull request ARMmbed#13492 from talorion/fix-PwmOut-resets-after-suspend
Fix pwm out resets after suspend
2 parents a17a481 + b1eedc0 commit 468372e

File tree

40 files changed

+1263
-573
lines changed

40 files changed

+1263
-573
lines changed

UNITTESTS/stubs/pwmout_api_stub.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
5151
{
5252
}
5353

54+
int pwmout_read_period_us(pwmout_t *obj)
55+
{
56+
return 0;
57+
}
58+
5459
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
5560
{
5661
}
@@ -63,4 +68,9 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
6368
{
6469
}
6570

71+
int pwmout_read_pulsewidth_us(pwmout_t *obj)
72+
{
73+
return 0;
74+
}
75+
6676
#endif // DEVICE_PWMOUT

drivers/include/drivers/PwmOut.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ class PwmOut {
110110
*/
111111
void period_us(int us);
112112

113+
/** Read the PWM period
114+
* @returns
115+
* The PWM period, specified in microseconds (int)
116+
*/
117+
int read_period_us();
118+
113119
/** Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
114120
* @param seconds Change the pulse width of a PWM signal specified in seconds (float)
115121
*/
@@ -125,6 +131,12 @@ class PwmOut {
125131
*/
126132
void pulsewidth_us(int us);
127133

134+
/** Read the PWM pulsewidth
135+
* @returns
136+
* The PWM pulsewith, specified in microseconds (int)
137+
*/
138+
int read_pulsewitdth_us();
139+
128140
/** Suspend PWM operation
129141
*
130142
* Control the PWM state. This is primarily intended
@@ -191,6 +203,7 @@ class PwmOut {
191203
bool _deep_sleep_locked;
192204
bool _initialized;
193205
float _duty_cycle;
206+
int _period_us;
194207
#endif
195208
};
196209

drivers/source/PwmOut.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ PwmOut::PwmOut(PinName pin) :
3030
_pin(pin),
3131
_deep_sleep_locked(false),
3232
_initialized(false),
33-
_duty_cycle(0)
33+
_duty_cycle(0),
34+
_period_us(0)
3435
{
3536
PwmOut::init();
3637
}
@@ -83,6 +84,14 @@ void PwmOut::period_us(int us)
8384
core_util_critical_section_exit();
8485
}
8586

87+
int PwmOut::read_period_us()
88+
{
89+
core_util_critical_section_enter();
90+
auto val = pwmout_read_period_us(&_pwm);
91+
core_util_critical_section_exit();
92+
return val;
93+
}
94+
8695
void PwmOut::pulsewidth(float seconds)
8796
{
8897
core_util_critical_section_enter();
@@ -104,11 +113,20 @@ void PwmOut::pulsewidth_us(int us)
104113
core_util_critical_section_exit();
105114
}
106115

116+
int PwmOut::read_pulsewitdth_us()
117+
{
118+
core_util_critical_section_enter();
119+
auto val = pwmout_read_pulsewidth_us(&_pwm);
120+
core_util_critical_section_exit();
121+
return val;
122+
}
123+
107124
void PwmOut::suspend()
108125
{
109126
core_util_critical_section_enter();
110127
if (_initialized) {
111128
_duty_cycle = PwmOut::read();
129+
_period_us = PwmOut::read_period_us();
112130
PwmOut::deinit();
113131
}
114132
core_util_critical_section_exit();
@@ -120,6 +138,7 @@ void PwmOut::resume()
120138
if (!_initialized) {
121139
PwmOut::init();
122140
PwmOut::write(_duty_cycle);
141+
PwmOut::period_us(_period_us);
123142
}
124143
core_util_critical_section_exit();
125144
}

hal/include/hal/pwmout_api.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ typedef struct pwmout_s pwmout_t;
4444
* * ::pwmout_period sets the PWM period specified in seconds, keeping the duty cycle the same
4545
* * ::pwmout_period_ms sets the PWM period specified in miliseconds, keeping the duty cycle the same
4646
* * ::pwmout_period_us sets the PWM period specified in microseconds, keeping the duty cycle the same
47+
* * ::pwmout_read_period_us reads the PWM period specified in microseconds
4748
* * ::pwmout_pulsewidth sets the PWM pulsewidth specified in seconds, keeping the period the same
4849
* * ::pwmout_pulsewidth_ms sets the PWM pulsewidth specified in miliseconds, keeping the period the same
4950
* * ::pwmout_pulsewidth_us sets the PWM pulsewidth specified in microseconds, keeping the period the same
51+
* * ::pwmout_read_pulsewidth_us read the PWM pulsewidth specified in microseconds
5052
* * The accuracy of the PWM is +/- 10%
5153
* * The PWM operations ::pwmout_write, ::pwmout_read, ::pwmout_read, ::pwmout_period_ms, ::pwmout_period_us
5254
* ::pwmout_pulsewidth, ::pwmout_pulsewidth_ms, ::pwmout_pulsewidth_us take less than 20us to complete
@@ -125,6 +127,13 @@ void pwmout_period_ms(pwmout_t *obj, int ms);
125127
*/
126128
void pwmout_period_us(pwmout_t *obj, int us);
127129

130+
/** Read the PWM period specified in microseconds
131+
*
132+
* @param obj The pwmout object
133+
* @return A int output period
134+
*/
135+
int pwmout_read_period_us(pwmout_t *obj);
136+
128137
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
129138
*
130139
* @param obj The pwmout object
@@ -146,6 +155,13 @@ void pwmout_pulsewidth_ms(pwmout_t *obj, int ms);
146155
*/
147156
void pwmout_pulsewidth_us(pwmout_t *obj, int us);
148157

158+
/** Read the PWM pulsewidth specified in microseconds
159+
*
160+
* @param obj The pwmout object
161+
* @return A int output pulsewitdth
162+
*/
163+
int pwmout_read_pulsewidth_us(pwmout_t *obj);
164+
149165
/** Get the pins that support PWM
150166
*
151167
* Return a PinMap array of pins that support PWM.

targets/TARGET_Cypress/TARGET_PSOC6/cy_pwmout_api.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
7474
}
7575
}
7676

77+
int pwmout_read_period_us(pwmout_t *obj)
78+
{
79+
return obj->period_us;
80+
}
81+
7782
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
7883
{
7984
pwmout_pulsewidth_us(obj, (int)(seconds * CY_US_PER_SECOND));
@@ -92,6 +97,11 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
9297
}
9398
}
9499

100+
int pwmout_read_pulsewidth_us(pwmout_t *obj)
101+
{
102+
return obj->width_us;
103+
}
104+
95105
const PinMap *pwmout_pinmap(void)
96106
{
97107
return PinMap_PWM_OUT;

targets/TARGET_Freescale/TARGET_K20XX/pwmout_api.c

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
static float pwm_clock = 0;
2424

25-
void pwmout_init(pwmout_t* obj, PinName pin) {
25+
void pwmout_init(pwmout_t *obj, PinName pin)
26+
{
2627
// determine the channel
2728
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
2829
MBED_ASSERT(pwm != (PWMName)NC);
@@ -36,8 +37,9 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
3637
while (clkval > 1) {
3738
clkdiv++;
3839
clkval /= 2.0;
39-
if (clkdiv == 7)
40+
if (clkdiv == 7) {
4041
break;
42+
}
4143
}
4244

4345
pwm_clock = clkval;
@@ -53,7 +55,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
5355
ftm->MODE = FTM_MODE_FTMEN_MASK;
5456
ftm->SYNC = FTM_SYNC_CNTMIN_MASK;
5557
ftm->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK | FTM_SYNCONF_SWSOC_MASK | FTM_SYNCONF_SWWRBUF_MASK;
56-
58+
5759
//Without SYNCEN set CnV does not seem to update
5860
ftm->COMBINE = FTM_COMBINE_SYNCEN0_MASK | FTM_COMBINE_SYNCEN1_MASK | FTM_COMBINE_SYNCEN2_MASK | FTM_COMBINE_SYNCEN3_MASK;
5961

@@ -64,60 +66,86 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
6466
// default to 20ms: standard for servos, and fine for e.g. brightness control
6567
pwmout_period_ms(obj, 20);
6668
pwmout_write(obj, 0.0);
67-
69+
6870
// Wire pinout
6971
pinmap_pinout(pin, PinMap_PWM);
7072
}
7173

72-
void pwmout_free(pwmout_t* obj) {}
74+
void pwmout_free(pwmout_t *obj) {}
7375

74-
void pwmout_write(pwmout_t* obj, float value) {
76+
void pwmout_write(pwmout_t *obj, float value)
77+
{
7578
if (value < 0.0) {
7679
value = 0.0;
7780
} else if (value > 1.0) {
7881
value = 1.0;
7982
}
80-
81-
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
83+
84+
while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
8285
*obj->CnV = (uint32_t)((float)(*obj->MOD + 1) * value);
83-
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
86+
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
8487
}
8588

86-
float pwmout_read(pwmout_t* obj) {
87-
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
89+
float pwmout_read(pwmout_t *obj)
90+
{
91+
while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
8892
float v = (float)(*obj->CnV) / (float)(*obj->MOD + 1);
8993
return (v > 1.0) ? (1.0) : (v);
9094
}
9195

92-
void pwmout_period(pwmout_t* obj, float seconds) {
96+
void pwmout_period(pwmout_t *obj, float seconds)
97+
{
9398
pwmout_period_us(obj, seconds * 1000000.0f);
9499
}
95100

96-
void pwmout_period_ms(pwmout_t* obj, int ms) {
101+
void pwmout_period_ms(pwmout_t *obj, int ms)
102+
{
97103
pwmout_period_us(obj, ms * 1000);
98104
}
99105

100106
// Set the PWM period, keeping the duty cycle the same.
101-
void pwmout_period_us(pwmout_t* obj, int us) {
107+
void pwmout_period_us(pwmout_t *obj, int us)
108+
{
102109
float dc = pwmout_read(obj);
103110
*obj->MOD = (uint32_t)(pwm_clock * (float)us) - 1;
104111
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
105112
pwmout_write(obj, dc);
106113
}
107114

108-
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
115+
int pwmout_read_period_us(pwmout_t *obj)
116+
{
117+
uint32_t pwm_period = 0;
118+
if (pwm_clock > 0) {
119+
pwm_period = ((*obj->MOD) + 1) / pwm_clock;
120+
}
121+
return pwm_period;
122+
}
123+
124+
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
125+
{
109126
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
110127
}
111128

112-
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
129+
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
130+
{
113131
pwmout_pulsewidth_us(obj, ms * 1000);
114132
}
115133

116-
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
134+
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
135+
{
117136
*obj->CnV = (uint32_t)(pwm_clock * (float)us);
118137
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
119138
}
120139

140+
int pwmout_read_pulsewidth_us(pwmout_t *obj)
141+
{
142+
uint32_t pwm_pulsewidth = 0;
143+
if (pwm_clock > 0) {
144+
pwm_pulsewidth = (*obj->CnV) / pwm_clock;
145+
}
146+
return pwm_pulsewidth;
147+
}
148+
121149
const PinMap *pwmout_pinmap()
122150
{
123151
return PinMap_PWM;

0 commit comments

Comments
 (0)