summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-03-01 12:03:38 -0500
committerGitHub <noreply@github.com>2019-03-01 12:03:38 -0500
commit7535326d38e3b1233d008f9bf296d2abacd662e1 (patch)
treeb194cc8d4d7c0b733179e2ccdd890a8be954b617
parent5af2c7fc16fc6ff1b16b1c02ee6b98b1b25f1d91 (diff)
parent3c24e893e98d158f939a8dba11c4b7783d998500 (diff)
Merge pull request #1605 from dhalbert/pwmout-tcc-lock-ccb
Use TCC LUPD lock when updating CCB
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PWMOut.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
index 19daaa14f..dd85e8c02 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,9 +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) {
- /* Wait for sync */
- }
+ while (tc->COUNT16.SYNCBUSY.reg != 0) {}
tc->COUNT16.CCBUF[0].reg = new_top;
#endif
} else {
@@ -438,14 +438,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
}