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

📄 lh79524_timer0_driver.c

📁 SHARP_ARM720T_LH79524/5软件开发包_支持TFT_LCD_NAND_FLASH_ETH_USB
💻 C
📖 第 1 页 / 共 2 页
字号:
      pregs->ctrl = temp;
      /* Set the new time base */
      temp = pregs->ctrl;
      /* Clear the current count clock bit field B[4:2] */
      temp &= ~_SBF(2,7); 
      /* Set up the new clock rate - set B[4:2] */
      temp |= _SBF(2,arg);
      /* Update the config structure */
      pdev->cfg.clock_rate = _SBF(2,arg);
      /* Restore the intial timer state (start/stop) */
      pregs->ctrl = (temp | running);
    }
    break;
    /* Set the clock rate */
  case TIMER_GET_CLK_RATE:
    /* Sanity check */
    if ((void*)arg == NULL)
    {
      status = _ERROR;
      break;
    }
    /* Return the driver interrupt service routine */
    *(INT_32*)arg = pdev->cfg.clock_rate;
    break;
    /* Enable PWM mode */
  case TIMER_SET_PWM_MODE:
    /* Get the current contents on the register */
    temp = pregs->cmp_cap_ctrl;
    /* Clear the CMP1 and CMP0 fields B[13:12] and B[11:10] */
    temp &= ~(_SBF(12,3) | _SBF(10,3));
    temp |= _SBF(15,1) |  /* PWM bit set B[15] = 1 */
      _SBF(14,1)    |  /* TC bit set  B[14] = 1 */       
      _SBF(12,2)    |  /* CMP1 B[13:12] = 10    */
      _SBF(10,1);      /* CMP0 B[11:10] = 01    */
    /* Update the register */
    pregs->cmp_cap_ctrl = temp;
    /* EJA - hack need to fix  */
#define TIMER_MUX_REG (0xFFFE500C)
    /* Set up the pin muxing */
    *(volatile long*)TIMER_MUX_REG = 0;
    *(volatile long*)TIMER_MUX_REG |= _SBF(1,2);
    break;
    /* Enable free running counter mode */
  case TIMER_SET_CNT_MODE:
    /* Get the current contents on the register */
    temp = pregs->cmp_cap_ctrl;
    /* Clear the CMP1 and CMP0 fields B[13:12] and B[11:10] */
    temp &= ~(_SBF(12,3) | _SBF(10,3));
    temp |= _SBF(15,0) |  /* PWM bit set B[15] = 0 */
      _SBF(14,0);      /* TC bit set  B[14] = 0 */       
    /* Update the register */
    pregs->cmp_cap_ctrl = temp;
    break;
    /* Enable Periodic counter mode */
  case TIMER_SET_PERIODIC_MODE:
    timer0_set_interval(pregs, (UNS_32)arg, pdev->cfg.sys_clk);
    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;
    /* Set the timer compare and capture control register */
  case TIMER0_SET_CMP_CAP_CTRL:
    pregs->cmp_cap_ctrl = arg;
    break;
    /* Get the timer compare and capture control register */
  case TIMER0_GET_CMP_CAP_CTRL:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cmp_cap_ctrl;
    break;
    /* Set the timer capture2 register */
  case TIMER0_SET_CAP2:
    break;
    /* Get the timer capture2 register */
  case TIMER0_GET_CAP2:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cap2;
    break;
    /* Set the timer capture3 register */
  case TIMER0_SET_CAP3:
    pregs->cap3 = arg;
    break;
    /* Get the timer capture3 register */
  case TIMER0_GET_CAP3:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cap3;
    break;
    /* Set the timer capture4 register */
  case TIMER0_SET_CAP4:
    pregs->cap4 = arg;
    break;
    /* Get the timer capture4 register */
  case TIMER0_GET_CAP4:
    if ((void*)arg == NULL)
    {
      status = _ERROR;
    }
    *(INT_32*)arg = pregs->cap4;
    break;
  default:
    status = _ERROR;
    break;
  }
  /* Return the io control status */
  return (status);
}

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

void timer0_isr (void)
{
  /* Call the default handler */
  timer0_default_isr ((INT_32)pdriver[0]);
}

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

static void timer0_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) timer0_ioctl (devid, TIMER_STOP, 0);
  
  /* Clear the timer */
  (void) timer0_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) timer0_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 TIMER0, 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 timer0_set_interval(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 < TM0_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 &= ~TM0_CTRL_SEL(TM0_CTRL_CTCLK);
  timer_regs->ctrl |= TM0_CTRL_SEL(best_prescale_index);
  timer_regs->cmp_cap_ctrl  = TM0_CMPCAP_TC;
  return usec;
}








⌨️ 快捷键说明

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