1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

cpu/samd21: pwm: fix GCLK_ID & APBCMASK calculation

GCLK_ID and APBCMASK entries are not always uniform.
The previous hack would already break for TCC3.

Just explosively write down the cases, there are only 5 at most.
This commit is contained in:
Benjamin Valentin 2020-04-03 00:46:46 +02:00 committed by Benjamin Valentin
parent 01c573c612
commit 4d90a9c6b5

View File

@ -30,11 +30,6 @@
#include "periph/gpio.h"
#include "periph/pwm.h"
static inline int _num(pwm_t dev)
{
return ((int)(pwm_config[dev].dev) & 0xc00) >> 10;
}
static inline Tcc *_tcc(pwm_t dev)
{
return pwm_config[dev].dev;
@ -47,10 +42,52 @@ static inline uint8_t _chan(pwm_t dev, int chan)
static int _clk_id(pwm_t dev)
{
if (_num(dev) == 2) {
Tcc *tcc = _tcc(dev);
if (tcc == TCC0) {
return TCC0_GCLK_ID;
}
if (tcc == TCC1) {
return TCC1_GCLK_ID;
}
if (tcc == TCC2) {
return TCC2_GCLK_ID;
}
return TCC0_GCLK_ID;
#ifdef TCC3
if (tcc == TCC3) {
return TCC3_GCLK_ID;
}
#endif
assert(0);
return 0;
}
static uint32_t _apbcmask_tcc(pwm_t dev)
{
Tcc *tcc = _tcc(dev);
if (tcc == TCC0) {
return PM_APBCMASK_TCC0;
}
if (tcc == TCC1) {
return PM_APBCMASK_TCC1;
}
if (tcc == TCC2) {
return PM_APBCMASK_TCC2;
}
#ifdef TCC3
if (tcc == TCC3) {
return PM_APBCMASK_TCC3;
}
#endif
assert(0);
return 0;
}
static uint8_t get_prescaler(unsigned int target, int *scale)
@ -89,7 +126,7 @@ static uint8_t get_prescaler(unsigned int target, int *scale)
static void poweron(pwm_t dev)
{
PM->APBCMASK.reg |= (PM_APBCMASK_TCC0 << _num(dev));
PM->APBCMASK.reg |= _apbcmask_tcc(dev);
GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN |
GCLK_CLKCTRL_GEN_GCLK0 |
GCLK_CLKCTRL_ID(_clk_id(dev)));
@ -189,7 +226,7 @@ void pwm_poweroff(pwm_t dev)
{
_tcc(dev)->CTRLA.reg &= ~(TCC_CTRLA_ENABLE);
PM->APBCMASK.reg &= ~(PM_APBCMASK_TCC0 << _num(dev));
PM->APBCMASK.reg &= ~_apbcmask_tcc(dev);
GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN_GCLK7 |
GCLK_CLKCTRL_ID(_clk_id(dev)));
while (GCLK->STATUS.bit.SYNCBUSY) {}