Skip to content
Snippets Groups Projects
Commit 01e5c056 authored by Paul Rathgeb's avatar Paul Rathgeb
Browse files

cpu/lpc11u34 : Added PWM support for the NXP LPC11U34

and added PWM capabilities to the board WeIO
parent fcdcfa10
No related branches found
No related tags found
No related merge requests found
......@@ -2,4 +2,5 @@ FEATURES_PROVIDED += cpp
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_pwm
FEATURES_MCU_GROUP = cortex_m0
......@@ -33,15 +33,15 @@ extern "C" {
#define TIMER_IRQ_PRIO 1
/* Timer 0 configuration */
#define TIMER_0_DEV LPC_CT32B0
#define TIMER_0_DEV LPC_CT32B1
#define TIMER_0_CHANNELS 4
#define TIMER_0_PRESCALER (48U)
#define TIMER_0_MAX_VALUE (0xffffffff)
#define TIMER_0_CLKEN() (LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9))
#define TIMER_0_CLKDIS() (LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 9))
#define TIMER_0_ISR isr_ct32b0
#define TIMER_0_IRQ TIMER_32_0_IRQn
/** @} */
#define TIMER_0_CLKEN() (LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 10))
#define TIMER_0_CLKDIS() (LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 10))
#define TIMER_0_ISR isr_ct32b1
#define TIMER_0_IRQ TIMER_32_1_IRQn
/* @} */
/**
* @brief UART configuration
......@@ -206,6 +206,50 @@ extern "C" {
#define GPIO_31_PIN 23
/** @} */
/**
* @brief PWM configuration
* @{
*/
#define PWM_0_EN 1
#define PWM_0_CHANNELS 3
#define PWM_1_EN 1
#define PWM_1_CHANNELS 3
#define PWM_NUMOF (2U)
/* PWM0 common configuration */
#define PWM_0_DEV LPC_CT16B0
#define PWM_0_CLK BIT7
/* PWM_0 channel configuration */
#define PWM_0_CH0_EN 1
#define PWM_0_CH0_IOCON LPC_IOCON->PIO1_13
#define PWM_0_CH0_AF 0x82
#define PWM_0_CH1_EN 1
#define PWM_0_CH1_IOCON LPC_IOCON->PIO1_14
#define PWM_0_CH1_AF 0x82
#define PWM_0_CH2_EN 1
#define PWM_0_CH2_IOCON LPC_IOCON->PIO1_15
#define PWM_0_CH2_AF 0x82
/* PWM1 common configuration */
#define PWM_1_DEV LPC_CT32B0
#define PWM_1_CLK BIT9
/* PWM_1 channel configuration */
#define PWM_1_CH0_EN 1
#define PWM_1_CH0_IOCON LPC_IOCON->PIO1_24
#define PWM_1_CH0_AF 0x81
#define PWM_1_CH1_EN 1
#define PWM_1_CH1_IOCON LPC_IOCON->PIO1_25
#define PWM_1_CH1_AF 0x81
#define PWM_1_CH2_EN 1
#define PWM_1_CH2_IOCON LPC_IOCON->PIO1_26
#define PWM_1_CH2_AF 0x81
/* @} */
#ifdef __cplusplus
}
#endif
......
/*
* Copyright (C) 2015 Freie Universität Berlin
*
* 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.
*/
/**
* @ingroup lpc11u34
* @{
*
* @file
* @brief CPU specific low-level PWM driver implementation for LPC11U34
*
* @author Paul RATHGEB <paul.rathgeb@skynet.be>
*
* @}
*/
#include "bitarithm.h"
#include "periph/gpio.h"
#include "periph/pwm.h"
#include "board.h"
#include "periph_conf.h"
/* guard file in case no PWM device is defined */
#if (PWM_0_EN || PWM_1_EN)
/**
* @note The LPC11U34 doesn't support centerized alignements
*/
int pwm_init(pwm_t dev, pwm_mode_t mode, unsigned int frequency, unsigned int resolution)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
/* This CPU doesn't support a centerized alignement */
if (mode == PWM_CENTER) {
return -1;
}
/* Check if the frequency and resolution is applicable */
if (F_CPU/(resolution*frequency) <= 0) {
return -2;
}
#if PWM_0_CH0_EN
PWM_0_CH0_IOCON = (PWM_0_CH0_IOCON & ~(BIT7 | 7)) | PWM_0_CH0_AF;
#endif
#if PWM_0_CH1_EN
PWM_0_CH1_IOCON = (PWM_0_CH1_IOCON & ~(BIT7 | 7)) | PWM_0_CH1_AF;
#endif
#if PWM_0_CH2_EN
PWM_0_CH2_IOCON = (PWM_0_CH2_IOCON & ~(BIT7 | 7)) | PWM_0_CH2_AF;
#endif
/* The configuration involve that the peripheral is powered */
pwm_poweron(dev);
/* Enable timer and keep it in reset state */
PWM_0_DEV->TCR = BIT0 | BIT1;
/* Set the prescaler (F_CPU / resolution) */
PWM_0_DEV->PR = (F_CPU/(resolution*frequency));
/* Reset timer on MR3 */
PWM_0_DEV->MCR = BIT10;
/* Set PWM period */
PWM_0_DEV->MR0 = (resolution);
PWM_0_DEV->MR1 = (resolution);
PWM_0_DEV->MR2 = (resolution);
PWM_0_DEV->MR3 = (resolution)-1;
/* Set mode for channels 0..2 */
PWM_0_DEV->EMR |= ((mode+1) << 4);
PWM_0_DEV->EMR |= ((mode+1) << 6);
PWM_0_DEV->EMR |= ((mode+1) << 8);
/* Enable PWM channels 0..2 */
PWM_0_DEV->PWMC = BIT0 | BIT1 | BIT2;
#endif /* PWM_0_EN */
#if PWM_1_EN
case PWM_1:
/* This CPU doesn't support a centerized alignement */
if (mode == PWM_CENTER) {
return -1;
}
/* Check if the frequency and resolution is applicable */
if (F_CPU/(resolution*frequency) <= 0) {
return -2;
}
#if PWM_1_CH0_EN
PWM_1_CH0_IOCON = (PWM_1_CH0_IOCON & ~(BIT7 | 7)) | PWM_1_CH0_AF;
#endif
#if PWM_1_CH1_EN
PWM_1_CH1_IOCON = (PWM_1_CH1_IOCON & ~(BIT7 | 7)) | PWM_1_CH1_AF;
#endif
#if PWM_1_CH2_EN
PWM_1_CH2_IOCON = (PWM_1_CH2_IOCON & ~(BIT7 | 7)) | PWM_1_CH2_AF;
#endif
/* The configuration involve that the peripheral is powered */
pwm_poweron(dev);
/* Enable timer and keep it in reset state */
PWM_1_DEV->TCR = BIT0 | BIT1;
/* Set the prescaler (F_CPU / resolution) */
PWM_1_DEV->PR = (F_CPU/(resolution*frequency));
/* Reset timer on MR3 */
PWM_1_DEV->MCR = BIT10;
/* Set PWM period */
PWM_1_DEV->MR0 = (resolution);
PWM_1_DEV->MR1 = (resolution);
PWM_1_DEV->MR2 = (resolution);
PWM_1_DEV->MR3 = (resolution)-1;
/* Set mode for channels 0..2 */
PWM_1_DEV->EMR |= ((mode+1) << 4);
PWM_1_DEV->EMR |= ((mode+1) << 6);
PWM_1_DEV->EMR |= ((mode+1) << 8);
/* Enable PWM channels 0..2 */
PWM_1_DEV->PWMC = BIT0 | BIT1 | BIT2;
#endif /* PWM_1_EN */
}
return frequency;
}
int pwm_set(pwm_t dev, int channel, unsigned int value)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
if (channel <= 2) {
PWM_0_DEV->MR[channel] = PWM_0_DEV->MR3 - value;
}
break;
#endif
#if PWM_1_EN
case PWM_1:
if (channel <= 2) {
PWM_1_DEV->MR[channel] = PWM_1_DEV->MR3 - value;
}
break;
#endif
}
return 0;
}
void pwm_start(pwm_t dev)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
/* Start the counter */
PWM_0_DEV->TCR &= ~BIT1;
break;
#endif
#if PWM_1_EN
case PWM_1:
/* Start the counter */
PWM_1_DEV->TCR &= ~BIT1;
break;
#endif
}
}
void pwm_stop(pwm_t dev)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
/* Stop the counter */
PWM_0_DEV->TCR |= BIT1;
break;
#endif
#if PWM_1_EN
case PWM_1:
/* Stop the counter */
PWM_1_DEV->TCR |= BIT1;
break;
#endif
}
}
void pwm_poweron(pwm_t dev)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
/* Enable clock for PWM_0 */
LPC_SYSCON->SYSAHBCLKCTRL |= PWM_0_CLK;
break;
#endif
#if PWM_1_EN
case PWM_1:
/* Enable clock for PWM_1 */
LPC_SYSCON->SYSAHBCLKCTRL |= PWM_1_CLK;
break;
#endif
}
}
void pwm_poweroff(pwm_t dev)
{
switch (dev) {
#if PWM_0_EN
case PWM_0:
/* Disable clock for PWM_0 */
LPC_SYSCON->SYSAHBCLKCTRL &= ~PWM_0_CLK;
break;
#endif
#if PWM_1_EN
case PWM_1:
/* Disable clock for PWM_1 */
LPC_SYSCON->SYSAHBCLKCTRL &= ~PWM_1_CLK;
break;
#endif
}
}
#endif /* (PWM_0_EN || PWM_1_EN) */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment