一,前言
学习的步骤一般都是从简单到难,从开发驱动的角度来看,linux和单片机的区别主要是框架不同。若简单来说linux的架构及API的使用方法了解后,就可以自己写驱动了。而不是仅仅只是改改设备树,改改配置,调试下了。当内核理论及常用API复习完成后,我开始进入自己动手写驱动了,光看不练是不行地~代码工程我会放在我gitee上https://gitee.com/applecai/linux-driver-study
二,globalmem改成了applepaper驱动
linux设备驱动开发详解中有globalmem虚拟驱动,然后几个章节都在其上做功能添加及改进。我也参考这个思路,由于globalmem就是一段内存区的字符设备驱动,所以我把它当做paper来使用。设备名字定义为applepaper。另外设备号一般都从0开始,我故意改成6,主要是习惯下那些API的参数。
刚刚做了2个工程
ko模块编译方法:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
APP编译方法:arm-linux-gnueabihf-gcc -static applepaperApp.c -o applepaperApp
1. 1_applepaper工程
功能说明:就是注释和注销设备号。目的是练习最小框架。
2. 2_applepaper工程
功能说明:在1的基础上添加了read和write函数。并且添加了APP对读写进行功能验证。仅简单入门读写框架。将来会继续添加功能。
三,过程中遇到的问题
1.编译出现错误:fatal error: asm/system.h: No such file or directory
错误信息可知,缺少此头文件
原因:
Linux内核是不断地更新换代,即3.3版本之后内核用switch_to.h替换了曾经的system.h头文件。
解决方法:
可在终端输入uname -r,查看自己Linux内核版本。如,我的内核版本是4.2.0-27-generic,可知为3.3之后版本,直接使用#include
2.insmod applepaper.ko 提示 loading out-of-tree module taints kernel
原因:
使用内核源代码未包含的树外模块,由于我每添加到设备树,所以警告是应该的。暂时不改。
参考网址:
https://unix.stackexchange.com/questions/118116/what-is-a-tainted-kernel-in-linux
3.device_create的oops错误解决方法
[ 25.443548] Backtrace:
[ 25.446020] [] (kvasprintf_const) from [] (kobject_set_name_vargs+0x34/0xa8)
[ 25.454846] r7:00000000 r6:bf001104 r5:dd2c6f40 r4:dd297e00
[ 25.460537] [] (kobject_set_name_vargs) from [] (device_create_groups_vargs+0x90/0xc4)
[ 25.470234] r7:00000000 r6:bf001104 r5:dd2c6f40 r4:dd297e00
[ 25.475920] [] (device_create_groups_vargs) from [] (device_create+0x40/0x60)
[ 25.484834] r9:bf002040 r8:bf002040 r7:bf002000 r6:c0e05148 r5:00000000 r4:c0e05148
[ 25.492627] [] (device_create) from [] (applepaper_init+0x124/0x1000 [applepaper])
[ 25.501973] r5:bf002240 r4:00000000
[ 25.505575] [] (applepaper_init [applepaper]) from [] (do_one_initcall+0x58/0x258)
[ 25.514924] r8:c0ec3aa0 r7:ffffe000 r6:00000000 r5:bf005000 r4:c0e05148
[ 25.521661] [] (do_one_initcall) from [] (do_init_module+0x6c/0x264)
[ 25.529789] r8:dd2eff28 r7:dd20cfc0 r6:dd20cf80 r5:dd206bc0 r4:bf002040
[ 25.536522] [] (do_init_module) from [] (load_module+0x2328/0x25b0)
[ 25.544561] r6:dd20cf80 r5:00000002 r4:00000002
[ 25.549201] [] (load_module) from [] (sys_finit_module+0xcc/0xec)
[ 25.557067] r10:0000017b r9:00000000 r8:7fffffff r7:00000003 r6:000d6008 r5:00000000
[ 25.564928] r4:c0e05148
[ 25.567474] [] (sys_finit_module) from [] (ret_fast_syscall+0x0/0x28)
[ 25.575686] Exception stack(0xdd2effa8 to 0xdd2efff0)
[ 25.580762] ffa0: 000d6008 00000006 00000003 000d6008 00000000 beb0cf49
[ 25.588979] ffc0: 000d6008 00000006 beb0cf49 0000017b 00000000 00000000 b6f3cf74 00000000
[ 25.597194] ffe0: beb0ccb0 beb0cca0 00030228 b6ea9cf0
[ 25.602270] r9:dd2ee000 r8:c01011c4 r7:0000017b r6:beb0cf49 r5:00000006 r4:000d6008
[ 25.610051] Code: 00000000 00000000 00000000 e20110ff (e4d02001)
[ 25.616236] ---[ end trace e39ec680f5e4bed7 ]---
Segmentation fault
device_create()参数使用很灵活,一不小心就会导致加载时内核报oops错误(vsnprintf引起)。
device_create(my_class, NULL, MKDEV(major,minor), "hello" "%d",0);
在"hello" "%d"之间加上","能解决insmod时oops错误,但是却不能在/dev目录下创建想要的设备文件。正确的调用方法如下:
device_create(my_class, NULL, MKDEV(major,minor), NULL,"hello%d",0);
4.可执行程序无法在Linux上运行,显示line 1: syntax error: word unexpected (expecting ")
解决方法:应该用静态编译。-static
修改前,确实包含了动态库
修改后,不包括动态库
四,成功的log
1的log,设备号major为247,设备minor为6。class和dev都创建正确。
# insmod applepaper.ko
[ 265.735980] b
[ 265.737626] 2
[ 265.739218] 3
[ 265.741211] Registered character driver
# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
29 fb
89 i2c
90 mtd
128 ptm
136 pts
247 applepaper
248 ttySDIO
249 rpmb
250 ttyO
251 ptp
252 pps
253 rtc
254 gpiochip
Block devices:
1 ramdisk
7 loop
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
259 blkext
# ls -l /dev|grep 247
crw------- 1 root root 247, 6 Jan 1 00:04 applepaper6
# cd /sys
# ls
block class devices fs module
bus dev firmware kernel power
# cd class
# ls
apple_class extcon mem pps spi_master
ata_device gpio misc ptp thermal
ata_link graphics mmc_host pwm tty
ata_port i2c-adapter mtd regulator ubi
backlight i2c-dev net remoteproc vc
bdi input pci_bus rtc vtconsole
block iommu pci_epc scsi_device wakeup
devcoredump lcd phy scsi_disk
dma mdio_bus power_supply scsi_host
# cd apple_class/
# ls
applepaper6
# cd applepaper6/
# la
-sh: la: not found
# ls
dev power subsystem uevent
# cat dev
247:6
# cd /sys/devices/
# ls
armv7_cortex_a8 platform system virtual
breakpoint soc0 tracepoint
kprobe software uprobe
# cd virtual/
# ls
apple_class block mem net vc workqueue
bdi graphics misc tty vtconsole
# cd apple_class/
# ls
applepaper6
# cd applepaper6/
# ls
dev power subsystem uevent
2的log,通过运行applepaperApp读写正确。
# insmod applepaper1.ko
[ 29.700013] applepaper1: loading out-of-tree module taints kernel.
[ 29.707770] Registered character driver
# ./applepaperApp /dev/applepaper6 2
[ 49.949258] written 50 bytes(s) from 0
# ./applepaperApp /dev/applepaper6 1
[ 52.665337] read 50 bytes(s) from 0
read data:usr data!
# echo "hi AppleCai" > /dev/applepaper6
[ 87.853832] written 12 bytes(s) from 0
# cat /dev/applepaper6
[ 94.177645] read 4096 bytes(s) from 0
hi AppleCai
��w|cat: read error: No such device or address
注:我主要用applepaperApp来进行读写是正确的,echo的读写调用的函数我暂时不太清楚,貌似也可以读写,只是尝试性用了下。