Skip to content

Fix pwm out resets after suspend #13492

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

Merged
merged 43 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e55421a
pwmout - add read methods for period and pulsewidth
talorion Aug 25, 2020
dc7aa87
pwmout - PSOC6 - add read methods for period and pulsewidth
talorion Aug 25, 2020
091e40e
pwmout - K20XX - add read methods for period and pulsewidth
talorion Aug 25, 2020
5763b3a
pwmout - KLXX - add read methods for period and pulsewidth
talorion Aug 25, 2020
8c2c7bd
pwmout - K66F - add read methods for period and pulsewidth
talorion Aug 25, 2020
32bcd62
pwmout - K82F - add read methods for period and pulsewidth
talorion Aug 25, 2020
ac64817
pwmout - KL27Z - add read methods for period and pulsewidth
talorion Aug 25, 2020
cbe9129
pwmout - KL43Z - add read methods for period and pulsewidth
talorion Aug 25, 2020
8aab37c
pwmout - KW41Z - add read methods for period and pulsewidth
talorion Aug 25, 2020
009191e
pwmout - K22F - add read methods for period and pulsewidth
talorion Aug 25, 2020
659bd20
pwmout - K64F - add read methods for period and pulsewidth
talorion Aug 25, 2020
a67e8d1
pwmout - GD32F30X - add read methods for period and pulsewidth
talorion Aug 25, 2020
13f57fe
pwmout - GD32F4XX - add read methods for period and pulsewidth
talorion Aug 25, 2020
b27b869
pwmout - MAX32600 - add read methods for period and pulsewidth
talorion Aug 25, 2020
d33e06e
pwmout - MAX32610 - add read methods for period and pulsewidth
talorion Aug 25, 2020
ebc2bc2
pwmout - MAX32620 - add read methods for period and pulsewidth
talorion Aug 25, 2020
fea23ef
pwmout - MAX32620C - add read methods for period and pulsewidth
talorion Aug 25, 2020
f996216
pwmout - MAX32625 - add read methods for period and pulsewidth
talorion Aug 25, 2020
3db5d7b
pwmout - MAX32630 - add read methods for period and pulsewidth
talorion Aug 25, 2020
dda71f0
pwmout - NRF52 - add read methods for period and pulsewidth
talorion Aug 25, 2020
b859d70
pwmout - M2351 - add read methods for period and pulsewidth
talorion Aug 25, 2020
1c75956
pwmout - M251 - add read methods for period and pulsewidth
talorion Aug 25, 2020
1a9d857
pwmout - M261 - add read methods for period and pulsewidth
talorion Aug 25, 2020
bdfe6a8
pwmout - M451 - add read methods for period and pulsewidth
talorion Aug 25, 2020
0512889
pwmout - M480 - add read methods for period and pulsewidth
talorion Aug 25, 2020
20dce73
pwmout - NANO100 - add read methods for period and pulsewidth
talorion Aug 25, 2020
a6f9c5b
pwmout - NUC472 - add read methods for period and pulsewidth
talorion Aug 25, 2020
fabd906
pwmout - LPC11U6X - add read methods for period and pulsewidth
talorion Aug 25, 2020
7270f29
pwmout - LPC11XX_11CXX - add read methods for period and pulsewidth
talorion Aug 25, 2020
ea6e806
pwmout - LPC176X - add read methods for period and pulsewidth
talorion Aug 25, 2020
9f83ce1
pwmout - IMX - add read methods for period and pulsewidth
talorion Aug 25, 2020
c4559ba
pwmout - RZ_A1XX - add read methods for period and pulsewidth
talorion Aug 25, 2020
2d5e517
pwmout - RZ_A2XX - add read methods for period and pulsewidth
talorion Aug 25, 2020
6a50eca
pwmout - STM - add read methods for period and pulsewidth
talorion Aug 25, 2020
067431e
pwmout - EFM32 - add read methods for period and pulsewidth
talorion Aug 25, 2020
7388ff8
pwmout - TMPM46B - add read methods for period and pulsewidth
talorion Aug 25, 2020
f2bed4d
pwmout - TMPM4G9 - add read methods for period and pulsewidth
talorion Aug 25, 2020
191ec42
pwmout - UNITTESTS - add read methods for period and pulsewidth
talorion Aug 25, 2020
6625bdb
fixed resets after suspend
talorion Aug 25, 2020
b03d80f
pwmout - fixed compile errors
talorion Aug 26, 2020
e117ef5
use descriptive variable names
talorion Sep 8, 2020
0361627
fixed order of operations
talorion Sep 8, 2020
b1eedc0
fixed order of operations
talorion Sep 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions UNITTESTS/stubs/pwmout_api_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
{
}

int pwmout_read_period_us(pwmout_t *obj)
{
return 0;
}

void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
}
Expand All @@ -63,4 +68,9 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
}

int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return 0;
}

#endif // DEVICE_PWMOUT
13 changes: 13 additions & 0 deletions drivers/include/drivers/PwmOut.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ class PwmOut {
*/
void period_us(int us);

/** Read the PWM period
* @returns
* The PWM period, specified in microseconds (int)
*/
int read_period_us();

/** Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
* @param seconds Change the pulse width of a PWM signal specified in seconds (float)
*/
Expand All @@ -125,6 +131,12 @@ class PwmOut {
*/
void pulsewidth_us(int us);

/** Read the PWM pulsewidth
* @returns
* The PWM pulsewith, specified in microseconds (int)
*/
int read_pulsewitdth_us();

/** Suspend PWM operation
*
* Control the PWM state. This is primarily intended
Expand Down Expand Up @@ -191,6 +203,7 @@ class PwmOut {
bool _deep_sleep_locked;
bool _initialized;
float _duty_cycle;
int _period_us;
#endif
};

Expand Down
21 changes: 20 additions & 1 deletion drivers/source/PwmOut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ PwmOut::PwmOut(PinName pin) :
_pin(pin),
_deep_sleep_locked(false),
_initialized(false),
_duty_cycle(0)
_duty_cycle(0),
_period_us(0)
{
PwmOut::init();
}
Expand Down Expand Up @@ -83,6 +84,14 @@ void PwmOut::period_us(int us)
core_util_critical_section_exit();
}

int PwmOut::read_period_us()
{
core_util_critical_section_enter();
auto val = pwmout_read_period_us(&_pwm);
core_util_critical_section_exit();
return val;
}

void PwmOut::pulsewidth(float seconds)
{
core_util_critical_section_enter();
Expand All @@ -104,11 +113,20 @@ void PwmOut::pulsewidth_us(int us)
core_util_critical_section_exit();
}

int PwmOut::read_pulsewitdth_us()
{
core_util_critical_section_enter();
auto val = pwmout_read_pulsewidth_us(&_pwm);
core_util_critical_section_exit();
return val;
}

void PwmOut::suspend()
{
core_util_critical_section_enter();
if (_initialized) {
_duty_cycle = PwmOut::read();
_period_us = PwmOut::read_period_us();
PwmOut::deinit();
}
core_util_critical_section_exit();
Expand All @@ -120,6 +138,7 @@ void PwmOut::resume()
if (!_initialized) {
PwmOut::init();
PwmOut::write(_duty_cycle);
PwmOut::period_us(_period_us);
}
core_util_critical_section_exit();
}
Expand Down
16 changes: 16 additions & 0 deletions hal/include/hal/pwmout_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ typedef struct pwmout_s pwmout_t;
* * ::pwmout_period sets the PWM period specified in seconds, keeping the duty cycle the same
* * ::pwmout_period_ms sets the PWM period specified in miliseconds, keeping the duty cycle the same
* * ::pwmout_period_us sets the PWM period specified in microseconds, keeping the duty cycle the same
* * ::pwmout_read_period_us reads the PWM period specified in microseconds
* * ::pwmout_pulsewidth sets the PWM pulsewidth specified in seconds, keeping the period the same
* * ::pwmout_pulsewidth_ms sets the PWM pulsewidth specified in miliseconds, keeping the period the same
* * ::pwmout_pulsewidth_us sets the PWM pulsewidth specified in microseconds, keeping the period the same
* * ::pwmout_read_pulsewidth_us read the PWM pulsewidth specified in microseconds
* * The accuracy of the PWM is +/- 10%
* * The PWM operations ::pwmout_write, ::pwmout_read, ::pwmout_read, ::pwmout_period_ms, ::pwmout_period_us
* ::pwmout_pulsewidth, ::pwmout_pulsewidth_ms, ::pwmout_pulsewidth_us take less than 20us to complete
Expand Down Expand Up @@ -125,6 +127,13 @@ void pwmout_period_ms(pwmout_t *obj, int ms);
*/
void pwmout_period_us(pwmout_t *obj, int us);

/** Read the PWM period specified in microseconds
*
* @param obj The pwmout object
* @return A int output period
*/
int pwmout_read_period_us(pwmout_t *obj);

/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
*
* @param obj The pwmout object
Expand All @@ -146,6 +155,13 @@ void pwmout_pulsewidth_ms(pwmout_t *obj, int ms);
*/
void pwmout_pulsewidth_us(pwmout_t *obj, int us);

/** Read the PWM pulsewidth specified in microseconds
*
* @param obj The pwmout object
* @return A int output pulsewitdth
*/
int pwmout_read_pulsewidth_us(pwmout_t *obj);

/** Get the pins that support PWM
*
* Return a PinMap array of pins that support PWM.
Expand Down
10 changes: 10 additions & 0 deletions targets/TARGET_Cypress/TARGET_PSOC6/cy_pwmout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
}
}

int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}

void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * CY_US_PER_SECOND));
Expand All @@ -92,6 +97,11 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
}
}

int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->width_us;
}

const PinMap *pwmout_pinmap(void)
{
return PinMap_PWM_OUT;
Expand Down
62 changes: 45 additions & 17 deletions targets/TARGET_Freescale/TARGET_K20XX/pwmout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@

static float pwm_clock = 0;

void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
Expand All @@ -36,8 +37,9 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
while (clkval > 1) {
clkdiv++;
clkval /= 2.0;
if (clkdiv == 7)
if (clkdiv == 7) {
break;
}
}

pwm_clock = clkval;
Expand All @@ -53,7 +55,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
ftm->MODE = FTM_MODE_FTMEN_MASK;
ftm->SYNC = FTM_SYNC_CNTMIN_MASK;
ftm->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK | FTM_SYNCONF_SWSOC_MASK | FTM_SYNCONF_SWWRBUF_MASK;

//Without SYNCEN set CnV does not seem to update
ftm->COMBINE = FTM_COMBINE_SYNCEN0_MASK | FTM_COMBINE_SYNCEN1_MASK | FTM_COMBINE_SYNCEN2_MASK | FTM_COMBINE_SYNCEN3_MASK;

Expand All @@ -64,60 +66,86 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write(obj, 0.0);

// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}

void pwmout_free(pwmout_t* obj) {}
void pwmout_free(pwmout_t *obj) {}

void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0) {
value = 0.0;
} else if (value > 1.0) {
value = 1.0;
}
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);

while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
*obj->CnV = (uint32_t)((float)(*obj->MOD + 1) * value);
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
}

float pwmout_read(pwmout_t* obj) {
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
float pwmout_read(pwmout_t *obj)
{
while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
float v = (float)(*obj->CnV) / (float)(*obj->MOD + 1);
return (v > 1.0) ? (1.0) : (v);
}

void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}

void pwmout_period_ms(pwmout_t* obj, int ms) {
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}

// Set the PWM period, keeping the duty cycle the same.
void pwmout_period_us(pwmout_t* obj, int us) {
void pwmout_period_us(pwmout_t *obj, int us)
{
float dc = pwmout_read(obj);
*obj->MOD = (uint32_t)(pwm_clock * (float)us) - 1;
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
pwmout_write(obj, dc);
}

void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock > 0) {
pwm_period = ((*obj->MOD) + 1) / pwm_clock;
}
return pwm_period;
}

void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}

void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}

void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
*obj->CnV = (uint32_t)(pwm_clock * (float)us);
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
}

int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock > 0) {
pwm_pulsewidth = (*obj->CnV) / pwm_clock;
}
return pwm_pulsewidth;
}

const PinMap *pwmout_pinmap()
{
return PinMap_PWM;
Expand Down
Loading