现在来看看汇编的源代码:
sam1.out: file format coff-arm-little
Disassembly of section .text:
10000000 <_start>:
10000000: e1a0c00d mov ip, sp
10000004: e92dd800 stmdb sp!, {fp, ip, lr, pc}
10000008: e24cb004 sub fp, ip, #4
1000000c <_my_start>:
1000000c: e3a0e070 mov lr, #70
10000010: ee01ef10 mcr 15, 0, lr, cr1, cr0, {0}
10000014: e10fe000 mrs lr, cpsr
10000018: e3cee01f bic lr, lr, #1f
1000001c: e38ee0d3 orr lr, lr, #d3
10000020: e129f00e msr cpsr, lr
10000024: e59fd000 ldr sp, 1000002c <$$lit__1>
10000028: e91ba800 ldmdb fp, {fp, sp, pc}
1000002c <$$lit__1>:
1000002c: c0020000 andgt r0, r2, r0
10000030 <__CTOR_LIST__>:
10000030: ffffffff swinv 0x00ffffff
10000034: 00000000 andeq r0, r0, r0
10000038 <__DTOR_LIST__>:
10000038: ffffffff swinv 0x00ffffff
1000003c: 00000000 andeq r0, r0, r0
哈哈!在<_start>和<_my_start>之间的代码在干什么?是在保存现场吧,还用到了
堆栈。而这时堆栈还没初始化,向堆栈里写东西那不乱套了!应该屏蔽这段代码。
那就在<_start>之前放一个跳转指令跳到<_my_start>吧。
#define DWORD unsigned int
asm ("
.text
.global _start
_start:
bl _my_start /* Omit the entry code for function c_start() */
");
void c_start(void)
{
register DWORD dwHardwareBase;
asm ("_my_start:
mov r14, #0x70
mcr p15, 0, r14, c1, c0, 0 /* MMU disabled, 32 Bit mode, Little endian */
mrs r14, cpsr
bic r14, r14, #0x1f /* Mask */
orr r14, r14, #0xc0 + 0x13 /* Diasble IRQ and FIQ, SVC32 Mode */
msr cpsr, r14
ldr r13, =0xc0020000 /* Setup Stack */
");
dwHardwareBase = (DWORD)0x80000000;
}
再编译看看汇编代码:
sam1.out: file format coff-arm-little
Disassembly of section .text:
10000000 <_start>:
10000000: eb000002 bl 10000010 <_my_start>
10000004 <_c_start>:
10000004: e1a0c00d mov ip, sp
10000008: e92dd800 stmdb sp!, {fp, ip, lr, pc}
1000000c: e24cb004 sub fp, ip, #4
10000010 <_my_start>:
10000010: e3a0e070 mov lr, #70
10000014: ee01ef10 mcr 15, 0, lr, cr1, cr0, {0}
10000018: e10fe000 mrs lr, cpsr
1000001c: e3cee01f bic lr, lr, #1f
10000020: e38ee0d3 orr lr, lr, #d3
10000024: e129f00e msr cpsr, lr
10000028: e59fd000 ldr sp, 10000030 <$$lit__1>
1000002c: e91ba800 ldmdb fp, {fp, sp, pc}
10000030 <$$lit__1>:
10000030: c0020000 andgt r0, r2, r0
10000034 <__CTOR_LIST__>:
10000034: ffffffff swinv 0x00ffffff
10000038: 00000000 andeq r0, r0, r0
1000003c <__DTOR_LIST__>:
1000003c: ffffffff swinv 0x00ffffff
10000040: 00000000 andeq r0, r0, r0
成功了!!!!剩下的就是写Flash的程序,我就不多写了,这里给出源代码。需要说明的是:
下面的这段指令是生成2K的二进制文件
debug bootldr.bin
rcx
800
w
q
所有的全局变量都定义成const,因为在linux 中用 gcc,ld,objcopy 处理过程序后如果不是定义的是const,生成的二进制文件很大,不知道为什么。谁知道原因请来信告知。(gavinux@yahoo.com)
在汇编代码的尾部有:<__CTOR_LIST__> 和<__DTOR_LIST__>,象是C++的构造函数和析构函数的列表,不只是否?我现在还不知道什么编译连接的选项能把它去掉。
最后问大家一个问题:向bootloader这样对文件大小很敏感的程序(2K size)我们都能够用以上的方法实现,那么是不是VxWorks BSP里的所有程序都能用这个办法实现呢?
/***********************************************************************
; bootloader for Cirrus Logic clps7111 ARM processor
; Author : Gavin Li
; web: http://embedded.homeunix.org
; rev 0
;
; INTEL Flash F160C3, F320C3
; -- For downloading vxWorks images.
; -- The size of the .bin file has to be limited to 2K and this program
; is to be downloaded by the on-chip boot program first.
; -- Runs in the on-chip 2K SRAM
; -- Works together with FTS (on the PC side)
; -- F160C3 has 2 M memory with 8 segments and F320C3 has 8 M memory with
; 2 segments. F320C3's memory space covers F160C3 and vxWork's image is
; normally smaller than 1M, therefor this program works for both 320
; and 160 though it is originally for 160.
; -- Erase 0.5M or 1M flash according to the image size
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
;**********************************************************************/
/* For VxWorks
rem asarm -EL -o start.o start.s
ccarm -c -O2 -mcpu=arm710 -mlittle-endian -nostdlib -fvolatile -nostdinc -static
bootldr.c
ldarm -o bootldr.out -Ttext 10000000 bootldr.o
objdumparm -d bootldr.out > bootldr.asm
coffarmtobin < bootldr.out > bootldr.bin
debug bootldr.bin
rcx
800
w
q
*/
/* For GNU gcc
PATH=/home/gavin/armtools/bin:$PATH
arm-linux-gcc -O2 -mcpu=arm710 -mlittle-endian -nostdlib -fvolatile -nostdinc -static
-e _start -Ttext 10000000 -o bootldr.out bootldr.c
arm-linux-objcopy -O binary -S bootldr.out bootldr.bin
arm-linux-objdump -d bootldr.out bootldr.asm
remeber to make bootldr.bin to 2K size for clps7111/clps7211 system board
You will get these warnings, Those are correct, just forget them. :-)
bootldr.c: In function `RecvData':
bootldr.c:252: warning: assignment of read-only variable `g_dwSaveAddr'
bootldr.c:253: warning: assignment of read-only variable `g_dwSaveCount'
bootldr.c:268: warning: assignment of read-only variable `g_dwCheckSum'
*/
/* -B/home/gavin/armtools */
#include "clps7111.h"
/* flash command defines */
#define FLASH_COMMAND_READ_ID 0x90
#define FLASH_COMMAND_READ 0xFF
#define FLASH_COMMAND_ERASE 0x20
#define FLASH_COMMAND_CONFIRM 0xD0
#define FLASH_COMMAND_CLEAR 0x50
#define FLASH_COMMAND_WRITE 0x40
#define FLASH_COMMAND_STATUS 0x70
#define FLASH_COMMAND_SUSPEND 0xB0
#define FLASH_COMMAND_RESUME 0xD0
#define FLASH_COMMAND_CONFIG_SETUP 0x60
#define FLASH_COMMAND_LOCK_BLOCK 0x01
#define FLASH_COMMAND_UNLOCK_BLOCK 0xD0
#define FLASH_STATUS_READY 0x80
#define FLASH_STATUS_ERASE_SUSPENDED 0x40
1 2 3 4 5 6