linux内核定时器 && 线程kthread相关

        Linux内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,调度函数在运行过一次后就不会再运行了(相当于自动注销),但可以通过在被调度的函数中重新调度自己来周期运行。

(1)jiffies定时器,HZ=100,精度只能达到10ms,已验证

#include <linux/jiffies.h>
#include <linux/timer.h>  

static struct timer_list ms_timer;
static void ms_timer_handler(void)
{
    printk("DO_DEBUG----------->%s\n",__func__);

    ms_timer.expires=jiffies+msecs_to_jiffies(10);
    ms_timer.function=&ms_timer_handler;
    add_timer(&ms_timer);				//循环执行自己

} 

static int32_t xxx_init(void)
{
    init_timer(&ms_timer);                          //DO-->初始化定时器
    ms_timer.expires=jiffies+msecs_to_jiffies(10);  //DO-->定义中断时间:10ms进入中断
    ms_timer.function=&ms_timer_handler;            //DO-->定义定时器中断处理函数
    add_timer(&ms_timer);                           //DO-->增加注册定时器,使定时器生效
}

 

     移除定时器,用del_timer_sync(&ms_timer)。以上ms_timer_handler的内容,可用

    printk("DO_DEBUG----------->%s\n",__func__);
    mod_timer(&ms_timer,jiffies+msecs_to_jiffies(10));
代替。碰到睡眠唤醒的处理,睡眠时删掉timer,唤醒时重新初始化timer。

(2)hrtimer高精度定时器,可做到ns级。

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/hrtimer.h>

MODULE_LICENSE("Dual BSD/GPL");
extern int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode);
extern void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,enum hrtimer_mode mode);
extern int hrtimer_cancel(struct hrtimer *timer);

#define BAT_MS_TO_NS(x) (x * 1000 * 1000)
static struct hrtimer charger_hv_detect_timer;
void __exit kernel_test_exit()
{
	hrtimer_cancel(&charger_hv_detect_timer);
	printk("module out kernel_test_exit \r\n");
}

enum hrtimer_restart charger_hv_detect_sw_workaround(struct hrtimer *timer)
{
    printk("charger_hv_detect_sw_workaround \n");    
    return HRTIMER_RESTART;
}
int __init kernel_test_init()
{
		ktime_t ktime;
		ktime = ktime_set(0, BAT_MS_TO_NS(2000));
		hrtimer_init(&charger_hv_detect_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		charger_hv_detect_timer.function = charger_hv_detect_sw_workaround;    
		hrtimer_start(&charger_hv_detect_timer, ktime, HRTIMER_MODE_REL);
		printk("module in kernel_test_init \r\n");
		return 0;
}

module_init(kernel_test_init);
module_exit(kernel_test_exit);
      最终insmod,提示

[ 2058.475797] charger_hv_detect_sw_workaround 
[ 2058.475800] charger_hv_detect_sw_workaround 
[ 2058.475802] charger_hv_detect_sw_workaround 

(3)时间点和时间段

很多时候在内核中,需要用到时间点和时间段的判断来处理事务,举例如下:

A,组合按键进入某个开机模式

BOOL recovery_check_key_trigger(void)
{
    ulong begin = get_timer(0);	//获得当前时间点
		.........................
#ifdef MT65XX_RECOVERY_KEY
    while (get_timer(begin) < 50) {		//从当前点开始时间差
        if (mtk_detect_key(MT65XX_RECOVERY_KEY)) {
            printf("%s Detect cal key\n",MODULE_NAME);
            printf("%s Enable recovery mode\n",MODULE_NAME);
            g_boot_mode = RECOVERY_BOOT;
            //video_printf("%s : detect recovery mode !\n",MODULE_NAME);
            return TRUE;
        }
    }
#endif
	.......................
    return FALSE;
}

B,长按或者短按上报不同功能键值

kpd_keymap_handler中不同次按键中断,通过判断弹起的时间差上报不同键值

if((FACTORY_BOOT == get_boot_mode()) || (RECOVERY_BOOT == get_boot_mode()))
{
				if((linux_keycode == KEY_BACK) && (pressed == 1))
				{
					singleK_click = 1;
					singleK_click_ts = jiffies;
					break ;
				}
				if(singleK_click == 1)
				{
					singleK_click = 0;
					int t = jiffies_to_msecs(jiffies - singleK_click_ts) ;
					if( t > 1000)	//more than 1000ms
					{
						printk("KEY_MENU single click\n");	
						input_report_key(kpd_input_dev, KEY_MENU, 1);
						input_sync(kpd_input_dev);
						input_report_key(kpd_input_dev, KEY_MENU, 0);
						input_sync(kpd_input_dev);	
					}
					else
					{
						printk("KEY_BACK single click\n");	
						input_report_key(kpd_input_dev, KEY_BACK, 1);
						input_sync(kpd_input_dev);
						input_report_key(kpd_input_dev, KEY_BACK, 0);
						input_sync(kpd_input_dev);
					}
					break;
				}
}				

================kthread线程相关的处理=========================

linux内核中创建线程方法:https://www.cnblogs.com/Ph-one/p/6077787.html。

Linux 线程调度与优先级设置:http://blog.youkuaiyun.com/a_ran/article/details/43759729(未验证)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值