📄 lh79520_timer_driver.c
字号:
/***********************************************************************
* $Workfile: lh79520_timer_driver.c $
* $Revision: 1.0 $
* $Author: LiJ $
* $Date: Jul 07 2003 16:40:02 $
*
* Project: LH79520 timer driver
*
* Description:
* This file contains driver support for the timer modules on the
* LH79520
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh79520/source/lh79520_timer_driver.c-arc $
*
* Rev 1.0 Jul 07 2003 16:40:02 LiJ
* Initial revision.
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
*
**********************************************************************/
#include "lh79520_rcpc.h"
#include "lh79520_timer_driver.h"
#ifdef __GNUC__
#define UNS_64 unsigned long
#endif
/***********************************************************************
* Timer driver private data
**********************************************************************/
/* Timer device configuration structure */
STATIC TIMER_CFG_T timer0cfg, timer1cfg, timer2cfg, timer3cfg;
/***********************************************************************
* Timer driver private functions
**********************************************************************/
/***********************************************************************
*
* Function: timer_set_delay_us
*
* Purpose: Set timer delay (undeflow) value in microSeconds.
*
* Processing:
* TIMER3 is clocked differently from TIMER1 and TIMER2, so treat
* each separately. For TIMER1 or TIMER2, first convert the time in
* microseconds to counts per 508 kHz clock tick. If the time
* interval is too long to be obtained using the 508 kHz clock,
* convert the time in microseconds to counts per 2 kHz clock tick.
* If the time interval is too long to be obtained using the 2 KHz
* clock, set the count interval to the maximum possible count.
*
* For TIMER3, convert the time in microseconds to counts per
* (roughly) 7.4MHz clock tick. If the time interval is too long to
* be obtained using TIMER3, set the count to the maximum possible
* count.
*
* Parameters:
* timer : Must be TIMER0, TIMER1, TIMER2 or TIMER3
* time_in_us : The desired delay in microseconds
*
* Outputs: None
*
* Returns: Nothing
*
* Notes: None
*
**********************************************************************/
STATIC void timer_set_delay_us(TIMER_REGS_T *timer,
UNS_32 time_in_us)
{
UNS_64 timer_load_value;
/* get the HCLK frequency, assume HCLK is driven by main crystal */
/* It is defined by PLL value / Prescaler */
UNS_32 hclk_freq = (CLOCK_MAINOSC * 21)/(RCPC->hclkprescale * 2);
timer_load_value = ((UNS_64)hclk_freq / 100ul) * (UNS_64)time_in_us;
timer_load_value /= 10000u;
if (timer_load_value > 0xffffu)
{
/* try prescaling hclk by 16 */
timer_load_value = ((UNS_64)hclk_freq / 160ul) * (UNS_64)time_in_us;
timer_load_value /= 100000ul;
if (timer_load_value > 0xffffu)
{
/* try prescaling hclk by 256 */
timer->control &= ~(_BIT(2) | _BIT(3));
timer->control |= TMRCTRL_PRESCALE256;
timer_load_value = ((UNS_64)hclk_freq / 256ul) * (UNS_64)time_in_us;
timer_load_value /= 1000000u;
if (timer_load_value > 0xffffu)
{
timer_load_value = 0xffffu;
}
}
else
{
timer->control &= ~(_BIT(2) | _BIT(3));
timer->control |= TMRCTRL_PRESCALE16;
}
}
timer->load = timer_load_value;
}
/***********************************************************************
* Timer driver public functions
**********************************************************************/
/***********************************************************************
*
* Function: timer_open
*
* Purpose: Open the timer
*
* Processing:
* TBD
*
* Parameters:
* ipbase: Pointer to a timer peripheral block
* arg : Not used
*
* Outputs: None
*
* Returns: The pointer to a timer config structure or 0
*
* Notes: None
*
**********************************************************************/
INT_32 timer_open(void *ipbase, INT_32 arg)
{
TIMER_CFG_T *timercfg;
if ((TIMER_REGS_T *) ipbase == TIMER0)
{
/* Timer 0 selected */
timercfg = &timer0cfg;
/* turn on the timer 0,1 clock in RCPC */
RCPC->periphclksel &= ~(RCPC_CLKCTRL_CT01_DISABLE);
}
else if ((TIMER_REGS_T *) ipbase == TIMER1)
{
/* Timer 1 selected */
timercfg = &timer1cfg;
/* turn on the timer 0,1 clock in RCPC */
RCPC->periphclksel &= ~(RCPC_CLKCTRL_CT01_DISABLE);
}
else if ((TIMER_REGS_T *) ipbase == TIMER2)
{
/* Timer 2 selected */
timercfg = &timer2cfg;
/* turn on the timer 2,3 clock in RCPC */
RCPC->periphclksel &= ~(RCPC_CLKCTRL_CT23_DISABLE);
}
else if ((TIMER_REGS_T *) ipbase == TIMER3)
{
/* Timer 3 selected */
timercfg = &timer3cfg;
/* turn on the timer 2,3 clock in RCPC */
RCPC->periphclksel &= ~(RCPC_CLKCTRL_CT23_DISABLE);
}
else
{
/* Invalid timer */
timercfg = (TIMER_CFG_T *) 0x00000000;
}
if (timercfg != (TIMER_CFG_T *) 0x00000000)
{
/* Valid timer selected, has it been previously initialized? */
if (timercfg->init == FALSE)
{
/* Device not initialized and it usable, so set it to
used */
timercfg->init = TRUE;
/* Save address of register block */
timercfg->regptr = (TIMER_REGS_T *) ipbase;
/* Set default timer state to disabled, prescale is 1,
no cascade, periodic timer */
timercfg->regptr->control = TMRCTRL_MODE_PERIODIC;
/* Clear pending interrupt */
timercfg->regptr->clear = 0x00000000;
}
}
return (INT_32) timercfg;
}
/***********************************************************************
*
* Function: timer_close
*
* Purpose: Close the timer
*
* Processing:
* If init is not TRUE, then return _ERROR to the caller as the
* device was not previously opened. Otherwise, disable the timer,
* set init to FALSE, and return _NO_ERROR to the caller.
*
* Parameters:
* devid: Pointer to timer config structure
*
* Outputs: None
*
* Returns: The status of the close operation
*
* Notes: None
*
**********************************************************************/
STATUS timer_close(INT_32 devid)
{
TIMER_CFG_T *timercfgptr = (TIMER_CFG_T *) devid;
STATUS status = _ERROR;
if (timercfgptr->init == TRUE)
{
/* Disable timer */
timercfgptr->regptr->control &= ~TMRCTRL_ENABLE;
/* Set timer as uninitialized */
timercfgptr->init = FALSE;
/* Successful operation */
status = _NO_ERROR;
}
if ((timer0cfg.init == FALSE) && (timer1cfg.init == FALSE))
{
/* disable the clock for timer 0,1 in RCPC controller */
RCPC->periphclksel |= (RCPC_CLKCTRL_CT01_DISABLE);
}
else if ((timer2cfg.init == FALSE) && (timer3cfg.init == FALSE))
{
/* disable the clock for timer 2,3 in RCPC controller */
RCPC->periphclksel |= (RCPC_CLKCTRL_CT23_DISABLE);
}
return status;
}
/***********************************************************************
*
* Function: timer_ioctl
*
* Purpose: Timer configuration block
*
* Processing:
* This function is a large case block. Based on the passed function
* and option values, set or get the appropriate timer parameter.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -