LINUX 产生PPM 驱动例子

Posted on 2013-07-26 19:20  冰天雪域  阅读(522)  评论(0编辑  收藏  举报

APP:

 

//author:DriverMonkey
//phone:13410905075
//mail:bookworepeng@Hotmail.com
//qq:196568501


#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

#define US (1000)

#define PPM_CHANEL 8
#define FIX_LOW_TIME 100*US
#define FIX_SYNC_TIME 5000

static long long ppm_values[(PPM_CHANEL + 1)*2] = 
	   {FIX_LOW_TIME,1000*US,  	// 1
	   FIX_LOW_TIME,1000*US,	// 2
	   FIX_LOW_TIME,1000*US,	// 3
	   FIX_LOW_TIME,1000*US,  	// 4
	   FIX_LOW_TIME,1000*US,	// 5
	   FIX_LOW_TIME,1000*US,	// 6
	   FIX_LOW_TIME,1000*US,	// 7
	   FIX_LOW_TIME,1000*US,	// 8
	   FIX_LOW_TIME,FIX_SYNC_TIME*US, };	// 9


int main(int argc,char *args[])
{
	int fd;
	int channel = 0;
	long long value = 0;
	
	fd=open("/dev/ppm",O_WRONLY|O_CREAT,0640);
	if(fd < 0)
		return 0;

	if(argc > 3)	
		return;
	channel = atol(args[1]);
	printf("input channle is: %d\n", channel);
	
	value  = atol(args[2]);
	printf("input value is: %d\n", (int)value );

	printf("old value is:%d\n",(int)ppm_values[channel*2 + 1]);
	ppm_values[channel*2 + 1] = value*US;
	printf("new value is:%d\n",(int)ppm_values[channel*2 + 1]);
	
	write(fd,ppm_values,sizeof(ppm_values));

	sleep(20);
	close(fd);
}

Driver:

 

 

//author:DriverMonkey
//phone:13410905075
//mail:bookworepeng@Hotmail.com
//qq:196568501


#include <linux/kernel.h>  
#include <linux/module.h>  
#include <linux/cdev.h>  
#include <linux/fs.h>  
#include <linux/device.h>  
#include <linux/syscalls.h>
#include <linux/interrupt.h> 
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>  
#include <linux/string.h> 

#include <mach/gpio.h>
#include <mach/irqs.h>

#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))

#define US (1000)

#define PPM_CHANEL 8
#define FIX_LOW_TIME 100*US


struct ppm_dev  
{  
    struct cdev cdev;  
    dev_t devno;  
    struct class *ppm_class; 
	int message_cdev_open;	
}; 

struct ppm_dev ppm_dev;  


static long long ppm_values[(PPM_CHANEL + 1)*2] = 
	   {FIX_LOW_TIME,1000*US,  	// 1
	   FIX_LOW_TIME,1000*US,	// 2
	   FIX_LOW_TIME,1000*US,	// 3
	   FIX_LOW_TIME,1000*US,  	// 4
	   FIX_LOW_TIME,1000*US,	// 5
	   FIX_LOW_TIME,1000*US,	// 6
	   FIX_LOW_TIME,1000*US,	// 7
	   FIX_LOW_TIME,1000*US,	// 8
	   FIX_LOW_TIME,5000*US, };	// 9

ktime_t ktime;
static struct hrtimer hr_timer;

static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
{
	static int index = 0;
	static ktime_t ktime;
	if(index == ((PPM_CHANEL + 1)*2))
		index = 0;
	ktime.tv64 = ppm_values[index];
	hrtimer_forward(timer, timer->base->get_time(), ktime);
	index++;
	if(ktime.tv64 == FIX_LOW_TIME)
		gpio_direction_output(GPIO_TO_PIN(0,27), 0);
	else
		gpio_direction_output(GPIO_TO_PIN(0,27), 1);

	//printk("%d\n",(int)ktime.tv64);
	
	return HRTIMER_RESTART;
}


static int ppm_open(struct inode *node, struct file *fd)  
{  
	int ret = 0;
	
	printk("ppm_open()++\n"); 
	
	ktime = ktime_set( 0, 200*1000);				   // 200us
	hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
	hr_timer.function = &hrtimer_callback;
	hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );


    printk("ppm_open()--\n");  
  
    return ret;  
}   

 ssize_t ppm_write(struct file *pfile, 
 					const char __user *buffer, 
 					size_t size, 
 					loff_t *pnull)
 
{	

	printk("ppm_write()++\n");
	
	if(size != sizeof(ppm_values))
		return 0;

	copy_from_user(ppm_values, buffer, size);

	printk("ppm_write()--\n");
	
	return size;
}
static int ppm_fasync(int fd, struct file *filp, int mode)
{

	printk("ppm_fasync()++\n");
	

	printk("ppm_fasync()--\n");
	
	return 0;
}

static int ppm_release(struct inode *node, struct file *fd)  
{  
	printk("ppm_release()++\n"); 

	hrtimer_cancel(&hr_timer);	
    printk("ppm_release()--\n");  
    return 0;  
} 


struct file_operations meassage_operatons =  
{  
    .owner = THIS_MODULE,  
    .open = ppm_open,  
    
	.write = ppm_write,
    .fasync = ppm_fasync,
    .release = ppm_release,  
};  
  
static int __init ppm_init(void)  
{  
    struct ppm_dev * dev;  
	int ret = 0;
  

    dev = &ppm_dev;  

    alloc_chrdev_region(&dev->devno, 0, 1, "out_ppm");  

    dev->ppm_class = class_create(THIS_MODULE, "ppm_class");  
    if(IS_ERR(dev->ppm_class)) {  
         printk(KERN_ERR"Err: failed in creating class./n");  
         goto fail1;   
     }  
    device_create(dev->ppm_class, NULL, dev->devno, NULL, "ppm");  

	
	//init irq
	ret = gpio_request(GPIO_TO_PIN(0,27), "ppm_inter");
	if(ret){
		printk(KERN_ERR"gpio_request() failed !\n");
		goto fail1;
	}
	ret = gpio_direction_output(GPIO_TO_PIN(0,27), 1);
	if(ret){
		printk(KERN_ERR"gpio_direction_input() failed !\n");
		goto fail2;	
	}
	
    cdev_init(&dev->cdev, &meassage_operatons);  
    cdev_add(&dev->cdev, dev->devno, 1);  

	
	if(ret){
		printk(KERN_ERR"request_irq() failed ! %d\n", ret);
		goto fail2;
	}
	
   printk("ppm_to_app_init(void)--\n");      
    return 0;  

fail2:	
	gpio_free(GPIO_TO_PIN(0,27));	
fail1:    
	device_destroy(dev->ppm_class, dev->devno);  
    class_destroy(dev->ppm_class);   
    cdev_del(&dev->cdev);  
    unregister_chrdev_region(dev->devno, 1);  

	return ret;
}  
static void __exit ppm_exit(void)  
{  
    struct ppm_dev *dev = &ppm_dev;  
  
   // printk("ppm_to_app_exit(void)++\n"); 
   	gpio_free(GPIO_TO_PIN(0,27));

    device_destroy(dev->ppm_class, dev->devno);  
    class_destroy(dev->ppm_class);   
    cdev_del(&dev->cdev);  
    unregister_chrdev_region(dev->devno, 1);  
       
   // printk("ppm_to_app_exit(void)--\n");  
}  
module_init(ppm_init);  
module_exit(ppm_exit);  
  
MODULE_LICENSE("GPL");  
MODULE_AUTHOR("Driver Monkey");  
MODULE_DESCRIPTION("Test ppm");  



 


Copyright © 2024 冰天雪域
Powered by .NET 9.0 on Kubernetes