1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/sam3/periph/pwm.c

132 lines
3.6 KiB
C
Raw Normal View History

2015-06-01 16:07:00 +02:00
/*
* Copyright (C) 2015 Hamburg University of Applied Sciences
* 2016 Freie Universität Berlin
2015-06-01 16:07:00 +02:00
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
2015-06-01 16:07:00 +02:00
*/
/**
* @ingroup cpu_sam3
* @ingroup drivers_periph_pwm
2015-06-01 16:07:00 +02:00
* @{
*
* @file
* @brief CPU specific low-level PWM driver implementation for the SAM3X8E
*
* The SAM3 has only support for a single PWM device, so we accept only
* PWM_DEV(0) for this driver.
*
2015-06-01 16:07:00 +02:00
* @author Andreas "Paul" Pauli <andreas.pauli@haw-hamburg.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
2015-06-01 16:07:00 +02:00
*
* @}
*/
#include "cpu.h"
#include "assert.h"
#include "periph/pwm.h"
#include "periph/gpio.h"
2020-10-22 11:34:00 +02:00
#define ENABLE_DEBUG 0
#include "debug.h"
2015-06-01 16:07:00 +02:00
2020-10-22 11:34:00 +02:00
#define PREA_MAX (10U)
2015-06-01 16:07:00 +02:00
static uint16_t pwm_period;
static uint8_t pwm_chan_mask;
2015-06-01 16:07:00 +02:00
uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
2015-06-01 16:07:00 +02:00
{
uint32_t pwm_clk = freq * res; /* Desired/real pwm_clock */
2015-06-01 16:07:00 +02:00
uint32_t diva = 1; /* Candidate for 8bit divider */
uint32_t prea = 0; /* Candidate for clock select */
/* check for valid device and mode (left-aligned PWM only so far) */
if ((dev != PWM_DEV(0)) || (mode != PWM_LEFT)) {
return 0;
2015-06-01 16:07:00 +02:00
}
/* check if target frequency and resolution is applicable */
if (pwm_clk > CLOCK_CORECLOCK) {
return 0;
2015-06-01 16:07:00 +02:00
}
/* calculate pre-scalers for targeted frequency and resolution:
* clk = CORECLOCK / (2 ^ prea) / diva
* width prea := [0, 10] and diva [1, 255]
2015-06-01 16:07:00 +02:00
*/
while ((diva = (CLOCK_CORECLOCK / pwm_clk / (1 << prea))) > 255) {
++prea;
2015-06-01 16:07:00 +02:00
}
/* make sure PREA does not exceed its limit */
if (prea > PREA_MAX) {
return 0;
2015-06-01 16:07:00 +02:00
}
/* activate PWM block by enabling it's clock. */
2015-06-01 16:07:00 +02:00
PMC->PMC_PCER1 = PMC_PCER1_PID36;
/* disable all channels to allow CPRD updates. */
PWM->PWM_DIS = 0xff;
/* configure clock generator */
PWM->PWM_CLK = PWM_CLK_PREA(prea) | PWM_CLK_DIVA(diva);
/* remember the used resolution (for cropping inputs later) */
pwm_period = res - 1;
/* setup the configured channels */
pwm_chan_mask = 0;
for (unsigned i = 0; i < PWM_CHAN_NUMOF; i++) {
/* configure the use pin */
gpio_init_mux(pwm_chan[i].pin, GPIO_MUX_B);
/* and setup the channel */
pwm_chan_mask |= (1 << pwm_chan[i].hwchan);
PWM->PWM_CH_NUM[pwm_chan[i].hwchan].PWM_CMR = PWM_CMR_CPRE_CLKA;
PWM->PWM_CH_NUM[pwm_chan[i].hwchan].PWM_CPRD = pwm_period;
PWM->PWM_CH_NUM[pwm_chan[i].hwchan].PWM_CDTY = 0;
}
2015-06-01 16:07:00 +02:00
/* enable all configured channels */
PWM->PWM_ENA = pwm_chan_mask;
2015-06-01 16:07:00 +02:00
/* and return the actual configured frequency */
return (CLOCK_CORECLOCK / (1 << prea) / diva / res);
}
uint8_t pwm_channels(pwm_t pwm)
{
build: fix unused parameter errors cpu, sam0_common: fix unused parameter in periph/spi cpu, kinetis_common: fix unused parameter in periph/spi cpu, cc2538: fix unused param in periph/i2c cpu, cc2538: fix unused param in periph/spi cpu, sam3: fix unused param in periph/spi cpu, stm32_common: fix unused param in periph/pm cpu, stm32f3: fix unused params in periph/i2c cpu, nrf5x_common: fix unused param in periph/gpio cpu, nrf5x_common: fix unused param in periph/spi cpu, lpc2387: fix unused params in periph/spi cpu, cc2538: fix unused params in radio/netdev cpu, cc2650: fix unused params in periph/uart cpu, lm4f120: fix unused param in periph/spi cpu, lm4f120: fix unused params in periph/timer cpu, lm4f120: fix unused params in periph/uart cpu, stm32_common: fix unused params in periph/dac cpu, stm32l0: fix unused params in periph/i2c cpu, msp430fxyz: fix unused params in periph/uart cpu, mips: fix unused params cpu, cc430: fix unused-params in periph/timer cpu, msp430fxyz: fix unused params in periph/spi drivers, cc2420: fix unused param cpu, mips32r2_common: fix unused params in periph/timer cpu, cc2538: fix unused-param in periph/i2c cpu, mips32r2_common: fix unused-param in periph/timer cpu, msp430fxyz: fix unused params in periph/timer cpu, atmega_common: fix unused params in periph/spi driver, nrfmin: fix unused params cpu, cc2538_rf: fix unused params driver, netdev_ieee802514: fix unused param cpu, mip_pic32m: fix unused params cpu, lpc2387: fix unused params in periph/pwm tests/driver_sdcard_spi: fix unused params cpu, sam3: fix unused param in periph/pwm tests/driver_dynamixel: fix unused params, and style issues cpu, cc430: fix unused param in periph/rtc cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
(void)pwm;
assert(pwm == PWM_DEV(0));
return (uint8_t)PWM_CHAN_NUMOF;
2015-06-01 16:07:00 +02:00
}
/*
* Update duty-cycle in channel with value.
* If value is larger than resolution set by pwm_init() it is cropped.
*/
void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value)
2015-06-01 16:07:00 +02:00
{
build: fix unused parameter errors cpu, sam0_common: fix unused parameter in periph/spi cpu, kinetis_common: fix unused parameter in periph/spi cpu, cc2538: fix unused param in periph/i2c cpu, cc2538: fix unused param in periph/spi cpu, sam3: fix unused param in periph/spi cpu, stm32_common: fix unused param in periph/pm cpu, stm32f3: fix unused params in periph/i2c cpu, nrf5x_common: fix unused param in periph/gpio cpu, nrf5x_common: fix unused param in periph/spi cpu, lpc2387: fix unused params in periph/spi cpu, cc2538: fix unused params in radio/netdev cpu, cc2650: fix unused params in periph/uart cpu, lm4f120: fix unused param in periph/spi cpu, lm4f120: fix unused params in periph/timer cpu, lm4f120: fix unused params in periph/uart cpu, stm32_common: fix unused params in periph/dac cpu, stm32l0: fix unused params in periph/i2c cpu, msp430fxyz: fix unused params in periph/uart cpu, mips: fix unused params cpu, cc430: fix unused-params in periph/timer cpu, msp430fxyz: fix unused params in periph/spi drivers, cc2420: fix unused param cpu, mips32r2_common: fix unused params in periph/timer cpu, cc2538: fix unused-param in periph/i2c cpu, mips32r2_common: fix unused-param in periph/timer cpu, msp430fxyz: fix unused params in periph/timer cpu, atmega_common: fix unused params in periph/spi driver, nrfmin: fix unused params cpu, cc2538_rf: fix unused params driver, netdev_ieee802514: fix unused param cpu, mip_pic32m: fix unused params cpu, lpc2387: fix unused params in periph/pwm tests/driver_sdcard_spi: fix unused params cpu, sam3: fix unused param in periph/pwm tests/driver_dynamixel: fix unused params, and style issues cpu, cc430: fix unused param in periph/rtc cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
(void)pwm;
assert((pwm == PWM_DEV(0)) && (channel < PWM_CHAN_NUMOF));
2015-06-01 16:07:00 +02:00
/* clip and set new value */
value = (value > pwm_period) ? pwm_period : value;
PWM->PWM_CH_NUM[pwm_chan[channel].hwchan].PWM_CDTYUPD = value;
2015-06-01 16:07:00 +02:00
}
void pwm_poweron(pwm_t pwm)
2015-06-01 16:07:00 +02:00
{
build: fix unused parameter errors cpu, sam0_common: fix unused parameter in periph/spi cpu, kinetis_common: fix unused parameter in periph/spi cpu, cc2538: fix unused param in periph/i2c cpu, cc2538: fix unused param in periph/spi cpu, sam3: fix unused param in periph/spi cpu, stm32_common: fix unused param in periph/pm cpu, stm32f3: fix unused params in periph/i2c cpu, nrf5x_common: fix unused param in periph/gpio cpu, nrf5x_common: fix unused param in periph/spi cpu, lpc2387: fix unused params in periph/spi cpu, cc2538: fix unused params in radio/netdev cpu, cc2650: fix unused params in periph/uart cpu, lm4f120: fix unused param in periph/spi cpu, lm4f120: fix unused params in periph/timer cpu, lm4f120: fix unused params in periph/uart cpu, stm32_common: fix unused params in periph/dac cpu, stm32l0: fix unused params in periph/i2c cpu, msp430fxyz: fix unused params in periph/uart cpu, mips: fix unused params cpu, cc430: fix unused-params in periph/timer cpu, msp430fxyz: fix unused params in periph/spi drivers, cc2420: fix unused param cpu, mips32r2_common: fix unused params in periph/timer cpu, cc2538: fix unused-param in periph/i2c cpu, mips32r2_common: fix unused-param in periph/timer cpu, msp430fxyz: fix unused params in periph/timer cpu, atmega_common: fix unused params in periph/spi driver, nrfmin: fix unused params cpu, cc2538_rf: fix unused params driver, netdev_ieee802514: fix unused param cpu, mip_pic32m: fix unused params cpu, lpc2387: fix unused params in periph/pwm tests/driver_sdcard_spi: fix unused params cpu, sam3: fix unused param in periph/pwm tests/driver_dynamixel: fix unused params, and style issues cpu, cc430: fix unused param in periph/rtc cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
(void)pwm;
assert(pwm == PWM_DEV(0));
PMC->PMC_PCER1 = PMC_PCDR1_PID36;
PWM->PWM_ENA = pwm_chan_mask;
2015-06-01 16:07:00 +02:00
}
void pwm_poweroff(pwm_t pwm)
2015-06-01 16:07:00 +02:00
{
build: fix unused parameter errors cpu, sam0_common: fix unused parameter in periph/spi cpu, kinetis_common: fix unused parameter in periph/spi cpu, cc2538: fix unused param in periph/i2c cpu, cc2538: fix unused param in periph/spi cpu, sam3: fix unused param in periph/spi cpu, stm32_common: fix unused param in periph/pm cpu, stm32f3: fix unused params in periph/i2c cpu, nrf5x_common: fix unused param in periph/gpio cpu, nrf5x_common: fix unused param in periph/spi cpu, lpc2387: fix unused params in periph/spi cpu, cc2538: fix unused params in radio/netdev cpu, cc2650: fix unused params in periph/uart cpu, lm4f120: fix unused param in periph/spi cpu, lm4f120: fix unused params in periph/timer cpu, lm4f120: fix unused params in periph/uart cpu, stm32_common: fix unused params in periph/dac cpu, stm32l0: fix unused params in periph/i2c cpu, msp430fxyz: fix unused params in periph/uart cpu, mips: fix unused params cpu, cc430: fix unused-params in periph/timer cpu, msp430fxyz: fix unused params in periph/spi drivers, cc2420: fix unused param cpu, mips32r2_common: fix unused params in periph/timer cpu, cc2538: fix unused-param in periph/i2c cpu, mips32r2_common: fix unused-param in periph/timer cpu, msp430fxyz: fix unused params in periph/timer cpu, atmega_common: fix unused params in periph/spi driver, nrfmin: fix unused params cpu, cc2538_rf: fix unused params driver, netdev_ieee802514: fix unused param cpu, mip_pic32m: fix unused params cpu, lpc2387: fix unused params in periph/pwm tests/driver_sdcard_spi: fix unused params cpu, sam3: fix unused param in periph/pwm tests/driver_dynamixel: fix unused params, and style issues cpu, cc430: fix unused param in periph/rtc cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
(void)pwm;
assert(pwm == PWM_DEV(0));
PWM->PWM_ENA = 0;
PMC->PMC_PCDR1 = PMC_PCDR1_PID36;
2015-06-01 16:07:00 +02:00
}