From 5c6dc23a28be0d7c2b3d45037deeee184ff5e71d Mon Sep 17 00:00:00 2001
From: Fabiano Riccardi <fabiuz4@hotmail.it>
Date: Tue, 25 Oct 2016 18:24:43 +0200
Subject: [PATCH] Discovered and solved a couple of bugs in GPIOtimer,
 refactoring of same inconsistent function names, started to write the code
 for ping-pong test for GPIOtimer

Signed-off-by: Fabiano Riccardi <fabiuz4@hotmail.it>
---
 .../interfaces-impl/cstimer.cpp               |  4 +-
 .../interfaces-impl/gpio_timer.cpp            | 19 +++++----
 .../interfaces-impl/gpio_timer.h              |  2 -
 .../high_resolution_timer_base.cpp            | 40 ++++++++++++++-----
 .../high_resolution_timer_base.h              | 17 +++++---
 .../interfaces-impl/radio_timer.cpp           | 10 ++---
 6 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp
index e4fbff90..690ee254 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp
@@ -23,11 +23,11 @@ namespace miosix {
     }
     
     long long ContextSwitchTimer::getCurrentTime() const{
-        return tc->tick2ns(pImpl->b.getCurrentTime());
+        return tc->tick2ns(pImpl->b.getCurrentTick());
     }
     
     long long ContextSwitchTimer::IRQgetCurrentTime() const{
-        return tc->tick2ns(pImpl->b.IRQgetCurrentTime());
+        return tc->tick2ns(pImpl->b.IRQgetCurrentTick());
     }
     
     ContextSwitchTimer::~ContextSwitchTimer(){}
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 35f28731..3ce195c6 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
@@ -17,7 +17,7 @@ using namespace miosix;
 Thread* GPIOtimer::tWaitingGPIO=nullptr;
 
 long long GPIOtimer::getValue() const{
-    return b.getCurrentTime();
+    return b.getCurrentTick();
 }
 
 unsigned int GPIOtimer::getTickFrequency() const{
@@ -29,7 +29,7 @@ void GPIOtimer::wait(long long tick){
 }
 
 bool GPIOtimer::absoluteWait(long long tick){
-    if(b.getCurrentTime()>=tick){
+    if(b.getCurrentTick()>=tick){
 	return true;
     }
     Thread::nanoSleepUntil(tc.tick2ns(tick));
@@ -47,7 +47,7 @@ long long GPIOtimer::getExtEventTimestamp() const{
 
 bool GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){
     FastInterruptDisableLock dLock;
-    if(tick<b.getCurrentTime()){
+    if(tick<b.getCurrentTick()){
 	return true;
     }
     if(!isInput){
@@ -55,6 +55,7 @@ bool GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){
 	expansion::gpio10::mode(Mode::INPUT);
 	isInput=true;
     }
+    b.cleanBufferGPIO();
     b.setCCInterrupt2(false);
     b.setCCInterrupt2Tim1(true);
     
@@ -65,7 +66,7 @@ bool GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){
             FastInterruptEnableLock eLock(dLock);
 	    Thread::yield();
         }
-    } while(tWaitingGPIO && tick>b.getCurrentTime());
+    } while(tWaitingGPIO && tick>b.getCurrentTick());
     
     if(tWaitingGPIO==nullptr){
 	return false;
@@ -75,7 +76,7 @@ bool GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){
 }
 
 bool GPIOtimer::waitTimeoutOrEvent(long long tick){
-    return absoluteWaitTimeoutOrEvent(b.getCurrentTime()+tick);
+    return absoluteWaitTimeoutOrEvent(b.getCurrentTick()+tick);
 }
 
 /*
@@ -86,6 +87,7 @@ bool GPIOtimer::absoluteWaitTrigger(long long tick){
     if(isInput){
 	b.setModeGPIOTimer(false);		//output timer 
 	expansion::gpio10::mode(Mode::OUTPUT);	//output pin
+	expansion::gpio10::low();
 	isInput=false;
     }
     if(b.IRQsetNextGPIOInterrupt(tick)==WaitResult::WAKEUP_IN_THE_PAST){
@@ -95,7 +97,7 @@ bool GPIOtimer::absoluteWaitTrigger(long long tick){
 }
 
 bool GPIOtimer::waitTrigger(long long tick){
-    return absoluteWaitTrigger(b.getCurrentTime()+tick);
+    return absoluteWaitTrigger(b.getCurrentTick()+tick);
 }
 
 /*
@@ -108,6 +110,7 @@ bool GPIOtimer::absoluteSyncWaitTrigger(long long tick){
 	if(isInput){
 	    b.setModeGPIOTimer(false);			//output timer 
 	    expansion::gpio10::mode(Mode::OUTPUT);	//output pin
+	    expansion::gpio10::low();
 	    isInput=false;
 	}
 	if(b.IRQsetNextGPIOInterrupt(tick)==WaitResult::WAKEUP_IN_THE_PAST){
@@ -121,13 +124,13 @@ bool GPIOtimer::absoluteSyncWaitTrigger(long long tick){
 		FastInterruptEnableLock eLock(dLock);
 		Thread::yield();
 	    }
-	} while(tWaitingGPIO && tick>b.getCurrentTime());
+	} while(tWaitingGPIO && tick>b.getCurrentTick());
     }
     return false;
 }
 
 bool GPIOtimer::syncWaitTrigger(long long tick){
-    return absoluteSyncWaitTrigger(b.getCurrentTime()+tick); 
+    return absoluteSyncWaitTrigger(b.getCurrentTick()+tick); 
 }
 
 long long GPIOtimer::tick2ns(long long tick){
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 289434b2..105c44ec 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
@@ -18,8 +18,6 @@
 #ifndef GPIO_TIMER_H
 #define GPIO_TIMER_H
 
-static volatile int aux=0;
-
 namespace miosix {
     
     class GPIOtimer : public HardwareTimer{    
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 1aaf6bb9..1e0302c3 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
@@ -55,11 +55,24 @@ static inline long long IRQgetTick(){
     return ms32time | static_cast<long long>(counter);
 }
 
+void falseRead(volatile uint32_t *p){
+    *p;
+}
+
 inline void interruptGPIOTimerRoutine(){
     if(TIMER1->CC[2].CTRL & TIMER_CC_CTRL_MODE_OUTPUTCOMPARE){
 	TIMER1->CC[2].CTRL = (TIMER1->CC[2].CTRL & ~_TIMER_CC_CTRL_CMOA_MASK) | TIMER_CC_CTRL_CMOA_CLEAR;
 	//10 tick are enough to execute this line
 	TIMER1->CC[2].CCV = static_cast<unsigned short>(TIMER1->CNT+10);//static_cast<unsigned int>(tick & 0xFFFF);
+    }else if(TIMER1->CC[2].CTRL & TIMER_CC_CTRL_MODE_INPUTCAPTURE){
+	ms32chkp[2]=ms32time;
+	HighResolutionTimerBase& b=HighResolutionTimerBase::instance();
+	//really in the past, the overflow of TIMER3 is occurred but the timer wasn't updated
+	long long a=b.IRQgetSetTimeCCV2();
+	long long c=b.getCurrentTick();
+	if(a-c< -48000000){ 
+	    ms32chkp[2]+=overflowIncrement;
+	}
     }
     //Reactivating the thread that is waiting for the event.
     if(GPIOtimer::tWaitingGPIO){
@@ -165,6 +178,7 @@ void __attribute__((used)) cstirqhnd3(){
     } 
 }
 
+
 void __attribute__((used)) cstirqhnd2(){
     //CC0 listening for received packet 
     if ((TIMER2->IEN & TIMER_IEN_CC0) && (TIMER2->IF & TIMER_IF_CC0) ){
@@ -172,7 +186,7 @@ void __attribute__((used)) cstirqhnd2(){
 	 TIMER2->IFC = TIMER_IFC_CC0;
 	 interruptRadioTimerRoutine();
     }
-    //CC1 for output/trigger
+    //CC1 for output/trigger the sending packet event
     if ((TIMER2->IEN & TIMER_IEN_CC1) && (TIMER2->IF & TIMER_IF_CC1) ){
 	 TIMER2->IEN &= ~ TIMER_IEN_CC1;
 	 TIMER2->IFC = TIMER_IFC_CC1;
@@ -198,7 +212,7 @@ void __attribute__((used)) cstirqhnd1(){
 	    
 	    //get nextInterrupt
 	    long long t=ms32chkp[2]|TIMER1->CC[2].CCV;
-	    long long diff=t-b.IRQgetCurrentTime();
+	    long long diff=t-b.IRQgetCurrentTick();
 	    if(diff<=0xFFFF){
 		TIMER1->CC[2].CTRL = (TIMER1->CC[2].CTRL & ~_TIMER_CC_CTRL_CMOA_MASK) | TIMER_CC_CTRL_CMOA_SET;
 		faseGPIO=1;
@@ -220,7 +234,7 @@ long long HighResolutionTimerBase::IRQgetSetTimeCCV2() const{
     return ms32chkp[2] | TIMER3->CC[2].CCV<<16 | TIMER1->CC[2].CCV;
 }
 
-long long HighResolutionTimerBase::IRQgetCurrentTime(){
+long long HighResolutionTimerBase::IRQgetCurrentTick(){
     return IRQgetTick();
 }
 
@@ -245,9 +259,10 @@ void HighResolutionTimerBase::setCCInterrupt2(bool enable){
 }
 
 void HighResolutionTimerBase::setCCInterrupt2Tim1(bool enable){
-    if(enable)
+    if(enable){
+	TIMER1->IFC= TIMER_IF_CC2;
         TIMER1->IEN|=TIMER_IEN_CC2;
-    else
+    }else
         TIMER1->IEN&=~TIMER_IEN_CC2;
 }
 
@@ -258,13 +273,13 @@ void HighResolutionTimerBase::setCCInterrupt0Tim2(bool enable){
         TIMER2->IEN&=~TIMER_IEN_CC0;
 }
 
-long long HighResolutionTimerBase::getCurrentTime(){
+long long HighResolutionTimerBase::getCurrentTick(){
     bool interrupts=areInterruptsEnabled();
     //TODO: optimization opportunity, if we can guarantee that no call to this
     //function occurs before kernel is started, then we can use
     //fastInterruptDisable())
     if(interrupts) disableInterrupts();
-    long long result=IRQgetCurrentTime();
+    long long result=IRQgetCurrentTick();
     if(interrupts) enableInterrupts();
     return result;
 
@@ -332,8 +347,7 @@ WaitResult HighResolutionTimerBase::IRQsetNextGPIOInterrupt(long long tick){
 	ms32chkp[2] = tick & (upperMask | 0xFFFF0000);
 	TIMER1->CC[2].CCV = t1;
 
-	TIMER1->IFC = TIMER_IFC_CC2;
-	TIMER1->IEN |= TIMER_IEN_CC2;
+	setCCInterrupt2Tim1(true);
 	//0xFFFF because it's the roundtrip of timer
 	if(diff<=0xFFFF){
 	    TIMER1->CC[2].CTRL = (TIMER1->CC[2].CTRL & ~_TIMER_CC_CTRL_CMOA_MASK) | TIMER_CC_CTRL_CMOA_SET;
@@ -366,7 +380,7 @@ void HighResolutionTimerBase::setModeGPIOTimer(bool input){
 	//TIMER3->CC2 as consumer
 	TIMER3->CC[2].CTRL= TIMER_CC_CTRL_PRSSEL_PRSCH0
 			|   TIMER_CC_CTRL_INSEL_PRS
-			|   TIMER_CC_CTRL_ICEDGE_BOTH
+			|   TIMER_CC_CTRL_ICEDGE_RISING  //NOTE: when does the output get low?
 			|   TIMER_CC_CTRL_MODE_INPUTCAPTURE;
 	faseGPIO=1;
     }else{
@@ -375,6 +389,12 @@ void HighResolutionTimerBase::setModeGPIOTimer(bool input){
     } 
 }
 
+void HighResolutionTimerBase::cleanBufferGPIO(){
+    falseRead(&TIMER3->CC[2].CCV);
+    falseRead(&TIMER1->CC[2].CCV);
+    falseRead(&TIMER3->CC[2].CCV);
+    falseRead(&TIMER1->CC[2].CCV);
+}
 
 void HighResolutionTimerBase::setModeRadioTimer(bool input){
     //Connect TIMER2->CC0/1 to pin PA8 and PA9
diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h
index 09b5616a..0e511496 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h
@@ -54,13 +54,23 @@ public:
     long long IRQgetSetTimeCCV0() const;
     long long IRQgetSetTimeCCV1() const;
     long long IRQgetSetTimeCCV2() const;
+    
+    /*
+     * Clean buffer in TIMER used by GPIOTimer
+     */
+    void cleanBufferGPIO();
     /**
      * Could be call both when the interrupts are enabled/disabled!
      * TODO: investigate if it's possible to remove the possibility to call
      * this with IRQ disabled and use IRQgetCurrentTime() instead
      * \return the current tick count of the timer
      */
-    long long getCurrentTime();
+    long long getCurrentTick();
+    /**
+     * \return the current tick count of the timer.
+     * Can only be called with interrupts disabled or within an IRQ
+     */
+    long long IRQgetCurrentTick();
     
     void setCCInterrupt0(bool enable);
     void setCCInterrupt1(bool enable);
@@ -69,11 +79,6 @@ public:
     void setCCInterrupt0Tim2(bool enable);
     void setModeGPIOTimer(bool input);
     void setModeRadioTimer(bool input);
-    /**
-     * \return the current tick count of the timer.
-     * Can only be called with interrupts disabled or within an IRQ
-     */
-    long long IRQgetCurrentTime();
     
     virtual ~HighResolutionTimerBase();
     
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
index b81d97da..ed7245f0 100644
--- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp
+++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.cpp
@@ -18,7 +18,7 @@ using namespace miosix;
 Thread* RadioTimer::tWaiting=nullptr;
 
 long long RadioTimer::getValue() const{
-     return b.getCurrentTime();
+     return b.getCurrentTick();
  }  
             
 void RadioTimer::wait(long long tick){
@@ -26,7 +26,7 @@ void RadioTimer::wait(long long tick){
 }
 
 bool RadioTimer::absoluteWait(long long tick){
-    if(b.getCurrentTime()>=tick){
+    if(b.getCurrentTick()>=tick){
 	return true;
     }
     Thread::nanoSleepUntil(tc.tick2ns(tick));
@@ -46,13 +46,13 @@ bool RadioTimer::absoluteWaitTrigger(long long tick){
 	    FastInterruptEnableLock eLock(dLock);
 	    Thread::yield();
 	}
-    } while(tWaiting && tick>b.getCurrentTime());
+    } while(tWaiting && tick>b.getCurrentTick());
     return false;
 }
 
 bool RadioTimer::absoluteWaitTimeoutOrEvent(long long tick){
     FastInterruptDisableLock dLock;
-    if(tick<b.getCurrentTime()){
+    if(tick<b.getCurrentTick()){
 	return true;
     }
     
@@ -66,7 +66,7 @@ bool RadioTimer::absoluteWaitTimeoutOrEvent(long long tick){
             FastInterruptEnableLock eLock(dLock);
 	    Thread::yield();
         }
-    } while(tWaiting && tick>b.getCurrentTime());
+    } while(tWaiting && tick>b.getCurrentTick());
     
     if(tWaiting==nullptr){
 	return false;
-- 
GitLab