当前位置:网站首页>[RT thread] construction and use of --hwtimer of NXP rt10xx device driver framework
[RT thread] construction and use of --hwtimer of NXP rt10xx device driver framework
2022-07-03 17:11:00 【L_ seventeen】
hwtimer For our commonly used hardware timers , The following will be used gpt The timer realizes the construction of device driver
Preparation before development
- Hardware platform :nxp rt10xx Single chip microcomputer
- IDE: Keil
1.Kconfig Modifications and menuconfig To configure
stay Env Environmental Science menuconfig in RT-Thread Components->Device Drivers The device driver defaults to n, So it needs to be turned on

First in Kconfig Add the following statement to , And then in Env Environmental Science menuconfig in Hardware Drivers Config->On-Chip Peripheral Drivers, Then select and specify as needed HWTIMER, Peripherals used by the author GPT1 namely :HWTIMER1

2. Engineering additions HWTIMER Drive framework and BSP Driver interface
Device drive frame :hwtimer.c BSP Interface :drv_hwtimer.c fsl_gpt.c

3. Add or modify drv_hwtimer.c
The author consulted the document , The driver is relatively perfect , The author changed the clock source , Use osc 24M As a clock source , In addition, some redundant configurations have been deleted
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);
};
static const struct rt_hwtimer_ops imxrt_hwtimer_ops =
{
.init = imxrt_hwtimer_init,
.start = imxrt_hwtimer_start,
.stop = imxrt_hwtimer_stop,
.count_get = imxrt_hwtimer_count_get,
.control = imxrt_hwtimer_control,
};
int rt_hw_hwtimer_init(void)
{
int ret = RT_EOK;
#ifdef BSP_USING_HWTIMER1
GPT_timer1.info = &imxrt_hwtimer_info;
GPT_timer1.ops = &imxrt_hwtimer_ops;
ret = rt_device_hwtimer_register(&GPT_timer1, "gpt1", GPT1);
if (ret != RT_EOK)
{
LOG_E("gpt1 register failed\n");
}
#endif
#ifdef BSP_USING_HWTIMER2
GPT_timer2.info = &imxrt_hwtimer_info;
GPT_timer2.ops = &imxrt_hwtimer_ops;
ret = rt_device_hwtimer_register(&GPT_timer2, "gpt2", GPT2);
if (ret != RT_EOK)
{
LOG_E("gpt1 register failed\n");
}
#endif
return ret;
}
Clock source selection and interrupt priority are the places that the author changed , All the codes are pasted here
#define GPT_CLK_FREQ CLOCK_GetFreq(kCLOCK_OscClk)
#define SAI_ISR_PRE (14U)
static void NVIC_Configuration(void)
{
#ifdef BSP_USING_HWTIMER1
NVIC_SetPriority(GPT1_IRQn,SAI_ISR_PRE);
EnableIRQ(GPT1_IRQn);
#endif
#ifdef BSP_USING_HWTIMER2
NVIC_SetPriority(GPT2_IRQn,SAI_ISR_PRE);
EnableIRQ(GPT2_IRQn);
#endif
}
static rt_err_t imxrt_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
{
rt_err_t err = RT_EOK;
GPT_Type *hwtimer_dev;
hwtimer_dev = (GPT_Type *)timer->parent.user_data;
RT_ASSERT(timer != RT_NULL);
switch (cmd)
{
case HWTIMER_CTRL_FREQ_SET:
{
uint32_t clk;
uint32_t pre;
clk = GPT_CLK_FREQ;
pre = clk / *((uint32_t *)args);
GPT_SetClockDivider(hwtimer_dev, pre);
}
break;
default:
err = -RT_ENOSYS;
break;
}
return err;
}
static rt_uint32_t imxrt_hwtimer_count_get(rt_hwtimer_t *timer)
{
rt_uint32_t CurrentTimer_Count;
GPT_Type *hwtimer_dev;
hwtimer_dev = (GPT_Type *)timer->parent.user_data;
RT_ASSERT(timer != RT_NULL);
CurrentTimer_Count = GPT_GetCurrentTimerCount(hwtimer_dev);
return CurrentTimer_Count;
}
static void imxrt_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
{
GPT_Type *hwtimer_dev;
gpt_config_t gptConfig;
hwtimer_dev = (GPT_Type *)timer->parent.user_data;
RT_ASSERT(timer != RT_NULL);
if (state == 1)
{
/* Initialize GPT module by default config */
GPT_GetDefaultConfig(&gptConfig);
gptConfig.clockSource = kGPT_ClockSource_Osc; // Select peripheral clock
gptConfig.divider = 24; // Set the frequency division coefficient 24M/24 = 1M
GPT_Init(hwtimer_dev, &gptConfig);
}
}
static rt_err_t imxrt_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
{
GPT_Type *hwtimer_dev;
hwtimer_dev = (GPT_Type *)timer->parent.user_data;
RT_ASSERT(timer != RT_NULL);
hwtimer_dev->CR |= (mode != HWTIMER_MODE_PERIOD) ? GPT_CR_FRR_MASK : 0U;
GPT_SetOutputCompareValue(hwtimer_dev, kGPT_OutputCompare_Channel1, cnt);
GPT_EnableInterrupts(hwtimer_dev, kGPT_OutputCompare1InterruptEnable);
NVIC_Configuration();
GPT_StartTimer(hwtimer_dev);
return RT_EOK;
}
static void imxrt_hwtimer_stop(rt_hwtimer_t *timer)
{
GPT_Type *hwtimer_dev;
hwtimer_dev = (GPT_Type *)timer->parent.user_data;
RT_ASSERT(timer != RT_NULL);
GPT_StopTimer(hwtimer_dev);
}
4. Build application layer demo
Turn on timer , Check whether the time accuracy ok
/**************************************************START OF FILE*****************************************************/
/*------------------------------------------------------------------------------------------------------------------ Includes */
#include <rtthread.h>
#include <rtdevice.h>
/*------------------------------------------------------------------------------------------------------------------ Macros */
#define HWTIMER_DEVICE_NAME "gpt1" /* Hardware timer device name */
/*------------------------------------------------------------------------------------------------------------------ Variables */
/*------------------------------------------------------------------------------------------------------------------ Functions */
/* Timer timeout callback function */
static rt_err_t timer_callback(rt_device_t dev, rt_size_t size)
{
rt_kprintf("this is hwtimer timeout callback fucntion!\n");
rt_kprintf("tick is :%d !\n", rt_tick_get());
return 0;
}
int xAPP_HwTimerInit(void)
{
rt_err_t ret = RT_EOK;
rt_hwtimerval_t timeout_s; /* Timer timeout value */
rt_device_t hw_dev = RT_NULL; /* Timer device handle */
rt_hwtimer_mode_t mode; /* timer mode */
rt_uint32_t freq = 100000; /* Counting frequency */
hw_dev = rt_device_find(HWTIMER_DEVICE_NAME);
if (hw_dev == RT_NULL)
{
rt_kprintf("hwtimer sample run failed! can't find %s device!\n", HWTIMER_DEVICE_NAME);
return RT_ERROR;
}
ret = rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);
if (ret != RT_EOK)
{
rt_kprintf("open %s device failed!\n", HWTIMER_DEVICE_NAME);
return ret;
}
/* Set the timeout callback function */
rt_device_set_rx_indicate(hw_dev, timer_callback);
/* Set the counting frequency ( If this item is not set , The default is 1Mhz or Minimum count frequency supported ) */
rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);
mode = HWTIMER_MODE_PERIOD;
ret = rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);
if (ret != RT_EOK)
{
rt_kprintf("set mode failed! ret is :%d\n", ret);
return ret;
}
/* Set the timer timeout value to 5s And start the timer */
timeout_s.sec = 5; /* second */
timeout_s.usec = 0; /* Microsecond */
if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
{
rt_kprintf("set timeout value failed\n");
return RT_ERROR;
}
/* Time delay 3200ms */
rt_thread_mdelay(3200);
rt_device_read(hw_dev, 0, &timeout_s, sizeof(timeout_s));
rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec);
return ret;
}
/****************************************************END OF FILE*****************************************************/

Add up ,gpt Conversion method :
The clock source is 24M, Division coefficient 0xEF + 1 = 240, The available clock is :100000Hz,COMP:0x7A120 namely :500000
500000/100000=5s therefore 5s Break once

边栏推荐
- Deep understanding of grouping sets statements in SQL
- 29:第三章:开发通行证服务:12:开发【获得用户账户信息,接口】;(使用VO类包装查到的数据,以符合接口对返回数据的要求)(在多处都会用到的逻辑,在Controller中可以把其抽成一个共用方法)
- CC2530 common registers for watchdog
- UCORE overview
- [JDBC] API parsing
- The most complete postman interface test tutorial in the whole network, API interface test
- 線程池:業務代碼最常用也最容易犯錯的組件
- Examination questions for the assignment of selected readings of British and American Literature in the course examination of Fujian Normal University in February 2022
- Build your own website (23)
- C language modifies files by line
猜你喜欢

Recommendation of good books on learning QT programming

CC2530 common registers for serial communication

C语言按行修改文件

kubernetes资源对象介绍及常用命令(五)-(NFS&PV&PVC)

人生还在迷茫?也许这些订阅号里有你需要的答案!

One brush 147-force deduction hot question-4 find the median of two positive arrays (H)

Talk about several methods of interface optimization

ANOVA example

CC2530 common registers for port interrupts

Fast Ethernet and Gigabit Ethernet: what's the difference?
随机推荐
How to promote cross department project collaboration | community essay solicitation
关于学习Qt编程的好书精品推荐
University of Electronic Science and technology, accounting computerization, spring 20 final exam [standard answer]
比亚迪、长城混动市场再“聚首”
RedHat 6.2 配置 Zabbix
[combinatorics] recursive equation (definition of general solution | structure theorem of general solution of recursive equation without multiple roots)
An example of HP array card troubleshooting
设计电商秒杀
CC2530 common registers
Kindeditor editor upload image ultra wide automatic compression -php code
Mysql database DDL and DML
kubernetes资源对象介绍及常用命令(三)
CC2530 common registers for watchdog
SVN完全备份svnadmin hotcopy
Thread pool: the most common and error prone component of business code
Why is WPA3 security of enterprise business so important?
绝对定位时元素水平垂直居中
基于主机的入侵系统IDS
Luogu: p1155 [noip2008 improvement group] double stack sorting (bipartite graph, simulation)
New library online | cnopendata complete data of Chinese insurance institution outlets