嵌入式驱动编写-第一个驱动程序
来源:互联网 发布:c语言编写驱动程序 编辑:程序博客网 时间:2024/05/16 15:20
打开开发板的原理图
找到操作LED的寄存器
1 确定运行环境正常
1 PC,linux虚拟机,JZ2440开发板之前可以互相ping通
查看设备类型
1 编写驱动程序
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>//定义一个open函数static int first_drv_open(struct inode *inode, struct file *file){printk("first_drv_open/n");return 0;}//定义一个write函数static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){printk("first_drv_write/n");return 0;}//定义一个file_operations 结构体static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = first_drv_open, //结构体的函数是定义的.write=first_drv_write,//结构体的函数是定义的};//定义入口函数static int first_drv_init(void){//app找到这个驱动 不是根据名字 是根据 设备类型 主设备号register_chrdev(123, "first_drv", &first_drv_fops);// 注册, 告诉内核 主设备号 名字 定义的结构体return 0;}//定义出口函数static void first_drv_exit(void){unregister_chrdev(123, "first_drv");}//通过module修饰成为linux内核可识别的入口和出口函数module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");
2 编写makefile来进行编译
KERN_DIR = /work/system/linux-2.6.22.6all:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m+= first_drv.o
3 将这两个文件上传到linux服务器上,进行编译得到的 first_drv.ko 放到网络文件系统中,启动开发板,启动内核,进入内核,挂接网络文件系统,进入 /mnt目录,查看目前的设备节点是否有123。
starting pid 767, tty '/dev/ttySAC0': '/bin/sh'# lsbin lib mnt sbin usrdev linuxrc proc sysetc lost+found root tmp# cd /mnt/# ls# cd ../# ifconfigeth0 Link encap:Ethernet HWaddr 00:60:6E:33:44:55 inet addr:192.168.1.17 Bcast:192.168.1.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:2 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:128 (128.0 B) TX bytes:0 (0.0 B) Interrupt:51 Base address:0xa000 # ifconfig eth0 192.168.0.105# mount -t nfs -o nolock,vers=2 192.168.0.104:/work/nfs_root/first_fs/ mnt# cd // /etc/ /mnt/ /sbin/ /usr//bin/ /lib/ /proc/ /sys//dev/ /lost+found/ /root/ /tmp/# cd /mnt/# lsbin first_drv.ko mnt sysbutton_drv.ko firstdrvtest myleds.ko test.txtbuttontest forth_drv.ko myleds2.ko test_drv.kocfbcopyarea.ko forthdrvtest proc testdrv_testcfbfillrect.ko hello sbin third_drv.kocfbimgblt.ko hello.c second_drv.ko thirddrvtestdev lcd.ko seconddrvtest uImageetc ledtest signal uImage_nolcdfifth_drv.ko lib sixth_drv.ko usrfifthdrvtest linuxrc sixthdrvtest# insmod first_drv.ko # remmod first_drv.ko -sh: remmod: not found# cat /proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 /dev/vc/0 4 tty 4 ttyS 5 /dev/tty 5 /dev/console 5 /dev/ptmx 6 lp 7 vcs 10 misc 13 input 14 sound 29 fb 90 mtd 99 ppdev116 alsa128 ptm136 pts180 usb189 usb_device204 s3c2410_serial252 first_drv253 usb_endpoint254 rtcBlock devices: 1 ramdisk 7 loop 8 sd 31 mtdblock 65 sd 66 sd 67 sd 68 sd 69 sd 70 sd 71 sd128 sd129 sd130 sd131 sd132 sd133 sd134 sd135 sd179 mmc#
确定后,开始挂载设备节点,insmod first_drv.ko ,
通过# cat /proc/devices 查看当前的设备节点 看到挂接成功
通过rmmod first_drv 命令后 再次查看 发现你123的设备节点没有了
4 修改一下驱动程序,在第一个驱动程序中,设备号是写死的,这样我们不确定这个设备号是否已经被占用。
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>//定义一个open函数static int first_drv_open(struct inode *inode, struct file *file){printk("first_drv_open/n");return 0;}//定义一个write函数static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){printk("first_drv_write/n");return 0;}//定义一个file_operations 结构体static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = first_drv_open, //结构体的函数是定义的.write=first_drv_write,//结构体的函数是定义的};int major;//定义入口函数static int first_drv_init(void){//app找到这个驱动 不是根据名字 是根据 设备类型 主设备号//主设备号 随便写个123 写 0会自动分配major = register_chrdev(0, "first_drv", &first_drv_fops);// 注册, 告诉内核 主设备号 名字 定义的结构体return 0;}//定义出口函数static void first_drv_exit(void){unregister_chrdev(major, "first_drv");}//通过module修饰成为linux内核课识别的入口和出口函数module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");
重复之前的操作,上传,编译,运行,看到自动分配的是252
# insmod first_drv.ko # cat /proc/devices Character devices: 1 mem 2 pty 3 ttyp 4 /dev/vc/0 4 tty 4 ttyS 5 /dev/tty 5 /dev/console 5 /dev/ptmx 6 lp 7 vcs 10 misc 13 input 14 sound 29 fb 90 mtd 99 ppdev116 alsa128 ptm136 pts180 usb189 usb_device204 s3c2410_serial252 first_drv253 usb_endpoint254 rtcBlock devices: 1 ramdisk 7 loop 8 sd 31 mtdblock 65 sd 66 sd 67 sd 68 sd 69 sd 70 sd 71 sd128 sd129 sd130 sd131 sd132 sd133 sd134 sd135 sd179 mmc
5 写测试程序调用驱动程序
#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;}
上传到服务器上编译,放到网络文件系统下,进入开发板来运行
# ./firstdev_test can't open!#
发现没有这个目录,我们来创建这个设备目录
# mknod /dev/xxx c 252 0
再次运行,发现打印出驱动程序的实现。
# ./firstd./firstdev_test ./firstdrvtest# ./firstdev_test first_drv_open/nfirst_drv_write/n#
6 继续修改代码,设备号每次都通过 cat来获得太麻烦
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>static struct class *firstdrv_class;static struct class_device*firstdrv_class_dev;//定义一个open函数static int first_drv_open(struct inode *inode, struct file *file){printk("first_drv_open/n");return 0;}//定义一个write函数static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){printk("first_drv_write/n");return 0;}//定义一个file_operations 结构体static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = first_drv_open, //结构体的函数是定义的.write=first_drv_write,//结构体的函数是定义的};int major;//定义入口函数static int first_drv_init(void){//app找到这个驱动 不是根据名字 是根据 设备类型 主设备号//主设备号 随便写个123 写 0会自动分配major = register_chrdev(0, "first_drv", &first_drv_fops);// 注册, 告诉内核 主设备号 名字 定义的结构体firstdrv_class = class_create(THIS_MODULE, "firstdrv");firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */return 0;}//定义出口函数static void first_drv_exit(void){unregister_chrdev(major, "first_drv");class_device_unregister(firstdrv_class_dev);class_destroy(firstdrv_class);}//通过module修饰成为linux内核课识别的入口和出口函数module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");
0 0
- 嵌入式驱动编写-第一个驱动程序
- 嵌入式Linux驱动笔记(一)------第一个LED驱动程序
- 嵌入式Linux驱动学习笔记(一)------第一个LED驱动程序
- 嵌入式驱动编写-按键驱动程序
- 嵌入式驱动编写-LCD驱动程序
- 编写第一个HelloWorld驱动程序
- 第一个驱动程序-led驱动
- 【Linux驱动】第一个驱动程序
- Windows8.1驱动编写以及内核调试(一) 做好准备工作并编写第一个驱动程序
- 嵌入式驱动编写-点亮LED驱动程序
- 第一个嵌入式Linux的驱动程序
- 驱动入门 二 第一个驱动程序
- Windows驱动开发之第一个驱动程序
- 郁金香驱动编程学习>第一课:第一个驱动程序
- Tiny6410 我的第一个嵌入式linux驱动程序模块
- Tiny6410 我的第一个嵌入式Linux驱动程序模块
- 第一个嵌入式linux驱动程序——LED
- 第一个模块,hello world 驱动编写
- Android弹幕功能实现,模仿斗鱼直播的弹幕效果
- 4.一些关简单的键字.package,private,this
- Leetcode||14.Longest Common Prefix
- “玲珑杯”ACM比赛 Round #4 E题
- dht11模块的学习
- 嵌入式驱动编写-第一个驱动程序
- 文件属性分析
- 高低压为什么不能共地的一个解释
- 项目版本不同导致Eclipse报错问题——关于在JDK1.7环境中,运行JDK1.8环境下编写的项目。
- C语言模拟考|Proper Fraction
- Python的垃圾回收
- 平面上的邮局
- 161105
- js this的应用场景