summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/daisy/board.h4
-rw-r--r--board/snow/board.h4
-rw-r--r--board/spring/board.h4
-rw-r--r--chip/stm32/hwtimer.c136
4 files changed, 88 insertions, 60 deletions
diff --git a/board/daisy/board.h b/board/daisy/board.h
index b2308abc6f..da85579d7d 100644
--- a/board/daisy/board.h
+++ b/board/daisy/board.h
@@ -47,6 +47,10 @@
#define I2C_PORT_CHARGER I2C_PORT_HOST
#define I2C_PORT_SLAVE 1
+/* Timer selection */
+#define TIM_CLOCK_MSB 3
+#define TIM_CLOCK_LSB 4
+
/* GPIO signal list */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/snow/board.h b/board/snow/board.h
index 749960bc6f..072b5ec40e 100644
--- a/board/snow/board.h
+++ b/board/snow/board.h
@@ -59,6 +59,10 @@
/* Battery */
#define CONFIG_BATTERY_BQ20Z453
+/* Timer selection */
+#define TIM_CLOCK_MSB 3
+#define TIM_CLOCK_LSB 4
+
/* GPIO signal list */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/spring/board.h b/board/spring/board.h
index e31a635fad..192eddc550 100644
--- a/board/spring/board.h
+++ b/board/spring/board.h
@@ -55,6 +55,10 @@
/* Battery */
#define CONFIG_BATTERY_BQ20Z453
+/* Timer selection */
+#define TIM_CLOCK_MSB 2
+#define TIM_CLOCK_LSB 4
+
/* ADC signal */
#define CONFIG_ADC
enum adc_channel {
diff --git a/chip/stm32/hwtimer.c b/chip/stm32/hwtimer.c
index 3a58e9dcd1..ef09a8dd5e 100644
--- a/chip/stm32/hwtimer.c
+++ b/chip/stm32/hwtimer.c
@@ -21,6 +21,15 @@
#define TIM_WD 1 /* Timer to use for watchdog */
#endif
+/*
+ * TIM_CLOCK_MSB and TIM_CLOCK_LSB must be defined per board. The available
+ * values are 2, 3, and 4. This gives us flexibility to make any of the three
+ * timer as a PWM source.
+ */
+#define IRQ_TIM(n) STM32_CAT(STM32_IRQ_TIM, n, )
+#define IRQ_MSB IRQ_TIM(TIM_CLOCK_MSB)
+#define IRQ_LSB IRQ_TIM(TIM_CLOCK_LSB)
+
enum {
TIM_WD_BASE = STM32_TIM1_BASE,
};
@@ -31,33 +40,33 @@ void __hw_clock_event_set(uint32_t deadline)
{
last_deadline = deadline;
- if ((deadline >> 16) > STM32_TIM_CNT(3)) {
+ if ((deadline >> 16) > STM32_TIM_CNT(TIM_CLOCK_MSB)) {
/* first set a match on the MSB */
- STM32_TIM_CCR1(3) = deadline >> 16;
+ STM32_TIM_CCR1(TIM_CLOCK_MSB) = deadline >> 16;
/* disable LSB match */
- STM32_TIM_DIER(4) &= ~2;
+ STM32_TIM_DIER(TIM_CLOCK_LSB) &= ~2;
/* Clear the match flags */
- STM32_TIM_SR(3) = ~2;
- STM32_TIM_SR(4) = ~2;
+ STM32_TIM_SR(TIM_CLOCK_MSB) = ~2;
+ STM32_TIM_SR(TIM_CLOCK_LSB) = ~2;
/* Set the match interrupt */
- STM32_TIM_DIER(3) |= 2;
+ STM32_TIM_DIER(TIM_CLOCK_MSB) |= 2;
}
/*
- * In the unlikely case where the MSB on TIM3 has increased and matched
+ * In the unlikely case where the MSB has increased and matched
* the deadline MSB before we set the match interrupt, as the STM
* hardware timer won't trigger an interrupt, we fall back to the
* following LSB event code to set another interrupt.
*/
- if ((deadline >> 16) == STM32_TIM_CNT(3)) {
+ if ((deadline >> 16) == STM32_TIM_CNT(TIM_CLOCK_MSB)) {
/* we can set a match on the LSB only */
- STM32_TIM_CCR1(4) = deadline & 0xffff;
+ STM32_TIM_CCR1(TIM_CLOCK_LSB) = deadline & 0xffff;
/* disable MSB match */
- STM32_TIM_DIER(3) &= ~2;
+ STM32_TIM_DIER(TIM_CLOCK_MSB) &= ~2;
/* Clear the match flags */
- STM32_TIM_SR(3) = ~2;
- STM32_TIM_SR(4) = ~2;
+ STM32_TIM_SR(TIM_CLOCK_MSB) = ~2;
+ STM32_TIM_SR(TIM_CLOCK_LSB) = ~2;
/* Set the match interrupt */
- STM32_TIM_DIER(4) |= 2;
+ STM32_TIM_DIER(TIM_CLOCK_LSB) |= 2;
}
/*
* If the LSB deadline is already in the past and won't trigger an
@@ -75,8 +84,8 @@ uint32_t __hw_clock_event_get(void)
void __hw_clock_event_clear(void)
{
/* Disable the match interrupts */
- STM32_TIM_DIER(4) &= ~2;
- STM32_TIM_DIER(3) &= ~2;
+ STM32_TIM_DIER(TIM_CLOCK_LSB) &= ~2;
+ STM32_TIM_DIER(TIM_CLOCK_MSB) &= ~2;
}
uint32_t __hw_clock_source_read(void)
@@ -86,89 +95,95 @@ uint32_t __hw_clock_source_read(void)
/* Ensure the two half-words are coherent */
do {
- hi = STM32_TIM_CNT(3);
- lo = STM32_TIM_CNT(4);
- } while (hi != STM32_TIM_CNT(3));
+ hi = STM32_TIM_CNT(TIM_CLOCK_MSB);
+ lo = STM32_TIM_CNT(TIM_CLOCK_LSB);
+ } while (hi != STM32_TIM_CNT(TIM_CLOCK_MSB));
return (hi << 16) | lo;
}
void __hw_clock_source_set(uint32_t ts)
{
- STM32_TIM_CNT(3) = ts >> 16;
- STM32_TIM_CNT(4) = ts & 0xffff;
+ STM32_TIM_CNT(TIM_CLOCK_MSB) = ts >> 16;
+ STM32_TIM_CNT(TIM_CLOCK_LSB) = ts & 0xffff;
}
static void __hw_clock_source_irq(void)
{
- uint32_t stat_tim3 = STM32_TIM_SR(3);
+ uint32_t stat_tim_msb = STM32_TIM_SR(TIM_CLOCK_MSB);
/* Clear status */
- STM32_TIM_SR(4) = 0;
- STM32_TIM_SR(3) = 0;
+ STM32_TIM_SR(TIM_CLOCK_LSB) = 0;
+ STM32_TIM_SR(TIM_CLOCK_MSB) = 0;
/*
* Find expired timers and set the new timer deadline
* signal overflow if the 16-bit MSB counter has overflowed.
*/
- process_timers(stat_tim3 & 0x01);
+ process_timers(stat_tim_msb & 0x01);
}
-DECLARE_IRQ(STM32_IRQ_TIM3, __hw_clock_source_irq, 1);
-DECLARE_IRQ(STM32_IRQ_TIM4, __hw_clock_source_irq, 1);
+DECLARE_IRQ(IRQ_MSB, __hw_clock_source_irq, 1);
+DECLARE_IRQ(IRQ_LSB, __hw_clock_source_irq, 1);
int __hw_clock_source_init(uint32_t start_t)
{
/*
* we use 2 chained 16-bit counters to emulate a 32-bit one :
- * TIM3 is the MSB (Slave)
- * TIM4 is the LSB (Master)
+ * TIM_CLOCK_MSB is the MSB (Slave)
+ * TIM_CLOCK_LSB is the LSB (Master)
*/
- /* Enable TIM3 and TIM4 clocks */
- STM32_RCC_APB1ENR |= 0x6;
+ /* Enable TIM_CLOCK_MSB and TIM_CLOCK_LSB clocks */
+ STM32_RCC_APB1ENR |= (1 << (TIM_CLOCK_MSB - 2)) |
+ (1 << (TIM_CLOCK_LSB - 2));
/*
* Timer configuration : Upcounter, counter disabled, update event only
* on overflow.
*/
- STM32_TIM_CR1(3) = 0x0004;
- STM32_TIM_CR1(4) = 0x0004;
- /* TIM4 (master mode) generates a periodic trigger signal on each UEV */
- STM32_TIM_CR2(3) = 0x0000;
- STM32_TIM_CR2(4) = 0x0020;
- /* TIM3 (slave mode) uses ITR3 as internal trigger */
- STM32_TIM_SMCR(3) = 0x0037;
- STM32_TIM_SMCR(4) = 0x0000;
+ STM32_TIM_CR1(TIM_CLOCK_MSB) = 0x0004;
+ STM32_TIM_CR1(TIM_CLOCK_LSB) = 0x0004;
+ /*
+ * TIM_CLOCK_LSB (master mode) generates a periodic trigger signal on
+ * each UEV
+ */
+ STM32_TIM_CR2(TIM_CLOCK_MSB) = 0x0000;
+ STM32_TIM_CR2(TIM_CLOCK_LSB) = 0x0020;
+ /* TIM_CLOCK_MSB (slave mode) uses TIM_CLOCK_LSB as internal trigger */
+ STM32_TIM_SMCR(TIM_CLOCK_MSB) = 0x0007 | ((TIM_CLOCK_LSB - 1) << 4);
+ STM32_TIM_SMCR(TIM_CLOCK_LSB) = 0x0000;
/* Auto-reload value : 16-bit free-running counters */
- STM32_TIM_ARR(3) = 0xffff;
- STM32_TIM_ARR(4) = 0xffff;
- /* Pre-scaler value :
- * TIM4 is counting microseconds, TIM3 is counting every TIM4 overflow.
+ STM32_TIM_ARR(TIM_CLOCK_MSB) = 0xffff;
+ STM32_TIM_ARR(TIM_CLOCK_LSB) = 0xffff;
+ /*
+ * Pre-scaler value :
+ * TIM_CLOCK_LSB is counting microseconds, TIM_CLOCK_MSB is counting
+ * every TIM_CLOCK_LSB overflow.
*/
- STM32_TIM_PSC(3) = 0;
- STM32_TIM_PSC(4) = CLOCKSOURCE_DIVIDER - 1;
+ STM32_TIM_PSC(TIM_CLOCK_MSB) = 0;
+ STM32_TIM_PSC(TIM_CLOCK_LSB) = CLOCKSOURCE_DIVIDER - 1;
/* Reload the pre-scaler */
- STM32_TIM_EGR(3) = 0x0001;
- STM32_TIM_EGR(4) = 0x0001;
+ STM32_TIM_EGR(TIM_CLOCK_MSB) = 0x0001;
+ STM32_TIM_EGR(TIM_CLOCK_LSB) = 0x0001;
- /* setup the overflow interrupt on TIM3 */
- STM32_TIM_DIER(3) = 0x0001;
- STM32_TIM_DIER(4) = 0x0000;
+ /* setup the overflow interrupt on TIM_CLOCK_MSB */
+ STM32_TIM_DIER(TIM_CLOCK_MSB) = 0x0001;
+ STM32_TIM_DIER(TIM_CLOCK_LSB) = 0x0000;
/* Start counting */
- STM32_TIM_CR1(3) |= 1;
- STM32_TIM_CR1(4) |= 1;
+ STM32_TIM_CR1(TIM_CLOCK_MSB) |= 1;
+ STM32_TIM_CR1(TIM_CLOCK_LSB) |= 1;
/* Override the count with the start value now that counting has
* started. */
__hw_clock_source_set(start_t);
/* Enable timer interrupts */
- task_enable_irq(STM32_IRQ_TIM3);
- task_enable_irq(STM32_IRQ_TIM4);
+ task_enable_irq(IRQ_MSB);
+ task_enable_irq(IRQ_LSB);
- return STM32_IRQ_TIM4;
+ return IRQ_LSB;
}
/*
@@ -224,18 +239,19 @@ void hwtimer_setup_watchdog(void)
*/
timer->cr1 = 0x0014 | (1 << 7);
- /* TIM (slave mode) uses ITR3 as internal trigger */
- timer->smcr = 0x0037;
+ /* TIM (slave mode) uses TIM_CLOCK_LSB as internal trigger */
+ timer->smcr = 0x0007 | ((TIM_CLOCK_LSB - 1) << 4);
/*
* The auto-reload value is based on the period between rollovers for
- * TIM4. Since TIM4 runs at 1MHz, it will overflow in 65.536ms. We
- * divide our required watchdog period by this amount to obtain the
- * number of times TIM4 can overflow before we generate an interrupt.
+ * TIM_CLOCK_LSB. Since TIM_CLOCK_LSB runs at 1MHz, it will overflow
+ * in 65.536ms. We divide our required watchdog period by this amount
+ * to obtain the number of times TIM_CLOCK_LSB can overflow before we
+ * generate an interrupt.
*/
timer->arr = timer->cnt = WATCHDOG_PERIOD_MS * 1000 / (1 << 16);
- /* count on every TIM4 overflow */
+ /* count on every TIM_CLOCK_LSB overflow */
timer->psc = 0;
/* Reload the pre-scaler from arr when it goes below zero */