Example #1
0
/*
 *  ======== Seconds_get ========
 */
UInt32 Seconds_get(Void)
{
    UInt32 curSeconds;
    UInt   key;

    /*
     *  Disable scheduling.  We use Swi_disable() instead of
     *  Hwi_disable() because of the large times for accessing
     *  these registers.
     */
    key = Swi_disable();

    /*
     *  The CC3200 timer has a frequency of 32768 (2 ** 15), so
     *  to get seconds, drop the lower 15 bits.
     */
    curSeconds = (UInt32)(Seconds_getCount() >> 15);

    curSeconds = curSeconds - Seconds_module->refSeconds +
        Seconds_module->setSeconds;

    /* Re-enable scheduling */
    Swi_restore(key);

    return (curSeconds);
}
Example #2
0
/*
 *  ======== Power_updateConstraints ========
 */
Void Power_updateConstraints(Power_Constraint type, UArg value)
{
    UInt key;

    /* stop threading */
    key = Swi_disable();

    /* update the disallowed CPU domain setpoints mask(?) */
    if (type == Power_DISALLOWED_CPU_SETPOINT_MASK) {
        Power_module->disallowedSetpointsCPU |= (UInt) value;
    }

    /* or, update disallowed PER domain setpoints mask(?) */
    else if (type == Power_DISALLOWED_PER_SETPOINT_MASK) {
        Power_module->disallowedSetpointsPER |= (UInt) value;
    }

    /* or, update disallowed sleep modes mask(?) */
    else if (type == Power_DISALLOWEDSLEEPSTATE_MASK) {
        Power_module->disallowedSleepModes |= (UInt) value;
    }

    /* resume threading */
    Swi_restore(key);
}
Example #3
0
/*
 *  ======== tsk0Fxn =======
 */
Void tsk0Fxn(UArg arg0, UArg arg1)
{
    UInt key;

    /* wait for swis to be posted from Clock function */
    Semaphore_pend(sem0, BIOS_WAIT_FOREVER);

    System_printf("Running tsk0Fxn\n");
         
    key = Swi_disable();        /* swis are disabled */
    Swi_inc(swi0);              /* swi0 trigger = 1 */
    Swi_inc(swi0);              /* swi0 trigger = 2 */
    Swi_restore(key);           /* swi0 runs */

    Swi_or(swi1, 0x100);        /* swi1 runs with trigger = 0x111 */

    Swi_andn(swi1, 0x1);        /* swi1 trigger = 0x10 */
    Swi_andn(swi1, 0x2);        /* swi1 runs with trigger = 0x00 */
        
    Swi_dec(swi1);              /* swi1 trigger = 2 */     
    Swi_dec(swi1);              /* swi1 trigger = 1 */
    Swi_dec(swi1);              /* swi1 runs with trigger = 0 */
        
    System_printf("Calling BIOS_exit\n");
    BIOS_exit(0);
}
Example #4
0
/*
 *  ======== GateAll_leave ========
 */
Void GateAll_leave(GateAll_Object *gate, IArg key)
{
    if (key == 0) {
        gate->entered = FALSE;
        Swi_restore(gate->swiKey);
        Hwi_restore(gate->hwiKey);
    }
}
Example #5
0
/*
 *  ======== Swi_restorePri ========
 */
Void Swi_restorePri(UInt priority)
{
    UInt swiKey;

    swiKey = Swi_disable();

    Swi_module->curQ = Queue_Object_get(Swi_module->readyQ, priority);

    Swi_restore(swiKey);
}
Example #6
0
/*
 *  ======== Power_rebuildConstraint ========
 */
Void Power_rebuildConstraint(Power_Constraint type)
{
    Queue_Handle constraintsQ;
    Queue_Elem * elem;
    UInt value;
    UInt key;

    /* disable scheduling */
    key = Swi_disable();

    /* first, re-initialize the aggregate constraint */
    if (type == Power_DISALLOWED_CPU_SETPOINT_MASK) {
        Power_module->disallowedSetpointsCPU = 0;
    }
    else if (type == Power_DISALLOWED_PER_SETPOINT_MASK) {
        Power_module->disallowedSetpointsPER = 0;
    }
    else if (type == Power_DISALLOWEDSLEEPSTATE_MASK) {
        Power_module->disallowedSleepModes = 0;
    }

    constraintsQ = Power_Module_State_constraintsQ();

    if (!Queue_empty(constraintsQ)) {
        elem = Queue_head(constraintsQ);

        do {
            /* only if constraint 'type' matches... */
            if (((Power_ConstraintObj *)elem)->type == type) {

                /* get the constraint value */
                value = (UInt) ((Power_ConstraintObj *)elem)->value;

                /* update the agregate constraint */
                if (type == Power_DISALLOWED_CPU_SETPOINT_MASK) {
                    Power_module->disallowedSetpointsCPU |= value;
                }
                else if (type == Power_DISALLOWED_PER_SETPOINT_MASK) {
                    Power_module->disallowedSetpointsPER |= value;
                }
                else if (type == Power_DISALLOWEDSLEEPSTATE_MASK) {
                    Power_module->disallowedSleepModes |= value;
                 }
            }

            elem = Queue_next(elem);

        } while (elem != (Queue_Elem *) constraintsQ);
    }        

    /* re-enable scheduling */
    Swi_restore(key);
}
Example #7
0
/*
 *  ======== IpcPower_hibernateLock ========
 */
UInt IpcPower_hibernateLock()
{
    IArg hwiKey, swiKey;

    hwiKey = Hwi_disable();
    swiKey = Swi_disable();

    IpcPower_hibLock++;

    Swi_restore(swiKey);
    Hwi_restore(hwiKey);

    return (IpcPower_hibLock);
}
Example #8
0
/*
 *  ======== IpcPower_hibernateUnlock ========
 */
UInt IpcPower_hibernateUnlock()
{
    IArg hwiKey, swiKey;

    hwiKey = Hwi_disable();
    swiKey = Swi_disable();

    if (IpcPower_hibLock > 0) {
        IpcPower_hibLock--;
    }

    Swi_restore(swiKey);
    Hwi_restore(hwiKey);

    return (IpcPower_hibLock);
}
Example #9
0
/*
 *  ======== Seconds_set ========
 */
Void Seconds_set(UInt32 seconds)
{
    UInt64        curCount;
    UInt          key;

    /*
     *  Disable scheduling.  We use Swi_disable() instead of
     *  Hwi_disable() because of the large times for accessing
     *  these registers.
     */
    key = Swi_disable();

    /*
     *  Start the RTC counter the first time Seconds_set() is called, if
     *  it is not already running.
     */
    if (Seconds_module->refSeconds == 0xffffffff) {
        /*
         *  Only start the RTC if it is not already running.
         */
        if (!(HWREG(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE) & 0x1)) {
            /* Enable the timer */
            HWREG(HIB3P3_BASE + HIB3P3_O_MEM_HIB_RTC_TIMER_ENABLE) = 0x1;
        }
    }

    curCount = Seconds_getCount();

    /*
     *  The CC3200 timer has a frequency of 32768 (2 ** 15), so
     *  to get seconds, drop the lower 15 bits.
     */
    Seconds_module->refSeconds = (UInt32)(curCount >> 15);
    Seconds_module->setSeconds = seconds;

    /* Re-enable scheduling */
    Swi_restore(key);
}
Example #10
0
/*
 *  ======== Seconds_getTime ========
 */
UInt32 Seconds_getTime(Seconds_Time *ts)
{
    UInt64 curCount;
    UInt   key;

    /*
     *  Disable scheduling.  We use Swi_disable() instead of
     *  Hwi_disable() because of the large times for accessing
     *  these registers.
     */
    key = Swi_disable();

    curCount = Seconds_getCount();

    ts->secs = (UInt32)(curCount >> 15) - Seconds_module->refSeconds +
        Seconds_module->setSeconds;

    ts->nsecs = (UInt32)(1000000000 * (curCount & 0x7FFF) / 32768);

    /* Re-enable scheduling */
    Swi_restore(key);

    return (0);
}
Example #11
0
/*
 *  ======== Power_releaseDependency ========
 *  Release a dependency that has been previously declared by
 *  Power_setDependency.
 *
 */
Power_Status Power_releaseDependency(Power_Resource resourceID)
{
    Power_Status status = Power_SOK;
    PMI_Status pmi = PMI_BUSY;
    Bool callStatus;
    UInt checks = 0;
    UInt state = 0;
    UInt refCount;
    UInt key;

    /* make sure RT has been configured ON */
    if (!ti_sysbios_family_c674_Power_trackResources) {
        status = Power_ENOTSUPPORTED;
    }

    /* validate resource ID is within range of pre-defined  resources */
    else if (resourceID >= Power_RSRC_END) {
        status = Power_EOUTOFRANGE;
    }

    /* make sure this resource is 'valid' for DSP control */
    else if ((ti_sysbios_family_c674_Power_database[resourceID].flags & VALID)
        == 0) {
        status = Power_EINVALIDVALUE;
    }

    /* else, check reference count, de-activate resource */
    else {

        /* disable scheduling */
        key = Swi_disable();

        /* read reference count */
        refCount = ti_sysbios_family_c674_Power_database[resourceID].count;

        /* if reference count already zero return an error code */
        if (refCount == 0) {
            status = Power_ETOOMANYCALLS;
        }
        /* else, if dependencies remain simply decrement count */
        else if (refCount > 1) {
            ti_sysbios_family_c674_Power_database[resourceID].count = 
                refCount - 1;
        }

        /* else, one remaining dependency, and it is being released... */
        else {

            /* if resource has special handler - call it now */
            if (ti_sysbios_family_c674_Power_database[resourceID].specialHandler != NULL) {
                callStatus = (*ti_sysbios_family_c674_Power_database[resourceID].specialHandler)
                    (resourceID, Power_RELEASE);
            }
            /* else, call to PMI to deactivate the resource */
            else {

                state = ti_sysbios_family_c674_Power_database[resourceID].inactiveState;

                /* optionally assert force for the transition */
                if ((ti_sysbios_family_c674_Power_database[resourceID].flags 
                    & FORCE_MODE) != 0) {
                    state = state | FORCE_BIT;
                }

                /* initiate transition to inactive state */
                PMI_setModuleState(0,
                (UInt)ti_sysbios_family_c674_Power_database[resourceID].pscNum,
                (UInt)ti_sysbios_family_c674_Power_database[resourceID].lpscNum,
                 state);

                /* now wait for the PSC transition to complete */
                while ((pmi == PMI_BUSY) && (checks++ < PSCWAITTHRESHOLD)) {
                    pmi = PMI_getModuleState(0,
                        (UInt)ti_sysbios_family_c674_Power_database[resourceID].pscNum,
                        (UInt)ti_sysbios_family_c674_Power_database[resourceID].lpscNum, &state);
                }

                /* check that transitioned to inactive state */
                if ((pmi == PMI_OK) &&
                   (state == (UInt)ti_sysbios_family_c674_Power_database[resourceID].inactiveState)) {
                    callStatus = TRUE;
                }
                else {
                    callStatus = FALSE;
                }
            }

            /* if returned status is good, set reference count to 0 */
            if (callStatus == TRUE) {
                ti_sysbios_family_c674_Power_database[resourceID].count = 0;
            }
            /* else, don't modify reference count, return failure code */
            else {
                status = Power_EFAIL;
            }
        }

        /* re-enable scheduling */
        Swi_restore(key);
    }

    return (status);
}
/*
 *  ======== 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();
    }
}
Example #13
0
/*
 *  ======== Swi_startup ========
 */
Void Swi_startup()
{
    Swi_restore(FALSE);
}
Example #14
0
/*
 *  ======== Power_changeSetpoint ========
 *  Initiate a change to the F/V setpoint of the CPU, or the peripheral domain.
 *
 */
Power_Status Power_changeSetpoint(Power_Domain domain, UInt newSetpoint,
    UInt notifyTimeout)
{
    PSCL_Status statusPSCL = PSCL_CANNOT_CHANGE_SETPOINT;
    Power_Status status = Power_SOK;
    Power_Status statusNotifyCPU = Power_SOK;
    Power_Status statusNotifyPER = Power_SOK;
    Bool notifyCPU = FALSE;
    Bool notifyPER = FALSE;
    UInt willChange = FALSE;
    Bool proceed = FALSE;
    Types_FreqHz cpuFreq;
    UInt previousSPPER;
    UInt previousSP;
    UInt disallowed;
    PSCL_ClkID clk;
    UInt frequency;
    UInt voltage;
    UInt maskSP;
    UInt taskKey;
    UInt swiKey;
    UInt key;

    /* make sure V/F scaling is supported */
    if (!ti_sysbios_family_c674_Power_enableScaling) {
        status = Power_ENOTIMPLEMENTED;
    }

    /* check to make sure V/F scaling initialized OK */
    else if (Power_module->PSCLinitOK == FALSE) {
        status = Power_EINITFAILURE;
    }

    /* check that domain ID is valid */
    else if ((domain != Power_CPU) && (domain != Power_PER)) {
        status = Power_EINVALIDVALUE;
    }

    /* check if setpoint ID is out of range for the specified domain ID */
    else if (((domain == Power_CPU) && (newSetpoint > 
                 (Power_module->numSPCPU - 1))) ||
             ((domain == Power_PER) && (newSetpoint > 
                 (Power_module->numSPPER - 1)))) {
        status = Power_EOUTOFRANGE;
    }

    else {

        /* convert requested setpoint into a mask bit */
        maskSP = 1 << newSetpoint;

        /* go atomic */
        key = Hwi_disable();

        /* now check the requested SP against disallowed SP constraints */
        if (domain == Power_CPU) {
            disallowed = maskSP & Power_module->disallowedSetpointsCPU;
        }
        else {
            disallowed = maskSP & Power_module->disallowedSetpointsPER;
        }

        /* if the SP is *not* disallowed, check and set the 'busy' flag */
        if (disallowed == 0) {

            if (Power_module->busy == FALSE) {
                Power_module->busy = TRUE;
                proceed = TRUE;
            }
            else {
                status = Power_EBUSY;
            }
        }
        else {
            status = Power_ENOTSUPPORTED;
        }

        /* end ATOMIC */
        Hwi_restore(key);

        if (proceed == TRUE) {

            /* determine PSCL clock ID */
            clk = (PSCL_ClkID) domain == Power_CPU ? PSCL_CPU_CLK : 
                PSCL_PER_CLK;

            /* disable Task scheduling; allow Swi & Hwi for completion */
            taskKey = Task_disable();

            /* set flag for domain to be notified for SP change */
            if (domain == Power_CPU) {
                notifyCPU = TRUE;
            }
            else {
                notifyPER = TRUE;
            }

            /* if voltage scaling enabled, call to PSCL to see if this setpoint
               change will result in a voltage change; if yes, then must notify
               for other clk domain too, as there will be a voltage scale even
               though that clk frequency isn't changing */
            if (Power_module->currentConfig.scaleVoltage == TRUE) {

                PSCL_queryWillChangeVoltage(clk, newSetpoint, &willChange);

                if (willChange == TRUE) {
                    if (domain == Power_CPU) {
                        notifyPER = TRUE;
                    }
                    else {
                        notifyCPU = TRUE;
                    }
                }
            }

            /* now send any pre-notifications for CPU domain */
            if (notifyCPU == TRUE) {

                /* set nextSP to indicate the pending setpoint */
                if (domain == Power_CPU) {
                    Power_module->nextSP = newSetpoint; /* yes, new setpoint */
                    previousSP = Power_module->currentSetpointCPU;
                }
                else {                               /* not new CPU setpoint */
                    Power_module->nextSP = Power_module->currentSetpointCPU; 
                    previousSP = Power_module->currentSetpointCPU;
                }

                /* notify clients registered for pre CPU SP notification */
                statusNotifyCPU = 
                    Power_notify(Power_PENDING_CPU_SETPOINTCHANGE, 
                    notifyTimeout, Power_SigType_INTERNAL, NULL, NULL);
             }

            /* now send any pre-notifications for PER domain */
            if ((statusNotifyCPU == Power_SOK) && (notifyPER == TRUE)) {

                /* set nextSPPER to indicate the pending setpoint */
                if (domain == Power_CPU) {           /* not new PER SP */
                    Power_module->nextSPPER = Power_module->currentSetpointPER;
                    previousSPPER = Power_module->currentSetpointPER;
                }
                else {
                    Power_module->nextSPPER = newSetpoint; /* yes, new PER SP */
                    previousSPPER = Power_module->currentSetpointPER;
                }

                /* notify clients registered for pre PER SP notification */
                statusNotifyPER = 
                    Power_notify(Power_PENDING_PER_SETPOINTCHANGE,
                    notifyTimeout, Power_SigType_INTERNAL, NULL, NULL);
            }


            /* if all 'pre' notifications succeeded... do the scaling op */
            if ((statusNotifyCPU == Power_SOK) &&
                (statusNotifyPER == Power_SOK)) {

                swiKey = Swi_disable();

                /* call to PSCL to change the setpoint */
                statusPSCL = PSCL_changeSetpoint(clk, newSetpoint,
                    Power_module->currentConfig.scaleVoltage,
                    Power_module->currentConfig.waitForVoltageScale,NULL,NULL);

                Swi_restore(swiKey);
            }

            /* if scaling operation successful... */
            if (statusPSCL == PSCL_OK) {

                /* update previous and current SP globals */
                if (notifyCPU == TRUE) {
                    Power_module->currentSetpointCPU = Power_module->nextSP;
                    Power_module->previousSP = previousSP;
                }
                if (notifyPER == TRUE) {
                    Power_module->currentSetpointPER = Power_module->nextSPPER;
                    Power_module->previousSPPER = previousSPPER;
                }

                /* if scaled the CPU frequency... tell BIOS about it */
                if (domain == Power_CPU) {
                    Power_getSetpointInfo(Power_CPU, newSetpoint, &frequency,
                        &voltage);
                    cpuFreq.lo = frequency * 1000; /* convert kHz to Hz */
                    cpuFreq.hi = 0;             
                    BIOS_setCpuFreq(&cpuFreq);
                }

                /* now notify post-notification clients */
                if (notifyCPU == TRUE) {

                    /* notify clients registered of post CPU SP change */
                    statusNotifyCPU = 
                        Power_notify(Power_DONE_CPU_SETPOINTCHANGE, 
                            notifyTimeout, Power_SigType_INTERNAL, NULL, NULL);
                }

                if ((statusNotifyCPU == Power_SOK) && (notifyPER == TRUE)) {

                    /* notify clients registered of post PER SP change */
                    statusNotifyPER = 
                        Power_notify(Power_DONE_PER_SETPOINTCHANGE,
                            notifyTimeout, Power_SigType_INTERNAL, NULL, NULL);
                }
            }

            /* done, so clear Power busy flag */
            Power_module->busy = FALSE;

            /* resume Tasking */
            Task_restore(taskKey);

            /* figure out return code */
            if (statusPSCL == PSCL_INVALID_SETPOINT) {
                status = Power_EOUTOFRANGE;  /* invalid SP according to PSCL */
            }
            else if ((statusNotifyCPU == Power_ETIMEOUT) ||
                     (statusNotifyPER == Power_ETIMEOUT) ) {
                status = Power_ETIMEOUT;     /* notification timeout */
            }
            else if ((status != Power_SOK) || (statusPSCL != PSCL_OK)) {
                status = Power_EFAIL;        /* convert to 'general failure' */
            }
        }
    }

    return (status);
}
Example #15
0
/*
 *  ======== Power_sleepDSP ========
 */
Power_Status Power_sleepDSP(UInt sleepCode, UInt sleepArg, UInt notifyTimeout)
{
    Power_Status status = Power_SOK;
    Bool exitNow = FALSE;
    Power_Event preEvent;
    Power_Event postEvent;
    PMI_Sleep sleepMode;
    UInt taskKey;
    UInt swiKey;
    UInt hwiKey;

    /* first validate the sleep code */
    if ( (sleepCode != Power_STANDBY) &&
         (sleepCode != Power_SLEEP) &&
         (sleepCode != Power_DEEPSLEEP) ) {
        status = Power_ENOTIMPLEMENTED;
    }

    /* make sure sleep request doesn't violate a registered constraint */
    else if ( ( (sleepCode == Power_STANDBY) &&
                ((Power_module->disallowedSleepModes & Power_STANDBY) != 0) ) ||
              ( (sleepCode == Power_SLEEP) &&
                ((Power_module->disallowedSleepModes & Power_SLEEP) != 0) ) ||
              ( (sleepCode == Power_DEEPSLEEP) &&
               ((Power_module->disallowedSleepModes & Power_DEEPSLEEP) != 0))) {
        status = Power_ENOTSUPPORTED;
    }

    /* check for valid sleepArg */
    else if (sleepCode == Power_DEEPSLEEP) {
        if ((sleepArg != Power_EXTERNAL) && (sleepArg != Power_RTC_ALARM)) {
            status = Power_EINVALIDVALUE;
        }
    }

    if (status == Power_SOK) {

        /* make sure Power is not still busy with a previous transition */
        hwiKey = Hwi_disable();

        if (Power_module->busy == FALSE) {
            Power_module->busy = TRUE;
        }
        else {
            exitNow = TRUE;
        }

        Hwi_restore(hwiKey);

        if (exitNow == TRUE) {
            status = Power_EBUSY;
        }

        else {

            /* setup sleep vars */
            if (sleepCode == Power_STANDBY) {
                preEvent = Power_GOINGTOSTANDBY;
                postEvent = Power_AWAKEFROMSTANDBY;
                sleepMode = PMI_STANDBY;
            }
            else if (sleepCode == Power_SLEEP) {
                preEvent = Power_GOINGTOSLEEP;
                postEvent = Power_AWAKEFROMSLEEP;
                sleepMode = PMI_SLEEP;
            }
            else {
                preEvent = Power_GOINGTODEEPSLEEP;
                postEvent = Power_AWAKEFROMDEEPSLEEP;
                sleepMode = PMI_DEEPSLEEP;
            }

            /* disable Task scheduling; allow Swis and Hwis for notifications */
            taskKey = Task_disable();

            /* signal all clients registered for pre-sleep notification */
            status = Power_notify(preEvent, notifyTimeout, 
                Power_SigType_INTERNAL, NULL, NULL);

            /* check for timeout or any other error */
            if (status != Power_SOK) {
                Power_module->busy = FALSE;     /* clear busy */
                Task_restore(taskKey);          /* re-enable scheduler */
                return (status);
            }

            /* now disable Swi scheduling */
            swiKey = Swi_disable();

            /* start the sleep sequence */
            hwiKey = Hwi_disable();

            /* call to PMI to go to and wake from sleep... */
            PMI_sleepCPU(sleepMode, Power_module->currentConfig.scaleVoltage,
                (UInt) sleepArg);

            /* when get here CPU has already processed the wakeup interrupt */

            /* restore the previous interrupt enable state */
            Hwi_restore(hwiKey);

            /* re-enable Swi scheduling */
            Swi_restore(swiKey);

            /* signal all clients registered for post-sleep notification */
            status = Power_notify(postEvent, notifyTimeout, 
                Power_SigType_INTERNAL, NULL, NULL);

            /* now clear the busy flag before re-enabling scheduler */
            Power_module->busy = FALSE;

            /* re-enable Task scheduling */
            Task_restore(taskKey);

            /* check for timeout or other notification error */
            if (status != Power_SOK) {
                return (status);
            }
        }
    }

    return (status);
}
Example #16
0
/*
 *  ======== Power_suspend ========
 */
UInt Power_suspend(Power_Suspend level)
{
    Bool l1CacheEnabled;
    Bool l2CacheEnabled;
    UInt32 *wordPtr;
    UInt32 taskKey;
    UInt32 swiKey;
    UInt32 hwiKey;
    UInt32 reset;
    UInt32 tmp1;
    UInt32 tmp2;
    UInt32 i;

    /* disable interrupts */
    hwiKey = Hwi_disable();

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

    /* check Unicache state; set 'enabled' flags */
    l1CacheEnabled = Cache_cache.L1_CONFIG & 0x2;
    l2CacheEnabled = Cache_cache.L2_CONFIG & 0x2;

#if _VERBOSE_
    System_printf("Power_suspend\n");
    System_printf("    suspend level = 0x%x\n", level);
    System_printf("    subsystem context = 0x%x\n", &ssContext);
    System_printf("    CPU context = 0x%x\n", 
        &ti_sysbios_family_c64p_tesla_Power_cpuRegs);
    System_printf("    CPU sys regs = 0x%x\n", &ssContext.cpuSysRegs);
    System_printf("    INTC context = 0x%x\n", &ssContext.configINTC);
    System_printf("    SYSC context = 0x%x\n", &ssContext.configSYSC);
    System_printf("    AMMU context = 0x%x\n", &ssContext.configAMMU);
    System_printf("    EDMA context = 0x%x\n", &ssContext.configEDMA);
    System_printf("    TSC flag = 0x%x\n", &ssContext.tscRunning);
    System_printf("    L1 context = 0x%x\n", &ssContext.configL1);
    System_printf("    L1 enabled = 0x%x\n", l1CacheEnabled);
    System_printf("    L2 context = 0x%x\n", &ssContext.configL2);
    System_printf("    L2 enabled = 0x%x\n", l2CacheEnabled);
#endif

    /* = = = = = = = = */
    
    /* if HIBERNATE: save Tesla subsystem context ... */
    if (level == Power_Suspend_HIBERNATE) {

        /* save Unicache config context */
        ssContext.configL1.CONFIG = (UInt32) Cache_cache.L1_CONFIG;
        ssContext.configL1.OCP = (UInt32) Cache_cache.L1_OCP;
        ssContext.configL2.CONFIG = (UInt32) Cache_cache.L2_CONFIG;
        ssContext.configL2.OCP = (UInt32) Cache_cache.L2_OCP;

        /* = = = = = = = = */

        /* save AMMU context */
        for (i = 0; i < AMMU_numLargePages; i++) {
            ssContext.configAMMU.largeAddr[i] = 
                (UInt32) AMMU_mmu.LARGE_ADDR[i];
            ssContext.configAMMU.largePolicy[i] = 
                (UInt32) AMMU_mmu.LARGE_POLICY[i];
        }
        for (i = 0; i < AMMU_numMediumPages; i++) {
            ssContext.configAMMU.medAddr[i] = 
                (UInt32) AMMU_mmu.MEDIUM_ADDR[i];
            ssContext.configAMMU.medPolicy[i] = 
                (UInt32) AMMU_mmu.MEDIUM_POLICY[i];
        }
        for (i = 0; i < AMMU_numSmallPages; i++) {
            ssContext.configAMMU.smallAddr[i] = 
                (UInt32) AMMU_mmu.SMALL_ADDR[i];
            ssContext.configAMMU.smallPolicy[i] = 
                (UInt32) AMMU_mmu.SMALL_POLICY[i];
        }

        /* = = = = = = = = */

        /* save SYSC context */
        ssContext.configSYSC.SYSCONFIG = 
            REG((UInt32)Power_syscRegs + SYSCONFIG_REG_OFFSET);
        ssContext.configSYSC.VBUSM2OCP = 
            REG((UInt32)Power_syscRegs + VBUSM2OCP_REG_OFFSET);
        ssContext.configSYSC.EDMA = 
            REG((UInt32)Power_syscRegs + EDMA_REG_OFFSET);
        ssContext.configSYSC.CORE = 
            REG((UInt32)Power_syscRegs + CORE_REG_OFFSET);
        ssContext.configSYSC.IVA_ICTRL = 
            REG((UInt32)Power_syscRegs + IVA_ICTRL_REG_OFFSET);
        ssContext.configSYSC.IDLEDLY = 
            REG((UInt32)Power_syscRegs + IDLEDLY_REG_OFFSET);

        /* = = = = = = = = */

        /* save INTC context */
        ssContext.configINTC.EVTMASK0 = REG(EVTMASK0_REG);
        ssContext.configINTC.EVTMASK1 = REG(EVTMASK1_REG);
        ssContext.configINTC.EVTMASK2 = REG(EVTMASK2_REG);
        ssContext.configINTC.EVTMASK3 = REG(EVTMASK3_REG);
        ssContext.configINTC.EXPMASK0 = REG(EXPMASK0_REG);
        ssContext.configINTC.EXPMASK1 = REG(EXPMASK1_REG);
        ssContext.configINTC.EXPMASK2 = REG(EXPMASK2_REG);
        ssContext.configINTC.EXPMASK3 = REG(EXPMASK3_REG);
        ssContext.configINTC.INTMUX1 = REG(INTMUX1_REG);
        ssContext.configINTC.INTMUX2 = REG(INTMUX2_REG);
        ssContext.configINTC.INTMUX3 = REG(INTMUX3_REG);
        ssContext.configINTC.AEGMUX0 = REG(AEGMUX0_REG);
        ssContext.configINTC.AEGMUX1 = REG(AEGMUX1_REG);
        ssContext.configINTC.INTDMASK = REG(INTDMASK_REG);

        /* = = = = = = = = */

        /* save EDMA context */
 
        ssContext.configEDMA.CLKGDIS = 
            REG((UInt32)Power_tpccRegs + CLKGDIS_REG_OFFSET);

        /* save DMA chan to PARAM mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DCHMAP0_REG_OFFSET);
        for (i = 0; i < 64; i++) {      
            ssContext.configEDMA.DCHMAP[i] = *wordPtr++;
        }

        /* save QDMA chan to PARAM mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + QCHMAP0_REG_OFFSET);
        for (i = 0; i < 8; i++) {       
            ssContext.configEDMA.QCHMAP[i] = *wordPtr++;
        }

        /* save DMA queue mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DMAQNUM0_REG_OFFSET);
        for (i = 0; i < 8; i++) {       
            ssContext.configEDMA.DMAQNUM[i] = *wordPtr++;
        }

        ssContext.configEDMA.QDMAQNUM = 
            REG((UInt32)Power_tpccRegs + QDMAQNUM_REG_OFFSET);
        ssContext.configEDMA.QUETCMAP = 
            REG((UInt32)Power_tpccRegs + QUETCMAP_REG_OFFSET);
        ssContext.configEDMA.QUEPRI = 
            REG((UInt32)Power_tpccRegs + QUEPRI_REG_OFFSET);

        /* save DMA and QDMA region access enable bits */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DRAEM0_REG_OFFSET);
        for (i = 0; i < (8 * 3); i++) { 
            ssContext.configEDMA.regionAccessBits[i] = *wordPtr++;
        }

        ssContext.configEDMA.QWMTHRA = 
            REG((UInt32)Power_tpccRegs + QWMTHRA_REG_OFFSET);
        ssContext.configEDMA.AETCTL = 
            REG((UInt32)Power_tpccRegs + AETCTL_REG_OFFSET);
        ssContext.configEDMA.IER = 
            REG((UInt32)Power_tpccRegs + IER_REG_OFFSET);
        ssContext.configEDMA.IERH = 
            REG((UInt32)Power_tpccRegs + IERH_REG_OFFSET);
        ssContext.configEDMA.QEER = 
            REG((UInt32)Power_tpccRegs + QEER_REG_OFFSET);

        /* bulk save of all PaRAMs (8 regs * 128 PaRAMs */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + OPT0_REG_OFFSET);
        for (i = 0; i < (8 * 128); i++) {       
            ssContext.configEDMA.PaRAMs[i] = *wordPtr++;
        }

        /* = = = = = = = = */

        /* save CPU control registers */
        ssContext.cpuSysRegs.AMR = AMR;
        ssContext.cpuSysRegs.CSR = CSR;
        ssContext.cpuSysRegs.IER = IER;
        ssContext.cpuSysRegs.ISTP = ISTP;
        ssContext.cpuSysRegs.IRP = IRP;
        ssContext.cpuSysRegs.SSR = SSR;
        ssContext.cpuSysRegs.GPLYB = GPLYB;
        ssContext.cpuSysRegs.GFPGFR = GFPGFR;
        ssContext.cpuSysRegs.TSR = TSR;
        ssContext.cpuSysRegs.ITSR = ITSR;
        ssContext.cpuSysRegs.IERR = IERR;

    }

    /* sample and set the 'TSC is running' state flag */
    tmp1 = TSCL;
    tmp2 = TSCL;
    if (tmp1 == tmp2) {
        ssContext.tscRunning = 0;
    }
    else {
        ssContext.tscRunning = 1;
    }

    /* if Unicache enabled, prepare for standby ... */
    if (l1CacheEnabled || l2CacheEnabled) {

        /* if HIBERNATE: write back all for L1 and L2 */
        if (level == Power_Suspend_HIBERNATE) { 
            Cache_wbAll();
        }
        /* else, retention, just clean the write buffers */
        else {
            Cache_wb(0, 0, Cache_Type_ALL, TRUE);/* start=end=0 -> clean bufs */
        }

        /* now bypass the caches... */
        if (l1CacheEnabled) {
            Cache_disable(Cache_Type_L1);
        }
        if (l2CacheEnabled) {
            Cache_disable(Cache_Type_L2);
        }
    }

    /* set reset-function-sampled 'doing a resume' flag */
    ti_sysbios_family_c64p_tesla_Power_doResume = 1;

    /* set the ready-to-standby flag (an FYI for the MPU) */
    ti_sysbios_family_c64p_tesla_Power_readyIdle = 1;

    /* setup PDC to put GEM into standby when execute IDLE */
    REG(PDCCMD_REG) = PDCCMD_STANDBY;
    REG(PDCCMD_REG);

    /* make function call to save child-preserved CPU regs and do standby ... */
    reset = ti_sysbios_family_c64p_tesla_Power_standby(
        &ti_sysbios_family_c64p_tesla_Power_cpuRegs);

    /* = = = = = = = = */

    /* NOTE: return here both when woke from IDLE, or resumed after reset */

    /* = = = = = = = = */

    /* note: this symbol is not used, but is defined for debug purposes only */
    asm(" .global ti_sysbios_family_c64p_tesla_Power_suspend_RESUME");
    asm("ti_sysbios_family_c64p_tesla_Power_suspend_RESUME:");

    /* if HIBERNATE and *did* reset: restore all context ... */
    if ((reset != 0) && (level == Power_Suspend_HIBERNATE)) {

        /* restore CPU control registers */
        AMR = ssContext.cpuSysRegs.AMR;
        CSR = ssContext.cpuSysRegs.CSR;
        IER = ssContext.cpuSysRegs.IER;
        ISTP = ssContext.cpuSysRegs.ISTP;
        IRP = ssContext.cpuSysRegs.IRP;
        SSR = ssContext.cpuSysRegs.SSR;
        GPLYB = ssContext.cpuSysRegs.GPLYB;
        GFPGFR = ssContext.cpuSysRegs.GFPGFR;
        TSR = ssContext.cpuSysRegs.TSR;
        ITSR = ssContext.cpuSysRegs.ITSR;
        IERR = ssContext.cpuSysRegs.IERR;

        /* = = = = = = = = */

        /* restore AMMU configuration */
        for (i = 0; i < AMMU_numLargePages; i++) {
            AMMU_mmu.LARGE_ADDR[i] = 
                (Char *) ssContext.configAMMU.largeAddr[i];
            AMMU_mmu.LARGE_POLICY[i] = 
                ssContext.configAMMU.largePolicy[i];
        }
        for (i = 0; i < AMMU_numMediumPages; i++) {
            AMMU_mmu.MEDIUM_ADDR[i] =
                (Char *) ssContext.configAMMU.medAddr[i];
            AMMU_mmu.MEDIUM_POLICY[i] =
                ssContext.configAMMU.medPolicy[i];
        }
        for (i = 0; i < AMMU_numSmallPages; i++) {
            AMMU_mmu.SMALL_ADDR[i] =
                (Char *) ssContext.configAMMU.smallAddr[i];
            AMMU_mmu.SMALL_POLICY[i] =
                ssContext.configAMMU.smallPolicy[i];
        }

        /* = = = = = = = = */

        /* restore Unicache config */
        Cache_cache.L1_OCP = ssContext.configL1.OCP;
        tmp1 = Cache_cache.L1_OCP;      /* read to ensure posted write done */
        Cache_cache.L1_CONFIG = ssContext.configL1.CONFIG;
        tmp1 = Cache_cache.L1_CONFIG;   /* read to ensure posted write done */
        Cache_cache.L2_OCP = ssContext.configL2.OCP;
        tmp1 = Cache_cache.L2_OCP;      /* read to ensure posted write done */
        Cache_cache.L2_CONFIG = ssContext.configL2.CONFIG;
        tmp1 = Cache_cache.L2_CONFIG;   /* read to ensure posted write done */

        /* = = = = = = = = */

        /* restore SYSC context */
        REG((UInt32)Power_syscRegs + SYSCONFIG_REG_OFFSET) =
            ssContext.configSYSC.SYSCONFIG;
        REG((UInt32)Power_syscRegs + VBUSM2OCP_REG_OFFSET) =
            ssContext.configSYSC.VBUSM2OCP;
        REG((UInt32)Power_syscRegs + EDMA_REG_OFFSET) =
            ssContext.configSYSC.EDMA;
        REG((UInt32)Power_syscRegs + CORE_REG_OFFSET) =
            ssContext.configSYSC.CORE;
        REG((UInt32)Power_syscRegs + IVA_ICTRL_REG_OFFSET) =
            ssContext.configSYSC.IVA_ICTRL;
        REG((UInt32)Power_syscRegs + IDLEDLY_REG_OFFSET) =
            ssContext.configSYSC.IDLEDLY;

        /* = = = = = = = = */

        /* restore INTC context */
        REG(EVTMASK0_REG) = ssContext.configINTC.EVTMASK0;
        REG(EVTMASK1_REG) = ssContext.configINTC.EVTMASK1;
        REG(EVTMASK2_REG) = ssContext.configINTC.EVTMASK2;
        REG(EVTMASK3_REG) = ssContext.configINTC.EVTMASK3;
        REG(EXPMASK0_REG) = ssContext.configINTC.EXPMASK0;
        REG(EXPMASK1_REG) = ssContext.configINTC.EXPMASK1;
        REG(EXPMASK2_REG) = ssContext.configINTC.EXPMASK2;
        REG(EXPMASK3_REG) = ssContext.configINTC.EXPMASK3;
        REG(INTMUX1_REG) = ssContext.configINTC.INTMUX1;
        REG(INTMUX2_REG) = ssContext.configINTC.INTMUX2;
        REG(INTMUX3_REG) = ssContext.configINTC.INTMUX3;
        REG(AEGMUX0_REG) = ssContext.configINTC.AEGMUX0;
        REG(AEGMUX1_REG) = ssContext.configINTC.AEGMUX1;
        REG(INTDMASK_REG) = ssContext.configINTC.INTDMASK;

        /* = = = = = = = = */

        /* restore EDMA context */

        REG((UInt32)Power_tpccRegs + CLKGDIS_REG_OFFSET) =
            ssContext.configEDMA.CLKGDIS;

        /* restore DMA chan to PARAM mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DCHMAP0_REG_OFFSET);
        for (i = 0; i < 64; i++) {      
            *wordPtr++ = ssContext.configEDMA.DCHMAP[i];
        }

        /* restore QDMA chan to PARAM mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + QCHMAP0_REG_OFFSET);
        for (i = 0; i < 8; i++) {       
            *wordPtr++ = ssContext.configEDMA.QCHMAP[i];
        }

        /* restore DMA queue mapping registers */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DMAQNUM0_REG_OFFSET);
        for (i = 0; i < 8; i++) {       
            *wordPtr++ = ssContext.configEDMA.DMAQNUM[i];
        }

        REG((UInt32)Power_tpccRegs + QDMAQNUM_REG_OFFSET) =
            ssContext.configEDMA.QDMAQNUM;
        REG((UInt32)Power_tpccRegs + QUETCMAP_REG_OFFSET) =
            ssContext.configEDMA.QUETCMAP;
        REG((UInt32)Power_tpccRegs + QUEPRI_REG_OFFSET) =
            ssContext.configEDMA.QUEPRI;

        /* restore DMA and QDMA region access enable bits */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + DRAEM0_REG_OFFSET);
        for (i = 0; i < (8 * 3); i++) { 
            *wordPtr++ = ssContext.configEDMA.regionAccessBits[i];
        }

        REG((UInt32)Power_tpccRegs + QWMTHRA_REG_OFFSET) =
            ssContext.configEDMA.QWMTHRA;
        REG((UInt32)Power_tpccRegs + AETCTL_REG_OFFSET) =
            ssContext.configEDMA.AETCTL;

        /* restore interrupt enable registers (using IESR and IESRH) */
        REG((UInt32)Power_tpccRegs + IESR_REG_OFFSET) =
            ssContext.configEDMA.IER;
        REG((UInt32)Power_tpccRegs + IESRH_REG_OFFSET) =
            ssContext.configEDMA.IERH;

        /* restore QDMA event enable register (using QEESR) */
        REG((UInt32)Power_tpccRegs + QEESR_REG_OFFSET) = 
            ssContext.configEDMA.QEER;

        /* restore all PaRAMs (8 regs * 128 PaRAMs */
        wordPtr = (UInt32 *)((UInt32)Power_tpccRegs + OPT0_REG_OFFSET);
        for (i = 0; i < (8 * 128); i++) {       
            *wordPtr++ = ssContext.configEDMA.PaRAMs[i];
        }

#if _VERBOSE_
        System_printf("hibernate: restored context\n");
#endif

    }

    /* Else: Restore caches to their pre-standby enable state.
     * Note: When come out of retention reset caches will always be enabled,
     *       even if they weren't enabled before standby. So, need to disable
     *       them now, if they weren't enabled when suspend was invoked. 
     */
    else {
        /* restore the enabled state of the caches ... */
        if (l1CacheEnabled) {
            Cache_enable(Cache_Type_L1);
        }
        else {
            Cache_disable(Cache_Type_L1);
        }
        if (l2CacheEnabled) {
            Cache_enable(Cache_Type_L2);
        }
        else {
            Cache_disable(Cache_Type_L2);
        }
    }

#if _VERBOSE_
    System_printf("reset flag = %d\n", reset);
#endif

    /* if TSC was enabled on entry: start it again */
    if (ssContext.tscRunning == 1) {
        TSCL = 1;       /* write any value to TSC to kick start it */
    }

    /* clear the ready-to-standby flag */
    ti_sysbios_family_c64p_tesla_Power_readyIdle = 0;

    /* clear the reset-sampled 'do resume' flag */
    ti_sysbios_family_c64p_tesla_Power_doResume = 0;

    /* re-enable scheduling */
    Task_restore(taskKey);
    Swi_restore(swiKey);

    /* re-enable interrupts */
    Hwi_restore(hwiKey);

    return (reset);
}
/*
 *  ======== Power_sleep ========
 */
Power_Status Power_sleep(Power_SleepState sleepState, UArg arg0, UArg arg1)
{
    Power_Status status = Power_SOK;
    UInt xosc_hf_active = FALSE;
    Power_Event postEventLate;
    UInt32 poweredDomains = 0;
    Bool exitNow = FALSE;
    Power_Event preEvent;
    Power_Event postEvent;
    UInt32 constraints;
    Bool retainCache = FALSE;
    UInt32 modeVIMS;
    UInt taskKey;
    UInt swiKey;
    UInt hwiKey;

    /* first validate the sleep code */
    if ( sleepState != Power_STANDBY) {
        status = Power_EFAIL;
    }

    if (status == Power_SOK) {

        /* make sure Power is not still busy with a previous transition */
        hwiKey = Hwi_disable();

        if (Power_module->state == Power_ACTIVE) {

            /* set transition state to entering sleep */
            Power_module->state = Power_ENTERING_SLEEP;
        }
        else {
            exitNow = TRUE;
        }

        Hwi_restore(hwiKey);

        if (exitNow == TRUE) {
            status = Power_EBUSY;
        }

        else {

            /* setup sleep vars */
            if (sleepState == Power_STANDBY) {
                preEvent = Power_ENTERING_STANDBY;
                postEvent = Power_AWAKE_STANDBY;
                postEventLate = Power_AWAKE_STANDBY_LATE;
            }

            /* disable Task scheduling; allow Swis and Hwis for notifications */
            taskKey = Task_disable();

            /* signal all clients registered for pre-sleep notification */
            status = Power_notify(preEvent);

            /* check for any error */
            if (status != Power_SOK) {
                Power_module->state = Power_ACTIVE;
                Task_restore(taskKey);          /* re-enable scheduler */
                return (status);
            }

            /* now disable Swi scheduling */
            swiKey = Swi_disable();

            /* freeze the IOs on the boundary between MCU and AON */
            AONIOCFreezeEnable();

            /* if XOSC_HF is active, force it off */
            if(OSCClockSourceGet(OSC_SRC_CLK_HF) == OSC_XOSC_HF) {
                xosc_hf_active = TRUE;
                ti_sysbios_family_arm_cc26xx_Power_XOSC_HF(DISABLE);
            }

            /* allow AUX to power down */
            AONWUCAuxWakeupEvent(AONWUC_AUX_ALLOW_SLEEP);

            /* make sure writes take effect */
            SysCtrlAonSync();

            /* invoke specific sequences to activate sleep states... */

            if (sleepState == Power_STANDBY) {

                /* query and save domain states before powering them off */
                if (Power_getDependencyCount(DOMAIN_RFCORE)) {
                    poweredDomains |= PRCM_DOMAIN_RFCORE;
                }
                if (Power_getDependencyCount(DOMAIN_SERIAL)){
                    poweredDomains |= PRCM_DOMAIN_SERIAL;
                }
                if (Power_getDependencyCount(DOMAIN_PERIPH)) {
                    poweredDomains |= PRCM_DOMAIN_PERIPH;
                }

                /* gate running deep sleep clocks for Crypto and DMA */
                if (Power_getDependencyCount(PERIPH_CRYPTO)) {
                    PRCMPeripheralDeepSleepDisable(
                        ti_sysbios_family_arm_cc26xx_Power_db[
                            PERIPH_CRYPTO].driverlibID);
                }
                if (Power_getDependencyCount(PERIPH_UDMA)) {
                    PRCMPeripheralDeepSleepDisable(
                        ti_sysbios_family_arm_cc26xx_Power_db[
                            PERIPH_UDMA].driverlibID);
                }
                /* make sure clock settings take effect */
                PRCMLoadSet();

                /* request power off of domains in the MCU voltage domain */
                PRCMPowerDomainOff(poweredDomains | PRCM_DOMAIN_CPU);

                /* request uLDO during standby */
                PRCMMcuUldoConfigure(true);

                /* query constraints to determine if cache should be retained */
                constraints = Power_getConstraintInfo();
                if ((constraints & Power_SB_VIMS_CACHE_RETAIN) != 0) {
                    retainCache = TRUE;
                }

                /* if don't want retention in standby, disable it now ... */
                if (retainCache == FALSE) {
                    modeVIMS = VIMSModeGet(VIMS_BASE);
                    /* wait if invalidate in progress... */
                    while (modeVIMS == VIMS_MODE_CHANGING) {
                        modeVIMS = VIMSModeGet(VIMS_BASE);
                    }
                    PRCMCacheRetentionDisable();
                    VIMSModeSet(VIMS_BASE, VIMS_MODE_OFF);
                }

                /* setup recharge parameters */
                SysCtrlSetRechargeBeforePowerDown(XoscInHighPowerMode);

                /* make sure all writes have taken effect */
                SysCtrlAonSync();

                /* invoke deep sleep to go to STANDBY */
                PRCMDeepSleep();

                /* if didn't retain cache in standby, re-enable retention now */
                if (retainCache == FALSE) {
                    VIMSModeSet(VIMS_BASE, modeVIMS);
                    PRCMCacheRetentionEnable();
                }

                /* force power on of AUX to keep it on when system is not
                 * sleeping; this also counts as a write to the AON interface
                 * ensuring that a following sync of the AON interface will
                 * force an update of all registers
                 */
                AONWUCAuxWakeupEvent(AONWUC_AUX_WAKEUP);
                while(!(AONWUCPowerStatusGet() & AONWUC_AUX_POWER_ON)) {};

                /* if XOSC_HF was forced off above, initiate switch back */
                if (xosc_hf_active == TRUE) {
                    ti_sysbios_family_arm_cc26xx_Power_XOSC_HF(ENABLE);
                }

                /* restore power domain states in effect before standby */
                PRCMPowerDomainOn(poweredDomains);
                while (PRCMPowerDomainStatus(poweredDomains) !=
                    PRCM_DOMAIN_POWER_ON){};

                /* restore deep sleep clocks of Crypto and DMA */
                if (Power_getDependencyCount(PERIPH_CRYPTO)) {
                    PRCMPeripheralDeepSleepEnable(
                        ti_sysbios_family_arm_cc26xx_Power_db[
                            PERIPH_CRYPTO].driverlibID);
                }
                if (Power_getDependencyCount(PERIPH_UDMA)) {
                    PRCMPeripheralDeepSleepEnable(
                        ti_sysbios_family_arm_cc26xx_Power_db[
                            PERIPH_UDMA].driverlibID);
                }
                /* make sure clock settings take effect */
                PRCMLoadSet();
            }

            /* release request for uLDO */
            PRCMMcuUldoConfigure(false);

            /* set transition state to EXITING_SLEEP */
            Power_module->state = Power_EXITING_SLEEP;

            /*
             * signal clients registered for early post-sleep notification;
             * this should be used to initialize any timing critical or IO
             * dependent hardware
             */
            status = Power_notify(postEvent);

            /* disable IO freeze and ensure RTC shadow value is updated */
            AONIOCFreezeDisable();
            SysCtrlAonSync();

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

            /* signal all clients registered for late post-sleep notification */
            status = Power_notify(postEventLate);

            /* now clear the transition state before re-enabling scheduler */
            Power_module->state = Power_ACTIVE;

            /* re-enable Swi scheduling */
            Swi_restore(swiKey);

            /* adjust recharge parameters */
            SysCtrlAdjustRechargeAfterPowerDown();

            /* re-enable Task scheduling */
            Task_restore(taskKey);

            /* check for any notification error */
            if (status != Power_SOK) {
                return (status);
            }
        }
    }

    return (status);
}
/*
 *  ======== PowerMSP432_policyFxn ========
 */
void PowerMSP432_policyFxn()
{
    UInt constraints;
    Bool slept = false;
    UInt taskKey;
    UInt swiKey;

    /* disable interrupts */
    CPU_cpsid();

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

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

    /*
     *  Check if can go to a sleep state, starting with the deepest level.
     *  Do not go to a sleep state if a lesser sleep state is disallowed.
     */

     /* check if can go to DEEPSLEEP_1 */
    if ((constraints & ((1 << PowerMSP432_DISALLOW_SLEEP) |
                        (1 << PowerMSP432_DISALLOW_DEEPSLEEP_0) |
                        (1 << PowerMSP432_DISALLOW_DEEPSLEEP_1))) == 0) {

        /* go to DEEPSLEEP_1 */
        Power_sleep(PowerMSP432_DEEPSLEEP_1);

        /* set 'slept' to true*/
        slept = true;
    }

    /* if didn't sleep yet, now check if can go to DEEPSLEEP_0 */
    if (!slept && ((constraints & ((1 << PowerMSP432_DISALLOW_SLEEP) |
                        (1 << PowerMSP432_DISALLOW_DEEPSLEEP_0))) == 0)) {

        /* go to DEEPSLEEP_0 */
        Power_sleep(PowerMSP432_DEEPSLEEP_0);

        /* set 'slept' to true*/
        slept = true;
    }

    /* if didn't sleep yet, now check if can go to SLEEP */
    if (!slept && ((constraints & (1 << PowerMSP432_DISALLOW_SLEEP)) == 0)) {

        /* go to SLEEP */
        Power_sleep(PowerMSP432_SLEEP);

        /* set 'slept' to true*/
        slept = true;
    }

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

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

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

    /* if didn't sleep yet, just do WFI */
    if (!slept) {
        __asm(" wfi");
    }
}
/*
 *  ======== PowerMSP432_schedulerRestore ========
 */
void PowerMSP432_schedulerRestore()
{
    Swi_restore(PowerMSP432_swiKey);
    Task_restore(PowerMSP432_taskKey);
}
Example #20
0
/*
 *  ======== Swi_enable ========
 */
Void Swi_enable()
{
    Swi_restore(FALSE);
}