diff --git a/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp b/miosix/arch/cortexM4_stm32f4/common/interfaces-impl/portability.cpp index c9631866ef84718b143678e886ffd595d2661126..1f4cc55fc4720918d668199bfeb5ed215b7c1c95 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 45bac3be78c1c41e7468382a798bb2d113a6e8d1..08d7663f6acd5c4366decf9031cef8cb9544b15e 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 90a5ae67a597d32da1b043aaf1166ad9c47f9366..ba5dd9403477843b9837b6d9f501cc32e02cd8dd 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