📄 timer.c
字号:
myTimer->oldPrescale = myTimer->prescale; /* copy old */
myTimer->prescale = ( *word >> 2) & 0x3;
/* Now process any changes */
/* Has the Prescale value changed? */
if ( ( (myTimer->TimerControlChangeMask >> 2) & 0x3))
{
/* Yes the prescale has changed
we have to do the following;
1. Retract the scheduled timeout event.
2. Work out what the 16 bit down counter value actually was
3. Recalculate the timeout time and re-schedule
If the timer is enabled then we need to do something
otherwise it is just a value change and can pass unnoticed.
*/
if ( myTimer->enabled )
{
ARMTime Now = getNow(ts);
/* Only ditch the event if one is pending! If one isn't pending then
* the prescale change will be dealt with when the next event is
* scheduled. At this point we are only concerned with removing events
* that we calculated the timeout for using the old prescale value!
*/
if ( Now <= myTimer->nextEventTime)
{
PrescaleValueChanged(ts, myTimer);
}
}
}
/* Has the timer been Enabled or disabled? */
if ( ( (myTimer->TimerControlChangeMask >> 7) & 0x1))
{
/* Enabled bit changed */
if (myTimer->enabled)
{
/* We need to kick off the timer NOW */
KickOffTimer(ts,myTimer,0, FALSE);
}
else
{
/* We have been disabled - so we need to grab
the scheduled timeout event from the queue
*/
if (myTimer->timedCallback != NULL)
ARMulif_DescheduleTimedCallback(&ts->coredesc,
myTimer->timedCallback,
ARMulCallbackID_ScheduleFunctionEvery/*BCLK*/);
myTimer->timedCallback = NULL;
myTimer->nextEventTime = 0;
}
}
/* There is nothing to do for mode changes - these are dealt with
at timeout time.
*/
return 0;
}
/*
Function Name: TICRegisterAccess
Parameters: TimerState *ts, -TimerState pointer
ARMword addr, - access address
ARMword *word, - pointer to data word
ARMul_acc acc - access type information
Return: int 1 = success, -2 = failed to decode address.
Description: Called from MemAccess. This meory model is called from the switch
because partial address decoding identified this as a memory that could
fully decode the address. This function continues the address decoding
trying to identify individual registers. For each decoded address
an action is carried out. For any addressed that aren't decoded -2 is
returned indicating failure to decode. In the case of failure to decode
then the access is passed on to the next level of memory by switch.
*/
static int TICRegisterAccess(TimerState *ts,ARMword addr,ARMword *word,
unsigned /*ARMul_acc*/ acc)
{
unsigned long maskedAddress = addr & 0x0000003F;
#ifdef VERBOSE_ACCESS
printf("TICRegisterAccess: A:%08lx D:%08lx.\n",(unsigned long)addr,
(word==NULL)?0UL:(unsigned long)*word);
#endif
/* Yes it is a memory access - now is it a read or a write? */
if ( ACCESS_IS_READ(acc) )
{
/* Read from registers */
switch ( maskedAddress)
{
case 0x00: /* Timer1Load */
/* Only the bottom 16 bits are significant */
*word = ts->timer1.TimerLoad & 0x0000FFFF;
break;
case 0x04: /* Timer1Value */
/* We need to work out what this value is at present. */
*word = ValueRegRead(ts, &ts->timer1);
break;
case 0x08: /* Timer1Control*/
*word = ts->timer1.TimerControl;
/* nothing to do apart from give it back */
break;
case 0x0c: /* Reserved */
case 0x10:
case 0x2c:
case 0x30:
if ( ts->warn == TRUE) {
Hostif_ConsolePrint(ts->hostif,"Warning - accessed Reserved "
"Timer Counter register address %08x\n",addr);
}
return PERIP_NODECODE; /*-2*/
break;
case 0x20:
/*Timer2Load */
/* Only the bottom 16 bits are significant */
*word = ts->timer2.TimerLoad & 0x0000FFFF;
break;
case 0x24:
/*Timer2Value */
/* We need to work out what this value is at present. */
*word = ValueRegRead(ts, &ts->timer2);
break;
case 0x28:
/*Timer2Control */
*word = ts->timer2.TimerControl;
/* nothing to do apart from give it back */
break;
default:
return PERIP_NODECODE; /* Failed to decode address */
}
}
else
{
/* Write to registers */
switch ( maskedAddress)
{
case 0x00:
/* Timer1Load */
/* Only the bottom 16 bits are significant */
ts->timer1.TimerLoad = *word & 0x0000FFFF;
/* QQQ We may need to kick off the timer NOW
we may also need to retract an event */
/* Retract any existing events */
if ( ts->timer1.nextEventTime != 0)
{
if (ts->timer1.timedCallback != NULL)
ARMulif_DescheduleTimedCallback(&ts->coredesc,
ts->timer1.timedCallback,
ARMulCallbackID_ScheduleFunctionEvery/*BCLK*/);
/* free(ts->timer1.timedCallback); */
ts->timer1.timedCallback = NULL;
ts->timer1.nextEventTime=0;
}
/* Kick off the timer */
KickOffTimer(ts,&ts->timer1, 0, FALSE);
break;
case 0x08:
/* Timer1Control*/
TICControlRegisterWrite(ts,&ts->timer1, word);
break;
case 0x0c:
/* Timer1Clear */
TimerClearInterrupt(ts, &ts->timer1);
break;
case 0x4: /* Reserved */
case 0x10:
case 0x24:
case 0x30:
if ( ts->warn == TRUE) {
Hostif_ConsolePrint(ts->hostif,"Warning - accessed Reserved "
"Timer Counter register address %08x\n",addr);
}
return PERIP_NODECODE;
break;
case 0x20:
/*Timer2Load */
/* Only the bottom 16 bits are significant */
ts->timer2.TimerLoad = *word & 0x0000FFFF;
/* Retract any existing events */
if ( ts->timer2.nextEventTime != 0)
{
if (ts->timer2.timedCallback != NULL)
ARMulif_DescheduleTimedCallback(&ts->coredesc,
ts->timer2.timedCallback,
ARMulCallbackID_ScheduleFunctionEvery/*BCLK*/);
/* free(ts->timer2.timedCallback); */
ts->timer2.timedCallback = NULL;
ts->timer2.nextEventTime=0;
}
/* Kick off the timer */
KickOffTimer(ts,&ts->timer2, 0, FALSE);
break;
case 0x28:
/*Timer2Control */
TICControlRegisterWrite(ts,&ts->timer2, word);
break;
case 0x2c:
/* Timer2Clear */
/* Clear the interrupt source */
TimerClearInterrupt(ts, &ts->timer2);
break;
default:
return PERIP_NODECODE; /* Failed to decode address */
}
}
return PERIP_OK; /* Successful */
}
/* Bus state machine */
static int BusState(TimerState *ts, ARMword addr, ARMword *word,
unsigned /*ARMul_acc*/ acc)
{
if (!ACCESS_IS_REAL(acc)) /* acc_ACCOUNT() */
{
return TICRegisterAccess(ts, addr, word, acc);
}
if ( ts->accessState == 0 )
{
/* Idle on access */
if ( ts->waitStates == 0)
{
/* No waits - do access now */
return TICRegisterAccess(ts,addr,word,acc);
}
else
{
/* First access -but with waits - so decrement and return 0*/
ts->waits = ts->waitStates;
ts->accessState=1;
return PERIP_BUSY; /* tell core to wait */
}
}
else /* ts->accessState == 1) */
{
/* Waiting state */
if ( ts->waits == 0)
{
/* No waits - do access now */
ts->accessState = 0; /* restore access state */
/* Post wait - doing access */
return TICRegisterAccess(ts,addr,word,acc);
}
else
{
/* Subsequent access -but with waits - so decrement and return 0*/
ts->waits--;
/* Subsequent wait */
return PERIP_BUSY; /* tell core to wait */
}
}
/* accessState : 0=Idle, 1= Waiting */
}
/* MemAccess functions */
static int Timer_Access(void *handle,
struct ARMul_AccessRequest *req)
{
ARMWord address = req->req_address[0];
ARMWord *data = req->req_data;
unsigned type = req->req_access_type;
TimerState *state=(TimerState *)handle;
assert(address >= state->my_bpar.range[0].lo && \
address <= state->my_bpar.range[0].hi);
/* We have idenfitied a TIC memory access */
return BusState(state,address,data,type);
}
/*--- <SORDI STUFF> ---*/
#define SORDI_DLL_DESCRIPTION_STRING "Timer (a Reference Peripheral)"
#define SORDI_RDI_PROCVEC Timer_AgentRDI
#include "perip_sordi.h"
#include "perip_rdi_agent.h"
IMPLEMENT_AGENT_PROCS_NOEXE_NOMODULE(Timer)
IMPLEMENT_AGENT_PROCVEC_NOEXE(Timer)
/*--- </> ---*/
/* EOF timer.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -