基于ARM体系结构的嵌入式开发(一)-移植第一个驱动程序

基于ARM体系结构的嵌入式开发(1)-----移植第一个驱动程序

本文是基于s3c2440,arm9内核的linux开发

一.选用arm开发板;S3C2440  (天嵌的那款)

买来的板子已经移植好uboot,linux内核。所以先用secureCRT链接开发板,然后执行命令 uname -a

Linux EmbedSky 2.6.30.4-EmbedSky

二.PC机装上linux操作系统

1)安装虚拟机:vmware

2)安装操作系统:fedore 14(界面非常友好)

这两个软件下载都很容易的

3)下载linux内核 (版本要与arm上移植的相同)    内核下载

4)将内核压缩文件复制到fedore14 操作系统,在终端输入命令:

tar xjvf  linux-2.6.30.4_20100531.tar.bz2  -C/linux-2.6.30

-C表示解压后的目标文件夹

三.熟悉linux界面

1.熟悉linux的常用命令

上面  tar xjvf  linux-2.6.30.4_20100531.tar.bz2  -C/linux-2.6.30 就是解压文件

linux 命令格式为 命令+[选项的方式]


了解vi编辑器,这是linux系统下的一种常用的文本编辑方式

详细的命令及vi的介绍见基于ARM体系结构的嵌入式开发(一)-移植第一个驱动程序  linux命令详解

2.了解shell                                                               

这个可以暂时不看,有兴趣的同学可以参考   shell参考资料

3.gcc编译器

和学习其他语言,使用编译器是一样的道理,将高级语言编译为硬件能明白的语言。

这里值得一提的是交叉编译器,采用的是ARM-LINUX-gcc   。因为arm板或者说其他嵌入式平台,其本身资源很少,没有足够的资源去运行编译开发工具,调试工具。所以我们要在本机上编译,然后移植到嵌入式平台中执行

。有关ARM-linux-gcc版本和linux内核版本问题将在下文提到


eg.现在终端输入vi  test-1.c ,进入vi编辑器

#include<stdio.h>

void main()

{

printf(“hello,world!”);

}

esc  :wq 保存退出

然后在终端下执行gcc  test_1.c -o  test_1 

然后执行  ./test-1  即可打印出hello,world!

4.关于smb(window与linux之间的通信) nfs(linux与linux之间的通信) 网上资料很多,就不提了。对于本实验,也用不到上述服务

具体可参考这篇     配置smb和nfs


四.移植第一个驱动程序

基于ARM体系结构的嵌入式开发(一)-移植第一个驱动程序

这是嵌入式开发的基本架构,右侧只是举了个例子。

linux的驱动开发有两种方法:1.直接编译到内核,再运行新的内核来测试

2.编译模块的方式,单独加载进行调试

1)由于是第一个驱动程序,所以首先必须要编译内核。

编译内核:终端下进入linux内核目录  ,

#make menuconfig 进入 load an alternate configuration file

输入 arch/arm/configs/s3c2440_defconfig 

ok

在system type 选单中s3c24**中只选中smdk2410/a9m2410,smdk2440, smdk2440 with s3c2440 cpu mode

保存配置文件为.config

终端下输入#make zImage   (如果要移植内核到开发板,可以以JTAG方式将生成的zimage移植到开发板上)

2)移植驱动程序

将厂家提供的模块EmbedSky_gpio.c复制到内核目录的drivers/char 目录

1、修改同目录下的Kconfig

添加下面代码 [此选项将会在内核配置界面显示]

config TQ2440_GPIO_TEST
tristate "EmbedSky SKY2440/TQ2440 Board GPIO Test(control LED)"
depends on ARCH_S3C2440
default y if ARCH_S3C2440
help
 GPIO control for EmbedSky SKY2440/TQ2440 Board.

2、修改同目录下的Makefile

obj-$(CONFIG_TQ2440_GPIO_TEST)+= EmbedSky_gpio.o

3、配置内核 DEVICE drivers -character devices 选中

4、终端输入

#make SUBDIR=drivers/char modules

或者另外为EmbedSky_gpio.c建一个文件,编写相应的Makefile

obj-m   :=EmbedSky_gpio.o
KERNELDIR := /linux-2.6.30/linux-2.6.30.4/   #指向内核目录
PWD := $(shell pwd)
all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules


clean:
        rm -rf *.o *.ko *.mod.* *.symvers
.PHONY: all clean

make.生成.ko文件

5.insmod 加载到内核模块

这时出现个错误

insmod: errorinserting 'EmbedSky_gpio.ko': -1 Invalid module format

查看日志 #cat   /var/log/messages |tail

显示

Nov  8 19:11:06 localhost smbd[5242]: [2012/11/0819:11:06.786765,  0]printing/print_cups.c:109(cups_connect)

Nov  8 19:11:06 localhost smbd[5242]:   Unable to connect to CUPS serverlocalhost:631 - Connection refused

Nov  8 19:11:06 localhost smbd[1790]: [2012/11/0819:11:06.787232,  0]printing/print_cups.c:468(cups_async_callback)

Nov  8 19:11:06 localhost smbd[1790]:   failed to retrieve printer list:NT_STATUS_UNSUCCESSFUL

都是smb什么的。这应该和smb没什么关系啊

根据意思,是模块不匹配

网上百度了一下,发现犯这个错误的人真是不少,找了些文章看了下,发现都是说要加载的模块指定的内核版本与当前的内核版本不一致。需要修改成一致。

这里要说明下有关版本的问题:

首先得明确你是要基于什么开发的,PC 机的linux下,还是嵌入式平台。我之前已经说过,我是基于arm体系结构,我arm上移植了linux操作系统,我现在要基于ARM上的linux操作系统开发,我只是在PC机的linux系统下开发而已。所以我要加载的模块指定的内核版本和我linux系统版本没多大关系,也不需要匹配的。所以网友提高的错误应该不是我的错误。我将.ko文件复制,用U盘挂载到arm上。执行insmod 命令时提示错误

version magic '2.6.30.4 mod_unload ARMv4 ' should be '2.6.30.4-EmbedSky mod_unload ARMv4 

为什么linux内核版本都是2.6.30 ,还是提示有错误呢。后来想到我这是天嵌的平台,可能有别于其他平台。

所以重新配置内核,在Local version 中加入 -EmbedSky  退出保存为.config 然后重新编译内核。编译模块,重新加载,最后解决了问题。