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

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 <[email protected]>");
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 下

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

[email protected] ~$ 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下载内核),开发板执行

[email protected] ~$ reboot

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

[email protected] ~$ insmod hello.ko
Hello World
[email protected] ~$ rmmod hello.ko
Saya, Hello World !
时间: 2024-10-08 03:50:40

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

如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)

六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上) 八.LCD1602点阵字符型液晶显示模块驱动封装(中) 已经有好一阵子没写了,一方面是因为最近闲杂的事特多,另一方面(主要方面)是因为我卡在了LCD1602驱动的权衡上面——总共3个控制线和一个8位并行的数据线,放在51

第四十二天:Tiny4412模块驱动开发

因为前面写裸板程序的时候,已经详细的叙述过LED灯的控制,按键的控制,以及watchdog的配置,这里就不赘述了,主要是说明模块如何控制底层硬件的. 第一个程序是模块程序控制LED灯全亮. 因为友善之臂将LED灯的驱动默认加载到内核中,编写模块驱动程序前就要先把原先的LED灯驱动裁剪掉. 首先进入linux源码目录.执行 make menuconfig 进入Device Drivers  ---> Character devices  ---> 将LED Support for Friendl

3.2Linux的模块驱动

Linux的模块驱动 ? 接下来写个最简单的驱动程序,就像程序语言的hello world程序. 首先是:hello.c的代码: 这是个最简单的驱动程序.就是打印hello的信息.驱动程序和我们的程序语言结果有点不大一样.驱动模块的入口是倒数第二行的module_init()的函数.驱动模块的出口是module_exit()的函数. 3.接着是makfile文件: 这也是一个很简单的Makefile文件了.Obj-m后面跟的是我们的最终目标依赖的文件hello.o.第三行的KDIR是我们编译进的

(三)内存 SDRAM 驱动实验

SDRAM 芯片讲解: 地址: 行地址 (A0-A12) 列地址 (A0-A8)    片选信号(BA0 BA1)(L-BANK)(因为SDRAM有 4片) 两片SDRAM 连线唯一区别在 UDQM LDQM DQM0 ---片1 LDQM DQM1----片1 UDQM DQM2----片2  LDQM DQM3---片2   UDQM ———————————————————————————————————————————————————————————— 1.读操作(见杨铸 121) 地址线

ecos stm32 步步深入8 - 手工打造串口usart2驱动实验ecos中断

最近忙别的事情,很长时间没碰ecos了,这两天有点空,抽空写个串口驱动玩玩,也验证一下ecos的中断调用.LZ花了两天时间写好这个驱动,中间遇到了几个比较恶心的问题,后来发现是前面的基础没打好,所幸都解决了. 尽管ECOS已经写好了串口的驱动程序,只需要在配置工具中使能即可.不过别人写的毕竟不是自己的,还是自己写的用的方便,这次试验的主要目的是为了调试ecos的中断服务,让串口中断能收发数据. 首先遇到的最大的问题,事实上跟什么串口都没关系,就是debug时一执行task delay,调试程序就

linux模块驱动之led(ioremap)

一:led内核驱动 (1)在编写led内核驱动时,我们首先要进行内核裁剪,因为友善之臂将LED灯的驱动默认加载到内核中,所以编写模块驱动程序前就要先把原先的LED灯驱动裁剪掉: led驱动在源码里面的Device Drivers /Character devices目录下,进行完裁剪之后重新编译linux源码: (2)ioremap() define ioremap(cookie,size)        __arm_ioremap((cookie), (size), MT_DEVICE) 编写

linux驱动开发-模块驱动

linux内核是可以高度定制的,通过配置编译选项达到定制的目的. 在配置kernel编译选项时驱动程序的编译选项一般有三种,不编译.编译为内核驱动.编译为模块驱动.所以linux驱动一般分为两类,内核驱动和模块驱动,当然这两者之间并无绝对区别:当编译为内核驱动时,驱动程序将会随内核一起运行,就相当于内核的固有部分一样:当编译为模块驱动时,每个驱动程序都是独立的个体,在需要的时候安装,用完了再卸载,可以节约硬件资源.以下内容描述的是模块驱动的开发过程. 1.获取内核源码,按照目标器件(PC机或者开

电信NB-LOT模块驱动说明

@font-face{ font-family:"Times New Roman"; } @font-face{ font-family:"宋体"; } @font-face{ font-family:"Arial"; } @font-face{ font-family:"黑体"; } @list l0:level1{ mso-level-number-format:decimal; mso-level-suffix:tab;

驱动代码内部相关关键字等

1.     LPVOID -指针 一个没有类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量(一般作为参数传递),然后在使用的时候再转换回来.可以将其理解为long型的指针,指向void型,没有函数返回值. 2.     PDWORD -短指针(LPDWORD也基本一样.) windef.h中定义的数据类型,原文如下: typedef DWORD near *PDWORD; 表示指向DWORD的短指针类型,是WINDOWS编程中常用的数据类型之一. 3.BOOL和bool