在设备树下创建IO子节点,方便一点在根节点/,把寄存器的复用以及电气属性追加在IOMUX(目前学到的引脚)。记得编译设备树,linux内核重新启动。
点灯大法:
编写驱动和编写APP
需要注意失败时的处理cdev和device分配了内存需要释放,设备号要注销,class要销毁。
注册设备号
if(beep.major){
beep.devid = MKDEV(beep.major, beep.minor);
register_chrdev_region(beep.devid,DEV_NUMBER,DEV_NAME);
}else {
alloc_chrdev_region(&beep.devid,0,DEV_NUMBER,DEV_NAME);
beep.major = MAJOR(beep.devid);
beep.minor = MINOR(beep.devid);
}printk("beep major = %d, minor = %drn",beep.major, beep.minor);
初始化c_dev并add上(将*ops与其绑定)
beep.cdev.owner = THIS_MODULE;
cdev_init(&beep.cdev,&beep_ops);
cdev_add(&beep.cdev,beep.devid,DEV_NUMBER);
创建class类(入口参数MODULE和注册名,感觉不太重要,作为device入口参数)
beep.class = class_create(THIS_MODULE,DEV_NAME);
if(IS_ERR(beep.class)){
return PTR_ERR(beep.class);
}
创建device设备
beep.device = device_create(beep.class,NULL,beep.devid,NULL,DEV_NAME);
if(IS_ERR(beep.device)){
return PTR_ERR(beep.device);
}
beep.nd = of_find_node_by_path("/beep");
if(beep.nd == NULL){
ret = -EINVAL;
goto failed_find_node;
}
beep.beep_gpio = of_get_named_gpio(beep.nd,"beep-gpios",0);
if(beep.beep_gpio < 0 ){
printk("can't find BEEP rn");
ret = -EINVAL;
goto failed_find_node;
}printk("beep gpio number = %drn",beep.beep_gpio);
ret = gpio_request(beep.beep_gpio,"beep-gpios");
if(ret){
printk("beep_gpio request failedrn");
ret = -EINVAL;
goto failed_find_node;
}
终于不用在像之前学习操作寄存器了, 通过获取节点对应IO号操作,记得向内核申请防止IO正在被使用。
ret = gpio_direction_output(beep.beep_gpio,1);
if(ret){
ret = -EINVAL;
goto failed_setoutput;
}
gpio_set_value(beep.beep_gpio,1);
file_operations指针
static const struct file_operations beep_ops = {
.owner = THIS_MODULE,
.write = beep_write,
.open = beep_open,
.release = beep_release,
};
static ssize_t beep_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
{
int ret;
unsigned char databuf[1];
struct beep_dev *dev = filp->private_data;
ret = copy_from_user(databuf, buf, count);
if(ret < 0){
return -EFAULT;
}
gpio_set_value(dev->beep_gpio,databuf[0]);
return 0;
}
数据由用户到内核空间write->beep_write
编写APP
#include#include #include #include #include #include #include #define LEDOFF 0 #define LEDON 1 int main(int argc, char *argv[]) { int fd; char *filename = argv[1]; unsigned char databuf[1]; int retval = 0; if(argc != 3){ printf("Usage:Errorrn"); return -1; } fd = open(filename, O_RDWR); if(fd < 0){ printf("Error openingrn"); return -1; } databuf[0] = atoi(argv[2]); retval = write(fd, databuf, sizeof(databuf)); if(retval < 0) { printf("LED write Errorrn"); close(fd); return -1; } close(fd); return 0; }



