注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

W_中原的博客笔记

通知:新博客日志将更新到个人站点:http://www.zhgyuan.cn/

 
 
 

日志

 
 

S5PV210内核定时器驱动LED  

2014-05-16 10:39:21|  分类: 嵌入式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

linux内核定时器:

struct timer_list {
    struct list_head entry;
    unsigned long expires;//
定时时间,jiffies+delayn

    void (*function)(unsigned long);//
处理函数
    unsigned long data; //存放参数,作为function的参数进行传递

    struct tvec_base *base;
    ...
};//
内核定时器结构体

一般操作步骤:声明一个定时器,然后初始化,然后添加定时器到内核,定时器开始启动,时间到后,定时器处理程序会自动执行,在中断程序里需要重新设置定时值,并重新使用add_timer来开启定时器

struct timer_list my_timer; //声明一个定时器

void init_timer(struct timer_list *timer); //初始化定时器,在该定时器成员赋值前,先执行初始化

void add_timer(struct timer_list *timer); //向内核添加一个定时器,启动该定时器

int mod_timer(struct timer_list *timer,unsigned long expires);//修改定时的expire

int del_timer(struct timer_list *timer); //删除一个定时器


基于S5PV210的内核定时器驱动LED的小例子(两个LED以0.5s的频率闪烁):

led.c:

#include<linux/init.h>

#include<linux/module.h>

#include <linux/kernel.h>

#include <mach/regs-gpio.h>

#include <linux/device.h>

#include <linux/gpio.h>

#include <linux/poll.h>


#define LED_DEV_NAME "led"

static struct timer_list timer_led;

static int major = 0; //主设备号,动态分配

static void GPIOInit ( void );

static int led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);

static int led_init ( void );

static void led_exit ( void );


static struct class *led_class; //节点

static int led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

switch(cmd)

{

case 0: //cmd为0则关闭LED

{

gpio_set_value (S5PV210_GPH3(arg), 0);

return 0;

}

case 1:

{

gpio_set_value (S5PV210_GPH3(arg), 1);

return 0;

}

default: return -EFAULT;

}

}


static void led_timer()

{

static char sta = 0;

timer_led.expires = jiffies + (HZ / 2);

add_timer(&timer_led);

sta = !sta;

gpio_set_value (S5PV210_GPH3(2), sta);

gpio_set_value (S5PV210_GPH3(1), sta);

}


static int led_open ( struct inode *inode_ptr, struct file *fptr ) 

{

GPIOInit ();

timer_led.function = led_timer;

init_timer(&timer_led);

timer_led.expires = jiffies + (HZ / 2);

add_timer(&timer_led);

return 0;

}


static struct file_operations led_fops =

{

.owner = THIS_MODULE,

.open  = led_open,

.ioctl = led_ioctl,

};


static void GPIOInit ( void )

{

//初始化输出低电平

gpio_direction_output (S5PV210_GPH3(4), 0);

//gpio_set_value (S5PV210_GPH3(4), 0);


gpio_direction_output (S5PV210_GPH3(0), 0);

//gpio_set_value (S5PV210_GPH3(0), 0);


gpio_direction_output (S5PV210_GPH3(1), 0);

//gpio_set_value (S5PV210_GPH3(1), 0);


gpio_direction_output (S5PV210_GPH3(2), 0);

//gpio_set_value (S5PV210_GPH3(2), 0);


gpio_direction_output (S5PV210_GPH3(3), 0);

//gpio_set_value (S5PV210_GPH3(3), 0);

}

static int led_init ( void )

{

int status=0;

//GPIOInit();

status = register_chrdev(major, LED_DEV_NAME, &led_fops); //注册设备,LED_DEV_NAME:设备名


if ( status < 0 ) //注册失败

{

printk ( "myled_init : cannot get major number .\n" );

return status;

}

else if ( major == 0 )

{

major = status ;

}

printk ( "myled_init OK\n" ) ;

led_class = class_create(THIS_MODULE, LED_DEV_NAME); //创建节点

if(IS_ERR(led_class))

{

printk("Err: failed in Real210-LED class. \n");

return -1;

}

device_create(led_class, NULL, MKDEV(major, 0), NULL, LED_DEV_NAME);

return 0 ;

}

static void led_exit ( void )

{

//LED退出测试

//printk("Real210 LED OFF\n");

/*

gpio_set_value (S5PV210_GPH3(4), 1);

gpio_set_value (S5PV210_GPH3(0), 1);

gpio_set_value (S5PV210_GPH3(1), 1);

gpio_set_value (S5PV210_GPH3(2), 1);

gpio_set_value (S5PV210_GPH3(3), 1);

//gpio_set_value (S5PV210_GPH2(4), 1);

*/

//注销设备

unregister_chrdev ( major, LED_DEV_NAME);

device_destroy(led_class, MKDEV(major, 0));

class_destroy(led_class);

printk("led exit ok\n");

}

module_init ( led_init ) ;

module_exit ( led_exit ) ;

MODULE_DESCRIPTION ( "S5PV210  led timer driver" ) ;

MODULE_AUTHOR ( "wzy201109" ) ;

MODULE_LICENSE ( "GPL" ) ;


led.c对应的Makefile(/opt/kernel_2.6.35  为内核目录):

ifneq ($(KERNELRELEASE),)  

obj-m := led.o   

else  

KDIR := /opt/kernel_2.6.35  

all:

make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux- 

clean:

rm -f *.ko *.o *.mod.o *~ *.mod.c *.symvers   

endif 

S5PV210内核定时器驱动LED - W_中原 - 汪中原的博客笔记

测试程序ledtext.c:
#include <stdio.h>  
#include <string.h>  
#include <sys/types.h>  
//#include <sys/stat.h>  
#include <sys/ioctl.h>  
#include <fcntl.h>  
#include <linux/types.h>  
#include <time.h>  
#include <sys/time.h>  
#include <stdlib.h>  

#define false 0  
 
int main (int argc, char *argv[])
{
    int fd,i,j;

    fd = open ( "/dev/led",O_RDONLY) ;
    if ( fd == -1 )
    {
        printf( "Open device led failed .\n" ) ;
        return false ;
    }
    printf( "LED timer init OK.\n" );
    close ( fd ) ;
    return 0;
 }

 


  评论这张
 
阅读(19)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017