运维开发网

liunx驱动----点亮LED

运维开发网 https://www.qedev.com 2020-02-27 13:59 出处:网络
自动挂接根文件系统(直接从NFS启动) 修改uboot命令行 把 bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200

自动挂接根文件系统(直接从NFS启动)

  1. 修改uboot命令行

把 bootargs=noinitrd root=/dev/mtdblock3 init=/Linuxrc console=ttySAC0,115200

改为: set bootarges noinitrd root=/dev/nfs nfsroot=192.168.0.104:/home/book/work/nfs_root/first_fs ip=192.168.0.10:192.168.0.104:192.168.0.1:255.255.255.0::eth0:off init=/Linuxrc console=ttySAC0,115200   在uboot中设置如下: setenv bootargs noinitrd root=/dev/nfs console=ttySAC0 nfsroot=192.168.0.104:/home/book/work/nfs_root/first_fs ip=192.168.0.3:192.168.0.104:192.168.0.1:255.255.255.0::eth0:off init=/Linuxrc 设置NFS启动参数 :
  1. 设置服务器IP,目录
  2. 设置自己的IP
  运行第一个驱动程序 insmod first_drv.ko 挂载first_drv.ko cat /proc/devices 查看当前挂载了的驱动 ?

liunx驱动----点亮LED?   增加一个测试程序    

include <sys/types.h> include <sys/stat.h> include <fcntl.h> include <stdio.h> int main(int argc, char **argv) { int fd; int val = 1; fd = open("/dev/xxx", O_RDWR);//打开 if (fd < 0) { printf("can‘t open!\n"); } write(fd,&val,4);//写 return 0; }

 

  编译测试程序 arm-Linux-gcc -o first_dev_test first_dev_test.c ?分享图片? 提示不能打开当前测试文件是因为不存在/dev/xxx这个文件 所以需要创建这个设备节点 创建设备节点使用mknod 命令 mknod /dev/xxx c 111 0 命令 设备节点 设备类型(字符型) 主设备号(111) 次设备号   ?分享图片?   挂载设备 命令:insmod xxx(设备名称) 卸载设备命令:rmmod xxx( 设备名称) 查看设备命令:lsmod cat /proc/devices 查看当前挂载了的驱动     自动分配主设备号 ? ?

liunx驱动----点亮LED? 在注册 register_chrdev函数中设备号位置填写0 系统将在自动分配设备号 1驱动程序里面可以自动分配主设备号 也可以手动指定设备号

  1. 应用程序去打开一个open("/dev/xxx", O_RDWR); 使用 mknod /dev/xxx c 主设备号 次设备号 手动创建
  2. 使用自动创建 使用udev机制 就是busybox 中的mdev机制自动创建 (根据系统信息创设备节点)

定义一个类和一个设备

static struct class *firstdrv_class; static struct class_device *firstdrv_class_dev; 在初始化设备时添加
  1. 使用class_create创建一个firstdrv_class类
firstdrv_class = class_create(THIS_MODULE,"firstdrv");//创建一个 first_class 这样的一个类
  1. 使用class_device_create创建一个设备 设备节点是 xyz

firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); //mdev 自动创建一个 /dev/xyz */

 

int frist_drv_init(void)

{

major= register_chrdev(0,"frist_drv",&first_drv_fops);//注册函数(注册驱动程序) (major 主设备号 )告诉内核

//主设备号 驱动名称 file_operations结构

 

/*生成系统信息*/

firstdrv_class = class_create(THIS_MODULE,"firstdrv");//创建一个 first_class 这样的一个类

firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); //mdev 自动创建一个 /dev/xyz */

return 0;

}

 

在出口函数中添加如下
  1. 使用class_device_unregister 函数来卸载 class_device_create创建的设备

class_device_unregister(firstdrv_class_dev);

  1. 使用class_destroy 释放 掉firstdrv_class这个类

class_destroy(firstdrv_class);

void frist_drv_exit(void)
{
unregister_chrdev(major,"frist_drv");//卸载函数 卸载驱动
class_device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
}

 

实现点亮LED灯功能   硬件操作 映射虚拟地址 :使用 ioremap(off,sz) 函数 映射 /*将设备的物理地址映射为虚拟地址*/ gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); //0x56000050 (物理 地址) 16(长度) gpfdat = gpfcon+1; //0x56000050+4 = 0x56000054 (物理地址) 16(长度) 取消虚拟地址映射:iounmap(_addr); iounmap(gpfcon); iounmap(gpfcon+1); 内核和用户之间参数传递 : copy_from_user的功能是从用户空间传递数据到内核空间 对应的 copy_to_user 从内核空间传递数据到 用户空间 copy_from_user(&val,buf,count);  
  1. 配置 GPFCON open
static int first_drv_open(struct inode *inode, struct file *file)

{

//printk("first_drv_open\n");

/*配置GPFCON 4 5 6为输出*/

*gpfcon &=~((0x3<<(4*2))|(0x3<<(5*2))|(0x3<<(6*2)));//清除GPFCON 4 5 6对应位

*gpfcon |= ((0x1<<(4*2))|(0x1<<(5*2))|(0x1<<(6*2)));//设置 GPFCON 4 5 6 为输出

return 0;

}

 

 
  1. 设置 GPFDAT write
static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
int val;
//printk("first_drv_write\n");
copy_from_user(&val,buf,count);//将buf中的数据拷贝到 val中 val的值等于 *buf的前0-count的数据 copy_from_user的功能是从用户空间传递数据到内核空间
// 对应的 copy_to_user 从内核空间传递数据到 用户空间
if(val == 0)
{
*gpfdat |= ((1<<4)|(1<<5)|(1<<6));// 熄灭灯
}
else
{
*gpfdat &= ~((1<<4)|(1<<5)|(1<<6));//打开led
}
return 0;
}

 

使用次设备号: 主设备号 是建立与内核的链接,次设备号 是用来给驱动使用的 

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号