1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 22:43:50 +01:00

Merge pull request #13797 from benpicco/cpu/samd21-pwm

cpu/samd21: pwm: allow to use channels > 3
This commit is contained in:
Dylan Laduranty 2020-04-08 15:45:22 +02:00 committed by GitHub
commit f9a4c509b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

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)));
@ -167,8 +204,16 @@ void pwm_set(pwm_t dev, uint8_t channel, uint16_t value)
(pwm_config[dev].chan[channel].pin == GPIO_UNDEF)) {
return;
}
_tcc(dev)->CC[_chan(dev, channel)].reg = value;
while (_tcc(dev)->SYNCBUSY.reg & (TCC_SYNCBUSY_CC0 << _chan(dev, channel))) {}
uint8_t chan = _chan(dev, channel);
if (chan < 4) {
_tcc(dev)->CC[chan].reg = value;
while (_tcc(dev)->SYNCBUSY.reg & (TCC_SYNCBUSY_CC0 << chan)) {}
} else {
chan -= 4;
_tcc(dev)->CCB[chan].reg = value;
while (_tcc(dev)->SYNCBUSY.reg & (TCC_SYNCBUSY_CCB0 << chan)) {}
}
}
void pwm_poweron(pwm_t dev)
@ -181,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) {}