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 7ad008ad4e35fcba458f7a7e78e387172e3f2441..ce0ee8788e57597ba172f9beb08222d9a670f03b 100644 --- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp @@ -18,6 +18,8 @@ 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; @@ -112,7 +114,8 @@ namespace miosix { return instance; } - void ContextSwitchTimer::IRQsetNextInterrupt(long long tick){ + 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); @@ -130,7 +133,7 @@ namespace miosix { long long ContextSwitchTimer::getNextInterrupt() const { - return nextInterrupt(); + return tc->tick2ns(nextInterrupt()); } long long ContextSwitchTimer::getCurrentTick() const @@ -140,14 +143,14 @@ namespace miosix { //function occurs before kernel is started, then we can use //fastInterruptDisable()) if(interrupts) disableInterrupts(); - long long result=IRQgetTick(); + long long result=tc->tick2ns(IRQgetTick()); if(interrupts) enableInterrupts(); return result; } long long ContextSwitchTimer::IRQgetCurrentTick() const { - return IRQgetTick(); + return tc->tick2ns(IRQgetTick()); } ContextSwitchTimer::~ContextSwitchTimer(){} @@ -185,9 +188,8 @@ namespace miosix { TIMER1->CMD = TIMER_CMD_START; //Setup tick2ns conversion tool timerFreq = 48000000; - tc=new TimeConversion(timerFreq); + static TimeConversion stc(timerFreq); + tc = &stc; } -TimeConversion *tc; - } \ No newline at end of file diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp index 4b8ef538c66fdd9043630f8f75dea1de30b6a216..f3c678fb66416a8baa91e1dda4d06419e4069f58 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp @@ -16,6 +16,8 @@ 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 | TIM2->CCR1; @@ -91,8 +93,9 @@ ContextSwitchTimer& ContextSwitchTimer::instance() return instance; } -void ContextSwitchTimer::IRQsetNextInterrupt(long long tick) +void ContextSwitchTimer::IRQsetNextInterrupt(long long ns) { + long long tick = tc->ns2tick(ns); ms32chkp = tick & upperMask; TIM2->CCR1 = static_cast<unsigned int>(tick & lowerMask); if(IRQgetTick() >= nextInterrupt()) @@ -104,7 +107,7 @@ void ContextSwitchTimer::IRQsetNextInterrupt(long long tick) long long ContextSwitchTimer::getNextInterrupt() const { - return nextInterrupt(); + return tc->tick2ns(nextInterrupt()); } long long ContextSwitchTimer::getCurrentTick() const @@ -114,14 +117,14 @@ long long ContextSwitchTimer::getCurrentTick() const //function occurs before kernel is started, then we can use //fastInterruptDisable()) if(interrupts) disableInterrupts(); - long long result=IRQgetTick(); + long long result=tc->tick2ns(IRQgetTick()); if(interrupts) enableInterrupts(); return result; } long long ContextSwitchTimer::IRQgetCurrentTick() const { - return IRQgetTick(); + return tc->tick2ns(IRQgetTick()); } ContextSwitchTimer::~ContextSwitchTimer() {} @@ -170,9 +173,8 @@ ContextSwitchTimer::ContextSwitchTimer() // interface. After this, the freq variable contains the frequency in Hz // at which the timer prescaler is clocked. if(RCC->CFGR & RCC_CFGR_PPRE1_2) timerFreq/=1<<((RCC->CFGR>>10) & 0x3); - tc=new TimeConversion(timerFreq); + static TimeConversion stc(timerFreq); + tc = &stc; } -TimeConversion *tc; - } //namespace miosix diff --git a/miosix/interfaces/cstimer.h b/miosix/interfaces/cstimer.h index e9b1af524d92e8fb8bce9d2ebc9a9eb407950f58..704bc62b741d30a0721eaafcf6791b811b78cab5 100644 --- a/miosix/interfaces/cstimer.h +++ b/miosix/interfaces/cstimer.h @@ -1,14 +1,16 @@ #ifndef CSTIMER_H #define CSTIMER_H -#include "kernel/timeconversion.h" - namespace miosix { /** * This class is a low level interface to a hardware timer, that is used as * the basis for the Miosix timing infrastructure. In detail, it allows to - * set interrupts used both for thread wakeup from sleep, and for preemption. + * set interrupts used both for thread wakeup from sleep, and for preemption. + * Please note that although the HW timer may operate in ticks, the class should + * provide the user (which is kernel/scheduler codes) with a timing scheme + * in nanoseconds. It is highly recommended to use TimeConversion class for + * this purpose. */ class ContextSwitchTimer { @@ -21,7 +23,7 @@ public: /** * 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 + * \param tick the time when the interrupt will be fired, in nanoseconds */ void IRQsetNextInterrupt(long long tick); @@ -35,12 +37,12 @@ public: * 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 + * \return the current tick count of the timer (in terms of nanoseconds) */ long long getCurrentTick() const; /** - * \return the current tick count of the timer. + * \return the current tick count of the timer (in terms of nanoseconds) * Can only be called with interrupts disabled or within an IRQ */ long long IRQgetCurrentTick() const; @@ -67,8 +69,6 @@ private: unsigned int timerFreq; }; -extern TimeConversion *tc; - } //namespace miosix #endif //TIMER_H diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp index 2bda2f376f4d2d3df5fd52bde9be5ad7eecc463b..e1b0e5dc31e05ea2bfed6daf8f4eea4c61c9d438 100644 --- a/miosix/kernel/kernel.cpp +++ b/miosix/kernel/kernel.cpp @@ -66,8 +66,6 @@ volatile Thread *cur=NULL;///<\internal Thread currently running static volatile bool exist_deleted=false; IntrusiveList<SleepData> *sleepingList=nullptr;///list of sleeping threads -///Contains head of the sleeping list in terms of timer's ticks -long long firstSleepItemTicks = std::numeric_limits<long long>::max(); ///\internal !=0 after pauseKernel(), ==0 after restartKernel() volatile int kernel_running=0; @@ -251,7 +249,7 @@ bool isKernelRunning() long long getTick() { - return tc->tick2ns(ContextSwitchTimer::instance().getCurrentTick())/preemptionPeriodNs; + return ContextSwitchTimer::instance().getCurrentTick(); } /** @@ -274,7 +272,7 @@ void IRQaddToSleepingList(SleepData *x) while (it != sleepingList->end() && (*it)->wakeup_time < x->wakeup_time ) ++it; sleepingList->insert(it,x); } - firstSleepItemTicks = tc->ns2tick(sleepingList->front()->wakeup_time); + //firstSleepItemTicks = tc->ns2tick(sleepingList->front()->wakeup_time); } /** @@ -304,10 +302,10 @@ bool IRQwakeThreads(long long currentTick) result = true; } } - if(sleepingList->empty()) - firstSleepItemTicks = std::numeric_limits<long long>::max(); - else - firstSleepItemTicks = tc->ns2tick(sleepingList->front()->wakeup_time); +// if(sleepingList->empty()) +// firstSleepItemTicks = std::numeric_limits<long long>::max(); +// else +// firstSleepItemTicks = tc->ns2tick(sleepingList->front()->wakeup_time); return result; } @@ -375,7 +373,7 @@ void Thread::nanoSleep(long long ns) { if(ns==0) return; //TODO: should be (ns < resolution + epsilon) //TODO: Mutual Exclusion issue - nanoSleepUntil(tc->tick2ns(ContextSwitchTimer::instance().getCurrentTick()) + ns); + nanoSleepUntil(ContextSwitchTimer::instance().getCurrentTick() + ns); } void Thread::nanoSleepUntil(long long absoluteTime) diff --git a/miosix/kernel/scheduler/priority/priority_scheduler.cpp b/miosix/kernel/scheduler/priority/priority_scheduler.cpp index c146898c537dc50bae36afb610891c11b84cfd19..e5aed7b52a6b7cd031331016b8a1b43b72295275 100644 --- a/miosix/kernel/scheduler/priority/priority_scheduler.cpp +++ b/miosix/kernel/scheduler/priority/priority_scheduler.cpp @@ -30,6 +30,7 @@ #include "kernel/process.h" #include "interfaces/cstimer.h" #include "kernel/timeconversion.h" +#include <limits> #ifdef SCHED_TYPE_PRIORITY namespace miosix { @@ -38,7 +39,6 @@ namespace miosix { extern volatile Thread *cur; extern volatile int kernel_running; static ContextSwitchTimer& timer = ContextSwitchTimer::instance(); -extern long long firstSleepItemTicks; extern IntrusiveList<SleepData> *sleepingList; // @@ -202,13 +202,17 @@ void PriorityScheduler::IRQsetIdleThread(Thread *idleThread) } static void setNextPreemption(bool curIsIdleThread){ - static long long preemptionPeriodTicks = tc->ns2tick(preemptionPeriodNs); + long long firstWakeupInList; + if (sleepingList->empty()) + firstWakeupInList = std::numeric_limits<long long>::max(); + else + firstWakeupInList = sleepingList->front()->wakeup_time; if (curIsIdleThread){ - timer.IRQsetNextInterrupt(firstSleepItemTicks); + timer.IRQsetNextInterrupt(firstWakeupInList); }else{ - long long nextPeriodicPreemption = timer.IRQgetCurrentTick() + preemptionPeriodTicks; - if (firstSleepItemTicks < nextPeriodicPreemption ) - timer.IRQsetNextInterrupt(firstSleepItemTicks); + long long nextPeriodicPreemption = timer.IRQgetCurrentTick() + preemptionPeriodNs; + if (firstWakeupInList < nextPeriodicPreemption ) + timer.IRQsetNextInterrupt(firstWakeupInList); else timer.IRQsetNextInterrupt(nextPeriodicPreemption); }