NIOS2 uCLinux-mmu驱动之LED 2

功能: 不用ioctl函数控制LED,用read函数读取PIO寄存器值, Write函数写入寄存器值实现控制LED灯

myleds_2.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/io.h>
#include <linux/string.h>
#include <linux/cdev.h> 
#include <linux/device.h> 
#include <asm/uaccess.h>
#include <linux/slab.h>

#define DEV_NAME "leddev"
#define NUMBER_OF_DEVICE 1

#define PIO_LED        0x00401420|0xE0000000

struct class *led_class; 
static struct cdev cdev; 
dev_t devno;

static ssize_t led_open(struct inode *inode, struct file *file)
{
    //printk(KERN_ALERT "led device open successfully!\n");
    return 0;
}

static ssize_t led_release(struct inode *inode, struct file *file)
{
    //printk(KERN_ALERT "led device close successfully!\n");
    return 0;
}

static ssize_t led_read(struct file *file, char __user *buff, size_t count, loff_t *offp){
    unsigned char led_dat;
    char led_string;

    if(NULL == file){
        return -1;
    }
    
    led_dat = readb(PIO_LED) & 0x0f;
    if(sprintf(&led_string,"%x",led_dat)==0) {
            printk(KERN_ALERT "read:sprintf error\n");
                return -EFAULT;
        }

    if(copy_to_user(buff,&led_string,count)!=0) {
            printk(KERN_ALERT "read:copy_to_user error\n");
                return -EFAULT;
    }

    return count;
}

static ssize_t led_write(struct file *file, char __user *buff, size_t count, loff_t *offp){
    unsigned char led_dat;
    char led_string;

    if(NULL == file){
        return -1;
    }

    if(copy_from_user(&led_string,buff,count)!=0){
            printk(KERN_ALERT "write:user pointer is not valid\n");
                return -EFAULT;
    }
    if(sscanf(&led_string,"%x",&led_dat)==0){
            printk(KERN_ALERT "write:sscanf error\n");
                return -EFAULT;
    }

    writeb(led_dat,PIO_LED);

    return count;
}

static struct file_operations led_fops=
{
    .owner= THIS_MODULE,
    .open = led_open,
    .read = led_read,
    .write = led_write,
    .release = led_release,
};

static int led_init(void)
{
    int ret;

    ret = alloc_chrdev_region(&devno,0, NUMBER_OF_DEVICE, DEV_NAME);
    if(ret<0){
    	printk(KERN_ALERT "%s alloc device error",__func__);    
    	return ret;
	}

    led_class = class_create(THIS_MODULE,"led_char_class");
    if(IS_ERR(led_class)){
        printk(KERN_ALERT "%s create class error\n",__func__);
        return -1;
    }

    device_create(led_class, NULL, devno, NULL, DEV_NAME);

    cdev_init(&cdev, &led_fops);
    cdev.owner = THIS_MODULE;
    cdev_add(&cdev, devno, NUMBER_OF_DEVICE);

    return 0;
}

static void led_exit(void)
{
    printk(KERN_ALERT "%s",__func__);
    cdev_del(&cdev);
    device_destroy(led_class,devno);
    class_destroy(led_class);
    unregister_chrdev_region(devno,NUMBER_OF_DEVICE);
    
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kimi Shi");


test_led_2.c

#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 fd, led_dat;
    char arg[3];
    char buff;

    //check argument
    if(argc!=2 && argc!=3){
        printf("INPUT ERROR, Use format below:\n");
        printf("test_led_2 -r         --read data from PIO_LED register\n");
        printf("test_led_2 -w [0-15]  --set PIO_LED register\n");
        exit(1);
    }
    //check argument 1 
    if(sscanf(argv[1],"%s",&arg)!=1 || (strcmp(arg,"-r")!=0 && strcmp(arg,"-w")!=0) ){
        printf("Input argument 1 wrong!\n");
        exit(1);
    }
    //open led device
    fd=open("/dev/leddev",O_RDWR);
    if(fd<0){
        perror("open led device\n");
        exit(1);
    }

    //read PIO_LED register data
    if(strcmp(arg,"-r")==0){
        read(fd, &buff, 1);
        printf("Value of PIO_LED register: %c\n",buff);
    }

    //Wrtie data to PIO_LED register
    if(strcmp(arg,"-w")==0){
        //check argument, 0x00 to 0x0f
        if(sscanf(argv[2],"%d",&led_dat)!=1 ||led_dat<0 ||led_dat>15){
    	    printf("input argument 2 wrong!\n");
    	    exit(1);
        }
        sprintf(&buff,"%x",led_dat);
        write(fd,&buff,1);
    }

    //clode device 
    close(fd);

    return 0;
}

test_led_3.c  流水灯

#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 fd = -1;
    int i, cnt;
    unsigned char led = 0x0f;
    unsigned char buff;

    //open
    fd = open("/dev/leddev",O_RDWR);
    if(0>fd){
        perror("open err:");
        exit(1);
    }

    //light water
    while(1){
        for(i=0;i<4;i++){
            led &= (1 << i);
            sprintf(&buff, "%x",led);
            cnt = write(fd, &buff, 1);
            if(0>cnt){
                perror("write err:");
                exit(1);
            }

            led = 0x0f;
            sleep(1);
        }
    }

    //close 
    close(fd);

    return 0;
       
}




你可能感兴趣的:(NIOS2 uCLinux-mmu驱动之LED 2)