From c8bf4efbb462b2e622ec4d06bd7bc3fc156c8c96 Mon Sep 17 00:00:00 2001
From: Oleg Hahm <oleg@hobbykeller.org>
Date: Thu, 20 Mar 2014 23:12:38 +0100
Subject: [PATCH] msp430: cc430: handle hwtimer interrupts correctly

TAIFG should count the overflows, instead of using the first CCR for this purpose.
Without this commit ARCH_MAXTIMERS returns the wrong number as
effectively one timer less can be used.

Additional fixed comment style and added timer debug.
---
 cpu/cc430/hwtimer_cc430.c       | 34 ++++++++++++++++++--------------
 cpu/msp430x16x/hwtimer_msp430.c | 35 ++++++++++++++++++++++-----------
 2 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/cpu/cc430/hwtimer_cc430.c b/cpu/cc430/hwtimer_cc430.c
index 781135fcb9..466ca500ba 100644
--- a/cpu/cc430/hwtimer_cc430.c
+++ b/cpu/cc430/hwtimer_cc430.c
@@ -20,11 +20,9 @@
  *
  */
 
-#include <legacymsp430.h>
-#include "board.h"
+#include "cpu.h"
 #include "hwtimer.h"
 #include "hwtimer_arch.h"
-#include "cpu.h"
 
 #define ENABLE_DEBUG (0)
 #include "debug.h"
@@ -33,15 +31,18 @@ static uint32_t ticks = 0;
 
 extern void (*int_handler)(int);
 extern void timer_unset(short timer);
+extern uint16_t overflow_interrupt[HWTIMER:_MAXTIMERS+1];
+extern uint16_t timer_round;
 
 void timerA_init(void)
 {
-    ticks = 0;                               // Set tick counter value to 0
-    TA0CTL = TASSEL_1 + TACLR;               // Clear the timer counter, set ACLK
-    TA0CTL &= ~TAIE;                         // Clear the IFG
-
     volatile unsigned int *ccr = &TA0CCR0;
     volatile unsigned int *ctl = &TA0CCTL0;
+    ticks = 0;                               /* Set tick counter value to 0 */
+    timer_round = 0;                         /* Set to round 0 */
+    TA0CTL = TASSEL_1 + TACLR;               /* Clear the timer counter, set ACLK */
+    TA0CTL &= ~TAIFG;                        /* Clear the IFG */
+    TA0CTL |= TAIE;                          /* Enable TAIE (overflow IRQ) */
 
     for (int i = 0; i < HWTIMER_MAXTIMERS; i++) {
         *(ccr + i) = 0;
@@ -55,9 +56,10 @@ void timerA_init(void)
 interrupt(TIMER0_A0_VECTOR) __attribute__((naked)) timer0_a0_isr(void)
 {
     __enter_isr();
-
-    timer_unset(0);
-    int_handler(0);
+    if (overflow_interrupt[0] == timer_round) {
+        timer_unset(0);
+        int_handler(0);
+    }
     __exit_isr();
 }
 
@@ -66,13 +68,15 @@ interrupt(TIMER0_A1_VECTOR) __attribute__((naked)) timer0_a1_5_isr(void)
     __enter_isr();
 
     short taiv = TA0IV;
-    short timer;
-
-    if (taiv & TAIFG) {
+    short timer = taiv / 2;
+    /* TAIV = 0x0E means overflow */
+    if (taiv == 0x0E) {
         DEBUG("Overflow\n");
+        timer_round += 1;
     }
-    else {
-        timer = (taiv / 2);
+    /* check which CCR has been hit and if the overflow counter for this timer
+     * has been reached */
+    else if (overflow_interrupt[timer] == timer_round) {
         timer_unset(timer);
         int_handler(timer);
     }
diff --git a/cpu/msp430x16x/hwtimer_msp430.c b/cpu/msp430x16x/hwtimer_msp430.c
index 5522c30b23..aa55b05662 100644
--- a/cpu/msp430x16x/hwtimer_msp430.c
+++ b/cpu/msp430x16x/hwtimer_msp430.c
@@ -24,6 +24,9 @@
 #include "hwtimer.h"
 #include "hwtimer_arch.h"
 
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
 static uint32_t ticks = 0;
 
 extern void (*int_handler)(int);
@@ -35,11 +38,11 @@ void timerA_init(void)
 {
     volatile unsigned int *ccr;
     volatile unsigned int *ctl;
-    ticks = 0;                               // Set tick counter value to 0
-    timer_round = 0;                         // Set to round 0
-    TACTL = TASSEL_1 + TACLR;                // Clear the timer counter, set ACLK
-    TACTL &= ~TAIFG;                         // Clear the IFG
-    TACTL &= ~TAIE;                          // Clear the IFG
+    ticks = 0;                               /* Set tick counter value to 0 */
+    timer_round = 0;                         /* Set to round 0 */
+    TACTL = TASSEL_1 + TACLR;                /* Clear the timer counter, set ACLK */
+    TACTL &= ~TAIFG;                         /* Clear the IFG */
+    TACTL |= TAIE;                           /* Enable TAIE (overflow IRQ) */
 
     for (int i = 0; i < HWTIMER_MAXTIMERS; i++) {
         ccr = &TACCR0 + (i);
@@ -55,7 +58,10 @@ void timerA_init(void)
 interrupt(TIMERA0_VECTOR) __attribute__((naked)) timer_isr_ccr0(void)
 {
     __enter_isr();
-    timer_round += 1;
+    if (overflow_interrupt[0] == timer_round) {
+        timer_unset(0);
+        int_handler(0);
+    }
     __exit_isr();
 }
 
@@ -64,12 +70,17 @@ interrupt(TIMERA1_VECTOR) __attribute__((naked)) timer_isr(void)
     __enter_isr();
 
     short taiv = TAIV;
-    if (!(taiv & TAIV_TAIFG)) {
-        short timer = taiv / 2;
-        if (overflow_interrupt[timer] == timer_round) {
-            timer_unset(timer);
-            int_handler(timer);
-        }
+    short timer = taiv / 2;
+    /* TAIV = 0x0A means overflow */
+    if (taiv == 0x0A) {
+        DEBUG("Overflow\n");
+        timer_round += 1;
+    }
+    /* check which CCR has been hit and if the overflow counter for this timer
+     * has been reached */
+    else if (overflow_interrupt[timer] == timer_round) {
+        timer_unset(timer);
+        int_handler(timer);
     }
 
     __exit_isr();
-- 
GitLab