熟悉 S3C44B0X 开发板的开发流程
一. Bootloader
1. 建立 Cygwin 虚拟 linux 环境
(1) 点击 setup.exe 开始安装
(2) 点击下一步,进入选择安装方法的界面:
图 1 安装界面
图二选择安装途径界面
在这里,如果你的安装文件没有下载到本地,你可以选择从 Internet 安装。我们选择从本地安装,点击下一步继续。
图三选择安装路径等
图四选择 Cygwin 安装程序路径
(3) 选择好 Cygwin 安装程序的路径后点击下一步继续安装。
图五选择安装模块
(4) 选择好自己需要的模块后,点击下一步继续安装
图六选择自己需要的模块安装
图七拷贝文件过程
图 8 结束安装
接下来 Cygwin 会进行自解压过程
图 9Cygwin 自解压过程
图 10 环境变量设置
安装好 Cygwin 后,我们还需要设置一下环境变量。打开系统属性对话框,点击高级 - 56518. 环境变量,打开环境变量设置窗口。
图 11 新建环境变量
点击新建按钮增加一个环境一个用户级的环境变量 PATH=C:/Cygwin/bin ,将 Cygwin/bin 目录加入到用户的 PATH 环境变量中,这样用户可以在任何路径下都可以执行 Cygwin/bin 目录中的命令。
图 12 设置新的环境变量
至此 Cygwin 在 Windows 下安装就已经 OK 了。
2. 安装基于 Cygwin 的 ARM 平台交叉编译器
在Windows下安装好Cygwin后,我们需要建立编译arm程序的环境,也即安装arm-tools工具。
将光盘目录光盘:/工具/编程工具/armtools/windows版本复制到本地硬盘(在这里我们在D:盘建立一个armtools的目录,然后将光盘:/工具/编程工具/armtools/windows版本复制到这里),然后在dos环境下进入此目录,执行unpack.bat批处理命令,解压缩过程开始,不用关心在解压缩的最后出现错误提示。请参看以下截图:
最后添加将armtools的命令路径添加到Windows的环境变量Path中。注意在上一步解压的过程中,armtools被解压到Cygwin的安装目录下,在这里Cygwin是安装在C:/根目录下的。这样armtools交叉编译环境就安装好了。
3. u-boot 简介
U-BOOT是一个开源bootloader,是由德国的工程师WolfgangDenk从8XXROM代码发展而来的,它支持很多处理器,比如PowerPC、ARM、MIPS和x86。目前,U-BOOT源代码在sourceforge网站的社区服务器中,Internet上有一群自由开发人员对其进行维护和开发,它的项目主页是http://sourceforge.net/projects/U-BOOT。U-BOOT的最新版本源代码可以在Sourceforge的CVS服务器中匿名获得。由于其成熟和稳定,已经在许多嵌入式系统开发过程中被采用。
为什么我们需U-BOOT?显然可以将ucLinux直接烧入flash,从而不需要额外的引导装载程序(bootloader)。但是从软件升级的角度以及程序修补的来说,软件的自动更新非常重要。
4. 编译 u-boot
a) 在linux(或其他linux虚拟环境下,如cygwin)解压源码包,在这里我们选择在Windows系统下的Cygwin环境下来编译。先将光盘中的u-boot包拷贝到系统的一个目录下,在这里我们拷贝到D:盘的s3c44b0目录下
tarzxvfu-boot-xxxxxxxx.tar.gz
b) 解压后进入u-boot目录,输入 makedistclean 清除上一次编译的输出文件
C) 输入 makeITSN_s3c44b0_config ,以产生一些编译配置文件(.mk文件)和相应的一些头文件(.h文件)
d) 编译,执行 make 。
这一步骤生成了三个文件,其中:
u-boot,ELF文件格式,使用Flashpgm工具来打开此文件编程到Flash当中
u-boot.bin是二进制文件,使用Fluted工具来将此文件编程到Flash当中
5. U- BOOT 下载
在这里我们介绍两种方法来将编译好的U-Boot编程Flash,一种是使用Flashpgm工具,另外一种是Fluted工具。
a) FlashPgm
FlashPgm是什么公司的,是一个GUI界面的Flash编成工具。由于其友好的编程界面,更快的编程速度和更高的编程成功率使其被大家普遍使用。在使用FlashPgm编程Flash的时候注意使用JTAG板的Wiggler接口连接到目标板上,FlashPgm不支持STD的JTAG接口。打开Configuration菜单下的Communications可以设置设置FlashPgm的连接方式,在这里我使用,同时确保JTAG板的J5条线到Wiggler接口状态。
们
点击菜单File-Open选择.ocd文件。Ooc文件是一个硬件系统的配置文件,设置了CPU,Flash类型,Flash接口的位宽等具体的参数,可通过FlashPgm生成。光盘上已经带有两个已经配置好的.ocd文件,在光盘:/工具/Flash编程工具/目录,其中包含两个.ocd文件。
44B0X_SST.ocd —— 配有SST39VF160Flash的学习板使用
44B0X_AMD.ocd —— 配有AM29LV160Flash的学习板使用
点击FlashID按钮检测一下FlashID能够读取到,以测试JTAG连接是否正常。如果能够正常读取出来,表示JTAG连接没有问题
点击Program按钮,在出现的对话框中选择编译好的u-boot文件(ELF格式的),然后选择在编程前先擦除选型,点击Program。首先将会擦除相应的Flash区域,然后编程和校验。进度条将显示当前编程进度。
正在擦除 Flash
编程,校验成功
这时候超级中断将显示 U-BOOT 打印输出,通过 FlashPgm 成功的将 U-BOOT 烧写到 Flash 当中。
B) Fluted.exe
Fluted.exe是一个基于命令行方式的Flash编程工具,其只支持STD方式的JTAG链接。以下是其运行的参数:
命令:(大小写无关)
R —— 读Flash
W —— 写Flash
E —— 擦除Flash
V —— 校验Flash
T —— 测试扫描线
A —— 擦除+写Flash
选项:(大小写无关)
-V校验(默认是关闭的,也就是说默认不校验)
-DDebug模式(默认关闭)
-C指定配置文件(默认是default.fcd)
-F指定数据文件
-S指定Flash起始地址(十进制方式)
-L指定写入的数据长度(256或者文件的大小,十进制方式)
一般我们使用Fluted.exe的方法如下,
allowio.exeFluted/aA – Fu-boot.bin-V-S0
此命令将u-boot.bin文件(二进制)写入到Flash,从地址0开始,使用默认的default.fcd文件,通常编写将上述命令放在一个.bat批处理文件来方便执行。
Fluted.exe工具编程的速度相对FlashPgm要慢得多,参看下图实际的编程过程。
Fluted.exe 工具编程过程
6. U-BOOT的使用
系统上电后,U-BOOT开始执行,在串口超级终端软件上将有答应输出,在3秒钟内按任意键,将进入U-BOOT命令提示符,如下图。其中输出信息提示SDRAM是8M字节,Flash是2M字节。
执行help指令,将显示U-BOOT支持命令,常用U-BOOT指令有:
命令 |
功能 |
go |
执行指定地址上的程序 |
bootm |
引导应用程序或者操作系统(压缩格式) |
tftp |
通过太网调入指定的文件到指定的内存地址 |
loadb |
通过串口以kermit方式下载文件 |
md |
Memorydisplay,显示指定地址的值 |
mm |
ModifyMemory,修改内存指定地址的值 |
mw |
MemoryWrite,写内存 |
cp |
数据复制,如果目的地址空间在Flash中,就可以通过cp来写Flash |
printenv |
显示环境变量,如IP地址等 |
setenv |
设置环境变量 |
Saveenv |
保存环境变量 |
erase |
擦除指定地址的Flash |
flinfo |
显示Flash的信息 |
reset |
复位CPU |
version |
显示版本信息 |
?/help |
显示帮助信息 |
二. uClinux 编译与下载
1 .建立编译环境
与在 Windows 的 Cygwin 环境下编译 U-BOOT 类似,我们在 linux 下编译运行在 ARM 上的程序同样需要使用交叉编译工具 armtools 。将光盘: / 工具 / 编程工具 /armtools/linux 版本 /arm-elf-tools-20040427.sh 拷贝到硬盘后执行这个程序将会自动安装此 armtools 交叉编译器。
2. 编译 uClinux
将 uClinux 的压缩包拷贝到 linux 主机上,然后通过下列命令解压缩源码包,这样会在当前的目录下面生成 uClinux-dist 目录。(在这里,我们通过通过 SecureCRT 超级终端工具用 ssh 登陆到 Linux 主机的 , 因为在 Cygwin 的虚拟 Linux 环境下不能使用 makemenuconfig 。)
tarzxvfuClinux-dist-xxxxxxxx.tar.gz
进入 uClinux-Distru 目录执行 makemenuconfig ,将弹出以下的配置 uClinux 界面,如下。
选择 Vendor/ProductSelection---> 进入下级菜单,我们的配置如下:
选择 Exit 返回上级界面,然后选择 Kernel/Library/DefaultsSelection---> ,界面如图:在这里我们我们选择了使用的 linux 内核版本 linux-2.4.x , Libc 版本选择 uClibc ,然后选中 CustomizeKernelSettings( 内核配置 ) 和 CustomizeVendor/UserSettings(NEW)( 厂商 / 用户程序设置 ) 进行更进一步的配置。
退出后选择Yes保存配置信息,如下图。
我们在上面配置的时候选择了CustomizeKernelSettings和CustomizeVendor/UserSettings(NEW)选项。所以程序会自动进入KernelSettings和Vendor/UserSettings界面。
注:makemenuconfig将打开上一次的配置选项,如果希望重新构建一个全新的内核,可以在makemenuconfig之前先运行makemrproper。
KernelSettings ,内核配置界面
Vendor/UserSettings界面
这样完成了上面两个配置后,整个uClinux的配置就结束了。接下来编译uClinux。依次执行如下指令:
makedep
makeclean
makelib_only
makeuser_only
makeromfs
makeimage (这一步报错不用管,只要下一步没有错就行)
make
完成所有的操作后,在uClinux-dist/images/目录下将生成uclinux_rom.bin(二进制压缩文件)。接下来我们可以通过U-BOOT配合串口或者网口来将此文件下载到Flash当中。
3. 将 uClinux 下载到 Flash
我们这里通过U-BOOT提供的几种方式来将编译好的uClinux下载到Flash当中运行。
a )串口下载(下载速度慢):
在 U-BOOT 命令提示符下输入 loadb0xC500000 命令 (0xC500000 是下载文件存放的地址, SDRAM 中 ) , U-BOOT 将等待用户传送文件。然后我们启动超级终端的文件发送,点击菜单传送 -> 发送文件,出现发送文件对话框。选择好发送协议为 Kermit 协议,选择发送的文件,然后点击发送。这时候出现发送进度对话框
文件发送完后, uClinux 的压缩的二进制文件就存放在地址 0xC500000 ( SDRAM 空间)上了。
如果我们要测试新编译的 uClinux 运行情况,可以直接输入 bootm 命令,这样 U-BOOT 就会在当前放置下载的程序的地方 ( 这里是 0xC500000) 解压缩代码到指定地址,然后跳转到这个地址开始运行程序
接下来我们通过cp命令将数据从0xC500000写入到Flash中的0x50000开始的地方。在复制数据之前,先将Flash对应的区域删除。拷贝数据的长度是按照双字来操作的,所以我们需要将字节长度/4+1来得到最终要输入的长度参数(16进制)。
数据写入到Flash空间的0x50000后,我们可以重启我们的系统,就可以看到这个启动过程了。U-Boot启动后,3秒钟内如果超级终端没有任何输入,就会自动从Flash0x50000(0x50000这个地址是U-B0OT程序编程固定的,可以根据需要修改)的地址上将压缩的uClinux解压缩到0xc008000(SDRAM)上,然后跳转到这个地址上,开始uClinux的启动。
b) 网口下载(下载速度快):
网口下载是通过tftp协议的,在下载之前先确认一下U-BOOT的环境变量配置是否正确,在U-BOOT的命 令提示符下输入printenv显示环境变量(启动参数),如下图:
其主要的环境参数包括:
bootcmd —— 启动命令,也就是U-Boot启动后如果在指定时间内没有按下任何按键后执行的指令。
bootdelay —— 指定自动启动的等待时间,单位为秒
baudrate —— 串口波特率
etheaddr —— 以太网芯片的MAC地址
stdin —— 指定标准输入设备
stdout —— 指定标准输出设备
stderr —— 指定标准错误输出设备
bootfile —— 通过tftp从服务器上获取的文件名
ipaddr —— 本机(S3C44B0板)的IP地址
serverip —— 运行tftp服务器程序的PC机IP地址
我们在使用tftp下载的时候要关心的参数是bootfile,ipaddr,serverip三个。
需要保证服务器的IP与目标板的IP在同一个网段内。如果需要修改参数可以通过setenv命令修改,例如:
=>setenvipaddr192.168.1.104//设置本级的IP为192.168.1.104
=>setenvserverip192.168.1.100//设置Server的IP为192.168.1.100
=>setenvbootfile “ uclinux_rom.bin ” //设置tftp获取uclinux_rom.bin文件
注意在使用的时候不要使用 “ = ” ,例如setenvipaddr=192.168.1.104是错误。
先将PC机的tftp服务器软件启动,在这里我们使用的CiscoTFTPServer(安装文件在光盘:/工具/FTP软件/tftpserver/TFTPServer1-1-980730.exe)。第一次启动我们需要设置tftp服务器的本地路径,点击view->Options弹出tftp设置窗口,如图6-13所示。在这里我们主要设置tftp的服务器路径(就是包含你需要下载到学习板的文件的目录路径)。单击确定后,tftp服务器就设置好了,这时候我们可以使用U-Boot来下载uclinux到目标板上了。
然后在U-BOOT命令提示符下输入tftp0xC500000命令,下载就开始了。下载完后界面如下:
tftp 下载完界面
同时CiscoTFTPServer也将打印相应的信息,如下图。
后续的操作如同串口下载一样,我们可以通过bootm直接解压缩代码执行,也可以先将Flash擦除,然后通过cp命令将压缩代码写入Flash,这样每次U-BOOT都能够在启动的时候自动解压并运行这个程序。
我们也可以使用光盘:/工具/FTP软件/tftpserver/tftpd32.exe这一个tftp服务器端软件,其使用方法很简单,无需安装,直接启动后设置下载文件的服务器路径(此路径包含了我们需要下载的文件)就好了。下载界面参看下图
三. 应用程序
lo 1 . Helloworld
建立 helloworld 应用程序步骤如下:
在 uClinux-dist/user 目录下新建目录: Myapp
1 . 1 编写 Helloworld 程序
编写 demo.c 文件,代码如下:
#include<stdlib.h>
#include<stdio.h>
intmain(void)
{
printf( “ HelloWorld!Thisismyfirstapplication./n ” );
return0;
}
保存在 Myapp 目录下。
1 . 2 编写 Makefile 文件
内容如下:
EXEC=demo
OBJS=demo.o
all:$(EXEC)
$(EXEC):$(OBJS)
$(CC)$(LDFLAGS)-o$@$(OBJS)$(LDLIBS)
romfs:
$(ROMFSINST)/bin/$(EXEC)
clean:
-rm-f$(EXEC)*.elf*.gdb*.o
同样放在 Myapp 目录下。
1 . 3 修改 user/Makefile
为了让编译器编译上述添加的内容,在 user/Makefile 中添加一句(一般按照字母
排列):
dir_$(CONFIG_USER_MYAPP_DEMO)+=Myapp
1 . 4 修改 config/config.in
config/config.in 文件中添加的内容会在对用户选项进行配置时反映出来。在文件
的最后,增加一条:
###################################################################
mainmenu_optionnext_comment
comment'MyNewApplication'
bool'demo'CONFIG_USER_MYAPP_DEMO
endmenu
###################################################################
输入 makemenuconfig
选择
然后 exit 保存,自动进入下一个画面
选择 Myapplication 回车,出现
选中,然后退出,保存。
接着执行:
makedep
makeclean
makelib_only
makeuser_only
makeromfs
makeimage
make
下载到开发板,可以通过串口终端在 teraterm 看到 bin 下面多了一个 demo 程序。
输入 ./demo 启动演示程序
输出: HelloWorld!Thisismyfirstapplication.
四. 驱动程序的编写
一个简单的驱动程序
一个典型的驱动程序 , 大体上可以分为以下两个方面 :
1) 注册设备 : 在系统初启时 , 必须将设备登记到相应的设备数组 , 例如 : 对于字符驱动设备来说 , 要使用 register-chrdev() 来注册设备的驱动号 , 然后对这个设备的所有调用都用这个设备号来实现 ;
2) 定义功能函数 : 对于每一个驱动函数来说 , 都有一些和此设备密切相关的功能函数 , 就最常用的字符设备来说 , 都存在着诸如 open() 、 read() 、 write() 、 ioctrol() 这一类的操作。当系统调用这些操作时 , 将自动的使用 file-operations 结构中对应的函数来实现具体的操作 ; 在编写驱动程序前 , 不得不提 file-operations 这个结构 , 每个设备都有自己的 file-operations 结构 , 它定义了设备的基本入口
点 , 即上面提到的功能函数。下面以一个简单的演示例子 , 说明编写字符设备驱动程序的具体过程 , 设备取名为“ test ” , 设备号定为 254, 当然这个设备并没有涉及真正的硬件 , 仅是从内核空间拷贝了一些特定数据到用户空间。
第一步 : 在目录 /linux-2 . 4 .x /drives/char 编写源
程序 test.c, 源码如下 :
头文件和全局变量 :
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/mm.h>
#include<linux/errno.h>
#include<asm/uaccess.h>
inttest_major=254;
// 读函数 , 仅向用户缓冲区填入数据 1
staticssize_tread_test(structfile*file,char*buf,ssize_tcount,loff_t*f_pos)
{
intleft,ret;
chardata=0x41;
for(left=count;left>0;left--)
{
put_user(data,buf);buf++;}
returncount;
}
// 写函数 , 空操作
staticssize_twrite_test(structfile*file,char*buf,ssize_tcount,loff_t*f_pos)
{returncount;
}
// 打开函数
staticintopen_test(structinode*inode,structfile*file)
{
MOD_INC_USE_COUNT;return0;}
// 释放函数
staticvoidrelease_test(structinode*inode,structfile*file)
{
MOD_DEC_USE_COUNT;}
structfile_operationstest_fops={
read:read_test,
write:write_test,
open:open_test,
release:release_test,
};
// 注册函数
inttest_init(void)
{
intresult;
result=register_chrdev(254,"test",&test_fops);
if(result<0){printk("test:cannotgetmajornumber!/n");
returnresult;}
return0;
}
// 撤消函数
voidcleanup_module(void)
{unregister_chrdev(test_major,"test");}
第二步 : 添加设备 ;
1) 修改 l in ux-2 . 4.x/driver/char/Makefile 在适当位置添加一行 :obj - $ (CONFIG - TEST)+=test.o
2)linux-2 1 4.x/driver/char/Config.in, 添加一行 :bool ’ testdevice ’ CONFIG - TEST
3) 修改 linux-2 1 4.x/driver/char/mem.c 在适当位置添加 :
#ifdefCONFIG - TEST
externvoidtest - init(void);
#endif
同时在 chr - dev - init() 函数中添加 :
#ifdefCONFIG - TEST
test - init();
#endif
4) 修改 vendor/Samsung/44bb0/Makefile 建立设备节点 :
在 12---35 行间 ,DEVICE 部分添加如下内容 test,c,254,0
5)makemenuconfig, 在 characterdevice 选中 testdevice
重新编译内核 , 在控制台输入
/proc>catdevices
Characterdevices:
1mem
2pty
3ttyp
4ttyS
5cua
10misc
162raw
180usb
254test
Blockdevices:
1ramdisk
31Blkmem
/proc>
就包含了名为“ test ”的设备驱动 , 下面的例子是用于验证这个设备驱动程序 .
B. 应用程序的编写
在μ CLinux 的 /user 目录下提供许多资源供开发者参考。下面以上节提到的源程序为例 , 说明在μ CLinux 中加入自己应用程序的过程。第一步 : 首先在 /user/ 目录下建立自己的文件夹如 , 取名 apptest, 然后在新建文件夹 (apptest) 下编辑自己的应用程序 apptest.c( 源码为上面的设备驱动验证程序 ), 然后参照 user 目录下其他应用程序编写自己的 makefile, 同样保存
在文件 apptest 下 ;
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
main()
{
intfd,i,j;
charbuf[10];
fd=open("/dev/test",O_RDWR);
if(fd<0)
{
printf("cannotopenfile/n");
exit(0);
}
j=read(fd,buf,10);
for(i=0;i<j;i++)
printf("%d/n",buf[i]);
close(fd);
}
第二步 : 在 /user/Makefile 中适当位置加入下行语句 :
dir - $ (CONFIG - USER - APPTEST)+=apptest
第三步 : 在 /config/Configure.help 的适当位置添加以下语句 :
CONFIG - USER - APPTEST
ThisprogramdoesAPPTESTthingstoyourbars.
第四步 : 在 /config/config.in 的适当位置添加以下语句 :
bool ’ apptest ’ CONFIG - USER - APPTEST
最后再重新编译内核 , 在 makemenuconfig 时 , 选中自己的应用程序 , 完成后在 /
bin 目录可以看见 ap2ptest 的可执行文件 , 通过控制台直接输入该文件名即可
运行该程序 ! 当然也可以在文件 vendor/Samsung/44B0/rc 中添加文件名
apptest, 重新编译 , 在 uclinux 启动后自动执行该应用程序 .
字符设备的另一种做法
(这个设备驱动程序是让蜂鸣器叫)
这里不采用前面提到的 file 结构中的 readwrite 等,而使用 IOCTL 来实现。
首先修改前面给出的 test.c ,添加 Port_init 函数,这个函数用来初始化 I/O 配置寄存器。然
后就是修改
structfile_operationstest_fops={
ioctl:ledman_ioctl,/*ledman_ioctl*/
};
去除原先的内部结构,最后定义 ledman_ioctl 函数。整个驱动程序的结构如下,
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/types.h>
#include<linux/fs.h>
#include<linux/mm.h>
#include<linux/errno.h>
#include<asm/uaccess.h>
#include<asm/arch/s3c44b0x.h>
inttest_major=254;
#defineNon_Cache_Start(0x2000000)
#defineNon_Cache_End(0xc000000)
#defineBEEP_CMD_SIGNAL0
/*************************PORTS****************************/
staticintledman_ioctl(structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg);
voidPort_Init(void)
{
(*(volatileunsigned*)S3C44B0X_PCONA)=0x1ff;
(*(volatileunsigned*)S3C44B0X_PDATB)=0x3ff;
(*(volatileunsigned*)S3C44B0X_PCONB)=0x3ff;
(*(volatileunsigned*)S3C44B0X_PDATC)=0xffff;//AllI/OIsHigh
(*(volatileunsigned*)S3C44B0X_PCONC)=0x0f05ff55;
(*(volatileunsigned*)S3C44B0X_PUPC)=0x30f0;//PULLUPRESISTORshouldbeenabledtoI/O
(*(volatileunsigned*)S3C44B0X_PDATD)=0xff;
(*(volatileunsigned*)S3C44B0X_PCOND)=0x0;
(*(volatileunsigned*)S3C44B0X_PUPD)=0x0;
(*(volatileunsigned*)S3C44B0X_PDATE)=0x1ff;
(*(volatileunsigned*)S3C44B0X_PCONE)=0x25568;
(*(volatileunsigned*)S3C44B0X_PUPE)=0x0df;pull-upresistor.
(*(volatileunsigned*)S3C44B0X_PDATF)=0x1ff;//AllI/OIsHigh
(*(volatileunsigned*)S3C44B0X_PCONF)=0x20900a;//AllNCisINPUT
(*(volatileunsigned*)S3C44B0X_PUPF)=0x163;
(*(volatileunsigned*)S3C44B0X_PDATG)=0xff;
(*(volatileunsigned*)S3C44B0X_PCONG)=0x00ff;
(*(volatileunsigned*)S3C44B0X_PUPG)=0x0;//shouldbeenabled
(*(volatileunsigned*)S3C44B0X_SPUCR)=0x7;//D15-D0pull-updisable
(*(volatileunsigned*)S3C44B0X_EXTINT)=0x0;//AllEXTINT0-7Lowlevelinterrupt
(*(volatileunsigned*) S3C44B0X_NCACHBE0)=0;//((Non_Cache_End>>12)<<16)|(Non_Cache_Start>>12);
}
voidBeep(intBeepStatus)
{
//PE5Lowavailable
if(BeepStatus==0)
(*(volatileunsigned*)S3C44B0X_PDATE)=(*(volatileunsigned*)S3C44B0X_PDATE)&0x1df;
else
(*(volatileunsigned*)S3C44B0X_PDATE)=(*(volatileunsigned*)S3C44B0X_PDATE)|0x020;
}
staticint ledman_ioctl(
structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)
{
inti;
if(cmd==BEEP_CMD_SIGNAL){
printk("beep0/n");
Beep(0);
return(0);
}
e lse
{
printk("beep1/n");
Beep(1);
}
return0;
}
structfile_operationstest_fops={
ioctl:ledman_ioctl,/*ledman_ioctl*/
};
inttest_init(void)
{
intresult;
result=register_chrdev(254,"test",&test_fops);
if(result<0){printk("test:cannotgetmajornumber!/n");
returnresult;}
return0;
}
voidcleanup_module(void)
{unregister_chrdev(test_major,"test");}
其余文件不要动,将 test.c 存盘到 44b0 当前目录下的 /linux-xxx/driver/char 然后在 44b0 目
录下面 Make 进行编译。
接着修改应用程序 apptest ,这个比较简单,程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
main()
{
intfd,i,j;
charbuf[10];
fd=open("/dev/test",O_RDWR);
if(fd<0){printf("cannotopenfile/n");
exit(0);
}
ioctl(fd,1,0);// 第 2 个参数 1 表示喇叭叫 ,0 表示不叫
close(fd);
}
其中把原先的 read,write 等调用改为 IOCTL 函数调用。
存盘后,执行 makeuser_only 进行编译。