嵌入式linux系统移植和简单驱动讲稿

嵌入式linux系统移植和简单驱动讲稿
嵌入式linux系统移植和简单驱动讲稿

嵌入式linux 系统移植和简单驱动

文件状态: [ ] 草稿

[ ] 正式发布 [ √ ] 正在修改

文件标识:北航科技园嵌入式技术中心

嵌入式linux 系统移植和简单驱动 当前版本:0.1 作 者: 蒙洋

博 客: https://www.360docs.net/doc/3113424667.html,/mistyeyed

进度记录

GNUtools 完成 Bootloader 部分还有待丰富内容

完成日期:

2010‐8‐30

嵌入式Linux开发环境搭建

内容提纲

`嵌入式linux开发介绍

`嵌入式系统简介

`嵌入式linux系统构成

`嵌入式linux系统开发移植主要工作

`嵌入式Linux开发环境的搭建

`搭建嵌入式Linux开发环境的主要工作

`嵌入式Linux交叉开发环境硬件基本组成

`为什么需要交叉编译?

`gnu工具链简介

`安装交叉编译工具,开源的gcc的编译

`主机、目标机通讯及为提供开发效率辅助方法介绍

`主机端需要什么

`目标机端需要什么

GNU Tools建立和开发环境

GUN Tools是Linux环境下的主要开发工具,掌握这些开发工具的使用是嵌入式Linux开发人员所必须的技能,必须的!

这一讲我们将花费很长的时间来介绍GUN Tools开发工具中的核心软件及其调试工具,为后面的驱动和应用的开发打下坚实的基础。我们这里只是涉及到了在嵌入式开发经常用的工具软件,更多的参数和功能大家可以参考手册。我这里是抛砖引玉,希望能发现几块好玉,呵呵!

1、GUN Tools简介

嵌入式软件开发与普通的软件开发没有什么不同,但是由于嵌入式系统的可配置性和定制性,需要开发者对嵌入式系统的每个环节要十分的了解(举例在PC下写应用不需要了解系统的很多机制)。为了更好的进行嵌入式linux开发至少要了解如下4类开发工具: 编译工具:源程序—》可执行程序,GCC

调试工具:debug源程序,包括c代码和汇编代码,GDB

软件工程工具:用于大型项目的管理,make,CVS(注)

其他工具:连接器,格式转换的工具

注:CVS: 全称是Current Version Control. CVS是一种GNU 软件包.由Intersolv公司开发,最新的版本是1.10.8.它是一种基于RCS系统的维护工具.它明确的将源文件的存储和用户的工作空间独立开来,有在一定的模式上扩展了RCS的恢复提交功能. 并使其有利与并行开发.

2、GCC和GNUTools工具集介绍

在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux 程序员面临的首要问题都是如何灵活运用C编译器。目前Linux 下最常用的C语言编译器是

GCC(GNU Compiler Collection),它是GNU项目中符合ANSI C标准的编译系统,能够编译用C、C++和Object C等语言编写的程序。GCC不仅功能非常强大,结构也异常灵活。最值得称

道的一点就是它可以通过不同的前端模块来支持各种语言,如Java、 Fortran、Pascal等。

GNU Tools工具集

Gcc:符合ISO标准的C编译器

G++:符合ISO标准的C++编译器

GNU binutils是一组二进制工具集。包括:addr2line、ar、as、gprof、ld、nm、objcopy、 objdump、ranlib、size、strings、 strip. 这里归纳他们的常用法。

ar

ar用于建立、修改、提取档案文件(archive)。archive是一个包含多个被包含文件的单一

文件(也称之为库文件),其结构保证了可以从中检索并得到原始的被包含文件(称之为archive中的member)。member的原始文件内容、模式(权限)、时间戳、所有着和组等属

性都被保存在 archive中。member被提取后,他们的属性被恢复到初始状态。

ar可以主要用于创建C库文件

多说没用,大家可以参考数据手册。举个简单的例子:

建立程序add.c

int Add(int a,int b)

{

int result;

result=a+b;

return result;

}

建立程序minus.c

int Minus(int a ,int b)

{

int result;

result=a‐b;

return result;

}

执行命令:

gcc –c add.c minus.c ‐c的含义是只编译生成object文件,生成add.o和minus.o

ar rv libtest.a add.o minux.o 生成一个libtest.a的库文件

将libtest.a文件拷贝到/usr/lib/下,下面我们编写一个测试程序来验证一下我的库文件是否好用。

建立test_ar.c文件用于测试

#include

int main(int argc,char *argv[])

{

int a=10;

int b=9;

printf("a=%d\t b=%d\n",a,b);

int sum=Add(a,b);

printf("a+b=%d\n",sum);

int cha=Minus(a,b);

printf("a‐b=%d\n",cha);

return 0;

}

这个程序调用了我们自己做的库文件中的函数Add()和Minus(),编译测试程序,命令如下:

gcc ‐o test_ar test_ar.c ‐ltest

‐ltest就是链接刚才的生成库文件,这样就可以使用库文件中的函数了,编译生成test_ar可执行文件,运行结果如下:

a=10 b=9

a+b=19

a‐b=1

t : 显示archive中member的内容,若不指定member,则列出所有。

v : 与t结合使用时,显示member的详细信息。

r :将参数“member…”指定的文件列表插入归档文件。

nm

nm用来列出目标文件中的符号,可以帮助程序员定位和分析执行程序和目标文件中的符号信息和它的属性。 如果没有目标文件作为参数传递给nm, nm假定目标文件为a.out. 这里用一个简单的示例程序来介绍nm的用法:

通过如下的命令可以查看nm的帮助

nm ‐h

还是利用刚才我们那个ar的测试例子,来分析nm的功能,执行如下的命令,相应的输出结果如下:

#gcc –c test_ar.c 产生test_ar.o文件

# nm test_ar.o

U Add 说明没有定义Add()函数

00000000 T main 说明定义了main()函数

U Minus 说明没有定义Minus()函数

U printf 说明没有定义printf()函数,实际printf函数定义在libc.a # nm add.o

00000000 T Add 说明定义了Add()函数

# nm minus.o

00000000 T Minus 说明定义了Minus()函数

objcopy

objcopy可以将一种格式的目标文件转化为另外一种格式的目标文件. 它使用GNU BFD库进行读/写目标文件.使用BFD, objcopy就能将原格式的目标文件转化为不同格式的目标文件. 以我们在nm中使用的test_ar.o目标文件和test_ar可执行为例:

#file test_ar.o test_ar

file命令用来判别文件类型, 输出如下:

test_ar.o: ELF 32‐bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

test_ar: ELF 32‐bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, not stripped

现在运行objcopy来改变test_ar的文件类型: 原先它是ELF格式的可执行程序, 现将它转换为srec格式. srec格式文件是Motolora S‐Record格式的文件, 主要用来在主机和目标机之间传输数据.

#objcopy -O srec test_ar ts_objcopy

#file ts_objcopy

ts_objcopy: Motorola S-Record; binary data in text format

执行完后,生成一个ts_objcopy文件,查看其文件格式发生了变化。

注意objcopy的格式, "‐O"指定输出文件类型; 输入文件名和输出文件名位于命令末尾.

objdump

objdump用来显示目标文件的信息. 可以通过选项控制显示那些特定信息. objdump一个最大的用处恐怕就是将C代码反汇编了. 在嵌入式软件开发过程中, 也可以用它查看执行文件或库文件的信息.

下面我们用上文提到的test_ar可执行文件和ts_objcopy可执行文件为例, 介绍objdump 的简单用法:

# objdump ‐f test_ar

test_ar: file format elf32‐i386

architecture: i386, flags 0x00000112:

EXEC_P, HAS_SYMS, D_PAGED

start address 0x08048310

# objdump ‐f ts_objcopy

ts_objcopy: file format srec

architecture: UNKNOWN!, flags 0x00000000:

‐f : 显示目标文件的头文件概要信息.

生成反汇编代码,比如前面的add.o文件:

# objdump -d add.o

add.o: file format elf32-i386

Disassembly of section .text:

00000000 :

0: 55 push %ebp

1: 89 e5 mov %esp,%ebp

3: 83 ec 10 sub $0x10,%esp

6: 8b 45 0c mov 0xc(%ebp),%eax

9: 03 45 08 add 0x8(%ebp),%eax

c: 89 45 fc mov %eax,0xfffffffc(%ebp)

f: 8b 45 fc mov 0xfffffffc(%ebp),%eax

12: c9 leave

13: c3 ret

‐d : 显示目标文件中机器指令使用的汇编语言. 只反汇编那些应该含有指令机器码的节(显示.text段); 如果用‐D, 则反汇编所有节的内容.

readelf

readelf用来显示ELF格式目标文件的信息.可通过参数选项来控制显示哪些特定信息.下面利用先前的test_ar可执行文件演示readelf的简单用法:

# readelf -h test_ar

ELF Header:

Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

Class: ELF32

Data: 2's complement, little endian

Version: 1 (current)

OS/ABI: UNIX - System V

ABI Version: 0

Type: EXEC (Executable file)

Machine: Intel 80386

Version: 0x1

Entry point address: 0x8048310

Start of program headers: 52 (bytes into file)

Start of section headers: 3328 (bytes into file)

Flags: 0x0

Size of this header: 52 (bytes)

Size of program headers: 32 (bytes)

Number of program headers: 8

Size of section headers: 40 (bytes)

Number of section headers: 35

Section header string table index: 32

注意: readelf只能用于ELF格式目标文件, 且选项中至少要指定一个(除V, H外)的选项!

‐h 显示包含在文件开始出的ELF头中的信息

as

GNU汇编器,主要用于把汇编代码转化成二进制代码,并存放到一个object文件中。

参看PPT中的实例,这里简单举个例子,将刚才的add.c文件汇编,查看其中的内容。

#gcc ‐S add.c 生成汇编代码

#cat a dd.s 查看汇编代码

.file "add.c"

.text

.globl Add

.type Add, @function

Add:

pushl %ebp

movl %esp, %ebp

subl $16, %esp

movl 12(%ebp), %eax

addl 8(%ebp), %eax

movl %eax, ‐4(%ebp)

movl ‐4(%ebp), %eax

leave

ret

.size Add, .‐Add

.ident "GCC: (GNU) 4.1.0 (SUSE Linux)"

.section .note.GNU‐stack,"",@progbits

#as ‐o add.o add.s 有汇编器从汇编代码生成目标代码

size

显示一个目标文件或者链接库文件中的目标文件的各个段的大小,当没有输入文件名时,默认为a.out,两个参数,分别为‐A和‐B

使用举例:

#Size test_ar ‐A

test_ar :

section size addr

.interp 19 134512948

.note.ABI‐tag 32 134512968

.note.SuSE 24 134513000

.hash 44 134513024

.dynsym 96 134513068

.dynstr 96 134513164

.gnu.version 12 134513260

.gnu.version_r 32 134513272

.rel.dyn 8 134513304

.rel.plt 24 134513312

.init 23 134513336

.plt 64 134513360

.text 524 134513424

.fini 28 134513948

.rodata 36 134513976

.eh_frame 4 134514012

.ctors 8 134518112

.dtors 8 134518120

.jcr 4 134518128

.dynamic 200 134518132

.got 4 134518332

.got.plt 24 134518336

.data 12 134518360

.bss 4 134518372

.comment 279 0

.debug_aranges 88 0

.debug_pubnames 37 0

.debug_info 401 0

.debug_abbrev 98 0

.debug_line 311 0

.debug_str 165 0

Total 2709

#size test_ar –B

text data bss dec hex filename

1066 260 4 1330 532 test_ar

strip

strip用来丢弃目标文件中的全部或者特定符号,减小文件体积。对于嵌入式系统,这个命令必不可少。文件一旦strip后就不能恢复原样了,所以strip是一个减肥工具而不是压缩工具。而且,被strip后的文件不包含调试信息。

注:

1.如果文件大小没有减小,那就是已经strip过了.

https://www.360docs.net/doc/3113424667.html, 编译时加上"‐s"参数,具有同样的作用。

举例说明:

在实验环境中建立测试程序test_strip.c

test_strip.c程序清单:

#include

int main(viod)

{

printf("I want to test strip!\n");

return 0;

}

执行命令编译:

#gcc test_strip.c ‐o test_strip

# ll test_strip

‐rwxr‐xr‐x 1 root root 6512 2009‐04‐10 14:46 test_strip

# strip test_strip

#ll test_strip

‐rwxr‐xr‐x 1 root root 2980 2009‐04‐10 14:48 test_strip

通过上面的操作,我们看到应用程序确实小了很多哦!

慎用strip命令(提高的部分,征求同学的意见是否提及)

目标文件分为:可重定位文件、可执行文件、共享文件

strip的默认选项会去除.symbol节的内容以及.debug节的内容,因此尽量只对可执行文件执行strip而不要对静态库或动态库等目标文件strip。这里我们还是根据前面的加法的例子进行试验,看看我们要是对库文件strip了,会怎样呢?

试验过程和步骤:

#gcc ‐c add.c minus.c

#ar rcs libcmp.a add.o minus.o

#gcc ‐o test main.c libcmp.a

#gcc ‐shared ‐fPIC ‐o libcmp.so max.c min.c

#cp libcmp.a libcmp.a.bak

#cp libcmp.so libcmp.so.bak

#cp test test.orig

#strip libcmp.a libcmp.so

#strip test

#gcc –o test_ar test_ar.c libcmp.a

会报错,说您的库文件里没有您需要的函数定义

#ls ‐l

可见无论是静态库(lib.a)还是动态库(lib.so)还是可执行文件(test),去掉一些符号信息后都减小了很多,但如果这时再链接这两个库的话是编不过的,因此,如果不是指定特殊的strip 选项的话,还是尽量不要对库文件strip,只对链接后的可执行文件strip就可以了(如果也不调试)。

strings

显示整个文件中的字符串

参看PPT中的例子

addr2line

addr2line能够把程序地址转换为文件名和行号,前提是这个可执行文件包括调试符号。 如果可执行文件中没有包括调试符号,shell将返回??:0。

Addr2line 工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。这种功能对于将跟踪地址转换成更有意义的内容来说简直是太棒了。

要了解这个过程是怎样工作的,我们可以试验一个简单的交互式的例子。(我直接从 shell 中进行操作,因为这是最简单地展示这个过程的方法,如清单 4 所示。)这个示例 C 文件(test.c)是通过 cat 一个简单的应用程序实现的(也就是说,将标准输出的文本重定向到一个文件中)。然后使用 gcc 来编译这个文件,它会传递一些特殊的选项。首先,要(使用 ‐Wl 选项)通知链接器生成一个映像文件,并(使用 ‐g 选项)通知编译器生成调试符号。最终生成可执行文件 test。得到新的可执行应用程序之后,您就可以使用 grep 工具在映像文件中查找 main 来寻找它的地址了。使用这个地址和 Addr2line 工具,就可以判断出函数名(main)、源文件(/home/mtj/test/test.c)以及它在源文件中的行号(4)。

在调用 Addr2line 工具时,要使用 ‐e 选项来指定可执行映像是 test。通过使用 ‐f 选项,可以告诉工具输出函数名。

$ gcc -Wl,-Map=test.map -g -o test test.c

$ grep main test.map

0x08048258 __libc_start_main@@GLIBC_2.0

0x08048258 main

$ addr2line 0x08048258 -e test -f

main

/home/mtj/test/test.c:4

最常用的选项是“‐e”用来指定文件名和地址。

可以将指令地址,可执行映像转化成文件名,函数名和源代码函数的工具。

作用:跟踪地址,将地址转化成更有意义的内容。

参看PPT中的例子

交叉编译环境的建立(基于ubuntu 8.10)

Ubuntu 8.10建立交叉编译工具链的主机环境:

2.6.27-7-generic-Ubuntu 8.10-64 bit , gcc-4.

3.2 , make 3.81-5

保证你的 Ubuntu 8.10 安装了如下的软件:

Bison flex build-essential patch libncurses5-dev

其中 Bison flex 是本人亲试必需软件,这些软件一定要事先安装好,否则可能会出错,然后只能重新编译

本方案所选软件包如下:

gcc-3.4.5.tar.gz

glibc-2.3.6.tar.gz

linux-2.6.26.5.tar.gz

crosstool-0.43.tar.gz

binutils-2.15.tar.gz

glibc-linuxthreads-2.3.3.tar.gz

linux-libc-headers-2.6.12.0.tar.bz2

可用的搭配方案可参考《 Crosstool build results 》

1. Ubuntu 8.10 默认安装的 gcc 版本为4.3.2,根据多人反映,用此版本编译会出错,目前不宜选用

于是选择了 gcc-4.1.1 ,但并不需要卸载 gcc-4.3.2

在 Ubuntu 8.10 不要去下 gcc-4.1.1 的源码来编译(自行下载源码编译会发现遇到更多的问题),直接在终端输入

sudo apt-get install gcc-4.1

安装就可以了

然后是

sudo rm /usr/bin/gcc (删除GCC,它只是个到gcc-4.3.2的软链接文件) sudo ln -s /usr/bin/gcc-4.1 /usr/bin/gcc (建立GCC到gcc-4.1的软链接)

编译完成后可以运行以下命令修改回来

sudo rm /usr/bin/gcc

sudo ln -s /usr/bin/gcc-4.3 /usr/bin/gcc

如果运行

ls -la /bin/sh

看到链接的是 dash ,则请运行以下命令

sudo dpkg-reconfigure dash

选择 no 以删除 dash ,编译完成可再运行此命令选择 yes 以重新安装 dash 此处如果不改好的话,编译时会出现错误

1)解压软件包,并进入该目录,查看重要的脚本文件。

$cd downloads

$tar –zxvf crosstool-0.43.tar.gz

$cd crosstool-0.43

在此目录下可以看到有很多.sh脚本和.dat配置文件,每一个支持的处理器都有它所相应的脚本。假如选用demo-arm-softfloat.sh 就是建立目标为支持软浮点的arm交叉编译工具链。

2)修改demo-arm-softfloat.sh

$vim demo-arm-softfloat.sh

修改下面两句

TARBALLS_DIR=$HOME/downloads //表示下载的源码的存放目录

RESULT_TOP=/opt/crosstools //表示生成的工具链的存放目录

为:

TARBALLS_DIR=/(downloads所在目录)

RESULT_TOP=/(crosstools所在目录)

3)修改 gcc-3.4.5-glibc-2.3.6.dat

$ vim gcc-3.4.5-glibc-2.3.6.dat

修改内容为:

BINUTILS_DIR=binutils-2.15

GCC_DIR=gcc-3.4.5

GLIBC_DIR=glibc-2.3.6

LINUX_DIR=linux-2.6.26.5

LINUX_SANITIZED_HEADER_DIR=linux-libc-headers-2.6.12.0 GLIBCTHREADS_FILENAME=glibc-linuxthreads-2.3.6

4)$ ./ demo-arm-softfloat.sh

这个过程较长(半个小时作用)

编译会出一个错误 (这个是在编译过程中产生,所以无法事先解决。约30分钟)。修改

build/arm-softfloat-linux-gnu/gcc-3.4.5-glibc-2.3.6/build-glibc/csu/v ersion-info.h

为:

"Compiled on a Linux >>2.6.20-15-generic<< system on 2008-01-30.\n"

"Available extensions:\n"

"\n"

" GNU libio by Per Bothner\n"

" crypt add-on version 2.1 by Michael Glad and others\n"

" linuxthreads-0.10 by Xavier Leroy\n"

" BIND-8.2.3-T5B\n"

" libthread_db work sponsored by Alpha Processor Inc\n"

" NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk\n"

然后必须在eval `cat arm-softfloat.dat gcc-3.4.5-glibc-2.3.6.dat` sh all.sh --notest 末尾处加--nounpack表示不重新解压安装包,目的是让安装过程继续进行,而不覆盖掉以前的编译结果。

继续执行:$ ./ demo-arm-softfloat.sh

约1小时后,编译完毕。在利用它编译内核之前还要设置环境变量,及设置内核

5)在当前用户目录的.bashrc中添加如下内容

$export

PATH=$PATH:/home/linux/crosstool/gcc-3.4.5-glibc-2.3.6/arm-softfloat-linux-gnu/bin:

6)执行如下命令

$ arm-softfloat-linux-gnu-gcc -v

显示

Reading specs from

/home/david/project/crosstool/gcc-3.4.5-glibc-2.3.6/arm-softfloat-lin ux-gnu/lib/gcc/arm-softfloat-linux-gnu/3.4.5/specs

Configured with:

/home/david/downloads/crosstool-0.43/build/arm-softfloat-linux-gnu/gc

c-3.4.5-glibc-2.3.6/gcc-3.4.5/configure

--target=arm-softfloat-linux-gnu --host=i686-host_pc-linux-gnu

--prefix=/home/david/project/crosstool/gcc-3.4.5-glibc-2.3.6/arm-soft float-linux-gnu --with-float=soft

--with-headers=/home/david/project/crosstool/gcc-3.4.5-glibc-2.3.6/ar

m-softfloat-linux-gnu/arm-softfloat-linux-gnu/include

--with-local-prefix=/home/david/project/crosstool/gcc-3.4.5-glibc-2.3 .6/arm-softfloat-linux-gnu/arm-softfloat-linux-gnu --disable-nls

--enable-threads=posix --enable-symvers=gnu --enable-__cxa_atexit

--enable-languages=c,c++ --enable-shared --enable-c99

--enable-long-long

Thread model: posix

gcc version 3.4.5

ok交叉编译环境创建成功!

在虚拟机下Ubuntu建立NFS网络文件系统

在ubuntu上默认没有安装NFS服务器,因此:

apt-get install nfs-kernel-server

apt-get install nfs-common

NFS服务程序和客户端程序安装完成。

上面的两个服务程序已经给大家安装好了,默认它是正常的。

配置NFS相关的IP地址(由于我们是XP下的VMware下的Ubuntu,稍复杂):

PC机的windows下的网络连接地址:192.168.1.100,这个应该都会设置吧!

在VMware->Settings->Network Adapter->bridged,选上。Device status的连接全部选上

OK在linux下设置IP地址,一定和windows在同一个网段,例如:192.168.1.10

测试一下windows和linux通信正常吗?

运行命令:#ping 192.168.1.100

配置/etc/exports

运行命令:#gedit /etc/exports

在文件的最后添加如下一句话:

/root (rw,sync,no_root_squash) //这一步可能比较关键的,我之前括号里都只是写了(rw),结果一直都不行。

共享/root目录内容.且有读,写权限, 并且该用户进入/root目录后的身份为root

当然你的root里面一定有可以正常工作的文件系统哦

运行 #showmount -e 查看NFS server的export list.

若更改了/etc/exports, 运行#sudo exportfs -r 更新

运行#sudo /etc/init.d/nfs-kernel-server restart 重启nfs服务

以上若有错误,说明nfs还是没有完全配置好,但是不影响后面的操作

测试NFS:

可以尝试一下挂载本地磁盘(假设本地主机IP地址为:192.168.1.10., 将/root挂载到/mnt) #mount 192.168.1.10:/root /mnt

运行#df 看看结果

若想卸载刚才挂载的文件系统,运行如下命令:

# umount /mnt

现在可以通过NFS启动系统了

因为我用的uboot可以传启动参数给内核,所以还可以直接uboot引导内核,直接自动挂载nfs文件系统

附件:

一、分区信息 0 256K 2M 32M 64M

uboot kernel root user

二、flash启动方式

在串口终端:

setenv serverip 192.168.1.***

setenv ipaddr 192.168.1.***

setenv gatewayip 192.168.1.1

setenv ethaddr 11:22:33:44:55:66

tftp 30008000 zImage‐2.6.8.1

nand erase 40000 1c0000

nand write 30008000 40000 1c0000

tftp 30008000 root.cramfs

nand erase 200000 1e00000

nand write 30008000 200000 1e00000

setenv bootargs root=1f02 console=ttySAC0,115200 init=/linuxrc devfs=mount display=sam240 setenv bootcmd nand read 30008000 40000 1c0000 \; go 30008000

saveenv

三、网络启动方式

在串口终端:

setenv serverip 192.168.1.***

setenv ipaddr 192.168.1.***

setenv gatewayip 192.168.1.1

setenv ethaddr 11:22:33:44:55:66

setenv bootcmd tftp 30008000 zImage\; go 30008000

setenv bootargs root=nfs nfsroot=192.168.1.23:/source/rootfs ip=192.168.1.134 console=ttySAC0,115200 init=/linuxrc devfs=mount display=sam240

saveenv

U‐boot常用命令:

Printenv 打印环境变量。

Uboot> printenv

baudrate=115200

ipaddr=192.168.1.1

ethaddr=12:34:56:78:9A:BC

serverip=192.168.1.5

Environment size: 80/8188 bytes

Setenv 设置新的变量

Saveenv 保存变量

命令将当前定义的所有的变量及其值存入flash中。用来存储变量及其值的空间只有8k字节,应不要超过。

Loadb 通过串口Kermit协议下载二进制数据。

Tftp通过网络下载程序,需要先设置好网络配置

Uboot> setenv ethaddr 12:34:56:78:9A:BC

Uboot> setenv ipaddr 192.168.1.1

Uboot> setenv serverip 192.168.1.254 (tftp服务器的地址)

下载bin文件到地址0x20000000处。

Uboot> tftp 20000000 application.bin (application.bin应位于tftp服务程序的目录)Uboot> tftp 32000000 vmlinux

把server(IP=环境变量中设置的serverip)中/tftpdroot/ 下的vmlinux通过TFTP读入到物理内存32000000处。

Md 显示内存区的内容。

Mm 修改内存,地址自动递增。

Nm 修改内存,地址不自动递增。

Mw 用模型填充内存

mw 32000000 ff 10000(把内存0x32000000开始的0x10000字节设为0xFF)

Cp 拷贝一块内存到另一块

Cmp 比较两块内存区

这些内存操作命令后都可加一个后缀表示操作数据的大小,比如cp.b表示按字节拷贝。Protect 写保护操作

protect on 1:0-3(就是对第一块FLASH的0-3扇区进行保护)

protect off 1:0-3取消写保护

Erase 擦除扇区。

erase: 删除FLASH的扇区

erase 1:0-2(就是对每一块FLASH的0-2扇区进行删除)

对DataFlash的操作

U-Boot在引导时如果发现NPCS0和NPCS3上连有DataFlash,就会分配虚拟的地址给它,具体为 :0xC0000000---NPCS0

0xD0000000---NPCS3

run 执行设置好的脚本

Uboot> setenv flashit tftp 20000000 mycode.bin\; erase 10020000 1002FFFF\;

cp.b 20000000 10020000 8000

Uboot> saveenv

Uboot> run flashit

bootcmd 保留的环境变量,也是一种脚本

如果定义了该变量,在autoboot模式下,将会执行该脚本的内容。

Go 执行内存中的二进制代码,一个简单的跳转到指定地址

Bootm 执行内存中的二进制代码

要求二进制代码为制定格式的。通常为mkimage处理过的二进制文件。

起动UBOOT TOOLS制作的压缩LINUX内核, bootm 3200000

Bootp通过网络启动,需要提前设置好硬件地址。

? 得到所有命令列表

help help usb, 列出USB功能的使用说明

ping 注:只能开发板PING别的机器

usb

usb start: 起动usb 功能

usb info: 列出设备

usb scan: 扫描usb storage(u 盘)设备

kgo 起动没有压缩的linux内核

kgo 32000000

fatls 列出DOS FAT文件系统

fatls usb 0列出第一块U盘中的文件

fatload 读入FAT中的一个文件

fatload usb 0:0 32000000 aa.txt 把USB中的aa.txt 读到物理内存0x32000000处!

flinfo 列出flash的信息

nfs

nfs 32000000 192.168.0.2:aa.txt

把192.168.0.2(LINUX 的NFS文件系统)中的NFS文件系统中的aa.txt 读入内存0x32000000处。

Bootloader技术

Bootloader 简介

`什么是Bootloader

`Bootloader的特点、工作模式、基本功能

`Bootloader的启动过程

`目前典型Bootloader简介

`U‐boot 介绍

`U‐boot 简介(出处、下载代码、代码结构)

`U‐boot 启动流程及代码分析

`U‐boot 的编译和移植

`U‐boot 的下载烧录和使用

Bootloader的定义和特点

Bootloader通俗的讲是系统启动时运行的第一段程序,类似于PC机的BIOS和位于硬盘MBR中的引导程序共同其的作用,只不过是我们的bootloader通常只存在于Flash中而已,

上电由CPU自动搬到RAM中运行而已。其作用主要是在内核运行之前,初始化硬件设备、

建立内存空间映射,为操作系统运行做好准备,然后加载操作系统。嵌入式的bootloader

除了上面提到的功能,一般它还有下载系统,调试系统等扩展功能。目前的bootloader和硬

件紧密相关,所有的功能几乎依赖于所有的硬件资源,所以bootloader的移植性和可重用性

都非常的差。

Bootloader的工作模式和工作流程

工作模式

大多数bootloader都包含两种不同的操作模式(通常只有开发人员才会关心,所以这里讲讲): 启动模式:bootloader从目标机上的固态存储设备上将操作系统加载到RAM中运 行,整个过程没有用户介入,这也是正常的产品发布时的状态

下载模式:通过USB、网络、串口等通信手段将系统的内核文件等下载得到RAM

中的方式,通常只有开发人员才会用到。例如uboot有网口,目前板子上的bios

用usb口和串口都行。

Bootloader的工作流程:

首先我们做一个假定,那就是:假定内核映像与根文件系统映像都被加载到 RAM 中运行。之所以提出这样一个假设前提是因为,在嵌入式系统中内核映像与根文件系统映像也可

以直接在 ROM 或 Flash 这样的固态存储设备中直接运行(XIP技术,大家有兴趣可以参考)。

但这种做法无疑是以运行速度的牺牲为代价的。

从操作系统的角度看,Bootloader的总目标就是正确地调用内核来执行。 另外,由于 Bootloader 的实现依赖于 CPU 的体系结构,因此大多数 Bootloader 都分为 stage1 和 stage2 两大部分。依赖于 CPU 体系结构的代码,比如设备初始化代码等,通常都放在 stage1 中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而 stage2 则通常用C语言来

实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。

Boot Loader 的 stage1 通常包括以下步骤(以执行的先后顺序):

硬件设备初始化。

为加载 Bootloader的 stage2 准备 RAM 空间。

拷贝 Bootloader 的 stage2 到 RAM 空间中。

设置好堆栈。

跳转到 stage2 的 C 入口点。

Bootloader 的 stage2 通常包括以下步骤(以执行的先后顺序):

初始化本阶段要使用到的硬件设备。

检测系统内存映射(memory map)。

将 kernel 映像和根文件系统映像从 flash 上读到 RAM 空间中。

为内核设置启动参数。

调用内核。

这么和大家描述了上面的Bootloader的启动过程,相信大家应该有了一个模糊的认识了,下面我们将细化我们的描述,使大家达到清楚的目标。

目前典型的bootloader简介,参看PPT297

上面已经介绍了关于Bootloader的概念和一些常见的Bootloader,这里引入U‐boot,开始详细介绍U‐boot。

U‐boot(Universal Bootloader),遵循GPL条款的开源项目,由armboot和ppcboot演化而来,所以其源码目录结构和Linux和相似,目前支持的操作系统,Linux、VxWorks、QNX 和wince等。支持的CPU包括:MIPS、x86、ARM、Xscale等。几乎所有常用的微处理器

u‐boot目录结构,和linux非常的相似:

board:目标板相关的文件,主要是sdram和flash的驱动

common:独立于处理器体系结构的通用代码,例如内存大小检测和故障检测等

cpu:与处理器相关的文件

driver:通用的设备驱动

doc:u‐boot的相关文档

example:可以在u‐boot下运行的事例程序,例如hello.c等

include:u‐boot的头文件,尤其是configs文件夹下的和目标板相关的配置头文件,是移植过程中经常要修改的文件。

Lib_xxx:处理器体系结构相关的文件

net:有网络功能相关的代码,例如tftp功能

post:上电自检目录

tools:用于创建u‐boot等镜像文件的工具。

u‐boot代码分析

大多数的Bootloader都分为stage1和stage2两部分,u‐boot也不例外,依赖于CPU体系结构的代码通常放在stage1中,且通常用汇编语言实现,stage2是功能部分,通常用c 语言是想,这样可以实现复杂的功能和很好可移植性。

都知道U‐BOOT分为两个阶段,第一阶段是(~/cpu/arm920t/start.S中)在FLASH上运行(一般情况下),完成对硬件的初始化, 包括看门狗,中断缓存等,并且负责把代码搬移到SDRAM中

嵌入式Linux应用软件开发流程

从软件工程的角度来说,嵌入式应用软件也有一定的生命周期,如要进行需求分析、系统设计、代码编写、调试和维护等工作,软件工程的许多理论对它也是适用的。 但和其他通用软件相比,它的开发有许多独特之处: ·在需求分析时,必须考虑硬件性能的影响,具体功能必须考虑由何种硬件实现。 ·在系统设计阶段,重点考虑的是任务的划分及其接口,而不是模块的划分。模块划分则放在了任务的设计阶段。 ·在调试时采用交叉调试方式。 ·软件调试完毕固化到嵌入式系统中后,它的后期维护工作较少。 下面主要介绍分析和设计阶段的步骤与原则: 1、需求分析 对需求加以分析产生需求说明,需求说明过程给出系统功能需求,它包括:·系统所有实现的功能 ·系统的输入、输出 ·系统的外部接口需求(如用户界面) ·它的性能以及诸如文件/数据库安全等其他要求 在实时系统中,常用状态变迁图来描述系统。在设计状态图时,应对系统运行过程进行详细考虑,尽量在状态图中列出所有系统状态,包括许多用户无需知道的内部状态,对许多异常也应有相应处理。 此外,应清楚地说明人机接口,即操作员与系统间地相互作用。对于比较复杂地系统,形成一本操作手册是必要的,为用户提供使用该系统的操作步骤。为使系统说明更清楚,可以将状态变迁图与操作手册脚本结合起来。

在对需求进行分析,了解系统所要实现的功能的基础上,系统开发选用何种硬件、软件平台就可以确定了。 对于硬件平台,要考虑的是微处理器的处理速度、内存空间的大小、外部扩展设备是否满足功能要求等。如微处理器对外部事件的响应速度是否满足系统的实时性要求,它的稳定性如何,内存空间是否满足操作系统及应用软件的运行要求,对于要求网络功能的系统,是否扩展有以太网接口等。 对于软件平台而言,操作系统是否支持实时性及支持的程度、对多任务的管理能力是否支持前面选中的微处理器、网络功能是否满足系统要求以及开发环境是否完善等都是必须考虑的。 当然,不管选用何种软硬件平台,成本因素都是要考虑的,嵌入式Linux 正是在这方面具有突出的优势。 2、任务和模块划分 在进行需求分析和明确系统功能后,就可以对系统进行任务划分。任务是代码运行的一个映象,是无限循环的一段代码。从系统的角度来看,任务是嵌入式系统中竞争系统资源的最小运行单元,任务可以使用或等待CPU、I/O设备和内存空间等系统资源。 在设计一个较为复杂的多任务应用系统时,进行合理的任务划分对系统的运行效率、实时性和吞吐量影响都极大。任务分解过细会不断地在各任务之间切换,而任务之间的通信量也会很大,这样将会大大地增加系统的开销,影响系统的效率。而任务分解过粗、不够彻底又会造成原本可以并行的操作只能按顺序串行执行,从而影响系统的吞吐量。为了达到系统效率和吞吐量之间的平衡折中,在划分任务时应在数据流图的基础上,遵循下列步骤和原则:

Linux网络设备驱动开发实验

实验三:Linux网络设备驱动开发实验 一、实验目的 读懂linux网络设备驱动程序例子,并且实际加载驱动程序,加载进操作系统以后,会随着上层应用程序的触发而执行相应动作,具体执行的动作可以通过代码进行改变。 ●读懂源码及makefile ●编译驱动程序 ●加载 ●多种形式触发动作 二、预备知识 熟悉linux驱动基本原理,能读懂简单的makefile。 三、实验预计时间 80-120分钟左右 四、驱动程序部分具体步骤 要求读懂一个最简单的驱动程序,在驱动程序的诸如“xxx_open”、“xxx_read”等标准接口里面加入打印语句。可参考多模式教学网上的驱动样例。 五、用于触发驱动动作的应用程序及命令 驱动程序就是以静态的标准接口库函数形式存在,网络设备驱动会受到两大类情况的触发,一种是linux里面的控制台里面的命令,另一种是套接口应用程序,首先要搞清都有哪些具体的命令和应用程序流程,应用程序参考多模式教学网的例子。 六、运行测试 提示:需要将驱动程序以dll加载进系统中,并且触发应用程序调用各种文件操作的接口函数,使得驱动有所动作,打印出相关信息。 1.编译驱动: cd /某某目录/vnetdev/ make clean make 2.加载驱动与打开网卡: insmod netdrv.ko

ifconfig vnet0 up 3.运行应用程序 ../raw 4.通过命令“修改网卡MTU”触发驱动执行动作: ifconfig vnet0 mtu 1222 5.显示内核打印: cat /var/log/messages 6.卸载: ifconfig vnet0 down rmmod netdrv.ko 7.修改代码中的某些函数中的打印信息,重新试验上述流程。 至此大家都应该真正理解和掌握了驱动程序-操作系统-应用程序的三者联动机制。 七、实验结果 由图可知能正常加载网卡驱动,并且能够打印调试信息。

嵌入式linux基本操作实验一的实验报告

实验一linux基本操作实验的实验报告 一实验目的 1、熟悉嵌入式开发平台部件,了解宿主机/目标机开发模式; 2、熟悉和掌握常用Linux的命令和工具。 二实验步骤 1、连接主机和目标板;(三根线,网线直接连接实验箱和PC机,实验箱UART2连接主机的UART口)。 2、Linux命令的熟悉与操作 PC端:在PC机的桌面上打开虚拟机,并启动Linux系统,打开命令终端,操作Linux基本命令,如:查看:ls,进入目录:cd,创建文件:mkdir,删除文件:rmdir,配置网络:ifconfig,挂载:mount,设置权限:chmod,编辑器:vi,拷贝:cp等命令,要求能熟练操作。 使用方法: 1.查看:ls Ls列出文件和目录 Ls–a 显示隐藏文件 Ls–l 显示长列格式ls–al 其中:蓝:目录;绿:可执行文件;红:压缩文件;浅蓝:链接文件;灰:其他文件;红底白字:错误的链接文件 2.进入目录:cd 改变当前目录:cd 目录名(进入用户home目录:cd ~;进入上一级目录:cd -) 3.创建文件:mkdir 建立文件/目录:touch 文件名/mkdir目录名 4.删除文件:rmdir 删除空目录:rmdir目录名 5.配置网络:ifconfig 网络- (以太网和WIFI无线) ifconfig eth0 显示一个以太网卡的配置 6.挂载:mount mount /dev/hda2 /mnt/hda2 挂载一个叫做hda2的盘- 确定目录'/ mnt/hda2' 已经存在 umount /dev/hda2 卸载一个叫做hda2的盘- 先从挂载点'/ mnt/hda2' 退出fuser -km /mnt/hda2 当设备繁忙时强制卸载 umount -n /mnt/hda2 运行卸载操作而不写入/etc/mtab文件- 当文件为只读或当磁盘写满时非常有用 mount /dev/fd0 /mnt/floppy 挂载一个软盘 mount /dev/cdrom /mnt/cdrom挂载一个cdrom或dvdrom mount /dev/hdc /mnt/cdrecorder挂载一个cdrw或dvdrom mount /dev/hdb /mnt/cdrecorder挂载一个cdrw或dvdrom mount -o loop file.iso /mnt/cdrom挂载一个文件或ISO镜像文件

嵌入式Linux系统中音频驱动的设计与实现

第31卷 第2期 2008年4月 电子器件 Ch in es e Jo u rnal Of Electro n Devi ces Vol.31 No.2Apr.2008 Design and Implementation of Audio Driver for Embedded Linux System YU Yue,YA O G uo -liang * (N ational A S I C S ystem Eng ine ering Center ,S outhe ast Unive rsity ,N anj ing 210096,China) Abstract:This paper intro duces the fundam ental principle and architecture of the audio system w hich con -sists of the CODEC UCB1400and the 805puls,and describes the design of audio dev ice dr iv er based on Audio Codec .97for Embedded Linux System.The paper focuses o n the implementatio n of the DM A trans -port and ioctl interface.T he audio dr iv e is running w ell in actual Embedded Linux system equipments.Key words:805plus;embedded Linux;Audio A C .97driver;DM A;ioctl interface EEACC :1130B 嵌入式Linux 系统中音频驱动的设计与实现 虞 跃,姚国良 * (东南大学国家专用集成电路系统工程中心,南京210096) 收稿日期:2007-07-09 作者简介:虞 跃(1982-),男,东南大学电子工程系国家专用集成电路工程技术研究中心硕士研究生,研究方向为嵌入式系统设计; 姚国良(1979-),男,东南大学电子工程系博士研究生,yuyueo@https://www.360docs.net/doc/3113424667.html,. 摘 要:介绍了由805puls 处理器和U CB1400编解码芯片构成的音频系统体系结构及工作原理,接着阐述了嵌入式Linux 操作系统下基于A C .97协议标准的音频设备驱动程序的设计与实现。其中着重讲述了采用循环缓冲区进行音频数据的DM A 传输流程以及ioctl 接口的实现。此设计方案已在嵌入式L inux 系统中得到使用,运行效果良好。 关键词:805plus;嵌入式L inux ;AC .97音频驱动;DM A;ioctl 接口中图分类号:TP391 文献标识码:A 文章编号:1005-9490(2008)02-0709-03 嵌入式音频系统广泛应用于GPS 自动导航、PDA,3G 手机等移动信息终端,具备播放、录音功能的音频系统的应用使得移动信息终端上视听娱乐IP 电话、音频录制等成为可能,并推动了移动信息终端设备的发展。 在软件上,嵌入式操作系统的新兴力量Linux 的开源性,内核可定制等优点吸引了许多的开发者与开发商。它是个和U nix 相似、以核心为基础的、完全内存保护、多任务多进程的操作系统。支持广泛的计算机硬件,包括X86,A lpha,Sparc,M IPS,PPC,ARM ,NEC,MOT OROLA 等现有的大部分芯片[1]。 本文针对805puls 微处理器选用Philips 公司的编解码芯片(CODEC)U CB1400,构建了基于Au -dio Codec .97(AC .97)标准的音频系统。并介绍了该音频系统在Linux 操作系统2.4.19内核下驱动 程序的实现技术。 1 音频系统构架 1.1 微处理器805plus 805plus 是东南大学ASIC 系统工程技术研究中心和北京大学微处理器研究开发中心共同设计和开发的32bit 嵌入式微处理器,是采用H ar vard 结构的RISC 处理器。内部采用五级流水线结构,兼容16bit 和32bit 的指令系统805plus 嵌入式微处理器集成了存储接口EMI,时钟和功耗管理PM C,中断控制器INTC,通用定时器T IM ER,脉宽调制器PWM,实时时钟RT C,通用串口UA RT,LCD 控制器LCDC,AC .97控制器,同步外设接口SPI 。1.2 AC .97协议标准[2] AC'97协议标准是一套关于A C'97数字音频处理(AC'97Digital Controller)、AC '97数字串口(AC

CAN总线在嵌入式Linux下驱动程序的实现

CAN总线在嵌入式Linux下驱动程序的实现 时间:2009-11-05 09:41:22 来源:微计算机信息作者:黄捷峰蔡启仲郭毅锋田小刚 1 引言 基于嵌入式系统设计的工业控制装置,在工业控制现场受到各种干扰,如电磁、粉尘、天气等对系统的正常运行造成很大的影响。在工业控制现场各个设备之间要经常交换、传输数据,需要一种抗干扰性强、稳定、传输速率快的现场总线进行通信。文章采用CAN总线,基于嵌入式系统32位的S3C44B0X微处理器,通过其SPI接口,MCP2510 CAN控制器扩展CAN总线;将嵌入式操作系统嵌入到S3C44B0X微处理器中,能实现多任务、友好图形用户界面;针对S3C44B0X微处理器没有内存管理单元MMU,采用uClinux嵌入式操作系统。这样在嵌入式系统中扩展CAN设备关键技术就是CAN设备在嵌入式操作系统下驱动程序的实现。文章重点解决了CAN总线在嵌入式操作系统下驱动程序实现的问题。对于用户来说,CAN设备在嵌入式操作系统驱动的实现为用户屏蔽了硬件的细节,用户不用关心硬件就可以编出自己的用户程序。实验结果表明驱动程序的正确性,能提高整个系统的抗干扰能力,稳定性好,最大传输速率达到1Mb/s;硬件的错误检定特性也增强了CAN的抗电磁干扰能力。 2 系统硬件设计 系统采用S3C44B0X微处理器,需要扩展CAN控制器。常用的CAN控制器有SJA1000和MCP2510,这两种芯片都支持CAN2.0B标准。SJA1000采用的总线是地址线和数据线复用的方式,但是嵌入式处理器外部总线大多是地址线和数据线分开的结构,这样每次对SJA1000操作时需要先后写入地址和数据2次数据,而且SJA1000使用5V逻辑电平。所以应用MCP2510控制器进行扩展,收发器采用82C250。MCP2510控制器特点:1.支持标准格式和扩展格式的CAN数据帧结构(CAN2.0B);2.0~8字节的有效数据长度,支持远程帧;3.最大1Mb/s的可编程波特率;4.2个支持过滤器的接受缓冲区,3个发送缓冲区; 5.SPI高速串行总线,最大5MHz; 6.3~5.5V宽电压范围供电。MCP2510工作电压为3.3V,能够直接与S3C44B0X微处理器I/O口相连。为了进一步提高系统抗干扰性,可在CAN控制器和收发器之间加一个光隔6N137。其结构原理框图如图1: 图1.S3C44B0X扩展CAN结构框图图2.字符设备注册表 3 CAN设备驱动程序的设计 Linux把设备看成特殊的文件进行管理,添加一种设备,首先要注册该设备,增加它的驱动。设备驱动程序是操作系统内核与设备硬件之间的接口,并为应用程序屏蔽了硬件细节。在linux中用户进程不能直接对物理设备进行操作,必须通过系统调用向内核提出请求,

《嵌入式系统与开发》构建嵌入式Linux系统-实验报告

《嵌入式数据库sqlite移植及使用》 实验报告 学生姓名:陈彤 学号:13004405 专业班级:130044 指导教师:孙国梓 完成时间:2016.5.31 实验3 嵌入式数据库sqlite移植及使用 一.实验目的 理解嵌入式软件移植的基本方法,掌握sqlite数据库软件移植的步骤,掌握sqlite开发的两种方式—命令模式和C代码开发模式的使用方法,并编程实现简单通讯录查询实验。 二.实验内容 实验3.1 移植嵌入式数据库sqlite 实验3.2 简单通讯录查询实例设计和测试 三.预备知识 Linux使用、数据库相关知识等 四.实验设备及工具(包括软件调试工具) 硬件:ARM 嵌入式开发平台、PC 机Pentium100 以上、串口线。 软件:WinXP或UBUNTU开发环境。 五.实验步骤 5.1 移植嵌入式数据库sqlite 步骤【参看教材103页】: 第一步,解压缩sqlite源码,命令tar zxvf sqlite-autoconf-3080900.tar.gz,在解压后的文件夹下,可以看到源码文件有shell.c 和sqlite3.c文件,生成Makefile的配置脚本文件configure.ac ,并检查当前文件夹下__A__(A.存在 B.不存在)Makefile文件。 第二步利用configure脚本文件生成基于ARM实验台的Makefile,具体命令为./configure CC=arm-linux-gcc –prefix=/opt/sqlite –host=arm-linux(假设安装目录为/opt/sqlite),并检查当前文件夹下___A__(A.存在 B.不存在)Makefile文件。 第三步,编译sqlite,命令为_make_,编译过程中使用的编译器为_ arm-linux-gcc _。 第四步,安装sqlit,命令为_make install_。安装完成后到_/opt/sqlite_文件夹下去查看相关文件,可以看到该文件夹下有_bin_、_include_、__lib__和share文件夹,其中可执行文件sqlite3位于_./bin_文件夹,库位于_./lib_文件夹。 第五步,将sqlite3拷贝到开发板bin目录下,将库下的文件拷贝到开发板的lib目录下【注意链接文件的创建】 第六步,数据库的使用 方式1:命令操纵数据库 在超级终端环境下创建数据库stucomm.db,命令为_sqlite3 stucomm.db_; 创建数据表stutable,字段包括id 整型,name 字符型,phoneNum 字符型,具体命令为_sqlite> create table stutable (id int(20),name char(20),phoneNum char(20));_; 插入2条记录,记录信息如下 001,zhangsan,10086 002,lisi,10000

南邮嵌入式系统B实验报告2016年度-2017年度-2

_* 南京邮电大学通信学院 实验报告 实验名称:基于ADS开发环境的程序设计 嵌入式Linux交叉开发环境的建立 嵌入式Linux环境下的程序设计 多线程程序设计 课程名称嵌入式系统B 班级学号 姓名 开课学期2016/2017学年第2学期

实验一基于ADS开发环境的程序设计 一、实验目的 1、学习ADS开发环境的使用; 2、学习和掌握ADS环境下的汇编语言及C语言程序设计; 3、学习和掌握汇编语言及C语言的混合编程方法。 二、实验内容 1、编写和调试汇编语言程序; 2、编写和调试C语言程序; 3、编写和调试汇编语言及C语言的混合程序; 三、实验过程与结果 1、寄存器R0和R1中有两个正整数,求这两个数的最大公约数,结果保存在R3中。 代码1:使用C内嵌汇编 #include int find_gcd(int x,int y) { int gcdnum; __asm { MOV r0, x MOV r1, y LOOP: CMP r0, r1 SUBLT r1, r1, r0 SUBGT r0, r0, r1 BNE LOOP MOV r3, r0 MOV gcdnum,r3 //stop // B stop // END } return gcdnum; } int main() { int a; a = find_gcd(18,9);

printf("gcdnum:%d\n",a); return 0; } 代码2:使用纯汇编语言 AREA example1,CODE,readonly ENTRY MOV r0, #4 MOV r1, #9 start CMP r0, r1 SUBLT r1, r1, r0 SUBGT r0, r0, r1 BNE start MOV r3, r0 stop B stop END 2、寄存器R0 、R1和R2中有三个正整数,求出其中最大的数,并将其保存在R3中。 代码1:使用纯汇编语言 AREA examp,CODE,READONL Y ENTRY MOV R0,#10 MOV R1,#30 MOV R2,#20 Start CMP R0,R1 BLE lbl_a CMP R0,R2 MOVGT R3,R0 MOVLE R3,R2 B lbl_b lbl_a CMP R1,R2 MOVGT R3,R1 MOVLE R3,R2 lbl_b B . END 代码2:使用C内嵌汇编语言 #include int find_maxnum(int a,int b,int c)

linux字符设备驱动课程设计报告

一、课程设计目的 Linux 系统的开源性使其在嵌入式系统的开发中得到了越来越广泛的应用,但其本身并没有对种类繁多的硬件设备都提供现成的驱动程序,特别是由于工程应用中的灵活性,其驱动程序更是难以统一,这时就需开发一套适合于自己产品的设备驱动。对用户而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文件,用户程序可以像对其它文件一样对此设备文件进行操作。 通过这次课程设计可以了解linux的模块机制,懂得如何加载模块和卸载模块,进一步熟悉模块的相关操作。加深对驱动程序定义和设计的了解,了解linux驱动的编写过程,提高自己的动手能力。 二、课程设计内容与要求 字符设备驱动程序 1、设计目的:掌握设备驱动程序的编写、编译和装载、卸载方法,了解设备文件的创建,并知道如何编写测试程序测试自己的驱动程序是否能够正常工作 2、设计要求: 1) 编写一个简单的字符设备驱动程序,该字符设备包括打开、读、写、I\O控制与释放五个基本操作。 2) 编写一个测试程序,测试字符设备驱动程序的正确性。 3) 要求在实验报告中列出Linux内核的版本与内核模块加载过程。 三、系统分析与设计 1、系统分析 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1、对设备初始化和释放; 2、把数据从内核传送到硬件和从硬件读取数据; 3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4、检测和处理设备出现的错误。 字符设备提供给应用程序的是一个流控制接口,主要包括op e n、clo s e(或r ele as e)、r e ad、w r i t e、i o c t l、p o l l和m m a p等。在系统中添加一个字符设备驱动程序,实际上就是给上述操作添加对应的代码。对于字符设备和块设备,L i n u x内核对这些操作进行了统一的抽象,把它们定义在结构体fi le_operations中。 2、系统设计: 、模块设计:

linux驱动程序的编写

linux驱动程序的编写 一、实验目的 1.掌握linux驱动程序的编写方法 2.掌握驱动程序动态模块的调试方法 3.掌握驱动程序填加到内核的方法 二、实验内容 1. 学习linux驱动程序的编写流程 2. 学习驱动程序动态模块的调试方法 3. 学习驱动程序填加到内核的流程 三、实验设备 PentiumII以上的PC机,LINUX操作系统,EL-ARM860实验箱 四、linux的驱动程序的编写 嵌入式应用对成本和实时性比较敏感,而对linux的应用主要体现在对硬件的驱动程序的编写和上层应用程序的开发上。 嵌入式linux驱动程序的基本结构和标准Linux的结构基本一致,也支持模块化模式,所以,大部分驱动程序编成模块化形式,而且,要求可以在不同的体系结构上安装。linux是可以支持模块化模式的,但由于嵌入式应用是针对具体的应用,所以,一般不采用该模式,而是把驱动程序直接编译进内核之中。但是这种模式是调试驱动模块的极佳方法。 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。同时,设备驱动程序是内核的一部分,它完成以下的功能:对设备初始化和释放;把数据从内核传送到硬件和从硬件读取数据;读取应用程序传送给设备文件的数据和回送应用程序请求的数据;检测和处理设备出现的错误。在linux操作系统下有字符设备和块设备,网络设备三类主要的设备文件类型。 字符设备和块设备的主要区别是:在对字符设备发出读写请求时,实际的硬件I/O一般就紧接着发生了;块设备利用一块系统内存作为缓冲区,当用户进程对设备请求满足用户要求时,就返回请求的数据。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 1 字符设备驱动结构 Linux字符设备驱动的关键数据结构是cdev和file_operations结构体。

linux应用程序开发实验报告3

实验报告 学生姓名:白迪学生学号:222014********* 日期:2016年11月15日与11月29日 院(系):计算机与信息科学学院软件学院专业(班级):网络工程实验题目:终端驱动属性编程及利用属性特性的应用程序编程 一. 实验目的 掌握终端驱动属性的特殊功能,掌握终端驱动属性的显示与修改方法编程,掌握利用终端驱动属性的特属性编写需要特殊功能的应用程序技巧。 二. 实验原理 三. 实验器材 安装有Windows操作系统PC机一台,实验环境为LINUX虚拟机(包含gcc 与gdb). 四. 实验分析与设计 补全终端设备属性位与控制字符的信息输出: Main函数

Flags的补充 显示flags函数

Setecho函数,设置echo的状态位Echostate函数。显示echo状态 Setecho函数

忽略特殊的一些按键,CTRL+C、CTRL+\,不能一直阻塞等待键盘输入,设置等待一定的时间的非阻塞。 预处理 Main函数 Tty—mode set_nodelay_mode()//没阻塞 set_nobuf_noecho_mode()//没回显,没缓冲

Getresponse() 中断处理函数 五. 实验结果 属性位与控制字符的信息输出

stty控制字符的修改功能,setecho 忽略特殊的一些按键,CTRL+C、CTRL+\,不能一直阻塞等待键盘输入,设置等待一定的时间的非阻塞。当按下的键不是y或者n就显示f。 六. 实验心得 通过本次试验中对终端文件更加的了解了,还学会了对中断文件的一些基本的设置,前面的实验做起来就是一些验证比较简单,但是收获很大,最后一个做的时候先看过书后,自己编写的,调试过程中总是出错,做到最后跟书上的代码比较发现自己的代码跟书上比差了好远,修改了很多,自己用的是Redhat5,cc—

嵌入式linux android驱动工程师 面试题总汇

嵌入式linux android驱动工程师面试题总汇 1.嵌入式系统中断服务子程序(ISR)收藏中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 2.C语言中对位的操作,比如对a的第三位清0,第四位置1.本来应该会的,一犯晕写反了,以后注意! #define BIT3 (1<<3) #define BIT4 (1<<4) a &= ~BIT3;a |= BIT4; 3.考到volatile含义并举例: 理解出错,举了很具体的例子,连程序都搬上去了,有些理解不深的没举出来…… volatile表示这个变量会被意想不到的改变,每次用他的时候都会小心的重新读取一遍,不适用寄存器保存的副本。 volatile表示直接存取原始地址 例: 并行设备的硬件寄存器(状态寄存器) 在多线程运行的时候共享变量也要时时更新 一个中断服务子程序中访问到的的非自动变量(不太清楚,正在查找资料ing……) 4.要求设置一绝对地址为0x67a9的整型变量的值为0xaa66

当时我的写法: #define AA *(volatile unsigned long *)0xaa66AA = 0x67a9; 答案: int *ptr =(int *)0xaa66; *ptr = 0x67a9; 我感觉自己写的应该不算错吧(自我感觉,还请达人指正),我写的适合裸机下用,当做寄存器用,而答案就是适合在操作系统下的写法。 1. linux内核里面,内存申请有哪几个函数,各自的区别? 2. IRQ和FIQ有什么区别,在CPU里面是是怎么做的? 3. int *a; char *b; a 和b本身是什么类型? a、b里面本身存放的只是一个地址,难道是这两个地址有不同么? 4.xx的上半部分和下半部分的问题: 讲下分成上半部分和下半部分的原因,为何要分?讲下如何实现? 5.内核函数mmap的实现原理,机制? 6.驱动里面为什么要有并发、互斥的控制?如何实现?讲个例子? 7. spinlock自旋锁是如何实现的? 8.任务调度的机制? 【二、本人碰到】

嵌入式linux实验指导书

目录 实验一 linux常用指令练习 (3) 1、在线帮助指令 (3) 2、linux开关机及注销指令。 (3) 重启指令: (3) 1)、reboot命令 (3) 2)、init 6命令 (3) 关机指令: (3) 1)、halt命令 (3) 2)、poweroff命令 (4) 3)、init 0命令 (4) 4)、shutdown命令 (4) 注销指令: (4) 3、用户管理命令 (4) 1)、用户切换su命令 (4) 2)、添加用户命令adduser/useradd (5) 3)、删除用户及更改用户属性 (5) 4)、设置用户密码 (6) 5)、查看用户信息 (6) 4、文件目录操作指令 (7) 1)、改变当前工作目录命令(cd) (7) 2)、显示当前路径pwd (7) 3)、查看当前目录下的文件命令ls (7) 4)、新建目录指令mkdir (8) 5)、删除目录命令rmdir (8) 6)、新建文件命令touch (8) 7)、删除文件指令rm (8) 8)、文件和目录的复制命令cp (8) 9)、文件和目录的移动命令mv (9) 10)、更改文件或目录的使用权限chmod (9) 11)、查看文件的命令cat (9) 12)、文件链接命令ln (9) 13)、文件压缩解压命令 (10) 5、网络相关命令 (11) 6、磁盘管理命令 (11) 7、挂载文件命令mount (12) 8、其他系统命令 (12) 练习1: (13) 练习2: (15) 练习3: (16) 练习4: (21) 实验二 VI文本编辑器的使用 (24) 1、练习使用VI指令 (24) 2、利用VI编写一个hello.c文件 (24)

嵌入式LINUX四按键驱动

对一个具有四个按键的按键驱动的分析 源代码: /*Headers-------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_DEVFS_FS #include #endif /*V ars----------------------------------------------------*/ #define DEVICE_NAME "buttons" #define EXTINT_OFF (IRQ_EINT4 - 4) unsigned int buttons_major=0; unsigned int buttons_minor=0; unsigned int type = IRQT_FALLING; struct button_info { unsigned int irq_no; unsigned int gpio_port; unsigned int IN; int button_no; }; struct button_info realarm_button_info[4] = { { IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_INP, 1 }, { IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_INP, 2 },

linux基础实验报告含代码

Linux基础实验

目录 实验一 (3) 实验二 (4) 实验三 (6) 实验四 (9) 实验五 (11) 实验六 (14) 实验七 (16)

实验一螺旋矩阵 一、实验目的 1.熟悉linux下c程序编写。 2.掌握Makefile编写方法。 二、实验环境和工具 Red Hat Linux 三、实验流程 1.编写螺旋矩阵程序 2.编写Makefile文件 四、实验结果 五、实验心得 通过这次实验,我熟悉了linux下c语言程序的编写,掌握了vi的一些常用操作,学会了使用gcc命令和makefile文件两种方法编译程序。同时也使我熟悉了linux里常用命令的使 用,还有,学会了挂载U盘的方法,可以很方便的往linux里传送文件。 六、关键代码 Makefile 文件 CC=gcc EXEC=juzhen OBJS=juzhen.o all:$(EXEC) $(EXEC):$(OBJS) $(CC) -o $@ $(OBJS) clean: -rm -f $(EXEC) $(OBJS)

实验二添加、删除用户 一、实验目的 1.设计一个shell程序,分组批量添加用户。 2.再设计一个批量删除用户的shell程序。 二、实验环境和工具 Red Hat Linux 三、实验流程 1.编写shell程序 2.修改文件权限 chmod +x addusers 3.运行脚本 四、实验结果 添加用户: 删除用户:

五、实验心得 通过本次实验,我了解了shell脚本编程的方法和其语法规则。掌握了使用shell脚本程序添加、删除用户的方法。需要注意的是:shell脚本直接用vi编写,要特别注意空格。 六、关键代码 添加用户: 删除用户:

嵌入式Linux系统开发教程实验报告

嵌入式实验报告 : 学号: 学院: 日期:

实验一熟悉嵌入式系统开发环境 一、实验目的 熟悉Linux 开发环境,学会基于S3C2410 的Linux 开发环境的配置和使用。使用Linux的armv4l-unknown-linux-gcc 编译,使用基于NFS 方式的下载调试,了解嵌入式开发的基本过程。 二、实验容 本次实验使用Redhat Linux 9.0 操作系统环境,安装ARM-Linux 的开发库及编译器。创建一个新目录,并在其中编写hello.c 和Makefile 文件。学习在Linux 下的编程和编译过程,以及ARM 开发板的使用和开发环境的设置。下载已经编译好的文件到目标开发板上运行。 三、实验设备及工具 硬件::UP-TECH S2410/P270 DVP 嵌入式实验平台、PC 机Pentium 500 以上, 硬盘10G 以上。 软件:PC 机操作系统REDHAT LINUX 9.0+超级终端(或X-shell)+AMR-LINUX 开发环境。 四、实验步骤 1、建立工作目录 [rootlocalhost root]# mkdir hello [rootlocalhost root]# cd hello 2、编写程序源代码 我们可以是用下面的命令来编写hello.c的源代码,进入hello目录使用vi命令来编辑代码: [rootlocalhost hello]# vi hello.c 按“i”或者“a”进入编辑模式,将上面的代码录入进去,完成后按Esc 键进入

命令状态,再用命令“:wq!”保存并退出。这样我们便在当前目录下建立了一个名为hello.c的文件。 hello.c源程序: #include int main() { char name[20]; scanf(“%s”,name); printf(“hello %s”,name); return 0; } 3、编写Makefile 要使上面的hello.c程序能够运行,我们必须要编写一个Makefile文件,Makefile文件定义了一系列的规则,它指明了哪些文件需要编译,哪些文件需要先编译,哪些文件需要重新编译等等更为复杂的命令。使用它带来的好处就是自动编译,你只需要敲一个“make”命令整个工程就可以实现自动编译。Makefile源程序: CC= armv4l-unknown-linux-gcc EXEC = hello OBJS = hello.o CFLAGS += LDFLAGS+= –static all: $(EXEC) $(EXEC): $(OBJS) $(CC) $(LDFLAGS) -o $ $(OBJS) clean: -rm -f $(EXEC) *.elf *.gdb *.o 下面我们来简单介绍这个Makefile 文件的几个主要部分: CC 指明编译器 EXEC 表示编译后生成的执行文件名称 OBJS 目标文件列表

嵌入式Linux下3G模块的驱动和应用

嵌入式Linux下3G模块的驱动和应用 1、开发资源 1.1、硬件资源: ZTE-mf637u(中国联通) ZTE-mu351(中国移动) 1.2、软件资源: 1.2.1、usb-modeswitch-1.1.3 libusb-0.1.12.tar.gz usb-modeswitch-1.1.3.tar.bz2 1.2.2、ppp-2.4.4 libpcap-0.9.8.tar.gz ppp-2.4.4.tar.gz 1.2.3、wvdial 1.2.3.1、wvdial-1.54.0(arm-linux-gcc 3.4.1) zlib-1.2.5.tar.bz2 openssl-0.9.7g.tar.gz openssl-0.9.7g-fix_manpages-1.patch wvstreams-4.0.1.tar.bz2

wvstreams-4.0.1-tcl84-1.patch wvdial-1.54.0.tar.gz 1.2.3.2、wvdial_1.60.4(arm-linux-gcc 4.2.2) zlib-1.2.5.tar.bz2 openssl-0.9.8n.tar.gz openssl-0.9.8n-fix_manpages-1.patch wvstreams-4.6.1.tar.gz wvdial_1.60.4.tar.gz 2、Linux开发环境 2.1、主机环境 2.1.1、主机linux系统 Fedora Core 6 2.1.2、主机编译环境 2.1.2.1、gcc -v Using built-in specs. Target: i386-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile

编写嵌入式Linux设备驱动程序的实例教程

编写嵌入式Linux设备驱动程序的实例教程 一、Linux device driver 的概念 系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1、对设备初始化和释放; 2、把数据从内核传送到硬件和从硬件读取数据; 3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4、检测和处理设备出现的错误。 在linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如

果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。 已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。 最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 二、实例剖析 我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把

实验七Linux块设备驱动

实验七:Linux块设备驱动块设备是与字符设备并列的概念,这两类设备在Linux中驱动的结构有较大差异,总体而言,块设备驱动比字符设备驱动要复杂得多,在I/O操作上表现出极大的不同,缓冲、I/O调度、请求队列等都是与块设备驱动相关的概念。本章将详细讲解Linux块设备驱动的编程方法。 1.块设备的I/O操作特点 字符设备与块设备I/O操作的不同如下: (1)块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位。大多数设备是字符设备,因为它们不需要缓冲而且不以固定块大小进行操作。 (2)块设备对于I/O请求有对应的缓冲区,因此它们可以选择以什么顺序进行响应,字符设备无须缓冲且被直接读写。对于存储设备而言调整读写的顺序作用巨大,因为在读写连续的扇区比分离的扇区更快。 (3)字符设备只能被顺序读写,而块设备可以随机访问。虽然块设备可随机访问,但是对于磁盘这类机械设备而言,顺序地组织块设备的访问可以提高性能。而对SD卡、RamDisk(RamDisk 是通过使用软件将RAM模拟当做硬盘来使用的一种技术)等块设备而言,不存在机械上的原因,进行这样的调整没有必要。 2.Linux块设备驱动结构 2.1.block_device_operations结构体 在块设备驱动中,有一个类似于字符设备驱动中file_operations结构体的 block_device_operations结构体,它是对块设备操作的集合,定义如代码清单1所示。 代码清单1 block_device_operations结构体

下面对其主要的成员函数进行分析。 与字符设备驱动类似,当设备被打开和关闭时将调用它们。 2.IO控制 上述函数是ioctl()系统调用的实现,块设备包含大量的标准请求,这些标准请求由Linux 块设备层处理,因此大部分块设备驱动的ioctl()函数相当短。 被内核调用来检查是否驱动器中的介质已经改变,如果是,则返回一个非0值,否则返回0。这个函数仅适用于支持可移动介质的驱动器,通常需要在驱动中增加一个表示介质状态是否改变的标志变量,非可移动设备的驱动不需要实现这个方法。 4.使介质有效 revalidate_disk()被调用来响应一个介质改变,它给驱动一个机会来进行必要的工作以使新介质准备好。 5.获得驱动器信息 根据驱动器的几何信息填充一个hd_geometry结构体,hd_geometry结构体包含磁头、扇区、柱面等信息。 6.模块指针 一个指向拥有这个结构体的模块的指针,它通常被初始化为THIS_MODULE。 2.2.gendisk结构体 在Linux内核中,使用gendisk(通用磁盘)结构体来表示1个独立的磁盘设备(或分区),这个结构体的定义如代码清单2所示。 代码清单2 gendisk结构体

相关文档
最新文档