嵌入式Linux设备驱动开发笔记(二)

2023-05-16

一、内核的时间

(1)Tick(滴答)

内核采用了一个新的时间单位来进行计时。该时间单位称为tick(滴答),一个tick对应硬件定时器两次中断之间的时间间隔。当前内核每秒钟硬件定时器会发生HZ次中断。tick和秒的换算关系为: 1 tick = 1/HZ秒。
HZ是在内核make menuconfig(内核的.config文件)时确定,如果要修改HZ值,需要重新编译内核。

(2)相对时间

内核从开机开始记录一个相对时间。内核利用全局变量jiffies来记录从开机到当前时间所经过的tick的总量。
jiffies++的工作是由硬件定时器的中断处理函数完成的。jiffies的类型是unsigned long,在32位平台上最大值为4G。因此,当HZ为1000时,大约49.7天会溢出一次。为了避免溢出,可以使用64位的变量jiffies_64,大约2000亿天会溢出一次。

内核里的很多延迟和定时,都是用jiffies进行判断的。如果要访问jiffies,应包含头文件”linux/sched.h”。

(3)绝对时间

1969 UNIX诞生,绝对时间为从1970年1月1日0时0分0秒开始到现在的时间。在内核中用两个结构体来记录绝对时间:timeval和timespec,在头文件“linux/time.h”中。

#include <linux/time.h>
struct timeval tval;
struct timespec tspec;
调用内核的函数来获得绝对时间
do_gettimeofday(&tval);
getnstimeofday(&tspec);
打印绝对时间
printk("%lds : %ldus\n", tval.tv_sec, tval.tv_usec);
printk("%lds : %ldns\n", tspec.tv_sec, tspec.tv_nsec);

二、内核的延迟和定时

延迟:当前程序停下来,等待某个条件满足。延迟是不得已的,如果程序可以运行,就不应该延迟;
定时:启动定时器,由内核(硬件定时器的中断处理函数)在未来的某个时间为启动定时器者完成某项工作。

(1)基于忙循环的延迟
如果是比较短时间的延迟,则可以通过在cpu上运行一段循环来延迟,如果要延迟较长的时间,则需要将当前进程置入睡眠来延迟。

#include <linux/delay.h>
ndelay(10); //延迟10ns
udelay(20); //延迟20us
mdelay(30); //延迟30ms

内核用for循环实现上述3个函数。其中udelay用的最多,一般用于寄存器间设置的间隔。延迟时间和for循环次数的转换是一个经验值。内核在开机时会运行1s(或1个tick)的循环,然后记录循环的次数。udealy等的时间就通过该次数进行转换。这个次数记录在/proc/cpuinfo文件的变量bogomips中。

(2)基于等待队列的延迟(基于睡眠)

A、进程状态和运行队列

进程的核心结构体为“linux/sched.h”中的task_struct,区分进程的3个核心状态:
TASK_RUNNING
TASK_INTERRUPTIBLE
TASK_UNINTERRUPTIBLE

处于TASK_RUNNING状态的进程会组织在一个运行队列中,2.6.23内核以后,通过CFS调度器(Completely Fair Scheduler, 完全公平调度器)来调度,运行队列中的进程用rb_tree组织在一起。

B、直接睡眠延时(基于等待队列)

set_current_state(state);
state可以用TASK_INTERRUPT或TASK_UNINTERRUPTIBLE
schedule_timeout(delaytime);
delaytime以tick为单位,例如睡眠3s,则dalaytime可设置为3*HZ。

C、等待队列延时

每个要等待的条件都可以分配对应的等待队列,每个队列有一个等待队列头(wait_queue_head_t),等待队列定义在“linux/wait.h”头文件中。

#include <linux/wait.h>

//声明等待队列头
wait_queue_head_t mywait;

//队列头使用前要初始化
init_waitqueue_head(&mywait);

//在char驱动的write函数中,如果缓冲区满则睡眠
ssize_t my_write(...)
{
    int ret;

    if (dev->wp == dev->buf_size) {
        //wait_event(mywait, dev->wp < dev->buf_size);
        ret = wait_event_interruptible(mywait, dev-wp < dev->buf_size);
        if (ret != 0)
            return -ERESTARTSYS;
    }

    //如果缓冲区非满,则可写
    ...
}

//在ioctl函数中,可以让缓冲区复位,此时可以唤醒等待队列中的睡眠进程
int my_ioctl(xxx)
{
    //如果复位缓冲区,则唤醒整个队列
    memset(xxx);
    dev->wp = 0;
    //wake_up(&mywait);
    wake_up_interruptible(&mywait);
    ...
}

(3)定时器

定时器的特征:
A、启动定时器的人和执行定时器的人不一样
一般启动定时器的常常是某个进程或者中断,而内核中负责执行定时器的是硬件定时器的中断处理函数

B、定时器的执行时间一定是未来
内核利用jiffies来确定定时器的执行时间

C、定时器对应的函数只执行一次
一般谁准备定时器,谁提供执行函数;执行函数的人是内核的硬件定时器中断。如果希望实现一个循环的定时器,则需要在执行函数中自行将定时器再重新启动定时器。

D、定时器的函数在中断上下文(context)执行
因此,执行函数中不能睡眠

定时器的核心结构体定义在头文件“linux/timer.h”中,为timer_list。timer_list由启动者准备,当启动定时器后,timer_list会形成一个链表,由内核的硬件定时器中断来检查链表,看有没有定时器到时。

#include <linux/timer.h>

//声明定时器
struct timer_list mytimer;

//定时器的执行函数
//当定时器到期后,由硬件定时器中断执行一次
static void 
my_timer_func(unsigned long data)
{
    ...//不可睡眠
}

//初始化定时器
setup_timer(&mytimer, my_timer_func, data);
初始化定时器时传入的参数为timer_list的指针;执行函数;传给执行函数的参数

//启动定时器
mod_timer(&mytimer, jiffies+HZ);
//定时器一旦启动,就会加入一个timer_list的链表,一旦到时,就会被执行。
//启动定时器的人和执行的人不是一个。即使启动者退出,定时器仍然执行。

//删除定时器
del_timer(&mytimer);
如果模块要rmmod,在卸载之前,必须删除所有没执行的定时器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式Linux设备驱动开发笔记(二) 的相关文章

  • 交响乐排布及乐器音色特点

    交响乐布局 乐器组成及音色特点 木管组及铜管组代表乐器 木管组 铜管组 钢琴键谱图 国际谱和大小字组记录方式对比 其他乐器在钢琴键盘上音域表示图示 单簧管和长笛音色特点 音色特点综合分析
  • 【matlab】获取文件夹下文件名或路径保存到txt

    获取某文件夹下的所有文件名并保存 当需要在某一个文件夹下获取子文件的所有文件名 xff0c 并进行保存时 xff0c 可使用下面的代码 xff1a Path 61 39 D 文件夹 39 设置数据存放的文件夹路径 File 61 dir f
  • pycharm:新建虚拟环境和安装依赖

    前言 小编深有体会 xff0c 在刚开始用pycharm跑python的项目的时候 xff0c 一时间不知道如何下手 xff0c 特别是作为一个新手小白 xff0c 这里总结了一份新手避坑指南 xff0c 主要是新建虚拟环境 xff08 生
  • unbuntu安装 PyTorch 1.7.0+ torchvision 0.8.1

    unbuntu安装 PyTorch 1 7 0 43 torchvision 0 8 1 一 创建环境二 启动环境三 查看电脑CUDA版本 xff0c 若电脑只有CPU则忽略这一步四 下载安装包到本地安装4 1 点击以下链接进入下载网站4
  • 树莓派VNC界面不显示或显示不全问题_解决方案

    刚开始上手树莓派的小伙伴们估计都遇到过这一问题 xff0c 用树莓派登录VNC时 xff0c 界面不显示或者界面显示的比例有问题 先打开VNC xff0c 输入自己的IP地址 xff0c 登录VNC 我这里在登录VNC时 xff0c VNC
  • ArcGIS Engine:对COM组件的调用返回了错误HRESULT E_FAIL

    最近做一个项目 xff0c 需要调用GP的 通视性 工具 该工具在ARCScene中界面如下 xff1a 需要两个参数 xff08 必选 xff09 xff0c 即视线和障碍物 xff0c 在 帮助 中查看要求参数都是FeatureLaye
  • idea 2019.3之后的版本的项目使用gradle构建,编译时会出现中文乱码

    目录 背景1 修改gradle编译选项2 修改idea设置3 其他方法 xff08 尝试后没有效果 xff09 3 1 修改File Encdoing3 2 修改idea的custom VM option 背景 把公司电脑的idea更新到了
  • shell编程3循环语句

    文章目录 shell编程3循环语句1 for循环1 1 基本格式1 2 类C语言格式 2 while循环2 1 基本格式2 2 死循环 3 until循环4 跳出循环4 1 continue4 2 break 5 实验5 1 编写脚本实现计
  • ArduPilot飞控之ubuntu22.04-Gazebo模拟

    ArduPilot飞控之ubuntu22 04 Gazebo模拟 1 源由2 Gazebo安装2 1 ubuntu22 04系统更新2 2 安装Gazebo Garden2 3 安装ArduPilot Gazebo插件2 3 1 基础库安装
  • ArduPilot飞控之DIY-F450计划

    ArduPilot飞控之DIY F450计划 1 历史2 源由3 计划3 1 硬件3 2 软件 4 动手4 1 接线4 1 1 ELRS nano接收机4 1 2 BN880 GPS模块4 1 3 Radio Telemetry 4 2 配
  • ArduPilot Kakute F7 AIO DIYF450 without GPS配置

    ArduPilot Kakute F7 AIO DIYF450 without GPS配置 1 源由2 配置2 1 Kakute F7 AIO相关配置2 1 1 串口规划2 1 2 电传配置2 1 3 GPS配置2 1 4 CRSF接收机配
  • ArduPilot之posHold&RTL实测

    ArduPilot之posHold amp RTL实测 1 源由2 模式配置3 测试步骤4 飞行实测5 总结6 参考资料7 附录 关于QGC 暂不支持MAVLink2 signing Protocol问题7 1 问题描述7 2 硬件配置7
  • BetaFlight统一硬件配置文件研读之resource命令

    BetaFlight统一硬件配置文件研读之resource命令 1 源由2 代码分析3 实例分析4 配置情况4 1 resource4 2 resource show 5 参考资料 统一硬件配置文件的设计是一种非常好的设计模式 xff0c
  • ArduPilot之开源代码UARTs and the Console使用

    ArduPilot之开源代码UARTs and the Console使用 1 源由2 UART定义2 1 HAL Empty2 2 HAL ChibiOS2 3 HAL ESP322 4 HAL Linux2 5 HAL SITL 3 配
  • ArduPilot之开源代码调试技巧

    ArduPilot之开源代码调试技巧 1 源由2 ArduPilot Code Debugging Part13 ArduPilot Code Debugging Part24 持续更新中 5 参考资料 1 源由 对于如何调试和验证Ardu
  • ArduPilot飞控启动&运行过程简介

    ArduPilot飞控启动 amp 运行过程简介 1 源由2 Copter飞控2 1 入口2 3 运行 main loop 3 Ardunio编程3 1 setup AP Vehicle setup3 2 loop AP Vehicle l
  • WIN7 64位系统 CDC类 虚拟串口驱动无法安装的解决办法

    最近用STM32装个USB转虚拟串口 xff0c 但是驱动怎么也安装不上 百度了一些网页 xff0c 方法很多 xff0c 但是我这里按如下步骤处理 xff1a 首先 xff0c 确保C Windows System32 drivers u
  • ubuntu桌面版打开终端Terminal的几种方法

    1 Ctrl 43 Alt 43 T 快捷键直接打开 2 在Ubuntu左上角选择File Open in Terminal 3 快捷键alt 43 F2调出Run a Command xff0c 输入gnome terminal 4 添加
  • 什么是对称加密(对称加密简介)

    什么是对称加密 1 什么是对称加密2 编码3 加密算法3 1 DES3 1 1 什么是DES3 1 2 加密和解密 4 3DES4 3 1 什么是3DES4 3 2 3DES加密解密 5 AES5 1 什么是AES5 2 AES加密解密 1
  • Linux应用程序之Helloworld入门

    对于初学者来说 xff08 本人就是 xff09 xff0c 如何开始写第一个程序至关重要 有的时候一个简单的问题会严重影响到学习的积极性和自信心 这里结合实际工作中的一些经验 xff0c 总结方法步骤 xff0c 对Linux下应用程序H

随机推荐

  • ctags简明使用方法

    ctags xff08 Generate tag files for source code xff09 是vim下方便代码阅读的工具 xff0c 它可以在命令行下帮助程序员很容易地浏览源代码 ctags 最先是用来生成C代码的tags文件
  • char和unsigned char强制转换成int后的差异

    最近有人提到char和unsigned char有什么区别 xff0c 当然这个问题如果刚学计算机或者编程语言的人来说 xff0c 非常简单 我也这么认为 xff0c 无非就是有符号和无符号的差别嘛 这个问题让我想到了以前学习计算机常识的时
  • 如何使用mstsc进行远程登录?

    如何使用mstsc进行远程登录 xff1f 步骤一 xff1a 点击 开始 gt 运行 xff0c 输入mstsc xff0c 如下图所示 xff1a 步骤二 xff1a 输入连接PC的IP地址 xff0c 如下图所示 xff1a 步骤三
  • VNC远程ubuntu时,右击无法打开terminal

    参考博客 xff1a https blog csdn net qq 44132116 article details 103960393 问题描述 xff1a 我通过命令行连接实验室服务器 xff0c 装了anaconda xff0c 之后
  • TCP实时传图像

    目的 xff1a QT 43 openCV xff0c 在Ubuntu16 04版本下 xff0c 通过TCP实现图片的传输 步骤 xff1a 客户端建一个相机线程 xff0c 一个TCP线程 xff0c 相机线程捕获画面并将Mat传到TC
  • Ubuntu mate 16.04安装ROS

    官方文档有详细的安装步骤 xff1a http wiki ros org kinetic Installation Ubuntu 配置Ubuntu属性如下 xff1a https help ubuntu com community Repo
  • 关于ROS中的namespace

    当我们给发布的消息起名字时 xff0c 注意 34 points image 34 和 34 points image 34 是不一样的 xff0c 前者表示这个话题的名字是一个绝对名称 xff0c 它不在任何的namespace中 xff
  • 算法移植arm开发板小结(一)

    将windows的c c 43 43 代码移植到友善Tinny4412的arm上运行 首先要先将windows代码在ubuntu系统下编译通过 xff0c 然后在ubuntu系统下建立Tinny4412的arm交叉编译器 xff0c 并将代
  • CVTE嵌入式软件实习面经-已offer

    面试通过 时间线 4月份投的简历 xff0c 后面因为考试错过了 xff0c 后面月尾赶上最后了最后一场笔试 xff0c 笔试完四天左右通过 xff0c 通过两天后接到面试官电话 xff0c 那时候投了挺多公司的 xff0c 以为是其他的
  • 非对称加密详解

    非对称加密 1 非对称加密1 1 什么是非对称加密1 2 非对称加密通信流程1 3 RSA1 3 1 RSA加密1 3 2 RSA解密1 3 3 总结 1 4 ECC椭圆曲线 1 非对称加密 1 1 什么是非对称加密 非对称加密也叫公钥密码
  • PHP函数usort()解释

    定义和用法 usort 函数使用用户自定义的函数对数组排序 注释 xff1a 如果两个元素比较结果相同 xff0c 则它们在排序后的数组中的顺序未经定义 到 PHP 4 0 6 之前 xff0c 用户自定义函数将保留这些元素的原有顺序 但是
  • strchr()、strrchr()、strchrnul()…

    头文件 xff1a include 函数原型 xff1a char strchr char str int c char strrchr char str int c define GNU SOURCE 头文件 xff1a include
  • freertos- 任务调度器-vTaskStartScheduler()解析(笔记)

    1 全局状态量 系统时钟节拍计数器tick static volatile TickType t xTickCount 61 TickType t 0U 全局下一任务调度需要的阻塞时间 xff0c 用于及其唤醒任务static volati
  • freertos- 重要管理数据结构-列表List及其操作API (笔记)

    1 xff0c 源码中的位置 list h xff0c list c 2 xff0c 列表和列表项结构 列表项分为2种 xff1a struct xLIST ITEM listFIRST LIST ITEM INTEGRITY CHECK
  • 技术分享 | Javaer 如何做单元测试?

    前言 xff1a 本文适用于 javaer xff0c 其他开发者或许可以借鉴 写本文的主旨有两个 xff0c 一是简单的给大家介绍下单元测试 xff0c 二是通过一个简单的示例来介绍一些单元测试的技巧 xff0c 希望以此来降低大家写单元
  • 扩展卡尔曼滤波【转】

    1 重点看 SLAM中的EKF xff0c UKF xff0c PF原理简介 半闲居士 博客园 2 机器人重点看 定位 xff08 一 xff09 xff1a 扩展卡尔曼滤波 windSeS的博客 3 重点实例 扩展卡尔曼滤波 xff08
  • AGV - Background(1)- Company

    Company 米克力美 DZ 80无轨导航AGV小车采用windows10智能交互系统 xff0c xff08 米克力美工业AGV小车机器人采用安卓交互系统 xff09 可自动编程和程序化 xff0c 实现自主学习 使用人员无需培训即可轻
  • 无线路由器CPU浅析 MT7621A、 BCM47189 到底谁强?

    转自 xff1a http bbs 360 cn thread 14459037 1 1 html 在第一讲中 xff0c 已经粗略介绍过了目前路由芯片的四大厂 xff1a Broadcom xff08 博通 xff09 Qualcomm
  • STM32F4_串口通信详解

    目录 1 串口相关介绍及使用 1 1 串口设置的一般步骤 xff1a 1 1 1 串口时钟和GPIO时钟使能 1 1 2 设置引脚复用器映射 1 1 3 GPIO端口模式设置 1 1 4 串口参数初始化 1 1 5 开启中断并且初始化NVI
  • 嵌入式Linux设备驱动开发笔记(二)

    一 内核的时间 xff08 1 xff09 Tick xff08 滴答 xff09 内核采用了一个新的时间单位来进行计时 该时间单位称为tick 滴答 xff0c 一个tick对应硬件定时器两次中断之间的时间间隔 当前内核每秒钟硬件定时器会