驱动:6 内核定时器

系统时钟中断:选取一个硬件定时器,对该硬件定时器作出相应的初始化,使得该定时器产生周期性的系统时钟中断

setup_irq(info->irqno, &timer_event_irqaction);
timer_event_handler:会调用tick_periodic
更新墙上时间
计算当前线程的时间片是否耗尽
如果耗尽重新执行任务调度
jiffies++;

HZ:它是一个宏
它对规定了每秒钟产生的系统时钟中断次数
当前所使用的系统 HZ=1000
tick:系统滴答
时钟节拍
tick=1/HZ;两次系统时钟中断的时间间隔
jiffies,一个unsigned int 类型全局变量
记录自开机以产生系统时钟中断的次数
例如:HZ=1000
在时间点A去读取jiffies,发现其值为10000,问开机多长时间了?10s
jiffies会溢出吗? 会
1.内核中的延时函数

睡眠延时:
	schedule_timeout(signed long timeout)
	msleep
忙等待延时:内核中长时间延时建议使用睡眠延时
	udelay(n),微秒延时
	mdelay,毫秒延时
Linux系统非实时操作系统,以上给的延时函数都不够准确,mdelay要比msleep准确度要高些
问题:睡眠延时函数如何做到的减少功耗

2.内核定时器
是在系统时钟中断基础上发展起来了,软件意义上的定时器

核心数据结构
	struct timer_list
	{
		/*定时器时间到*/
		unsigned long expires;
		/*定时时间到后要执行的动作*/
		void (*function)(unsigned long);
		/*当系统调用function时传递个funciton的参数值*/
		unsigned long data;
		。。。
	}
定时器的使用
	1)定义一个定时器变量
		struct tiemr_list btn_timer;
	2) 初始化定时器
		init_timer(&btn_timer);
		btn_timer.expires =
		btn_timer.function =
		btn_timer.data =
	3) 启动定时器
		void add_timer(struct timer_list *timer)/int mod_timer(struct timer_list *timer, unsigned long expires);
	4)修改定时器超时时间
		int mod_timer(struct timer_list *timer, unsigned long expires);
	5)停止定时器
		int del_timer(struct timer_list *timer);

练习:希望在安装内核模块时LED1开始闪烁 闪烁的时间间隔为1s,卸载模块时停止闪烁
案例代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <mach/platform.h>

MODULE_LICENSE("GPL");
/*定义定时器变量*/
struct timer_list led_timer;
void led_timer_func(unsigned long data)
{
    gpio_set_value(PAD_GPIO_C+12,!!data);
    led_timer.data = !data;
    mod_timer(&led_timer,jiffies+1*HZ);
}
int __init led_drv_init(void)
{
    /*申请管脚*/
    gpio_request(PAD_GPIO_C+12,"lED1");
    /*使用管脚*/
    gpio_direction_output(PAD_GPIO_C+12,0);
    /*初始化定时器*/
    init_timer(&led_timer);
    led_timer.function = led_timer_func;
    led_timer.expires = jiffies + 1*HZ;
    led_timer.data = 1;//定时时间到后,管脚要输出的电平值
    /*启动定时器*/
    add_timer(&led_timer);
    return 0;
}
void __exit led_drv_exit(void)
{
    del_timer(&led_timer);
    gpio_free(PAD_GPIO_C+12);
}
module_init(led_drv_init);
module_exit(led_drv_exit);

练习2: 能不能实现在用户空间调整LED1闪烁的时间间隔

        1s
        2s
        3s
        4s
        ...
   模块参数

vmware + ubuntu系统中 kermit软件的使用

  1)vmware  菜单: 虚拟机---》可移动设备---》串行端口2(可能不同)----》连接
  2)vi /home/tarena/.kermrc
      set line /dev/ttyUSB0  #改成这样报错  跳过这个步骤就没有问题了set line /dev/ttyS1
  3)sudo kermit -c
  4)退出kermit的方式
     ctrl + \
     q

扩展:dmesg 命令 重新输出缓冲区内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值