嵌入式实验报告(linux实验)

2019-07-12 14:43发布

1 LED 灯驱动程序1.1 “文件”的实现
设备驱动作为操作系统的一部分,是操作系统对设备进行操作的接口。操作系统规定了设备驱动需要实现的接口,而我们在裸机实验中也用到了控制设备所用到的接口。为了实现我们嵌入式实验箱的linux 驱动程序,我们需要将这
两个接口好好的“对接”一下。
参考ours_led.c 文件,我们做如下分析:
首先,我们定义设备的i 节点名称, 这样我们就能在我们的文件系统中找到我们的设备。
其次,在驱动程序加载一个设备之前,首先要做的就是获取设备编号。设备号包括主设备号和次设备号两部分, 前者表示一个特定的驱动程序, 后者表示使用该驱动程序的各设备。类似C 语言裸机实验,我们还需要定义我们的端口号。



之后我们就要来实现操作系统规定的对“文件”操作的方法了。首先我们先把表填上:

这里定义了三个属性:所有者、打开方式、释放方式、控制方式。这三种方式就是我们写测试文件时需要用到的控制设备的函数。我们先看一下led_open 函数




led_open 函数调用了init 函数和led_all_off 函数。init 函数与我们的C 语言裸机实验对LED 灯初始化的步骤相同。led_all_off 也是利用开发包为我们提供的接口将所有的灯关闭。
再看一下led_release 函数:

这和我们C 语言裸机实验的步骤完全一样了。再看一下led_unlocked_ioctl 函数:

第一个参数是i 节点,第二个参数是命令,对LED 灯来说有两种命令:开和关,第三个参数指定对哪一个灯操作。当然,cmd 和arg 的值反过来写也没什么问题,不过是不太符合逻辑。至此,我们的文件系统中就有了这么一个“文件”。

1.2 驱动引导我们的文件系统中终于有了这么一个“文件”,但这个文件和一般的文件不同,因为它是驱动程序,它需要在我们“打开文件”之前就要和设备建立联系,做一系列的初始化工作,当然这主要是操作系统层面的。
linux 同样提供了这样一个接口:

参数为两个函数指针。这两个函数将函数指针存放在一个段中,当linux 系统启动时调用do_basic_steup 函数,遍历这个段执行每一个初始化函数。(当然这是将驱动加载进内核的方法)
我们来看一下led_init 函数:




这是这个驱动文件里面最长的一个函数了。之前我们定义设备号为0, 意味着要动态申请设备号。之后将设备号添加到设备表中,并创建设备文件目录。而我们在关机时,会执行led_exit 函数:

这里会在文件系统中删除这个i 节点。原因很简单,因为操作系统下次开机时不知道还有没有这个设备,就像U 盘一样,这次开机有了不代表下次开机U 盘还会插在上面。为了防止访问出错,所以销毁i 节点。
1.3 编译驱动随后,我们创建Makefile 文件,将需要编译的文件添加进去,再在上层Makefile 文件中添加依赖关系。
首先我们将编译后的文件放进去:
再在上层目录ours/文件夹下的Makefile 中添加CONFIG_OURS_LED 的依赖:

在编译时,drivers 文件夹下的Makefile 会检查ours 文件夹下所有的依赖,保证drivers 生成的编译结果的时间戳比ours 文件夹下所有的编译结果都更新。这样我们就将驱动加载了进去。
为了更方便的管理加载哪些模块,我们还需要实现Kconfig,用来在menuconfig中方便选择。在ours_led 文件夹下,创建Kconfig 文件:

在上层Kconfig 文件中添加上我们的源文件:
这样,我们在顶层的终端下执行make menuconfig,就可以方便的选择哪些模块加载进内核了。

2 测试
在写测试文件时,我们需要打开设备所在的“文件”,利用操作系统提供的接口进行操作。在这里,操作系统的意义就体现了出来:对每一种设备的操作,都是那几种函数,方便了编程人员的开发。以下是我写的跑马灯测试程序:

核心是在while(1) 循环中将灯开、灭。
至此,作业三完成。