【Makefile文件】
KERNELDIR = /home/wolf/wolfkittools/linux-2.6.32.2
#到网上下载目标板内核版本的内核源码并解压编译,这里填源码目录
#驱动程序编译时需要从目标平台的内核获取一些信息
PWD := $(shell pwd) #输出到当前目录
CC = arm-linux-gcc #交叉编译器
#注意设置好PATH环境变量,让系统能找到arm-linux-gcc
obj-m := led_driver.o
#输出为模块led_driver.o,编译器自然会去找led_driver.c来编译
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.o *.moc.o *.mod.c *.sysvers *.order *~
【注意】
"CC = "那里本来想写arm-linux-gcc的完整路径的,省得设置PATH环境变量了,结果反倒提示arm-linux-gcc找不到了。现在觉得原因可能是计算机会按照“PATH中的每一个值 + arm-linux-gcc的完整路径”的方式找gcc,当然找不到。
---------狼犬的随笔---------
今天没有什么可说的,只是想写个LED驱动,本以为只要把之前写的LED的裸机代码改写成init open read write exit形式就行了,没想到运行时没法handle不了那些寄存器地址,报“segmentation fault”。上网一查才知道原来裸机代码操纵设备和驱动程序操纵设备的方式不一样,所以学习驱动程序应该会是一个长期而艰巨的过程了。
【今日提醒】
1.返回非空的函数一定要return一个东西,不能不写return。总不写C连基本语法都记不清了。
2.结构型变量的定义:
struct file_operations fOps =
{
.open = openDevice,
.release = closeDevice
};
定义了一个struct file_operation型的变量fOps,还是基本语法忘了。
3.驱动程序的装载函数和卸载函数最好写成标准形式:
static int __int 函数名(void){...}
static int __exit 函数名(void){...}
否则会报warning“function declaration is not a prototype.”
4.驱动程序的函数和全局变量几乎都是静态的,据说static是给它们加了个在本文件外不可见的属性,防止和其它程序中的变量/函数冲突。不确定,关于静态变量的事以后再研究。