/* * ======== InterruptDsp_intRegister ======== */ Void InterruptDsp_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, Fxn func, UArg arg) { UInt key; Int index; Hwi_Params hwiAttrs; Error_Block eb; InterruptDsp_FxnTable *table; Assert_isTrue(intInfo->intVectorId <= 15, ti_sdo_ipc_Ipc_A_internal); /* init error block */ Error_init(&eb); if (remoteProcId == InterruptDsp_hostProcId) { index = 0; } else if (remoteProcId == InterruptDsp_videoProcId) { index = 1; } else if (remoteProcId == InterruptDsp_vpssProcId) { index = 2; } else if (remoteProcId == InterruptDsp_eveProcId) { index = 3; } else { Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal); return; /* keep Coverity happy */ } /* Disable global interrupts */ key = Hwi_disable(); table = &(InterruptDsp_module->fxnTable[index]); table->func = func; table->arg = arg; InterruptDsp_intClear(remoteProcId, intInfo); if (remoteProcId == InterruptDsp_eveProcId) { /* This should be called only once */ /* Register interrupt for eve internal mailbox */ Hwi_Params_init(&hwiAttrs); hwiAttrs.arg = arg; hwiAttrs.eventId = EVE_MAILBOX_DSPINT; Hwi_create(intInfo->intVectorId, (Hwi_FuncPtr)InterruptDsp_intEveShmStub, &hwiAttrs, &eb); Hwi_enableInterrupt(intInfo->intVectorId); } else { /* Make sure the interrupt only gets plugged once */ InterruptDsp_module->numPlugged++; if (InterruptDsp_module->numPlugged == 1) { /* Register interrupt for system mailbox */ Hwi_Params_init(&hwiAttrs); hwiAttrs.arg = arg; hwiAttrs.eventId = MAILBOX_DSPINT; Hwi_create(intInfo->intVectorId, (Hwi_FuncPtr)InterruptDsp_intShmStub, &hwiAttrs, &eb); Hwi_enableInterrupt(intInfo->intVectorId); } } /* Enable the mailbox interrupt to the DSP */ InterruptDsp_intEnable(remoteProcId, intInfo); /* Restore global interrupts */ Hwi_restore(key); }
/* * ======== PWMTiva_open ======== * @pre Function assumes that the handle is not NULL */ PWM_Handle PWMTiva_open(PWM_Handle handle, PWM_Params *params) { unsigned int key; uint8_t cyclesPerMicroSec; uint8_t prescalar; uint16_t pwmGenerator; uint16_t *pwmGenPeriod; uint32_t pwmGenOptions; uint32_t prescalarRegVal; uint32_t tempPeriod; Types_FreqHz freq; PWMTiva_Object *object = handle->object; PWMTiva_HWAttrs const *hwAttrs = handle->hwAttrs; BIOS_getCpuFreq(&freq); cyclesPerMicroSec = freq.lo / 1000000; if(params == NULL) { params = (PWM_Params *) &PWM_defaultParams; } /* Assert if period is too large for peripheral */ tempPeriod = params->period * cyclesPerMicroSec; Assert_isTrue(tempPeriod <= (PWMTiva_MAX_MATCH_VALUE * PWMTiva_MAX_PRESCALAR), NULL); PWMTiva_calculatePrescalar(tempPeriod, &prescalarRegVal, &prescalar); /* Get the PWM generator and it's period */ pwmGenerator = hwAttrs->pwmOutput & PWM_GEN_MASK; pwmGenPeriod = (object->pwmStatus)->genPeriods + ((hwAttrs->pwmOutput / PWM_OUT_0) - 1); key = Hwi_disable(); /* Verify if PWM peripheral has been initialized by another PWM instance */ if ((object->pwmStatus)->cyclesPerMicroSec) { /* * The PWM peripheral has already been initialized. * * Ensure the instance has not been opened and the peripheral prescalar * is >= the prescalar required for new instance. */ if (((object->pwmStatus)->activeOutputs & object->pwmOutputBit) || ((object->pwmStatus)->prescalar < prescalar)) { Hwi_restore(key); return (NULL); } /* Check if the other output on the generator is active */ if (*pwmGenPeriod) { /* Ensure period are the same */ if (params->period != *pwmGenPeriod) { Hwi_restore(key); return (NULL); } /* Get PWM generator options & ensure options are the same */ pwmGenOptions = (HWREG(hwAttrs->baseAddr + pwmGenerator) & ~PWM_X_CTL_ENABLE); if (hwAttrs->pwmGenOpts != pwmGenOptions) { Hwi_restore(key); return (NULL); } } } else { /* PWM has not been initialized by another instance */ (object->pwmStatus)->prescalar = prescalar; (object->pwmStatus)->cyclesPerMicroSec = cyclesPerMicroSec; PWMTiva_setPrescalar(hwAttrs->baseAddr, prescalarRegVal); } /* PWM can be opened safely, mark as being used */ (object->pwmStatus)->activeOutputs |= object->pwmOutputBit; if (!(*pwmGenPeriod)) { /* Initialize PWM signal generator */ *pwmGenPeriod = params->period; PWMGenConfigure(hwAttrs->baseAddr, pwmGenerator, hwAttrs->pwmGenOpts); PWMGenPeriodSet(hwAttrs->baseAddr, pwmGenerator, (tempPeriod / prescalar)); } Hwi_restore(key); /* * Set PWM duty to initial value (not 0 or period) - required when * inverting output polarity to generate a duty equal to 0 or * period. See comments in PWMTiva_setDuty for more information. */ object->pwmDuty = 1; object->dutyMode = params->dutyMode; /* Set PWM generator outputs to 0 initially */ PWMOutputInvert(hwAttrs->baseAddr, object->pwmOutputBit, params->polarity); PWMTiva_setDuty(handle, 0); PWMOutputState(hwAttrs->baseAddr, object->pwmOutputBit, true); PWMGenEnable(hwAttrs->baseAddr, pwmGenerator); Log_print2(Diags_USER1, "PWM:(%p) opened; period set to: %d", (UArg) handle, params->period); return (handle); }
/* * ======== Task_Instance_finalize ======== */ Void Task_Instance_finalize(Task_Object *tsk, Int status) { #ifndef ti_sysbios_knl_Task_DISABLE_ALL_HOOKS Int i, cnt; #endif UInt taskKey, hwiKey; /* * Task's can only be deleted from main and task threads. * Running Tasks can not be deleted. */ if (status == 0) { taskKey = Task_disable(); /* * Bar users from calling Task_delete() on terminated tasks * if deleteTerminatedTasks is enabled. */ if ((Task_deleteTerminatedTasks == TRUE) && (Task_getMode(tsk) == Task_Mode_TERMINATED) && (tsk->readyQ == Task_Module_State_terminatedQ())) { Error_raise(NULL, Task_E_deleteNotAllowed, tsk, 0); } Assert_isTrue((Task_getMode(tsk) != Task_Mode_RUNNING), Task_A_badTaskState); Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Main) || (BIOS_getThreadType() == BIOS_ThreadType_Task), Task_A_badThreadType); hwiKey = Hwi_disable(); if (tsk->mode == Task_Mode_READY) { /* remove task from its ready list */ Queue_remove((Queue_Elem *)tsk); /* if last task in readyQ, remove corresponding bit in curSet */ if (Queue_empty(tsk->readyQ)) { Task_module->curSet &= ~tsk->mask; } /* * if task was made ready by a pend timeout but hasn't run yet * then its clock object is still on the Clock service Q. */ if (tsk->pendElem != NULL) { if (BIOS_clockEnabled && tsk->pendElem->clock) { Clock_removeI(tsk->pendElem->clock); } } } if (tsk->mode == Task_Mode_BLOCKED) { Assert_isTrue(tsk->pendElem != NULL, Task_A_noPendElem); /* Seemingly redundant test in case Asserts are disabled */ if (tsk->pendElem != NULL) { Queue_remove(&(tsk->pendElem->qElem)); if (BIOS_clockEnabled && tsk->pendElem->clock) { Clock_removeI(tsk->pendElem->clock); } } } if (tsk->mode == Task_Mode_TERMINATED) { /* remove task from terminated task list */ Queue_remove((Queue_Elem *)tsk); } else { Task_processVitalTaskFlag(tsk); } Hwi_restore(hwiKey); Task_restore(taskKey); } /* return if failed before allocating stack */ if (status == 1) { return; } if (BIOS_runtimeCreatesEnabled) { /* free stack if it was allocated dynamically */ if (tsk->stackHeap != (xdc_runtime_IHeap_Handle)(-1)) { Memory_free(tsk->stackHeap, tsk->stack, tsk->stackSize); } } /* return if failed to allocate Hook Env */ if (status == 2) { return; } /* status == 0 or status == 3 - in both cases create hook was called */ #ifndef ti_sysbios_knl_Task_DISABLE_ALL_HOOKS /* free any allocated Hook Envs */ if (Task_hooks.length > 0) { if (status == 0) { cnt = Task_hooks.length; } else { cnt = status - 3; /* # successful createFxn() calls */ } /* * only call deleteFxn() if createFxn() was successful */ for (i = 0; i < cnt; i++) { if (Task_hooks.elem[i].deleteFxn != NULL) { Task_hooks.elem[i].deleteFxn(tsk); } } Memory_free(Task_Object_heap(), tsk->hookEnv, Task_hooks.length * sizeof (Ptr)); } #endif }
/* * ======== Timer_Instance_init ======== * 1. Select timer based on id * 2. Mark timer as in use * 3. Save timer handle if necessary (needed by TimestampProvider on 64). * 4. Init obj using params * 5. Create Hwi if tickFxn !=NULL * 6. Timer_init() * 7. Timer configuration (wrt emulation, external frequency etc) * 8. Timer_setPeriod() * 9. Timer_start() */ Int Timer_Instance_init(Timer_Object *obj, Int id, Timer_FuncPtr tickFxn, const Timer_Params *params, Error_Block *eb) { UInt key; Int i, status; Hwi_Params hwiParams; UInt tempId = 0xffff; /* make sure id is not greater than number of 32-bit timer devices */ if (id >= Timer_numTimerDevices ) { if (id != Timer_ANY) { Error_raise(eb, Timer_E_invalidTimer, id, 0); return (1); } } key = Hwi_disable(); if (id == Timer_ANY) { for (i = 0; i < Timer_numTimerDevices; i++) { if ((Timer_anyMask & (1 << i)) && (Timer_module->availMask & (1 << i))) { Timer_module->availMask &= ~(1 << i); tempId = i; break; } } } else if (Timer_module->availMask & (1 << id)) { Timer_module->availMask &= ~(1 << id); tempId = id; } Hwi_restore(key); obj->staticInst = FALSE; if (tempId == 0xffff) { Error_raise(eb, Timer_E_notAvailable, id, 0); return (2); } else { obj->id = tempId; } if (params->intNum == -1) { if (Timer_module->device[obj->id].intNum == -1) { Error_raise(eb, Timer_E_badIntNum, params->intNum, 0); } } Timer_module->handles[obj->id] = obj; /* initialize the timer state object */ Timer_initObj(obj, tickFxn, params); /* create the Hwi object if function is specified */ if (obj->tickFxn != NULL) { if (params->hwiParams) { Hwi_Params_copy(&hwiParams, params->hwiParams); } else { Hwi_Params_init(&hwiParams); } hwiParams.eventId = obj->eventId; hwiParams.arg = (UArg)obj; obj->hwi = Hwi_create(obj->intNum, Timer_stub, &hwiParams, eb); if (obj->hwi == NULL) { return (4); } } else { obj->hwi = NULL; } status = Timer_postInit(obj, eb); if (status) { return (status); } if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } return (0); }
/* * ======== NotifyDriverShm_sendEvent ======== */ Int NotifyDriverShm_sendEvent(NotifyDriverShm_Object *obj, UInt32 eventId, UInt32 payload, Bool waitClear) { NotifyDriverShm_EventEntry *eventEntry; UInt32 i; UInt sysKey; eventEntry = EVENTENTRY(obj->otherEventChart, obj->eventEntrySize, eventId); /* Check whether driver on other processor is initialized */ if (obj->cacheEnabled) { Cache_inv(obj->otherProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } if (obj->otherProcCtrl->recvInitStatus != NotifyDriverShm_INIT_STAMP) { /* * This may be used for polling till the other driver is ready, so * do not assert or error */ return (Notify_E_NOTINITIALIZED); } /* Check to see if the remote event is enabled */ if (!TEST_BIT(obj->otherProcCtrl->eventEnableMask, eventId)) { return (Notify_E_EVTDISABLED); } /* Check to see if the remote event is registered */ if (!TEST_BIT(obj->otherProcCtrl->eventRegMask, eventId)) { return (Notify_E_EVTNOTREGISTERED); } if (waitClear) { i = 0; if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * The system gate is needed to ensure that checking eventEntry->flag * is atomic with the eventEntry modifications (flag/payload). */ sysKey = Hwi_disable(); /* Wait for completion of previous event from other side. */ while ((eventEntry->flag != NotifyDriverShm_DOWN)) { /* * Leave critical section protection. Create a window * of opportunity for other interrupts to be handled. */ Hwi_restore(sysKey); i++; if ((i != (UInt32)-1) && (i == ti_sdo_ipc_Notify_sendEventPollCount)) { return (Notify_E_TIMEOUT); } if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Re-enter the system gate */ sysKey = Hwi_disable(); } } else { /* * The system gate is needed to ensure that checking eventEntry->flag * is atomic with the eventEntry modifications (flag/payload). */ sysKey = Hwi_disable(); } /* Set the event bit field and payload.*/ eventEntry->payload = payload; eventEntry->flag = NotifyDriverShm_UP; if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* Send an interrupt to the Remote Processor */ NotifyDriverShm_InterruptProxy_intSend(obj->remoteProcId, &(obj->intInfo), eventId); /* must not restore interrupts before sending the interrupt */ Hwi_restore(sysKey); return (Notify_S_SUCCESS); }
// ----------------------------------------------------------------------------- //! \brief LCD main event processing loop. //! //! \return void // ----------------------------------------------------------------------------- static void LCDTask_process(void) { uint16_t timeout_counter = 0; uint8_t last_motion_state = 0; int8_t last_touch_value = -1; /* Forever loop */ for (;; ) { if (LCDTask_State == LCDTASK_OFF_STATE) { Semaphore_pend(lcdSem, BIOS_WAIT_FOREVER); } // Capture the ISR events flags now within a critical section. // We do this to avoid possible race conditions where the ISR is // modifying the event mask while the task is read/writing it. UInt hwiKey = Hwi_disable(); UInt taskKey = Task_disable(); LCDTask_events = MOTION_ISR_EVENT_FLAGS; MOTION_ISR_EVENT_FLAGS = 0; Task_restore(taskKey); Hwi_restore(hwiKey); // motion_state = PIN_getInputValue(Board_LCD_MOTION); // if (motion_state != last_motion_state) { // if (motion_state) { // LCDTask_events = LCDTASK_MOTION_SENSED_EVENT; // } else { // LCDTask_events = LCDTASK_MOTION_GONE_EVENT; // } // last_motion_state = motion_state; // } if(LCDTask_events & LCDTASK_MOTION_SENSED_EVENT) { if (LCDTask_State == LCDTASK_OFF_STATE) { LCDTask_turnOnLCD(); LCDTask_State = LCDTASK_TURNING_ON_STATE; } // If only a start to motion was detected, // Then we want to disable the timeout timeout_counter = 0; } if (LCDTask_events & LCDTASK_MOTION_GONE_EVENT) { //if (LCDTask_events & LCDTASK_MOTION_SENSED_EVENT) { LCDTask_State = LCDTASK_WAIT_STATE; // Since we've sensed no more motion start timeout // Start/reset count down to power off timeout_counter = 300; } if (LCDTask_State > LCDTASK_OFF_STATE) { // Check for presses int8_t touch = LCDTask_getTouchPoint(); if (touch != last_touch_value) { if (touch>-1) { // Add some sort of feedback ILI9341_fillRect(4+length*20,4,10,10,ILI9341_WHITE); // Check to see if this is a command press if (touch > 9) { // Process command if (touch == 10) { // Lock the door // sendLockRequest(); } else if (touch == 12) { // Process keycode (enter) if (length > 0) { // Send keycode for checking // checkKeyCode(keybuf,length); // Reset buffer ILI9341_fillRect(4,4,20*length + 10,10,ILI9341_BLACK); length = 0; } } } else { // Add touch to buffer if (length < LCD_MAX_KEYLENGTH) { keybuf[length++] = touch; } } } last_touch_value = touch; } } if (LCDTask_State != LCDTASK_OFF_STATE) { // Check for timeout if (timeout_counter > 0) { timeout_counter--; if (timeout_counter==0) { LCDTask_State = LCDTASK_OFF_STATE; LCDTask_turnOffLCD(); length = 0; } } delay_ms(10); } } }
/* * ======== Timer_checkFreq ======== */ Void Timer_checkFreq(Timer_Object *obj) { UInt key; UInt32 timerCountStart, timerCountEnd, tsCountStart, tsCountEnd; UInt32 deltaTs, deltaCnt; Types_FreqHz timerFreq, timestampFreq; UInt freqRatio; UInt32 actualFrequency; Timer_Object tempObj; /* * Make a temporary copy of 'obj' and modify it to be used for the timer * frequency check. Set the period to Timer_MAX_PERIOD to ensure that * the timer does not roll over while performing the check. */ memcpy((void *)&tempObj, (void *)obj, sizeof(Timer_Object)); tempObj.period = Timer_MAX_PERIOD; tempObj.periodType = Timer_PeriodType_COUNTS; tempObj.runMode = Timer_RunMode_ONESHOT; tempObj.startMode = Timer_StartMode_USER; /* Initialize the timer registers */ Timer_deviceConfig(&tempObj, NULL); /* Get the frequencies of the Timer and the Timestamp */ Timer_getFreq(&tempObj, &timerFreq); Timestamp_getFreq(×tampFreq); /* Assume that timer frequency is less than 2^32 Hz */ Assert_isTrue(timestampFreq.hi == 0 && timerFreq.hi == 0, NULL); freqRatio = timestampFreq.lo / timerFreq.lo; key = Hwi_disable(); /* * Warning: halting the core between Timer_start and the point of * code indicated below can cause the frequency check to fail. This is * is because the DMTimer will continue to run while this core is halted, * this causing the ratio between timer counts to change */ Timer_start(&tempObj); /* Record the initial timer & timestamp counts */ timerCountStart = Timer_getCount(&tempObj); tsCountStart = Timestamp_get32(); /* Wait for 'TIMERCOUNTS' timer counts to elapse */ while (Timer_getCount(&tempObj) < timerCountStart + TIMERCOUNTS); timerCountEnd = Timer_getCount(&tempObj); /* Record the timestamp ticks that have elapsed during the above loop */ tsCountEnd = Timestamp_get32(); /* End of code segment where core should not be halted */ Hwi_restore(key); deltaTs = tsCountEnd - tsCountStart; deltaCnt = timerCountEnd - timerCountStart; /* Check the timer frequency. Allow a margin of error. */ if (((deltaTs / deltaCnt) > freqRatio * 2) || ((deltaTs / deltaCnt) < freqRatio / 2)) { actualFrequency = ((UInt64)timestampFreq.lo * (UInt64)deltaCnt) / (UInt64)deltaTs; Error_raise(NULL, Timer_E_freqMismatch, Timer_module->intFreqs[obj->id].lo, actualFrequency); } }
/*! * @brief Function to start a transfer from the CC26XX I2C peripheral specified * by the I2C handle. * * This function is used for both transmitting and receiving data. If the I2C * is configured in ::I2C_MODE_CALLBACK mode, it is possible to chain transactions * together and receive a callback when all transactions are done. * When active I2C transactions exist, the device might enter idle, not standby. * * @pre I2CCC26XX_open() has to be called first. * Calling context: Hwi and Swi (only if using ::I2C_MODE_CALLBACK), Task * * @param handle An I2C_Handle returned by I2C_open() * * @param transaction Pointer to a I2C transaction object * * @return TRUE on successful transfer. * FALSE on an error, such as a I2C bus fault. * * @note The generic I2C API should be used when accessing the I2CCC26XX. * * @sa I2CCC26XX_open(), I2C_transfer() */ bool I2CCC26XX_transfer(I2C_Handle handle, I2C_Transaction *transaction) { bool ret = false; UInt key; I2CCC26XX_Object *object; I2CCC26XX_HWAttrs const *hwAttrs; /* Get the pointer to the object and hwAttrs */ object = handle->object; hwAttrs = handle->hwAttrs; /* Check if anything needs to be written or read */ if ((!transaction->writeCount) && (!transaction->readCount)) { /* Nothing to write or read */ return (ret); } if (object->transferMode == I2C_MODE_CALLBACK) { /* Check if a transfer is in progress */ key = Hwi_disable(); if (object->headPtr) { /* Transfer in progress */ /* * Update the message pointed by the tailPtr to point to the next * message in the queue */ object->tailPtr->nextPtr = transaction; /* Update the tailPtr to point to the last message */ object->tailPtr = transaction; /* I2C is still being used */ Hwi_restore(key); return (true); } else { /* Store the headPtr indicating I2C is in use */ object->headPtr = transaction; object->tailPtr = transaction; } Hwi_restore(key); } /* Set standby disallow constraint. */ threadSafeStdbyDisSet(); /* Acquire the lock for this particular I2C handle */ Semaphore_pend(Semaphore_handle(&(object->mutex)), BIOS_WAIT_FOREVER); /* * I2CCC26XX_primeTransfer is a longer process and * protection is needed from the I2C interrupt */ Hwi_disableInterrupt(hwAttrs->intNum); I2CCC26XX_primeTransfer(handle, transaction); Hwi_enableInterrupt(hwAttrs->intNum); if (object->transferMode == I2C_MODE_BLOCKING) { Log_print1(Diags_USER1, "I2C:(%p) Pending on transferComplete semaphore", hwAttrs->baseAddr); /* * Wait for the transfer to complete here. * It's OK to block from here because the I2C's Hwi will unblock * upon errors */ Semaphore_pend(Semaphore_handle(&(object->transferComplete)), BIOS_WAIT_FOREVER); /* Release standby disallow constraint. */ threadSafeStdbyDisRelease(); Log_print1(Diags_USER1, "I2C:(%p) Transaction completed", hwAttrs->baseAddr); /* Hwi handle has posted a 'transferComplete' check for Errors */ if (object->mode == I2CCC26XX_IDLE_MODE) { Log_print1(Diags_USER1, "I2C:(%p) Transfer OK", hwAttrs->baseAddr); ret = true; } } else { /* Always return true if in Asynchronous mode */ ret = true; } /* Release the lock for this particular I2C handle */ Semaphore_post(Semaphore_handle(&(object->mutex))); /* Return status */ return (ret); }
/* * ======== InterruptEve_intRegister ======== */ Void InterruptEve_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, Fxn func, UArg arg) { UInt key; Int index; Hwi_Params hwiAttrs; Error_Block eb; InterruptEve_FxnTable *table; Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors, ti_sdo_ipc_Ipc_A_internal); /* Assert that our MultiProc id is set correctly */ Assert_isTrue((InterruptEve_eveProcId == MultiProc_self()), ti_sdo_ipc_Ipc_A_internal); /* init error block */ Error_init(&eb); if (remoteProcId == InterruptEve_hostProcId) { index = 0; } else if ((remoteProcId == InterruptEve_videoProcId) || (remoteProcId == InterruptEve_vpssProcId)) { index = 1; } else if (remoteProcId == InterruptEve_dspProcId) { index = 2; } else { Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal); } /* Disable global interrupts */ key = Hwi_disable(); table = &(InterruptEve_module->fxnTable[index]); table->func = func; table->arg = arg; InterruptEve_intClear(remoteProcId, intInfo); /* Make sure the interrupt only gets plugged once */ InterruptEve_module->numPlugged++; if (InterruptEve_module->numPlugged == 1) { /* Register interrupt to remote processor */ Hwi_Params_init(&hwiAttrs); hwiAttrs.arg = arg; hwiAttrs.vectorNum = intInfo->intVectorId; Hwi_create(MAILBOX_EVEINT, (Hwi_FuncPtr)InterruptEve_intShmStub, &hwiAttrs, &eb); Hwi_enableInterrupt(MAILBOX_EVEINT); } /* enable the mailbox and Hwi */ InterruptEve_intEnable(remoteProcId, intInfo); /* Restore global interrupts */ Hwi_restore(key); }
/* * ======== GateDualCore_leave ======== */ Void GateDualCore_leave(GateDualCore_Object *obj, IArg key) { *obj->gateBytePtr = 0; Hwi_restore(key); }
/*! * @brief Function to initialize a given I2C CC26XX peripheral specified by the * particular handle. The parameter specifies which mode the I2C * will operate. * * After calling the open function, the I2C is enabled. If there is no active * I2C transactions, the device can enter standby. * * @pre The I2CCC26XX_Config structure must exist and be persistent before this * function can be called. I2CCC26XX has been initialized with I2CCC26XX_init(). * Calling context: Task * * @param handle An I2C_Handle * * @param params Pointer to a parameter block, if NULL it will use default values. * * @return A I2C_Handle on success, or a NULL on an error or if it has been * already opened. * * @note The generic I2C API should be used when accessing the I2CCC26XX. * * @sa I2CCC26XX_close(), I2CCC26XX_init(), I2C_open(), I2C_init() */ I2C_Handle I2CCC26XX_open(I2C_Handle handle, I2C_Params *params) { union { Hwi_Params hwiParams; Semaphore_Params semParams; } paramsUnion; UInt key; I2C_Params i2cParams; I2CCC26XX_Object *object; I2CCC26XX_HWAttrs const *hwAttrs; /* Get the pointer to the object and hwAttrs */ object = handle->object; hwAttrs = handle->hwAttrs; /* Determine if the device index was already opened */ key = Hwi_disable(); if(object->isOpen == true){ Hwi_restore(key); return (NULL); } /* Mark the handle as being used */ object->isOpen = true; Hwi_restore(key); /* Store the I2C parameters */ if (params == NULL) { /* No params passed in, so use the defaults */ I2C_Params_init(&i2cParams); params = &i2cParams; } /* Configure the IOs early to ensure allocation is allowed (PIN driver and IO config setup only).*/ if (I2CCC26XX_initIO(handle, params->custom)) { /* If initialization and allocation of IOs failed, log error and return NULL pointer */ Log_print1(Diags_USER1, "I2C: Pin allocation failed, open did not succeed (baseAddr:0x%x)", hwAttrs->baseAddr); return (NULL); } /* Save parameters */ object->transferMode = params->transferMode; object->transferCallbackFxn = params->transferCallbackFxn; object->bitRate = params->bitRate; /* Create Hwi object for this I2C peripheral */ Hwi_Params_init(¶msUnion.hwiParams); paramsUnion.hwiParams.arg = (UArg)handle; Hwi_construct(&(object->hwi), hwAttrs->intNum, I2CCC26XX_hwiFxn, ¶msUnion.hwiParams, NULL); /* * Create thread safe handles for this I2C peripheral * Semaphore to provide exclusive access to the I2C peripheral */ Semaphore_Params_init(¶msUnion.semParams); paramsUnion.semParams.mode = Semaphore_Mode_BINARY; Semaphore_construct(&(object->mutex), 1, ¶msUnion.semParams); /* * Store a callback function that posts the transfer complete * semaphore for synchronous mode */ if (object->transferMode == I2C_MODE_BLOCKING) { /* * Semaphore to cause the waiting task to block for the I2C * to finish */ Semaphore_construct(&(object->transferComplete), 0, ¶msUnion.semParams); /* Store internal callback function */ object->transferCallbackFxn = I2CCC26XX_blockingCallback; } else { /* Check to see if a callback function was defined for async mode */ Assert_isTrue(object->transferCallbackFxn != NULL, NULL); } /* Specify the idle state for this I2C peripheral */ object->mode = I2CCC26XX_IDLE_MODE; /* Clear the head pointer */ object->headPtr = NULL; object->tailPtr = NULL; /* Power on the I2C module */ Power_setDependency(hwAttrs->powerMngrId); /* Initialize the I2C hardware module */ I2CCC26XX_initHw(handle); /* Register notification functions */ Power_registerNotify(&object->i2cPostObj, Power_AWAKE_STANDBY, (Fxn)i2cPostNotify, (UInt32)handle, NULL ); Log_print1(Diags_USER1, "I2C: Object created 0x%x", hwAttrs->baseAddr); /* Return the address of the handle */ return (handle); }
/* * ======== Notify_unregisterEvent ======== */ Int Notify_unregisterEvent(UInt16 procId, UInt16 lineId, UInt32 eventId, Notify_FnNotifyCbck fnNotifyCbck, UArg cbckArg) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; UInt sysKey, modKey; ti_sdo_ipc_Notify_Object *obj; List_Handle eventList; ti_sdo_ipc_Notify_EventListener *listener; UInt count = 0; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); modKey = Gate_enterModule(); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); eventList = List_Object_get(obj->eventList, strippedEventId); if (List_empty(eventList)) { return (Notify_E_NOTFOUND); } /* Get the first listener on the list */ listener = (ti_sdo_ipc_Notify_EventListener *)List_next(eventList, NULL); while (listener != NULL) { count++; if (listener->callback.fnNotifyCbck == (Fxn)fnNotifyCbck && listener->callback.cbckArg == cbckArg ) { break; /* found a match! */ } listener = (ti_sdo_ipc_Notify_EventListener *) List_next(eventList, (List_Elem *)listener); } if (listener == NULL) { /* Event listener not found */ status = Notify_E_NOTFOUND; } else { if (count == 1 && List_next(eventList, (List_Elem *)listener) == NULL) { /* * If only one element counted so far and the List_next returns * NULL, the list will be empty after unregistering. Therefore, * unregister the callback function. */ status = Notify_unregisterEventSingle(procId, lineId, eventId); /* unregisterEvent should always suceed */ Assert_isTrue(status == Notify_S_SUCCESS, ti_sdo_ipc_Notify_A_internal); /* No need to protect the list removal: the event's unregistered */ List_remove(eventList, (List_Elem *)listener); } else { /* * Need to atomically remove from the list using the system gate * because Notify_exec might preempt List_remove (the event is * still registered) */ sysKey = Hwi_disable(); List_remove(eventList, (List_Elem *)listener); Hwi_restore(sysKey); } /* Free the memory alloc'ed for the event listener */ Memory_free(ti_sdo_ipc_Notify_Object_heap(), listener, sizeof(ti_sdo_ipc_Notify_EventListener)); status = Notify_S_SUCCESS; } Gate_leaveModule(modKey); return (status); }
/* * ======== Notify_sendEvent ======== */ Int Notify_sendEvent(UInt16 procId, UInt16 lineId, UInt32 eventId, UInt32 payload, Bool waitClear) { UInt32 strippedEventId = (eventId & 0xFFFF); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(procId); Int status; ti_sdo_ipc_Notify_Object *obj; UInt sysKey; Assert_isTrue(procId < ti_sdo_utils_MultiProc_numProcessors && lineId < ti_sdo_ipc_Notify_numLines, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(strippedEventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Notify_A_invArgument); Assert_isTrue(ISRESERVED(eventId), ti_sdo_ipc_Notify_A_reservedEvent); obj = (ti_sdo_ipc_Notify_Object *) Notify_module->notifyHandles[clusterId][lineId]; Assert_isTrue(obj != NULL, ti_sdo_ipc_Notify_A_notRegistered); if (procId != MultiProc_self()) { /* Send a remote event */ status = INotifyDriver_sendEvent(obj->driverHandle, strippedEventId, payload, waitClear); } else { /* * The check agaist non-NULL fnNotifyCbCk must be atomic with * Notify_exec so Notify_exec doesn't encounter a null callback. */ sysKey = Hwi_disable(); /* * If nesting == 0 (the driver is enabled) and the event is enabled, * send the event */ if (obj->callbacks[strippedEventId].fnNotifyCbck == NULL) { /* No callbacks are registered locally for the event. */ status = Notify_E_EVTNOTREGISTERED; } else if (obj->nesting != 0) { /* Driver is disabled */ status = Notify_E_FAIL; } else if (!TEST_BIT (Notify_module->localEnableMask, strippedEventId)){ /* Event is disabled */ status = Notify_E_EVTDISABLED; } else { /* Execute the callback function registered to the event */ ti_sdo_ipc_Notify_exec(obj, strippedEventId, payload); status = Notify_S_SUCCESS; } Hwi_restore(sysKey); } return (status); }
/* * ======== PWMTiva_setDuty ======== * @pre Function assumes that handle is not NULL */ void PWMTiva_setDuty(PWM_Handle handle, uint32_t duty) { unsigned int key; uint8_t maxDutySet; uint16_t period; uint16_t pwmGenerator; uint16_t pwmGenPeriod; uint32_t newDuty; PWMTiva_Object *object = handle->object; PWMTiva_HWAttrs const *hwAttrs = handle->hwAttrs; /* Get the PWM generator, generator period and instance output bit */ pwmGenerator = hwAttrs->pwmOutput & PWM_GEN_MASK; pwmGenPeriod = *(object->pwmStatus)->genPeriods + ((hwAttrs->pwmOutput / PWM_OUT_0) - 1); /* Get the generator period */ period = PWMGenPeriodGet(hwAttrs->baseAddr, pwmGenerator); switch(object->dutyMode) { case PWM_DUTY_COUNTS: /* Duty specified as PWM timer counts */ Assert_isTrue(duty <= period, NULL); maxDutySet = (duty >= period); newDuty = (duty && duty < period) ? duty : period; break; case PWM_DUTY_TIME: /* Duty is specified in microseconds */ Assert_isTrue(duty <= pwmGenPeriod, NULL); maxDutySet = (duty >= pwmGenPeriod); newDuty = (duty * (object->pwmStatus)->cyclesPerMicroSec) / (object->pwmStatus)->prescalar; if (!(newDuty) || newDuty > period) { newDuty = period; } break; case PWM_DUTY_SCALAR: /* Duty specified as a number [0 - 65535] scaled to the period */ Assert_isTrue(duty <= PWMTiva_MAX_MATCH_VALUE, NULL); maxDutySet = (duty >= PWMTiva_MAX_MATCH_VALUE); newDuty = period; if (duty && duty < PWMTiva_MAX_MATCH_VALUE) { newDuty = (newDuty * 100) / PWMTiva_MAX_MATCH_VALUE; newDuty = (newDuty * duty) / 100; if (!newDuty) { newDuty++; } } break; default: Log_print1(Diags_USER1, "PWM: (%p) unsupported PWM duty mode; duty unchanged", (UArg) handle); return; } key = Hwi_disable(); /* * The PWM peripheral cannot generate a duty of 0 when in count down mode * or a duty equal to period when in count up-down mode. To generate a 0 * duty when in count down mode, the PWM duty is set * to the period value (output remains active) and output polarity is * inverted. Additionally, if the output is changed from 0 (to a non-zero * value) the PWM output polarity must be inverted again. * * Likewise, to generate a duty equal to the period when in count up-down * mode, the PWM duty is set to the period value and the output polarity is * inverted. * * The code below determines if the PWM is in count down or count up-down * mode and inverts the PWM output polarity if necessary. * For more details refer to the device specific datasheet and the following * E2E post: * http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/471/t/137249.aspx * http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/354826.aspx */ if (HWREG(hwAttrs->baseAddr + pwmGenerator) & PWM_GEN_MODE_UP_DOWN) { /* * PWM in count up/down mode - invert output if setting duty to or * changing from MAX */ if ((maxDutySet && object->pwmDuty != period) || ((!maxDutySet) && object->pwmDuty == period)) { HWREG(hwAttrs->baseAddr + PWM_O_INVERT) ^= object->pwmOutputBit; } } else { /* * PWM in count down mode - invert output if setting duty to or * changing from 0 */ if (((!duty) && object->pwmDuty) || (duty && (!object->pwmDuty))) { HWREG(hwAttrs->baseAddr + PWM_O_INVERT) ^= object->pwmOutputBit; } } object->pwmDuty = (duty) ? newDuty : 0; PWMPulseWidthSet(hwAttrs->baseAddr, hwAttrs->pwmOutput, newDuty); Hwi_restore(key); Log_print2(Diags_USER2, "PWM: (%p) duty set to: %d", (UArg) handle, duty); }
/* * ======== InterruptHost_intRegister ======== */ Void InterruptHost_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, Fxn func, UArg arg) { UInt key; Int index; Error_Block eb; InterruptHost_FxnTable *table; /* init error block */ Error_init(&eb); if (remoteProcId == InterruptHost_dspProcId) { index = 0; } else if (remoteProcId == InterruptHost_videoProcId) { index = 1; } else if (remoteProcId == InterruptHost_vpssProcId) { index = 2; } else if (remoteProcId == InterruptHost_eveProcId) { index = 3; } else { Assert_isTrue(FALSE, ti_sdo_ipc_Ipc_A_internal); return; /* should never get here, but keep Coverity happy */ } /* Disable global interrupts */ key = Hwi_disable(); table = &(InterruptHost_module->fxnTable[index]); table->func = func; table->arg = arg; InterruptHost_intClear(remoteProcId, intInfo); if (remoteProcId == InterruptHost_eveProcId) { /* Register interrupt for eve mailbox */ Hwi_create(EVE_MAILBOX_HOSTINT, (Hwi_FuncPtr)InterruptHost_intEveShmStub, NULL, &eb); Hwi_enableInterrupt(EVE_MAILBOX_HOSTINT); } else { /* Make sure the interrupt only gets plugged once */ InterruptHost_module->numPlugged++; if (InterruptHost_module->numPlugged == 1) { /* Register interrupt for system mailbox */ Hwi_create(MAILBOX_HOSTINT, (Hwi_FuncPtr)InterruptHost_intShmStub, NULL, &eb); Hwi_enableInterrupt(MAILBOX_HOSTINT); } } /* Enable the mailbox interrupt to the HOST core */ InterruptHost_intEnable(remoteProcId, intInfo); /* Restore global interrupts */ Hwi_restore(key); }
/* * ======== GateMutexPri_leave ======== * Only releases the gate if key == FIRST_ENTER. */ Void GateMutexPri_leave(GateMutexPri_Object *obj, IArg key) { UInt tskKey, hwiKey; Task_Handle owner; Task_Handle newOwner; Task_PendElem *elem; Queue_Handle pendQ; pendQ = GateMutexPri_Instance_State_pendQ(obj); owner = Task_self(); /* * Prior to tasks starting, Task_self() will return NULL. * Simply return here as, by definition, there is * is only one thread running at this time. */ if (owner == NULL) { return; } /* * Gate may only be called from task context, so Task_disable is sufficient * protection. */ tskKey = Task_disable(); /* Assert that caller is gate owner. */ // ASSERT(owner == obj->owner); /* If this is not the outermost call to leave, just return. */ if (key != FIRST_ENTER) { Task_restore(tskKey); return; } /* * Restore this task's priority. The if-test is worthwhile because of the * cost of a call to setPri. */ if (obj->ownerOrigPri != Task_getPri(owner)) { Task_setPri(owner, obj->ownerOrigPri); } /* If the list of waiting tasks is not empty... */ if (!Queue_empty(pendQ)) { /* * Get the next owner from the front of the queue (the task with the * highest priority of those waiting on the queue). */ elem = (Task_PendElem *)Queue_dequeue(pendQ); newOwner = elem->task; /* Setup the gate. */ obj->owner = newOwner; obj->ownerOrigPri = Task_getPri(newOwner); /* Task_unblockI must be called with interrupts disabled. */ hwiKey = Hwi_disable(); Task_unblockI(newOwner, hwiKey); Hwi_restore(hwiKey); } /* If the gate is to be posted... */ else { obj->mutexCnt = 1; } Task_restore(tskKey); }
// ----------------------------------------------------------------------------- //! \brief Critical section exit. Enables Tasks and HWI //! //! \param key key obtained with corresponding call to EnterCS() //! //! \return void // ----------------------------------------------------------------------------- void NPIUtil_ExitCS(_npiCSKey_t key) { Hwi_restore((UInt) key.hwikey); Task_restore((UInt) key.taskkey); }
/* * ======== Timer_Instance_init ======== * 1. Select timer based on id * 2. Mark timer as in use * 3. Save timer handle if necessary * 4. Init obj using params * 5. Create Hwi if tickFxn !=NULL * 6. Timer_init() * 7. Timer configuration (wrt emulation, external frequency etc) * 8. Timer_setPeriod() * 9. Timer_start() */ Int Timer_Instance_init(Timer_Object *obj, Int id, Timer_FuncPtr tickFxn, const Timer_Params *params, Error_Block *eb) { UInt key; Int i, status; Hwi_Params hwiParams; UInt tempId = 0xffff; if (id >= Timer_numTimerDevices) { if (id != Timer_ANY) { Error_raise(eb, Timer_E_invalidTimer, id, 0); return (1); } } key = Hwi_disable(); if (id == Timer_ANY) { for (i = 0; i < Timer_numTimerDevices; i++) { if ((Timer_anyMask & (1 << i)) && (Timer_module->availMask & (1 << i))) { Timer_module->availMask &= ~(1 << i); tempId = i; break; } } } else if (Timer_module->availMask & (1 << id)) { Timer_module->availMask &= ~(1 << id); tempId = id; } Hwi_restore(key); obj->staticInst = FALSE; if (tempId == 0xffff) { Error_raise(eb, Timer_E_notAvailable, id, 0); return (2); } else { obj->id = tempId; } obj->runMode = params->runMode; obj->startMode = params->startMode; if (params->altclk && !Timer_supportsAltclk) { Error_raise(eb, Timer_E_noaltclk, id, 0); return (1); } obj->altclk = params->altclk; obj->period = params->period; obj->periodType = params->periodType; if (obj->altclk) { /* if using altclk the freq is always 16MHz */ obj->extFreq.lo = 16000000; obj->extFreq.hi = 0; } else { /* else use specified extFreq */ obj->extFreq.lo = params->extFreq.lo; obj->extFreq.hi = params->extFreq.hi; } obj->arg = params->arg; obj->intNum = Timer_module->device[obj->id].intNum; obj->tickFxn = tickFxn; obj->prevThreshold = params->prevThreshold; obj->rollovers = 0; obj->savedCurrCount = 0; if (obj->tickFxn) { if (params->hwiParams) { Hwi_Params_copy(&hwiParams, (params->hwiParams)); } else { Hwi_Params_init(&hwiParams); } hwiParams.arg = (UArg)obj; obj->hwi = Hwi_create (obj->intNum, Timer_isrStub, &hwiParams, eb); if (obj->hwi == NULL) { return (3); } } else { obj->hwi = NULL; } Timer_module->handles[obj->id] = obj; /* enable and reset the timer */ Timer_enableFunc(obj->id); Timer_initDevice(obj); if (obj->periodType == Timer_PeriodType_MICROSECS) { if (!Timer_setPeriodMicroSecs(obj, obj->period)) { Error_raise(eb, Timer_E_cannotSupport, obj->period, 0); Hwi_restore(key); return (4); } } status = Timer_postInit(obj, eb); if (status) { return (status); } if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } return (0); }
/* * ======== Event_pend ======== */ UInt Event_pend(Event_Object *event, UInt andMask, UInt orMask, UInt 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_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg)&elem; clockParams.startFlag = FALSE; /* will start when necessary, thankyou */ Clock_construct(&clockStruct, (Clock_FuncPtr)Event_pendTimeout, timeout, &clockParams); 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(); /* leave a pointer for Task_delete() */ elem.tpElem.task->pendElem = (Task_PendElem *)&(elem); /* Atomically check for a match and block if none */ hwiKey = Hwi_disable(); /* check if events are already available */ matchingEvents = checkEvents(event, andMask, orMask); if (matchingEvents != 0) { Hwi_restore(hwiKey); /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } 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); /* lock scheduler */ tskKey = Task_disable(); /* only one Task allowed!!! */ Assert_isTrue(Queue_empty(pendQ), Event_A_eventInUse); /* 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 */ /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } elem.tpElem.task->pendElem = NULL; /* event match? */ if (elem.pendState != Event_PendState_TIMEOUT) { return (elem.matchingEvents); } else { return (0); /* timeout */ } }
/* * ======== Timer_start ======== * 1. Hwi_disable(); * 2. Clear the counters * 3. Clear IFR * 4. Enable timer interrupt * 5. Start timer * 6. Hwi_restore() */ Void Timer_start(Timer_Object *obj) { UInt key; UInt32 amr; ti_catalog_arm_peripherals_timers_TimerRegsM4 *timer; timer = (ti_catalog_arm_peripherals_timers_TimerRegsM4 *) Timer_module->device[obj->id].baseAddr; key = Hwi_disable(); /* stop timer */ Timer_write(obj->altclk, &timer->GPTMCTL, timer->GPTMCTL & ~0x1); /* clear all of timer's interrupt status bits */ Timer_write(obj->altclk, &timer->GPTMICR, (UInt32)0xFFFFFFFF); /* setup timer's Hwi */ if (obj->hwi) { Hwi_clearInterrupt(obj->intNum); Hwi_enableInterrupt(obj->intNum); /* clear match and timeout enable bits */ Timer_write(obj->altclk, &timer->GPTMIMR, timer->GPTMIMR & ~0x11); /* set appropriate interrupt enable based on timer mode */ if (obj->runMode != Timer_RunMode_DYNAMIC) { /* unmask the timeout interrupt */ Timer_write(obj->altclk, &timer->GPTMIMR, timer->GPTMIMR | 0x01); } else { /* unmask the match interrupt */ Timer_write(obj->altclk, &timer->GPTMIMR, timer->GPTMIMR | 0x10); } } /* clear timer mode bits and match interrupt enable */ amr = timer->GPTMTAMR & ~0x23; /* Timer_RunMode_CONTINUOUS */ if (obj->runMode == Timer_RunMode_CONTINUOUS) { Timer_write(obj->altclk, &timer->GPTMTAILR, obj->period); Timer_write(obj->altclk, &timer->GPTMTAMR, amr | 0x2); /* periodic */ } /* Timer_RunMode_DYNAMIC */ else if (obj->runMode == Timer_RunMode_DYNAMIC) { obj->prevThreshold = Timer_MAX_PERIOD; Timer_write(obj->altclk, &timer->GPTMTAV, Timer_MAX_PERIOD); Timer_write(obj->altclk, &timer->GPTMTAMATCHR, Timer_MAX_PERIOD - obj->period); Timer_write(obj->altclk, &timer->GPTMTAMR, amr | 0x22);/* prd & match */ } /* Timer_RunMode_ONESHOT */ else { Timer_write(obj->altclk, &timer->GPTMTAILR, obj->period); Timer_write(obj->altclk, &timer->GPTMTAMR, amr | 0x1); /* one-shot */ } if (obj->altclk) { timer->GPTMCC = 1; /* note: this write not affected by erratum */ } /* configure timer to halt with debugger, and start it */ Timer_write(obj->altclk, &timer->GPTMCTL, timer->GPTMCTL | 0x3); Hwi_restore(key); }
/* * ======== Timer_deviceConfig ======== * Configure the timer. */ Int Timer_deviceConfig(Timer_Object *obj, Error_Block *eb) { TimerRegs *timer; UInt hwiKey; UInt32 tsicr; timer = (TimerRegs *)Timer_module->device[obj->id].baseAddr; /* initialize the timer */ Timer_initDevice(obj, eb); hwiKey = Hwi_disable(); /* if doing SOFTRESET: do it first before setting other flags */ if (obj->tiocpCfg & TIMER_TIOCP_CFG_SOFTRESET_FLAG) { timer->tiocpCfg = TIMER_TIOCP_CFG_SOFTRESET_FLAG; while (timer->tiocpCfg & TIMER_TIOCP_CFG_SOFTRESET_FLAG) ; } timer->tiocpCfg = obj->tiocpCfg & ~TIMER_TIOCP_CFG_SOFTRESET_FLAG; /* xfer 'posted' setting if not current */ tsicr = timer->tsicr; if (obj->tsicr & TIMER_TSICR_POSTED) { if ((tsicr & TIMER_TSICR_POSTED) == 0) { timer->tsicr = (tsicr | TIMER_TSICR_POSTED); } } else { if ((tsicr & TIMER_TSICR_POSTED) != 0) { timer->tsicr = (tsicr & ~TIMER_TSICR_POSTED); } } /* set the period */ if (obj->periodType == Timer_PeriodType_MICROSECS) { if (!Timer_setPeriodMicroSecs(obj, obj->period)) { Hwi_restore(hwiKey); Error_raise(eb, Timer_E_cannotSupport, obj->period, 0); return (3); } } else { if (obj->runMode != Timer_RunMode_DYNAMIC) { timer->tcrr = Timer_MAX_PERIOD - obj->period; while (timer->twps & TIMER_TWPS_W_PEND_TCRR) ; timer->tldr = Timer_MAX_PERIOD - obj->period; while (timer->twps & TIMER_TWPS_W_PEND_TLDR) ; } else { timer->tcrr = 0; while (timer->twps & TIMER_TWPS_W_PEND_TCRR) ; timer->tmar = obj->period; while (timer->twps & TIMER_TWPS_W_PEND_TMAR) ; } } if (obj->runMode != Timer_RunMode_DYNAMIC) { timer->tmar = obj->tmar; while (timer->twps & TIMER_TWPS_W_PEND_TMAR) ; } timer->twer = obj->twer; timer->tier = obj->tier; timer->tclr = obj->tclr; while (timer->twps & TIMER_TWPS_W_PEND_TCLR) ; Hwi_restore(hwiKey); return (0); }
/* * ======== Task_setPri ======== */ UInt Task_setPri(Task_Object *tsk, Int priority) { Int oldPri; UInt newMask, tskKey, hwiKey; Queue_Handle newQ; Assert_isTrue((((priority == -1) || (priority > 0) || ((priority == 0 && Task_module->idleTask == NULL))) && (priority < (Int)Task_numPriorities)), Task_A_badPriority); Log_write4(Task_LM_setPri, (UArg)tsk, (UArg)tsk->fxn, (UArg)tsk->priority, (UArg)priority); tskKey = Task_disable(); hwiKey = Hwi_disable(); oldPri = tsk->priority; if (oldPri == priority) { Hwi_restore(hwiKey); Task_restore(tskKey); return (oldPri); } if (priority < 0) { newMask = 0; newQ = Task_Module_State_inactiveQ(); } else { newMask = 1 << priority; newQ = (Queue_Handle)((UInt8 *)(Task_module->readyQ) + (UInt)(priority*(2*sizeof(Ptr)))); } if (tsk->mode == Task_Mode_READY) { Queue_remove((Queue_Elem *)tsk); /* if last task in readyQ, remove corresponding bit in curSet */ if (Queue_empty(tsk->readyQ)) { Task_module->curSet &= ~tsk->mask; } if (Task_module->curTask == tsk) { Task_module->curQ = newQ; /* force a Task_switch() */ /* if no longer maxQ */ /* Put current task at front of its new readyQ */ Queue_insert(((Queue_Elem *)(newQ))->next, (Queue_Elem *)tsk); } else { /* place task at end of its readyQ */ Queue_enqueue(newQ, (Queue_Elem *)tsk); } Task_module->curSet |= newMask; } tsk->priority = priority; tsk->mask = newMask; tsk->readyQ = newQ; if (priority < 0) { Task_module->curQ = NULL; /* force a Task_switch() */ } Task_module->workFlag = 1; Hwi_restore(hwiKey); Task_restore(tskKey); return oldPri; }
/* * ======== Timer_Instance_init ======== * 1. Select timer based on id * 2. Mark timer as in use * 3. Save timer handle if necessary (needed by TimestampProvider on 64). * 4. Init obj using params * 5. Create Hwi if tickFxn !=NULL * 6. Timer_init() * 7. Timer configuration (wrt emulation, external frequency etc) * 8. Timer_setPeriod() * 9. Timer_start() */ Int Timer_Instance_init(Timer_Object *obj, Int id, Timer_FuncPtr tickFxn, const Timer_Params *params, Error_Block *eb) { UInt key; Int i, status; Hwi_Params hwiParams; UInt tempId = 0xffff; if (id >= Timer_NUM_TIMER_DEVICES) { if (id != Timer_ANY) { Error_raise(eb, Timer_E_invalidTimer, id, 0); return (1); } } key = Hwi_disable(); if (id == Timer_ANY) { for (i = 0; i < Timer_NUM_TIMER_DEVICES; i++) { if ((Timer_anyMask & (1 << i)) && (Timer_module->availMask & (1 << i))) { Timer_module->availMask &= ~(1 << i); tempId = i; break; } } } else if (Timer_module->availMask & (1 << id)) { Timer_module->availMask &= ~(1 << id); tempId = id; } Hwi_restore(key); obj->staticInst = FALSE; if (tempId == 0xffff) { Error_raise(eb, Timer_E_notAvailable, id, 0); return (2); } else { obj->id = tempId; } /* if timer id == 0, use systick */ if (obj->id == 0) { obj->ctmid = 0; obj->intNum = 15; } /* if timer id == 1, must select which CTM timer based on core id */ else { if (Core_getId() == 0) { obj->ctmid = 0; obj->intNum = 18; } else { obj->ctmid = 1; obj->intNum = 22; } } obj->runMode = params->runMode; obj->startMode = params->startMode; obj->period = params->period; obj->periodType = params->periodType; obj->extFreq.lo = params->extFreq.lo; obj->extFreq.hi = params->extFreq.hi; if (obj->periodType == Timer_PeriodType_MICROSECS) { if (!Timer_setPeriodMicroSecs(obj, obj->period)) { Error_raise(eb, Timer_E_cannotSupport, obj->period, 0); Hwi_restore(key); return (4); } } obj->arg = params->arg; obj->tickFxn = tickFxn; if (obj->tickFxn) { if (params->hwiParams) { Hwi_Params_copy(&hwiParams, (params->hwiParams)); } else { Hwi_Params_init(&hwiParams); } /* we'll enable the interrupt when we're ready */ hwiParams.enableInt = FALSE; /* SysTick needs to be acknowledged, use stub functions */ if (obj->id == 0) { hwiParams.arg = (UArg)obj; if (obj->runMode == Timer_RunMode_CONTINUOUS) { obj->hwi = Hwi_create (obj->intNum, Timer_periodicStub, &hwiParams, eb); } else { obj->hwi = Hwi_create (obj->intNum, Timer_oneShotStub, &hwiParams, eb); } } /* CTM doesn't need to be acknowledged, no stub required */ else { hwiParams.arg = obj->arg; obj->hwi = Hwi_create (obj->intNum, obj->tickFxn, &hwiParams, eb); } if (obj->hwi == NULL) { return (3); } } else { obj->hwi = NULL; } Timer_module->handles[obj->id] = obj; status = postInit(obj, eb); if (status) { return (status); } if (obj->startMode == Timer_StartMode_AUTO) { Timer_start(obj); } return (0); }
/* * ======== 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; }
/* * ======== NotifyDriverShm_disableEvent ======== */ Void NotifyDriverShm_disableEvent(NotifyDriverShm_Object *obj, UInt32 eventId) { UInt sysKey; NotifyDriverShm_EventEntry *eventEntry; Assert_isTrue(eventId < ti_sdo_ipc_Notify_numEvents, ti_sdo_ipc_Ipc_A_invArgument); /* * Atomically unset the corresponding bit in the processor's * eventEnableMask */ sysKey = Hwi_disable(); CLEAR_BIT(obj->selfProcCtrl->eventEnableMask, eventId); Hwi_restore(sysKey); if (obj->cacheEnabled) { Cache_wbInv(obj->selfProcCtrl, sizeof(NotifyDriverShm_ProcCtrl), Cache_Type_ALL, TRUE); } eventEntry = EVENTENTRY(obj->selfEventChart, obj->eventEntrySize, eventId); if (obj->cacheEnabled) { Cache_inv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * Disable incoming Notify interrupts. This is done to ensure that the * eventEntry->flag is read atomically with any write back to shared * memory */ NotifyDriverShm_disable(obj); /* * Is the local NotifyDriverShm_disableEvent happening between the * following two NotifyDriverShm_sendEvent operations on the remote * processor? * 1. Writing NotifyDriverShm_UP to shared memory * 2. Sending the interrupt across * If so, we should handle this event so the other core isn't left spinning * until the event is re-enabled and the next NotifyDriverShm_isr executes * This race condition is very rare but we need to account for it: */ if (eventEntry->flag == NotifyDriverShm_UP) { /* * Acknowledge the event. No need to store the payload. The other side * will not send this event again even though flag is down, because the * event is now disabled. So the payload within the eventChart will not * get overwritten. */ eventEntry->flag = NotifyDriverShm_DOWN; /* Write back acknowledgement */ if (obj->cacheEnabled) { Cache_wbInv(eventEntry, sizeof(NotifyDriverShm_EventEntry), Cache_Type_ALL, TRUE); } /* * Execute the callback function. This will execute in a Task * or Swi context (not Hwi!) */ ti_sdo_ipc_Notify_exec(obj->notifyHandle, eventId, eventEntry->payload); } /* Re-enable incoming Notify interrupts */ NotifyDriverShm_enable(obj); }
/*! * ======== InterruptArp32_intRegister ======== */ Void InterruptArp32_intRegister(UInt16 remoteProcId, IInterrupt_IntInfo *intInfo, Fxn func, UArg arg) { UInt key; UInt16 index; UInt mbxIdx; Hwi_Params hwiAttrs; Error_Block eb; InterruptArp32_FxnTable *table; Assert_isTrue(remoteProcId < ti_sdo_utils_MultiProc_numProcessors, ti_sdo_ipc_Ipc_A_internal); /* Assert that our MultiProc id is set correctly */ Assert_isTrue((InterruptArp32_eve0ProcId == MultiProc_self()) || (InterruptArp32_eve1ProcId == MultiProc_self()) || (InterruptArp32_eve2ProcId == MultiProc_self()) || (InterruptArp32_eve3ProcId == MultiProc_self()), ti_sdo_ipc_Ipc_A_internal); /* init error block */ Error_init(&eb); index = PROCID(remoteProcId); /* Disable global interrupts */ key = Hwi_disable(); table = &(InterruptArp32_module->fxnTable[index]); table->func = func; table->arg = arg; InterruptArp32_intClear(remoteProcId, intInfo); if ((index == DSP0_ID) || (index == BENELLI_CORE0_ID)) { mbxIdx = 0; } else if ((index == DSP1_ID) || (index == BENELLI_CORE1_ID)) { mbxIdx = 1; } else if (index < InterruptArp32_NUM_EVES) { mbxIdx = 2; } /* Make sure the interrupt only gets plugged once */ InterruptArp32_module->numPlugged[mbxIdx]++; if (InterruptArp32_module->numPlugged[mbxIdx] == 1) { /* Register interrupt to remote processor */ Hwi_Params_init(&hwiAttrs); hwiAttrs.arg = arg; hwiAttrs.vectorNum = intInfo->intVectorId; Hwi_create(InterruptArp32_eveInterruptTable[index], (Hwi_FuncPtr)InterruptArp32_intShmStub, &hwiAttrs, &eb); Hwi_enableInterrupt(InterruptArp32_eveInterruptTable[index]); } /* enable the mailbox and Hwi */ InterruptArp32_intEnable(remoteProcId, intInfo); /* Restore global interrupts */ Hwi_restore(key); }