diff options
| author | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-06-09 15:29:02 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2017-06-09 15:29:02 -0700 |
| commit | 9434db07b2d931132b440dc0dc574b384e74d61b (patch) | |
| tree | fe7f36d919480ffdfa95be262df11758790e8026 | |
| parent | 43881f933d0049d08aee6c51f72f407e3a7b5007 (diff) | |
atmel-samd: Handle TCC2 correctly. Unlike the other TCCs its 16bit
rather than 24bit. Setting the period for more than a 16bit number
caused the TCC to be in a weird state where resetting it would hard
crash.
Fixes #153
| -rw-r--r-- | atmel-samd/common-hal/pulseio/PWMOut.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/atmel-samd/common-hal/pulseio/PWMOut.c b/atmel-samd/common-hal/pulseio/PWMOut.c index 11bf6f693..ff61965a7 100644 --- a/atmel-samd/common-hal/pulseio/PWMOut.c +++ b/atmel-samd/common-hal/pulseio/PWMOut.c @@ -35,6 +35,9 @@ #undef ENABLE +# define _TCC_SIZE(n,unused) TPASTE3(TCC,n,_SIZE), +# define TCC_SIZES { MREPEAT(TCC_INST_NUM, _TCC_SIZE, 0) } + uint32_t target_timer_frequencies[TC_INST_NUM + TCC_INST_NUM]; uint8_t timer_refcount[TC_INST_NUM + TCC_INST_NUM]; const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024}; @@ -55,6 +58,12 @@ void pwmout_reset(void) { } Tcc *tccs[TCC_INST_NUM] = TCC_INSTS; for (int i = 0; i < TCC_INST_NUM; i++) { + // Disable the module before resetting it. + if (tccs[i]->CTRLA.bit.ENABLE == 1) { + tccs[i]->CTRLA.bit.ENABLE = 0; + while (tccs[i]->SYNCBUSY.bit.ENABLE == 1) { + } + } tccs[i]->CTRLA.bit.SWRST = 1; } Tc *tcs[TC_INST_NUM] = TC_INSTS; @@ -63,6 +72,8 @@ void pwmout_reset(void) { continue; } tcs[i]->COUNT16.CTRLA.bit.SWRST = 1; + while (tcs[i]->COUNT16.CTRLA.bit.SWRST == 1) { + } } } @@ -142,7 +153,9 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, if (t->is_tc) { resolution = 16; } else { - resolution = 24; + // TCC resolution varies so look it up. + const uint8_t _tcc_sizes[TCC_INST_NUM] = TCC_SIZES; + resolution = _tcc_sizes[index]; } // First determine the divisor that gets us the highest resolution. uint32_t system_clock = system_cpu_clock_get_hz(); @@ -164,7 +177,10 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_PWM; config_tc.counter_16_bit.compare_capture_channel[0] = top; - tc_init(&self->tc_instance, t->tc, &config_tc); + enum status_code status = tc_init(&self->tc_instance, t->tc, &config_tc); + if (status != STATUS_OK) { + mp_raise_RuntimeError("Failed to init timer"); + } tc_enable(&self->tc_instance); } else { struct tcc_config config_tcc; @@ -174,7 +190,10 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, config_tcc.counter.period = top; config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; - tcc_init(&self->tcc_instance, t->tcc, &config_tcc); + enum status_code status = tcc_init(&self->tcc_instance, t->tcc, &config_tcc); + if (status != STATUS_OK) { + mp_raise_RuntimeError("Failed to init timer"); + } tcc_enable(&self->tcc_instance); } |
