/********************************************************************* * @fn Util_stopClock * * @brief Stop a clock. * * @param pClock - pointer to clock struct * * @return none */ void Util_stopClock(Clock_Struct *pClock) { Clock_Handle handle = Clock_handle(pClock); // Stop clock instance Clock_stop(handle); }
/********************************************************************* * @fn Util_rescheduleClock * * @brief Reschedule a clock by changing the timeout and period values. * * @param pClock - pointer to clock struct * @param clockPeriod - longevity of clock timer in milliseconds * @return none */ void Util_rescheduleClock(Clock_Struct *pClock, uint32_t clockPeriod) { bool running; uint32_t clockTicks; Clock_Handle handle; handle = Clock_handle(pClock); running = Clock_isActive(handle); if (running) { Clock_stop(handle); } // Convert period in milliseconds to ticks. clockTicks = clockPeriod * (1000 / Clock_tickPeriod); Clock_setTimeout(handle, clockTicks); Clock_setPeriod(handle, clockTicks); if (running) { Clock_start(handle); } }
/********************************************************************* * @fn Util_constructClock * * @brief Initialize a TIRTOS Clock instance. * * @param pClock - pointer to clock instance structure. * @param clockCB - callback function upon clock expiration. * @param clockDuration - longevity of clock timer in milliseconds * @param clockPeriod - if set to a value other than 0, the first * expiry is determined by clockDuration. All * subsequent expiries use the clockPeriod value. * @param startFlag - TRUE to start immediately, FALSE to wait. * @param arg - argument passed to callback function. * * @return Clock_Handle - a handle to the clock instance. */ Clock_Handle Util_constructClock(Clock_Struct *pClock, Clock_FuncPtr clockCB, uint32_t clockDuration, uint32_t clockPeriod, uint8_t startFlag, UArg arg) { Clock_Params clockParams; // Convert clockDuration in milliseconds to ticks. uint32_t clockTicks = clockDuration * (1000 / Clock_tickPeriod); // Setup parameters. Clock_Params_init(&clockParams); // Setup argument. clockParams.arg = arg; // If period is 0, this is a one-shot timer. clockParams.period = clockPeriod * (1000 / Clock_tickPeriod); // Starts immediately after construction if true, otherwise wait for a call // to start. clockParams.startFlag = startFlag; // Initialize clock instance. Clock_construct(pClock, clockCB, clockTicks, &clockParams); return Clock_handle(pClock); }
/********************************************************************* * @fn Util_isActive * * @brief Determine if a clock is currently active. * * @param pClock - pointer to clock struct * * @return TRUE if Clock is currently active FALSE otherwise */ bool Util_isActive(Clock_Struct *pClock) { Clock_Handle handle = Clock_handle(pClock); // Start clock instance return Clock_isActive(handle); }
/* * ======== Task_sleep ======== */ Void Task_sleep(UInt timeout) { Task_PendElem elem; UInt hwiKey, tskKey; Clock_Struct clockStruct; if (timeout == BIOS_NO_WAIT) { return; } Assert_isTrue((timeout != BIOS_WAIT_FOREVER), Task_A_badTimeout); /* add Clock event if timeout is not FOREVER */ if (BIOS_clockEnabled) { Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg)&elem; clockParams.startFlag = FALSE; /* will start when necessary, thankyou */ Clock_construct(&clockStruct, (Clock_FuncPtr)Task_sleepTimeout, timeout, &clockParams); elem.clock = Clock_handle(&clockStruct); } hwiKey = Hwi_disable(); /* lock scheduler */ tskKey = Task_disable(); /* get task handle and block tsk */ elem.task = Task_self(); Task_blockI(elem.task); if (BIOS_clockEnabled) { Clock_startI(elem.clock); } /* Only needed for Task_delete() */ Queue_elemClear(&elem.qElem); elem.task->pendElem = (Ptr)(&elem); Hwi_restore(hwiKey); Log_write3(Task_LM_sleep, (UArg)elem.task, (UArg)elem.task->fxn, (UArg)timeout); Task_restore(tskKey); /* the calling task will block here */ /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled) { Clock_destruct(Clock_struct(elem.clock)); } }
static Int32 IpcFramesInLink_createPrdObj(IpcFramesInLink_Obj * pObj) { Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg) pObj; UTILS_assert(pObj->prd.clkHandle == NULL); Clock_construct(&(pObj->prd.clkStruct), IpcFramesInLink_prdCalloutFcn, 1, &clockParams); pObj->prd.clkHandle = Clock_handle(&pObj->prd.clkStruct); pObj->prd.clkStarted = FALSE; return IPC_FRAMES_IN_LINK_S_SUCCESS; }
/********************************************************************* * @fn initBuzzTimer * * @brief Set up timer for buzz generation (use PWM when RTOS driver in place) * * @param none * * @return none */ static void initBuzzTimer(void) { Clock_Params clockParams; // Setup parameters. Clock_Params_init(&clockParams); // Setup argument. clockParams.arg = 0; // Period clockParams.period = BUZZER_PERIOD; // Do not start until called. clockParams.startFlag = false; // Initialize clock instance. Clock_construct(&buzzClockStruct, timerIsr, BUZZER_PERIOD, &clockParams); buzzClockHandle = Clock_handle(&buzzClockStruct); }
/********************************************************************* * @fn Util_restartClock * * @brief Restart a clock by changing the timeout. * * @param pClock - pointer to clock struct * @param clockTimeout - longevity of clock timer in milliseconds * * @return none */ void Util_restartClock(Clock_Struct *pClock, uint32_t clockTimeout) { uint32_t clockTicks; Clock_Handle handle; handle = Clock_handle(pClock); if (Clock_isActive(handle)) { // Stop clock first Clock_stop(handle); } // Convert timeout in milliseconds to ticks. clockTicks = clockTimeout * (1000 / Clock_tickPeriod); // Set the initial timeout Clock_setTimeout(handle, clockTicks); // Start clock instance Clock_start(handle); }
/* * ======== Event_pend ======== */ UInt Event_pend(Event_Object *event, UInt andMask, UInt orMask, UInt32 timeout) { UInt hwiKey, tskKey; Event_PendElem elem; UInt matchingEvents; Queue_Handle pendQ; Clock_Struct clockStruct; Assert_isTrue(((andMask | orMask) != 0), Event_A_nullEventMasks); Log_write5(Event_LM_pend, (UArg)event, (UArg)event->postedEvents, (UArg)andMask, (UArg)orMask, (IArg)((Int)timeout)); /* * elem is filled in entirely before interrupts are disabled. * This significantly reduces latency at the potential cost of wasted time * if it turns out that there is already an event match. */ /* add Clock event if timeout is not FOREVER nor NO_WAIT */ if (BIOS_clockEnabled && (timeout != BIOS_WAIT_FOREVER) && (timeout != BIOS_NO_WAIT)) { Clock_addI(Clock_handle(&clockStruct), (Clock_FuncPtr)Event_pendTimeout, timeout, (UArg)&elem); elem.tpElem.clock = Clock_handle(&clockStruct); elem.pendState = Event_PendState_CLOCK_WAIT; } else { elem.tpElem.clock = NULL; elem.pendState = Event_PendState_WAIT_FOREVER; } /* fill in this task's Event_PendElem */ elem.andMask = andMask; elem.orMask = orMask; pendQ = Event_Instance_State_pendQ(event); /* get task handle */ elem.tpElem.task = Task_self(); /* Atomically check for a match and block if none */ hwiKey = Hwi_disable(); /* check if events are already available */ matchingEvents = Event_checkEvents(event, andMask, orMask); if (matchingEvents != 0) { /* remove Clock object from Clock Q */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_removeI(elem.tpElem.clock); elem.tpElem.clock = NULL; } Hwi_restore(hwiKey); return (matchingEvents);/* yes, then return with matching bits */ } if (timeout == BIOS_NO_WAIT) { Hwi_restore(hwiKey); return (0); /* No match, no wait */ } Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task), Event_A_badContext); /* * Verify that THIS core hasn't already disabled the scheduler * so that the Task_restore() call below will indeed block */ Assert_isTrue((Task_enabled()), Event_A_pendTaskDisabled); /* lock scheduler */ tskKey = Task_disable(); /* only one Task allowed!!! */ Assert_isTrue(Queue_empty(pendQ), Event_A_eventInUse); /* leave a pointer for Task_delete() */ elem.tpElem.task->pendElem = (Task_PendElem *)&(elem); /* add it to Event_PendElem queue */ Queue_enqueue(pendQ, (Queue_Elem *)&elem); Task_blockI(elem.tpElem.task); if (BIOS_clockEnabled && (elem.pendState == Event_PendState_CLOCK_WAIT)) { Clock_startI(elem.tpElem.clock); } Hwi_restore(hwiKey); /* unlock task scheduler and block */ Task_restore(tskKey); /* the calling task will switch out here */ /* Here on unblock due to Event_post or Event_pendTimeout */ hwiKey = Hwi_disable(); /* remove Clock object from Clock Q */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_removeI(elem.tpElem.clock); elem.tpElem.clock = NULL; } elem.tpElem.task->pendElem = NULL; Hwi_restore(hwiKey); /* event match? */ if (elem.pendState != Event_PendState_TIMEOUT) { return (elem.matchingEvents); } else { return (0); /* timeout */ } }
/* * ======== Semaphore_pend ======== */ Bool Semaphore_pend(Semaphore_Object *sem, UInt timeout) { UInt hwiKey, tskKey; Semaphore_PendElem elem; Queue_Handle pendQ; Clock_Struct clockStruct; Log_write3(Semaphore_LM_pend, (IArg)sem, (UArg)sem->count, (IArg)((Int)timeout)); /* * Consider fast path check for count != 0 here!!! */ /* * elem is filled in entirely before interrupts are disabled. * This significantly reduces latency. */ /* add Clock event if timeout is not FOREVER nor NO_WAIT */ if (BIOS_clockEnabled && (timeout != BIOS_WAIT_FOREVER) && (timeout != BIOS_NO_WAIT)) { Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg)&elem; clockParams.startFlag = FALSE; /* will start when necessary, thankyou */ Clock_construct(&clockStruct, (Clock_FuncPtr)Semaphore_pendTimeout, timeout, &clockParams); elem.tpElem.clock = Clock_handle(&clockStruct); elem.pendState = Semaphore_PendState_CLOCK_WAIT; } else { elem.tpElem.clock = NULL; elem.pendState = Semaphore_PendState_WAIT_FOREVER; } pendQ = Semaphore_Instance_State_pendQ(sem); hwiKey = Hwi_disable(); /* check semaphore count */ if (sem->count == 0) { if (timeout == BIOS_NO_WAIT) { Hwi_restore(hwiKey); return (FALSE); } Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task), Semaphore_A_badContext); /* lock task scheduler */ tskKey = Task_disable(); /* get task handle and block tsk */ elem.tpElem.task = Task_self(); /* leave a pointer for Task_delete() */ elem.tpElem.task->pendElem = (Task_PendElem *)&(elem); Task_blockI(elem.tpElem.task); if (((UInt)sem->mode & 0x2) != 0) { /* if PRIORITY bit is set */ Semaphore_PendElem *tmpElem; Task_Handle tmpTask; UInt selfPri; tmpElem = Queue_head(pendQ); selfPri = Task_getPri(elem.tpElem.task); while (tmpElem != (Semaphore_PendElem *)pendQ) { tmpTask = tmpElem->tpElem.task; /* use '>' here so tasks wait FIFO for same priority */ if (selfPri > Task_getPri(tmpTask)) { break; } else { tmpElem = Queue_next((Queue_Elem *)tmpElem); } } Queue_insert((Queue_Elem *)tmpElem, (Queue_Elem *)&elem); } else { /* put task at the end of the pendQ */ Queue_enqueue(pendQ, (Queue_Elem *)&elem); } /* start Clock if appropriate */ if (BIOS_clockEnabled && (elem.pendState == Semaphore_PendState_CLOCK_WAIT)) { Clock_startI(elem.tpElem.clock); } Hwi_restore(hwiKey); Task_restore(tskKey); /* the calling task will block here */ /* Here on unblock due to Semaphore_post or timeout */ if (Semaphore_supportsEvents && (sem->event != NULL)) { /* synchronize Event state */ hwiKey = Hwi_disable(); Semaphore_eventSync(sem->event, sem->eventId, sem->count); Hwi_restore(hwiKey); } /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } elem.tpElem.task->pendElem = NULL; return ((Bool)(elem.pendState)); } else { --sem->count; if (Semaphore_supportsEvents && (sem->event != NULL)) { /* synchronize Event state */ Semaphore_eventSync(sem->event, sem->eventId, sem->count); } Hwi_restore(hwiKey); /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } return (TRUE); } }
/* * ======== 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(); } }
/********************************************************************* * @fn Util_getClockTimeout * * @brief Get the remaining timeout for the clock if it is started * * @param pClock - pointer to clock struct * * @return none */ uint32 Util_getClockTimeout(Clock_Struct *pClock){ Clock_Handle handle = Clock_handle(pClock); return Clock_getTimeout(handle); }
/* * ======== Task_sleep ======== */ Void Task_sleep(UInt32 timeout) { Task_PendElem elem; UInt hwiKey, tskKey; Clock_Struct clockStruct; if (timeout == BIOS_NO_WAIT) { return; } Assert_isTrue((timeout != BIOS_WAIT_FOREVER), Task_A_badTimeout); /* * BIOS_clockEnabled check is here to eliminate Clock module * references in the custom library */ if (BIOS_clockEnabled) { /* add Clock event */ Clock_addI(Clock_handle(&clockStruct), (Clock_FuncPtr)Task_sleepTimeout, timeout, (UArg)&elem); elem.clock = Clock_handle(&clockStruct); } hwiKey = Hwi_disable(); /* * Verify that THIS core hasn't already disabled the scheduler * so that the Task_restore() call below will indeed block */ Assert_isTrue((Task_enabled()), Task_A_sleepTaskDisabled); /* lock scheduler */ tskKey = Task_disable(); /* get task handle and block tsk */ elem.task = Task_self(); Task_blockI(elem.task); /* * BIOS_clockEnabled check is here to eliminate Clock module * references in the custom library */ if (BIOS_clockEnabled) { Clock_startI(elem.clock); } /* Only needed for Task_delete() */ Queue_elemClear(&elem.qElem); elem.task->pendElem = (Ptr)(&elem); Hwi_restore(hwiKey); Log_write3(Task_LM_sleep, (UArg)elem.task, (UArg)elem.task->fxn, (UArg)timeout); /* unlock task scheduler and block */ Task_restore(tskKey); /* the calling task will block here */ /* * BIOS_clockEnabled check is here to eliminate Clock module * references in the custom library */ if (BIOS_clockEnabled) { hwiKey = Hwi_disable(); /* remove Clock object from Clock Q */ Clock_removeI(elem.clock); elem.clock = NULL; Hwi_restore(hwiKey); } elem.task->pendElem = NULL; }