rtt-f030/bsp/efm32/drv_timer.c
onelife.real ea6d73f140 *** EFM32 branch ***
1. Upgrade Cortex driver library (CMSIS -> CMSIS & Device): version 2.3.2 -> 3.0.1 & 3.0.0
 - Remove "bsp/efm32/Libraries/CMSIS/Lib/ARM", "bsp/efm32/Libraries/CMSIS/Lib/G++" and "bsp/efm32/Libraries/CMSIS/SVD" to save space
2. Upgrade EFM32 driver libraries (efm32lib -> emlib): version 2.3.2 -> 3.0.0
 - Remove "bsp/efm32/Libraries/Device/EnergyMicro/EFM32LG" and "bsp/efm32/Libraries/Device/EnergyMicro/EFM32TG" to save space
3. Upgrade EFM32GG_DK3750 development kit driver library: version 1.2.2 -> 2.0.1
4. Upgrade EFM32_Gxxx_DK development kit driver library: version 1.7.3 -> 2.0.1
5. Add energy management unit driver and test code
6. Modify linker script and related code to compatible with new version of libraries
7. Change EFM32 branch version number to 1.0
8. Add photo frame demo application

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2122 bbd45198-f89e-11dd-88c7-29a3b14d5316
2012-05-18 04:40:40 +00:00

375 lines
11 KiB
C

/***************************************************************************//**
* @file drv_timer.c
* @brief Timer driver of RT-Thread RTOS for EFM32
* COPYRIGHT (C) 2012, RT-Thread Development Team
* @author onelife
* @version 1.0
*******************************************************************************
* @section License
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
*******************************************************************************
* @section Change Logs
* Date Author Notes
* 2011-01-18 onelife Initial creation for EFM32
* 2011-06-17 onelife Modify init function for efm32lib v2 upgrading
******************************************************************************/
/***************************************************************************//**
* @addtogroup efm32
* @{
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "board.h"
#include "drv_timer.h"
#if (defined(RT_USING_TIMER0) || defined(RT_USING_TIMER1) || defined(RT_USING_TIMER2))
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#ifdef RT_TIMER_DEBUG
#define timer_debug(format,args...) rt_kprintf(format, ##args)
#else
#define timer_debug(format,args...)
#endif
#define TIMER_TopCalculate(p) \
(p * (EFM32_HFXO_FREQUENCY / (1 << TMR_CFG_PRESCALER) / 1000))
/* Private variables ---------------------------------------------------------*/
#ifdef RT_USING_TIMER0
static struct rt_device timer0_device;
#endif
#ifdef RT_USING_TIMER1
static struct rt_device timer1_device;
#endif
#ifdef RT_USING_TIMER2
static struct rt_device timer2_device;
#endif
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/***************************************************************************//**
* @brief
* Initialize Timer device
*
* @details
*
* @note
*
* @param[in] dev
* Pointer to device descriptor
*
* @return
* Error code
******************************************************************************/
static rt_err_t rt_hs_timer_init (rt_device_t dev)
{
RT_ASSERT(dev != RT_NULL);
struct efm32_timer_device_t *timer;
timer = (struct efm32_timer_device_t *)(dev->user_data);
timer->hook.cbFunc = RT_NULL;
timer->hook.userPtr = RT_NULL;
return RT_EOK;
}
/***************************************************************************//**
* @brief
* Configure Timer device
*
* @details
*
* @note
*
* @param[in] dev
* Pointer to device descriptor
*
* @param[in] cmd
* Timer control command
*
* @param[in] args
* Arguments
*
* @return
* Error code
******************************************************************************/
static rt_err_t rt_hs_timer_control (
rt_device_t dev,
rt_uint8_t cmd,
void *args)
{
RT_ASSERT(dev != RT_NULL);
struct efm32_timer_device_t *timer;
timer = (struct efm32_timer_device_t *)(dev->user_data);
switch (cmd)
{
case RT_DEVICE_CTRL_SUSPEND:
/* Suspend device */
dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
TIMER_Enable(timer->timer_device, false);
break;
case RT_DEVICE_CTRL_RESUME:
/* Resume device */
dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
TIMER_Enable(timer->timer_device, true);
break;
case RT_DEVICE_CTRL_TIMER_PERIOD:
{
/* change device setting */
struct efm32_timer_control_t *control;
rt_uint32_t running;
control = (struct efm32_timer_control_t *)args;
running = timer->timer_device->STATUS & 0x00000001;
TIMER_Enable(timer->timer_device, false);
timer->timer_device->CNT = _TIMER_CNT_RESETVALUE;
TIMER_TopSet(timer->timer_device, TIMER_TopCalculate(control->period));
timer->hook.cbFunc = control->hook.cbFunc;
timer->hook.userPtr = control->hook.userPtr;
if (running)
{
TIMER_Enable(timer->timer_device, true);
}
}
break;
}
return RT_EOK;
}
/***************************************************************************//**
* @brief
* Register Timer device
*
* @details
*
* @note
*
* @param[in] device
* Pointer to device descriptor
*
* @param[in] name
* Device name
*
* @param[in] flag
* Configuration flags
*
* @param[in] timer
* Pointer to Timer device descriptor
*
* @return
* Error code
******************************************************************************/
rt_err_t rt_hw_timer_register(
rt_device_t device,
const char *name,
rt_uint32_t flag,
struct efm32_timer_device_t *timer)
{
RT_ASSERT(device != RT_NULL);
device->type = RT_Device_Class_Char; /* fixme: should be timer type*/
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = rt_hs_timer_init;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = RT_NULL;
device->write = RT_NULL;
device->control = rt_hs_timer_control;
device->user_data = timer;
/* register a character device */
return rt_device_register(device, name, flag);
}
/***************************************************************************//**
* @brief
* Timer counter overflow interrupt handler
*
* @details
*
* @note
******************************************************************************/
void rt_hw_timer_isr(rt_device_t dev)
{
RT_ASSERT(dev != RT_NULL);
struct efm32_timer_device_t *timer;
timer = (struct efm32_timer_device_t *)(dev->user_data);
if (timer->hook.cbFunc != RT_NULL)
{
(timer->hook.cbFunc)(timer->hook.userPtr);
}
}
/***************************************************************************//**
* @brief
* Initialize the specified TIMER unit
*
* @details
*
* @note
*
* @param[in] device
* Pointer to device descriptor
*
* @param[in] unitNumber
* Unit number
*
* @return
* Pointer to TIMER device
******************************************************************************/
static struct efm32_timer_device_t *rt_hw_timer_unit_init(
rt_device_t device,
rt_uint8_t unitNumber,
rt_uint8_t mode)
{
struct efm32_timer_device_t *timer;
TIMER_Init_TypeDef init;
efm32_irq_hook_init_t hook;
CMU_Clock_TypeDef timerClock;
IRQn_Type timerIrq;
do
{
/* Allocate device */
timer = rt_malloc(sizeof(struct efm32_timer_device_t));
if (timer == RT_NULL)
{
timer_debug("no memory for TIMER%d driver\n", unitNumber);
break;
}
/* Initialization */
if (unitNumber >= TIMER_COUNT)
{
break;
}
switch (unitNumber)
{
case 0:
timer->timer_device = TIMER0;
timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER0;
timerIrq = TIMER0_IRQn;
break;
case 1:
timer->timer_device = TIMER1;
timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER1;
timerIrq = TIMER1_IRQn;
break;
case 2:
timer->timer_device = TIMER2;
timerClock = (CMU_Clock_TypeDef)cmuClock_TIMER2;
timerIrq = TIMER2_IRQn;
break;
default:
break;
}
/* Enable TIMER clock */
CMU_ClockEnable(timerClock, true);
/* Reset */
TIMER_Reset(timer->timer_device);
/* Init specified TIMER unit */
init.enable = false;
init.debugRun = true;
init.prescale = TMR_CFG_PRESCALER;
init.clkSel = timerClkSelHFPerClk;
init.fallAction = timerInputActionNone;
init.riseAction = timerInputActionNone;
init.mode = timerModeUp;
init.dmaClrAct = false;
init.quadModeX4 = false;
init.oneShot = (mode > 0) ? true : false;
init.sync = false;
TIMER_Init(timer->timer_device, &init);
/* Config interrupt and NVIC */
hook.type = efm32_irq_type_timer;
hook.unit = unitNumber;
hook.cbFunc = rt_hw_timer_isr;
hook.userPtr = device;
efm32_irq_hook_register(&hook);
/* Enable overflow interrupt */
TIMER_IntEnable(timer->timer_device, TIMER_IF_OF);
TIMER_IntClear(timer->timer_device, TIMER_IF_OF);
/* Enable TIMERn interrupt vector in NVIC */
NVIC_ClearPendingIRQ(timerIrq);
NVIC_SetPriority(timerIrq, EFM32_IRQ_PRI_DEFAULT);
NVIC_EnableIRQ(timerIrq);
return timer;
} while(0);
if (timer)
{
rt_free(timer);
}
rt_kprintf("TIMER: Init failed!\n");
return RT_NULL;
}
/***************************************************************************//**
* @brief
* Initialize all Timer module related hardware and register Timer device to
* kernel
*
* @details
*
* @note
******************************************************************************/
void rt_hw_timer_init(void)
{
struct efm32_timer_device_t *timer;
#ifdef RT_USING_TIMER0
if ((timer = rt_hw_timer_unit_init(&timer0_device, 0, RT_USING_TIMER0)) \
!= RT_NULL)
{
rt_hw_timer_register(&timer0_device, RT_TIMER0_NAME, 0, timer);
}
#endif
#ifdef RT_USING_TIMER1
if ((timer = rt_hw_timer_unit_init(&timer1_device, 1, RT_USING_TIMER1)) \
!= RT_NULL)
{
rt_hw_timer_register(&timer1_device, RT_TIMER1_NAME, 0, timer);
}
#endif
#ifdef RT_USING_TIMER2
if ((timer = rt_hw_timer_unit_init(&timer2_device, 2, RT_USING_TIMER2)) \
!= RT_NULL)
{
rt_hw_timer_register(&timer2_device, RT_TIMER2_NAME, 0, timer);
}
#endif
}
#endif
/***************************************************************************//**
* @}
******************************************************************************/