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 720c68ad2a2b1ffc03cfc17c143d09c56a470c3d..5a7f8b783073e0cb7bcc7ceff67b6d0da7dee9e5 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 @@ -6,7 +6,6 @@ */ #include "gpio_timer.h" -#include "high_resolution_timer_base.h" #include "hwmapping.h" #include "miosix.h" #include <cstdlib> @@ -19,13 +18,34 @@ GPIOtimer& GPIOtimer::instance(){ return instance; } -GPIOtimer::GPIOtimer(): b(HighResolutionTimerBase::instance()) { +GPIOtimer::GPIOtimer(): b(HighResolutionTimerBase::instance()),tc(b.getTimerFrequency()) { setPinMode(false); isInput=true; } Thread* GPIOtimer::tWaitingGPIO=nullptr; +long long GPIOtimer::getValue() const{ + return b.getCurrentTick(); +} + +unsigned int GPIOtimer::getTickFrequency() const{ + return b.getTimerFrequency(); +} + +void GPIOtimer::wait(long long tick){ + Thread::nanoSleep(tc.tick2ns(tick)); +} + +bool GPIOtimer::absoluteWait(long long tick){ + if(b.getCurrentTick()>=tick){ + return true; + } + Thread::nanoSleepUntil(tc.tick2ns(tick)); + return false; +} + + void GPIOtimer::setPinMode(bool inputMode){ if(inputMode){ expansion::gpio10::mode(Mode::INPUT); @@ -44,17 +64,16 @@ long long GPIOtimer::getExtEventTimestamp() const{ return b.IRQgetSetTimeCCV2(); } -WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){ +bool GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){ FastInterruptDisableLock dLock; if(tick<b.getCurrentTick()){ - return WaitResult::WAKEUP_IN_THE_PAST; + return true; } b.setModeGPIOTimer(true); setPinMode(true); b.setCCInterrupt2(false); b.setCCInterrupt2Tim1(true); - long long ctick=0; do { tWaitingGPIO=Thread::IRQgetCurrentThread(); Thread::IRQwait(); @@ -62,17 +81,16 @@ WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){ FastInterruptEnableLock eLock(dLock); Thread::yield(); } - ctick = b.getCurrentTick(); - } while(tWaitingGPIO && tick>ctick); + } while(tWaitingGPIO && tick>b.getCurrentTick()); if(tWaitingGPIO==nullptr){ - return WaitResult::EVENT; + return false; }else{ - return WaitResult::WAIT_COMPLETED; + return true; } } -WaitResult GPIOtimer::waitTimeoutOrEvent(long long tick){ +bool GPIOtimer::waitTimeoutOrEvent(long long tick){ return absoluteWaitTimeoutOrEvent(b.getCurrentTick()+tick); } @@ -83,10 +101,10 @@ bool GPIOtimer::absoluteWaitTrigger(long long tick){ FastInterruptDisableLock dLock; b.setModeGPIOTimer(false); //output timer setPinMode(false); //output pin - if(!b.IRQsetNextInterrupt2(tick)){ - return false; + if(b.IRQsetNextInterrupt2(tick)==WaitResult::WAKEUP_IN_THE_PAST){ + return true; } - return true; + return false; } bool GPIOtimer::waitTrigger(long long tick){ @@ -98,8 +116,8 @@ bool GPIOtimer::absoluteSyncWaitTrigger(long long tick){ FastInterruptDisableLock dLock; b.setModeGPIOTimer(false); //output timer setPinMode(false); //output pin - if(!b.IRQsetNextInterrupt2(tick)){ - return false; + if(b.IRQsetNextInterrupt2(tick)==WaitResult::WAKEUP_IN_THE_PAST){ + return true; } do { @@ -111,13 +129,21 @@ bool GPIOtimer::absoluteSyncWaitTrigger(long long tick){ } } while(tWaitingGPIO && tick>b.getCurrentTick()); } - return true; + return false; } bool GPIOtimer::syncWaitTrigger(long long tick){ return absoluteSyncWaitTrigger(b.getCurrentTick()+tick); } +long long GPIOtimer::tick2ns(long long tick){ + return tc.tick2ns(tick); +} + +long long GPIOtimer::ns2tick(long long ns){ + return tc.ns2tick(ns); +} + 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 32d859e36988a7e72d20cf0832004882afbeb9db..c1e8a1130962b267808803a77f8b98ff6c38ba68 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 @@ -13,6 +13,7 @@ #include "high_resolution_timer_base.h" #include "hwmapping.h" +#include "timer.h" #ifndef GPIO_TIMER_H #define GPIO_TIMER_H @@ -20,21 +21,21 @@ static volatile int aux=0; namespace miosix { - enum class WaitResult - { - WAKEUP_IN_THE_PAST, - WAIT_COMPLETED, - EVENT - }; - class GPIOtimer{ + class GPIOtimer : public TimerInterface{ public: static Thread *tWaitingGPIO; static long long aux1; + + long long getValue() const; + + void wait(long long value); + bool absoluteWait(long long value); + static GPIOtimer& instance(); virtual ~GPIOtimer(); - WaitResult waitTimeoutOrEvent(long long value); - WaitResult absoluteWaitTimeoutOrEvent(long long value); + bool waitTimeoutOrEvent(long long value); + bool absoluteWaitTimeoutOrEvent(long long value); /** * Set the timer interrupt to occur at an absolute value and put the @@ -54,10 +55,13 @@ namespace miosix { bool absoluteSyncWaitTrigger(long long tick); bool syncWaitTrigger(long long tick); - + unsigned int getTickFrequency() const; long long getExtEventTimestamp() const; + long long tick2ns(long long tick); + long long ns2tick(long long ns); + bool getMode(); private: @@ -65,6 +69,7 @@ namespace miosix { void setPinMode(bool inputMode); HighResolutionTimerBase& b; bool isInput; + TimeConversion tc; }; } 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 933535092fbd84373dce2c20fee200738ebacb84..751ef222e23667c19e822db15d71c465c0599122 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 @@ -28,7 +28,6 @@ const unsigned long long upperMask=0xFFFFFFFFFFFFFFFFLL-lowerMask; static long long ms32time = 0; //most significant 32 bits of counter static long long ms32chkp[3] = {0,0,0}; //most significant 32 bits of check point -static bool lateIrq=false; static TimeConversion* tc; static inline unsigned int IRQread32Timer(){ @@ -72,7 +71,7 @@ inline void interruptGPIOTimerRoutine(){ } -static inline void callScheduler(){ +static __attribute__((noinline)) void callScheduler(){ TIMER1->IEN &= ~TIMER_IEN_CC1; TIMER3->IEN &= ~TIMER_IEN_CC1; TIMER1->IFC = TIMER_IFC_CC1; @@ -81,13 +80,14 @@ static inline void callScheduler(){ IRQtimerInterrupt(tick); } -static inline void setupTimers(){ +static void setupTimers(){ // We assume that this function is called only when the checkpoint is in future if (ms32chkp[1] == ms32time){ // If the most significant 32bit matches, enable TIM3 TIMER3->IFC = TIMER_IFC_CC1; TIMER3->IEN |= TIMER_IEN_CC1; - if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1){ + unsigned short temp=static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1; + if (static_cast<unsigned short>(TIMER3->CNT) >= temp){ // If TIM3 matches by the time it is being enabled, disable it right away TIMER3->IFC = TIMER_IFC_CC1; TIMER3->IEN &= ~TIMER_IEN_CC1; @@ -103,7 +103,10 @@ static inline void setupTimers(){ // If the most significant 32bit aren't match wait for TIM3 to overflow! } -static inline bool setupTimers2(){ +/* + Return EVENT if the timer triggers in this routine, otherwise the timer is set and returns WAITING + */ +static WaitResult 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 @@ -123,11 +126,11 @@ static inline bool setupTimers2(){ TIMER1->CC[2].CCV = static_cast<unsigned int>(10+TIMER1->CNT); // If TIM1 matches by the time it is being enabled, call the scheduler right away interruptGPIOTimerRoutine(); - return false; + return WaitResult::EVENT; } } } - return true; + return WaitResult::WAITING; // If the most significant 32bit aren't match wait for TIM3 to overflow! } @@ -158,7 +161,8 @@ void __attribute__((used)) cstirqhnd3(){ //Checkpoint if ((TIMER3->IEN & TIMER_IEN_CC1) && (TIMER3->IF & TIMER_IF_CC1)){ TIMER3->IFC = TIMER_IFC_CC1; - if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1){ + unsigned short temp=static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1; + if (static_cast<unsigned short>(TIMER3->CNT) >= temp){ // Should happen if and only if most significant 32 bits have been matched TIMER3->IEN &= ~ TIMER_IEN_CC1; // Enable TIM1 since TIM3 has been already matched @@ -211,13 +215,13 @@ HighResolutionTimerBase& HighResolutionTimerBase::instance(){ return hrtb; } -inline long long HighResolutionTimerBase::IRQgetSetTimeCCV0(){ +long long HighResolutionTimerBase::IRQgetSetTimeCCV0() const{ return ms32chkp[0] | TIMER3->CC[0].CCV<<16 | TIMER1->CC[0].CCV; } -inline long long HighResolutionTimerBase::IRQgetSetTimeCCV1(){ +long long HighResolutionTimerBase::IRQgetSetTimeCCV1() const{ return ms32chkp[1] | TIMER3->CC[1].CCV<<16 | TIMER1->CC[1].CCV; } -inline long long HighResolutionTimerBase::IRQgetSetTimeCCV2(){ +long long HighResolutionTimerBase::IRQgetSetTimeCCV2() const{ return ms32chkp[2] | TIMER3->CC[2].CCV<<16 | TIMER1->CC[2].CCV; } @@ -352,7 +356,7 @@ void HighResolutionTimerBase::IRQsetNextInterrupt1(long long tick){ /* Return true if the pin is going to raise, otherwise false, the pin remain low because the command arrived too late */ -bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ +WaitResult HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ TIMER1->IEN &= ~TIMER_IEN_CC2; TIMER3->IEN &= ~TIMER_IEN_CC2; @@ -360,7 +364,7 @@ bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ if(curTick >= tick){ // The interrupt is in the past => call timerInt immediately interruptGPIOTimerRoutine(); //TODO: It could cause multiple invocations of sched. - return false; + return WaitResult::WAKEUP_IN_THE_PAST; }else{ ms32chkp[2] = tick & upperMask; TIMER3->CC[2].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16)-1; 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 d0dbe197245412ddce2d63f5b8eaf0d21b5163cc..ef084bbaa7732b76b954269ea9d4d1f5c46c9235 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 @@ -18,6 +18,14 @@ namespace miosix { +enum class WaitResult +{ + WAKEUP_IN_THE_PAST, + WAIT_COMPLETED, + EVENT, + WAITING +}; + class HighResolutionTimerBase { public: @@ -26,8 +34,7 @@ public: /** * \return the timer frequency in Hz */ - unsigned int getTimerFrequency() const - { + unsigned int getTimerFrequency() const{ return timerFreq; } @@ -38,15 +45,15 @@ public: */ bool IRQsetNextInterrupt0(long long tick); void IRQsetNextInterrupt1(long long tick); - bool IRQsetNextInterrupt2(long long tick); + WaitResult IRQsetNextInterrupt2(long long tick); /** * \return the time when the next interrupt will be fired. * That is, the last value passed to setNextInterrupt(). */ - long long IRQgetSetTimeCCV0(); - long long IRQgetSetTimeCCV1(); - long long IRQgetSetTimeCCV2(); + long long IRQgetSetTimeCCV0() const; + long long IRQgetSetTimeCCV1() const; + long long IRQgetSetTimeCCV2() const; /** * Could be call both when the interrupts are enabled/disabled! * TODO: investigate if it's possible to remove the possibility to call 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 2ee7f01327c800f50b0c6724bda4e532113cd3dc..5589214dc33fb43333e3ff85229a17c7e76f0dc8 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 @@ -15,9 +15,53 @@ using namespace miosix; -Thread* RadioTimer::tWaitingGPIO=nullptr; +Thread* RadioTimer::tWaitingRadio=nullptr; -RadioTimer::RadioTimer():b(HighResolutionTimerBase::instance()) {} +long long RadioTimer::getValue() const{ + return b.getCurrentTick(); + } + +void RadioTimer::wait(long long tick){ + Thread::nanoSleep(tc.tick2ns(tick)); +} + +bool RadioTimer::absoluteWait(long long tick){ + if(b.getCurrentTick()>=tick){ + return true; + } + Thread::nanoSleepUntil(tc.tick2ns(tick)); + return false; +} + +bool RadioTimer::absoluteWaitTrigger(long long tick){ + return 0; +} + +bool RadioTimer::waitTimeoutOrEvent(long long tick){ + return 0; +} +bool RadioTimer::absoluteWaitTimeoutOrEvent(long long tick){ + return 0; +} + +long long RadioTimer::tick2ns(long long tick){ + return tc.tick2ns(tick); +} + +long long RadioTimer::ns2tick(long long ns){ + return tc.ns2tick(ns); +} + +unsigned int RadioTimer::getTickFrequency() const{ + return b.getTimerFrequency(); +} + + +long long RadioTimer::getExtEventTimestamp() const{ + return b.IRQgetSetTimeCCV0(); +} + +RadioTimer::RadioTimer():b(HighResolutionTimerBase::instance()),tc(b.getTimerFrequency()) {} RadioTimer& RadioTimer::instance(){ static RadioTimer instance; 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 index aef3f89cbca5e2f1e296d6b0beeebe3678e2d1dd..e23669b2fa83d8aa2076534ebccd33f532999890 100644 --- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/radio_timer.h @@ -12,20 +12,43 @@ */ #include "high_resolution_timer_base.h" - +#include "timer.h" #ifndef RADIO_TIMER_H #define RADIO_TIMER_H namespace miosix{ - class RadioTimer { + class RadioTimer : public TimerInterface { public: - static Thread *tWaitingGPIO; + //transceiver::excChB //usato per la ricezione INPUT_CAPTURE + //transceiver::stxon //usato per attivare la trasmissione OUTPUTCOMPARE + static Thread *tWaitingRadio; static RadioTimer& instance(); virtual ~RadioTimer(); + + long long getValue() const; + + void wait(long long tick); + bool absoluteWait(long long tick); + + + bool absoluteWaitTrigger(long long tick); + + bool waitTimeoutOrEvent(long long tick); + bool absoluteWaitTimeoutOrEvent(long long tick); + + long long tick2ns(long long tick); + long long ns2tick(long long ns); + + unsigned int getTickFrequency() const; + + long long getExtEventTimestamp() const; + + private: RadioTimer(); HighResolutionTimerBase& b; + TimeConversion tc; }; } diff --git a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/timer.h b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/timer.h new file mode 100644 index 0000000000000000000000000000000000000000..378a7a9174b685d15ec733634630fff3018ef4a9 --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/timer.h @@ -0,0 +1,119 @@ +/* + * 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: timer.h + * Author: fabiuz + * + * Created on October 17, 2016, 10:27 AM + */ + +#ifndef TIMER_H +#define TIMER_H + +#include <kernel/timeconversion.h> + +namespace miosix { + +/** + * Pure virtual class defining the HardwareTimer interface. + * This interface includes support for an input capture module, used by the + * Transceiver driver to timestamp packet reception, and an output compare + * module, used again by the Transceiver to send packets deterministically. + */ + class TimerInterface{ + public: + /** + * \return the timer counter value in ticks + */ + virtual long long getValue() const=0; + + /** + * Put thread in wait for the specified relative time. + * This function wait for a relative time passed as parameter. + * \param value relative time to wait, expressed in ticks + */ + virtual void wait(long long value)=0; + + /** + * Puts the thread in wait for the specified absolute time. + * \param value absolute wait time in ticks + * If value of absolute time is in the past no waiting will be set + * and function return immediately. + * \return true if the wait time was in the past + */ + virtual bool absoluteWait(long long value)=0; + + /** + * Set the timer interrupt to occur at an absolute value and put the + * thread in wait of this. + * When the timer interrupt will occur, the associated GPIO passes + * from a low logic level to a high logic level for few us. + * \param value absolute value when the interrupt will occur, expressed in + * ticks + * If value of absolute time is in the past no waiting will be set + * and function return immediately. In this case, the GPIO will not be + * pulsed + * \return true if the wait time was in the past, in this case the GPIO + * has not been pulsed + */ + virtual bool absoluteWaitTrigger(long long value)=0; + + /** + * Put thread in waiting of timeout or extern event. + * \param value timeout expressed in ticks + * \return true in case of timeout + */ + virtual bool waitTimeoutOrEvent(long long value)=0; + + /** + * Put thread in waiting of timeout or extern event. + * \param value absolute timeout expressed in ticks + * If value of absolute time is in the past no waiting will be set + * and function return immediately. + * \return true in case of timeout, or if the wait time is in the past. + * In the corner case where both the timeout and the event are in the past, + * return false. + */ + virtual bool absoluteWaitTimeoutOrEvent(long long value)=0; + + /** + * \return the precise time in ticks when the IRQ signal of the event was + * asserted + */ + virtual long long getExtEventTimestamp() const=0; + + /** + * Althought the interface to the timer is in ticks to be able to do + * computations that are exact and use the timer resolution fully, + * these member functions are provided to convert to nanoseconds + * + * \param tick time point in timer ticks + * \return the equivalent time point in the nanosecond timescale + */ + virtual long long tick2ns(long long tick)=0; + + /** + * Althought the interface to the timer is in ticks to be able to do + * computations that are exact and use the timer resolution fully, + * these member functions are provided to convert to nanoseconds + * + * \param ns time point in nanoseconds + * \return the equivalent time point in the timer tick timescale + */ + virtual long long ns2tick(long long ns)=0; + + /** + * \return the timer frequency in Hz + */ + virtual unsigned int getTickFrequency() const=0; + }; +} + + + +#endif /* TIMER_H */ +