Skip to content

Fix for nrf52 pwm issues #7779

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 2 commits into from
Sep 6, 2018
Merged
Changes from all commits
Commits
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
41 changes: 27 additions & 14 deletions targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/pwmout_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
#define MAX_PWM_PERIOD_MS (MAX_PWM_PERIOD_US / 1000)
#define MAX_PWM_PERIOD_S ((float) MAX_PWM_PERIOD_US / 1000000.0f)

/* Sequence bit that denotes the polarity of the pwm waveform. */
#define SEQ_POLARITY_BIT (0x8000)

/* Allocate PWM instances. */
static nrf_drv_pwm_t nordic_nrf5_pwm_instance[] = {
#if PWM0_ENABLED
Expand Down Expand Up @@ -98,9 +101,6 @@ static void nordic_pwm_init(pwmout_t *obj)
.step_mode = NRF_PWM_STEP_AUTO,
};

/* Make sure PWM instance is not running before making changes. */
nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]);

/* Initialize instance with new configuration. */
ret_code_t result = nrf_drv_pwm_init(&nordic_nrf5_pwm_instance[obj->instance],
&config,
Expand All @@ -114,6 +114,9 @@ static void nordic_pwm_restart(pwmout_t *obj)
{
MBED_ASSERT(obj);

/* Uninitialize PWM instace */
nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]);

/* (Re)initialize PWM instance. */
nordic_pwm_init(obj);

Expand All @@ -140,7 +143,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
/* Get hardware instance from pinmap. */
int instance = pin_instance_pwm(pin);

MBED_ASSERT(instance < (int)(sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t)));
MBED_ASSERT(instance < (int) (sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t)));

/* Populate PWM object with default values. */
obj->instance = instance;
Expand All @@ -153,6 +156,9 @@ void pwmout_init(pwmout_t *obj, PinName pin)
obj->sequence.repeats = 0;
obj->sequence.end_delay = 0;

/* Set active low logic. */
obj->pulse |= SEQ_POLARITY_BIT;

/* Initialize PWM instance. */
nordic_pwm_init(obj);
}
Expand Down Expand Up @@ -184,17 +190,20 @@ void pwmout_write(pwmout_t *obj, float percent)
/* Find counts based on period. */
uint16_t pulse = obj->period * percent;

/* Clear sequence, but keep the polarity bit */
obj->pulse &= SEQ_POLARITY_BIT;

/* Ensure we don't overcount. */
obj->pulse = (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse;
obj->pulse |= (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse;

/* Store actual percentage passed as parameter to avoid floating point rounding errors. */
obj->percent = percent;

/* Set new duty-cycle. */
ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance],
&obj->sequence,
1,
NRF_DRV_PWM_FLAG_LOOP);
&obj->sequence,
1,
NRF_DRV_PWM_FLAG_LOOP);

MBED_ASSERT(result == NRF_SUCCESS);
}
Expand Down Expand Up @@ -266,10 +275,11 @@ void pwmout_period_us(pwmout_t *obj, int period)
}

/* Scale new count based on stored duty-cycle and new period. */
uint32_t pulse = (period * obj->pulse) / obj->period;
uint32_t pulse = (period * (obj->pulse & ~SEQ_POLARITY_BIT)) / obj->period;

/* Store new values in object. */
obj->pulse = pulse;
obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= pulse;
obj->period = period;
obj->percent = (float) pulse / (float) period;

Expand All @@ -287,8 +297,9 @@ void pwmout_pulsewidth(pwmout_t *obj, float pulse)
DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse);

/* Cap pulsewidth to period before setting it. */
if ((pulse * 1000000) > (float) obj->pulse) {
obj->pulse = obj->period;
if ((pulse * 1000000) > (float) (obj->pulse & ~SEQ_POLARITY_BIT)) {
obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= obj->period;
pwmout_pulsewidth_us(obj, obj->pulse);
} else {
pwmout_pulsewidth_us(obj, pulse * 1000000);
Expand All @@ -306,7 +317,8 @@ void pwmout_pulsewidth_ms(pwmout_t *obj, int pulse)

/* Cap pulsewidth to period before setting it. */
if ((pulse * 1000) > (int) obj->period) {
obj->pulse = obj->period;
obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= obj->period;
pwmout_pulsewidth_us(obj, obj->pulse);
} else {
pwmout_pulsewidth_us(obj, pulse * 1000);
Expand All @@ -328,7 +340,8 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int pulse)
}

/* Store new values in object. */
obj->pulse = pulse;
obj->pulse &= SEQ_POLARITY_BIT;
obj->pulse |= pulse;
obj->percent = (float) pulse / (float) obj->period;

/* Restart instance with new values. */
Expand Down