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 21b7724021500501be5efc356297473c58a75781..eb2111ff9dff77fc8a5bcec5fdc8f82db277cdd2 100644 --- a/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp +++ b/miosix/arch/cortexM3_efm32gg/efm32gg332f1024_wandstem/interfaces-impl/cstimer.cpp @@ -13,6 +13,8 @@ static TimeConversion *tc; // // class ContextSwitchTimer // +void __attribute__((used)) cstirqhnd2(){} + namespace miosix { ContextSwitchTimer& ContextSwitchTimer::instance() 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 e5bd2bc0a255365e58796fd255fd5ddeb4091d96..ed9ca78afb2c4a81115e2a8934d03e1b3218dfab 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 @@ -19,10 +19,12 @@ GPIOtimer& GPIOtimer::instance(){ } GPIOtimer::GPIOtimer(): b(HighResolutionTimerBase::instance()) { - expansion::gpio10::mode(Mode::OUTPUT); + setPinMode(false); isInput=true; } +Thread* GPIOtimer::tWaitingGPIO=nullptr; + void GPIOtimer::setPinMode(bool inputMode){ if(inputMode){ expansion::gpio10::mode(Mode::INPUT); @@ -41,9 +43,9 @@ long long GPIOtimer::getExtEventTimestamp() const{ return b.IRQgetSetTimeCCV2(); } -WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long value){ +WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long tick){ FastInterruptDisableLock dLock; - if(value<b.getCurrentTick()){ + if(tick<b.getCurrentTick()){ return WaitResult::WAKEUP_IN_THE_PAST; } @@ -51,45 +53,45 @@ WaitResult GPIOtimer::absoluteWaitTimeoutOrEvent(long long value){ setPinMode(true); b.setCCInterrupt2(false); b.setCCInterrupt2Tim1(true); - long long ctick; + long long ctick=0; do { - HighResolutionTimerBase::tWaiting=Thread::IRQgetCurrentThread(); + tWaitingGPIO=Thread::IRQgetCurrentThread(); Thread::IRQwait(); { FastInterruptEnableLock eLock(dLock); - Thread::yield(); + Thread::yield(); } ctick = b.getCurrentTick(); - } while(HighResolutionTimerBase::tWaiting && value>ctick); + } while(tWaitingGPIO && tick>ctick); - if(HighResolutionTimerBase::tWaiting==nullptr){ + if(tWaitingGPIO==nullptr){ return WaitResult::EVENT; }else{ return WaitResult::WAIT_COMPLETED; } } -WaitResult GPIOtimer::waitTimeoutOrEvent(long long value){ - return absoluteWaitTimeoutOrEvent(b.getCurrentTick()+value); +WaitResult GPIOtimer::waitTimeoutOrEvent(long long tick){ + return absoluteWaitTimeoutOrEvent(b.getCurrentTick()+tick); } /* Not blocking function! */ -bool GPIOtimer::absoluteWaitTrigger(long long value){ +bool GPIOtimer::absoluteWaitTrigger(long long tick){ FastInterruptDisableLock dLock; - if(!b.IRQsetNextInterrupt2(value)){ + if(!b.IRQsetNextInterrupt2(tick)){ return true; } b.setModeGPIOTimer(false); //output timer setPinMode(false); //output pin - b.setCCInterrupt2(false); + b.setCCInterrupt2Tim1(false); b.setCCInterrupt2(true); //enable return false; } -bool GPIOtimer::waitTrigger(long long value){ - return absoluteWaitTrigger(b.getCurrentTick()+value); +bool GPIOtimer::waitTrigger(long long tick){ + return absoluteWaitTrigger(b.getCurrentTick()+tick); } 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 fb024b47691b41f3b72db7afa35197933433f806..cfd19d258d1e14ef01c60730413bb14d9cce0bc7 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 @@ -29,6 +29,7 @@ namespace miosix { class GPIOtimer{ public: + static Thread *tWaitingGPIO; static GPIOtimer& instance(); virtual ~GPIOtimer(); WaitResult waitTimeoutOrEvent(long long value); @@ -47,8 +48,8 @@ namespace miosix { * \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); + bool absoluteWaitTrigger(long long tick); + bool waitTrigger(long long tick); 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 349c7723b9f18131e4fd86a3f7de0ee7c6dcc79b..b01f15f5986f8195b66712759fe9d801923ab164 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 @@ -16,6 +16,8 @@ #include "kernel/scheduler/timer_interrupt.h" #include "high_resolution_timer_base.h" #include "kernel/timeconversion.h" +#include "gpio_timer.h" + using namespace miosix; const unsigned int timerBits=32; @@ -51,12 +53,12 @@ inline void interruptGPIOTimerRoutine(){ expansion::gpio10::high(); }else if(TIMER1->CC[2].CTRL & TIMER_CC_CTRL_MODE_INPUTCAPTURE){ //Reactivating the thread that is waiting for the event. - if(HighResolutionTimerBase::tWaitingGPIO) + if(GPIOtimer::tWaitingGPIO) { - HighResolutionTimerBase::tWaitingGPIO->IRQwakeup(); - if(HighResolutionTimerBase::tWaitingGPIO->IRQgetPriority()>Thread::IRQgetCurrentThread()->IRQgetPriority()) + GPIOtimer::tWaitingGPIO->IRQwakeup(); + if(GPIOtimer::tWaitingGPIO->IRQgetPriority()>Thread::IRQgetCurrentThread()->IRQgetPriority()) Scheduler::IRQfindNextThread(); - HighResolutionTimerBase::tWaitingGPIO=nullptr; + GPIOtimer::tWaitingGPIO=nullptr; } } } @@ -64,135 +66,34 @@ inline void interruptGPIOTimerRoutine(){ static inline void callScheduler(){ TIMER1->IEN &= ~TIMER_IEN_CC1; TIMER3->IEN &= ~TIMER_IEN_CC1; + TIMER1->IFC = TIMER_IFC_CC1; + TIMER3->IFC = TIMER_IFC_CC1; long long tick = tc->tick2ns(IRQgetTick()); IRQtimerInterrupt(tick); } -static inline void setupTimers(long long curTick,long long nextIntTick){ - long long diffs = ms32chkp[1] - ms32time; - long int diff = TIMER3->CC[1].CCV - TIMER3->CNT; - if (diffs == 0 || (diffs==1 && (TIMER3->IF & TIMER_IF_OF)) ){ - if (diff==0 || diff==-1){ - if (diff==-1){ //if TIM1 overflows before calculating diff - callScheduler(); - }else{ - TIMER1->IFC = TIMER_IFC_CC1; - TIMER1->IEN |= TIMER_IEN_CC1; - if (TIMER1->CNT > TIMER1->CC[1].CCV || /* TIM1 overflows after calculating diff */ - (TIMER3->CC[1].CCV - static_cast<unsigned int>((IRQgetTick() & 0xFFFF0000)>>16)==-1 && - TIMER1->CNT < TIMER1->CC[1].CCV)){ - - callScheduler(); - } - } - }else{ - TIMER3->CC[1].CCV--; - TIMER3->IFC = TIMER_IFC_CC1; - TIMER3->IEN |= TIMER_IEN_CC1; - if (TIMER3->CNT == TIMER3->CC[1].CCV){ - TIMER1->IFC = TIMER_IFC_CC1; - TIMER1->IEN |= TIMER_IEN_CC1; - TIMER3->IEN &= ~TIMER_IEN_CC1; - }else if (TIMER3->CNT > TIMER3->CC[1].CCV){ - callScheduler(); - } - } - }else{ +static inline 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; - } -} -/* -void __attribute__((naked)) TIMER3_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd3v"); - restoreContext(); -} - - - //This routine has to manage the timer1 interrupt disable/enable to guarantee efficiency - -void __attribute__((used)) cstirqhnd3(){ - //Context Switch - Checkpoint - if (lateIrq){ - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); - lateIrq = false; - }else if (TIMER3->IF & TIMER_IF_CC1){ - TIMER3->IFC = TIMER_IFC_CC1; - if (ms32time == ms32chkp[1]){ - TIMER1->IFC = TIMER_IFC_CC1; - NVIC_ClearPendingIRQ(TIMER1_IRQn); - NVIC_EnableIRQ(TIMER1_IRQn); - //TIMER1->IEN |= TIMER_IEN_CC1; + TIMER3->IEN |= TIMER_IEN_CC1; + if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1){ + // If TIM3 matches by the time it is being enabled, disable it right away + TIMER3->IFC = TIMER_IFC_CC1; + TIMER3->IEN &= ~TIMER_IEN_CC1; + // Enable TIM1 since TIM3 has been already matched + TIMER1->IFC = TIMER_IFC_CC1; + TIMER1->IEN |= TIMER_IEN_CC1; if (TIMER1->CNT >= TIMER1->CC[1].CCV){ - TIMER1->IFC = TIMER_IFC_CC1; - NVIC_DisableIRQ(TIMER1_IRQn); - //TIMER1->IEN &= ~TIMER_IEN_CC1; - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); + // If TIM1 matches by the time it is being enabled, call the scheduler right away + callScheduler(); } } } - -// if(TIMER3->IF & TIMER_IF_CC0){ -// TIMER3->IFC = TIMER_IFC_CC0; -// if (ms32time == ms32chkp[0]){ -// //global++; -// TIMER1->IFC = TIMER_IFC_CC0; -// TIMER1->IEN |= TIMER_IEN_CC0; -// NVIC_ClearPendingIRQ(TIMER1_IRQn); -// NVIC_EnableIRQ(TIMER1_IRQn); -// if (TIMER1->CNT >= TIMER1->CC[0].CCV){ -// TIMER1->IEN &= ~TIMER_IEN_CC0; -// TIMER1->IFC = TIMER_IFC_CC0; -// interruptGPIOTimerRoutine(); -// //global+=10; -// } -// } -// } - - //Rollover - if (TIMER3->IF & TIMER_IF_OF){ - TIMER3->IFC = TIMER_IFC_OF; - ms32time += overflowIncrement; - } -} - -void __attribute__((used)) cstirqhnd1(){ - //Context Switch - Checkpoint - if (TIMER1->IF & TIMER_IF_CC1){ - TIMER1->IFC = TIMER_IFC_CC1; - //TIMER1->IEN &= ~TIMER_IEN_CC1; - NVIC_ClearPendingIRQ(TIMER1_IRQn); - NVIC_DisableIRQ(TIMER1_IRQn); - IRQtimerInterrupt(tc->tick2ns(IRQgetTick())); - } - -// if (TIMER1->IF & TIMER_IF_CC2){ -// //global+=100; -// TIMER1->IEN &= ~TIMER_IEN_CC2; -// TIMER1->IFC = TIMER_IFC_CC2; -// NVIC_ClearPendingIRQ(TIMER1_IRQn); -// interruptGPIOTimerRoutine(); -// } - -} - -void __attribute__((naked)) TIMER1_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd1v"); - restoreContext(); -} -void __attribute__((naked)) TIMER2_IRQHandler() -{ - saveContext(); - asm volatile("bl _Z10cstirqhnd2v"); - restoreContext(); + // If the most significant 32bit aren't match wait for TIM3 to overflow! } -void __attribute__((used)) cstirqhnd2(){} -*/ void __attribute__((naked)) TIMER3_IRQHandler() { saveContext(); @@ -208,31 +109,59 @@ void __attribute__((naked)) TIMER1_IRQHandler() } void __attribute__((used)) cstirqhnd3(){ - + //rollover + if (TIMER3->IF & TIMER_IF_OF){ + TIMER3->IFC = TIMER_IFC_OF; + ms32time += overflowIncrement; + setupTimers(); + } //Checkpoint - if (TIMER3->IF & TIMER_IF_CC1){ - + if ((TIMER3->IEN & TIMER_IEN_CC1) && (TIMER3->IF & TIMER_IF_CC1)){ TIMER3->IFC = TIMER_IFC_CC1; - long long diffs = ms32chkp[1] - ms32time; - if (diffs == 0|| (diffs==1 && (TIMER3->IF & TIMER_IF_OF)) ){ - TIMER3->IEN &= ~TIMER_IEN_CC1; + if (static_cast<unsigned short>(TIMER3->CNT) >= static_cast<unsigned short>(TIMER3->CC[1].CCV) + 1){ + // 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 TIMER1->IFC = TIMER_IFC_CC1; TIMER1->IEN |= TIMER_IEN_CC1; if (TIMER1->CNT >= TIMER1->CC[1].CCV){ - callScheduler(); //WHat if CCV=0xFFFF + // If TIM1 matches by the time it is being enabled, call the scheduler right away + TIMER1->IFC = TIMER_IFC_CC1; + callScheduler(); } } - } - //rollover - if (TIMER3->IF & TIMER_IF_OF){ - TIMER3->IFC = TIMER_IFC_OF; - ms32time += overflowIncrement; + } + + //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(); + } + } } } void __attribute__((used)) cstirqhnd1(){ - if (TIMER1->IF & TIMER_IF_CC1){ + if ((TIMER1->IEN & TIMER_IEN_CC1) && (TIMER1->IF & TIMER_IF_CC1)){ + TIMER1->IFC = TIMER_IFC_CC1; + // Should happen if and only if most significant 48 bits have been matched callScheduler(); } + + //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(); + } } HighResolutionTimerBase& HighResolutionTimerBase::instance(){ @@ -308,9 +237,9 @@ HighResolutionTimerBase::HighResolutionTimerBase() { TIMER3->CTRL &= ~TIMER_CTRL_SYNC; } -Thread* HighResolutionTimerBase::tWaitingGPIO=nullptr; - -HighResolutionTimerBase::~HighResolutionTimerBase() {} +HighResolutionTimerBase::~HighResolutionTimerBase() { + delete tc; +} long long HighResolutionTimerBase::IRQgetCurrentTick(){ return IRQgetTick(); @@ -343,9 +272,12 @@ void HighResolutionTimerBase::setCCInterrupt2Tim1(bool enable){ TIMER1->IEN&=~TIMER_IEN_CC2; } -// In this function I prepare the timer, but i don't enable the timer. +// In this function I prepare the timer, but i don't enable the timer. +// Set true to get the input mode: wait for the raising of the pin and timestamp the time in which occurs +// Set false to get the output mode: When the time set is reached, raise the pin! void HighResolutionTimerBase::setModeGPIOTimer(bool input){ if(input){ + //Connect TIMER1->CC2 to PIN PE12, meaning GPIO10 on wandstem TIMER1->ROUTE=TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC1; //Configuro la modalità input @@ -353,7 +285,7 @@ void HighResolutionTimerBase::setModeGPIOTimer(bool input){ 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 + //Config PRS: Timer3 has to be a consumer, Timer1 a 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; @@ -416,16 +348,16 @@ bool HighResolutionTimerBase::IRQsetNextInterrupt1(long long tick){ }else{ // Apply the new interrupt on to the timer channels TIMER1->CC[1].CCV = static_cast<unsigned int>(tick & 0xFFFF); - TIMER3->CC[1].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); + TIMER3->CC[1].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16)-1; ms32chkp[1] = tick & upperMask; - setupTimers(curTick, tick); + setupTimers(); return true; } } bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ ms32chkp[2] = tick & upperMask; - TIMER3->CC[2].CCV = static_cast<unsigned int>((tick & 0xFFFF0000)>>16); + 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 @@ -434,8 +366,7 @@ bool HighResolutionTimerBase::IRQsetNextInterrupt2(long long tick){ */ if(IRQgetCurrentTick() >= IRQgetSetTimeCCV2()) { - NVIC_SetPendingIRQ(TIMER3_IRQn); - // TIMER3->IFS=TIMER_IFS_CC2; ??? + //TIMER3->IFS=TIMER_IFS_CC2; lateIrq=true; return false; } 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 d55229207c0de2c71cad193cb5d71d17e5d67ee1..aa9e7690f26391bdb5afdff9a6b57a38f7873f62 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 @@ -20,7 +20,6 @@ namespace miosix { class HighResolutionTimerBase { public: - static Thread *tWaitingGPIO; static HighResolutionTimerBase& instance(); diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index ce0bcf4cf6e0d1e5dc41fb1e3241551947140a1d..2470bdb26214796a21bdc7681a7da0ff87c6b0ce 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -2110,11 +2110,11 @@ else ifeq ($(ARCH),cortexM3_efm32gg) $(BOARD_INC)/interfaces-impl/bsp.cpp \ $(BOARD_INC)/interfaces-impl/spi.cpp \ $(BOARD_INC)/interfaces-impl/power_manager.cpp \ + $(BOARD_INC)/interfaces-impl/high_resolution_timer_base.cpp \ $(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/high_resolution_timer_base.cpp + $(BOARD_INC)/interfaces-impl/cstimer.cpp ## Add a #define to allow querying board name CFLAGS_BASE += -DEFM32GG332F1024 -D_BOARD_WANDSTEM