A40i Linux3.10开发板移植高精度定时器hrtimer驱动

news2024/11/27 8:30:05

目录

整编内核

修改Makefile文件

编译内核

生成.ko文件

应用层调用


这里使用整个编译内核的方式编译.ko文件。

整编内核

编写一个hrtimer_demo.c的驱动程序源码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "hrtimer"

static struct hrtimer hr_timer;
static ktime_t kt;
static int timer_count = 0;
static int trigger_count = 10;  // 默认触发次数

static enum hrtimer_restart timer_callback(struct hrtimer *timer)
{
    timer_count++;
    printk(KERN_INFO "Timer callback, count: %d\n", timer_count);
    
    if (timer_count >= trigger_count) {
        printk(KERN_INFO "Timer triggered %d times, stopping\n", trigger_count);
        return HRTIMER_NORESTART;
    }
    
    hrtimer_forward_now(timer, kt);
    return HRTIMER_RESTART;
}

static int hrtimer_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
    char tmp[32];
    int len;
    
    len = snprintf(tmp, sizeof(tmp), "Timer count: %d\n", timer_count);
    if (count >= len) {
        if (copy_to_user(buf, tmp, len) != 0) {
            return -EFAULT;
        }
        return len;
    }
    
    return -EINVAL;
}

static int hrtimer_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case 0:  // 停止定时器
            hrtimer_cancel(&hr_timer);
            printk(KERN_INFO "Hrtimer stopped\n");
            break;
        case 1:  // 重启定时器
            hrtimer_start(&hr_timer, kt, HRTIMER_MODE_REL);
            printk(KERN_INFO "Hrtimer restarted\n");
            break;
        case 2:  // 设置触发次数
            if (arg <= 0) {
                return -EINVAL;
            }
            trigger_count = arg;
            printk(KERN_INFO "Trigger count set to %d\n", trigger_count);
            break;
        case 3:  // 设置触发周期
            if (arg <= 0) {
                return -EINVAL;
            }
            kt = ktime_set(arg, 0);
            printk(KERN_INFO "Trigger period set to %ld seconds\n", arg);
            break;
        default:
            return -EINVAL;
    }
    
    return 0;
}

static struct file_operations hrtimer_fops = {
    .read = hrtimer_read,
    .unlocked_ioctl = hrtimer_ioctl,
};

static struct miscdevice hrtimer_miscdev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &hrtimer_fops,
};

static int __init hrtimer_demo_init(void)
{
    int ret;
    
    printk(KERN_INFO "Hrtimer module loaded\n");
    
    // 初始化定时器
    hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    
    // 设置定时器的超时时间为1秒
    kt = ktime_set(1, 0);
    
    // 设置定时器的回调函数
    hr_timer.function = timer_callback;
    
    // 启动定时器
    hrtimer_start(&hr_timer, kt, HRTIMER_MODE_REL);
    
    // 注册设备
    ret = misc_register(&hrtimer_miscdev);
    if (ret < 0) {
        printk(KERN_ERR "Failed to register misc device\n");
        return ret;
    }
    
    return 0;
}

static void __exit hrtimer_demo_exit(void)
{
    // 注销设备
    misc_deregister(&hrtimer_miscdev);
    
    // 停止定时器
    hrtimer_cancel(&hr_timer);
    
    printk(KERN_INFO "Hrtimer module unloaded\n");
}

module_init(hrtimer_demo_init);
module_exit(hrtimer_demo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Hrtimer Example");

将hrtimer_demo.c程序拷贝到linux-3.10/drivers/char/目录下

 

修改Makefile文件

修改linux-3.10/drivers/char/目录下Makefile文件,在Makefile中增加如下代码: 

obj-m += hrtimer_demo.o

编译内核

lu@Computer:~/workplace/A40i/lichee$ ./build.sh -m kernel

生成.ko文件

 

应用层调用

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

#define DEVICE_PATH "/dev/hrtimer"

int stop_timer(int fd)
{
    if (ioctl(fd, 0) < 0) {
        perror("Failed to stop timer");
        return -1;
    }

    printf("Timer stopped\n");

    return 0;
}

int restart_timer(int fd)
{
    if (ioctl(fd, 1) < 0) {
        perror("Failed to restart timer");
        return -1;
    }

    printf("Timer restarted\n");

    return 0;
}

int set_trigger_count(int fd, int count)
{
    if (ioctl(fd, 2, count) < 0) {
        perror("Failed to set trigger count");
        return -1;
    }

    printf("Trigger count set to %d\n", count);

    return 0;
}

int set_trigger_period(int fd, int period)
{
    if (ioctl(fd, 3, period) < 0) {
        perror("Failed to set trigger period");
        return -1;
    }

    printf("Trigger period set to %d ms\n", period);

    return 0;
}

int main()
{
    int fd;
    char buf[256];

    // 打开设备文件
    fd = open(DEVICE_PATH, O_RDWR);
    if (fd < 0) {
        perror("Failed to open device");
        return -1;
    }

    // 读取设备文件
    if (read(fd, buf, sizeof(buf)) < 0) {
        perror("Failed to read device");
        close(fd);
        return -1;
    }

    printf("Read from device: %s\n", buf);

    // 停止定时器
    if (stop_timer(fd) < 0) {
        close(fd);
        return -1;
    }

    // 设置触发次数为5
    if (set_trigger_count(fd, 5) < 0) {
        close(fd);
        return -1;
    }

    // 设置触发周期为2毫秒
    if (set_trigger_period(fd, 2) < 0) {
        close(fd);
        return -1;
    }

    // 重启定时器
    if (restart_timer(fd) < 0) {
        close(fd);
        return -1;
    }

    // 关闭设备文件
    close(fd);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/724239.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

相机图片给 Livox 激光雷达点云赋色(python代码 单文件)

需要配置PCD文件路径, 图片路径,相机内参,相机和雷达的外参; 单文件, Windows , liunx 都可以运行。 雷达和相机外参如何标定请看我的另外一篇标定的代码文章。 效果如下图: 附上代码: # coding:utf-8import cv2 import numpy as np import open3d as o3ddef get_U…

记录一次在泛微OA中添加js代码块,限制开始日期时间不能大于等于结束日期时间

目标&#xff1a; 在选择流程后提交时&#xff0c;选择的开始日期、时间不能大于结束日期、时间选择的开始日期、时间不能等于结束日期、时间满足以上条件才可以提交 效果图&#xff1a; 在OA后台添加js代码的步骤&#xff0c;如下&#xff1a; 图一&#xff08;第1-5步参考图…

[NPUCTF2020]你好sao啊

前言 base64的解密算法&#xff0c;开始还以为是什么变种加密手段 分析 可以发现加密区域主要位于RxEncode中&#xff0c;最终结果为s中保存数据 解密算法写的有点怪怪的&#xff0c;知道是4转3但给人1的感觉不像是在解密&#xff0c;更像是在换表之类的操作 strchr的作用为…

小程序前端上传图片直传七牛云不存储服务器

fastadmin文件API接口文件下的common修改默认的upload方法&#xff0c;直接替换即可 /*** 上传文件* ApiMethod (POST)* param File $file 文件流*/public function upload(){$file $this->request->file(file);if (empty($file)) {$this->error(__(No file upload…

IDEA中使用Git拉取项目时设置重新输入用户名和密码

1、选择&#xff1a;file ----> setting ---->passwords 2、选中这个Do not save 3、点击OK 4、重新使用Git拉取代码会提示重新输入用户名和密码

培训报名小程序报名列表页开发

目录 1 创建页面2 组件搭建3 设置URL参数4 设置筛选条件5 首页跳转6 最终的效果总结 这节我们来开发报名列表功能&#xff0c;先看原型 1 创建页面 功能要在页面上呈现&#xff0c;需要先创建页面。打开我们的培训报名小程序&#xff0c;在页面区&#xff0c;点击创建页面的…

Golang每日一练(leetDay0115) 重新安排行程、递增的三元子序列

目录 332. 重新安排行程 Reconstruct Itinerary &#x1f31f;&#x1f31f;&#x1f31f; 334. 递增的三元子序列 Increasing Triplet Subsequence &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 P…

【数据挖掘从入门到实战】——专栏导读

目录 1、专栏大纲 &#x1f40b;基础部分 &#x1f40b;实战部分 &#x1f40b;竞赛部分 2、代码附录 数据挖掘专栏&#xff0c;包含基本的数据挖掘算法分析和实战&#xff0c;数据挖掘竞赛干货分享等。数据挖掘是从大规模数据集中发现隐藏模式、关联和知识的过程。它结合…

CE-Net

一、贡献 (1)提出DAC模块和RMP模块&#xff0c;以捕获更多高级特征并保留更多空间信息 (2)将所提出的DAC模块和RMP模块与编码器-解码器结构集成在一起&#xff0c;用于医学图像分割 二、方法 (b)部分是shortcut mechanism 空洞卷积 公式化为&#xff1a; 空洞率r对应于对输…

写一个函数求某个数对应的二进制中1的个数(牛客)

[该题的牛客链接](https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8? 一、方法一&#xff1a;%/达到二进制位右移的效果1.1用>>操作符实现1.2方法一代码的改进&#xff08;针对负数情况&#xff09; 二、方法二&#xff1a;按位与1&#x…

基于PyQt5的桌面图像调试仿真平台开发(14)色彩增强

系列文章目录 基于PyQt5的桌面图像调试仿真平台开发(1)环境搭建 基于PyQt5的桌面图像调试仿真平台开发(2)UI设计和控件绑定 基于PyQt5的桌面图像调试仿真平台开发(3)黑电平处理 基于PyQt5的桌面图像调试仿真平台开发(4)白平衡处理 基于PyQt5的桌面图像调试仿真平台开发(5)…

VSCode编译github上面的C++项目

1、下载cmake 在这里下载对应的版本 https://cmake.org/download/ 测试下载的是这个 下载完成后安装&#xff0c;安装都比较简单 2、安装CMake工具扩展 3、安装C扩展 4、下载github项目 例如&#xff1a;下载这个项目 https://gitcode.net/mirrors/zrax/pycdc?utm_source…

Axure教程—菜单滚动切换交互

本文接受的是用Axure中的动态面板和热区制作菜单滚动切换交互 效果 预览地址&#xff1a;https://u5ircj.axshare.com 功能 页面滚动到某一内容部分&#xff0c;显示其相应的菜单。 制作 一、所需元件 矩形、动态面板、热区 二、制作过程 拖入一个矩形元件&#xff0c;其大小…

CSO 们关注的软件供应链安全十个关键问题

写在前面 自从和几个小伙伴一起创办墨菲安全以来&#xff0c;有一年半多的时间了&#xff0c;创业对于我来说&#xff0c;很有意思的一个地方&#xff0c;就是有机会可以和各行各业很多非常有意思的人一起交流&#xff0c;在这个交流的过程中能够不断的提升自己的认知&#xf…

【Java基础教程】(四)程序概念篇 · 中:探索Java编程基础,解析各类运算符功能、用法及其应用场景~

Java基础教程之程序概念 中 本节学习目标1️⃣ 运算符1.1 关系运算符1.2 算术运算符1.3 三目运算符1.4 逻辑运算1.4.1 与操作1.4.2 或操作1.4.3 非操作 1.5 位运算&#x1f50d;位运算规则1.5.1 位与运算1.5.2 位或运算 &#x1f33e; 总结 本节学习目标 掌握Java中各类运算符…

MSF安装使用指导案例

零.简介 Metasploit&#xff08;MSF&#xff09;是一个免费的、可下载的框架&#xff0c;它本身附带数百个已知软件漏洞&#xff0c;是一款专业级漏洞攻击工具。当H.D. Moore在2003年发布Metasploit时&#xff0c;计算机安全状况也被永久性地改变了&#xff0c;仿佛一夜之间&a…

选择排序--简单选择排序,堆排序(大根堆,小根堆的建立,堆排序,插入删除元素)包含程序

选择排序&#xff1a;每一趟从待排序列中选择最小的元素作为有序子序列中的元素&#xff0c;待元素只剩下一个&#xff0c;就不用选了。 一&#xff0c;简单选择排序 1.过程&#xff1a;假设以A[]表示数组 1.1最开始定义一个变量用来存储数组数组第一个元素的序号 i 0; min…

赛效:怎么无损压缩Word文档

1&#xff1a;在电脑上打开PDF猫&#xff0c;在导航栏的“文件压缩”菜单里点击“Word压缩”。 2&#xff1a;点击或者拖拽Word文档上传。 3&#xff1a;文件添加成功后&#xff0c;点击右下角“开始转换”。 4&#xff1a;转换成功后&#xff0c;文件下方有下载按钮&#xff0…

快速搭建专属于自己的单商户商城系统!

<系统简介> 基于ThinkPHP6.0、Vue、uni-app、PHP8.0、MySQL5.7、element-ui等主流通用技术开发的一套likeshop单商户商城系统&#xff0c;真正做到好懂&#xff0c;易改&#xff0c;不绕弯 代码全开源 极易二开 可免费商用 系统适用于B2C、单商户、自营商城场景。完…

SOLIDWORKS电控柜设计插件

电控柜设备的种类有很多种&#xff0c;但它们大体都是箱柜式的结构。电控柜是有标准的&#xff0c;但对于公司产品而言&#xff0c;针对不同的项目&#xff0c;如果都使用同一种规格的电控柜&#xff0c;又有可能空间太大&#xff0c;造成浪费&#xff0c;因此一般来说&#xf…