From 36e6b6e34d651dcdb621672b7a6d029db1208bec Mon Sep 17 00:00:00 2001 From: sasan_golchin <ahmad.golchin@mail.polimi.it> Date: Sun, 13 Dec 2015 00:21:56 +0100 Subject: [PATCH] IRQportableStartKernel splitted It is ensured that the miosix::kernel_started flag is false during the execution of IRQportableStartKernel. Upon return, miosix::kernel_started is set to be true and IRQportableFinishKernelStartup is called immediately. A motivation for this kind of flow could be that it allows running of general purpose driver classes that would be ran either before or after start of the kernel. Probably these drivers may need to disable interrupts using InterruptDisableLock in the case that they are initialized after kernel's startup, while using InterruptDisableLock is error-prone when the kernel_started flag is true and the kernel is not fully started yet and the driver is started within IRQportableStartKernel. Signed-off-by: Sasan Golchin <ahmad.golchin@mail.polimi.it> Signed-off-by: Terraneo Federico <fede.tft@miosix.org> --- .../common/interfaces-impl/portability.cpp | 11 +++++---- miosix/interfaces/portability.h | 23 ++++++++++++++++++- miosix/kernel/kernel.cpp | 11 +++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp index c9631866..1f4cc55f 100644 --- a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp +++ b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp @@ -23,7 +23,7 @@ * * * You should have received a copy of the GNU General Public License * * along with this program; if not, see <http://www.gnu.org/licenses/> * - ***************************************************************************/ + ***************************************************************************/ //Miosix kernel #include "interfaces/portability.h" @@ -305,22 +305,23 @@ void IRQportableStartKernel() 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) SysTick->LOAD=SystemCoreClock/miosix::TICK_FREQ; - //Start SysTick, set to generate interrupts SysTick->CTRL=SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; - #ifdef WITH_PROCESSES miosix::IRQenableMPUatBoot(); #endif //WITH_PROCESSES #ifdef SCHED_TYPE_CONTROL_BASED AuxiliaryTimer::IRQinit(); #endif //SCHED_TYPE_CONTROL_BASED - + //create a temporary space to save current registers. This data is useless //since there's no way to stop the sheduler, but we need to save it anyway. unsigned int s_ctxsave[miosix::CTXSAVE_SIZE]; ctxsave=s_ctxsave;//make global ctxsave point to it - //Note, we can't use enableInterrupts() now since the call is not mathced +} + +void IRQportableFinishKernelStartup(){ + //Note, we can't use enableInterrupts() now since the call is not mathced //by a call to disableInterrupts() __enable_fault_irq(); __enable_irq(); diff --git a/miosix/interfaces/portability.h b/miosix/interfaces/portability.h index 45bac3be..08d7663f 100644 --- a/miosix/interfaces/portability.h +++ b/miosix/interfaces/portability.h @@ -237,10 +237,31 @@ void IRQstackOverflowCheck(); /** * \internal * Called by miosix::start_kernel to handle the architecture-specific part of - * initialization. It is used by the kernel, and should not be used by end users + * initialization. It is used by the kernel, and should not be used by end users. + * It is ensured that the miosix::kernel_started flag false during the execution + * of this function. Upon return, miosix::kernel_started is set to be true and + * IRQportableFinishKernelStartup is called immediately. + * A motivation for this flow could be that it allows running of general purpose + * driver classes that would be ran either before or after start of the kernel. + * Probably these drivers may need to disable interrupts using InterruptDisableLock + * in the case that they are initialized after kernel's startup, while using + * InterruptDisableLock is error-prone when the kernel_started flag is true and + * the kernel is not fully started yet. */ void IRQportableStartKernel(); +/** + * \internal + * This function is called right after IRQportableStartKernel by + * miosix::start_kernel. The miosix::kernel_started is set to true at this + * stage. + * A typical behaviour that's expected is to : + * 1) Enable falut IRQ + * 2) Enable IRQs + * 3) miosix::Thread::yield(); + */ +void IRQportableFinishKernelStartup(); + /** * \internal * This function disables interrupts. diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp index 90a5ae67..ba5dd940 100644 --- a/miosix/kernel/kernel.cpp +++ b/miosix/kernel/kernel.cpp @@ -72,7 +72,7 @@ volatile int kernel_running=0; ///\internal true if a tick occurs while the kernel is paused volatile bool tick_skew=false; -static bool kernel_started=false;///<\internal becomes true after startKernel. +bool kernel_started=false;///<\internal becomes true after startKernel. /// This is used by disableInterrupts() and enableInterrupts() to allow nested /// calls to these functions. @@ -198,10 +198,11 @@ void startKernel() setCReentrancyCallback(Thread::getCReent); // Now kernel is started - kernel_started=true; - + // Dispatch the task to the architecture-specific function miosix_private::IRQportableStartKernel(); + kernel_started=true; + miosix_private::IRQportableFinishKernelStartup(); } bool isKernelRunning() @@ -341,7 +342,7 @@ bool Thread::testTerminate() //Just reading, no need for critical section return const_cast<Thread*>(cur)->flags.isDeleting(); } - + void Thread::sleep(unsigned int ms) { if(ms==0) return; @@ -452,7 +453,7 @@ void Thread::wait() Thread::yield(); //Return here after wakeup } - + void Thread::wakeup() { //pausing the kernel is not enough because of IRQwait and IRQwakeup -- GitLab