aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPerry Hung <iperry@gmail.com>2010-10-12 20:58:48 -0400
committerPerry Hung <iperry@gmail.com>2010-10-12 20:59:46 -0400
commitaa7a43efce35fa41d57f9858ee41be0c33e84709 (patch)
treed1ed6a43df75776dd35ee1ca8513bc5f7be47ce2
parentfccf017f3a5aa7182080c1ed062ab46773a8f34a (diff)
downloadlibrambutan-aa7a43efce35fa41d57f9858ee41be0c33e84709.tar.gz
librambutan-aa7a43efce35fa41d57f9858ee41be0c33e84709.zip
Add selective enabling of channels for pwm channels
pinMode(PWM) turns the channel on, other modes should turn it off Fixes bug with conflicting timer for spi1 and timer. This is not well-tested. Conflicts: libmaple/timers.c
-rw-r--r--libmaple/timers.c4
-rw-r--r--libmaple/timers.h54
-rw-r--r--wirish/boards.h84
-rw-r--r--wirish/pwm.c4
-rw-r--r--wirish/wirish_digital.c16
5 files changed, 88 insertions, 74 deletions
diff --git a/libmaple/timers.c b/libmaple/timers.c
index 5b97e20..334ec0b 100644
--- a/libmaple/timers.c
+++ b/libmaple/timers.c
@@ -103,19 +103,15 @@ void timer_init(uint8 timer_num, uint16 prescale) {
* we'll worry about that later. */
timer->CCR1 = 0x8FFF; // PWM start value
timer->CCMR1 |= 0x68; // PWM mode 1, enable preload register.
- timer->CCER |= 0x001; // enable ch
timer->CCR2 = 0x8FFF; // PWM start value
timer->CCMR1 |= (0x68 << 8);// PWM mode 1, enable preload register.
- timer->CCER |= 0x010; // enable ch
timer->CCR3 = 0x8FFF; // PWM start value
timer->CCMR2 |= 0x68; // PWM mode 1, enable preload register.
- timer->CCER |= 0x100; // enable ch
timer->CCR4 = 0x8FFF; // PWM start value
timer->CCMR2 |= (0x68 << 8);// PWM mode 1, enable preload register.
- timer->CCER |= 0x1000; // enable ch
/* Advanced timer? */
if (is_advanced) {
diff --git a/libmaple/timers.h b/libmaple/timers.h
index cbdf088..ba8245c 100644
--- a/libmaple/timers.h
+++ b/libmaple/timers.h
@@ -98,39 +98,39 @@ typedef volatile uint32* TimerCCR;
#define TIMER_CCR(NUM,CHAN) TIMER ## NUM ## _CH ## CHAN ## _CRR
-#define TIMER1_CH1_CCR (TimerCCR)(TIMER1_BASE + 0x34)
-#define TIMER1_CH2_CCR (TimerCCR)(TIMER1_BASE + 0x38)
-#define TIMER1_CH3_CCR (TimerCCR)(TIMER1_BASE + 0x3C)
-#define TIMER1_CH4_CCR (TimerCCR)(TIMER1_BASE + 0x40)
-
-#define TIMER2_CH1_CCR (TimerCCR)(TIMER2_BASE + 0x34)
-#define TIMER2_CH2_CCR (TimerCCR)(TIMER2_BASE + 0x38)
-#define TIMER2_CH3_CCR (TimerCCR)(TIMER2_BASE + 0x3C)
-#define TIMER2_CH4_CCR (TimerCCR)(TIMER2_BASE + 0x40)
-
-#define TIMER3_CH1_CCR (TimerCCR)(TIMER3_BASE + 0x34)
-#define TIMER3_CH2_CCR (TimerCCR)(TIMER3_BASE + 0x38)
-#define TIMER3_CH3_CCR (TimerCCR)(TIMER3_BASE + 0x3C)
-#define TIMER3_CH4_CCR (TimerCCR)(TIMER3_BASE + 0x40)
-
-#define TIMER4_CH1_CCR (TimerCCR)(TIMER4_BASE + 0x34)
-#define TIMER4_CH2_CCR (TimerCCR)(TIMER4_BASE + 0x38)
-#define TIMER4_CH3_CCR (TimerCCR)(TIMER4_BASE + 0x3C)
-#define TIMER4_CH4_CCR (TimerCCR)(TIMER4_BASE + 0x40)
+#define TIMER1_CH1_CCR TIMER1_BASE + 0x34
+#define TIMER1_CH2_CCR TIMER1_BASE + 0x38
+#define TIMER1_CH3_CCR TIMER1_BASE + 0x3C
+#define TIMER1_CH4_CCR TIMER1_BASE + 0x40
+
+#define TIMER2_CH1_CCR TIMER2_BASE + 0x34
+#define TIMER2_CH2_CCR TIMER2_BASE + 0x38
+#define TIMER2_CH3_CCR TIMER2_BASE + 0x3C
+#define TIMER2_CH4_CCR TIMER2_BASE + 0x40
+
+#define TIMER3_CH1_CCR TIMER3_BASE + 0x34
+#define TIMER3_CH2_CCR TIMER3_BASE + 0x38
+#define TIMER3_CH3_CCR TIMER3_BASE + 0x3C
+#define TIMER3_CH4_CCR TIMER3_BASE + 0x40
+
+#define TIMER4_CH1_CCR TIMER4_BASE + 0x34
+#define TIMER4_CH2_CCR TIMER4_BASE + 0x38
+#define TIMER4_CH3_CCR TIMER4_BASE + 0x3C
+#define TIMER4_CH4_CCR TIMER4_BASE + 0x40
/* Timer5 and Timer8 are in high-density devices only (such as Maple
Native). Timer6 and Timer7 in these devices have no output compare
pins. */
-#define TIMER5_CH1_CCR (TimerCCR)(TIMER5_BASE + 0x34)
-#define TIMER5_CH2_CCR (TimerCCR)(TIMER5_BASE + 0x38)
-#define TIMER5_CH3_CCR (TimerCCR)(TIMER5_BASE + 0x3C)
-#define TIMER5_CH4_CCR (TimerCCR)(TIMER5_BASE + 0x40)
+#define TIMER5_CH1_CCR TIMER5_BASE + 0x34
+#define TIMER5_CH2_CCR TIMER5_BASE + 0x38
+#define TIMER5_CH3_CCR TIMER5_BASE + 0x3C
+#define TIMER5_CH4_CCR TIMER5_BASE + 0x40
-#define TIMER8_CH1_CCR (TimerCCR)(TIMER8_BASE + 0x34)
-#define TIMER8_CH2_CCR (TimerCCR)(TIMER8_BASE + 0x38)
-#define TIMER8_CH3_CCR (TimerCCR)(TIMER8_BASE + 0x3C)
-#define TIMER8_CH4_CCR (TimerCCR)(TIMER8_BASE + 0x40)
+#define TIMER8_CH1_CCR TIMER8_BASE + 0x34
+#define TIMER8_CH2_CCR TIMER8_BASE + 0x38
+#define TIMER8_CH3_CCR TIMER8_BASE + 0x3C
+#define TIMER8_CH4_CCR TIMER8_BASE + 0x40
#define TIMER_DISABLED 0
#define TIMER_PWM 1
diff --git a/wirish/boards.h b/wirish/boards.h
index eed3e26..fed5ead 100644
--- a/wirish/boards.h
+++ b/wirish/boards.h
@@ -57,15 +57,17 @@ enum {
ADC12, ADC13, ADC14, ADC15, ADC16, ADC17, ADC18, ADC19, ADC20, };
#define ADC_INVALID 0xFFFFFFFF
-#define TIMER_INVALID (TimerCCR)0xFFFFFFFF
+#define TIMER_INVALID 0xFFFFFFFF
/* Types used for the tables below */
typedef struct PinMapping {
GPIO_Port *port;
uint32 pin;
uint32 adc;
- TimerCCR timer_channel;
+ uint32 timer_channel;
uint32 exti_port;
+ uint32 timer_num;
+ uint32 timer_chan;
} PinMapping;
/* LeafLabs Maple rev3, rev4 */
@@ -76,89 +78,89 @@ typedef struct PinMapping {
static __attribute__ ((unused)) PinMapping PIN_MAP[NR_GPIO_PINS] = {
/* D0/PA3 */
- {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 3, ADC3, TIMER2_CH4_CCR, EXTI_CONFIG_PORTA, TIMER2, 4},
/* D1/PA2 */
- {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 2, ADC2, TIMER2_CH3_CCR, EXTI_CONFIG_PORTA, TIMER2, 3},
/* D2/PA0 */
- {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 0, ADC0, TIMER2_CH1_CCR, EXTI_CONFIG_PORTA, TIMER2, 1},
/* D3/PA1 */
- {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 1, ADC1, TIMER2_CH2_CCR, EXTI_CONFIG_PORTA, TIMER2, 2},
/* D4/PB5 */
- {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 5, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D5/PB6 */
- {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 6, ADC_INVALID, TIMER4_CH1_CCR, EXTI_CONFIG_PORTB, TIMER4, 1},
/* D6/PA8 */
- {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 8, ADC_INVALID, TIMER1_CH1_CCR, EXTI_CONFIG_PORTA, TIMER1, 1},
/* D7/PA9 */
- {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 9, ADC_INVALID, TIMER1_CH2_CCR, EXTI_CONFIG_PORTA, TIMER1, 2},
/* D8/PA10 */
- {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 10, ADC_INVALID, TIMER1_CH3_CCR, EXTI_CONFIG_PORTA, TIMER1, 3},
/* D9/PB7 */
- {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 7, ADC_INVALID, TIMER4_CH2_CCR, EXTI_CONFIG_PORTB, TIMER4, 2},
/* D10/PA4 */
- {GPIOA_BASE, 4, ADC4, TIMER_INVALID, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 4, ADC4, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D11/PA7 */
- {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 7, ADC7, TIMER3_CH2_CCR, EXTI_CONFIG_PORTA, TIMER3, 2},
/* D12/PA6 */
- {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 6, ADC6, TIMER3_CH1_CCR, EXTI_CONFIG_PORTA, TIMER3, 1},
/* D13/PA5 */
- {GPIOA_BASE, 5, ADC5, TIMER_INVALID, EXTI_CONFIG_PORTA},
+ {GPIOA_BASE, 5, ADC5, TIMER_INVALID, EXTI_CONFIG_PORTA, TIMER_INVALID, TIMER_INVALID},
/* D14/PB8 */
- {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 8, ADC_INVALID, TIMER4_CH3_CCR, EXTI_CONFIG_PORTB, TIMER4, 3},
/* Little header */
/* D15/PC0 */
- {GPIOC_BASE, 0, ADC10, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 0, ADC10, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D16/PC1 */
- {GPIOC_BASE, 1, ADC11, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 1, ADC11, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D17/PC2 */
- {GPIOC_BASE, 2, ADC12, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 2, ADC12, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D18/PC3 */
- {GPIOC_BASE, 3, ADC13, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 3, ADC13, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D19/PC4 */
- {GPIOC_BASE, 4, ADC14, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 4, ADC14, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D20/PC5 */
- {GPIOC_BASE, 5, ADC15, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 5, ADC15, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* External header */
/* D21/PC13 */
- {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D22/PC14 */
- {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D23/PC15 */
- {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D24/PB9 */
- {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 9, ADC_INVALID, TIMER4_CH4_CCR, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D25/PD2 */
- {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTD},
+ {GPIOD_BASE, 2, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTD, TIMER_INVALID, TIMER_INVALID},
/* D26/PC10 */
- {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D27/PB0 */
- {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 0, ADC8, TIMER3_CH3_CCR, EXTI_CONFIG_PORTB, TIMER3, 3},
/* D28/PB1 */
- {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 1, ADC9, TIMER3_CH4_CCR, EXTI_CONFIG_PORTB, TIMER3, 4},
/* D29/PB10 */
- {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 10, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D30/PB11 */
- {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 11, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D31/PB12 */
- {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 12, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D32/PB13 */
- {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 13, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D33/PB14 */
- {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 14, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D34/PB15 */
- {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB},
+ {GPIOB_BASE, 15, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTB, TIMER_INVALID, TIMER_INVALID},
/* D35/PC6 */
- {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 6, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D36/PC7 */
- {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 7, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* D37/PC8 */
- {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC},
+ {GPIOC_BASE, 8, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID},
/* PC9 (BUT) */
- {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC}
+ {GPIOC_BASE, 9, ADC_INVALID, TIMER_INVALID, EXTI_CONFIG_PORTC, TIMER_INVALID, TIMER_INVALID}
};
#endif
diff --git a/wirish/pwm.c b/wirish/pwm.c
index 2f555ab..0bf27aa 100644
--- a/wirish/pwm.c
+++ b/wirish/pwm.c
@@ -38,9 +38,9 @@ void pwmWrite(uint8 pin, uint16 duty_cycle) {
return;
}
- ccr = PIN_MAP[pin].timer_channel;
+ ccr = (TimerCCR)(PIN_MAP[pin].timer_channel);
- if (ccr == TIMER_INVALID) {
+ if (ccr == (TimerCCR)TIMER_INVALID) {
return;
}
diff --git a/wirish/wirish_digital.c b/wirish/wirish_digital.c
index f4868da..9298b60 100644
--- a/wirish/wirish_digital.c
+++ b/wirish/wirish_digital.c
@@ -31,6 +31,7 @@
void pinMode(uint8 pin, WiringPinMode mode) {
uint8 outputMode;
+ uint32 pwm = 0;
if (pin >= NR_GPIO_PINS) {
return;
@@ -58,9 +59,11 @@ void pinMode(uint8 pin, WiringPinMode mode) {
break;
case PWM:
outputMode = GPIO_MODE_AF_OUTPUT_PP;
+ pwm = 1;
break;
case PWM_OPEN_DRAIN:
outputMode = GPIO_MODE_AF_OUTPUT_OD;
+ pwm = 1;
break;
default:
ASSERT(0);
@@ -68,6 +71,19 @@ void pinMode(uint8 pin, WiringPinMode mode) {
}
gpio_set_mode(PIN_MAP[pin].port, PIN_MAP[pin].pin, outputMode);
+
+ if (PIN_MAP[pin].timer_num != TIMER_INVALID) {
+ /* enable/disable timer channels if we're switching into or out of pwm */
+ if (pwm) {
+ timer_set_mode(PIN_MAP[pin].timer_num,
+ PIN_MAP[pin].timer_chan,
+ TIMER_PWM);
+ } else {
+ timer_set_mode(PIN_MAP[pin].timer_num,
+ PIN_MAP[pin].timer_chan,
+ TIMER_DISABLED);
+ }
+ }
}