void nrf_pwr_mgmt_run(void) { #if NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED /* * Clear FPU exceptions. * Without this step, the FPU interrupt is marked as pending, * preventing system from sleeping. */ uint32_t fpscr = __get_FPSCR(); __set_FPSCR(fpscr & ~0x9Fu); __DMB(); NVIC_ClearPendingIRQ(FPU_IRQn); // Assert if a critical FPU exception is signaled. ASSERT((fpscr & 0x03) == 0); #endif // NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED SLEEP_LOCK(); #if NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED uint32_t sleep_start; uint32_t sleep_end; uint32_t sleep_duration; sleep_start = app_timer_cnt_get(); #endif // NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED DEBUG_PIN_SET(); // Wait for an event. #ifdef SOFTDEVICE_PRESENT ret_code_t ret_code = sd_app_evt_wait(); if (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED) { __WFE(); __SEV(); __WFE(); } else { APP_ERROR_CHECK(ret_code); } #else __WFE(); __SEV(); __WFE(); #endif // SOFTDEVICE_PRESENT DEBUG_PIN_CLEAR(); #if NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED sleep_end = app_timer_cnt_get(); UNUSED_VARIABLE(app_timer_cnt_diff_compute(sleep_end, sleep_start, &sleep_duration)); m_ticks_sleeping += sleep_duration; #endif // NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED SLEEP_RELEASE(); }
/** \brief Test case: TC_CoreFunc_BASEPRI \details - Check if __get_FPSCR and __set_FPSCR intrinsics can be used */ void TC_CoreFunc_FPSCR(void) { uint32_t fpscr = __get_FPSCR(); __ISB(); __DSB(); __set_FPSCR(~fpscr); __ISB(); __DSB(); uint32_t result = __get_FPSCR(); __set_FPSCR(fpscr); #if (defined (__FPU_USED ) && (__FPU_USED == 1U)) ASSERT_TRUE(result != fpscr); #else (void)result; #endif }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) { /* The port_extctx structure is pointed by the PSP register.*/ struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsRescRequiredI()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ (void) __get_FPSCR(); #endif } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } #if CORTEX_USE_FPU { uint32_t fpccr; /* Saving the special register SCB_FPCCR into the reserved offset of the Cortex-M4 exception frame.*/ (ctxp + 1)->fpccr = (regarm_t)(fpccr = FPU->FPCCR); /* Now the FPCCR is modified in order to not restore the FPU status from the artificial return context.*/ FPU->FPCCR = fpccr | FPU_FPCCR_LSPACT_Msk; } #endif /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB_ICSR & ICSR_RETTOBASE) != 0) { struct extctx *ctxp; /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; __set_PSP((unsigned long)ctxp); ctxp->xpsr = (regarm_t)0x01000000; /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; #if CORTEX_USE_FPU /* Triggering a lazy FPU state save.*/ (void)__get_FPSCR(); #endif } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } #if CORTEX_USE_FPU { uint32_t fpccr; /* Saving the special register SCB_FPCCR into the reserved offset of the Cortex-M4 exception frame.*/ (ctxp + 1)->fpccr = (regarm_t)(fpccr = SCB_FPCCR); /* Now the FPCCR is modified in order to not restore the FPU status from the artificial return context.*/ SCB_FPCCR = fpccr | FPCCR_LSPACT; } #endif /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0) { struct port_extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ (void) __get_FPSCR(); #endif /* The port_extctx structure is pointed by the PSP register.*/ ctxp = (struct port_extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; /* Setting up a fake XPSR register value.*/ ctxp->xpsr = (regarm_t)0x01000000; #if CORTEX_USE_FPU ctxp->fpscr = (regarm_t)FPU->FPDSCR; #endif /* Writing back the modified PSP value.*/ __set_PSP((uint32_t)ctxp); /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }
/** * @brief Exception exit redirection to _port_switch_from_isr(). */ void _port_irq_epilogue(void) { port_lock_from_isr(); if ((SCB_ICSR & ICSR_RETTOBASE) != 0) { struct extctx *ctxp; #if CORTEX_USE_FPU /* Enforcing a lazy FPU state save. Note, it goes in the original context because the FPCAR register has not been modified.*/ (void)__get_FPSCR(); #endif /* Current PSP value.*/ ctxp = (struct extctx *)__get_PSP(); /* Adding an artificial exception return context, there is no need to populate it fully.*/ ctxp--; ctxp->xpsr = (regarm_t)0x01000000; #if CORTEX_USE_FPU ctxp->fpscr = (regarm_t)SCB_FPDSCR; #endif __set_PSP((unsigned long)ctxp); /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { /* Preemption is required we need to enforce a context switch.*/ ctxp->pc = (regarm_t)_port_switch_from_isr; } else { /* Preemption not required, we just need to exit the exception atomically.*/ ctxp->pc = (regarm_t)_port_exit_from_isr; } /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); }