bl跳转指令使用错误导致编译出现错误--relocation truncated to fit: R_ARM_PC24 init_irq

来源:互联网 发布:数据新闻手册 中文版 编辑:程序博客网 时间:2024/05/22 03:17

在用编写JZ2440 LCD硬件实验时在head.S中使用bl init_irq导致错误:

bl 跳转指令只能在+/- 32MB内跳转:

BL指令在编码的时候,有24位用于表示相对地址的,(BL跳转的范围有限,这也是ldr给pc赋值跳转的区别),其中最高位是符号位,余下23位表示相对地址,BL都是跳转到某个指令的执行处,一个指令都是占4个字节,就是4个地址,属于字对齐,最低2位地址固定为0,所以可以看做是有25位表示相对地址,所以就有了正负32MB的地址空间。(每个程序运行的时候都有一个运行地址,称之为整个程序的基址)错误代码:
@******************************************************************************@ File: head.S@ 功能: 设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行@******************************************************************************          .extern     main.text .global _start _start:@******************************************************************************       @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用@******************************************************************************           b   Reset@ 0x04: 未定义指令中止模式的向量地址HandleUndef:    b   HandleUndef  @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式HandleSWI:    b   HandleSWI@ 0x0c: 指令预取终止导致的异常的向量地址HandlePrefetchAbort:    b   HandlePrefetchAbort@ 0x10: 数据访问终止导致的异常的向量地址HandleDataAbort:    b   HandleDataAbort@ 0x14: 保留HandleNotUsed:    b   HandleNotUsed@ 0x18: 中断模式的向量地址    b   HandleIRQ@ 0x1c: 快中断模式的向量地址HandleFIQ:    b   HandleFIQReset:                      ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈    bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启    bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK    bl  memsetup            @ 设置存储控制器以使用SDRAM    bl  nand_init           @ 初始化NAND Flash                                @ 复制代码到SDRAM中    ldr r0, =0x30000000     @ 1. 目标地址 = 0x30000000,这是SDRAM的起始地址    mov r1, #4096           @ 2. 源地址   = 4096,运行地址在SDRAM中的代码保存在NAND Flash 4096地址开始处    mov r2, #16*1024        @ 3. 复制长度 = 16K,对于本实验,这是足够了    bl  CopyCode2SDRAM      @ 调用C函数CopyCode2SDRAM        bl  clean_bss           @ 清除bss段,未初始化或初值为0的全局/静态变量保存在bss段    msr cpsr_c, #0xd2       @ 进入中断模式    ldr sp, =0x31000000     @ 设置中断模式栈指针    msr cpsr_c, #0xdf       @ 进入系统模式    ldr sp, =0x34000000     @ 设置系统模式栈指针,//    ldr lr, =ret_initirq    @ 设置返回地址    //这里查看寄存器应该是sp = 0x34000000  //  ldr pc, =init_irq       @ 调用中断初始化函数 //这里用bl也可以把//ret_initirq:blinit_irq //相对跳转指令跳转范围+/- 32MB,但是由interrupt.o在SDRAM中,而从片内4K SRAM调到SDRAM显然超过了+/- 32M    msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断    ldr lr, =halt_loop      @ 设置返回地址    ldr pc, =main           @ 调用main函数halt_loop:    b   halt_loopHandleIRQ:    sub lr, lr, #4                  @ 计算返回地址    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器                                    @ 注意,此时的sp是中断模式的sp                                    @ 初始值是上面设置的4096        ldr lr, =int_return             @ 设置调用IRQ_Handle函数后的返回地址      ldr pc, =IRQ_Handle             @ 调用中断分发函数,在interrupt.c中int_return:    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr    

make后出现:
book@book-desktop:/work/video_example/lcd$ makearm-linux-gcc -nostdinc -I/work/video_example/lcd/include -Wall -O2 -c -o head.o head.Scd lib; make; cd ..make[1]: Entering directory `/work/video_example/lcd/lib'make[1]: `libc.a' is up to date.make[1]: Leaving directory `/work/video_example/lcd/lib'arm-linux-ld -Tlcd.lds -o lcd_elf head.o init.o nand.o interrupt.o serial.o lcddrv.o framebuffer.o lcdlib.o main.o lib/libc.ahead.o(.text+0x58): In function `Reset':: relocation truncated to fit: R_ARM_PC24 init_irqmake: *** [lcd.bin] Error 1
链接脚本lcd.lds:
SECTIONS {    . = 0x00000000;    .init : AT(0){ head.o init.o nand.o}    . = 0x30000000;    .text : AT(4096) { *(.text) }    .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {*(.rodata*)}     .data ALIGN(4)   : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }    __bss_start = .;    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }    __bss_end = .;}
init_irq 函数在在interrupt.o定义,链接地址在SDRAM中了,所以出现编译错误
解决方法:把bl指令换为ldr指令


0 0
原创粉丝点击