267 lines
7.0 KiB
C
267 lines
7.0 KiB
C
|
/******************************************************************//**
|
||
|
* @file drv_timer.c
|
||
|
* @brief USART driver of RT-Thread RTOS for EFM32
|
||
|
* COPYRIGHT (C) 2011, RT-Thread Development Team
|
||
|
* @author onelife
|
||
|
* @version 0.4 beta
|
||
|
**********************************************************************
|
||
|
* @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
|
||
|
*********************************************************************/
|
||
|
|
||
|
/******************************************************************//**
|
||
|
* @addtogroup efm32
|
||
|
* @{
|
||
|
*********************************************************************/
|
||
|
|
||
|
/* Includes -------------------------------------------------------------------*/
|
||
|
#include "board.h"
|
||
|
#include "drv_timer.h"
|
||
|
|
||
|
/* Private typedef -------------------------------------------------------------*/
|
||
|
/* Private define --------------------------------------------------------------*/
|
||
|
/* Private macro --------------------------------------------------------------*/
|
||
|
#define TIMER_TopCalculate(p) \
|
||
|
(p * (HFXO_FREQUENCY / (1 << TMR_CFG_PRESCALER) / 1000))
|
||
|
|
||
|
/* Private variables ------------------------------------------------------------*/
|
||
|
#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;
|
||
|
|
||
|
RT_ASSERT(dev != RT_NULL);
|
||
|
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)
|
||
|
{
|
||
|
struct efm32_timer_device_t *timer;
|
||
|
|
||
|
RT_ASSERT(dev != RT_NULL);
|
||
|
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:
|
||
|
{
|
||
|
/* change device setting */
|
||
|
struct efm32_timer_control_t *control;
|
||
|
|
||
|
control = (struct efm32_timer_control_t *)args;
|
||
|
|
||
|
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;
|
||
|
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)
|
||
|
{
|
||
|
struct efm32_timer_device_t *timer;
|
||
|
|
||
|
RT_ASSERT(dev != RT_NULL);
|
||
|
timer = (struct efm32_timer_device_t *)(dev->user_data);
|
||
|
|
||
|
if (timer->hook.cbFunc != RT_NULL)
|
||
|
{
|
||
|
(timer->hook.cbFunc)(timer->hook.userPtr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************************************************//**
|
||
|
* @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;
|
||
|
TIMER_Init_TypeDef init;
|
||
|
efm32_irq_hook_init_t hook;
|
||
|
|
||
|
/* Set TIMERn parameters */
|
||
|
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 = false;
|
||
|
init.sync = false;
|
||
|
|
||
|
#ifdef RT_USING_TIMER2
|
||
|
timer = rt_malloc(sizeof(struct efm32_timer_device_t));
|
||
|
if (timer == RT_NULL)
|
||
|
{
|
||
|
rt_kprintf("no memory for TIMER driver\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
timer->timer_device = TIMER2;
|
||
|
|
||
|
/* Enable clock for TIMERn module */
|
||
|
CMU_ClockEnable(cmuClock_TIMER2, true);
|
||
|
|
||
|
/* Reset */
|
||
|
TIMER_Reset(TIMER2);
|
||
|
|
||
|
/* Configure TIMER */
|
||
|
TIMER_Init(TIMER2, &init);
|
||
|
|
||
|
hook.type = efm32_irq_type_timer;
|
||
|
hook.unit = 2;
|
||
|
hook.cbFunc = rt_hw_timer_isr;
|
||
|
hook.userPtr = &timer2_device;
|
||
|
efm32_irq_hook_register(&hook);
|
||
|
|
||
|
/* Enable overflow interrupt */
|
||
|
TIMER_IntEnable(TIMER2, TIMER_IF_OF);
|
||
|
TIMER_IntClear(TIMER2, TIMER_IF_OF);
|
||
|
|
||
|
/* Enable TIMERn interrupt vector in NVIC */
|
||
|
NVIC_ClearPendingIRQ(TIMER2_IRQn);
|
||
|
NVIC_SetPriority(TIMER2_IRQn, EFM32_IRQ_PRI_DEFAULT);
|
||
|
NVIC_EnableIRQ(TIMER2_IRQn);
|
||
|
|
||
|
rt_hw_timer_register(&timer2_device, RT_TIMER2_NAME, 0, timer);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/******************************************************************//**
|
||
|
* @}
|
||
|
*********************************************************************/
|