From 808304e8276a51a6ec2ac69e6f33a908c756f722 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 28 Feb 2019 19:53:35 -0500 Subject: [PATCH 1/2] Use TCC LUPD lock when updating CCB --- ports/atmel-samd/common-hal/pulseio/PWMOut.c | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 19daaa14fd..0908f9a01a 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -328,32 +328,29 @@ extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, #endif #ifdef SAMD51 Tc* tc = tc_insts[t->index]; - while (tc->COUNT16.SYNCBUSY.bit.CC1 != 0) { - // Wait for a previous value to be written. This can wait up to one period so we do - // other stuff in the meantime. - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - } + while (tc->COUNT16.SYNCBUSY.bit.CC1 != 0) {} tc->COUNT16.CCBUF[1].reg = adjusted_duty; #endif } else { uint32_t adjusted_duty = ((uint64_t) tcc_periods[t->index]) * duty / 0xffff; uint8_t channel = tcc_channel(t); Tcc* tcc = tcc_insts[t->index]; - while ((tcc->SYNCBUSY.vec.CC & (1 << channel)) != 0) { - // Wait for a previous value to be written. This can wait up to one period so we do - // other stuff in the meantime. - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - } + + // Write into the CC buffer register, which will be transferred to the + // CC register on an UPDATE (when period is finished). + // Do clock domain syncing as necessary. + + while (tcc->SYNCBUSY.reg != 0) {} + + // Lock out double-buffering while updating the CCB value. + tcc->CTRLBSET.bit.LUPD = 1; #ifdef SAMD21 tcc->CCB[channel].reg = adjusted_duty; #endif #ifdef SAMD51 tcc->CCBUF[channel].reg = adjusted_duty; #endif + tcc->CTRLBCLR.bit.LUPD = 1; } } @@ -368,7 +365,12 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { Tcc* tcc = tcc_insts[t->index]; uint8_t channel = tcc_channel(t); uint32_t cv = 0; + + while (tcc->SYNCBUSY.bit.CTRLB) {} + #ifdef SAMD21 + // If CCBV (CCB valid) is set, the CCB value hasn't yet been copied + // to the CC value. if ((tcc->STATUS.vec.CCBV & (1 << channel)) != 0) { cv = tcc->CCB[channel].reg; } else { @@ -425,7 +427,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, tc->COUNT16.CC[0].reg = new_top; #endif #ifdef SAMD51 - while (tc->COUNT16.SYNCBUSY.reg != 0) { + while (tc->COUNT16.SYNCBUSY.reg != 0) {} /* Wait for sync */ } tc->COUNT16.CCBUF[0].reg = new_top; @@ -438,14 +440,12 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, tcc->CTRLA.bit.PRESCALER = new_divisor; tcc_set_enable(tcc, true); } + while (tcc->SYNCBUSY.reg != 0) {} tcc_periods[t->index] = new_top; #ifdef SAMD21 tcc->PERB.bit.PERB = new_top; #endif #ifdef SAMD51 - while (tcc->SYNCBUSY.reg != 0) { - /* Wait for sync */ - } tcc->PERBUF.bit.PERBUF = new_top; #endif } From 3c24e893e98d158f939a8dba11c4b7783d998500 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 28 Feb 2019 23:38:26 -0500 Subject: [PATCH 2/2] Fix SYNCBUSY loop typo. --- ports/atmel-samd/common-hal/pulseio/PWMOut.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c index 0908f9a01a..dd85e8c02d 100644 --- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c @@ -428,8 +428,6 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, #endif #ifdef SAMD51 while (tc->COUNT16.SYNCBUSY.reg != 0) {} - /* Wait for sync */ - } tc->COUNT16.CCBUF[0].reg = new_top; #endif } else {