1. ARM不支持除法
一个简单的C除法语句可能编译不过,如int c = a/b ; 或int c = a%b,都会报错。
提示:
undefined reference to `__divsi3'
GNU内部使用__divsi3函数来替代ARM下的除法运算,此函数定义在libgcc.a中。本来gcc应该是默认
找这个库的,但由于在命令行中使有的arm-linux-ld(因为要使用-T选项),所以要手工为之指定
arm工具链的libgcc.a。
$(LD) -Tlink.lds -o $@
$^ /code/arm/libgcc.a
经测试只有把libgcc.a的实际路径放在命令行的所有object的后面(位置敏感)才好使。另外,用-lgcc
指定也可以,但也是要求必须放在最后面。
$(LD) -Tlink.lds -o $@ $^ -lgcc -L/code/arm
2. 'not enough room for program headers'
这是一个很复杂的错误,通常是由于在链接脚本里没指定.rodata段来导致的。
ENTRY(start)
SECTIONS
{
. =0x30000000;
.text : { *(.text) }
.data : {*(.data) }
.bss : {*(.bss) }
.rodata :{*(.rodata) }
}
3. AXD在加载elf文件时可能会失败,提示如下:
DBE Warning 00255: WIN32
exception code 0xc0000005 was caught in
dbess_image\dbt_image.cpp:160
网上说,这是由于AXD对高版本的gcc支持不好的原因。例如,在用4.3.2版本编译时,elf文件无法加载。
(1) . 应该换成2.95.3版本(但此版本的gcc不支持c99语法,郁闷)
(2) .
检查是否有未声明的函数调用,尽量使用规矩的方式。例如,调用一个printf(),则最后在前加上该函数的proto-type
(3) 修改设置后,要重启板子、重启AXD再试试
(4) 寄存器变量不可简写
u32 _2440irq_check_srcpnd(u32 index)
{
return rSRCPND &
BIT_VALUE(index);
}
改成
u32 _2440irq_check_srcpnd(u32 index)
{
u32 value = rSRCPND; return value &
BIT_VALUE(index);
}
(5) 板子在启动的时候可能已经运行了程序,这时再进行调试,可能会受到板子上正在运行的程序的影响。
所以可以先做一个简单的程序,用H-Flasher烧写到板子上。这个程序简单到只有一个无限循环。
_reset_handler:
b .
4. 中断向量表的随意跳转
中断向量表是4*8个字节 = 8个向量,如果在每个向量放置B指令跳转的话,由于B指令只能跳转到前后32M的
地址,所以跳转能力有限。所以中断向量一段这么做的:
.section
VectorTable,"x" 0000 ldr pc,
ResetAddr 0001 ldr pc,
UndefinedAddr 0002 …… 0003 …… 0004 …… 0005 …… 0006 …… 0007 …… 0008 ResetAddr: .word
HandlerReset 0009 UndefinedAddr: .word
HandlerUndefined 0010 …… 0011 …… 0012 …… 0013 …… 0014 …… 0015 ……
第0000行,ldr指令把内存在[ResetAddr]的一个字取出来,存到PC;而[ResetAddr]处存放的正是
处理函数Handler的地址。因为arm在进入异常时已经到返回值存到LR里了,所以用ldr pc,...的方式
跳转是没有问题的,处理结束后可以返回来。
(用bl跳转时自动将返回地址存入LR,异常发生时ARM自动将返回地址存到LR)
5. 注意libgcc.a要跟编译器的版本一致
6. 无效的地址可以加载,但不能运行
例如,板子有效的内存地址是0x30000000 -
0x34000000,但是如果指定起始地址为0x60000000也可以加载。
只是运行的时候会提示无法运行。
DBT Warning 00135: Cannot set breakpoints in literal pools
7. 编译器
(1) Friendly Arm带的2.95.3有问题,从网上下载了一个2.95.3可以用,可以接受-gdwarf-2选项
(2) 如果使用2.95.3编译器,需要加上-gdwarf-2选项;如果使用3.4.1,则使用-g即可
(3) elf转成binary
$ arm-linux-objcopy -O binary xxx.elf xxx.bin