熟悉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服务器端软件,其使用方法很简单,无需安装,直接启动后设置下载文件的服务器路径(此路径包含了我们需要下载的文件)就好了。下载界面参看下图
三.应用程序
lo1.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)修改linux-2.4.x/driver/char/Makefile在适当位置添加一行:obj-$(CONFIG-TEST)+=test.o
2)linux-214.x/driver/char/Config.in,添加一行:bool’testdevice’CONFIG-TEST
3)修改linux-214.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;
}
staticintledman_ioctl(
structinode*inode,structfile*file,unsignedintcmd,unsignedlongarg)
{
inti;
if(cmd==BEEP_CMD_SIGNAL){
printk("beep0/n");
Beep(0);
return(0);
}
else
{
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进行编译。