summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-06-09 15:29:02 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-06-09 15:29:02 -0700
commit9434db07b2d931132b440dc0dc574b384e74d61b (patch)
treefe7f36d919480ffdfa95be262df11758790e8026
parent43881f933d0049d08aee6c51f72f407e3a7b5007 (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.c25
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);
}