您的当前位置:首页正文

嵌入式系统及应用实验指导书

来源:个人技术集锦


嵌入式系统及应用

实验指导书

李 剑 编

中国矿业大学 信息与电气工程学院 2012年12月

实 验 要 求

实验前应充分预习阅读实验指导书,查看相关技术文档,复习教材中有关内容。明确实验目的、实验原理及内容,以减少实验中的盲目性,提高主

动性。自行拟定实验步骤,掌握注意事项。

实验报告在实验完成后一周内交到实验室,采用统一报告纸,手写完成,

并装订成册。

目 录

嵌入式系统与应用实验硬软件介绍

实验一 ADI IDE嵌入式集成开发环境基础实验 实验二 嵌入式Linux应用程序开发基础实验

嵌入式系统与应用实验硬软件介绍

一、JXARM9-2410实验箱硬件简介:

图1 JXARM9-2410实验箱结构示意图

JXARM9-2410教学实验系统的硬件部分包括:基本模块、调试模块、通讯模块、人机交互模块、A/D模块、步进电机驱动模块、IDE/CF接口模块、GPRS模块、GPS模块。

1. 基本模块:

SDRAM存储器:主板包含64MB SDRAM。由一片16位数据宽度的SDRAM存储器组成,地址从0x30000000~0x33fffffff。

FLASH 存储器:主板包含32MB NOR FLASH存储器和8MB NAND FLASH,NOR FLASH内部存放启动代码Bootloader、Linux 内核映象、IIS测试声音文件等。其数据宽度为32位,地址从:0x00000000~0x01ffffff;NAND FLASH中包含一个cramfs文件系统,在Linux中使用。

串行通讯口:主板包含3 个UART接口:UART0和UART1 用作RS232 串行接口,UART2 用作RS485 接口。UART0在Bootloader、演示程序、Linux 和多个实验中用于人机交互(通过超级终端)以及文件传输;

IIS 录放音接口:主板有一个可以基于DMA 操作的IIS 总线接口,可进行立体声录放音; I2C 总线接口:与24C08 芯片接口,可以存放一些固定的配置数据;

4 个LED 跑马灯:可独立软件编程; 6 个七段数码管:6个共阳七段数码管;

外部中断测试:一个按键用于外部中断0 的测试; 复位按键:按键用于CPU 复位;

两通道通用DMA,两通道具有外部请求引脚的外设 DMA; 五个PWM 定时器和一个内部定时器; 看门狗定时器; 8 通道10-bit ADC。 2. 调试模块:

标准JTAG接口:14针标准JTAG接口,该接口用于高速仿真调试;

简易调试接口并口:直连标准计算机并口,调试接口,该接口用于简易仿真调试。 3. 通讯模块:

以太网通讯接口:10M以太网卡; USB接口:遵循USB1.1标准; 标准计算机打印口(并口)。 4. 人机交互模块:

显示器/触摸屏:8英寸,TFT LCD显示器,640X480; 按键:4X4按键。 5. A/D模块: 10bit A/D模块。 6. 步进电机驱动模块: 两相步进电机驱动。 7. IDE/CF接口模块: 标准IDE硬盘接口; 标准CF卡接口。 8. GPRS模块: GPRS无线通讯模块。 9. GPS模块:

GPS全球定位系统模块。

二、JXARM9-2410实验箱硬件资源分配

在使用实验箱中的各个模块硬件资源时,需了解模块对应的地址空间及空间组织,以便编程调用。 1. 地址空间分配以及片选信号定义

表1 ARM9-2410 地址空间分配表

2. RAM空间组织

存储空间的定制是嵌入式系统开发的一个特色,我们可以根据自己的需要自行规定内存的使用。在本教学实验系统中,SDRAM地址范围从0x30000000–0x33ffffff共64Mbytes。在不同的程序中,SDRAM空间范围被分配成不同的区域用于不同的用途,下表是实验测试程序所用的一个默认分配方式,它的代码空间和数据空间分配如下:

表2 SDRAM空间组织分布

3. FLASH空间组织

FLASH 地址范围从0x00000000–0x01ffffff共32Mbytes。其空间组织如下表,各地址空间对应了不同的用途:

表3 FLASH 空间组织分布

三、超级终端的使用

普通PC软件开发是使用键盘和显示器作为标准输入输出设备,而嵌入式系统开发一般使用串口作为标准输入输出设备。嵌入式系统上电后执行u-boot代码进行系统引导,在u-boot中指定了串口0作为输入输出设备。这对于我们进行嵌入式应用非常重要。

超级终端是windows XP系统自带的终端连接软件,当连接设备选择为串口时,即可作为实验箱的输入输出界面使用。Widows 7等版本不自带超级终端,但网上有大量的类似软件可以使用。下面介绍超级终端的使用方法。

下图给出了xp系统中超级终端打开的路径:

图2 超级终端打开路径

打开超级终端后弹出的画面如图3所示,随意给新建连接起个名称,如ARM、ARM2410:

图3 超级终端界面1

点击确定后,弹出的界面如图4所示:

图4

再点击取消,界面如图5所示,此时还为设置连接。

图5

点击图5中红圈所圈的工具图标,弹出的设置对话框如图6所示

图6 超级终端设置对话框

点击“连接时使用”的下拉条,选中相应的串口设备,普通PC机上一般是com1。如果是笔记本或其他电脑没有自带串口的,一般使用USB转串口设备,此时需先打开系统的设备管理器,找到端口一项,查看USB serial的端口号。然后点击超级终端设置对话框中的设置按钮,打开串口属性设置对话框,设置如图7所示:

图7 串口属性设置对话框

按照图7所示进行设置后,点击确定后返回到图6对话框,再点击确定,回到主界面,点击呼叫图标(有时候设置好后返回主界面会自动连接呼叫)如图8所示红圈内的电话标志,就可以连接外部串口设备了。如果要断开连接就点击旁边的断开图标。

图8

用串口线连接到JXARM9-2410实验箱的串口0上,打开超级终端的呼叫图标,然后打开实验箱的电源,正常情况下超级终端会显示如下信息,如图9所示:

四、嵌入式Linux开发环境的建立(JXARM9-2410实验箱)

嵌入式Linux开发环境主要包括四个方面:选择并安装一个合适的主机Linux操作系统;在主机Linux系统中安装tftp服务器;在主机中安装Linux系统;在主机Linux系统安装交叉编译器。

1.安装主机Linux操作系统

要进行嵌入式linux的开发首先要按照好一个主机开发环境,因为嵌入式linux下的大部分开发工作都是在pc中开发的。如果你的机器足够好(内存至少大于1GB),那么建议首先在Windows下安装一个虚拟机软件vmware,毕竟Windows下可用的工具比较多,再在vmware基础上安装一个桌面版本的Linux系统。实验室使用的是vmware-8.0和Ubuntu-11.10,这2个软件都可以在网上下载到。 由于在linux系统的开发过程中需要经常使用管理员权限,因此建议使用root登录linux系统。通常新建系统是不允许root登录的,如何获得root登录则需根据不同的linux系统版本在网络上查找方法,本文不详细介绍。

2.建立tftp服务器

在嵌入式linux开发过程中需要使用tftp方式从Linux主机下载文件到板子中,因此需要在主机linux系统中安装tftp服务器。

(1)安装tftp软件

在Ubuntu的终端中输入“apt-get install tftpd tftp xinetd”,默认执行到结束。 (2)建立配置文件

在终端中输入“gedit /etc/xinetd.d/tftp”新建一个tftp配置文件,并在文件中输入: service tftp

{

socket_type = dgram protocol = udp wait = yes user = root

server = /usr/sbin/in.tftpd server_args = -s /tftpboot disable = no per_source = 11 cps = 100 2 flags = IPv4 }

服务器的根目录地址即为tftpboot。 (3)重启服务

在终端中输入“/etc/init.d/xinetd restart”。 3.建立nfs服务器

在嵌入式linux开发的时候,常常需要使用nfs以方便程序的调试。使用nfs,用户可以将板子要用到的根文件系统放在主机目录下,开发板则通过以太网挂载到这个目录并将这个目录下的文件作为根文件系统的内容,这样用户的程序更新后不比重新烧写板子的根文件系统便能被重新使用,这点能够大大加快程序的调试。

Ubuntu下安装nfs服务器的步骤如下: (1)进行NFS服务器端与客户端的安装: apt-get install nfs-kernel-server (2)配置挂载目录和权限 gedit /etc/exports 在最后一行添加配置如下: /nfsboot *(rw,sync)

其中/nfsboot指的是是NFS的共享目录,*表示任何IP都可以共享这个目录,你可以改为受限的IP,rw表示的是权限,sync是默认的。

(3)重启NFS服务

/etc/init.d/nfs-kernel-server restart 重启nfs服务 4.安装交叉编译链

arm处理器不断发展,已经有很多种架构,针对不同的arm架构和linux内核版本,需使用不同的编译器。JXARM9-2410的嵌入式linux系统使用的是版本为2.95.3。ARM11H或其他嵌入式设备的交叉编译器版本不同,但安装安装方法类似。

(1)安装编译器

将附件文件cross-2.95.3.tar复制到Ubuntu主文件夹下,然后打开终端执行:

mkdir /usr/local/arm

cp cross-2.95.3.tar /usr/local/arm cd /usr/local/arm

tar xvf cross-2.95.3.tar

rm /usr/local/arm/cross-2.95.3.tar

(2)将编译器添加到环境变量中

为了使用方便,还可以编辑/etc/bash.bashrc文件添加把编译器路径到环境变量PATH中,只要在这个文件中添加下面这个语句即可:

export PATH=$PATH:/usr/local/arm/2.95.3/bin:

编辑完毕后使用source /etc/bash.bashrc命令执行以下这个文件,让设置生效。 5. 安装内核树

要安装与目标板一样版本的内核树,查看内核版本方法: uname -r 将内核压缩包解压到工作目录下,然后依次执行命令

make oldconfig make zImage

执行此命令时若遇见cc1: error: unrecognized command line option \"-mlittle-endian\" 错误,解决问题方法:make CROSS_COMPILE=arm-linux- zImage。

make modules

make modules_install后就安装成功

没有内核树是无法单独编译驱动模块的,一些库文件无法找到。

实验一 ADI IDE嵌入式集成开发基础实验

一、实验目的

1.了解ADT IDE的 ARM开发环境;

2.掌握ADT IDE开发环境中基本的工程设置以及程序编译方法; 3.掌握ADT IDE开发环境中基本的程序调试方法。

二、实验内容

在ADT集成开发环境中编写数码管显示程序,利用6位数码管构成一个简易秒表。

三、实验设备

1.硬件:JXARM9-2410教学实验箱、PC机;

2.软件:PC机操作系统 Windows 98(2000、XP) + ADT 1000开发环境。

四、实验预备知识

更详细的内容见《ARM9 嵌入式技术及嵌入式 Linux 高级实践教程》第4章。 1.C语言的基础知识;

2.ADI IDE集成开发环境的程序调试基础知识和方法; 3.LED数码管基本原理;

发光二极管数码显示器简称LED显示器。LED显示器具有耗电省、成本低廉、配置简单灵活、安装方便、耐振动、寿命长等优点,目前广泛应用于嵌入式系统中。

7段LED由7个发光二极管按“日”字形排列,所有发光二极管的阳极连在一起称共阳极接法,阴极连在一起称为共阴极接法。一般共阴极可以不需外接电阻,但共阳极接法中发光二极管必须外接电阻。LED的结构及连接图见下图。

当选用共阴极的LED显示器时,所有发光二极管的阴极连在一起接地,当某个发光二极管的阳极加入高电平时,对应的二极管点亮。因此要显示某字形就应使此字形的相应段的二极管点亮,也就是送一个用不同电平组合代表的数据字来控制LED的显示,此数据称为字符的段码。字符0、1、2„F与LED码段A、B、C„F以及DP(小数点)的关系如表4:

字符 DP 0

G 0 F 1 E 1 D 1 C 1 B 1 A 1 段码(共阴) 段码(共阳) 3FH C0H 0

1 2 3 4 5 6 7 8 9 A B C D E F - . 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1 1 1 1 0 1 1 1 1 0 0 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 0 0 0 0 1 0 0 0 1 0 1 0 1 1 1 1 1 1 0 0 0 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 0 0 06H 5BH 4FH 66H 6DH 7DH 07H 7FH 6FH 77H 7CH 39H 5EH 79H 71H 40H 80H 00H F9H A4H B0H 99H 92H 82H F8H 80H 90H 88H 83H C5H A1H 86H 8EH BFH 7FH FFH 熄灭 0 说明:共阴的LED,被选中时的段为高电平有效,熄灭的段码为00H; 共阳的LED,被选中时的段为低电平有效.熄灭的段码为FFH。

LED显示器的接口一般有静态显示与动态显示接口两种方式,下面分别加以介绍。 1) 静态显示

LED数码管采用静态接口时,共阴极或共阳极点连接在一起接地或接高电平。每个显示位的段选线与一个8位并行口线对应相连,只要在显示位上的段选线上保持段码电平不变,则该位就能保持相应的显示字符。这里的8位并行口可以直接采用并行I/O口,也可以采用串入/并出的移位寄存器或是其它具有三态功能的锁存器等。

2) 动态显示

在多位LED显示时,为了简化电路,降低成本,将所有位的段选线并联在一起,由一个8位I/O口控制。而共阴(或共阳)极公共端分别由相应的I/O线控制,实现各位的分时选通。由于各个数码管是共用同一个段码输出口,分时轮流通电的,从而大大简化了硬件线路,降低了成本。不过这种方式的数码管接口电路中数码管不宜太多,一般在8个以内,否则每个数码管所分配的实际导通时间会太少,显得亮度不足。若LED位数较多时应采用增加驱动能力以提高显示亮度。

本实验中采用的是动态显示接口,其中数码管扫描控制地址为0x0:1000006,位0-位5每位分别对应一个数码管,将其中某位清0来选择相应的数码管,地址0x01000004为数码管的数据寄存器。数码管采用共阳方式,向该地址写一个数据就可以控制LED的显示,其原理图如下图所示:

五、实验步骤

1.硬件连接

将实验箱的电源线接到电源插座上,使用串口连接线连接PC串口端和实验箱串口0,使用并口线连接PC机并口端和实验箱的简易JTAG并口调试端。 2.超级终端

按照前面的内容建立好一个超级终端后,打开实验箱电源,检查U-boot启动是否正常 3.建立工程

1)(以英文版为例,汉化版请同学们自己对照)打开ADT IDE,点击“File->New菜单”,弹出New对话框,如上图所示,选择Project页,在Project页中选择调试设备,对于简易调试器的用户,请选择“ARM9SIMPLE”,在“Project name”和“Location”中输入工程名称和路径,请注意路径和工程名中不能包含空格。在工程类型中选择“EXEC”。

2) 新建一个文件并保存为d:\\leddemo\\leddemo.c,编辑该文件,添加如下代码: /****************************************************************************/ /*文件名称: LEDSEG7.C */ /*实验现象: 数码管依次显示出0、1,2、„„9、a、b、C、d、E、F */ /****************************************************************************/ #define U8 unsigned char static int delayLoopCount=1000; unsigned char seg7table[16] = {

/* 0 1 2 3 4 5 6 7*/ 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,

/* 8 9 A B C D E F*/ 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, };

void Delay(int time);

/****************************************************************************/ /* 函数说明: JXARM9-2410 7段构共阳数码管测试 */ /* 功能描述: 依次在7段数码管上显示0123456789ABCDEF */ /* 返回代码: 无 */ /* 参数说明: 无 */ /****************************************************************************/ void Test_Seg7(void) {

int i;

*((U8*) 0x010000006) = 0x00;/*为什么是0x01000006?它是做什么用的?*/

for( ; ; ) {

/* 数码管从0到F依次将字符显示出来 */

{

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

/* 查表并输出数据 */

*((U8*) 0x010000004) = seg7table[i]; /* 0x01000004又是做什么用的?*/ Delay (1000);

}

/* 数码管从F到0依次将字符显示出来 */ for(i=0xf;i>=0x0;i--)

/* 查表并输出数据 */

{

}

} }

*((U8*) 0x010000004) = seg7table[i]; Delay (1000);

/****************************************************************************/ /* Function name : 循环延时子程序 */ /* Description : 循环 'time' 次 */ /* Return type :void */ /* Argument : 循环延时计数器 */ /****************************************************************************/ void Delay(int time) { int i;

for(;time>0;time--) }

3) 将leddemo.c文件加入到工程leddemo中,如下图所示,点击右键菜单:

for(i=0;i将弹出文件选择对话框,选择d:\\leddemo\\leddemo.c文件,并点击“打开”按钮。

4) 新建一个文件并保存为d:\\leddemo\\ldscript,编辑该文件,添加如下内容: SECTIONS {

. = 0x30000000; .text : { *(.text) } Image_RO_Limit = .; Image_RW_Base = .; Image_RO_Base = .; Image_RW_Limit = .; .data : { *(.data) } .rodata : { *(.rodata) } Image_ZI_Base = .; .bss : { *(.bss) } Image_ZI_Limit = .; __bss_start__ = .; __bss_end__ = .; __EH_FRAME_BEGIN__ = .; __EH_FRAME_END__ = .;

PROVIDE (__stack = .);

end = .; _end = .;

.debug_info 0 : { *(.debug_info) }

.debug_line 0 : { *(.debug_line) } .debug_abbrev 0 : { *(.debug_abbrev)} .debug_frame 0 : { *(.debug_frame) }

}

该文件为链接脚本文件,链接脚本文件中全部使用半角符号,文件编写格式必须从SECTIONS关键字开始,紧接着是开大括号,后面是所有需要输出的描述部分,最后用闭大括号收尾。具体意义参考附录A。该文件必须通过第5步中的工程设置对话框设置到链接参数中才有效。

鼠标右键点击工程中的MISC目录,选择添加文件,将该文件添加到工程中。

5) 如下图所示,在工作区窗口中的leddemo工程名上右键点击并选择“Setting”菜单项。

弹出设置对话框,选择“Link”页,在“Link script”链接脚本中输入“.\\ldscript”,点击“OK”按钮。

6) 如下图所示,在工作区窗口中的leddemo工程名上右键点击并选择“Build”菜单项。

编译成功后结果如下图所示。

7) 如并口线已经连接到JXARM9-2410 的简易JTAG并口上,且实验箱已经上电,就直接点击“Debug”菜单的“Remote Connect”进行连接,如下图所示。

正常连接结果如下图所示,有target connected的提示。

如果连接正确“Debug”菜单项将如下图所示

8) 点击Debug->Download菜单下载程序到SDRAM中

下载成功后,将显示入口点的源代码,如下图所示:

9) 运行程序,点击Debug->Go菜单项,运行该程序,如果运行正常,JXARM9-2410上的六个七段数码管将显示十六进制数据。

10) 点击Debug->Stop停止程序运行。

六、实验要求

1、使用examples的示例中的工程leddemo,利用动态显示和动态扫描的方式修改前面的程序,使6个7段数码管作为一个简易的计时器。

2、使用examples的示例,练习看门狗、中断、DMA等程序,了解S3C2410的结构和各种控制器的使用方法。

3、本实验不分组,每个学生独立完成自己的内容。然后通过并口数据线连接实验箱,下载和运行程序,进行验证。

七、实验报告要求

1.简述7段LED数码管显示原理和显示方法; 2.简述简易计时器的设计与实现过程,给出编程代码; 3.参考实验箱的用户手册,简述链接脚本代码的的各段意思;

实验二 嵌入式Linux应用程序开发基础实验

一、实验目的

1.了解交叉编译环境的建立和使用; 2.了解Linux开发环境;

3.掌握简单的linux应用程序的编译。

二、实验内容

编写简单的C语言helloworld程序,在Linux操作系统下的交叉编译环境下进行编译,然后下载到实验箱的嵌入式Linux系统中运行。

三、实验设备

1.硬件:JXARM9-2410教学实验箱、ARM11-6410实验箱、PC机; 2.软件:PC机操作系统XP + VMware+Linux虚拟操作系统。

四、实验预备知识

1.C语言的基础知识;

2.Linux基本知识(操作,命令等);

3.了解交叉编译环境的搭建过程(针对不同的ARM平台,有不同的编译版本,请自行参考书籍); 更详细的内容见《ARM9 嵌入式技术及嵌入式 Linux 高级实践教程》和《武汉创维特2410开发板的Linux实验指导书 2.00版》,以及其他介绍嵌入式Linux的书籍。

五、基础知识

helloworld程序是一个只在输出控制台(计算机屏幕或者串口控制台)上打印出“Hello, World!”(英语,意为“你好,世界!”)字串的程序。该程序通常是计算机程序设计语言的初学者所要学习编写的第一个程序。它还可以用来确定该语言的编译器、程序开发环境以及运行环境已经正确安装。

本实验也将helloworld程序作为第一个学写的程序,并通过实际的动作让学生了解嵌入式Linux应用程序开发和PC机中Linux应用程序开发的异同。 1. 交叉编译环境

通常,程序是在一台计算机上编译,然后再分布到将要使用的其他计算机上。当主机系统(运行编译器的系统)和目标系统(产生的程序将在其上运行的系统)不兼容时,该过程就叫做交叉编译。 除了兼容性这个明显的好处之外,交叉编译还由于以下两个原因而非常重要:当目标系统对其可用的编译工具没有本地设置时;当主机系统比目标系统要快得多,或者具有多得多的可用资源时。 本实验所使用的开发系统是x86体系结构的Linux系统(Ubuntu11)。而我们的目的是要开发能够运行在JXARM9-2410教学实验箱中的Linux应用程序。由于JXARM9-2410教学实验箱中的Linux本身

不具有自己的编译工具,因此我们必须在PC机的Linux系统中进行交叉编译,编译完成后将执行码下载到JXARM9-2410教学实验箱中的Linux,然后运行或者调试。这样做的另外一个好处是,在采用PC机的Linux的主机系统通常其CPU速度、接口等软硬件资源都比JXARM9-2410教学实验箱中的Linux要丰富得多,因此在其上进行交叉编译效率要高得多。

在同一平台编译能够运行在不同平台上运行的程序的最主要差别在于所采用的编译器不同。在PC机的Linux系统中编译x86平台的采用gcc编译器,而编译ARM平台的采用arm-elf-gcc或者arm-linux-gcc编译器。在本实验箱中,所有Linux实验均采用arm-linux-gcc编译器编译。 2. helloworld的编译

helloworld可以说是最简单的应用程序,通过如下命令进行编译: gcc -o helloworld helloworld.c

其中-o指定输出文件到helloworld,helloworld.c为编译的源文件。该命令执行后,将对helloworld.c文件进行编译,并将生成helloworld可执行文件。这个文件就是在指定平台上可以运行的执行程序,如果使用gcc进行编译即为可在x86平台上运行的程序,如果使用arm-linux-gcc进行编译则为可以在ARM平台上运行的程序,即:

arm-linux-gcc -o helloworld helloworld.c

需要注意的是arm-linux-gcc编译器需在环境变量中添加其路径,才能直接调用,否则需给出完整的路径。 3. Makefile文件

Makefile文件的作用有点类似于DOS下的批处理文件,通过编写Makefile文件,用户可以将一个很复杂的程序(可能包含上百个甚至更多的源文件或者目录)通过简单的make命令进行编译。 对于一个工程下有多个源程序和头文件的情况,一般都要使用Makefile文件来确定编译规则和顺序。

需要注意的是linux内核2.6以后的版本和之前的版本的Makefile规则有所不同,本指导书对应的是linux-2.4.18。

六、实验步骤

(虚拟机的linux系统一定要root登陆,否则非常麻烦。) 1.编写源文件

首先编写一个helloworld.c文件,内容清单为:

#include

int main(int argc, char **argv) { }

printf(\"Hello, World!\\n\");

2.编写Makefile文件

Makefile文件内容清单为:

CC = /usr/local/arm/2.95.3/bin/arm-linux-gcc # 给CC赋值,一般指定编译器

LD = /usr/local/arm/2.95.3/bin/arm-linux-ld # 给LD赋值,一般指定链接程序,可省略 EXEC = helloworld

# 给EXEC 赋值,一般指定生成的程序名 OBJS = helloworld.o

# 给OBJS赋值,一般指定生成的.o 文件文件名

CFLAGS +=

# 给CFLAGS 赋值,为编译命令指定附加编译行为,此处无附加编译行为,参看 3.5节

LDFLAGS +=

# 定义连接器选项, 参见gcc 和Makefile文件的解说(3.4和3.5 节)

all: $(EXEC)

$(EXEC): $(OBJS)

# 表示依赖关系,即 helloworld 依赖于helloworld.o

$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS$(LDLIBS_$@)) # 变量前加$表示取该变量的值,上述语句可认为是: # gcc –o helloworld

# $@ 扩展成当前规则的目的文件名,此处即为 helloworld clean:

-rm -f $(EXEC) *.elf *.gdb *.o

# 该语句是删除语句,-f 表示直接删除,$(EXEC) 表示可执行程序文件,即清除指 定的可执行文件,以及后缀为*.elf ,*.gdb,*.o 的文件。*.elf ,*.gdb,*.o 分别代 表所有后缀为# elf ,gdb,o 的文件。

3.下载执行

1)在虚拟机的linux系统中建立nfs服务器,使用前确认目录是否对的:打开/etc/exports文件,最后一行定义的为/nfsboot *(rw,sync),星号后的参数可以不同。如果没有就参照手册自己建立nfs服务器。同时在根目录下要有一个nfsboot文件夹。

2)修改虚拟机vmware网络连接方式:菜单虚拟机->设置->网络适配器->网络连接选择桥接方式和复制物理网络连接状态。

3)修改虚拟机linux系统的网络连接:点击系统界面右上方的网络连接图标(ubuntu和xubuntu图标不一样),选择编辑连接-》有线-》添加,有线连接名称改为2410或6410,选IPv4设置,方法选“手动”,点击添加,在地址栏输入如:192.168.1.111,(这个IP地址最后一段可以自己随便设,只要不和实验箱的ip一样就行,终端查看ip的命令为ifconfig),在子网掩码输入:

255.255.255.0。点击保存。重新点击系统界面右上方的网络连接图标,选择刚建立的连接。连接好后查看连接信息看ip信息是否正确。

4)编译程序:虚拟机的linux系统中打开终端到程序目录下(以helloworld为例),查看c语言文件是否正确后,编写Makefile文档(如果你的程序只有一个c文件,也可以不编写Makefile文档),如果有Makefile文档,直接在终端中运行make。如果没有Makefile文档,就在终端中运行arm-linux-gcc –o hello helloworld.c,hello是编译好的可执行程序,必须在实验箱的linux系统下运行,虚拟机的linux系统中无法运行。

5)windows下使用超级终端连接实验箱。如果使用笔记本,则需要首先安装usb转串口线的驱动程序,然后再将usb转串口线插到PC的usb接口上。打开windows的设备管理器,找到端口一项,展开后可以看到USB-bridge-to-serial(com3),com3指的是usb转串口线的端口号,也可能是com4、com5„。打开windows下的超级终端,win7系统没有自带的,就从网上下载一个。随便取个名字,打开属性,点击连接时使用,选刚才那个com几,然后点配置,设115200,8,无,1,无。好了,点连接。将usb转串口线和实验箱连接,打开实验箱电源,超级终端上有显示。如接2410实验箱,则等显示停后,按实验箱上的键盘7,启动linux文件系统,等显示再次停止后,按PC机的Ctrl+c键,进入linux系统终端,显示只有一个#号。如接6410实验箱,则等显示到„.not Server后,会停止,此时在超级终端中回车,即有“root$real6410#”提示,此时已经进入linux文件系统的终端了。

6)连接网线:用网线将PC机和实验箱相连。虚拟机linux系统的网络连接会有显示。如用笔记本,此时要断开无线连接。然后在超级终端中输入“ping 192.168.1.111”就是虚拟机linux系统的ip地址,如果不断有提示说收发多少,延迟xxms,即说明连接正常。如提示半天没反应,有time out之类的,说明没连接成功,要检查虚拟机linux系统的网络连接

7)挂载:连接成功后,在超级终端中输入 :

“mount 192.168.1.111:/nfsboot/ /mnt/nfs”,然后输入“cd /mnt/nfs”进入nfs目录,然后输入ls,查看有没有挂载成功。

如果使用real6410实验箱,上面的命令改为“mount –o nolock192.168.1.111:/nfsboot/ /mnt/nfs”

如果挂载成功,则超级终端会显示虚拟机linux系统的nfsboot目录下的文件和文件夹。 如果挂载不成功,首先查看虚拟机linux系统的网络连接是否正常,可以使用ping + IP地址的方式查看网络是否通畅。如果还不行,就“gedit /etc/exports”查看nfs的目录是否是nfsboot。 8)运行程序:找到hello文件,输入“./hello”,注意斜杠前有个点。超级终端会显示运行的结果。 4.替换练习

一、编写一个简单的人机交互对话C/C++ 语言程序。可以发挥自己的想象力,随意编写。也可以参考手册或其他书籍编写不同的应用程序。提示:使用函数getchar( ) 。根据键盘的一个按键决定输出的字符串。例如:按下'B'键或者'b' 键,输出“Beijing ”;按下'N'键或者'n' 键,输出

“Nanjing”;按下其他键,输出“The interaction processs is over. ”。人机交互过程通过超级终端观察,键盘操作在主机键盘上进行。输入ESC 键退出。

二、仿照教程编写一个简单的多线程应用程序。

七、实验报告要求

1.简述什么是交叉编译环境,并说明搭建嵌入式Linux开发环境的过程;

2.简述Makefile文件的作用和规则,make的工作原理,了解编译过程中各种后缀文件的作业; 3.简述你是怎样将编写的应用程序下载到实验箱JXARM9-2410的Linux系统中的,怎样在实验箱中运行该程序?

附录A 链接定位脚本

链接定位是系统级软件开发过程中必不可少的一部分,嵌入式软件开发均属于系统级开发,绝大部分嵌入式软件都涉及到链接定位脚本文件;链接定位脚本使得我们的目标代码组织更加灵活。

1. 链接定位脚本文件说明

链接定位过程一般由链接器根据链接定位脚本完成,比较简单的系统可以通过设置链接器开关选项取代链接定位脚本;链接定位的关键是链接定位脚本的编写。我们从典型的目标文件结构开始,来介绍链接定位脚本文件的编写。下面是该系统一个目标文件的典型组织:

其中第二栏开始分别展示了该文件各个段(Sections)的属性:名称(Name)、类型(Type)、地址(Addr)、偏移(Offs)、大小(Size)、固定单元大小(Es)、标志(Flg)、连接依赖(Lk)、附加属性(Inf)、字节对其宽度(Al)。

地址部分(Addr)描述了这一段在目标系统中的地址,而偏移(Offs)则记载了该段在目标文件中的偏移,大小(size)表示该段的实际长度;比如上图中.Text段的地址为0x0c700000,偏移为0x008000,大小为0x00d950,说明该段位于文件的偏移0x008000处,它将被下载到目标板0x0c700000处。

从段的分类来看,第7段以后的内容仅仅与调试有关,涉及到定位的也就是前面几段:.text、.data、.rodata、.bss,下面是一个具体的链接定位脚本文件: SECTIONS {

Image_RW_Base = .; /* RW(可写数据)基址,实际上是在这里声明了一个全局符号,我们可以在程序中使用该符号,它等同于在代码中声明一个全局变量,但它的值由链接器指定,在这里“=.”表示该符号的值等于当前地址;下面的定义类似*/

. = 0x0c200000; /*赋当前地址,后续的代码将从该地址开始存放 */ .text : { (.text) }

/*.text段表示代码段,从0x0c200000开始放置代码*/

.data : { (.data) } /*数据段, 保存已经初始化的全局数据 */

.rodata : { *(.rodata) } /*只读数据段, 保存已经初始化的全局只读数据*/ }

text段是程序代码段,紧随其后的是几个符号定义,它们是由编译器在编译连接时自动计算的,当我们在链接定位文件中申明这些符号后,编译连接时,该符号的值会自动代入到源程序的引用中,如果你想进一步了解连接定位的一些含义,可以参考编程手册中的ld一章。

data段的起始位置也是由连接定位文件所确定,大小在编译连接时自动分配,它和我们的程序大小没有关系,但和程序使用到的全局变量,常量数量相关。

bss的初始值也是由我们自己定义的连接定位文件所确定,我们应该将它定义在可读写的RAM区内,stack的顶部在可读写的RAM区的最后,我们可以非常灵活的定义其起点和大小,但对大部分情况来说,程序区在ROM或FLASH中,可读写区域在SRAM或DRAM中,我们可以考虑一下自己程序规模,函数调用规模,存储器组织,然后参照一个连接定位文件稍加修改就可以了。

Image_ZI_Base = .; /*ZI基地址, 需要清零的区域 zero init*/ .bss : { *(.bss) } /*堆栈段,未初始化的全局变量也保存在此*/

__bss_start__ = .; /* bss的基地址*/ __bss_end__ = .; /* bss的结束地址*/

__EH_FRAME_BEGIN__ = .; /* FRAME开始地址(基地址)*/ __EH_FRAME_END__ = .; /* FRAME结束地址,gcc编译器使用 */

PROVIDE (__stack = .); /* 当前地址赋给栈,栈地址一般是可读写区最高处*/

end = .; /* 结束地址*/ _end = .; /* 结束地址*/

.debug_info 0 : { *(.debug_info) } /*调试信息*/ .debug_line 0 : { *(.debug_line) } /*调试信息*/ .debug_abbrev 0 : { *(.debug_abbrev)} /*调试信息*/ .debug_frame 0 : { *(.debug_frame) } /*调试信息*/

2. 链接定位脚本修改实例

SECTIONS {

. = 0x00000000; /*将代码段起始地址修改到0*/ .text : { *(.text) } .=0xc0000000

Image_RW_Base = .;

/*设置数据段从0xc0000000开始存放*/

.data : { *(.data) }

/*设置只读数据段从0xd0000000开始存放*/

.=0xd0000000 }

.rodata : { *(.rodata) }

Image_ZI_Base = .; .bss : { *(.bss) } Image_ZI_Limit = .; /*申明一个符号download_size */

download_size = SIZEOF(.text)+SIZEOF(.data)+SIZEOF(.rodata)+SIZEOF(.bss); __bss_start__ = .; __bss_end__ = .;

__EH_FRAME_BEGIN__ = .; __EH_FRAME_END__ = .;

end = .; _end = .;

.debug_info 0 : { *(.debug_info) } .debug_line 0 : { *(.debug_line) } .debug_abbrev 0 : { *(.debug_abbrev)} .debug_frame 0 : { *(.debug_frame) }

PROVIDE (__stack = .);

因篇幅问题不能全部显示,请点此查看更多更全内容