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 ce0ee8788e57597ba172f9beb08222d9a670f03b..f18ff179de6266695c48f3885c180444948edfc6 100644 --- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp @@ -3,109 +3,15 @@ #include "kernel/kernel.h" #include "kernel/scheduler/timer_interrupt.h" #include "kernel/timeconversion.h" -#include "../../../../../debugpin.h" -#include "CMSIS/Include/core_cm3.h" -#include "bsp_impl.h" +#include "high_resolution_timer_base.h" using namespace miosix; -const unsigned int timerBits=32; -const unsigned long long overflowIncrement=(1LL<<timerBits); -const unsigned long long lowerMask=overflowIncrement-1; -const unsigned long long upperMask=0xFFFFFFFFFFFFFFFFLL-lowerMask; - -static long long ms32time = 0; //most significant 32 bits of counter -static long long ms32chkp = 0; //most significant 32 bits of check point -static bool lateIrq=false; - static TimeConversion *tc; -static inline long long nextInterrupt() -{ - return ms32chkp | TIMER3->CC[1].CCV<<16 | TIMER1->CC[1].CCV; -} - -static inline unsigned int IRQread32Timer(){ - unsigned int high=TIMER3->CNT; - unsigned int low=TIMER1->CNT; - unsigned int high2=TIMER3->CNT; - if(high==high2){ - return (high<<16)|low; - } - return high2<<16|TIMER1->CNT; -} - -static inline long long IRQgetTick(){ - //PENDING BIT TRICK - unsigned int counter=IRQread32Timer(); - if((TIMER3->IF & _TIMER_IFC_OF_MASK) && IRQread32Timer()>=counter) - return (ms32time | static_cast<long long>(counter)) + overflowIncrement; - return ms32time | static_cast<long long>(counter); -} - -void __attribute__((naked)) TIMER3_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd3v"); - restoreContext(); -} - -void __attribute__((naked)) TIMER1_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd1v"); - restoreContext(); -} -void __attribute__((naked)) TIMER2_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd2v"); - restoreContext(); -} - -void __attribute__((used)) cstirqhnd3(){ - //Checkpoint - if (lateIrq){ - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); - lateIrq = false; - }else if (TIMER3->IF & TIMER_IF_CC1){ - TIMER3->IFC = TIMER_IFC_CC1; - if (ms32time == ms32chkp){ - TIMER1->IFC = TIMER_IFC_CC1; - NVIC_ClearPendingIRQ(TIMER1_IRQn); - NVIC_EnableIRQ(TIMER1_IRQn); - if (TIMER1->CNT >= TIMER1->CC[1].CCV){ - TIMER1->IFC = TIMER_IFC_CC1; - NVIC_DisableIRQ(TIMER1_IRQn); - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); - } - } - } - - //rollover - if (TIMER3->IF & TIMER_IF_OF){ - TIMER3->IFC = TIMER_IFC_OF; - ms32time += overflowIncrement; - } -} -void __attribute__((used)) cstirqhnd1(){ - //Checkpoint - if (TIMER1->IF & TIMER_IF_CC1){ - TIMER1->IFC = TIMER_IFC_CC1; - NVIC_ClearPendingIRQ(TIMER1_IRQn); - NVIC_DisableIRQ(TIMER1_IRQn); - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); - } -} - -void __attribute__((used)) cstirqhnd2(){ - -} - // // class ContextSwitchTimer // - namespace miosix { ContextSwitchTimer& ContextSwitchTimer::instance() @@ -115,81 +21,29 @@ namespace miosix { } void ContextSwitchTimer::IRQsetNextInterrupt(long long ns){ - long long tick = tc->ns2tick(ns); - ms32chkp = tick & upperMask; - TIMER3->CC[1].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); - TIMER1->CC[1].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(IRQgetTick() >= nextInterrupt()) - { - NVIC_SetPendingIRQ(TIMER3_IRQn); - lateIrq=true; - } + b.IRQsetNextInterrupt1(tc->ns2tick(ns)); } long long ContextSwitchTimer::getNextInterrupt() const { - return tc->tick2ns(nextInterrupt()); + return tc->tick2ns(b.IRQgetSetTimeCCV1()); } long long ContextSwitchTimer::getCurrentTick() const { - 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=tc->tick2ns(IRQgetTick()); - if(interrupts) enableInterrupts(); - return result; + return tc->tick2ns(b.getCurrentTick()); } long long ContextSwitchTimer::IRQgetCurrentTick() const { - return tc->tick2ns(IRQgetTick()); + return tc->tick2ns(b.IRQgetCurrentTick()); } ContextSwitchTimer::~ContextSwitchTimer(){} - ContextSwitchTimer::ContextSwitchTimer() + ContextSwitchTimer::ContextSwitchTimer(): b(HighResolutionTimerBase::instance()) { - //Power the timers up - { - InterruptDisableLock l; - CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_TIMER1 | CMU_HFPERCLKEN0_TIMER2 - | CMU_HFPERCLKEN0_TIMER3; - } - //Configure Timers - TIMER1->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_PRESCHFPERCLK - | TIMER_CTRL_PRESC_DIV1 | TIMER_CTRL_SYNC; - TIMER2->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_PRESCHFPERCLK - | TIMER_CTRL_PRESC_DIV1 | TIMER_CTRL_SYNC; - TIMER3->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_TIMEROUF - | TIMER_CTRL_SYNC; - - //Enable necessary interrupt lines - TIMER1->IEN = TIMER_IEN_CC1; - TIMER3->IEN = TIMER_IEN_OF | TIMER_IEN_CC1; - - TIMER1->CC[1].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; - TIMER3->CC[1].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; - - NVIC_SetPriority(TIMER1_IRQn,3); - NVIC_SetPriority(TIMER3_IRQn,3); - NVIC_ClearPendingIRQ(TIMER3_IRQn); - NVIC_ClearPendingIRQ(TIMER1_IRQn); - NVIC_EnableIRQ(TIMER3_IRQn); - NVIC_DisableIRQ(TIMER1_IRQn); - //Start timers - TIMER1->CMD = TIMER_CMD_START; - //Setup tick2ns conversion tool - timerFreq = 48000000; - static TimeConversion stc(timerFreq); + static TimeConversion stc(b.getTimerFrequency()); tc = &stc; } - } \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..e5bd2bc0a255365e58796fd255fd5ddeb4091d96 --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.cpp @@ -0,0 +1,96 @@ +/* + * File: gpio_timer.cpp + * Author: fabiuz + * + * Created on September 27, 2016, 6:30 AM + */ + +#include "gpio_timer.h" +#include "high_resolution_timer_base.h" +#include "hwmapping.h" +#include "miosix.h" +#include <cstdlib> +#include <cstdio> +using namespace miosix; + +GPIOtimer& GPIOtimer::instance(){ + static GPIOtimer instance; + return instance; +} + +GPIOtimer::GPIOtimer(): b(HighResolutionTimerBase::instance()) { + expansion::gpio10::mode(Mode::OUTPUT); + isInput=true; +} + +void GPIOtimer::setPinMode(bool inputMode){ + if(inputMode){ + expansion::gpio10::mode(Mode::INPUT); + isInput=true; + }else{ + expansion::gpio10::mode(Mode::OUTPUT); + isInput=false; + } +} + +bool GPIOtimer::getMode(){ + return isInput; +} + +long long GPIOtimer::getExtEventTimestamp() const{ + return b.IRQgetSetTimeCCV2(); +} + +WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long value){ + FastInterruptDisableLock dLock; + if(value<b.getCurrentTick()){ + return WaitResult::WAKEUP_IN_THE_PAST; + } + + b.setModeGPIOTimer(true); + setPinMode(true); + b.setCCInterrupt2(false); + b.setCCInterrupt2Tim1(true); + long long ctick; + do { + HighResolutionTimerBase::tWaiting=Thread::IRQgetCurrentThread(); + Thread::IRQwait(); + { + FastInterruptEnableLock eLock(dLock); + Thread::yield(); + } + ctick = b.getCurrentTick(); + } while(HighResolutionTimerBase::tWaiting && value>ctick); + + if(HighResolutionTimerBase::tWaiting==nullptr){ + return WaitResult::EVENT; + }else{ + return WaitResult::WAIT_COMPLETED; + } +} + +WaitResult GPIOtimer::waitTimeoutOrEvent(long long value){ + return absoluteWaitTimeoutOrEvent(b.getCurrentTick()+value); +} + +/* + Not blocking function! + */ +bool GPIOtimer::absoluteWaitTrigger(long long value){ + FastInterruptDisableLock dLock; + if(!b.IRQsetNextInterrupt2(value)){ + return true; + } + b.setModeGPIOTimer(false); //output timer + setPinMode(false); //output pin + b.setCCInterrupt2(false); + b.setCCInterrupt2(true); //enable + return false; +} + +bool GPIOtimer::waitTrigger(long long value){ + return absoluteWaitTrigger(b.getCurrentTick()+value); +} + +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 new file mode 100644 index 0000000000000000000000000000000000000000..fb024b47691b41f3b72db7afa35197933433f806 --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/gpio_timer.h @@ -0,0 +1,69 @@ +/* + * 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: gpio_timer.h + * Author: fabiuz + * + * Created on September 27, 2016, 6:30 AM + */ + +#include "high_resolution_timer_base.h" +#include "hwmapping.h" + +#ifndef GPIO_TIMER_H +#define GPIO_TIMER_H + +static volatile int aux=0; + +namespace miosix { + enum class WaitResult + { + WAKEUP_IN_THE_PAST, + WAIT_COMPLETED, + EVENT + }; + + class GPIOtimer{ + public: + static GPIOtimer& instance(); + virtual ~GPIOtimer(); + WaitResult waitTimeoutOrEvent(long long value); + WaitResult absoluteWaitTimeoutOrEvent(long long value); + + /** + * 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 + * number of tick of the count rate of timer. + * 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 + */ + bool absoluteWaitTrigger(long long value); + bool waitTrigger(long long value); + + + + long long getExtEventTimestamp() const; + + bool getMode(); + + private: + GPIOtimer(); + void setPinMode(bool inputMode); + HighResolutionTimerBase& b; + bool isInput; + }; + +} + +#endif /* GPIO_TIMER_H */ + 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 new file mode 100644 index 0000000000000000000000000000000000000000..bad6a546704b93e0e34eb4dd3d149eab8fcf923d --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.cpp @@ -0,0 +1,246 @@ +/* + * 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: high_resolution_timer_base.cpp + * Author: fabiuz + * + * Created on September 27, 2016, 2:20 AM + */ + +#include "interfaces/arch_registers.h" +#include "kernel/kernel.h" +#include "kernel/scheduler/timer_interrupt.h" +#include "kernel/timeconversion.h" +#include "../../../../../debugpin.h" +#include "CMSIS/Include/core_cm3.h" +#include "bsp_impl.h" +#include "high_resolution_timer_base.h" + +using namespace miosix; + +const unsigned int timerBits=32; +const unsigned long long overflowIncrement=(1LL<<timerBits); +const unsigned long long lowerMask=overflowIncrement-1; +const unsigned long long upperMask=0xFFFFFFFFFFFFFFFFLL-lowerMask; + +static long long ms32time = 0; //most significant 32 bits of counter +static long long ms32chkp[3] = {0}; //most significant 32 bits of check point +static bool lateIrq=false; + +void __attribute__((naked)) TIMER1_IRQHandler() +{ + saveContext(); + asm volatile("bl _Z10cstirqhnd1v"); + restoreContext(); +} +void __attribute__((naked)) TIMER2_IRQHandler() +{ + saveContext(); + asm volatile("bl _Z10cstirqhnd2v"); + restoreContext(); +} + +void __attribute__((used)) cstirqhnd2(){} + + + +static inline unsigned int IRQread32Timer(){ + unsigned int high=TIMER3->CNT; + unsigned int low=TIMER1->CNT; + unsigned int high2=TIMER3->CNT; + if(high==high2){ + return (high<<16)|low; + } + return high2<<16|TIMER1->CNT; +} + +HighResolutionTimerBase& HighResolutionTimerBase::instance(){ + static HighResolutionTimerBase hrtb; + return hrtb; +} + +inline long long HighResolutionTimerBase::IRQgetSetTimeCCV0(){ + return ms32chkp[0] | TIMER3->CC[0].CCV<<16 | TIMER1->CC[0].CCV; +} +inline long long HighResolutionTimerBase::IRQgetSetTimeCCV1(){ + return ms32chkp[1] | TIMER3->CC[1].CCV<<16 | TIMER1->CC[1].CCV; +} +inline long long HighResolutionTimerBase::IRQgetSetTimeCCV2(){ + return ms32chkp[2] | TIMER3->CC[2].CCV<<16 | TIMER1->CC[2].CCV; +} + +HighResolutionTimerBase::HighResolutionTimerBase() { + //Power the timers up and PRS system + { + InterruptDisableLock l; + CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_TIMER1 | CMU_HFPERCLKEN0_TIMER2 + | CMU_HFPERCLKEN0_TIMER3 | CMU_HFPERCLKEN0_PRS; + } + //Configure Timers + TIMER1->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_PRESCHFPERCLK + | TIMER_CTRL_PRESC_DIV1 | TIMER_CTRL_SYNC; + TIMER2->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_PRESCHFPERCLK + | TIMER_CTRL_PRESC_DIV1 | TIMER_CTRL_SYNC; + TIMER3->CTRL = TIMER_CTRL_MODE_UP | TIMER_CTRL_CLKSEL_TIMEROUF + | TIMER_CTRL_SYNC; + + //Enable necessary interrupt lines + TIMER1->IEN = TIMER_IEN_CC1; + TIMER3->IEN = /*TIMER_IEN_OF |*/ TIMER_IEN_CC1; + + TIMER1->CC[1].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; + TIMER3->CC[1].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; + + NVIC_SetPriority(TIMER1_IRQn,3); + NVIC_SetPriority(TIMER3_IRQn,3); + NVIC_ClearPendingIRQ(TIMER3_IRQn); + NVIC_ClearPendingIRQ(TIMER1_IRQn); + NVIC_EnableIRQ(TIMER3_IRQn); + NVIC_DisableIRQ(TIMER1_IRQn); + + //Start timers + TIMER1->CMD = TIMER_CMD_START; + //Setup tick2ns conversion tool + timerFreq = 48000000; +} + +Thread* HighResolutionTimerBase::tWaiting=nullptr; + +HighResolutionTimerBase::~HighResolutionTimerBase() {} + +long long HighResolutionTimerBase::IRQgetCurrentTick(){ + //PENDING BIT TRICK + unsigned int counter=IRQread32Timer(); + if((TIMER3->IF & _TIMER_IFC_OF_MASK) && IRQread32Timer()>=counter) + return (ms32time | static_cast<long long>(counter)) + overflowIncrement; + return ms32time | static_cast<long long>(counter); +} + +void HighResolutionTimerBase::setCCInterrupt0(bool enable){ + if(enable){ + TIMER3->IEN|=TIMER_IEN_CC0; + }else{ + TIMER3->IEN&=~TIMER_IEN_CC0; + } +} +void HighResolutionTimerBase::setCCInterrupt1(bool enable){ + if(enable) + TIMER3->IEN|=TIMER_IEN_CC1; + else + TIMER3->IEN&=~TIMER_IEN_CC1; +} +void HighResolutionTimerBase::setCCInterrupt2(bool enable){ + if(enable) + TIMER3->IEN|=TIMER_IEN_CC2; + else + TIMER3->IEN&=~TIMER_IEN_CC2; +} + +void HighResolutionTimerBase::setCCInterrupt2Tim1(bool enable){ + if(enable) + TIMER1->IEN|=TIMER_IEN_CC2; + else + TIMER1->IEN&=~TIMER_IEN_CC2; +} + +// In this function I prepare the timer, but i don't enable the timer. +void HighResolutionTimerBase::setModeGPIOTimer(bool input){ + if(input){ + TIMER1->ROUTE=TIMER_ROUTE_CC2PEN + | TIMER_ROUTE_LOCATION_LOC1; + //Configuro la modalità input + TIMER1->CC[2].CTRL=TIMER_CC_CTRL_MODE_INPUTCAPTURE | + TIMER_CC_CTRL_ICEDGE_RISING | + TIMER_CC_CTRL_INSEL_PIN; + + //Configuro PRS Timer 3 deve essere un consumer, timer1 producer, TIMER3 keeps the most significative part + //TIMER1->CC2 as producer, i have to specify the event i'm interest in + PRS->CH[0].CTRL|=PRS_CH_CTRL_SOURCESEL_TIMER1 + |PRS_CH_CTRL_SIGSEL_TIMER1CC2; + + //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_MODE_INPUTCAPTURE; + + }else{ + TIMER1->CC[2].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; + TIMER3->CC[2].CTRL = TIMER_CC_CTRL_MODE_OUTPUTCOMPARE; + } + +} +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=IRQgetCurrentTick(); + if(interrupts) enableInterrupts(); + return result; + +} + +bool HighResolutionTimerBase::IRQsetNextInterrupt0(long long tick){ + ms32chkp[0] = tick & upperMask; + TIMER3->CC[0].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); + TIMER1->CC[0].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() >= IRQgetSetTimeCCV0()) + { + //Now we should set TIMER3->IFS=TIMER_IFS_CC0 + NVIC_SetPendingIRQ(TIMER3_IRQn); + lateIrq=true; + return false; + } + return true; +} + +bool HighResolutionTimerBase::IRQsetNextInterrupt1(long long tick){ + ms32chkp[1] = tick & upperMask; + TIMER3->CC[1].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); + TIMER1->CC[1].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() >= IRQgetSetTimeCCV1()) + { + NVIC_SetPendingIRQ(TIMER3_IRQn); + // TIMER3->IFS=TIMER_IFS_CC1; ???? + lateIrq=true; + return false; + } + return true; +} + +bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ + ms32chkp[2] = tick & upperMask; + TIMER3->CC[2].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); + 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()) + { + NVIC_SetPendingIRQ(TIMER3_IRQn); + // TIMER3->IFS=TIMER_IFS_CC2; ??? + lateIrq=true; + return false; + } + return true; +} + + 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 new file mode 100644 index 0000000000000000000000000000000000000000..9f14e31573150491447ee480102e37b8d4451b5d --- /dev/null +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h @@ -0,0 +1,79 @@ +/* + * 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: high_resolution_timer_base.h + * Author: fabiuz + * + * Created on September 27, 2016, 2:20 AM + */ + +#include "../../../../miosix.h" + +#ifndef HIGH_RESOLUTION_TIMER_BASE_H +#define HIGH_RESOLUTION_TIMER_BASE_H + +namespace miosix { + +class HighResolutionTimerBase { +public: + static Thread *tWaiting; + + static HighResolutionTimerBase& instance(); + + /** + * \return the timer frequency in Hz + */ + unsigned int getTimerFrequency() const + { + return timerFreq; + } + + /** + * Set the next interrupt. + * Can be called with interrupts disabled or within an interrupt. + * \param tick the time when the interrupt will be fired, in timer ticks + */ + bool IRQsetNextInterrupt0(long long tick); + bool IRQsetNextInterrupt1(long long tick); + bool 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(); + /** + * 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 IRQgetCurrentTick() instead + * \return the current tick count of the timer + */ + long long getCurrentTick(); + + void setCCInterrupt0(bool enable); + void setCCInterrupt1(bool enable); + void setCCInterrupt2(bool enable); + void setCCInterrupt2Tim1(bool enable); + void setModeGPIOTimer(bool input); + /** + * \return the current tick count of the timer. + * Can only be called with interrupts disabled or within an IRQ + */ + long long IRQgetCurrentTick(); + + virtual ~HighResolutionTimerBase(); + +private: + HighResolutionTimerBase(); + unsigned int timerFreq; +}; + +}//end miosix namespace +#endif /* HIGH_RESOLUTION_TIMER_BASE_H */ + diff --git a/miosix/interfaces/cstimer.h b/miosix/interfaces/cstimer.h index 704bc62b741d30a0721eaafcf6791b811b78cab5..e65b96e95cd9b96aaf3056089ffdd6a8eecb5092 100644 --- a/miosix/interfaces/cstimer.h +++ b/miosix/interfaces/cstimer.h @@ -1,6 +1,8 @@ #ifndef CSTIMER_H #define CSTIMER_H +#include "../arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/high_resolution_timer_base.h" + namespace miosix { /** @@ -65,7 +67,7 @@ private: * Constructor, private because it's a singleton */ ContextSwitchTimer(); - + HighResolutionTimerBase& b; unsigned int timerFreq; };