熟悉S3C44B0X开发板的开发流程

熟悉S3C44B0X开发板的开发流程

一.Bootloader

1.建立Cygwin虚拟linux环境

(1)点击setup.exe开始安装 

(2)点击下一步,进入选择安装方法的界面:

安装界面

图二 选择安装途径界面

在这里,如果你的安装文件没有下载到本地,你可以选择从Internet安装。我们选择从本地安装,点击下一步继续。

图三 选择安装路径等

图四 选择Cygwin安装程序路径

(3)选择好Cygwin安装程序的路径后点击下一步继续安装。

图五 选择安装模块

(4)选择好自己需要的模块后,点击下一步继续安装 

图六 选择自己需要的模块安装

图七 拷贝文件过程 

结束安装

接下来Cygwin会进行自解压过程

9 Cygwin自解压过程

10 环境变量设置

安装好Cygwin后,我们还需要设置一下环境变量。打开系统属性对话框,点击高级-56518 .环境变量,打开环境变量设置窗口。

11 新建环境变量

点击新建按钮增加一个环境一个用户级的环境变量 PATH=C:/Cygwin/bin,将Cygwin/bin目录加入到用户的PATH环境变量中,这样用户可以在任何路径下都可以执行Cygwin/bin目录中的命令。

12设置新的环境变量

至此CygwinWindows下安装就已经OK了。

2.安装基于CygwinARM平台交叉编译器

在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,是由德国的工程师Wolfgang Denk从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目录下 

tar zxvf u-boot-xxxxxxxx.tar.gz 

 

b)解压后进入u-boot目录,输入make distclean清除上一次编译的输出文件 

C)输入 make ITSN_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 —— 配有SST39VF160 Flash的学习板使用 

44B0X_AMD.ocd —— 配有AM29LV160 Flash的学习板使用 

点击Flash ID按钮检测一下Flash ID能够读取到,以测试JTAG连接是否正常。如果能够正常读取出来,表示JTAG连接没有问题

点击Program按钮,在出现的对话框中选择编译好的u-boot文件(ELF格式的),然后选择在编程前先擦除选型,点击Program。首先将会擦除相应的Flash区域,然后编程和校验。进度条将显示当前编程进度。

正在擦除Flash

编程,校验成功

这时候超级中断将显示U-BOOT打印输出,通过FlashPgm成功的将U-BOOT烧写到 Flash当中。

B)Fluted.exe 

Fluted.exe是一个基于命令行方式的Flash编程工具,其只支持STD方式的JTAG链接。 以下是其运行的参数: 

命令:(大小写无关) 

—— 读Flash 

—— 写Flash 

—— 擦除Flash 

—— 校验Flash 

—— 测试扫描线 

—— 擦除 + 写 Flash 

选项: (大小写无关) 

-V 校验(默认是关闭的,也就是说默认不校验) 

-D Debug模式 (默认关闭) 

-C 指定配置文件 (默认是default.fcd) 

-F 指定数据文件 

-S 指定Flash起始地址(十进制方式) 

-L 指定写入的数据长度 (256或者文件的大小,十进制方式) 

一般我们使用Fluted.exe的方法如下, 

allowio.exe Fluted /a A F u-boot.bin -V -S 0 

此命令将 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 

Memory display,显示指定地址的值 

mm 

Modify Memory,修改内存指定地址的值 

mw 

Memory Write,写内存 

cp 

数据复制,如果目的地址空间在Flash中,就可以通过cp来写Flash 

printenv 

显示环境变量,如IP地址等 

setenv 

设置环境变量 

Saveenv 

保存环境变量 

erase 

擦除指定地址的Flash 

flinfo 

显示Flash的信息 

reset 

复位CPU 

version 

显示版本信息 

?/ help 

显示帮助信息 

二.uClinux编译与下载

1.建立编译环境

与在WindowsCygwin环境下编译U-BOOT类似,我们在linux下编译运行在ARM上的程序同样需要使用交叉编译工具armtools。将光盘:/工具/编程工具/armtools/linux版本/ arm-elf-tools-20040427.sh拷贝到硬盘后执行这个程序将会自动安装此armtools交叉编译器。

2. 编译 uClinux

uClinux的压缩包拷贝到linux主机上,然后通过下列命令解压缩源码包,这样会在当前的目录下面生成uClinux-dist 目录。(在这里,我们通过通过SecureCRT超级终端工具用 ssh 登陆到 Linux 主机的因为在Cygwin的虚拟Linux环境下不能使用make menuconfig。)

tar zxvf uClinux-dist-xxxxxxxx.tar.gz

进入uClinux-Distru目录执行 make menuconfig,将弹出以下的配置uClinux界面,如下。

选择Vendor/Product Selection ---> 进入下级菜单,我们的配置如下:

选择Exit返回上级界面,然后选择Kernel/Library/Defaults Selection --->,界面如图:在这里我们我们选择了使用的linux内核版本 linux-2.4.xLibc 版本选择 uClibc,然后选中Customize Kernel Settings(内核配置Customize Vendor/User Settings (NEW)(厂商/用户程序设置)进行更进一步的配置。

退出后选择Yes保存配置信息,如下图。

 

我们在上面配置的时候选择了Customize Kernel Settings和Customize Vendor/User Settings (NEW)选项。所以程序会自动进入Kernel Settings 和 Vendor/User Settings界面。 

注:make menuconfig将打开上一次的配置选项,如果希望重新构建一个全新的内核,可以在make menuconfig之前先运行 make mrproper。 

Kernel Settings ,内核配置界面

Vendor/User Settings界面 

这样完成了上面两个配置后,整个uClinux的配置就结束了。接下来编译uClinux。依次执行如下指令: 

make dep 

make clean 

make lib_only 

make user_only 

make romfs 

make image (这一步报错不用管,只要下一步没有错就行)

make 

完成所有的操作后,在uClinux-dist/images/目录下将生成uclinux_rom.bin(二进制压缩文件)。接下来我们可以通过U-BOOT配合串口或者网口来将此文件下载到Flash当中。 

3. uClinux下载到Flash 

我们这里通过U-BOOT提供的几种方式来将编译好的uClinux下载到Flash当中运行。 

a)串口下载(下载速度慢):

U-BOOT命令提示符下输入 loadb 0xC500000命令(0xC500000是下载文件存放的地址,SDRAM)U-BOOT将等待用户传送文件。然后我们启动超级终端的文件发送,点击菜单 传送->发送文件,出现发送文件对话框。选择好发送协议为 Kermit协议,选择发送的文件,然后点击发送。这时候出现发送进度对话框

文件发送完后,uClinux的压缩的二进制文件就存放在地址0xC500000SDRAM空间)上了。

如果我们要测试新编译的uClinux运行情况,可以直接输入 bootm 命令,这样U-BOOT就会在当前放置下载的程序的地方(这里是0xC500000)解压缩代码到指定地址,然后跳转到这个地址开始运行程序

接下来我们通过cp命令将数据从0xC500000写入到Flash 中的0x50000开始的地方。在复制数据之前,先将Flash对应的区域删除。拷贝数据的长度是按照双字来操作的,所以我们需要将字节长度/4 + 1 来得到最终要输入的长度参数(16进制)。 

数据写入到Flash空间的0x50000后,我们可以重启我们的系统,就可以看到这个启动过程了。U-Boot启动后,3秒钟内如果超级终端没有任何输入,就会自动从Flash 0x50000(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命令修改,例如: 

=>setenv ipaddr 192.168.1.104 //设置本级的IP为192.168.1.104 

=>setenv serverip 192.168.1.100 //设置Server的IP为192.168.1.100 

=>setenv bootfile uclinux_rom.bin//设置tftp获取uclinux_rom.bin文件 

注意在使用的时候不要使用=,例如 setenv ipaddr=192.168.1.104是错误。 

先将PC机的tftp服务器软件启动,在这里我们使用的Cisco TFTP Server(安装文件在 光盘:/工具/FTP软件/tftp server/TFTPServer1-1-980730.exe)。第一次启动我们需要设置tftp服务器的本地路径,点击 view->Options弹出tftp设置窗口,如图6-13所示。在这里我们主要设置tftp的服务器路径(就是包含你需要下载到学习板的文件的目录路径)。单击确定后,tftp服务器就设置好了,这时候我们可以使用U-Boot来下载uclinux到目标板上了。 

然后在U-BOOT命令提示符下输入tftp 0xC500000 命令,下载就开始了。下载完后界面如下: 

tftp下载完界面

同时Cisco TFTP Server 也将打印相应的信息,如下图。 

后续的操作如同串口下载一样,我们可以通过bootm 直接解压缩代码执行,也可以先将Flash擦除,然后通过cp命令将压缩代码写入Flash,这样每次U-BOOT都能够在启动的时候自动解压并运行这个程序。 

我们也可以使用 光盘:/工具/FTP软件/tftp server/tftpd32.exe 这一个tftp服务器端软件,其使用方法很简单,无需安装,直接启动后设置下载文件的服务器路径(此路径包含了我们需要下载的文件)就好了。下载界面参看下图 

三.应用程序

lo1. Helloworld

建立 helloworld 应用程序步骤如下:

在 uClinux-dist/user 目录下新建目录:Myapp

1编写Helloworld 程序

编写 demo.c 文件,代码如下:

#include <stdlib.h>

#include <stdio.h>

int main(void)

{

printf(Hello World! This is my first application./n);

return 0;

}

保存在Myapp 目录下。

1. 编写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. 修改user/Makefile

为了让编译器编译上述添加的内容,在user/Makefile 中添加一句(一般按照字母

排列):

dir _$(CONFIG_USER_MYAPP_DEMO) +=Myapp

1. 修改config/config.in

config/config.in 文件中添加的内容会在对用户选项进行配置时反映出来。在文件

的最后,增加一条:

###################################################################

mainmenu_option next_comment

comment 'My New Application'

bool 'demo' CONFIG_USER_MYAPP_DEMO

endmenu

###################################################################

输入 make menuconfig

选择

然后 exit 保存,自动进入下一个画面

选择 My application 回车,出现

选中,然后退出,保存。

接着执行:

make dep

make clean

make lib_only

make user_only

make romfs

make image

make

下载到开发板,可以通过串口终端在teraterm 看到bin 下面多了一个demo 程序。

输入 ./demo 启动演示程序

输出:Hello World! This is my first application.

四.驱动程序的编写

一个简单的驱动程序

一个典型的驱动程序,大体上可以分为以下两个方面:

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>

int test_major=254;

//读函数,仅向用户缓冲区填入数据1

static ssize_t read_test(struct file *file,char * buf,ssize_t count,loff_t *f_pos)

{

int left,ret;

char data=0x41;

for(left=count;left>0;left--)

{

put_user(data,buf);buf++;}

return count;

}

//写函数,空操作

static ssize_t write_test(struct file *file,char *buf,ssize_t count,loff_t *f_pos)

{return count;

}

//打开函数

static int open_test(struct inode *inode,struct file *file)

{

MOD_INC_USE_COUNT;return 0;}

//释放函数

static void release_test(struct inode *inode,struct file *file)

{

MOD_DEC_USE_COUNT;}

struct file_operations test_fops={

read:read_test,

write:write_test,

open:open_test,

release:release_test,

};

//注册函数

int test_init(void)

{

int result;

result=register_chrdev(254,"test",&test_fops);

if(result<0){printk("test:cannot get major number!/n");

return result;}

return 0;

}

//撤消函数

void cleanup_module(void)

{unregister_chrdev(test_major,"test");}

第二步:添加设备;

1)修改linux - 2.4. x/ driver/ char/Makefile 在适当位置添加一行: obj (CONFIGTEST) + = test .o

2)linux - 214. x/ driver/ char/ Config. in , 添加一行: bool test deviceCONFIGTEST

3)修改linux - 214. x/ driver/ char/ mem. c 在适当位置添加:

# ifdef CONFIGTEST

extern void test init (void) ;

# endif

同时在chr devinit () 函数中添加:

# ifdef CONFIGTEST

test init () ;

# endif

4) 修改vendor/ Samsung/ 44bb0/Makefile建立设备节点:

12 - - - 35 行间,DEVICE 部分添加如下内容test ,c ,254 ,0

5) make menuconfig ,character device 选中testdevice

重新编译内核,在控制台输入

/proc> cat devices

Character devices:

1 mem

2 pty

3 ttyp

4 ttyS

5 cua

10 misc

162 raw

180 usb

254 test

Block devices:

1 ramdisk

31 Blkmem

/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()

{

int fd,i,j;

char buf[10];

fd=open("/dev/test",O_RDWR);

if(fd<0)

{

printf("can not open file/n");

exit(0);

}

j=read(fd,buf,10);

for(i=0;i<j;i++)

printf("%d /n",buf[i]);

close(fd);

}

第二步:/ user/Makefile 中适当位置加入下行语句:

dir (CONFIGUSERAPPTEST) += apptest

第三步:/ config/ Configure. help 的适当位置添加以下语句:

CONFIGUSERAPPTEST

This program does APPTEST things to your bars.

第四步:/ config/ config. in 的适当位置添加以下语句:

bool apptest ’ CONFIGUSERAPPTEST

最后再重新编译内核,make menuconfig ,选中自己的应用程序,完成后在/

bin 目录可以看见ap2ptest 的可执行文件,通过控制台直接输入该文件名即可

运行该程序当然也可以在文件vendor/ Samsung/ 44B0/ rc 中添加文件名

apptest ,重新编译uclinux 启动后自动执行该应用程序.

字符设备的另一种做法

(这个设备驱动程序是让蜂鸣器叫)

这里不采用前面提到的 file 结构中的read write 等,而使用IOCTL 来实现。

首先修改前面给出的 test.c,添加Port_init 函数,这个函数用来初始化I/O 配置寄存器。然

后就是修改

struct file_operations test_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>

int test_major=254;

#define Non_Cache_Start (0x2000000)

#define Non_Cache_End (0xc000000)

#define BEEP_CMD_SIGNAL 0

/************************* PORTS ****************************/

static int ledman_ioctl(struct inode * inode, struct file * file,unsigned int cmd, unsigned longarg);

void Port_Init(void)

{

(*(volatile unsigned *)S3C44B0X_PCONA)=0x1ff;

(*(volatile unsigned *)S3C44B0X_PDATB)=0x3ff;

(*(volatile unsigned *)S3C44B0X_PCONB)=0x3ff;

(*(volatile unsigned *)S3C44B0X_PDATC)=0xffff; //All I/O Is High

(*(volatile unsigned *)S3C44B0X_PCONC)=0x0f05ff55;

(*(volatile unsigned *)S3C44B0X_PUPC)=0x30f0; //PULL UP RESISTOR should beenabled to I/O

(*(volatile unsigned *)S3C44B0X_PDATD)=0xff;

(*(volatile unsigned *)S3C44B0X_PCOND)= 0x0;

(*(volatile unsigned *)S3C44B0X_PUPD) = 0x0;

(*(volatile unsigned *)S3C44B0X_PDATE)=0x1ff;

(*(volatile unsigned *)S3C44B0X_PCONE)=0x25568;

(*(volatile unsigned *)S3C44B0X_PUPE)=0x0df; pull-up resistor.

(*(volatile unsigned *)S3C44B0X_PDATF)=0x1ff; //All I/O Is High

(*(volatile unsigned *)S3C44B0X_PCONF)=0x20900a;//All NC is INPUT

(*(volatile unsigned *)S3C44B0X_PUPF)=0x163;

(*(volatile unsigned *)S3C44B0X_PDATG)=0xff;

(*(volatile unsigned *)S3C44B0X_PCONG)=0x00ff;

(*(volatile unsigned *)S3C44B0X_PUPG)=0x0; //should be enabled

(*(volatile unsigned *)S3C44B0X_SPUCR)=0x7; //D15-D0 pull-up disable

(*(volatile unsigned *)S3C44B0X_EXTINT)=0x0; //All EXTINT0-7 Low level interrupt

(*(volatile unsigned *)S3C44B0X_NCACHBE0)=0;//((Non_Cache_End>>12)<<16)|(Non_Cache_Start>>12);

}

void Beep(int BeepStatus)

{

//PE5 Low available

if (BeepStatus==0)

(*(volatile unsigned *)S3C44B0X_PDATE)=(*(volatile unsigned *)S3C44B0X_PDATE)&0x1df;

else

(*(volatile unsigned *)S3C44B0X_PDATE)=(*(volatile unsigned *)S3C44B0X_PDATE)|0x020;

}

static int ledman_ioctl(

struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)

{

int i;

if (cmd == BEEP_CMD_SIGNAL) {

printk("beep0/n");

Beep(0);

return(0);

}

else

{

printk("beep1/n");

Beep(1);

}

return 0;

}

struct file_operations test_fops={

ioctl: ledman_ioctl, /* ledman_ioctl */

};

int test_init(void)

{

int result;

result=register_chrdev(254,"test",&test_fops);

if(result<0){printk("test:cannot get major number!/n");

return result;}

return 0;

}

void cleanup_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()

{

int fd,i,j;

char buf[10];

fd=open("/dev/test",O_RDWR);

if(fd<0){printf("can not open file/n");

exit(0);

}

ioctl(fd, 1, 0); //个参数表示喇叭叫,0 表示不叫

close(fd);

}

其中把原先的read ,write 等调用改为IOCTL 函数调用。

存盘后,执行 make user_only 进行编译。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔷薇理想人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值