m0 tc and tcc work

This commit is contained in:
Scott Shawcroft 2018-02-13 16:44:04 -08:00
parent 6c3075bec6
commit 8479eef578
3 changed files with 57 additions and 26 deletions

View File

@ -34,6 +34,9 @@
#include "atmel_start_pins.h" #include "atmel_start_pins.h"
#include "hal/utils/include/utils_repeat_macro.h" #include "hal/utils/include/utils_repeat_macro.h"
#ifdef SAMD21
#include "hpl/gclk/hpl_gclk_base.h"
#endif
#include "samd21_pins.h" #include "samd21_pins.h"
@ -53,8 +56,16 @@ const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
#ifdef SAMD21 #ifdef SAMD21
uint8_t tcc_channels[3] = {0xf0, 0xfc, 0xfc}; uint8_t tcc_channels[3] = {0xf0, 0xfc, 0xfc};
const uint8_t tcc_cc_num[3] = {4, 2, 2}; const uint8_t tcc_cc_num[3] = {4, 2, 2};
const uint8_t tc_gclk_ids[] = {}; const uint8_t tc_gclk_ids[TC_INST_NUM] = {TC3_GCLK_ID,
const uint8_t tc_gclk_ids[5] = {TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID, TC6_GCLK_ID, TC7_GCLK_ID}; TC4_GCLK_ID,
TC5_GCLK_ID,
#ifdef TC6_GCLK_ID
, TC6_GCLK_ID
#endif
#ifdef TC7_GCLK_ID
, TC7_GCLK_ID
#endif
};
const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID}; const uint8_t tcc_gclk_ids[3] = {TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID};
#endif #endif
#ifdef SAMD51 #ifdef SAMD51
@ -120,9 +131,16 @@ static uint8_t tcc_channel(const pin_timer_t* t) {
static void tc_set_enable(Tc* tc, bool enable) { static void tc_set_enable(Tc* tc, bool enable) {
tc->COUNT16.CTRLA.bit.ENABLE = enable; tc->COUNT16.CTRLA.bit.ENABLE = enable;
#ifdef SAMD21
while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {
/* Wait for sync */
}
#endif
#ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.bit.ENABLE != 0) { while (tc->COUNT16.SYNCBUSY.bit.ENABLE != 0) {
/* Wait for sync */ /* Wait for sync */
} }
#endif
} }
static void tcc_set_enable(Tcc* tcc, bool enable) { static void tcc_set_enable(Tcc* tcc, bool enable) {
@ -132,6 +150,15 @@ static void tcc_set_enable(Tcc* tcc, bool enable) {
} }
} }
static void tc_wait_for_sync(Tc* tc) {
#ifdef SAMD21
while (tc->COUNT16.STATUS.bit.SYNCBUSY != 0) {}
#endif
#ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.reg != 0) {}
#endif
}
bool channel_ok(const pin_timer_t* t) { bool channel_ok(const pin_timer_t* t) {
uint8_t channel_bit = 1 << tcc_channel(t); uint8_t channel_bit = 1 << tcc_channel(t);
return (!t->is_tc && ((tcc_channels[t->index] & channel_bit) == 0)) || return (!t->is_tc && ((tcc_channels[t->index] & channel_bit) == 0)) ||
@ -381,9 +408,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
Tc* tc = tc_insts[t->index]; Tc* tc = tc_insts[t->index];
tc_set_enable(tc, false); tc_set_enable(tc, false);
tc->COUNT16.CTRLA.bit.SWRST = true; tc->COUNT16.CTRLA.bit.SWRST = true;
while (tc->COUNT16.SYNCBUSY.bit.SWRST != 0) { tc_wait_for_sync(tc);
/* Wait for sync */
}
} else { } else {
tcc_refcount[t->index]--; tcc_refcount[t->index]--;
tcc_channels[t->index] &= ~(1 << tcc_channel(t)); tcc_channels[t->index] &= ~(1 << tcc_channel(t));
@ -422,7 +447,12 @@ extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self,
while ((tcc->SYNCBUSY.vec.CC & (1 << channel)) != 0) { while ((tcc->SYNCBUSY.vec.CC & (1 << channel)) != 0) {
// Wait for a previous value to be written. // Wait for a previous value to be written.
} }
#ifdef SAMD21
tcc->CCB[channel].reg = adjusted_duty;
#endif
#ifdef SAMD51
tcc->CCBUF[channel].reg = adjusted_duty; tcc->CCBUF[channel].reg = adjusted_duty;
#endif
} }
} }
@ -430,9 +460,7 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
const pin_timer_t* t = self->timer; const pin_timer_t* t = self->timer;
if (t->is_tc) { if (t->is_tc) {
Tc* tc = tc_insts[t->index]; Tc* tc = tc_insts[t->index];
while (tc->COUNT16.SYNCBUSY.reg != 0) { tc_wait_for_sync(tc);
/* Wait for sync */
}
uint16_t cv = tc->COUNT16.CC[t->wave_output].reg; uint16_t cv = tc->COUNT16.CC[t->wave_output].reg;
return cv * 0xffff / tc_periods[t->index]; return cv * 0xffff / tc_periods[t->index];
} else { } else {
@ -487,39 +515,38 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
Tc* tc = tc_insts[t->index]; Tc* tc = tc_insts[t->index];
uint8_t old_divisor = tc->COUNT16.CTRLA.bit.PRESCALER; uint8_t old_divisor = tc->COUNT16.CTRLA.bit.PRESCALER;
if (new_divisor != old_divisor) { if (new_divisor != old_divisor) {
tc->COUNT16.CTRLA.bit.ENABLE = false; tc_set_enable(tc, false);
while (tc->COUNT16.SYNCBUSY.bit.ENABLE != 0) {
/* Wait for sync */
}
tc->COUNT16.CTRLA.bit.PRESCALER = new_divisor; tc->COUNT16.CTRLA.bit.PRESCALER = new_divisor;
tc->COUNT16.CTRLA.bit.ENABLE = true; tc_set_enable(tc, true);
} }
tc_periods[t->index] = new_top; tc_periods[t->index] = new_top;
while (tc->COUNT16.SYNCBUSY.reg != 0) {
/* Wait for sync */
}
#ifdef SAMD21 #ifdef SAMD21
tc->COUNT16.CC[0].reg = new_top; tc->COUNT16.CC[0].reg = new_top;
#endif #endif
#ifdef SAMD51 #ifdef SAMD51
while (tc->COUNT16.SYNCBUSY.reg != 0) {
/* Wait for sync */
}
tc->COUNT16.CCBUF[0].reg = new_top; tc->COUNT16.CCBUF[0].reg = new_top;
#endif #endif
} else { } else {
Tcc* tcc = tcc_insts[t->index]; Tcc* tcc = tcc_insts[t->index];
uint8_t old_divisor = tcc->CTRLA.bit.PRESCALER; uint8_t old_divisor = tcc->CTRLA.bit.PRESCALER;
if (new_divisor != old_divisor) { if (new_divisor != old_divisor) {
tcc->CTRLA.bit.ENABLE = false; tcc_set_enable(tcc, false);
while (tcc->SYNCBUSY.bit.ENABLE != 0) {
/* Wait for sync */
}
tcc->CTRLA.bit.PRESCALER = new_divisor; tcc->CTRLA.bit.PRESCALER = new_divisor;
tcc->CTRLA.bit.ENABLE = true; tcc_set_enable(tcc, true);
} }
tcc_periods[t->index] = new_top; tcc_periods[t->index] = new_top;
#ifdef SAMD21
tcc->PERB.bit.PERB = new_top;
#endif
#ifdef SAMD51
while (tcc->SYNCBUSY.reg != 0) { while (tcc->SYNCBUSY.reg != 0) {
/* Wait for sync */ /* Wait for sync */
} }
tcc->PERBUF.bit.PERBUF = new_top; tcc->PERBUF.bit.PERBUF = new_top;
#endif
} }
common_hal_pulseio_pwmout_set_duty_cycle(self, old_duty); common_hal_pulseio_pwmout_set_duty_cycle(self, old_duty);

View File

@ -39,12 +39,12 @@
#include "tick.h" #include "tick.h"
static pulseio_pulsein_obj_t *active_pulseins[EIC_NUMBER_OF_INTERRUPTS]; static pulseio_pulsein_obj_t *active_pulseins[EIC_EXTINT_NUM];
static uint64_t last_ms[EIC_NUMBER_OF_INTERRUPTS]; static uint64_t last_ms[EIC_EXTINT_NUM];
static uint16_t last_us[EIC_NUMBER_OF_INTERRUPTS]; static uint16_t last_us[EIC_EXTINT_NUM];
void pulsein_reset(void) { void pulsein_reset(void) {
for (int i = 0; i < EIC_NUMBER_OF_INTERRUPTS; i++) { for (int i = 0; i < EIC_EXTINT_NUM; i++) {
if (active_pulseins[i] != NULL) { if (active_pulseins[i] != NULL) {
//extint_chan_disable_callback(i, EXTINT_CALLBACK_TYPE_DETECT); //extint_chan_disable_callback(i, EXTINT_CALLBACK_TYPE_DETECT);
} }

View File

@ -386,7 +386,11 @@ PIN(PA22, EXTINT_CHANNEL(6), NO_ADC, NO_TOUCH,
SERCOM(3, 0), SERCOM(3, 0),
#ifdef SERCOM5 #ifdef SERCOM5
SERCOM(5, 0), SERCOM(5, 0),
#els0, 4)); #else
NO_SERCOM,
#endif
TC(4, 0),
TCC(0, 4));
#endif #endif
#ifdef PIN_PA23 #ifdef PIN_PA23
PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH, PIN(PA23, EXTINT_CHANNEL(7), NO_ADC, NO_TOUCH,