I.Mx6 hello world模块驱动实验及相关问题解决

时间:2022-12-04 09:21:12

1、模块驱动描述

1)模块本身不被编译入内核映像,从而控制了内核的大小

2)模块一旦被加载,它就和内核中的其他部分完全一样

 

2、实验步骤

1) 解压原厂提供的 linux-3.0.35 内核

$ tar xf linux-3.0.35.tar.bz2

2)建立一个专门用于编写驱动模块的目录,该目录不在内核目录中

$ mkdir s-module

3)进入该模块目录进行 hello world 驱动模块的编写

$ cd s-module
$ emacs hello.c &

hello world 驱动模块的内容如下:

#include <linux/init.h>
#include <linux/module.h>

static int __init hello_init(void)
{
    printk(KERN_ALERT "Hello World\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_ALERT "Saya, Hello World !\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("Rex <Rex@fk.com>");
MODULE_DESCRIPTION("hello world driver");
MODULE_LICENSE("GPL");

这个最简单的内核模块只包含内核模块加载函数,卸载函数和对GPL许可权限的声明以及一些描述信息。

4)linux 内核模块程序结构

  •  模块加载函数 (程序中 module_init 中传入的函数)

      当通过insmod或modprobe 命令加载到内核模块时,模块的加载函数会自动被内核执行。

  • 模块卸载函数(程序中 module_exit 中传入的函数)

          当通过rmmod 命令卸载某模块时,模块的卸载函数会自动被内核执行。

  • 模块许可证声明

          许可证(LICENSE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将会收到内核的警告

          信息(kernel tainted)

 

通常来说模块卸载函数要完成与模块加载函数相反的功能,如下示:

  • 若模块加载函数注册了xxx,则模块卸载函数应注销xxx
  • 若模块加载函数动态申请了内在,则模块卸载函数应释放该内存
  • 若模块加载函数申请了硬件资源(DMA,中断,I/O端口,I/O内存)的占用,则模块卸载函数应释放这些硬件资源
  • 若模块加载函数开启了硬件,则卸载函数中一般要关闭

5)模块的编译

通过编写Makefile 由make来完成模块的编译工作,Makefile与hello.c在相同目录下,具体内容如下:

KDIR=/home/xxx/s-linux-3.0.35
PWD:=$(shell pwd)

# kernel modules
obj-m := hello.o

modules:
    make -C $(KDIR) M=$(PWD) modules

clean:
    rm -rf *.o *.ko *.mod.c *.markesr *.order *.symvers

.PHONY:modules clean

6)模块的编译及遇到的问题

直接在s-module 目录下进行 make,出现如下错误提示:

ERROR: Kernel configuration is invalid.
         include/generated/autoconf.h or include/config/auto.conf are missing.
         Run 'make oldconfig && make prepare' on kernel src to fix it.

解决方法:编译生成内核后再编译模块

先进入内核根目录,进行如下操作:

s-linux-3.0.35$ make distclean
s-linux-3.0.35$ make imx6_defconfig
s-linux-3.0.35$ make uImage

然后再进入模块目录,编译模块,如下:

s-module$ make
s-module$ ls
hello.c   hello.mod.c  hello.o   modules.order
hello.ko  hello.mod.o  Makefile  Module.symvers

 

7)注册hello 驱动模块至 I.Mx6 开发板

目前开发板挂载的是 nfs 文件系统,将hello.ko复制到该nfs 系统中的 /root 下

在开发板上执行,有如下提示:

root@freescale ~$ insmod hello.ko 
hello: version magic '3.0.35-2666-gbdde708 SMP preempt mod_unload modversions ARMv7 ' should be '3.0.35-gae4624f-dirty SMP preempt mod_unload modversions ARMv7 p2v8 '
insmod: can't insert 'hello.ko': invalid module format

错误原因:模块驱动的版本信息与内核的版本信息不匹配,开发板加载的内核不是刚刚编译的内核

解决办法:将新编译好的uImage 内核放至tftp根目录下(开发板通过tftp下载内核),开发板执行

root@freescale ~$ reboot

 系统启动之后再执行加载操作:

root@freescale ~$ insmod hello.ko 
Hello World
root@freescale ~$ rmmod hello.ko 
Saya, Hello World !