From f5fcbad323f3cb21647662d41f2eaf0e0f1c24fe Mon Sep 17 00:00:00 2001 From: Sasan Golchin <ahmad.golchin@mail.polimi.it> Date: Tue, 15 Dec 2015 08:48:36 +0100 Subject: [PATCH] Context Switch Timer Interface A generic interface miosix::ContextSwitchTimer has been added to the kernel that can play the role of either periodic/aperiodic system timer. Like other kernel interfaces, there should be provided a proper implementation for cstimer. Currently the only available implementation is done for cortexM4_stm32f which is based on TIM2 timer. Although the implementation is an aperiodic timer, it is set to act like a periodic timer with T=1ms. Signed-off-by: Sasan Golchin <ahmad.golchin@mail.polimi.it> Signed-off-by: Terraneo Federico <fede.tft@miosix.org> --- Makefile | 2 +- main.cpp | 47 ++++-------- .../common/interfaces-impl/cstimer.cpp | 71 +++++++++++-------- .../common/interfaces-impl/portability.cpp | 8 +++ miosix/config/Makefile.inc | 1 + cstimer.h => miosix/interfaces/cstimer.h | 2 +- 6 files changed, 69 insertions(+), 62 deletions(-) rename cstimer.cpp => miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp (63%) rename cstimer.h => miosix/interfaces/cstimer.h (89%) diff --git a/Makefile b/Makefile index 69ace418..1f279089 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ SUBDIRS := $(KPATH) ## List here your source files (both .s, .c and .cpp) ## SRC := \ -main.cpp cstimer.cpp +main.cpp ## ## List here additional static libraries with relative path diff --git a/main.cpp b/main.cpp index 5e20d2f8..69d1f944 100644 --- a/main.cpp +++ b/main.cpp @@ -1,42 +1,25 @@ -#include <cstdio> -#include <cmath> +#include <stdio.h> +#include <pthread.h> #include "miosix.h" #include "kernel/logging.h" -#include "e20/e20.h" -#include "cstimer.h" +#include "interfaces/cstimer.h" using namespace std; using namespace miosix; -void basicTests(){ - ContextSwitchTimer t = ContextSwitchTimer::instance(); - long long chkpoint = 0xFFFFFFFFll+1899760; - //chkpoint = 0xFFFFFFFFll-20; //Test Case: CHKPNT right really before rollover -> OK - //chkpoint = 0xFFFFFFFFll-2000; //Test Case: CHKPNT right before rollover -> OK - //chkpoint = 0xFFFFFFFFll+2000; //Test Case: CHKPNT right afrer rollover -> OK - //chkpoint = 0xFFFFFFFFll+20; //Test Case: CHKPNT right really afrer rollover -> OK - t.setNextInterrupt(chkpoint); //checkpoint near the rollover - while(1){ - Thread::sleep(10000); - printf("-CNT: %llu , NEXT CHKPNT: %llu\n",t.getCurrentTick(),t.getNextInterrupt()); - - } -} -void rightAfterCurrentTime(){ - ContextSwitchTimer t = ContextSwitchTimer::instance(); - - while(1){ - Thread::sleep(10000); - //checkpoint near the current tick - //A chkpoint with dist. less than 80 is not set in time => lost! - t.setNextInterrupt(t.getCurrentTick()+80); - printf("-CNT: %llu , NEXT CHKPNT: %llu\n",t.getCurrentTick(),t.getNextInterrupt()); - +static void t1Task(void* p){ + while (true){ + IRQbootlog("1\r\n"); + Thread::sleep(1000); } } int main(){ - iprintf("Context Switch Timer Driver Test1 (80)\n"); - - //basicTests(); //passed - rightAfterCurrentTime(); + //ContextSwitchTimer::instance(); + Thread::setPriority(1); + printf("Context Switch Timer ....T=1ms\n"); + Thread *p=Thread::create(t1Task,512,1,NULL); + while (true){ + IRQbootlog("0\r\n"); + Thread::sleep(250); + } } diff --git a/cstimer.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp similarity index 63% rename from cstimer.cpp rename to miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp index 600f84f6..e2c2f80d 100644 --- a/cstimer.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/cstimer.cpp @@ -1,5 +1,6 @@ #include "miosix.h" -#include "cstimer.h" +#include "interfaces/cstimer.h" +#include "interfaces/portability.h" #include "kernel/logging.h" #include <cstdlib> using namespace miosix; @@ -7,7 +8,14 @@ using namespace miosix; static long long cst_ms32time = 0; //most significant 32 bits of counter static long long cst_ms32chkp = 0; //most significant 32 bits of check point static volatile bool cst_chkProcessed; +static long long cst_prevChk; + +#define CST_QUANTOM 84000 #define CST_ROLLOVER_INT (TIM2->SR & TIM_SR_UIF) && (TIM2->SR & TIM_SR_CC2IF) + +namespace miosix_private{ + void ISR_preempt(); +} ContextSwitchTimer& ContextSwitchTimer::instance() { static ContextSwitchTimer _instance; return _instance; @@ -18,7 +26,7 @@ ContextSwitchTimer::ContextSwitchTimer() { * TIM2 Source Clock (from APB1) Enable */ { - FastInterruptDisableLock idl; + InterruptDisableLock idl; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; RCC_SYNC(); } @@ -33,10 +41,10 @@ ContextSwitchTimer::ContextSwitchTimer() { TIM2->CCR3=0; TIM2->CCR4=0; TIM2->DIER=TIM_DIER_UIE | TIM_DIER_CC1IE; - NVIC_SetPriority(TIM2_IRQn,1); //TO-DO: WHICH IRQ Priority to use? 0? + NVIC_SetPriority(TIM2_IRQn,3); NVIC_EnableIRQ(TIM2_IRQn); /* - * Configure channel 1 as: + * Configure channel 1 as: * Output channel (CC1S=0) * No preload(OC1PE=0), hence TIM2_CCR1 can be written at anytime * No effect on the output signal on match (OC1M = 0) @@ -44,24 +52,21 @@ ContextSwitchTimer::ContextSwitchTimer() { TIM2->CCMR1 = 0; TIM2->CCR1 = 0; /* - * TIM2 Operation Frequency Configuration + * TIM2 Operation Frequency Configuration: Max Freq. and longest period */ - uint32_t pcsfreq = SystemCoreClock; - uint32_t apb1_div = (RCC->CFGR & RCC_CFGR_PPRE1)>>10; - //True assumption: AHB frequency is not divided :D - if (apb1_div & 0x4) //APB1 Divider is active - pcsfreq /= ((apb1_div & 0x3)+1)<<1; - TIM2->PSC = 0; TIM2->ARR = 0xFFFFFFFF; //printf("PSCFreq: %lu PCS: %lu ARR: %lu CCR1: %lu SR: %lu CNT: %lu\n",pcsfreq,TIM2->PSC,TIM2->ARR,TIM2->CCR1,TIM2->SR,TIM2->CNT); /* * Other initializations */ + // Set the first checkpoint interrupt + cst_prevChk = CST_QUANTOM; + setNextInterrupt(cst_prevChk); // Enable TIM2 Counter + cst_ms32time = 0; TIM2->EGR = TIM_EGR_UG; //To enforce the timer to apply PSC (and other non-immediate settings) TIM2->CR1 |= TIM_CR1_CEN; - cst_ms32time = 0; } long long ContextSwitchTimer::getCurrentTick() { @@ -70,7 +75,7 @@ long long ContextSwitchTimer::getCurrentTick() { //If overflow occurs while interrupts disabled /* * counter should be checked before rollover interrupt flag - * + * */ uint32_t counter = TIM2->CNT; if (CST_ROLLOVER_INT && counter < 0x80000000){ @@ -87,6 +92,7 @@ void ContextSwitchTimer::setNextInterrupt(long long tick) { cst_ms32chkp = tick & 0xFFFFFFFF00000000; TIM2->CCR1 = (uint32_t)(tick & 0xFFFFFFFF); cst_chkProcessed = false; + //if (getCurrentTick() > getNextInterrupt()) IRQbootlog("TIM2 - CHECK POINT SET IN THE PAST\r\n"); } long long ContextSwitchTimer::getNextInterrupt(){ @@ -94,26 +100,35 @@ long long ContextSwitchTimer::getNextInterrupt(){ } void __attribute__((used)) cstirqhnd(){ - if ((TIM2->SR & TIM_SR_CC1IF) && (cst_ms32time==cst_ms32chkp)){ + //IRQbootlog("TIM2-IRQ\r\n"); + if (TIM2->SR & TIM_SR_CC1IF){ //Checkpoint met + //The interrupt flag must be cleared unconditionally whether we are in the + //correct epoch or not otherwise the interrupt will happen even in unrelated + //epochs and slowing down the whole system. TIM2->SR = ~TIM_SR_CC1IF; - IRQbootlog(" (CHK POINT) \r\n"); - cst_chkProcessed = true; - + if(cst_ms32time==cst_ms32chkp){ + //Set next checkpoint interrupt + ////cst_prevChk += CST_QUANTOM; + ////ContextSwitchTimer::instance().setNextInterrupt(cst_prevChk); + ContextSwitchTimer::instance().setNextInterrupt( + ContextSwitchTimer::instance().getCurrentTick() + CST_QUANTOM); + cst_chkProcessed = true; + //Call preempt routine + miosix_private::ISR_preempt(); + } + } - if (CST_ROLLOVER_INT){ - //Rollover (Update and CC2 that is always set on zero) - //On the initial update SR = UIF (ONLY) + //Rollover (Update and CC2 that is always set on zero) + //On the initial update SR = UIF (ONLY) + if (TIM2->SR & TIM_SR_UIF){ TIM2->SR = ~TIM_SR_UIF; //w0 clear - IRQbootlog(" (ROLLOVER) \r\n"); - cst_ms32time += 0x100000000; - + if (TIM2->SR & TIM_SR_CC2IF){ + TIM2->SR = ~TIM_SR_CC2IF; + //IRQbootlog(" (ROLLOVER) \r\n"); + cst_ms32time += 0x100000000; + } } - /* - if (!cst_chkProcessed && cst_ms32chkp < (cst_ms32time | TIM2->CNT) && cst_ms32time==cst_ms32chkp){ - IRQbootlog(" (CHK POINT) \r\n"); - cst_chkProcessed = true; - }*/ } void __attribute__((naked)) TIM2_IRQHandler(){ diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp index 1f4cc55f..9f1884b8 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp @@ -38,6 +38,8 @@ #include <cstdio> #include <cstring> #include <cassert> +#include "interfaces/cstimer.h" +//#define CNTX_SWITCH_USE_SYSTICK /** * \internal @@ -49,10 +51,12 @@ void SysTick_Handler() __attribute__((naked)); void SysTick_Handler() { +#ifdef CNTX_SWITCH_USE_SYSTICK saveContext(); //Call ISR_preempt(). Name is a C++ mangled name. asm volatile("bl _ZN14miosix_private11ISR_preemptEv"); restoreContext(); +#endif } /** @@ -304,9 +308,13 @@ void IRQportableStartKernel() NVIC_SetPriority(SVCall_IRQn,3);//High priority for SVC (Max=0, min=15) NVIC_SetPriority(SysTick_IRQn,3);//High priority for SysTick (Max=0, min=15) NVIC_SetPriority(MemoryManagement_IRQn,2);//Higher priority for MemoryManagement (Max=0, min=15) +#ifdef CNTX_SWITCH_USE_SYSTICK SysTick->LOAD=SystemCoreClock/miosix::TICK_FREQ; SysTick->CTRL=SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; +#else //USE ContextSwitchTimer class (TIM2) + miosix::ContextSwitchTimer::instance(); +#endif #ifdef WITH_PROCESSES miosix::IRQenableMPUatBoot(); #endif //WITH_PROCESSES diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc index 62737f90..39452470 100644 --- a/miosix/config/Makefile.inc +++ b/miosix/config/Makefile.inc @@ -1737,6 +1737,7 @@ else ifeq ($(ARCH),cortexM4_stm32f4) $(ARCH_INC)/interfaces-impl/portability.cpp \ $(ARCH_INC)/interfaces-impl/delays.cpp \ $(ARCH_INC)/interfaces-impl/gpio_impl.cpp \ + $(ARCH_INC)/interfaces-impl/cstimer.cpp \ arch/common/drivers/sd_stm32f2_f4.cpp \ arch/common/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c diff --git a/cstimer.h b/miosix/interfaces/cstimer.h similarity index 89% rename from cstimer.h rename to miosix/interfaces/cstimer.h index 8b9491cb..3da5d860 100644 --- a/cstimer.h +++ b/miosix/interfaces/cstimer.h @@ -9,7 +9,7 @@ namespace miosix{ long long getNextInterrupt(); /** * Could be call both when the interrupts are enabled/disabled! - * @return + * @return the current tick count of the timer */ long long getCurrentTick(); virtual ~ContextSwitchTimer(); -- GitLab