0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【产品应用】AWorksLP 样例详解(MR6450)—— HWTimer

AGk5_ZLG_zhiyua 来源:未知 2023-02-01 21:55 次阅读
AWorksLP 对外设进行了高度抽象化,为同一类外设提供了相同的接口,应用程序可以轻松跨平台。本文以MR6450(点击了解详情)平台为例,介绍AWorksLP HWTimer 外设基本用法。


简介
在AWorksLP中将硬件定时器分为了4类,即延时型、计数型、周期型和输入捕获型硬件定时器。
  • 延时型硬件定时器:

    由硬件定时器外设提供的延时功能。

  • 计数型硬件定时器:

    提供较精确的类似时间戳的功能。

  • 周期型硬件定时器:

    可设置中断频率的计数器,不仅能提供计数器的功能,也能根据中断频率提供更精确的定时。

  • 输入捕获定时器:
    可测量脉冲宽度或者测量频率。

接口介绍
延时型硬件定时器:
函数原型
简要描述
aw_err_t aw_hwtimer_delay (int fd, struct aw_timespec *p_tv);
延时
aw_err_t aw_hwtimer_delay_cancel (int fd);
取消延时
数型硬件定时器:
函数原型
简要描述
aw_err_t aw_hwtimer_count_start (int fd);
启动一个计数型硬件定时器
aw_err_t aw_hwtimer_count_stop (int fd);
停止一个计数型硬件定时器
aw_err_t aw_hwtimer_count_get (int fd, uint64_t *p_count);
读取计数值
aw_err_t aw_hwtimer_count_rate_get (int fd, uint32_t *p_rate);
获取计数时钟频率
aw_err_t aw_hwtimer_count_rate_set (int fd, uint32_t rate);
设置计数时钟频率
aw_err_t aw_hwtimer_count_rate_set_accurate (int fd, uint32_t rate_numerator, uint32_t rate_denominator);
以精确化的方式设置计数时钟频率
aw_err_t aw_hwtimer_count_rate_get_accurate (int fd, uint32_t *p_rate_numerator, uint32_t *p_rate_denominator);
获取计数时钟频率的精确描述
周期型硬件定时器:
函数原型
简要描述
aw_err_t aw_hwtimer_period_wait (int fd, uint32_t wait_ms);
等待定时器周期中断
aw_err_t aw_hwtimer_period_intr (int fd);
打断周期型定时器的等待操作
aw_err_t aw_hwtimer_period_start (int fd);
启动定时器
aw_err_t aw_hwtimer_period_stop (int fd);
停止定时器
aw_err_t aw_hwtimer_period_count_get (int fd, uint64_t *p_count);
读取计数值
aw_err_t aw_hwtimer_period_count_freq_get (int fd, uint32_t *p_rate);
获取周期型定时器的硬件计数频率(不是中断频率)
aw_err_t aw_hwtimer_period_count_freq_get_frac (int fd, aw_hwtimer_rate_t *p_rate);
以更精确的分数形式获取周期型定时器的硬件计数频率(不是中断频率)
aw_err_t aw_hwtimer_period_intr_freq_set (int fd, uint32_t intr_freq);
设置中断频率
aw_err_t aw_hwtimer_period_intr_freq_get (int fd, uint32_t *p_intr_freq);
获取中断频率
aw_err_t aw_hwtimer_period_intr_freq_set_frac (int fd, aw_const aw_hwtimer_rate_t *p_intr_freq);
设置中断频率(以更精确的分数形式)
aw_err_t aw_hwtimer_period_intr_freq_get_frac (int fd, aw_hwtimer_rate_t *p_intr_freq);
获取中断频率(以更精确的分数形式)
输入捕获型硬件定时器:
函数原型
简要描述
aw_err_t aw_hwtimer_cap_start (int fd);
启动输入捕获型硬件定时器
aw_err_t aw_hwtimer_cap_stop (int fd);
停止输入捕获型硬件定时器
aw_err_t aw_hwtimer_cap_read (int fd, uint64_t *p_cap_val, uint32_t timeout_ms);
读取一个捕获到的事件的计数值
aw_err_t aw_hwtimer_cap_intr (int fd);
打断阻塞read读操作
aw_err_t aw_hwtimer_cap_config_set (int fd, aw_const aw_hwtimer_cap_config_t *p_config);
配置输入捕获型硬件定时器
aw_err_t aw_hwtimer_cap_config_get (int fd, aw_hwtimer_cap_config_t *p_config);
获取输入捕获型硬件定时器的配置

使用样例
AWorksLP SDK相关使用请参考《AWorksLP SDK快速入门(MR6450)——开箱体验》一文,本文不在赘述。
1. 周期型定时器
{SDK}demosperipheralhwtimer路径下为硬件定时器例程,默认运行的是demo_hwtimer.c 周期型定时器的代码,例程关键代码如下:
/**
* rief 硬件定时器中断服务函数。
* param[in] p_arg : 任务参数
*/
static void mytimer_isr (void *p_arg)
{
aw_gpio_toggle((int)p_arg);
aw_kprintf("enter isr ");
}


/**
* rief hwtimer 测试函数
*/
aw_local void* __task_handle (void *arg)
{
int fd;
aw_err_t ret;
uint32_t count = 5;
aw_hwtimer_rate_t p_intr_freq;


p_intr_freq.rate_denominator = 5;
p_intr_freq.rate_numerator = 1;


fd = aw_open(CONFIG_DEMO_HWTIMER_PEROID_DEV_NAME, AW_O_RDWR, 0);
if (fd < 0) {
aw_kprintf("hwtimer open failed:%d ", fd);
while(1);
}


ret = aw_hwtimer_period_intr_freq_set_frac(fd, &p_intr_freq);
while (count) {
aw_hwtimer_period_wait(fd, 500);
mytimer_isr(arg);
count --;
}


// 配置每秒中断2次
ret = aw_hwtimer_period_intr_freq_set(fd, 2);


ret = aw_hwtimer_period_start(fd);
if (ret != AW_OK) {
aw_kprintf("Timer allocation fail! ");
}


ret = aw_hwtimer_period_wait(fd, AW_WAIT_FOREVER);


while (1) {
aw_hwtimer_period_wait(fd, AW_WAIT_FOREVER);
mytimer_isr(arg);
}


for (;;) {
aw_mdelay(1000);
}
aw_close(fd);


return 0;
}
在代码中先使用了aw_hwtimer_period_intr_freq_set_frac 接口,以分数的形式设置中断频率,使用aw_hwtimer_period_start接口启动定时器。在循环中使用aw_hwtimer_period_wait 接口阻塞等待中断的产生、中断产生后继续执行mytimer_isr函数使LED 灯状态翻转,由于设置的频率为五分之一,所以5秒LED 灯的状态翻转一次;循环一定次数后用aw_hwtimer_period_intr_freq_set 接口设置中断频率为2HZ,循环等待中断、翻转LED。
实验现象为LED灯先以5s的频率闪烁,同时串口打印同时信息。闪烁一定次数后以0.5s的频率LED闪烁,同时串口打印信息。

下表为使用硬件周期型定时器,在中断中进行引脚翻转,通过逻辑分析仪所测量出的实际数据,在使用设计时可作为部分参考依据。

定时时间(s
实际时间(s
0.010000000
0.010000115
0.020000000
0.019999940
0.030000000
0.029999980
0.040000000
0.040000035
0.050000000
0.049999830
0.100000000
0.100000075
0.200000000
0.200000020
0.500000000
0.500000070
1.000000000
1.000000760
2.000000000
1.999999340
3.000000000
3.000002760
4.000000000
4.000001980
5.000000000
5.000004310
10.000000000
10.000008300
2.计数型定时器
在config配置脚本中选择hwtimer count计数型定时器测试如图1所示。
图1 计数型定时器例程
保存后重新Build工程,编译好后运行的是demo_hwtimer_count.c的代码,例程关键代码如下:
aw_local void* __task_handle (void *arg)
{
uint32_t count = 0;
int fd, led_fd;
int ret;
uint32_t start_count;

fd = aw_open(CONFIG_DEMO_HWTIMER_PEROID_DEV_NAME, AW_O_RDWR, 0);
if (fd < 0) {
aw_kprintf("hwtimer open fail! :%d ",fd);
return;
}
/* 打开设备会点亮LED */
led_fd = aw_open("/dev/led_run", AW_O_RDWR, 0);
if (led_fd < 0) {
aw_kprintf("led open fail! :%d ", led_fd);
aw_close(fd);
return;
}
ret = aw_hwtimer_count_rate_get(fd, &start_count);
if (ret != AW_OK) {
aw_kprintf("Timer count rate get fail! ");
aw_close(fd);
aw_close(led_fd);
return;
}
// 设置时钟频率
ret = aw_hwtimer_count_rate_set(fd, start_count/2);
if (ret != AW_OK) {
aw_kprintf("Timer count rate set fail! ");
aw_close(fd);
aw_close(led_fd);
return;
}
ret = aw_hwtimer_count_start(fd);
if (ret != AW_OK) {
aw_kprintf("Timer start fail! ");
aw_close(fd);
aw_close(led_fd);
return;
}
for (;;) {
aw_led_toggle(led_fd);
aw_mdelay(500);
aw_led_toggle(led_fd);
aw_hwtimer_count_get(fd, &count);
aw_kprintf("Count is %d ", count);
}
aw_close(fd);
aw_close(led_fd);
return 0;
}
在上述代码中使用了aw_hwtimer_count_rate_get接口获取改定时器时钟频率,可以在调试模式下查看获取到的参数,为100M 如图2所示。
图2查看参数
使用aw_hwtimer_count_rate_set接口设置定时器时钟的频率为50M,使用aw_hwtimer_count_start接口开启定时器,使用aw_hwtimer_count_get接口在循环中每延时500ms获取一次计数值,并在串口中打印,打印结果如图3所示。

图3串口打印计数值
打印出的计数值中,相邻两个计数值之差为25M,是由于设置定时器频率为50M,每延时500ms计数值增加25M。
3.延时型定时器
在config配置脚本中选择hwtimer delay延时型定时器测试如图4所示。
图4计数型定时器例程
保存后重新Build工程,编译好后运行的是demo_hwtimer_count.c的代码,例程关键代码如下:
aw_local void* __task_handle (void *arg)
{
int i;
int fd;
aw_err_t ret;
aw_timespec_t timespec;
aw_timestamp_t start_timestamp, stop_timestamp;
aw_timestamp_freq_t timestamp_freq;
uint64_t delay_ns, diff;
uint32_t ns_numerator = 1000000000;


timestamp_freq = aw_timestamp_freq_get();
while (0 == (timestamp_freq % 10)) {
timestamp_freq /= 10;
ns_numerator /= 10;
}


fd = aw_open(CONFIG_DEMO_HWTIMER_DELAY_DEV_NAME, AW_O_RDWR, 0);
if (fd < 0) {
aw_kprintf("hwtimer open failed:%d ", fd);
while(1);
}


delay_ns = 2001000;
for (i = 0; i < 100; i++) {
timespec.tv_sec = delay_ns / 1000000000u;
timespec.tv_nsec = (uint32_t)(delay_ns % 1000000000u);


start_timestamp = aw_timestamp_get();
ret = aw_hwtimer_delay(fd, ×pec);
if (ret !=AW_OK) {
aw_kprintf("hwtimer delay failed:%d ", ret);
}
aw_barrier();
stop_timestamp = aw_timestamp_get();


stop_timestamp -= start_timestamp;
diff = stop_timestamp;
diff *= ns_numerator;
diff /= timestamp_freq;


diff = diff - delay_ns;
aw_kprintf(
"hwtimer_delay delay = %u,diff = %u ns ",
(uint32_t)delay_ns,
(uint32_t)diff);
delay_ns += 100000;
}
aw_close(fd);
return 0;
}
上述代码中在延时开始前使用aw_timestamp_get接口记录时间戳,使用aw_hwtimer_delay接口进行延时,延时结束后记录结束时间戳,用两个时间戳的差值通过换算,用于对比延时不同时间下与timestamp相比的误差,并在串口中打印,打印后增加延时时间,再次循环,串口打印结果如下图所示。
图5串口打印结果
因外设接口调用时代码执行需要时间以及晶振等硬件会导致误差,分析例程打印数据可得,延时性定时器的软件开销在同一硬件以及接口下,其误差基本是一致的。
4. 捕获型定时器

{SDK}demosperipheralcap路径下为捕获型定时器例程,例程关键代码如下:

/* 单边沿触发*/
static void test_cap_single_edge(
int fd,
int gpio_cap,
uint32_t ms,
aw_hwtimer_cap_config_t *p_config,
int is_rising)
{
uint64_t cap_val1, cap_val2;
aw_err_t ret;


// 制造两次上升沿
mk_edge(gpio_cap, 5);
aw_task_delay(ms);
mk_edge(gpio_cap, 5);


// 此时应该产生了两次捕获事件
// 把它们读出来
ret = aw_hwtimer_cap_read(fd, &cap_val1, AW_WAIT_FOREVER);
if (AW_OK != ret) {
aw_kprintf("cap read cap_val1 failed ");
return;
}
ret = aw_hwtimer_cap_read(fd, &cap_val2, AW_WAIT_FOREVER);
if (AW_OK != ret) {
aw_kprintf("cap read cap_val2 failed ");
return;
}


cap_val2 -= cap_val1;
cap_val2 *= 1000000;
cap_val2 /= p_config->sample_rate;


if (is_rising) {
aw_kprintf("two rising edge between %u ms ", ms + 5);
}
else {
aw_kprintf("two falling edge between %u ms ", ms + 5);
}
aw_kprintf("two capture events between %llu us ", cap_val2);
}


static void demo_cap_base(int gpio_cap)
{
int fd;
aw_err_t ret;
aw_hwtimer_cap_config_t config;


// 使得测试GPIO输出为0
aw_gpio_set(gpio_cap, 0);


fd = aw_open(CONFIG_DEMO_HWTIMER_CAP_DEV_NAME, AW_O_RDWR, 0);
if (fd < 0) {
aw_kprintf("cap open failed! ");
return;
}


// 获取捕获定时器的配置
ret = aw_hwtimer_cap_config_get(fd, &config);
if (ret != AW_OK) {
aw_kprintf("cap config get failed... ");
aw_close(fd);
return ;
}


#if CONFIG_SINGLE_EDGE
int is_rising;
// 配置为上升沿触发捕获
config.cap_edge_flags = AW_CAPTURE_RISING_EDGE;
is_rising = 1;
ret = aw_hwtimer_cap_config_set(fd, &config);
if (ret != AW_OK) {
aw_kprintf("cap config set failed... ");
aw_close(fd);
return ;
}


ret = aw_hwtimer_cap_start(fd);
if (ret != AW_OK) {
aw_kprintf("cap start failed... ");
aw_close(fd);
return ;
}
test_cap_single_edge(fd, gpio_cap, 20, &config, is_rising);
#endif


aw_close(fd);
}
在CAP 例程中默认使用的是timer5_chan0,这个通道对应的引脚是PF08,可以通过查看工程下timer5_chan0对应的.h文件得知所使用的引脚的编号为168,通过查看hpm_pin.h头文件可知编号168对应的引脚为PF08 如下图所示。
图6默认通道
图7对应引脚编号

图8对应引脚
本实验中还用到了PF09 这个引脚,用于产生捕获事件,PF09 和 PF08 这两个引脚在开发板上并没有引出来,不利于这次实验,需要修改这两个引脚。
图9捕获产生引脚
参考{SDK} platformsplatform-hpm-aworks-lpoardsEPC6450-AWIdts 下的pins.dts 引脚描述文件,找到timer4_chan1 如图10所示,timer4_chan1 使用的引脚是PE25, 对应着开发板排针 UTX1 丝印的位置。
图10捕获产生引脚
打开配置界面将timer5_chan0修改为timer4_chan1 如图11所示,修改后点击保存,重新build工程。
图11配置界面
将CAP_GPIO 对应的引脚改为PIN_PE24,对应着开发板排针 URX1 丝印的位置,如图12所示。

图12CAP引脚
将 PE25 , PE24 这两个引脚,也就是排针上 URX1 和 UTX1 短接。

图13引脚位置
上诉代码中使用aw_hwtimer_cap_config_get接口获取捕获定时器的配置信息,配置AW_CAPTURE_RISING_EDGE单通道模式后使用aw_hwtimer_cap_config_set接口配置捕获定时器。使用aw_hwtimer_cap_start接口启动定时器。在test_cap_single_edge函数中调用mk_edge函数制造两次上升沿,使用aw_hwtimer_cap_read接口读取这两次事件捕获到的计数值,计算出差值后在串口上显示。
在test_cap_single_edge函数中使用mk_edge函数中控制CAP_GPIO引脚输出高电平后延时5ms再输出低电平。延时20ms后再次调用mk_edge函数,因此两次上升沿事件间隔应为25ms。串口打印结果如下图所示。
图14串口打印结果

至此,所有类型的硬件定时器样例均已展示完毕,在软件应用设计中可根据实际需求选取不同类型的定时器进行使用。更多其他类型外设的用法介绍,请关注后续同系列推文~


原文标题:【产品应用】AWorksLP 样例详解(MR6450)—— HWTimer

文章出处:【微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 致远电子
    +关注

    关注

    13

    文章

    406

    浏览量

    31310

原文标题:【产品应用】AWorksLP 样例详解(MR6450)—— HWTimer

文章出处:【微信号:ZLG_zhiyuan,微信公众号:ZLG致远电子】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    为何ZLG致远电子要推出LGA嵌入式核心板?

    MR6450等5个系列,共12个型号的LGA形态的嵌入式核心板,涵盖了ARM9、A7、RISC-V等不同处理器架构。为什么有板对板连接器之后,我们还要推出LGA
    的头像 发表于 11-30 01:04 169次阅读
    为何ZLG致远电子要推出LGA嵌入式核心板?

    差分硅振替换SiTime产品应用于SSD,相位抖动低于350fs

    差分硅振替换SiTime产品应用于SSD,相位抖动低于350fs
    的头像 发表于 11-08 09:41 205次阅读
    差分硅振替换SiTime<b class='flag-5'>产品应用</b>于SSD,相位抖动低于350fs

    使用官方SDK开发6450

    官网提供的SDK芯片类型没有包含HPM6450,如何添加6450到SDK中有人知道么?
    发表于 10-24 14:51

    TPA3255产品应用在消防广播,固定输入下, 如果输出负载变化时,输出电压还能保持不变吗?

    产品应用在消防广播或者公共广播。 固定输入下, 如果输出负载变化时,输出电压还能保持不变吗? 如果是100V定压 接20欧姆负载 能输出500W功率.
    发表于 10-09 08:07

    基于RL78/G16 FPB的触摸工程创建演示流程

    本篇将分两部分为大家介绍RL78/G16 FPB触摸工程创建演示,首先是RL78/G16快速原型开发板(FPB),然后是如何在e2 studio开发环境中创建触摸工程,以及通过添加LED点亮的应用代码来演示触摸按键按下抬起的效果。
    的头像 发表于 05-21 14:13 1001次阅读
    基于RL78/G16 FPB的触摸<b class='flag-5'>样</b><b class='flag-5'>例</b>工程创建演示流程

    武汉凡谷:现阶段已有产品应用到5.5G系统

    近日,武汉凡谷在接受机构调研时表示,公司具备5.5G方面的产品,如多频多通道滤波器,现阶段有相关的产品应用到客户的5.5G系统。
    的头像 发表于 05-20 09:54 549次阅读

    【Vision Board创客营连载体验】HWTIMER设备体验

    ,General PWM(r_gpt)”配置GPT如下图 点击Generate Project Content 生成配置代码 3、HWTIMER代码实现 hwtimer配置代码 int
    发表于 05-14 11:51

    产品详解 | 瑞萨电子RZ/N2L MPU

    产品详解 | 瑞萨电子RZ/N2L MPU
    的头像 发表于 04-20 08:06 991次阅读
    <b class='flag-5'>产品</b><b class='flag-5'>详解</b> | 瑞萨电子RZ/N2L MPU

    AI时代下的场效应管功能运用与产品应用

    AI时代下的场效应管功能运用与产品应用
    的头像 发表于 03-25 15:07 576次阅读
    AI时代下的场效应管功能运用与<b class='flag-5'>产品应用</b>

    产品详解 | 瑞萨电子RZ/T2L MPU

    产品详解 | 瑞萨电子RZ/T2L MPU
    的头像 发表于 03-21 08:05 491次阅读
    <b class='flag-5'>产品</b><b class='flag-5'>详解</b> | 瑞萨电子RZ/T2L MPU

    浅谈智慧校园的用电安全管理分析及产品应用

    浅谈智慧校园的用电安全管理分析及产品应用 张颖姣 摘要:阐述校园安全用电管理的特点,存在的问题,应对策略,包括在实习实训和维修保养中的安全用电、提升电气保证设备安全防护、电气设备运行维护管理
    的头像 发表于 03-13 10:09 306次阅读
    浅谈智慧校园的用电安全管理分析及<b class='flag-5'>产品应用</b>

    产品详解 | 瑞萨电子RZ/T2M MPU

    产品详解 | 瑞萨电子RZ/T2M MPU
    的头像 发表于 03-13 08:05 699次阅读
    <b class='flag-5'>产品</b><b class='flag-5'>详解</b> | 瑞萨电子RZ/T2M MPU

    《RT-Thread设备驱动开发指南》基础篇--以先楫bsp的hwtimer设备为

    :对RT-thread以及设备框架进行介绍,再分别介绍基于IO框架中常用的外设设备,分别是UART、PIN、SPI/QSPI、HWTIMER、PWM、RTC、ADC、DAC
    的头像 发表于 02-24 08:16 1663次阅读
    《RT-Thread设备驱动开发指南》基础篇--以先楫bsp的<b class='flag-5'>hwtimer</b>设备为<b class='flag-5'>例</b>

    AMAZINGIC晶焱科技:面板产品应用的EOS最佳解決方案

    AMAZINGIC晶焱科技:面板产品应用的EOS最佳解決方案
    的头像 发表于 01-24 10:16 613次阅读

    【2023电子工程师大会】基于RK3568的OH开发及ppt

    【2023电子工程师大会】基于RK3568的OH开发及ppt
    发表于 01-03 16:31 27次下载