一、相关知识
jiffies
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;
/*
* Convert various time units to each other:
*/
extern unsigned int jiffies_to_msecs(const unsigned long j);
extern unsigned int jiffies_to_usecs(const unsigned long j);
extern unsigned long msecs_to_jiffies(const unsigned int m);
extern unsigned long usecs_to_jiffies(const unsigned int u);
timer_list
struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct list_head entry;
unsigned long expires;
struct tvec_base *base;
void (*function)(unsigned long);
unsigned long data;
int slack;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
二、驱动源码
#include "nuc972_gpio.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define TIMER_DEV_NUMS 1
#define TIMER_NAME "timerled"
struct timer_dev{
dev_t devid;
int major;
int minor;
struct cdev cdev;
struct class *class;
struct device *device;
struct timer_list timer;
};
struct timer_dev timerdev;
/* */
#define SET_DIR 0X0100
#define GET_DIR 0X0200
#define SET_ODR 0X0300
#define GET_ODR 0X0400
#define GET_IDR 0X0500
#define GPIOA 0x0000
#define GPIOB 0x0001
#define GPIOC 0x0002
#define GPIOD 0x0003
#define GPIOE 0x0004
#define GPIOF 0x0005
#define GPIOG 0x0006
#define GPIOH 0x0007
#define GPIOI 0x0008
#define GPIOJ 0x0009
/* PF13-KEY1 PF14-KEY2 */
static int led_gpio_init(void)
{
int temp;
int ret = 0;
set_gpio_direction(GPIOB,0xffff);
set_gpio_odr(GPIOB,0xffff);
return ret;
}
void timer_function(unsigned long arg)
{
int temp;
temp = get_gpio_odr(GPIOB);
if(temp &(int)(1<<4))
{
set_gpio_odr(GPIOB,~(unsigned short)(1<<4));
}else
{
set_gpio_odr(GPIOB,0xffff);
}
mod_timer(&timerdev.timer,jiffies + msecs_to_jiffies(2000));
}
static int timerdev_open(struct inode *inode, struct file *filp)
{
int ret = 0;
init_timer(&timerdev.timer);
timerdev.timer.function = timer_function;
timerdev.timer.expires = jiffies + msecs_to_jiffies(2000);
led_gpio_init();
add_timer(&timerdev.timer);
return 0;
}
static ssize_t timerdev_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
int temp;
int ret = 0;
temp = get_gpio_idr(GPIOF);
ret = copy_to_user(buf,&temp,sizeof(temp));
return 0;
}
static int timerdev_release(struct inode *inode, struct file *filp)
{
del_timer(&timerdev.timer);
return 0;
}
static struct file_operations timerdev_fops = {
.owner = THIS_MODULE,
.open = timerdev_open,
.read = timerdev_read,
.release = timerdev_release,
};
static int __init timer_init(void)
{
int ret = 0;
timerdev.major = 0;
if(timerdev.major)
{
timerdev.devid = MKDEV(timerdev.major, 0);
ret = register_chrdev_region(timerdev.devid,TIMER_DEV_NUMS,TIMER_NAME);
}else
{
ret = alloc_chrdev_region(&timerdev.devid,0,TIMER_DEV_NUMS,TIMER_NAME);
timerdev.major = MAJOR(timerdev.devid);
timerdev.minor = MINOR(timerdev.devid);
}
if(ret < 0)
{
printk("register chrdev failed!\r\n");
goto fail_devid;
}
printk("timer major = %d, minor = %d \r\n", timerdev.major, timerdev.minor);
cdev_init(&timerdev.cdev, &timerdev_fops);
timerdev.cdev.owner = THIS_MODULE;
ret = cdev_add(&timerdev.cdev, timerdev.devid, TIMER_DEV_NUMS);
if(ret < 0)
{
printk("cdev_add failed!\r\n");
goto fail_cdevadd;
}
timerdev.class = class_create(THIS_MODULE, TIMER_NAME);
if(IS_ERR(timerdev.class))
{
printk("class_create failed!\r\n");
ret = PTR_ERR(timerdev.class);
goto fail_class;
}
timerdev.device = device_create(timerdev.class, NULL, timerdev.devid, 0, TIMER_NAME);
if(IS_ERR(timerdev.device))
{
printk("device_create failed!\r\n");
ret = PTR_ERR(timerdev.device);
goto fail_device;
}
printk("timer init success!\r\n");
return 0;
fail_device:
class_destroy(timerdev.class);
fail_class:
cdev_del(&timerdev.cdev);
fail_cdevadd:
unregister_chrdev_region(timerdev.devid,TIMER_DEV_NUMS);
fail_devid:
return ret;
}
static void __exit timer_exit(void)
{
del_timer(&timerdev.timer);
device_destroy(timerdev.class,timerdev.devid);
class_destroy(timerdev.class);
cdev_del(&timerdev.cdev);
unregister_chrdev_region(timerdev.devid, TIMER_DEV_NUMS);
printk("timer_exit!\r\n");
}
module_init(timer_init);
module_exit(timer_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mx");
三、APP源码
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "unistd.h"
int main(int argc, char *argv[])
{
int keyvalue = 0;
int destvalue = 0;
int fd;
int ret = 0;
char *filename;
if(argc != 2)
{
printf("Error Usage!\r\n");
return -1;
}
filename = argv[1];
fd = open(filename,O_RDWR);
if(fd < 0)
{
printf("file %s open failed!\r\n",filename);
return -1;
}
destvalue = 1<<13;
while(1)
{
}
close(fd);
return 0;
}
四、实验总结
无