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

📄 lh79524_timer_driver.c

📁 SHARP_ARM720T_LH79524/5软件开发包_支持TFT_LCD_NAND_FLASH_ETH_USB
💻 C
📖 第 1 页 / 共 2 页
字号:
    pregs->ctrl = temp;
    break;
    /* Enable free running counter operation */
  case TIMER_SET_CNT_MODE:
    /* Get the current contents on the register */
    temp = pregs->ctrl;
    /* Clear the CMP1 and CMP0 fields B[13:12] and B[11:10] */
    temp &= ~(_SBF(12,3) | _SBF(10,3));
    temp |= _SBF(14,0) |  /* PWM bit set B[14] = 0 */
      _SBF(13,0);      /* TC bit set  B[13] = 0 */       
    /* Update the register */
    pregs->ctrl = temp;
    break;
    /* Mask interrupts at the source */ 
  case TIMER_DISABLE_INT:   
    /* Get the current state */
    temp = pregs->int_ctrl;
    /* Mask off the interrupt */
    temp &= ~arg;
    /* Update the interrupt control register */
    pregs->int_ctrl = temp;
    break;
    /* Unmask interrupts at the source */ 
  case TIMER_ENABLE_INT: 
    /* Get the current state */
    temp = pregs->int_ctrl;
    /* UnMask the interrupt */
    temp |= arg;
    /* Update the interrupt control register */
    pregs->int_ctrl = temp;
    /* Update the driver control object */
    pdev->imask = temp;
    break;
    /* Return pointer to device isr */
  case TIMER_GET_ISR:
    /* Sanity check */
    if ((void*)arg == NULL)
    {
      status = _ERROR;
      break;
    }
    /* Return the driver interrupt service routine */
    *(INT_32**)arg = (void*)pdev->irq_hdlr;
    break;
    /* Bind a callback method to be used by the timer isr */
  case TIMER_SET_CALLBACK:
    /* Save the interrupt callback method */
    pdev->callback = (PFI)arg;
    break;
    /* Set the timer status register */
  case TIMER_SET_STATUS:
    pregs->status = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_STATUS:
    /* Sanity check */
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->status;
    break;
    /* Set the timer status register */
  case TIMER_SET_COUNT:
    pregs->cnt = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_COUNT:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cnt;
    break;
    /* Set the timer status register */
  case TIMER_SET_CMP0:
    pregs->cmp0 = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_CMP0:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cmp0;
    break;
    /* Set the timer status register */
  case TIMER_SET_CMP1:
    pregs->cmp1 = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_CMP1:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cmp1;
    break;
    /* Set the timer status register */
  case TIMER_SET_CAP0:
    pregs->cap0 = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_CAP0:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cap0;
    break;
    /* Set the timer status register */
  case TIMER_SET_CAP1:
    pregs->cap1 = arg;
    break;
    /* Get the timer status register */
  case TIMER_GET_CAP1:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cap1;
    break;
  default:
    status = _ERROR;
    break;
  }
  /* Return the io control status */
  return (status);
}


/*********************************************************************** 
 * 
 * Function: timer_wait_us
 * 
 * Purpose: Delay for usec microSeconds 
 * 
 * Processing:
 *     If the timer argument is a valid timer, stop the timer and use
 *     the timer_set_delay function to program the timer underflow to
 *     the needed delay and then restart the timer. Monitor the raw
 *     timer count value until the value underflows. Stop the timer and
 *     then clear the pending timer interrupt.
 * 
 * Parameters: 
 *     timer : Must be TIMER1 or TIMER2 
 *     usec  : the delay time in microseconds
 * 
 * Outputs: None
 * 
 * Returns: Nothing
 * 
 * Notes: 
 *     This function is intended for simple non-interruptable delays
 *     with accurate timing. Using this function will change the
 *     settings of the timer the function is used with. For very small
 *     times with a low CPU and bus clock speed, the timing may be
 *     inaccurate. Use with care.
 * 
 **********************************************************************/
void timer_wait_us(TIMER_REGS_T *timer_regs,
                   UNS_32 usec, 
                   UNS_32 xtal_in)
{
  if((timer_regs == TIMER1) || (timer_regs == TIMER2))
  {
    /* stop timer */
    timer_regs->ctrl &= ~TM12_CTRL_CS;
    /* set the desired interval */
    timer_set_interval(timer_regs, usec, xtal_in);
    
    /* clear counter register */
    timer_regs->ctrl |= TM12_CTRL_CCL;
    
    /* clear inetrrupt */
    timer_regs->status = _BIT(TM12_INTCTRL_CMP1);
    
    /* start timer */
    timer_regs->ctrl |= TM12_CTRL_CS | TM12_CTRL_CCL;
    
    /* wait of campare 1 event */
    while ( (timer_regs->status & TM12_INTCTRL_CMP1) == 0)
      ;
    /* clear compare interrupt */
    timer_regs->status = _BIT(TM12_INTCTRL_CMP1);
    
    /* stop timer */
    timer_regs->ctrl &= ~TM12_CTRL_CS;
  }
}

/***********************************************************************
 *
 * Function: timer_wait_ms
 *
 * Purpose:
 *     Wait for the specified number of milliseconds
 *
 * Processing:
 *     Call timer_wait_us() with a value of 1000 usec for the number of
 *     times specified by the msec argument.
 *
 * Parameters:
 *     timer: Must be one of TIMER1 or TIMER2 
 *     msec:   the delay time in milliseconds
 *
 * Outputs: None
 *
 * Returns: Nothing
 *
 * Notes: None
 *
 **********************************************************************/
void timer_wait_ms(TIMER_REGS_T *timer_regs, 
                   UNS_32 msec, 
                   UNS_32 xtal_in)
{
  UNS_32 elapsed_ms;

  for (elapsed_ms = 0; elapsed_ms < msec; elapsed_ms++)
  {
    timer_wait_us(timer_regs, 1000, xtal_in);
  }
}

/************************************************************************
*
* Function: timer1_isr
*
* Purpose: 
*  Services the interrupt for a timer1.
*
* Processing:
*     
* Parameters: 
*  None
*
* Outputs: 
*  None
*
* Returns: 
*  None
*
* Notes: 
*  None
*
************************************************************************/

static void timer1_isr (void)
{
  /* Call the default handler */
  timer_default_isr ((INT_32)pdriver[0]);
}

/************************************************************************
*
* Function: timer1_isr
*
* Purpose: 
*  Services the interrupt for a timer1.
*
* Processing:
*     
* Parameters: 
*  None
*
* Outputs: 
*  None
*
* Returns: 
*  None
*
* Notes: 
*  None
*
************************************************************************/

static void timer2_isr (void)
{
  /* Call the default handler */
  timer_default_isr ((INT_32)pdriver[1]);
}

/************************************************************************
*
* Function: timer_default_handler
*
* Purpose: 
*  Services the interrupt for a timer0.
*
* Processing:
*     
* Parameters: 
*  None
*
* Outputs: 
*  None
*
* Returns: 
*  None
*
* Notes: 
*  None
*
************************************************************************/

static void timer_default_isr (INT_32 devid)
{
  REGS_T*   pregs = NULL;
  DRIVER_T* pdev  = NULL; 
  
  /* Attach to the base address of the driver */
  pdev = (DRIVER_T*)devid;
  
  /* Attach to the base address of the selected timer */
  pregs = (REGS_T*)pdev->regs;
  
  /* Stop the timer */
  (void) timer_ioctl (devid, TIMER_STOP, 0);
  
  /* Clear the timer */
  (void) timer_ioctl (devid, TIMER_CLEAR_CNT, 0);
  
  /* Check if the counter has expired */
  if (pdev->callback != NULL)
  {
    /* Execute the callback method */
    (*(PFI)pdev->callback) ();
  }
  
  /* Clear the interrupt at the source */
  pregs->status = pdev->imask;
  
  /* Start the timer */
  (void) timer_ioctl (devid, TIMER_START, 0);
}


/*********************************************************************** 
 * 
 * Function: timer_set_interval 
 * 
 * Purpose: 
 *  Initialize the specified timer as an interval timer that clears 
 *  itself after the specified interval 
 * 
 * Processing: 
 *  Set the TC bit of the ctrl register and set CMP1 and the prescaler
 *  bits in the control register to values appropriate to the timer 
 *  interval. Find these values by trying every prescaler and CMP1 
 *  combination and determining which gives the smallest difference
 *  from the requested interval. Return _ERROR if the clock source 
 *  cannot generate a periodic time base.
 * 
 * Parameters: 
 *  timer:      either TIMER1 or TIMER2 
 *              (see LH79524_timer_driver.h) 
 *  usec:       the requested interval in microseconds 
 *  xtal_in:    On board oscillator clock 
 * 
 * Outputs: None. 
 * 
 * Returns: 
 *  the actual timer interval in microseconds that can be obtained with 
 *  the specified clock source or _ERROR if usec is out of range
 * 
 * Notes: 
 *  If the interval is too short, the function will set the interval 
 *  to the minimum available. If the interval is too long, the 
 *  interval will be set to the maximum. Users of this function should 
 *  check the return code to make sure the interval is close enough 
 *  to the requested interval. 
 * 
 **********************************************************************/ 
static INT_32 timer_set_interval(TIMER_REGS_T* timer_regs, 
                                  UNS_32 usec,
                                  UNS_32 xtal_in)
{
  INT_32 counts, new_counts;
  UNS_32 new_usec, best_usec, hclk;
  UNS_32 prescale_index, best_prescale_index;
  UNS_32 max_interval, min_interval;
  INT_32 delta, best_delta;
  
  hclk = RCPC_GET_HCLK(xtal_in);
  max_interval = (UNS_32)(((UNS_64)_BIT(16) * 
    (UNS_64)USECS_PER_SEC) / 
    ((UNS_64)hclk / (UNS_64)128));
  if (usec > max_interval)
    usec = max_interval;
  min_interval = 2 * USECS_PER_SEC / hclk;
  if (usec < min_interval)
    usec = min_interval;
  
  best_delta = usec;
  
  /* minimize the error in timing the interval*/
  for (best_prescale_index = 0, prescale_index = 0, best_usec = 0; 
  prescale_index < TM12_CTRL_CTCLK;
  prescale_index++)
  {
    new_counts = (UNS_32)((UNS_64)usec * 
      (UNS_64)(hclk / (1 << (prescale_index + 1))) /
      (UNS_64)USECS_PER_SEC) - 1;
    
    if (new_counts <= 0)
      new_counts = 1;
    
    new_counts &= _BITMASK(16); /* cmp1 register 16 bits.*/
    new_usec = USECS_PER_SEC / (hclk / 
      (_BIT(prescale_index + 1) * new_counts));
    delta = usec - new_usec;
    if (delta < 0)
      delta = -delta;
    if (delta <= best_delta) /* use <= to maximize prescale*/
    {                
      best_delta = delta;
      best_prescale_index = prescale_index;
      best_usec = new_usec;
      counts = new_counts;
    }
  } /* end for*/
  
  /* counts and best_prescale_index are initialized */
  timer_regs->cmp1 =  counts;
  timer_regs->ctrl &= ~TM12_CTRL_SEL(TM12_CTRL_CTCLK);
  timer_regs->ctrl |= TM12_CTRL_SEL(best_prescale_index) |
    TM12_CTRL_TC;
  return usec;
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -