调试驱动时,为了避免每修改一次内核配置或驱动都要重新编译一次内核镜像,可以将驱动配置成模块(module)的方式进行调试,可在LINUX启动时动态地加载驱动模式到内核中,减少了编译时间,也省去了重启LINUX的时间,大大加快调试进度。
以下以Micro2440 + linux 2.6.39的RTC驱动为例子,进行动态编译。
a) 将RTC编译成module,并打开DEBUG输出
# make menuconfig
Device Drivers --->
<*> Real Time Clock --->
[*] RTC debug support //打开DEBUG输出
<M> Samsung S3C series SoC RTC //编译成模块
b) 使内核支持动态加载调试信息输出
Kernel hacking --->
[*] Tracers --->
[*] Trace max stack //打开这里后,有些设置跟着默认打开
[*] Enable dynamic printk() support //支持动态加载时的输出
c) 重新编译内核,并将内核下载到开发板运行
# make uImage
# cp arch/arm/boot/uImage /opt/TFTP_DIR/MICRO2440 //复制到TFTP目录(通过U-BOOT的TFTP命令下载至RAM中运行)
d) 编译module并复制到根目录
# make modules
#cp ./drivers/rtc/rtc-s3c.ko ../../3.Filesystem/NFS/lib/modules/2.6.39/
注意,.ko文件必须放到/lib/modules/2.6.39/目录下,否则无法卸载。
e) 修改控制台打印级别
Console的默认级别是7,即级别小于7的调试信息才会打印出来。Printk的级别是7,那就还需要修改Console的打印级别。
# cat /proc/sys/kernel/printk //查看当前打印级别
# echo 8 > /proc/sys/kernel/printk //修改打印级别
注意,由于printk文件是在ramfs中的,因此重启INUX后又会恢复默认值,因此可以在/etc/init.d/rcS的末尾增修改打印级别的代码,让其启动自动修改。
f) 加载RTC模块、创建设备文件、运行
# insmod /lib/modules/2.6.39/rtc-s3c.ko
# lsmod //使用lsmod可以查看已经加载的模块
# mknod /dev/rtc0 c 254 0 //使用cat /proc/devices可以查看主设备号
# rmmod rtc_s3c //使用rmmod可以卸载模块
# date -s 2014.07.25-8:5:24 //设置系统时钟
# hwcolck -w //同步系统时钟到硬件时钟
如下图所示,各个操作均正常,需要注意的就是KO文件的存放路径,和rmmod时的模块名字要从lsmod的显示中取得。加载打开DEBUG信息的模块后,可看到使用hwclock命令后,已经可以打印出pr_debug()输出的调试信息了。