커 널 구동. - 커 널 타이머.

9046 단어 S5PV210
개념
커 널 타이머 란 커 널 이 미래의 특정한 시간 대 (jiffies 현재 시간 기반) 에서 특정한 함 수 를 실행 하 는 메커니즘 을 제어 하 는 것 입 니 다. 배 치 된 함 수 는 비동기 로 실 행 됩 니 다. '소프트웨어 중단' 과 유사 하고 비 프로 세 스 의 문맥 에 있 습 니 다. 배 치 된 함 수 는 다음 과 같은 규칙 을 따라 야 합 니 다.
1) 없다 current 포인터, 사용자 공간 에 접근 할 수 없습니다.프로 세 스 컨 텍스트 가 없 기 때문에 관련 코드 는 중 단 된 프로 세 스 와 아무런 연락 이 없습니다.
2) 휴면 (또는 휴면 을 일 으 킬 수 있 는 함수) 과 스케줄 을 실행 할 수 없습니다.
3) 모든 방문 한 데이터 구 조 는 동시 방문 을 보호 하여 경쟁 조건 을 방지 해 야 한다.
커 널 타이머 의 스 케 쥴 러 함수 가 한 번 실 행 된 후 다 시 는 실행 되 지 않 습 니 다 (자동 로그아웃 에 해당 합 니 다). 그러나 스 케 쥴 러 함수 에서 자신 을 다시 스 케 쥴 러 주기 로 실행 할 수 있 습 니 다.
커 널 타이머 의 데이터 구조
struct timer_list {
    struct list_head entry; 
    unsigned long expires;    //           jiffies  ,    jiffies   ,    function   ,    data     
    void (*function)(unsigned long);
    unsigned long data; 
    struct tvec_base *base;
    /* ... */
};

2. 버튼 + 커 널 타이머 떨 기 코드 다운로드 클릭 하여 링크 열기
1. struct timer 정의list buttons_timer;2 、 init 초기 화timer(&buttons_timer);3, 등록 타이머 addtimer(&buttons_timer);4 、 타이머 mod 시작timer(&buttons_timer, jiffies + (HZ / 10));   /*시간 지연 1s / 10 = 100 ms * / 5, 타이머 취소 deltimer(&buttons_timer);
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define	GPH0CON 0xE0200C00
#define	GPH0DAT 0xE0200C04
#define DEVICE_NAME	"tqkey"

#define	LEDCON 0xE0200060
#define LEDDAT 0xE0200064

volatile unsigned int *led_config;
volatile unsigned int *led_data;
volatile unsigned int *key_data;


//1、    
struct work_struct *work;

//(   )1、        
struct timer_list buttons_timer;

void work_func(struct work_struct *work)
{
	/*     */   /*   1s/10=100ms */
	mod_timer(&buttons_timer, jiffies + (HZ / 10));
}

//(   )5、  
static void buttons_timer_function(unsigned long data)
{
	unsigned int key_val;
	key_val = readw(key_data) & 0x1;  //GPH0_0  
	if(key_val == 0)	//        
	{
		volatile unsigned short data;

		data = readw(led_data);
		if(data == 0)
		{
			data = 0xFF;
		}
		else
		{
			data = 0;
		}
		
		writel(data, led_data);
	}
}

void timer_init(void)
{
	//(   )2、   
	init_timer(&buttons_timer);
	buttons_timer.function = &buttons_timer_function;

	//(   )3、        
	add_timer(&buttons_timer);
}

static irqreturn_t key_int(int irq, void *dev_id)
{
	//3、              keventd_wq 
	schedule_work(work);
	return 0;
}

void key_hw_init(void)
{
	volatile unsigned short data;
	volatile unsigned int *gpio_config;
	gpio_config = (volatile unsigned int *)ioremap(GPH0CON, 4);
	data = readw(gpio_config);		//          
	data &= ~0x0F;
	data |= 0x0F;
	writew(data, gpio_config);
	printk("key_hw_init!
"); led_config = (volatile unsigned int *)ioremap(LEDCON, 4); // writel(0x00011000, led_config); led_data = (volatile unsigned int *)ioremap(LEDDAT, 4); writel(0xFF, led_data); key_data = (volatile unsigned int *)ioremap(GPH0DAT, 4); } /*static long key_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return -EINVAL; }*/ static int key_open(struct inode *inode, struct file *file) { return 0; } static struct file_operations key_fops = { .owner = THIS_MODULE, //.unlocked_ioctl = key_ioctl, .open = key_open, .release = NULL, }; struct miscdevice key_miscdev = { .minor = 200, .name = DEVICE_NAME, .fops = &key_fops, }; // static int __init button_init(void) { int ret = 0; misc_register(&key_miscdev); // ret = request_irq(IRQ_EINT0, key_int, IRQF_TRIGGER_FALLING, DEVICE_NAME, 0); // key_hw_init(); //2、 work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); //( :GFP_KERNEL , ) INIT_WORK(work, work_func); // , // timer_init(); return 0; } // static void __exit button_exit(void) { misc_deregister(&key_miscdev); // free_irq(IRQ_EINT0, 0);         //         del_timer(&buttons_timer);  } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jerry.Gou"); MODULE_DESCRIPTION("TQ210 button driver");

다 중 버튼 인 터 럽 트
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define	GPH0CON 0xE0200C00
#define	GPH0DAT 0xE0200C04
#define DEVICE_NAME	"tqkey"


#define	LEDCON 0xE0200060
#define LEDDAT 0xE0200064

volatile unsigned int *led_config;
volatile unsigned int *led_data;
volatile unsigned int *key_data;


//1、    
struct work_struct *work;

//(   )1、        
struct timer_list buttons_timer;

void work_func(struct work_struct *work)
{
	/*     */   /*   1s/10=100ms */
	mod_timer(&buttons_timer, jiffies + (HZ / 10));
}

//(   )5、  
static void buttons_timer_function(unsigned long data)
{
	unsigned int key_val;
	volatile unsigned short leddata;
	key_val = readw(key_data) & 0x1;  //GPH0_0 Key_1  
	if(key_val == 0)	//        
	{
		leddata = 0xFF;  //  LED
		writel(leddata, led_data);
	}
	key_val = readw(key_data) & 0x02;  //GPH0_0 Key_2  
	if(key_val == 0)	//        
	{
		leddata = 0x00;  //  LED
		writel(leddata, led_data);
	}
}

void timer_init(void)
{
	//(   )2、   
	init_timer(&buttons_timer);
	buttons_timer.function = &buttons_timer_function;

	//(   )3、        
	add_timer(&buttons_timer);
}

static irqreturn_t key_int(int irq, void *dev_id)
{
	//3、              keventd_wq 
	schedule_work(work);
	return 0;
}

void key_hw_init(void)
{
	volatile unsigned short data;
	volatile unsigned int *gpio_config;
	gpio_config = (volatile unsigned int *)ioremap(GPH0CON, 4);
	data = readw(gpio_config);		//          
	data &= ~0xFF;
	data |= 0xFF;
	writew(data, gpio_config);
	printk("key_hw_init!
"); led_config = (volatile unsigned int *)ioremap(LEDCON, 4); // writel(0x00011000, led_config); led_data = (volatile unsigned int *)ioremap(LEDDAT, 4); writel(0xFF, led_data); key_data = (volatile unsigned int *)ioremap(GPH0DAT, 4); } /*static long key_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return -EINVAL; }*/ static int key_open(struct inode *inode, struct file *file) { return 0; } static struct file_operations key_fops = { .owner = THIS_MODULE, //.unlocked_ioctl = key_ioctl, .open = key_open, .release = NULL, }; struct miscdevice key_miscdev = { .minor = 200, .name = DEVICE_NAME, .fops = &key_fops, }; // static int __init button_init(void) { int ret = 0; misc_register(&key_miscdev); // ret = request_irq(IRQ_EINT0, key_int, IRQF_TRIGGER_FALLING, DEVICE_NAME, 0); ret = request_irq(IRQ_EINT1, key_int, IRQF_TRIGGER_FALLING, DEVICE_NAME, 0); // key_hw_init(); //2、 work = kmalloc(sizeof(struct work_struct), GFP_KERNEL); //( :GFP_KERNEL , ) INIT_WORK(work, work_func); // , // timer_init(); return 0; } // static void __exit button_exit(void) { misc_deregister(&key_miscdev); // free_irq(IRQ_EINT0, 0); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jerry.Gou"); MODULE_DESCRIPTION("TQ210 button driver");

타이머 구현
/*          log        */
 /*__func__           __TIME__        ,   “hh:mm:ss”*/
#include 
#include 
#include 
#include 
#include 

static struct timer_list tm;
struct timeval oldtv;

void callback(unsigned long arg)
{
    struct timeval tv;
    char *strp = (char*)arg;
    
    printk("%s: %lu, %s
", __func__, jiffies, strp); do_gettimeofday(&tv); printk("%s: %ld, %ld
", __func__, tv.tv_sec - oldtv.tv_sec, // s tv.tv_usec- oldtv.tv_usec); // ms oldtv = tv; tm.expires = jiffies+1*HZ; add_timer(&tm); // } static int __init demo_init(void) { printk(KERN_INFO "%s : %s : %d - ok.
", __FILE__, __func__, __LINE__); init_timer(&tm); // do_gettimeofday(&oldtv); // tm.function= callback; // tm.data = (unsigned long)"hello world"; // tm.expires = jiffies+1*HZ; // add_timer(&tm); // return 0; } static void __exit demo_exit(void) { printk(KERN_INFO "%s : %s : %d - ok.
", __FILE__, __func__, __LINE__); del_timer(&tm); // } module_init(demo_init); module_exit(demo_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jerry.Gou"); MODULE_DESCRIPTION("TQ210 button driver");

좋은 웹페이지 즐겨찾기