⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 realview22.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
 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 + -