示例#1
0
/*
 *  ======== 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
}
示例#4
0
/*
 *  ======== 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);
}
示例#5
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);
        } 
    }
}
示例#7
0
/*
 *  ======== 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(&timestampFreq);

    /* 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);
}
示例#9
0
/*
 *  ======== 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);
}
示例#10
0
/*
 *  ======== 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(&paramsUnion.hwiParams);
    paramsUnion.hwiParams.arg = (UArg)handle;
    Hwi_construct(&(object->hwi), hwAttrs->intNum, I2CCC26XX_hwiFxn,
                  &paramsUnion.hwiParams, NULL);

    /*
     * Create thread safe handles for this I2C peripheral
     * Semaphore to provide exclusive access to the I2C peripheral
     */
    Semaphore_Params_init(&paramsUnion.semParams);
    paramsUnion.semParams.mode = Semaphore_Mode_BINARY;
    Semaphore_construct(&(object->mutex), 1, &paramsUnion.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, &paramsUnion.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);
}
示例#12
0
文件: Notify.c 项目: mobiaqua/ti-ipc1
/*
 *  ======== 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);
}
示例#13
0
文件: Notify.c 项目: mobiaqua/ti-ipc1
/*
 *  ======== 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);
}
示例#15
0
/*
 *  ======== 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);
}
示例#16
0
/*
 *  ======== 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);
}
示例#18
0
/*
 *  ======== 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);
}
示例#19
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 */
    }
}
示例#20
0
/*
 *  ======== 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);
}
示例#21
0
/*
 *  ======== 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;
}
示例#23
0
/*
 *  ======== 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;
}
示例#25
0
/*
 *  ======== 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);
}
示例#26
0
/*!
 *  ======== 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);
}