Exemplo n.º 1
0
STATIC bool setup_timer_hibernate_wake (void) {
    uint64_t t_match, t_curr;
    int64_t t_remaining;

    // get the time remaining for the RTC timer to expire
    t_match = MAP_PRCMSlowClkCtrMatchGet();
    t_curr  = MAP_PRCMSlowClkCtrGet();

    // get the time remaining in terms of slow clocks
    t_remaining = (t_match - t_curr);
    if (t_remaining > WAKEUP_TIME_HIB) {
        // subtract the time it takes for wakeup from hibernate
        t_remaining -= WAKEUP_TIME_HIB;
        // setup the LPDS wake time
        MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining);
        // enable the wake source
        MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
        return true;
    }


    // disable the timer as wake source
    MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR);

    uint32_t f_seconds;
    uint16_t f_mseconds;
    // setup a timer interrupt immediately
    pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
    MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
    // LPDS wake by timer was not possible, force an interrupt in active mode instead
    MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);

    return false;
}
Exemplo n.º 2
0
/* Timer based wakeup from S3 (LPDS) */
static i32 check_n_setup_S3_wakeup_from_timer()
{
        u64 scc_match, scc_curr, scc_remaining;

        /* Check if there is an alarm set */
        if(cc_rtc_has_alarm()) {
                /* Get the time remaining for the RTC timer to expire */
                scc_match = MAP_PRCMSlowClkCtrMatchGet();
                scc_curr = MAP_PRCMSlowClkCtrGet();
                
                if(scc_match > scc_curr) {
                        /* Get the time remaining in terms of slow clocks */
                        scc_remaining = (scc_match - scc_curr);
                        if(scc_remaining > WAKEUP_TIME_LPDS) {
                                /* Subtract the time it takes for wakeup 
                                   from S3 (LPDS) */
                                scc_remaining -= WAKEUP_TIME_LPDS;
                                scc_remaining = (scc_remaining > 0xFFFFFFFF)?
                                        0xFFFFFFFF: scc_remaining;
                                /* Setup the LPDS wake time */
                                MAP_PRCMLPDSIntervalSet(
                                        (u32)scc_remaining);
                                /* Enable the wake source to be timer */
                                MAP_PRCMLPDSWakeupSourceEnable(
                                        PRCM_LPDS_TIMER);
                        } else {
                                /* Cannot enter LPDS */
                                return ERR_TIMER_TO_WAKE;
                        }
                } else {
                       return ERR_TIMER_TO_WAKE;
                }
        } else {
                /* Disable timer as the wake source  */
                MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
                return -1;
        }

        return 0;
}
Exemplo n.º 3
0
/* Timer based wakeup from S4 (HIB) */
static i32 check_n_setup_S4_wakeup_from_timer()
{
        u64 scc_match, scc_curr, scc_remaining;

        /* Check if there is an alarm set */
        if(cc_rtc_has_alarm()) {
                /* Get the time remaining for the RTC timer to expire */
                scc_match = MAP_PRCMSlowClkCtrMatchGet();
                scc_curr = MAP_PRCMSlowClkCtrGet();
                
                if(scc_match > scc_curr) {
                        /* Get the time remaining in terms of slow clocks */
                        scc_remaining = (scc_match - scc_curr);
                        if(scc_remaining > WAKEUP_TIME_HIB) {
                                /* Subtract the time it takes for wakeup 
                                   from S4 (HIB) */
                                scc_remaining -= WAKEUP_TIME_HIB;
                                /* Setup the HIB wake time */
                                MAP_PRCMHibernateIntervalSet(scc_remaining);
                                /* Enable the wake source to be RTC */
                                MAP_PRCMHibernateWakeupSourceEnable(
                                        PRCM_HIB_SLOW_CLK_CTR);
                        } else {
                                /* Cannot enter HIB */
                                return ERR_TIMER_TO_WAKE;
                        }
                } else {
                        return -1;
                }
        } else {
                /* Disable Timer as wake source */
                MAP_PRCMHibernateWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR);
                return -1;
        }

        return 0;
}
/*
 *  ======== PowerCC3200_sleepPolicy ========
 */
void PowerCC3200_sleepPolicy()
{
    bool returnFromSleep = FALSE;
    uint32_t constraintMask;
    uint32_t ticks;
    uint64_t time;
    uint64_t match;
    uint64_t curr;
    uint64_t remain;
    uint32_t taskKey;
    uint32_t swiKey;

    /* disable interrupts */
    CPUcpsid();

    /* disable Swi and Task scheduling */
    swiKey = Swi_disable();
    taskKey = Task_disable();

    /* query the declared constraints */
    constraintMask = Power_getConstraintMask();

    /*
     *  Do not go into LPDS if not allowed into DEEPSLEEP.
     *  Check to see if we can go into LPDS (lowest level sleep).
     *  If not allowed, then attempt to go into DEEPSLEEP.
     *  If not allowed in DEEPSLEEP then just SLEEP.
     */

     /* check if we are allowed to go to LPDS */
    if ((constraintMask &
        ((1 << PowerCC3200_DISALLOW_LPDS) |
        (1 << PowerCC3200_DISALLOW_DEEPSLEEP))) == 0) {
        /*
         * Check how many ticks until the next scheduled wakeup.  A value of
         * zero indicates a wakeup will occur as the current Clock tick period
         * expires; a very large value indicates a very large number of Clock
         * tick periods will occur before the next scheduled wakeup.
         */
        /* Get the time remaining for the RTC timer to expire */
        ticks = Clock_getTicksUntilInterrupt();

        /* convert ticks to microseconds */
        time = ticks * Clock_tickPeriod;

        /* check if can go to LPDS */
        if (time > Power_getTransitionLatency(PowerCC3200_LPDS, Power_TOTAL)) {
            /* get the current and match values for RTC */
            match = MAP_PRCMSlowClkCtrMatchGet();
            curr = MAP_PRCMSlowClkCtrGet();
            remain = match - curr -
                (((uint64_t)PowerCC3200_TOTALTIMELPDS * 32768) / 1000000);

            /* set the LPDS wakeup time interval */
            MAP_PRCMLPDSIntervalSet(remain);

            /* enable the wake source to be timer */
            MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);

            /* go to LPDS mode */
            Power_sleep(PowerCC3200_LPDS);

            /* set 'returnFromSleep' to TRUE*/
            returnFromSleep = TRUE;
        }
    }

    /* check if we are allowed to go to DEEPSLEEP */
    if ((constraintMask & (1 << PowerCC3200_DISALLOW_DEEPSLEEP) == 0) &&
        (!returnFromSleep)) {
        /*
         * Check how many ticks until the next scheduled wakeup.  A value of
         * zero indicates a wakeup will occur as the current Clock tick period
         * expires; a very large value indicates a very large number of Clock
         * tick periods will occur before the next scheduled wakeup.
         */
        ticks = Clock_getTicksUntilInterrupt();

        /* convert ticks to microseconds */
        time = ticks * Clock_tickPeriod;

        /* check if can go to DEEPSLEEP */
        if (time > Power_getTransitionLatency(PowerCC3200_DEEPSLEEP,
            Power_TOTAL)) {
            /* schedule the wakeup event */
            ticks -= PowerCC3200_RESUMETIMEDEEPSLEEP / Clock_tickPeriod;
            Clock_setTimeout(Clock_handle(&clockObj), ticks);
            Clock_start(Clock_handle(&clockObj));

            /* go to DEEPSLEEP mode */
            Power_sleep(PowerCC3200_DEEPSLEEP);
            Clock_stop(Clock_handle(&clockObj));

            /* set 'returnFromSleep' to TRUE so we don't go to sleep (below) */
            returnFromSleep = TRUE;
        }
    }

    /* re-enable interrupts */
    CPUcpsie();

    /* restore Swi scheduling */
    Swi_restore(swiKey);

    /* restore Task scheduling */
    Task_restore(taskKey);

    /* sleep only if we are not returning from one of the sleep modes above */
    if (!(returnFromSleep)) {
        MAP_PRCMSleepEnter();
    }
}