From 264b093da6c15a81c264e5954939bb5e165dc063 Mon Sep 17 00:00:00 2001
From: Fabiano Riccardi <fabiuz4@hotmail.it>
Date: Wed, 12 Oct 2016 15:59:32 +0200
Subject: [PATCH] Added the first part of RadioTimer and improvement of
 GPIOtimer

Signed-off-by: Fabiano Riccardi <fabiuz4@hotmail.it>
---
 .../interfaces-impl/gpio_timer.cpp            |  9 +-
 .../interfaces-impl/gpio_timer.h              |  1 +
 .../high_resolution_timer_base.cpp            | 88 ++++++++++++-------
 .../interfaces-impl/radio_timer.cpp           | 28 ++++++
 .../interfaces-impl/radio_timer.h             | 35 ++++++++
 miosix/config/Makefile.inc                    |  4 +-
 6 files changed, 128 insertions(+), 37 deletions(-)
 create mode 100644 miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp
 create mode 100644 miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h

diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.cpp b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.cpp
index ed9ca78a..fa4bcfe2 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.cpp
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.cpp
@@ -80,13 +80,11 @@ WaitResult GPIOtimer::waitTimeoutOrEvent(long long tick){
  */
 bool GPIOtimer::absoluteWaitTrigger(long long tick){
     FastInterruptDisableLock dLock;
-    if(!b.IRQsetNextInterrupt2(tick)){
-	return true;
-    }
     b.setModeGPIOTimer(false);    //output timer 
     setPinMode(false);	    //output pin
-    b.setCCInterrupt2Tim1(false);
-    b.setCCInterrupt2(true); //enable
+    if(b.IRQsetNextInterrupt2(tick)){
+	return true;
+    }
     return false;
 }
 
@@ -94,5 +92,6 @@ bool GPIOtimer::waitTrigger(long long tick){
     return absoluteWaitTrigger(b.getCurrentTick()+tick);
 }
 
+long long GPIOtimer::aux1=0;
 GPIOtimer::~GPIOtimer() {}
 
diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.h b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.h
index cfd19d25..4aae9c83 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.h
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.h
@@ -30,6 +30,7 @@ namespace miosix {
     class GPIOtimer{    
     public:
         static Thread *tWaitingGPIO;
+        static long long aux1;
         static GPIOtimer& instance();
         virtual ~GPIOtimer();
         WaitResult waitTimeoutOrEvent(long long value);
diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.cpp b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.cpp
index b01f15f5..03ad1119 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.cpp
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.cpp
@@ -49,6 +49,10 @@ static inline long long IRQgetTick(){
 }
 
 inline void interruptGPIOTimerRoutine(){
+    TIMER1->IEN &= ~TIMER_IEN_CC2;
+    TIMER3->IEN &= ~TIMER_IEN_CC2;
+    TIMER1->IFC = TIMER_IFC_CC2;
+    TIMER3->IFC = TIMER_IFC_CC2;
     if(TIMER1->CC[2].CTRL & TIMER_CC_CTRL_MODE_OUTPUTCOMPARE){
 	expansion::gpio10::high();
     }else if(TIMER1->CC[2].CTRL & TIMER_CC_CTRL_MODE_INPUTCAPTURE){
@@ -94,6 +98,30 @@ static inline void setupTimers(){
     // If the most significant 32bit aren't match wait for TIM3 to overflow!
 }
 
+static inline void setupTimers2(){
+    // We assume that this function is called only when the checkpoint is in future
+    if (ms32chkp[2] == ms32time){
+        // If the most significant 32bit matches, enable TIM3
+        TIMER3->IFC = TIMER_IFC_CC2;
+        TIMER3->IEN |= TIMER_IEN_CC2;
+        if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[2].CCV) + 1){
+            // If TIM3 matches by the time it is being enabled, disable it right away
+            TIMER3->IFC = TIMER_IFC_CC2;
+            TIMER3->IEN &= ~TIMER_IEN_CC2;
+            // Enable TIM1 since TIM3 has been already matched
+            TIMER1->IFC = TIMER_IFC_CC2;
+            TIMER1->IEN |= TIMER_IEN_CC2;
+            if (TIMER1->CNT >= TIMER1->CC[2].CCV){
+                // If TIM1 matches by the time it is being enabled, call the scheduler right away
+		interruptGPIOTimerRoutine();
+            }
+        }
+    }
+    // If the most significant 32bit aren't match wait for TIM3 to overflow!
+}
+
+
+
 void __attribute__((naked)) TIMER3_IRQHandler()
 {
     saveContext();
@@ -114,6 +142,7 @@ void __attribute__((used)) cstirqhnd3(){
         TIMER3->IFC = TIMER_IFC_OF;
         ms32time += overflowIncrement;
         setupTimers();
+	setupTimers2();
     }
     //Checkpoint
     if ((TIMER3->IEN & TIMER_IEN_CC1) && (TIMER3->IF & TIMER_IF_CC1)){
@@ -133,21 +162,20 @@ void __attribute__((used)) cstirqhnd3(){
     } 
     
     //This if is to manage the GPIOtimer in OUTPUT Mode
-    if((TIMER3->IEN & TIMER_IEN_CC2) && (TIMER3->IF & TIMER_IF_CC2)){
-	if (ms32time == ms32chkp[2]){
-	    TIMER3->IFC = TIMER_IFC_CC2;
-	    TIMER3->IEN &= ~TIMER_IEN_CC2;
-	    greenLed::high();
-	
-	    TIMER1->IFC = TIMER_IFC_CC2;
-	    TIMER1->IEN |= TIMER_IEN_CC2;
-	    if (TIMER1->CNT >= TIMER1->CC[2].CCV){
-		TIMER1->IEN &= ~TIMER_IEN_CC2;
-		TIMER1->IFC = TIMER_IFC_CC2;
-		interruptGPIOTimerRoutine();
-	    }
-	}
-    }
+    if ((TIMER3->IEN & TIMER_IEN_CC2) && (TIMER3->IF & TIMER_IF_CC2)){
+        TIMER3->IFC = TIMER_IFC_CC2;
+        if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[2].CCV) + 1){
+            // Should happen if and only if most significant 32 bits have been matched
+            TIMER3->IEN &= ~ TIMER_IEN_CC2;
+            // Enable TIM1 since TIM3 has been already matched
+            TIMER1->IFC = TIMER_IFC_CC2;
+            TIMER1->IEN |= TIMER_IEN_CC2;
+            if (TIMER1->CNT >= TIMER1->CC[2].CCV){
+                // If TIM1 matches by the time it is being enabled, call the scheduler right away
+                interruptGPIOTimerRoutine();
+            }
+        }
+    } 
 }
 void __attribute__((used)) cstirqhnd1(){
     if ((TIMER1->IEN & TIMER_IEN_CC1) && (TIMER1->IF & TIMER_IF_CC1)){
@@ -158,8 +186,6 @@ void __attribute__((used)) cstirqhnd1(){
     
     //This if is used to manage the case of GPIOTimer, both INPUT and OUTPUT mode
     if ((TIMER1->IEN & TIMER_IEN_CC2) && (TIMER1->IF & TIMER_IF_CC2)){
-        TIMER1->IEN &= ~TIMER_IEN_CC2;
-	TIMER1->IFC = TIMER_IFC_CC2;
         interruptGPIOTimerRoutine();
     }
 }
@@ -334,7 +360,7 @@ bool HighResolutionTimerBase::IRQsetNextInterrupt0(long long tick){
 } 
 
 bool HighResolutionTimerBase::IRQsetNextInterrupt1(long long tick){
-    // First off, clear and disable timers to prevent unnecessary IRQ
+    // First off, disable timers to prevent unnecessary IRQ
     // when IRQsetNextInterrupt is called multiple times consecutively.
     TIMER1->IEN &= ~TIMER_IEN_CC1;
     TIMER3->IEN &= ~TIMER_IEN_CC1;
@@ -356,21 +382,21 @@ bool HighResolutionTimerBase::IRQsetNextInterrupt1(long long tick){
 }
 
 bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){
-    ms32chkp[2] = tick & upperMask;
-    TIMER3->CC[2].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16)-1;
-    TIMER1->CC[2].CCV = static_cast<unsigned int>(tick & 0xFFFF);
-    /*
-    In order to prevent back to back interrupts due to a checkpoint
-    set in the past, raise lateIrq flag to indicate this IRQ should
-    be processed only once
-    */
-    if(IRQgetCurrentTick() >= IRQgetSetTimeCCV2())
-    {
-	//TIMER3->IFS=TIMER_IFS_CC2;
-        lateIrq=true;
+    TIMER1->IEN &= ~TIMER_IEN_CC2;
+    TIMER3->IEN &= ~TIMER_IEN_CC2;
+    
+    long long curTick = IRQgetTick();
+    if(curTick >= tick){
+	// The interrupt is in the past => call timerInt immediately
+	interruptGPIOTimerRoutine(); //TODO: It could cause multiple invocations of sched.
 	return false;
+    }else{
+	ms32chkp[2] = tick & upperMask;
+	TIMER3->CC[2].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16)-1;
+	TIMER1->CC[2].CCV = static_cast<unsigned int>(tick & 0xFFFF);
+	setupTimers2();
+	return true;
     }
-    return true;
 }
 
 
diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp
new file mode 100644
index 00000000..2ee7f013
--- /dev/null
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp
@@ -0,0 +1,28 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/* 
+ * File:   radio_timer.cpp
+ * Author: fabiuz
+ * 
+ * Created on October 11, 2016, 11:17 AM
+ */
+
+#include "radio_timer.h"
+
+using namespace miosix;
+
+Thread* RadioTimer::tWaitingGPIO=nullptr;
+
+RadioTimer::RadioTimer():b(HighResolutionTimerBase::instance()) {}
+
+RadioTimer& RadioTimer::instance(){
+    static RadioTimer instance;
+    return instance;
+}
+
+RadioTimer::~RadioTimer() {}
+
diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h
new file mode 100644
index 00000000..aef3f89c
--- /dev/null
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h
@@ -0,0 +1,35 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+/* 
+ * File:   radio_timer.h
+ * Author: fabiuz
+ *
+ * Created on October 11, 2016, 11:17 AM
+ */
+
+#include "high_resolution_timer_base.h"
+
+
+#ifndef RADIO_TIMER_H
+#define RADIO_TIMER_H
+
+namespace miosix{
+    class RadioTimer {
+        public:
+            static Thread *tWaitingGPIO;
+            static RadioTimer& instance();
+            virtual ~RadioTimer();
+        private:
+            RadioTimer();
+            HighResolutionTimerBase& b;
+    };
+}
+
+
+
+#endif /* RADIO_TIMER_H */
+
diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc
index 2470bdb2..2ade3acd 100644
--- a/miosix/config/Makefile.inc
+++ b/miosix/config/Makefile.inc
@@ -2114,7 +2114,9 @@ else ifeq ($(ARCH),cortexM3_efm32gg)
         $(BOARD_INC)/interfaces-impl/gpioirq.cpp        \
         $(BOARD_INC)/interfaces-impl/hardware_timer.cpp \
         $(BOARD_INC)/interfaces-impl/transceiver.cpp    \
-        $(BOARD_INC)/interfaces-impl/cstimer.cpp
+        $(BOARD_INC)/interfaces-impl/cstimer.cpp        \
+        $(BOARD_INC)/interfaces-impl/gpio_timer.cpp     \
+        $(BOARD_INC)/interfaces-impl/radio_timer.cpp
 
         ## Add a #define to allow querying board name
         CFLAGS_BASE   += -DEFM32GG332F1024 -D_BOARD_WANDSTEM
-- 
GitLab