Linux Driver 入门-2

second_cdrv.c :

#include <linux/init.h>

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");

static dev_t dev_id;
static struct cdev *my_cdev;
static struct class *second_drv_class;
static struct device *second_drv_class_device;
static volatile unsigned long *gpbcon;
static volatile unsigned long *gpbdat;

#define led_on(n) *gpbdat &= ~(1<<(n+4))
#define led_off(n) *gpbdat |= (1<<(n))


static int second_cdrv_read (struct file * file, char __user * buf, size_t count, loff_t *offset)
{
    printk(KERN_ALERT"second_cdrv_read start.\n");
    return 0;  
}

static int second_cdrv_write (struct file * file, const char __user * buf, size_t count, loff_t *offset)
{
    char val;
    if(count != 1)
    {
        return -EINVAL;
    }
    copy_from_user(&val, buf, 1);
    if(val >= 1 && val <= 4)
    {
        led_on(val);
    }
    else if(val>= 5 && val <= 8)
    {
        led_off(val);
    }
    else
    {
        return -EINVAL;
    }
    return 0;  
}

static int second_cdrv_release (struct inode * inode, struct file * file)
{
    iounmap(gpbcon);
    iounmap(gpbdat);
    return 0;
}

static int second_cdrv_open (struct inode * inode, struct file * file)
{
    gpbcon = (unsigned long *)ioremap(0x56000010 , 4);
    gpbdat = (unsigned long *)ioremap(0x56000014 , 4);
    *gpbcon &= ~(3<<10|3<<12|3<<14|3<<16);
    *gpbcon |= (1<<10|1<<12|1<<14|1<<16);
    *gpbdat |= (1<<5|1<<6|1<<7|1<<8);
    return 0;  
}

struct file_operations fops ={
    .owner = THIS_MODULE,
    .open = second_cdrv_open,
    .read = second_cdrv_read,
    .write = second_cdrv_write,
    .release = second_cdrv_release,
};

static int __init second_cdrv_init(void)
{
    int ret = 0;
    ret = alloc_chrdev_region(&dev_id, 0, 4, "second_cdrv");
    if(ret != 0)
    {
        printk(KERN_ERR"alloc_chrdev_region failed\n");  
    }

    my_cdev = cdev_alloc();
    cdev_init(my_cdev, &fops);
    my_cdev->owner = THIS_MODULE;

    ret = cdev_add(my_cdev, dev_id, 4);
    if(ret != 0)
    {
        printk(KERN_ERR"cdev_add failed\n");  
    }

    second_drv_class = class_create(THIS_MODULE, "second_cdrv");
    second_drv_class_device = device_create(second_drv_class, NULL, dev_id, NULL, "chenjun");
    
    return 0;
}

static void __exit second_cdrv_exit(void)
{
    device_destroy(second_drv_class, dev_id);
    class_destroy(second_drv_class);
    cdev_del(my_cdev);
       if(my_cdev)
      {
        printk(KERN_ALERT"kzfree\n");
        kzfree(my_cdev);
        my_cdev = NULL;
      }
    unregister_chrdev_region(dev_id, 4);
}

module_init(second_cdrv_init);

module_exit(second_cdrv_exit);


Makefile:

KERNELDIR := /opt/wfe/linux-3.2_m
PWD := $(shell pwd)
#obj-m := hello_world.o
#obj-m := first_cdrv.o
obj-m := second_cdrv.o
COMPILE_GCC := arm-linux-gcc

TEST := test
TEST_FILE := module_test.c

CLEAN_FILES := *.mod.* *.symvers *.order *.o *.ko $(TEST)

M_CFLAGS := -Os -Wall -g -c

default:
    make -C $(KERNELDIR) M=$(PWD) modules

$(TEST):$(TEST_FILE)
    $(COMPILE_GCC) -o $@ $<
.PHONY:clean
clean:
    rm -rf $(CLEAN_FILES)


module_test.c :

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
  char i = 1;
    int ret = 0;
    int fd;
    fd = open("/dev/chenjun",O_RDWR);
    while(1)
    {
        ret = write(fd, &i, 1);
        sleep(1);
        if(i++ == 8)
        {
            i = 1;
        }
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值