Exemplo n.º 1
1
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();
}
Exemplo n.º 2
0
/**
\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
}
Exemplo n.º 3
0
/**
 * @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();
}
Exemplo n.º 4
0
/**
 * @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();
}
Exemplo n.º 5
0
/**
 * @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();
}
Exemplo n.º 6
0
/**
 * @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();
}