假设我们现在进行一项嵌入式开产品的开发,比如说智能电力系统终端,那么我想首先应该对完整的开发流程有一个大致的了解,才不致于在以后的工作中被动。下面对嵌入式linux开发简单的介绍一下。
1、系统的需求分析
2、硬件平台的选择和设计
3、软件开发
(3-1)建立开发环境。
(3-2)引导装载程序。
(3-3)内核裁减与编译。
(3-4)建立文件系统。
(3-5)应用程序开发。
嵌入式开发环境一般由:宿主机(Linux Server)、工作站、嵌入式目标系统(target board)和将它们连在一起的网络环境。
1、linux server:嵌入式linux内核编译、应用程序编译的公共平台,有单独的一台pc机充当,安装标准的linux操作系统,比如redhat,debian等等。
2、工作站:为普通局域网计算机,以支持小组项目开发。工作站一般安装windows,需要linux服务器时,可以从工作站远程登陆到linux server。
3、target board:这是需要开发的最终产品,可以根据需要与工作站连接(通常通过串口或者usb接口),或连至局域网。
4、工作站需要安装ftp客户端(cuteftp、flashfxp等)和telnet客户端程序(secureCRT等),linux服务器应该开通ftp和telnet服务,还有ssh。
综述过程:开发人员在一台工作站进行操作,通过远程登陆的方式操作linux server,并且使用ftp在linux server和工作站进行文件传输,同时target board需要与网络连接,其串口与工作站的RS232接口连接。使用工作站上的超级终端作为嵌入式目标系统输入/输出端。
对于开发流程有了一定的了解后就有了目标,这样才能够不是太郁闷。
debug kernel rootfiles source tmp
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
export TARGET=arm-linux
export PRJROOT=/home/armlinux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=$PATH:$HOME/bin:$PREFIX/bin:/sbin:/usr/sbin:/usr/local/sbin
How to install:
mkdir arm
cd arm
tar Ixvf cross-<version>.tar.bz2
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
export TARGET=arm-linux
export PRJROOT=/home/armlinux
export PREFIX=${PRJROOT}/tools
export TARGET_PREFIX=${PREFIX}/${TARGET}
export PATH=$PATH:$HOME/bin:$PREFIX/bin:/usr/local/arm/2.95.3/bin:/sbin:/usr/sbin:/usr/local/sbin
{
int i;
for(i=1;i<9;i++)
printf("Hello World %d times!/n",i);
}
if [ x$n = x ]; then n=gdbserver; else true; fi; /
/usr/bin/install -c gdbserver /home/armlinux/tools/arm-linux/bin/$n; /
/usr/bin/install -c -m 644 ../../software/gdb-5.2.1/gdb/gdbserver/gdbserver.1 /home/armlinux/tools/arm-linux/man/man1/$n.1
/usr/bin/install: 无法创建一般文件‘/home/armlinux/tools/arm-linux/bin/gdbserver’: 没有那个文件或目录
/usr/bin/install: 无法创建一般文件‘/home/armlinux/tools/arm-linux/man/man1/gdbserver.1’: 没有那个文件或目录
make: *** [install-only] Error 1
-rwxr-xr-x 1 armlinux armlinux 23132 8月 10 11:33 gdbserver
Connected to mama.indstate.edu (139.102.70.201).
220 ProFTPD 1.3.0 Server (ProFTPD Default Installation) [139.102.70.201]
Name (mama.indstate.edu:armlinux): anonymous
331 Anonymous login ok, send your complete email address as your password.
Password:
230 Anonymous access granted, restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd linux/tree
250 CWD command successful
ftp> ls
227 Entering Passive Mode (139,102,70,201,149,53).
150 Opening ASCII mode data connection for file list
drwxr-xr-x 2 root root 4096 Jun 4 2001 binary
drwxr-xr-x 2 root root 4096 May 19 1999 slack
-rw-r--r-- 1 root root 406 Oct 11 1996 tree-1.1.lsm
-rw-r--r-- 1 root root 13135 Oct 11 1996 tree-1.1.tgz
-rw-r--r-- 1 root root 405 Jan 6 1997 tree-1.2.lsm
-rw-r--r-- 1 root root 16362 Jan 6 1997 tree-1.2.tgz
-rw-r--r-- 1 root root 436 Feb 21 2002 tree-1.3.lsm
-rw-r--r-- 1 root root 25060 Feb 21 2002 tree-1.3.tgz
-rw-r--r-- 1 root root 432 Feb 21 2002 tree-1.4b1.lsm
-rw-r--r-- 1 root root 27536 Feb 21 2002 tree-1.4b1.tgz
-rw-r--r-- 1 root root 27891 Mar 25 2002 tree-1.4b2.tgz
-rw-r--r-- 1 root root 432 Jun 18 2003 tree-1.4b3.lsm
-rw-r--r-- 1 root root 29366 Feb 6 2003 tree-1.4b3.tgz
-rw-r--r-- 1 root root 466 Aug 20 2004 tree-1.5.0.lsm
-rw-r--r-- 1 root root 26543 Aug 16 2004 tree-1.5.0.tgz
226 Transfer complete.
ftp> get tree-1.5.0.tgz
|-- bootloader
|-- debug
|-- images
|-- kernel
|-- program
|-- rootfiles
|-- software
|-- source
|-- sysapps
|-- tmp
`-- tools
1. PLL SETUP
设置PLLB产生48M时钟频率提供给USB DEVICE。同时DEBUG USART也被初始化为48M的时钟频率。
2. 相应模式下的堆栈设置
3. 检测主时钟源(Main oscillator)
4. 中断控制器(AIC)的设置
5. C 变量的初始化
6. 跳到主函数
完成以上步骤后,我们可以认为BOOT过程结束,接下来的就是LOADER的过程,或者也可以认为是装载二级BOOTLOER。 AT91RM9200 按照DATAFLASH、EEPROM、连接在外部总线上的8位并行FLASH的顺序依次来找合法的BOOT程序。所谓合法的指的是在这些存储设备的开始地址处连续的存放的32个字节,也就是8条指令必须是跳转指令或者装载PC的指令,其实这样规定就是把这8条指令当作是异常向量表来处理。必须注意的是第6条指令要包含将要装载的映像的大小。关于如何计算和写这条指令可以参考用户手册。一旦合法的映像找到之后,则BOOT程序会把找到的映像搬到SRAM中去,所以映像的大小是非常有限的,不能超过16K的大小。当BOOT程序完成了把合法的映像搬到SRAM的任务以后,接下来就进行存储器的REMAP,经过REMAP之后,SRAM从映设前的0X200000地址处被映设到了0X0地址并且程序从0X0处开始执行。而ROM这时只能在0X100000这个地址处看到了。至此9200就算完成了一种形式的启动过程。如果BOOT程序在以上所列的几种存储设备中找到合法的映像,则自动初始化DEBUG USART口和USB DEVICE口以准备从外部载入映像。对DEBUG口的初始化包括设置参数115200 8 N 1以及运行XMODEM协议。对USB DEVICE进行初始化以及运行DFU协议。现在用户可以从外部(假定为PC平台)载入你的映像了。在PC平台下,以WIN2000为例,你可以用超级终端来完成这个功能,但是还是要注意你的映像的大小不能超过13K。一旦正确从外部装载了映像,接下来的过程就是和前面一样重映设然后执行映像了。我们上面讲了BMS为高电平, AT91RM9200 选择从片内的ROM启动的一个过程。如果BMS为低电平,则 AT91RM9200 会从片外的FLASH启动,这时片外的FLASH的起始地址就是0X0了,接下来的过程和片内启动的过程是一样的,只不过这时就需要自己写启动代码了,至于怎么写,大致的内容和ROM的BOOT差不多,不同的硬件设计可能有不一样的地方,但基本的都是一样的。由于片外FLASH可以设计的大,所以这里编写的BOOTLOADER可以一步到位,也就是说不用像片内启动可能需要BOOT好几级了,目前 AT91RM9200 上使用较多的bootloer是u-boot,这是一个开放源代码的软件,用户可以自由下载并根据自己的应用配置。
以上三个文件时at91rm9200启动所需要的三个bin,他们的实现代码并不难。
如果是你是采用at91rm9200的评估版,应该能得到其源码。
loader.bin 执行流程,这个文件主要在片内启动从串口下载代码时会用到
loader/entry.S init cpu
b main ---> crt0.S
--> copydata --> clearbss --> b boot
main.c --> boot -->
/*Get internel rom service address*/
/* Init of ROM services structure */
pAT91 = AT91C_ROM_BOOT_ADDRESS;
/* Xmodem Initialization */
--> pAT91->OpenSBuffer
--> pAT91->OpenSvcXmodem
/* System Timer initialization */
---> AT91F_AIC_ConfigureIt
/* Enable ST interrupt */
AT91F_AIC_EnableIt
AT91F_DBGU_Printk("XMODEM: Download U-BOOT ");
Jump.S
// Jump to Uboot BaseAddr exec
Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS)
boot.bin执行流程 该文件会在从片内启动时被下载到板子上,以后还会被烧写到片外Flash中,以便在片外启动时
用它来引导并解压u-boot.bin.gz,并跳转到u-boot来执行。
boot/entry.S
b main --> crt0.S --> copydata --> clearbss --> b boot
AT91F_DBGU_Printk(" ");
AT91F_DBGU_Printk("************************************** ");
AT91F_DBGU_Printk("** Welcome to at91rm9200 ** ");
AT91F_DBGU_Printk("************************************** ");
boot/misc.s /* unzip uboot.bin.gz */
----> decompress_image(SRC,DST,LEN) --> gunzip
//jump to ubootBaseAddr exec 这里跳转到解压u-boot.bin.gz的地址处直接开始执行u-boot
asm("mov pc,%0" : : "r" (DST));
u-boot.bin执行流程
u-boot/cpu/at91rm9200/start.S
start --->reset
---> copyex ---> cpu_init_crit
---> /* set up the stack */ --> start_armboot
u-boot/lib_arm/board.c
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
dram_init, /* configure available RAM banks */
display_dram_config,
checkboard,
NULL,
};
---> start_armboot ---> call init_sequence
---> flash_init --> display_flash_config
---> nand_init ---> AT91F_DataflashInit
---> dataflash_print_info --> env_relocate
---> drv_vfd_init --> devices_init --> jumptable_init
---> console_init_r --> misc_init_r --> enable_interrupts
---> cs8900_get_enetaddr --> board_post_init -->
u-boot/common/main.c
for (;;)
{ /* shell parser */
main_loop () --> u_boot_hush_start --> readline
--> abortboot
-->printf("Hit any key to stop autoboot: %2d ", bootdelay);
}
以上是at91rm9200启动并进入u-boot的执行流分析。后面u-boot还会将uImage解压到特定的位置并开始执行内核代码。
.
|-- board 平台依赖,存放电路板相关的目录文件
|-- common 通用多功能函数的实现
|-- doc 文档
|-- drivers 通用的设备驱动程序,如以太网接口驱动
|-- dtt
|-- examples 应用例子
|-- fs 通用存放文件系统的程序
|-- include 头文件和开发板配置文件,所有开发板配置文件放在其configs里
|-- lib_arm 平台依赖,存放arm架构通用文件
|-- lib_generic 通用的库函数
|-- lib_i386 平台依赖,存放x86架构通用文件
|-- lib_m68k 平台依赖
|-- lib_mips 平台依赖
|-- lib_ppc平台依赖,存放ppc架构通用文件
|-- net 存放网络的程序
|-- post 存放上电自检程序
|-- rtc rtc的驱动程序
`-- tools 工具
[armlinux@lqm board]$ cd myboard
[armlinux@lqm myboard]$ ls
at91rm9200dk.c config.mk flash.c Makefile u-boot.lds
[armlinux@lqm myboard]$ mv at91rm9200dk.c myboard.c
[armlinux@lqm myboard]$ cat config.mk
TEXT_BASE = 0x21f80000
[armlinux@lqm myboard]$ vi config.mk
SOBJS :=
$(AR) crv $@ $(OBJS) $(SOBJS)
rm -f $(SOBJS) $(OBJS)
[armlinux@lqm myboard]$ cp ../xm250/flash.c ./
[armlinux@lqm myboard]$ ls
config.mk flash.c Makefile myboard.c u-boot.lds
[armlinux@lqm myboard]$ vi flash.c
35 #define FLASH_PORT_WIDTH16 /*定义位宽16*/
217
218 case (FPW) INTEL_ID_28F128J3A:
219 info->flash_id += FLASH_28F128J3A;
220 info->sector_count = 128;
221 info->size = 0x01000000;
222 break; /* => 16 MB */
223
224 case (FPW) INTEL_ID_28F640J3A: /*就是这个芯片*/
225 info->flash_id += FLASH_28F640J3A;
226 info->sector_count = 64;
227 info->size = 0x00800000;
228 break; /* => 8 MB */
[armlinux@lqm u-boot-1.1.1]$ vi Makefile
## AT91RM9200 Systems
#########################################################################
@./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk
@./mkconfig $(@:_config=) arm at91rm9200 myboard
at91rm9200dk integratorcp integratorap /
omap1510inn omap1610h2 omap1610inn /
smdk2400 smdk2410 trab /
VCMA9 versatile myboard /
"
[armlinux@lqm configs]$ cp at91rm9200dk.h myboard.h
[armlinux@lqm configs]$ vi myboard.h
111 #define PHYS_SDRAM 0x20000000 sdram起始地址
112 #define PHYS_SDRAM_SIZE 0x2000000 sdram容量32MB
129 #define PHYS_FLASH_2 0x00000000 定义,flash.c用到,但实际并未起作用
130 #define PHYS_FLASH_SIZE 0x800000 flash容量8MB
132 #define CFG_MAX_FLASH_BANKS 1 flash最大banks数
133 #define CFG_MAX_FLASH_SECT 64 扇区总数
134 #define PHYS_FLASH_SECT_SIZE (128*1024) 每个扇区128KB
135 #define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */
136 #define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */
137 #define CFG_FLASH_UNLOCK_TOUT (2*CFG_HZ)
138
139 #undef CFG_ENV_IS_IN_DATAFLASH
140
141 #ifdef CFG_ENV_IS_IN_DATAFLASH
142 #define CFG_ENV_OFFSET 0x20000
143 #define CFG_ENV_ADDR (CFG_DATAFLASH_LOGIC_ADDR_CS0 + CFG_ENV_OFFSET)
144 #define CFG_ENV_SIZE 0x2000 /* 0x8000 */
145 #else
146 #define CFG_ENV_IS_IN_FLASH 1
147 #define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x7e0000) /* 0x107E0000 */
148 #define CFG_ENV_SIZE 0x20000 环境变量占了一个扇区,共128KB
150
151 #define CFG_SOFT_RESET 1 定义软复位,flash.c用到
152 #define CFG_LOAD_ADDR 0x21000000 /* default load address */
Configuring for myboard board...
[armlinux@lqm u-boot-1.1.1]$ make CROSS_COMPILE=arm-linux-
正在开始 xmodem 传输。 按 Ctrl+C 取消。
正在传输 loader.bin...
100% 6 KB
CCCCCCCCCCCCC
正在开始 xmodem 传输。 按 Ctrl+C 取消。
正在传输 u-boot.bin...
100% 85 KB 6 KB/s 00:00:14 0 错误
U-Boot downloaded successfully
U-Boot 1.1.1 (Aug 17 2006 - 14:07:56)
RAM Configuration:
Bank #0: 20000000 32 MB
Flash: 8 MB
*** Warning - bad CRC, using default environment
Out: serial
Err: serial
U-boot> version
bootdelay=5
baudrate=115200
stdin=serial
stdout=serial
stderr=serial
U-boot> setenv ipaddr 192.168.1.100
U-boot> setenv serverip 192.168.1.106
U-boot> setenv ethaddr 36:B9:04:00:24:80
U-boot> saveenv
Saving Environment to Flash...
Un-Protected 1 sectors
Erasing Flash...
Erasing sector done
Erased 1 sectors
Writing to Flash.../done
Protected 1 sectors
TFTP from server 192.168.1.106; our IP address is 192.168.1.100
Filename 'boot.bin'.
Load address: 0x20000000
Loading: ###
done
Bytes transferred = 10628 (2984 hex)
Un-Protect Flash Sectors 0-0 in Bank # 1
U-boot> erase 1:0
Erase Flash Sectors 0-0 in Bank # 1
Erasing sector 0 ... done
U-boot> cp.b 20000000 10000000 2984
Copy to Flash...-done
TFTP from server 192.168.1.106; our IP address is 192.168.1.100
Filename 'u-boot.bin.gz'.
Load address: 0x20000000
Loading: #########
done
Bytes transferred = 43791 (ab0f hex)
U-boot> cp.b 20000000 10010000 ab0f
Copy to Flash.../done
RAM Configuration:
Bank #0: 20000000 32 MB
Flash: 8 MB
In: serial
Out: serial
Err: serial
U-Boot>
RCS file: /home/cvs/u-boot/tools/env/fw_env.c,v
retrieving revision 1.2
diff -u -r1.2 fw_env.c
--- fw_env.c 21 Jul 2004 03:28:43 -0000 1.2
+++ fw_env.c 23 Jul 2004 05:00:25 -0000
@@ -612,8 +612,8 @@
if (!crc1_ok) {
fprintf (stderr,
"Warning: Bad CRC, using default environment/n");
- environment.data = default_environment;
- free (addr1);
+ memset(environment.data, 0, ENV_SIZE);
+ memcpy(environment.data, default_environment, sizeof(default_environment));
}
} else {
flag1 = environment.flags;
Bug2:
{
extern char * env_name_spec;
when saving environment after changing stdin,
stdout,... the checksum is not consistent.
Adding an env_crc_update() before saving environment
could solve this. i.e in common/cmd_nvedit.c in
function do_saveenv() :
版本:Linux-2.4.27-vrs1
Target Board:ARM
U-boot:1.1.2
toolchain:cross-2.95.3
kernel下载到网站 www.kernel.org,可以通过ftp方式:$ftp ftp.kernel.org,采用匿名的方式输入anonymous即可进入下载。
patch准备:到官方网站 www.arm.linux.org.uk,这里提供ftp方式$ftp ftp.arm.linux.org.uk
2、打好补丁,执行make mrproper清理一下代码树。
3、修改根目录的Makefile文件,只需修改ARCH和CROSS_COMPILE即可。
ARCH :=arm
CROSS_COMPILE=arm-linux-
在这里,我已经将2.95.3放到PATH中,所以不需要写全路径。如果采用其他版本的toolchain,可以指明路径,如:CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux-
4、$make at91rm9200dk_config
该步的作用是把根目录下面的.config重命名为.config.old,然后把arch/arm/defconfig/里的at91rm9200dk开发板的默认配置文件复制到根目录下,命名为.config。简单的说,就是要利用提供的开发板的配置文件,然后在此基础上进行修改。
下一步如果执行make oldconfig,那么就完全按照.config来配置。而现在需要根据实际应用需要重新配置,所以不执行make oldconfig。而要执行make menuconfig。这两个命令都是首先寻找默认的.config文件并且执行,但不同的是,make oldconfig只出现.config没有的新配置选项供选择。而make menuconfig则提供所有选项,图形界面默认的是.config的配置。
在这里,还是推荐在提供的开发板配置文件的基础之上进行修改,否则后面很容易出现意想不到的问题。我就是因为开始没有使用默认配置,后面的错误一个接一个,折腾了一个上午。
5、make menuconfig
6、make clean dep
建立依赖关系。
7、make Image 或者 make zImage。这要看你后面使用什么方式的内核映象。如果是make Image,则生成vmlinux,需要arm-linux-objcopy进行处理,生成uImage影响文件。如果是make zImage,则生成zImage,vmlinux,system.map。
zImage和uImage对应的u-boot处理的方式也不相同,分别对应着go和bootm。
[armlinux@lqm linux-2.4.27]$ cp vmlinux $PRJROOT/images/vmlinux-2.4.27-vrs1
[armlinux@lqm linux-2.4.27]$ cp System.map $PRJROOT/images/System.map-2.4.27-vrs1
[armlinux@lqm linux-2.4.27]$ cp .config $PRJROOT/images/2.4.27-vrs1.config
[armlinux@lqm linux-2.4.27]$ gzip -v9 linux.bin
linux.bin: 55.7% -- replaced with linux.bin.gz
[armlinux@lqm linux-2.4.27]$ ../../bootloader/u-boot-1.1.2/tools/mkimage -n 'RAM disk' -A arm -O linux -T ramdisk -C gzip -a 0x20008000 -e 0x20008000 -d linux.bin.gz uImage
Image Name: RAM disk
Created: Wed Aug 23 09:09:27 2006
Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 617981 Bytes = 603.50 kB = 0.59 MB
Load Address: 0x20008000
Entry Point: 0x20008000
4342



被折叠的 条评论
为什么被折叠?



