This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

access to function using absolute addr

Hi,everyone ,I'm trying to access my function using its absolute address.It works when I debug it in KEIL step by step,but it jump to hard fault when runs.
my code is as below:

ptr=(int(*)(int))0x240; //0x240 is the address my function locates.
c=ptr(2);

And I've also met a very similar problem.The program jumps to hard fault when I have function(placed in a single file)placed in a special section .And the placement is fulfilled by sct file like this(fsk_tx.c):

; *************************************************************

LR_IROM1 0x00000000 0x00008000 { ; load region size_region ER_IROM1 0x00000000 0x00007000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO)

} ER_ROM 0x00007000 0X1000 { fsk_tx.o } ER_RAM 0x1FFFFB00 0X100 {

} RW_IRAM1 0x1FFFFD00 0x00000300 { ; RW data .ANY (+RW +ZI) } RW_IRAM2 0x20000000 0x00000C00 { .ANY (+RW +ZI) *(runinram) }
}

And the program works if I comment the fsk_tx.o in the sct file.

I'm really puzzled about it ,and I have to make it work soon.
Thanks !

Parents
  • Many ARM cores can run two different instruction sets. 32-bit ARM instructions and 16-bit thumb-mode instructions.

    The 16-bit instructions still operates on full 32-bit registers but needs a bit of extra work to load a 32-bit immediate value or for accessing a 32-bit absolute address.

    Anyway - the core looks at the least significant bit of function pointers to know if the function is using the 32-bit ARM instruction set or the 16-bit Thumb instruction set. This allows 32-bit and 16-bit code to be missed in the same program. So speed-sensitive code can use 32-bit instructions, while other code can save code space by using the more compact thumb instructions.

Reply
  • Many ARM cores can run two different instruction sets. 32-bit ARM instructions and 16-bit thumb-mode instructions.

    The 16-bit instructions still operates on full 32-bit registers but needs a bit of extra work to load a 32-bit immediate value or for accessing a 32-bit absolute address.

    Anyway - the core looks at the least significant bit of function pointers to know if the function is using the 32-bit ARM instruction set or the 16-bit Thumb instruction set. This allows 32-bit and 16-bit code to be missed in the same program. So speed-sensitive code can use 32-bit instructions, while other code can save code space by using the more compact thumb instructions.

Children
  • Thanks very much!
    Then I think I should still copy from the 0x230 And calls from the address+1.But why still I can't call it from ram and turns to hard fault?

    could you be nice to answer me again?
    Thanks!

  • You might want to examine the code you have copied, and using the debugger, step into the function. This might indicate why it's faulting.

    I don't know which part you are using, the address decoding can cause faults, and preclude execution of code. The Mx part's I'm more familiar with have RAM at 0x20000000, and code can generally be executed from there.

  • Not all processors can run code from all addresses - the address range needs to be handled by the prefetch logic.

    Another thing - some processors needs some form of barrier operation after writing code to RAM to make sure that the processor hasn't cached the content of RAM before the RAM write. This can happen when a processor have one instruction cache and one data cache - the data cache sees the RAM writes and has the correct information, but the instruction cache doesn't have any logic to sniff code memory changes.

  • I can't see anywhere that the chip in question - or even the core in question - has been mentioned but, if it's a Cortex-M, take a look at the links & info here:

    community.arm.com/.../5414

    Covers Cortex-M0, Cortex-M0+, Cortex-M3, Cortex-M4

  • The disassembling window presents code below:
    Mov r1,r0
    cmp r1,#00
    BEQ 0x20000010 --------------->the 0x20000010 is 0x10 bytes below the copy-to-address 0x20000000
    LDR r0,[pc,#12]
    LDR r0,[r0,#0x00] ------------------> hard fault occurs here
    ADDS r0,r0,#1
    LDR r2,[pc,#4]
    STR r0,[r2,#0x00]
    Movs r0,#0x01
    BX lr

    and my C code (copyTest):
    int shijian;
    int copyTest(int waste)
    { if(waste) shijian+=1; return 1;
    }

    And my MCU is freescale's ARM cortex_m0, it's ram is from 0x1ffffc00~0x20000C00.
    I had tried to execute code from ram,so I think the address is executed allowed.And the upper code is what I tried to copy the copyTest from flash to 0X20000000(ram).
    Can you find any problem?Thanks!

  • Thanks!I'm using cortex_m0.I'm not sure if it's one instruction cache.I'll check it .
    But I do think code can be executed from ram.

  • Hi,the core is ARM cortex_m0,and the chip is freescale's KL serials.
    I scanned the linked page,not understand full.I think they are telling how to locate the hard fault.It may be help,but can I ask if my problem is result from executing code from ram?
    actually I also want to know why it jumps to hard fault when I locate function in special session,like a session in flash?
    I think the crash has similarity with my coping code from flash to ram and running it.
    Am I on the right way to solve the problem?Thanks !

  • The LDR r0,[pc,#12] is attempting to load a literal beyond the end of the subroutine, so chances are you're not copying enough of the code representing the subroutine.

  • The prefetch here is pretty shallow, I don't think you're going to see any issue memcpy()ing and returning, and it not seeing the right code.

  • I don't know what else should I copy from.The assembly code in flash is almost the same besides address.
    Maybe I can transfer the question as:I want to have the function load in flash but execute in ram,meanwhile I want to know where is it loaded.Can I change the scatter file or should I get to know how does the keil do when execute __main? Thanks!

  • Hi,Westonsupermare Pier. Thanks! You maybe right.I tried to make KEIL fulfill the copy procedure itself by its __main.(through sct file,though I don't know the detail).
    And when I trace the code loaded in flash I find there are something else after :
    BX lr

    I guess it maybe some procedures restoring. So I think it should be the reason that I failed to copy the entirely function to the RAM.But what's the real length I should copy,I'm still confusing.I will think it more.

  • If you want to copy the function yourself, you should bracket the function by having it in a region that you can get the size of. Or maybe adding an extra function below so you can see the start address of the second function.

    It really is best to have the startup code copy the function into RAM.

  • Thank you very much,Per Westermark. So it's a question about how to get the right size of a function.I will try both.