/* * ======== Timer_Instance_finalize ======== */ Void Timer_Instance_finalize(Timer_Object *obj, Int status) { UInt key; /* fall through in switch below is intentional */ switch (status) { /* Timer_delete() */ case 0: /* Hwi create failed */ case 4: /* device config (setPeriodMicroSecs) failed */ case 3: Timer_initDevice(obj, NULL); if (obj->hwi) { Hwi_delete(&obj->hwi); } break; /* timer not available */ case 2: /* invalid timer id */ case 1: default: break; } key = Hwi_disable(); Timer_module->availMask |= (0x1 << obj->id); Timer_module->handles[obj->id] = NULL; Hwi_restore(key); }
/* * ======== Timer_postInit ======== */ Int Timer_postInit(Timer_Object *obj, Error_Block *eb) { UInt hwiKey; hwiKey = Hwi_disable(); Timer_initDevice(obj); Timer_setPeriod(obj, obj->period); Hwi_restore(hwiKey); return (0); }
/* * ======== Timer_enableTimers ======== */ Void Timer_enableTimers() { Int i; Timer_Object *obj; for (i = 0; i < Timer_numTimerDevices; i++) { obj = Timer_module->handles[i]; /* enable and reset the timer */ if (obj != NULL) { Timer_enableFunc(obj->id); Timer_initDevice(obj); } } }
/* * ======== Timer_deviceConfig ======== * Configure the timer. */ Int Timer_deviceConfig(Timer_Object *obj, Error_Block *eb) { TimerRegs *timer; UInt hwiKey; timer = (TimerRegs *)Timer_module->device[obj->id].baseAddr; /* reset the timer */ timer->tiocpCfg = obj->tiocpCfg | 0x2; /* wait for reset to finish */ while(timer->tistat != 0x01) ; /* initialize the timer */ Timer_initDevice(obj, eb); hwiKey = Hwi_disable(); /* 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 { 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) ; } timer->tmar = obj->tmar; while (timer->twps & TIMER_TWPS_W_PEND_TMAR) ; timer->twer = obj->twer; timer->tclr = obj->tclr; while (timer->twps & TIMER_TWPS_W_PEND_TCLR) ; Hwi_restore(hwiKey); return (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); }
/* * ======== 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); }