linkerembeddedarmgreenhills

ARM DCD working and Executing from RAM


I am using MBD9F126(ARM Cortex R4) micro-controller. In that I am flashing code into ROM and then I am executing the code from RAM after RAM copy. I am using the Green hills compiler. Before the RAM copy I am executing basic board Initialization code.

    LDR r12, ADDRESS_START_PREINIT
    BLX r12
    ADDRESS_START_PREINIT:DCD Start_PreInit

Start_PreInit is board initialization function. IF I am giving like this after BLX it'll branch to RAM location. As RAM copy is not done yet so it goes to unknown area.

Instead of this If I am writing

    bl Start_PreInit

Its working properly that is going to ROM location of code. I don't why compiler has such a behavior?
And also ADDRESS_START_PREINIT:DCD Start_PreInit . Is it done during linking??


Solution

  • The bl Start_PreInit instruction works because the branch target is encoded in the instruction opcode as an offset relative to the current PC (r15). Since r15 is pointing to ROM, the target is another ROM address.

    The blx r12 instruction branches to the absolute address that was loaded into the r12 register.

    When you load the contents of ADDRESS_START_PREINIT into a register, what you're getting is the absolute address that the linker calculated for the Start_PreInit address. Apparently the linker has fixed that to the RAM absolute address.

    You might be able to fix the problem with a linker configuration or by performing some transformation on r12 when it's loaded with the RAM address (something like (r12 - RAM_START) + ROM_START) before branching. Or use the pc-relative encoding instead of the register-absolute encoding for the branch instruction if the target address is in range.