From c84887d021bc0d66352ead42366bd45868e1e4df Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Wed, 2 Sep 2015 22:00:24 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E5=99=A8=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32f40x/drivers/drv_hwtimer.c | 170 ++++++++ bsp/stm32f40x/drivers/drv_hwtimer.h | 8 + bsp/stm32f40x/rtconfig.h | 3 + components/drivers/hwtimer/SConscript | 8 + components/drivers/hwtimer/hwtimer.c | 397 +++++++++++++++++++ components/drivers/include/drivers/hwtimer.h | 83 ++++ components/drivers/include/rtdevice.h | 4 + components/finsh/cmd.c | 1 + include/rtdef.h | 3 +- 9 files changed, 676 insertions(+), 1 deletion(-) create mode 100644 bsp/stm32f40x/drivers/drv_hwtimer.c create mode 100644 bsp/stm32f40x/drivers/drv_hwtimer.h create mode 100644 components/drivers/hwtimer/SConscript create mode 100644 components/drivers/hwtimer/hwtimer.c create mode 100644 components/drivers/include/drivers/hwtimer.h diff --git a/bsp/stm32f40x/drivers/drv_hwtimer.c b/bsp/stm32f40x/drivers/drv_hwtimer.c new file mode 100644 index 0000000000..ba6aed9dcb --- /dev/null +++ b/bsp/stm32f40x/drivers/drv_hwtimer.c @@ -0,0 +1,170 @@ +/* + * File : gpio.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, RT-Thread Development Team + * + * 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 + * + * Change Logs: + * Date Author Notes + * 2015-09-02 heyuanjie87 the first version + */ + +#include +#include +#include +#include "drv_hwtimer.h" + +#ifdef RT_USING_HWTIMER + +static void NVIC_Configuration(void) +{ + NVIC_InitTypeDef NVIC_InitStructure; + + /* Enable the TIM5 global Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +} + +static void timer_init(rt_hwtimer_t *timer) +{ + TIM_TypeDef *tim; + + tim = (TIM_TypeDef *)timer->parent.user_data; + + TIM_DeInit(tim); + NVIC_Configuration(); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + TIM_CounterModeConfig(tim, TIM_CounterMode_Up); +} + +static void timer_deinit(rt_hwtimer_t *timer) +{ + TIM_TypeDef *tim; + + tim = (TIM_TypeDef *)timer->parent.user_data; + TIM_DeInit(tim); +} + +static void timer_start(rt_hwtimer_t *timer, rt_hwtimer_mode_t opmode) +{ + TIM_TypeDef *tim; + uint16_t m; + + tim = (TIM_TypeDef *)timer->parent.user_data; + m = (opmode == HWTIMER_MODE_ONESHOT)? TIM_OPMode_Single : TIM_OPMode_Repetitive; + TIM_SelectOnePulseMode(tim, m); + TIM_Cmd(tim, ENABLE); +} + +static void timer_stop(rt_hwtimer_t *timer) +{ + TIM_TypeDef *tim; + + tim = (TIM_TypeDef *)timer->parent.user_data; + TIM_Cmd(tim, DISABLE); +} + +static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) +{ + TIM_TypeDef *tim; + rt_err_t err = RT_EOK; + + tim = (TIM_TypeDef *)timer->parent.user_data; + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + RCC_ClocksTypeDef clk; + uint16_t val; + rt_uint32_t freq; + + RCC_GetClocksFreq(&clk); + + freq = *((rt_uint32_t*)arg); + clk.PCLK1_Frequency *= 2; + val = clk.PCLK1_Frequency/freq; + + TIM_ITConfig(tim, TIM_IT_Update, DISABLE); + TIM_PrescalerConfig(tim, val - 1, TIM_PSCReloadMode_Immediate); + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + TIM_ITConfig(tim, TIM_IT_Update, ENABLE); + } + break; + default: + { + err = -RT_ENOSYS; + } + break; + } + + return err; +} + +static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer) +{ + TIM_TypeDef *tim; + + tim = (TIM_TypeDef *)timer->parent.user_data; + + return TIM_GetCounter(tim); +} + +static rt_err_t timer_timeout_set(rt_hwtimer_t *timer, rt_uint32_t t) +{ + TIM_TypeDef *tim; + + tim = (TIM_TypeDef *)timer->parent.user_data; + TIM_SetAutoreload(tim, t); + + return RT_EOK; +} + +static const struct rt_hwtimer_info _info = +{ + 1000000, /* 可设置的最大计数时钟 */ + 2000, /* 可设置的最小计数时钟 */ + 0xFFFF, /* 最大超时值 */ + HWTIMER_CNTMODE_UP,/* 递增计数方式 */ +}; + +static const struct rt_hwtimer_ops _ops = +{ + timer_init, + timer_deinit, + timer_start, + timer_stop, + timer_timeout_set, + timer_counter_get, + timer_ctrl, +}; + +static rt_hwtimer_t _timer0; + +int stm32_hwtimer_init(void) +{ + _timer0.info = &_info; + _timer0.ops = &_ops; + + rt_device_hwtimer_register(&_timer0, "timer0", TIM2); + + return 0; +} + +void TIM2_IRQHandler(void) +{ + if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) + { + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + rt_device_hwtimer_isr(&_timer0); + } +} + +INIT_BOARD_EXPORT(stm32_hwtimer_init); +#endif diff --git a/bsp/stm32f40x/drivers/drv_hwtimer.h b/bsp/stm32f40x/drivers/drv_hwtimer.h new file mode 100644 index 0000000000..b45b27dc06 --- /dev/null +++ b/bsp/stm32f40x/drivers/drv_hwtimer.h @@ -0,0 +1,8 @@ +#ifndef __DRV_HWTIMER_H__ +#define __DRV_HWTIMER_H__ + + +int stm32_hwtimer_init(void); + + +#endif diff --git a/bsp/stm32f40x/rtconfig.h b/bsp/stm32f40x/rtconfig.h index 88dfd0b616..9cca3f8424 100644 --- a/bsp/stm32f40x/rtconfig.h +++ b/bsp/stm32f40x/rtconfig.h @@ -69,6 +69,9 @@ /* Using GPIO pin framework */ #define RT_USING_PIN +/* Using Hardware Timer framework */ +//#define RT_USING_HWTIMER + /* SECTION: Console options */ #define RT_USING_CONSOLE /* the buffer size of console*/ diff --git a/components/drivers/hwtimer/SConscript b/components/drivers/hwtimer/SConscript new file mode 100644 index 0000000000..534e04b6c0 --- /dev/null +++ b/components/drivers/hwtimer/SConscript @@ -0,0 +1,8 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd + '/../include'] +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_HWTIMER'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/hwtimer/hwtimer.c b/components/drivers/hwtimer/hwtimer.c new file mode 100644 index 0000000000..0d2df8f8ea --- /dev/null +++ b/components/drivers/hwtimer/hwtimer.c @@ -0,0 +1,397 @@ +/* + * File : hwtimer.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-08-31 heyuanjie87 first version + */ + +#include +#include + +rt_inline rt_err_t timeout_set(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) +{ + rt_err_t err; + float overflow; + float timeout; + rt_uint32_t counter; + int i, index; + float tv_sec; + float devi_min = 1; + float devi; + + if (timer->ops->stop != RT_NULL) + { + timer->ops->stop(timer); + } + else + { + return -RT_ENOSYS; + } + + /* 把定时器溢出时间和定时时间换算成秒 */ + overflow = timer->info->maxcnt/(float)timer->freq; + tv_sec = tv->sec + tv->usec/(float)1000000; + + if (tv_sec < (1/(float)timer->freq)) + { + /* 定时时间小于计数周期 */ + i = 0; + timeout = 1/(float)timer->freq; + } + else + { + for (i = 1; i > 0; i ++) + { + timeout = tv_sec/i; + + if (timeout <= overflow) + { + counter = timeout*timer->freq; + devi = tv_sec - (counter/(float)timer->freq)*i; + /* 计算最小误差 */ + if (devi > devi_min) + { + i = index; + timeout = tv_sec/i; + break; + } + else if (devi == 0) + { + break; + } + else if (devi < devi_min) + { + devi_min = devi; + index = i; + } + } + } + } + + timer->cycles = i; + timer->reload = i; + timer->period_sec = timeout; + counter = timeout*timer->freq; + + if (timer->ops->timeout_set != RT_NULL) + { + err = timer->ops->timeout_set(timer, counter); + } + + return err; +} + +static rt_err_t rt_hwtimer_init(struct rt_device *dev) +{ + rt_err_t result = RT_EOK; + rt_hwtimer_t *timer; + + timer = (rt_hwtimer_t *)dev; + /* 尝试将默认计数频率设为1Mhz */ + if ((1000000 <= timer->info->maxfreq) && (1000000 >= timer->info->minfreq)) + { + timer->freq = 1000000; + } + else + { + timer->freq = timer->info->minfreq; + } + timer->mode = HWTIMER_MODE_ONESHOT; + timer->cycles = 0; + + if (timer->ops->init) + { + timer->ops->init(timer); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +static rt_err_t rt_hwtimer_open(struct rt_device *dev, rt_uint16_t oflag) +{ + rt_err_t result = RT_EOK; + rt_hwtimer_t *timer; + + timer = (rt_hwtimer_t *)dev; + if (timer->ops->control != RT_NULL) + { + timer->ops->control(timer, HWTIMER_CTRL_FREQ_SET, &timer->freq); + } + else + { + result = -RT_ENOSYS; + } + + return result; +} + +static rt_err_t rt_hwtimer_close(struct rt_device *dev) +{ + rt_err_t result = RT_EOK; + rt_hwtimer_t *timer; + + timer = (rt_hwtimer_t*)dev; + if (timer->ops->deinit != RT_NULL) + { + timer->ops->deinit(timer); + } + else + { + result = -RT_ENOSYS; + } + + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + dev->rx_indicate = RT_NULL; + + return result; +} + +static rt_size_t rt_hwtimer_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + rt_hwtimer_t *timer; + rt_hwtimerval_t tv; + rt_uint32_t cnt; + float t; + + timer = (rt_hwtimer_t *)dev; + if (timer->ops->count_get == RT_NULL) + return 0; + + cnt = timer->ops->count_get(timer); + if (timer->info->cntmode == HWTIMER_CNTMODE_DW) + { + cnt = timer->info->maxcnt - cnt; + } + + t = timer->overflow * timer->period_sec + cnt/(float)timer->freq; + tv.sec = t; + tv.usec = (t - tv.sec) * 1000000; + size = size > sizeof(tv)? sizeof(tv) : size; + rt_memcpy(buffer, &tv, size); + + return size; +} + +static rt_size_t rt_hwtimer_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + rt_size_t len = 0; + rt_hwtimerval_t *t; + rt_err_t err; + + if (size == sizeof(rt_hwtimerval_t)) + { + t = (rt_hwtimerval_t*)buffer; + err = timeout_set((rt_hwtimer_t*)dev, t); + if (err == RT_EOK) + { + len = size; + } + } + + return len; +} + +static rt_err_t rt_hwtimer_control(struct rt_device *dev, rt_uint8_t cmd, void *args) +{ + rt_err_t result = RT_EOK; + rt_hwtimer_t *timer; + + timer = (rt_hwtimer_t *)dev; + + switch (cmd) + { + case HWTIMER_CTRL_START: + { + if (timer->ops->start != RT_NULL) + { + rt_hwtimer_mode_t opm; + + if ((timer->cycles <= 1) && (timer->mode == HWTIMER_MODE_ONESHOT)) + { + opm = HWTIMER_MODE_ONESHOT; + } + else + { + opm = HWTIMER_MODE_PERIOD; + } + + timer->overflow = 0; + + timer->ops->start(timer, opm); + } + else + { + result = -RT_ENOSYS; + } + } + break; + case HWTIMER_CTRL_STOP: + { + if (timer->ops->stop != RT_NULL) + { + timer->ops->stop(timer); + } + else + { + result = -RT_ENOSYS; + } + } + break; + case HWTIMER_CTRL_TIMEOUT_SET: + { + if (args == RT_NULL) + { + result = -RT_EEMPTY; + break; + } + + result = timeout_set(timer, (rt_hwtimerval_t*)args); + } + break; + case HWTIMER_CTRL_FREQ_SET: + { + rt_uint32_t *f; + + if (args == RT_NULL) + { + result = -RT_EEMPTY; + break; + } + + f = (rt_uint32_t*)args; + if ((*f > timer->info->maxfreq) || (*f < timer->info->minfreq)) + { + result = -RT_ERROR; + break; + } + + if (timer->ops->control != RT_NULL) + { + result = timer->ops->control(timer, cmd, args); + if (result == RT_EOK) + { + timer->freq = *f; + } + } + else + { + result = -RT_ENOSYS; + } + } + break; + case HWTIMER_CTRL_INFO_GET: + { + if (args == RT_NULL) + { + result = -RT_EEMPTY; + break; + } + + *((struct rt_hwtimer_info*)args) = *timer->info; + } + case HWTIMER_CTRL_MODE_SET: + { + rt_hwtimer_mode_t *m; + + if (args == RT_NULL) + { + result = -RT_EEMPTY; + break; + } + + m = (rt_hwtimer_mode_t*)args; + + if ((*m != HWTIMER_MODE_ONESHOT) && (*m != HWTIMER_MODE_PERIOD)) + { + result = -RT_ERROR; + break; + } + + timer->mode = *m; + } + break; + default: + { + result = -RT_ENOSYS; + } + break; + } + + return result; +} + +void rt_device_hwtimer_isr(rt_hwtimer_t *timer) +{ + RT_ASSERT(timer != RT_NULL); + + timer->overflow ++; + + if (timer->cycles != 0) + { + timer->cycles --; + } + + if (timer->cycles == 0) + { + timer->cycles = timer->reload; + + if (timer->mode == HWTIMER_MODE_ONESHOT) + { + if (timer->ops->stop != RT_NULL) + { + timer->ops->stop(timer); + } + } + + if (timer->parent.rx_indicate != RT_NULL) + { + timer->parent.rx_indicate(&timer->parent, sizeof(struct rt_hwtimerval)); + } + } +} + +rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data) +{ + struct rt_device *device; + + RT_ASSERT(timer != RT_NULL); + RT_ASSERT(timer->ops != RT_NULL); + RT_ASSERT(timer->info != RT_NULL); + + device = &(timer->parent); + + device->type = RT_Device_Class_HwTimer; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + + device->init = rt_hwtimer_init; + device->open = rt_hwtimer_open; + device->close = rt_hwtimer_close; + device->read = rt_hwtimer_read; + device->write = rt_hwtimer_write; + device->control = rt_hwtimer_control; + device->user_data = user_data; + + return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); +} diff --git a/components/drivers/include/drivers/hwtimer.h b/components/drivers/include/drivers/hwtimer.h new file mode 100644 index 0000000000..e5b5d4661b --- /dev/null +++ b/components/drivers/include/drivers/hwtimer.h @@ -0,0 +1,83 @@ +#ifndef __HWTIMER_H__ +#define __HWTIMER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* 定时器控制命令 */ +typedef enum +{ + HWTIMER_CTRL_TIMEOUT_SET = 0x01, /* 设置超时值 */ + HWTIMER_CTRL_FREQ_SET, /* 设置计数频率 */ + HWTIMER_CTRL_START, /* 启动定时器 */ + HWTIMER_CTRL_STOP, /* 停止定时器 */ + HWTIMER_CTRL_INFO_GET, /* 获取定时器特征信息 */ + HWTIMER_CTRL_MODE_SET /* 设置定时模式 */ +} rt_hwtimer_ctrl_t; + +/* 定时模式 */ +typedef enum +{ + HWTIMER_MODE_ONESHOT = 0x01, + HWTIMER_MODE_PERIOD +} rt_hwtimer_mode_t; + +/* 定时器计数值 */ +typedef struct rt_hwtimerval +{ + rt_int32_t sec; /* 秒 */ + rt_int32_t usec; /* 微秒 */ +} rt_hwtimerval_t; + +#define HWTIMER_CNTMODE_UP 0x01 /* 定时器递增计数方式 */ +#define HWTIMER_CNTMODE_DW 0x02 /* 定时器递减计数方式 */ + +struct rt_hwtimer_device; + +struct rt_hwtimer_ops +{ + void (*init)(struct rt_hwtimer_device *timer); + void (*deinit)(struct rt_hwtimer_device *timer); + void (*start)(struct rt_hwtimer_device *timer, rt_hwtimer_mode_t mode); + void (*stop)(struct rt_hwtimer_device *timer); + rt_err_t (*timeout_set)(struct rt_hwtimer_device *timer, rt_uint32_t t); + rt_uint32_t (*count_get)(struct rt_hwtimer_device *timer); + rt_err_t (*control)(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args); +}; + +/* 定时器基本参数(不可动态更改) */ +struct rt_hwtimer_info +{ + rt_int32_t maxfreq; /* 定时器支持的最大计数时钟 */ + rt_int32_t minfreq; /* 定时器支持的最小计数时钟 */ + rt_uint32_t maxcnt; /* 计数器最大超时值 */ + rt_uint8_t cntmode; /* 计数模式(递增/递减,应用层无需关心此参数) */ +}; + +typedef struct rt_hwtimer_device +{ + struct rt_device parent; + const struct rt_hwtimer_ops *ops; + const struct rt_hwtimer_info *info; + + /* 驱动层不用关心以下参数 */ + rt_int32_t freq; /* 计数频率 */ + rt_int32_t overflow; /* 溢出次数 */ + float period_sec; /* 溢出周期(s) */ + rt_int32_t cycles; /* 循环次数 */ + rt_int32_t reload; /* 重载cycles */ + rt_hwtimer_mode_t mode; /* 定时模式 */ +} rt_hwtimer_t; + +rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data); +void rt_device_hwtimer_isr(rt_hwtimer_t *timer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index f4d967831c..475adebf80 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -370,6 +370,10 @@ rt_inline void rt_work_init(struct rt_work* work, void (*work_func)(struct rt_wo #include "drivers/can.h" #endif +#ifdef RT_USING_HWTIMER +#include "drivers/hwtimer.h" +#endif + #ifdef __cplusplus } #endif diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 7d24a33d6a..6e2ca631e3 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -468,6 +468,7 @@ static long _list_device(struct rt_list_node *list) "Pipe", "Portal Device", "Miscellaneous Device", + "Hardware Timer Device", "Unknown" }; diff --git a/include/rtdef.h b/include/rtdef.h index 2587df9c41..eda5d5da79 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -759,7 +759,8 @@ enum rt_device_class_type RT_Device_Class_Pipe, /**< Pipe device */ RT_Device_Class_Portal, /**< Portal device */ RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ - RT_Device_Class_Unknown /**< unknown device */ + RT_Device_Class_HwTimer, /**< Hardware timer device */ + RT_Device_Class_Unknown /**< unknown device */ }; /** From 47b3a4d3cc090dcf3a9abd554178acecc3c016cd Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Wed, 2 Sep 2015 22:03:16 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E5=99=A8=E4=BD=BF=E7=94=A8=E8=8C=83=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/test/hwtimer_test.c | 82 ++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 examples/test/hwtimer_test.c diff --git a/examples/test/hwtimer_test.c b/examples/test/hwtimer_test.c new file mode 100644 index 0000000000..e90f5c4783 --- /dev/null +++ b/examples/test/hwtimer_test.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#ifdef RT_USING_HWTIMER + +#define TIMER "timer0" + +static rt_err_t timer_timeout_cb(rt_device_t dev, rt_size_t size) +{ + rt_kprintf("HT %d\n", rt_tick_get()); + + return 0; +} + +int hwtimer(int freq, int t) +{ + rt_err_t err; + rt_hwtimerval_t val; + rt_device_t dev = RT_NULL; + rt_tick_t tick; + rt_hwtimer_mode_t mode; + + t = (t <= 0)? 5 : t; + + if ((dev = rt_device_find(TIMER)) == RT_NULL) + { + rt_kprintf("No Device: %s\n", TIMER); + return -1; + } + + if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK) + { + rt_kprintf("Open %s Fail\n", TIMER); + return -1; + } + + rt_device_set_rx_indicate(dev, timer_timeout_cb); + /* 计数时钟设置(默认1Mhz或支持的最小计数频率) */ + err = rt_device_control(dev, HWTIMER_CTRL_FREQ_SET, &freq); + if (err != RT_EOK) + { + rt_kprintf("Set Freq=%dhz Fail\n", freq); + goto EXIT; + } + + /* 设置定时器超时值 */ + val.sec = t; + val.usec = 0; + rt_kprintf("SetTime: Sec %d, Usec %d\n", val.sec, val.usec); + if (rt_device_write(dev, 0, &val, sizeof(val)) != sizeof(val)) + { + rt_kprintf("SetTime Fail\n"); + goto EXIT; + } + + /* 周期模式 */ + mode = HWTIMER_MODE_PERIOD; + err = rt_device_control(dev, HWTIMER_CTRL_MODE_SET, &mode); + /* 启动定时器 */ + tick = rt_tick_get(); + err = rt_device_control(dev, HWTIMER_CTRL_START, RT_NULL); + rt_kprintf("Start Timer> Tick: %d\n", tick); + rt_kprintf("Sleep %d sec\n", t); + rt_thread_delay(t*RT_TICK_PER_SECOND); + + /* 停止定时器 */ + err = rt_device_control(dev, HWTIMER_CTRL_STOP, RT_NULL); + rt_kprintf("Timer Stoped\n"); + /* 读取计数 */ + rt_device_read(dev, 0, &val, sizeof(val)); + rt_kprintf("Read: Sec = %d, Usec = %d\n", val.sec, val.usec); + +EXIT: + err = rt_device_close(dev); + rt_kprintf("Close %s\n", TIMER); + + return err; +} + +FINSH_FUNCTION_EXPORT(hwtimer, "Test hardware timer"); +#endif From d19f424909bbcaa22b222728aa94b65e4aa8a9ed Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Sun, 6 Sep 2015 15:05:47 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E7=AE=80=E5=8C=96=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/stm32f40x/drivers/drv_hwtimer.c | 55 +++++------- components/drivers/hwtimer/hwtimer.c | 94 ++++++-------------- components/drivers/include/drivers/hwtimer.h | 53 +++++------ examples/test/hwtimer_test.c | 24 +++-- 4 files changed, 82 insertions(+), 144 deletions(-) diff --git a/bsp/stm32f40x/drivers/drv_hwtimer.c b/bsp/stm32f40x/drivers/drv_hwtimer.c index ba6aed9dcb..8802021e18 100644 --- a/bsp/stm32f40x/drivers/drv_hwtimer.c +++ b/bsp/stm32f40x/drivers/drv_hwtimer.c @@ -1,5 +1,5 @@ /* - * File : gpio.c + * File : drv_hwtimer.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2015, RT-Thread Development Team * @@ -31,35 +31,34 @@ static void NVIC_Configuration(void) NVIC_Init(&NVIC_InitStructure); } -static void timer_init(rt_hwtimer_t *timer) +static void timer_init(rt_hwtimer_t *timer, rt_uint32_t state) { TIM_TypeDef *tim; tim = (TIM_TypeDef *)timer->parent.user_data; TIM_DeInit(tim); - NVIC_Configuration(); - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - TIM_CounterModeConfig(tim, TIM_CounterMode_Up); + + if (state == 1) + { + NVIC_Configuration(); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + TIM_CounterModeConfig(tim, TIM_CounterMode_Up); + } } -static void timer_deinit(rt_hwtimer_t *timer) -{ - TIM_TypeDef *tim; - - tim = (TIM_TypeDef *)timer->parent.user_data; - TIM_DeInit(tim); -} - -static void timer_start(rt_hwtimer_t *timer, rt_hwtimer_mode_t opmode) +static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode) { TIM_TypeDef *tim; uint16_t m; tim = (TIM_TypeDef *)timer->parent.user_data; + TIM_SetAutoreload(tim, t); m = (opmode == HWTIMER_MODE_ONESHOT)? TIM_OPMode_Single : TIM_OPMode_Repetitive; TIM_SelectOnePulseMode(tim, m); TIM_Cmd(tim, ENABLE); + + return RT_EOK; } static void timer_stop(rt_hwtimer_t *timer) @@ -90,11 +89,11 @@ static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) freq = *((rt_uint32_t*)arg); clk.PCLK1_Frequency *= 2; val = clk.PCLK1_Frequency/freq; - - TIM_ITConfig(tim, TIM_IT_Update, DISABLE); + + TIM_ITConfig(tim, TIM_IT_Update, DISABLE); TIM_PrescalerConfig(tim, val - 1, TIM_PSCReloadMode_Immediate); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(tim, TIM_IT_Update, ENABLE); + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + TIM_ITConfig(tim, TIM_IT_Update, ENABLE); } break; default: @@ -116,31 +115,19 @@ static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer) return TIM_GetCounter(tim); } -static rt_err_t timer_timeout_set(rt_hwtimer_t *timer, rt_uint32_t t) -{ - TIM_TypeDef *tim; - - tim = (TIM_TypeDef *)timer->parent.user_data; - TIM_SetAutoreload(tim, t); - - return RT_EOK; -} - static const struct rt_hwtimer_info _info = { - 1000000, /* 可设置的最大计数时钟 */ - 2000, /* 可设置的最小计数时钟 */ - 0xFFFF, /* 最大超时值 */ - HWTIMER_CNTMODE_UP,/* 递增计数方式 */ + 1000000, /* the maximum count frequency can be set */ + 2000, /* the minimum count frequency can be set */ + 0xFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP,/* Increment or Decreasing count mode */ }; static const struct rt_hwtimer_ops _ops = { timer_init, - timer_deinit, timer_start, timer_stop, - timer_timeout_set, timer_counter_get, timer_ctrl, }; diff --git a/components/drivers/hwtimer/hwtimer.c b/components/drivers/hwtimer/hwtimer.c index 0d2df8f8ea..22b8d6262c 100644 --- a/components/drivers/hwtimer/hwtimer.c +++ b/components/drivers/hwtimer/hwtimer.c @@ -25,9 +25,8 @@ #include #include -rt_inline rt_err_t timeout_set(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) +rt_inline rt_uint32_t timeout_calc(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) { - rt_err_t err; float overflow; float timeout; rt_uint32_t counter; @@ -36,15 +35,6 @@ rt_inline rt_err_t timeout_set(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) float devi_min = 1; float devi; - if (timer->ops->stop != RT_NULL) - { - timer->ops->stop(timer); - } - else - { - return -RT_ENOSYS; - } - /* 把定时器溢出时间和定时时间换算成秒 */ overflow = timer->info->maxcnt/(float)timer->freq; tv_sec = tv->sec + tv->usec/(float)1000000; @@ -90,12 +80,7 @@ rt_inline rt_err_t timeout_set(rt_hwtimer_t *timer, rt_hwtimerval_t *tv) timer->period_sec = timeout; counter = timeout*timer->freq; - if (timer->ops->timeout_set != RT_NULL) - { - err = timer->ops->timeout_set(timer, counter); - } - - return err; + return counter; } static rt_err_t rt_hwtimer_init(struct rt_device *dev) @@ -115,10 +100,11 @@ static rt_err_t rt_hwtimer_init(struct rt_device *dev) } timer->mode = HWTIMER_MODE_ONESHOT; timer->cycles = 0; + timer->overflow = 0; if (timer->ops->init) { - timer->ops->init(timer); + timer->ops->init(timer, 1); } else { @@ -152,9 +138,9 @@ static rt_err_t rt_hwtimer_close(struct rt_device *dev) rt_hwtimer_t *timer; timer = (rt_hwtimer_t*)dev; - if (timer->ops->deinit != RT_NULL) + if (timer->ops->init != RT_NULL) { - timer->ops->deinit(timer); + timer->ops->init(timer, 0); } else { @@ -195,21 +181,29 @@ static rt_size_t rt_hwtimer_read(struct rt_device *dev, rt_off_t pos, void *buff static rt_size_t rt_hwtimer_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { - rt_size_t len = 0; - rt_hwtimerval_t *t; - rt_err_t err; + rt_uint32_t t; + rt_hwtimer_mode_t opm = HWTIMER_MODE_PERIOD; + rt_hwtimer_t *timer; - if (size == sizeof(rt_hwtimerval_t)) + timer = (rt_hwtimer_t *)dev; + if ((timer->ops->start == RT_NULL) || (timer->ops->stop == RT_NULL)) + return 0; + + if (size != sizeof(rt_hwtimerval_t)) + return 0; + + if ((timer->cycles <= 1) && (timer->mode == HWTIMER_MODE_ONESHOT)) { - t = (rt_hwtimerval_t*)buffer; - err = timeout_set((rt_hwtimer_t*)dev, t); - if (err == RT_EOK) - { - len = size; - } + opm = HWTIMER_MODE_ONESHOT; } + timer->ops->stop(timer); + timer->overflow = 0; - return len; + t = timeout_calc(timer, (rt_hwtimerval_t*)buffer); + if (timer->ops->start(timer, t, opm) != RT_EOK) + size = 0; + + return size; } static rt_err_t rt_hwtimer_control(struct rt_device *dev, rt_uint8_t cmd, void *args) @@ -221,31 +215,6 @@ static rt_err_t rt_hwtimer_control(struct rt_device *dev, rt_uint8_t cmd, void * switch (cmd) { - case HWTIMER_CTRL_START: - { - if (timer->ops->start != RT_NULL) - { - rt_hwtimer_mode_t opm; - - if ((timer->cycles <= 1) && (timer->mode == HWTIMER_MODE_ONESHOT)) - { - opm = HWTIMER_MODE_ONESHOT; - } - else - { - opm = HWTIMER_MODE_PERIOD; - } - - timer->overflow = 0; - - timer->ops->start(timer, opm); - } - else - { - result = -RT_ENOSYS; - } - } - break; case HWTIMER_CTRL_STOP: { if (timer->ops->stop != RT_NULL) @@ -258,17 +227,6 @@ static rt_err_t rt_hwtimer_control(struct rt_device *dev, rt_uint8_t cmd, void * } } break; - case HWTIMER_CTRL_TIMEOUT_SET: - { - if (args == RT_NULL) - { - result = -RT_EEMPTY; - break; - } - - result = timeout_set(timer, (rt_hwtimerval_t*)args); - } - break; case HWTIMER_CTRL_FREQ_SET: { rt_uint32_t *f; @@ -381,7 +339,7 @@ rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void device = &(timer->parent); - device->type = RT_Device_Class_HwTimer; + device->type = RT_Device_Class_Timer; device->rx_indicate = RT_NULL; device->tx_complete = RT_NULL; diff --git a/components/drivers/include/drivers/hwtimer.h b/components/drivers/include/drivers/hwtimer.h index e5b5d4661b..24cec74d32 100644 --- a/components/drivers/include/drivers/hwtimer.h +++ b/components/drivers/include/drivers/hwtimer.h @@ -8,54 +8,50 @@ extern "C" { #endif -/* 定时器控制命令 */ +/* Timer Control Command */ typedef enum { - HWTIMER_CTRL_TIMEOUT_SET = 0x01, /* 设置超时值 */ - HWTIMER_CTRL_FREQ_SET, /* 设置计数频率 */ - HWTIMER_CTRL_START, /* 启动定时器 */ - HWTIMER_CTRL_STOP, /* 停止定时器 */ - HWTIMER_CTRL_INFO_GET, /* 获取定时器特征信息 */ - HWTIMER_CTRL_MODE_SET /* 设置定时模式 */ + HWTIMER_CTRL_FREQ_SET = 0x01, /* set the count frequency */ + HWTIMER_CTRL_STOP, /* stop timer */ + HWTIMER_CTRL_INFO_GET, /* get a timer feature information */ + HWTIMER_CTRL_MODE_SET /* Setting the timing mode(oneshot/period) */ } rt_hwtimer_ctrl_t; -/* 定时模式 */ +/* Timing Mode */ typedef enum { HWTIMER_MODE_ONESHOT = 0x01, HWTIMER_MODE_PERIOD } rt_hwtimer_mode_t; -/* 定时器计数值 */ +/* Time Value */ typedef struct rt_hwtimerval { - rt_int32_t sec; /* 秒 */ - rt_int32_t usec; /* 微秒 */ + rt_int32_t sec; /* second */ + rt_int32_t usec; /* microsecond */ } rt_hwtimerval_t; -#define HWTIMER_CNTMODE_UP 0x01 /* 定时器递增计数方式 */ -#define HWTIMER_CNTMODE_DW 0x02 /* 定时器递减计数方式 */ +#define HWTIMER_CNTMODE_UP 0x01 /* increment count mode */ +#define HWTIMER_CNTMODE_DW 0x02 /* decreasing count mode */ struct rt_hwtimer_device; struct rt_hwtimer_ops { - void (*init)(struct rt_hwtimer_device *timer); - void (*deinit)(struct rt_hwtimer_device *timer); - void (*start)(struct rt_hwtimer_device *timer, rt_hwtimer_mode_t mode); + void (*init)(struct rt_hwtimer_device *timer, rt_uint32_t state); + rt_err_t (*start)(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode); void (*stop)(struct rt_hwtimer_device *timer); - rt_err_t (*timeout_set)(struct rt_hwtimer_device *timer, rt_uint32_t t); rt_uint32_t (*count_get)(struct rt_hwtimer_device *timer); rt_err_t (*control)(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args); }; -/* 定时器基本参数(不可动态更改) */ +/* Timer Feature Information */ struct rt_hwtimer_info { - rt_int32_t maxfreq; /* 定时器支持的最大计数时钟 */ - rt_int32_t minfreq; /* 定时器支持的最小计数时钟 */ - rt_uint32_t maxcnt; /* 计数器最大超时值 */ - rt_uint8_t cntmode; /* 计数模式(递增/递减,应用层无需关心此参数) */ + rt_int32_t maxfreq; /* the maximum count frequency timer support */ + rt_int32_t minfreq; /* the minimum count frequency timer support */ + rt_uint32_t maxcnt; /* counter maximum value */ + rt_uint8_t cntmode; /* count mode (inc/dec) */ }; typedef struct rt_hwtimer_device @@ -64,13 +60,12 @@ typedef struct rt_hwtimer_device const struct rt_hwtimer_ops *ops; const struct rt_hwtimer_info *info; - /* 驱动层不用关心以下参数 */ - rt_int32_t freq; /* 计数频率 */ - rt_int32_t overflow; /* 溢出次数 */ - float period_sec; /* 溢出周期(s) */ - rt_int32_t cycles; /* 循环次数 */ - rt_int32_t reload; /* 重载cycles */ - rt_hwtimer_mode_t mode; /* 定时模式 */ + rt_int32_t freq; /* counting frequency set by the user */ + rt_int32_t overflow; /* timer overflows */ + float period_sec; + rt_int32_t cycles; /* how many times will generate a timeout event after overflow */ + rt_int32_t reload; /* reload cycles(using in period mode) */ + rt_hwtimer_mode_t mode; /* timing mode(oneshot/period) */ } rt_hwtimer_t; rt_err_t rt_device_hwtimer_register(rt_hwtimer_t *timer, const char *name, void *user_data); diff --git a/examples/test/hwtimer_test.c b/examples/test/hwtimer_test.c index e90f5c4783..8f69c4ef87 100644 --- a/examples/test/hwtimer_test.c +++ b/examples/test/hwtimer_test.c @@ -13,15 +13,15 @@ static rt_err_t timer_timeout_cb(rt_device_t dev, rt_size_t size) return 0; } -int hwtimer(int freq, int t) +int hwtimer(void) { rt_err_t err; rt_hwtimerval_t val; rt_device_t dev = RT_NULL; rt_tick_t tick; rt_hwtimer_mode_t mode; - - t = (t <= 0)? 5 : t; + int freq = 10000; + int t = 5; if ((dev = rt_device_find(TIMER)) == RT_NULL) { @@ -32,7 +32,7 @@ int hwtimer(int freq, int t) if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK) { rt_kprintf("Open %s Fail\n", TIMER); - return -1; + return -1; } rt_device_set_rx_indicate(dev, timer_timeout_cb); @@ -44,7 +44,13 @@ int hwtimer(int freq, int t) goto EXIT; } - /* 设置定时器超时值 */ + /* 周期模式 */ + mode = HWTIMER_MODE_PERIOD; + err = rt_device_control(dev, HWTIMER_CTRL_MODE_SET, &mode); + + tick = rt_tick_get(); + rt_kprintf("Start Timer> Tick: %d\n", tick); + /* 设置定时器超时值并启动定时器 */ val.sec = t; val.usec = 0; rt_kprintf("SetTime: Sec %d, Usec %d\n", val.sec, val.usec); @@ -53,14 +59,6 @@ int hwtimer(int freq, int t) rt_kprintf("SetTime Fail\n"); goto EXIT; } - - /* 周期模式 */ - mode = HWTIMER_MODE_PERIOD; - err = rt_device_control(dev, HWTIMER_CTRL_MODE_SET, &mode); - /* 启动定时器 */ - tick = rt_tick_get(); - err = rt_device_control(dev, HWTIMER_CTRL_START, RT_NULL); - rt_kprintf("Start Timer> Tick: %d\n", tick); rt_kprintf("Sleep %d sec\n", t); rt_thread_delay(t*RT_TICK_PER_SECOND); From 8f9bda579a4027cd88e44d6dcdfd61fc5d667a6f Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Sun, 6 Sep 2015 15:18:15 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E5=AE=9A=E4=B9=89Timer=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/finsh/cmd.c | 2 +- include/rtdef.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 6e2ca631e3..c42b412f23 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -467,8 +467,8 @@ static long _list_device(struct rt_list_node *list) "PM Pseudo Device", "Pipe", "Portal Device", + "Timer Device", "Miscellaneous Device", - "Hardware Timer Device", "Unknown" }; diff --git a/include/rtdef.h b/include/rtdef.h index eda5d5da79..a3dad27989 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -758,8 +758,8 @@ enum rt_device_class_type RT_Device_Class_PM, /**< PM pseudo device */ RT_Device_Class_Pipe, /**< Pipe device */ RT_Device_Class_Portal, /**< Portal device */ - RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ - RT_Device_Class_HwTimer, /**< Hardware timer device */ + RT_Device_Class_Timer, /**< Timer device */ + RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ RT_Device_Class_Unknown /**< unknown device */ }; From f8012b9000a92a5905b8dfa1144e5e3db91b9ecd Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Sun, 6 Sep 2015 16:37:43 +0800 Subject: [PATCH 5/7] =?UTF-8?q?[lpc408x]=E6=B7=BB=E5=8A=A0=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E5=99=A8=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bsp/lpc408x/drivers/drv_hwtimer.c | 153 ++++++++++++++++++++++++++++++ bsp/lpc408x/drivers/drv_hwtimer.h | 8 ++ 2 files changed, 161 insertions(+) create mode 100644 bsp/lpc408x/drivers/drv_hwtimer.c create mode 100644 bsp/lpc408x/drivers/drv_hwtimer.h diff --git a/bsp/lpc408x/drivers/drv_hwtimer.c b/bsp/lpc408x/drivers/drv_hwtimer.c new file mode 100644 index 0000000000..163c91fcd1 --- /dev/null +++ b/bsp/lpc408x/drivers/drv_hwtimer.c @@ -0,0 +1,153 @@ +/* + * File : drv_hwtimer.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, RT-Thread Development Team + * + * 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 + * + * Change Logs: + * Date Author Notes + * 2015-09-02 heyuanjie87 the first version + */ + +#include +#include +#include "lpc_timer.h" +#include "lpc_clkpwr.h" +#include "drv_hwtimer.h" + +#ifdef RT_USING_HWTIMER + +static void NVIC_Configuration(void) +{ + NVIC_EnableIRQ(TIMER0_IRQn); +} + +static void timer_init(rt_hwtimer_t *timer, rt_uint32_t state) +{ + LPC_TIM_TypeDef *tim; + TIM_TIMERCFG_Type cfg; + + tim = (LPC_TIM_TypeDef *)timer->parent.user_data; + + TIM_DeInit(tim); + + if (state == 1) + { + NVIC_Configuration(); + + cfg.PrescaleOption = TIM_PRESCALE_TICKVAL; + cfg.PrescaleValue = 0xFFFF; + TIM_Init(tim, TIM_TIMER_MODE, &cfg); + } +} + +static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode) +{ + LPC_TIM_TypeDef *tim; + TIM_MATCHCFG_Type match; + + tim = (LPC_TIM_TypeDef *)timer->parent.user_data; + + match.MatchChannel = 0; + match.IntOnMatch = ENABLE; + match.ResetOnMatch = ENABLE; + match.StopOnMatch = (opmode == HWTIMER_MODE_ONESHOT)? ENABLE : DISABLE; + match.ExtMatchOutputType = 0; + match.MatchValue = t; + + TIM_ConfigMatch(tim, &match); + TIM_Cmd(tim, ENABLE); + + return RT_EOK; +} + +static void timer_stop(rt_hwtimer_t *timer) +{ + LPC_TIM_TypeDef *tim; + + tim = (LPC_TIM_TypeDef *)timer->parent.user_data; + + TIM_Cmd(tim, DISABLE); +} + +static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) +{ + LPC_TIM_TypeDef *tim; + rt_err_t err = RT_EOK; + + tim = (LPC_TIM_TypeDef *)timer->parent.user_data; + + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + { + uint32_t clk; + uint32_t pre; + + clk = CLKPWR_GetCLK(CLKPWR_CLKTYPE_PER); + pre = clk / *((uint32_t*)arg) - 1; + tim->PR = pre; + } + break; + default: + { + err = -RT_ENOSYS; + } + break; + } + + return err; +} + +static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer) +{ + LPC_TIM_TypeDef *tim; + + tim = (LPC_TIM_TypeDef *)timer->parent.user_data; + + return tim->TC; +} + +static const struct rt_hwtimer_info _info = +{ + 1000000, /* the maximum count frequency can be set */ + 2000, /* the minimum count frequency can be set */ + 0xFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP,/* Increment or Decreasing count mode */ +}; + +static const struct rt_hwtimer_ops _ops = +{ + timer_init, + timer_start, + timer_stop, + timer_counter_get, + timer_ctrl, +}; + +static rt_hwtimer_t _timer0; + +int lpc_hwtimer_init(void) +{ + _timer0.info = &_info; + _timer0.ops = &_ops; + + rt_device_hwtimer_register(&_timer0, "timer0", LPC_TIM0); + + return 0; +} + +void TIMER0_IRQHandler(void) +{ + if (TIM_GetIntStatus(LPC_TIM0, TIM_MR0_INT) != RESET) + { + TIM_ClearIntPending(LPC_TIM0, TIM_MR0_INT); + rt_device_hwtimer_isr(&_timer0); + } +} + +INIT_BOARD_EXPORT(lpc_hwtimer_init); +#endif diff --git a/bsp/lpc408x/drivers/drv_hwtimer.h b/bsp/lpc408x/drivers/drv_hwtimer.h new file mode 100644 index 0000000000..b45b27dc06 --- /dev/null +++ b/bsp/lpc408x/drivers/drv_hwtimer.h @@ -0,0 +1,8 @@ +#ifndef __DRV_HWTIMER_H__ +#define __DRV_HWTIMER_H__ + + +int stm32_hwtimer_init(void); + + +#endif From efc1b058ac553db24232aa0f49c7b573f3a498c2 Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Mon, 7 Sep 2015 13:27:05 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/hwtimer/README_CN.md | 101 ++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 components/drivers/hwtimer/README_CN.md diff --git a/components/drivers/hwtimer/README_CN.md b/components/drivers/hwtimer/README_CN.md new file mode 100644 index 0000000000..8ee6f3df06 --- /dev/null +++ b/components/drivers/hwtimer/README_CN.md @@ -0,0 +1,101 @@ +瀹氭椂鍣ㄨ澶 +=== + +##鍔熻兘 +--- +* 鏃堕棿娴嬮噺 +* 鍛ㄦ湡鎴栧崟娆℃墽琛屽洖璋冨嚱鏁 + +##缂栬瘧 +--- +1. 鍦╮tconfig.h娣诲姞 `#define RT_USING_HWTIMER` + +##浣跨敤娴佺▼ +--- +1. 浠ヨ鍐欐柟寮忔墦寮璁惧 +2. 璁剧疆瓒呮椂鍥炶皟鍑芥暟锛堝鏋滈渶瑕侊級 +3. 鏍规嵁闇瑕佽缃畾鏃舵ā寮忥紙鍗曟/鍛ㄦ湡锛 +4. 璁剧疆璁℃暟棰戠巼锛堝彲閫夛級 +5. 鍐欏叆瓒呮椂鍊硷紝瀹氭椂鍣ㄩ殢鍗冲惎鍔 +6. 鍋滄瀹氭椂鍣紙鍙夛級 +7. 鍏抽棴璁惧锛堝鏋滈渶瑕侊級 + +搴旂敤鍙傝 [hwtimer_test] (/examples/test/hwtimer\_test.c) + +##椹卞姩缂栧啓鎸囧崡 +--- +###鎿嶄綔鎺ュ彛 + +``` +struct rt_hwtimer_ops +{ + void (*init)(struct rt_hwtimer_device *timer, rt_uint32_t state); + rt_err_t (*start)(struct rt_hwtimer_device *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode); + void (*stop)(struct rt_hwtimer_device *timer); + rt_uint32_t (*count_get)(struct rt_hwtimer_device *timer); + rt_err_t (*control)(struct rt_hwtimer_device *timer, rt_uint32_t cmd, void *args); +}; +``` + +* init - state <1 鎵撳紑璁惧 0 鍏抽棴璁惧> +* start - cnt <瓒呮椂鍊> - mode <鍗曟/鍛ㄦ湡> +* stop - <鍋滄璁℃暟> +* count_get - <璇诲彇璁℃暟鍣ㄥ> +* control - <璁剧疆璁℃暟棰戠巼 > + +###瀹氭椂鍣ㄧ壒寰佷俊鎭 + +``` +struct rt_hwtimer_info +{ + rt_int32_t maxfreq; + rt_int32_t minfreq; + rt_uint32_t maxcnt; + rt_uint8_t cntmode; + }; +``` + +* maxfreq <璁惧鏀寔鐨勬渶澶ц鏁伴鐜> +* minfreq <璁惧鏀寔鐨勬渶灏忚鏁伴鐜> +* maxcnt <璁℃暟鍣ㄦ渶澶ц鏁板> +* cntmode <閫掑璁℃暟/閫掑噺璁℃暟> + +###娉ㄥ唽璁惧 +``` +static rt_hwtimer_t _timer0; +int stm32_hwtimer_init(void) +{ + _timer0.info = &_info; + _timer0.ops = &_ops; + + rt_device_hwtimer_register(&_timer0, "timer0", TIM2); + + return 0; +} +``` + +###瀹氭椂鍣ㄤ腑鏂 +``` +void timer_irq_handler(void) +{ + //鍏跺畠鎿嶄綔 + + rt_device_hwtimer_isr(&_timer0); +} +``` + +##娉ㄦ剰浜嬮」 +--- + +鍙兘鍑虹幇瀹氭椂璇樊 + + +璇樊鍘熷洜锛 + +鍋囪璁℃暟鍣ㄦ渶澶у0xFFFF锛岃鏁伴鐜1Mhz锛屽畾鏃舵椂闂1绉掑張1寰銆 + +鐢变簬瀹氭椂鍣ㄤ竴娆℃渶澶氬彧鑳借鏃跺埌65535us锛屽浜1000001us鐨勫畾鏃惰姹 +灏遍渶鍒15娆″畬鎴愩傝宸椂闂: 1000001 - (65535*15) = 16976us銆 +杩欎釜璇樊澶ぇ锛屼负浜嗗噺灏忚宸渶鐞嗘兂鐨勬儏鍐靛氨鏄暣闄ゃ傚疄闄呬腑涓嶅彲鑳 +鎵鏈夋暟閮借鏁撮櫎(1涓嶅悎閫)锛屾墍浠ュ氨鍙湁鏈澶ч檺搴﹂艰繎鐞嗘兂鎯呭喌銆備緥濡 +涓婂紡涓互 50000us瀹氭椂20娆″嵆鍙皢璇樊鍑忓皬鍒1us(鐞嗚鍊,蹇界暐鎸囦护鏃堕棿) From 984a7ba05128992d8b89fc689f5f5e4f135e2f1b Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Wed, 9 Sep 2015 10:26:42 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/drivers/hwtimer/README_CN.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/drivers/hwtimer/README_CN.md b/components/drivers/hwtimer/README_CN.md index 8ee6f3df06..fb3b4fa60a 100644 --- a/components/drivers/hwtimer/README_CN.md +++ b/components/drivers/hwtimer/README_CN.md @@ -94,8 +94,5 @@ void timer_irq_handler(void) 鍋囪璁℃暟鍣ㄦ渶澶у0xFFFF锛岃鏁伴鐜1Mhz锛屽畾鏃舵椂闂1绉掑張1寰銆 -鐢变簬瀹氭椂鍣ㄤ竴娆℃渶澶氬彧鑳借鏃跺埌65535us锛屽浜1000001us鐨勫畾鏃惰姹 -灏遍渶鍒15娆″畬鎴愩傝宸椂闂: 1000001 - (65535*15) = 16976us銆 -杩欎釜璇樊澶ぇ锛屼负浜嗗噺灏忚宸渶鐞嗘兂鐨勬儏鍐靛氨鏄暣闄ゃ傚疄闄呬腑涓嶅彲鑳 -鎵鏈夋暟閮借鏁撮櫎(1涓嶅悎閫)锛屾墍浠ュ氨鍙湁鏈澶ч檺搴﹂艰繎鐞嗘兂鎯呭喌銆備緥濡 -涓婂紡涓互 50000us瀹氭椂20娆″嵆鍙皢璇樊鍑忓皬鍒1us(鐞嗚鍊,蹇界暐鎸囦护鏃堕棿) +鐢变簬瀹氭椂鍣ㄤ竴娆℃渶澶氬彧鑳借鏃跺埌65535us锛屽浜1000001us鐨勫畾鏃惰姹傘 +鍙互50000us瀹氭椂20娆″畬鎴愶紝姝ゆ椂灏嗕細鍑虹幇璁$畻璇樊1us銆