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

[Cortex-M3] Execution code from RAM during Flash Programming

I am writing a bootloader for Cortex M3 Toshiba controller.

During Flash Programming I need to execute code from RAM as entire Flash is inaccessible during write/erase operations

I wish to know how to copy code from FLASH to RAM and execute that code from RAM.

Thanks...
  • Note: This was originally posted on 14th March 2012 at http://forums.arm.com

    Thanks Joseph for the reply.

    Yes my bootloader will be having flash programming feature.
    I want to copy some piece of code(Flash APIs and some functions) from flash to SRAM  when Flash Programming is being performed as at that time Flash will be inaccessible.
    In this case then these functions should get executed from SRAM means program counter should take the function address from SRAM.
    I am presently unable to figure this out.
    Your inputs will be helpful

    Regards,
    Rohit




    Do you mean your bootloader has flash programming feature, and
    want to copy the boot loader from flash to SRAM when the startup code is executed?
    regards,
    Joseph
  • Note: This was originally posted on 14th March 2012 at http://forums.arm.com

    Thank you very much for the reply...

    This method is quite helpful. I will first try this out. Thanks alot...
    But I am not sure of the Bootloader size as I have Diagnostic services running in bootloader too. So copying entire bootloader will be difficult so I need to copy portion of code which is most required during Flash Programming. I am able to copy the code to SRAM but I am unaware of the method of changing the Program counter value to SRAM address while flash programming.

    The functions that are copied to SRAM must be executed from SRAM during Flash Programming. I am trying this with the help of function pointers but have not succeeded yet. I wish to know whether this can be done in any other way. Or function pointers will solve my purpose.

    Please suggest regarding this..

    Regards,
    Rohit










    In that case, it would be easier to copy the whole boot loader (rather than a portion of it) from flash to SRAM in the assembly startup code.
    The boot loader, assumed to be mostly written in C, will have to linked to use the SRAM address as program memory range.

    In the assembly startup code you will have a reset handler, and normally you can see something like:

    Reset_Handler   PROC
                 EXPORT  Reset_Handler    [WEAK]
                 IMPORT  __main
                 LDR  R0,=__main
                 BX     R0   ; this branch to C startup code
                 ENDP

    You can insert an assembly code to copy the memory from flash to SRAM, before jumping to the C startup code which will be in SRAM.

    Reset_Handler   PROC
                 EXPORT  Reset_Handler    [WEAK]
                 LDR  R4,=0x00000000 ; Source starting address
                 LDR  R5,=0x20000000 ; Destination starting address
                 LDR  R6,=0x4000  ; 16K program size to copy
    CopyFlashToSRAMLoop
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}
                 SUBS R6,#64 ; Each time 64 bytes are copied
                 BNE CopyFlashToSRAMLoop
                 IMPORT  __main
                 LDR  R0,=__main
                 BX     R0   ; this branch to C startup code  
                 ENDP

    In this way, the whole boot loader will be running in SRAM.  You need to be careful to make sure that the data use by the boot loader is not in the same address as the instruction memory.

    regards,
    Joseph
  • Note: This was originally posted on 15th March 2012 at http://forums.arm.com

    Hi Joseph,

    Thank you very much for your reply.

    Yes I think this will be a helpful way. I will try to implement this way.
    I will get back to you if I have any other doubts regarding the same.
    Thank you very much for your support..

    Regards,
    Rohit



    Hi Rohit,

    In this case you could develop the bootloader and flash programming code as two separate projects.
    The flash programming project is compiled and link using SRAM as program address.
    Then you can generate hex image, and insert this into your boot loader project as a constant array.
    Inside your boot loader, you can copy this constant array into SRAM.

    To jump from boot loader to flash programming code, personally I got used to use embedded assembly:

    /* ARM RVDS or Keil MDK */
    __asm void jump_to_sram(void)
    {
       LDR   R0,=0x20000000  ; starting address of program in SRAM.
       LDR   R1,[R0]  ; Get initial MSP value
       MOV   SP, R1  ; Set SP value
       LDR   R1,[R0, #4] ; Get initial PC value
       BX R1
    }

    You can use function pointer to do the same.
    regards,
    Joseph
  • Note: This was originally posted on 15th March 2012 at http://forums.arm.com

    Hi Scott,

    Thank you very much for your reply.

    I am trying to implement it using function pointer. I will try implementing as suggested by you.
    Thanks for your support.

    Regards,
    Rohit


    For Cortex-M3 the low bit of the address needs to be set to indicate Thumb state, so if the starting address in RAM was say 0x20000100 (i.e. 0x20000101 is stored at 0x20000004 in the asm above).

    In C it would be

    typedef void RAM_fn_t(void);
    RAM_fn_t* fp = (RAM_fn_t*)0x20000101;
    (*fp)();


    It doesn't set SP the way the asm above does.  The cast is technically undefined behavior in C, but pragmatically it does what it looks like.

    Equivalently, if you prefer terseness/parentesis:

    (*((void (*)(void))0x20000101))();

  • Note: This was originally posted on 10th April 2012 at http://forums.arm.com

    Hi Joseph,

    I am doing this kind of job also for keil c compiler.
    Do I also need the .SCT file to specify the code address?
    Could you advice?

    BR
    Kent


    In that case, it would be easier to copy the whole boot loader (rather than a portion of it) from flash to SRAM in the assembly startup code.
    The boot loader, assumed to be mostly written in C, will have to linked to use the SRAM address as program memory range.

    In the assembly startup code you will have a reset handler, and normally you can see something like:

    Reset_Handler   PROC
                    EXPORT  Reset_Handler             [WEAK]
                    IMPORT  __main
                    LDR     R0,=__main
                    BX        R0   ; this branch to C startup code
                    ENDP

    You can insert an assembly code to copy the memory from flash to SRAM, before jumping to the C startup code which will be in SRAM.

    Reset_Handler   PROC
                    EXPORT  Reset_Handler             [WEAK]
                    LDR     R4,=0x00000000 ; Source starting address
                    LDR     R5,=0x20000000 ; Destination starting address
                    LDR     R6,=0x4000     ; 16K program size to copy
    CopyFlashToSRAMLoop
                    LDMIA    R4!,{R0-R3}
                    STMIA    R5!,{R0-R3}               
                    LDMIA    R4!,{R0-R3}
                    STMIA    R5!,{R0-R3}               
                    LDMIA    R4!,{R0-R3}
                    STMIA    R5!,{R0-R3}               
                    LDMIA    R4!,{R0-R3}
                    STMIA    R5!,{R0-R3}
                    SUBS    R6,#64 ; Each time 64 bytes are copied
                    BNE    CopyFlashToSRAMLoop
                    IMPORT  __main
                    LDR     R0,=__main
                    BX        R0   ; this branch to C startup code        
                    ENDP

    In this way, the whole boot loader will be running in SRAM.  You need to be careful to make sure that the data use by the boot loader is not in the same address as the instruction memory.

    regards,
    Joseph
  • Note: This was originally posted on 11th April 2012 at http://forums.arm.com

    Hi Joseph,

    Many thanks for your replying.
    I will create the project which contains code runnung is flash and SRAM.
    but I am not familiar with creating the linker script.
    following is my ,sct file:
    could you give me some advice?

    FLASH 0x08000000 0x00010000
    {
        ;
        ; Place the vector table and reset handlers into flash.
        ;
        RESET 0x08000000 0x00010000
        {
            *.o (RESET, +First)
           my_startup.o(+RO)
           * (InRoot$$Sections)
        }

        ;
        ; Place everything else remaining into SRAM (RO, RW, and ZI)
        ;
        SRAM 0x20000000 0x00010000
        {
            * (+RO, +RW, +ZI)
        }
    }

    Best Regards,
    Kent


    Hi Kent,

    It depends on how you want the project to look like.

    If the program code in RAM is created as a completely independent project, and then merged into your other project running in flash using a hex file editor, then you don't have to use scatter files. In this way you will have two separated images in your running system. This can make sure you don't accidentally call a function in flash or read it when you are programming the flash.

    If you are trying to create a project that contains code running in flash as well as code running in SRAM, then you need to define the code running in SRAM with a section name, and then use linker script to specify this section is to be copied to and executed from SRAM.

    regards,
    Joseph





  • Note: This was originally posted on 15th March 2012 at http://forums.arm.com


    You can use function pointer to do the same.


    For Cortex-M3 the low bit of the address needs to be set to indicate Thumb state, so if the starting address in RAM was say 0x20000100 (i.e. 0x20000101 is stored at 0x20000004 in the asm above).

    In C it would be

    typedef void RAM_fn_t(void);
    RAM_fn_t* fp = (RAM_fn_t*)0x20000101;
    (*fp)();


    It doesn't set SP the way the asm above does.  The cast is technically undefined behavior in C, but pragmatically it does what it looks like.

    Equivalently, if you prefer terseness/parentesis:

    (*((void (*)(void))0x20000101))();
  • Note: This was originally posted on 10th April 2012 at http://forums.arm.com

    Hi Kent,

    It depends on how you want the project to look like.

    If the program code in RAM is created as a completely independent project, and then merged into your other project running in flash using a hex file editor, then you don't have to use scatter files. In this way you will have two separated images in your running system. This can make sure you don't accidentally call a function in flash or read it when you are programming the flash.

    If you are trying to create a project that contains code running in flash as well as code running in SRAM, then you need to define the code running in SRAM with a section name, and then use linker script to specify this section is to be copied to and executed from SRAM.

    regards,
    Joseph
  • Note: This was originally posted on 14th March 2012 at http://forums.arm.com

    Do you mean your bootloader has flash programming feature, and
    want to copy the boot loader from flash to SRAM when the startup code is executed?
    regards,
    Joseph
  • Note: This was originally posted on 14th March 2012 at http://forums.arm.com

    In that case, it would be easier to copy the whole boot loader (rather than a portion of it) from flash to SRAM in the assembly startup code.
    The boot loader, assumed to be mostly written in C, will have to linked to use the SRAM address as program memory range.

    In the assembly startup code you will have a reset handler, and normally you can see something like:

    Reset_Handler   PROC
                 EXPORT  Reset_Handler    [WEAK]
                 IMPORT  __main
                 LDR  R0,=__main
                 BX     R0   ; this branch to C startup code
                 ENDP

    You can insert an assembly code to copy the memory from flash to SRAM, before jumping to the C startup code which will be in SRAM.

    Reset_Handler   PROC
                 EXPORT  Reset_Handler    [WEAK]
                 LDR  R4,=0x00000000 ; Source starting address
                 LDR  R5,=0x20000000 ; Destination starting address
                 LDR  R6,=0x4000  ; 16K program size to copy
    CopyFlashToSRAMLoop
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}   
                 LDMIA R4!,{R0-R3}
                 STMIA R5!,{R0-R3}
                 SUBS R6,#64 ; Each time 64 bytes are copied
                 BNE CopyFlashToSRAMLoop
                 IMPORT  __main
                 LDR  R0,=__main
                 BX     R0   ; this branch to C startup code     
                 ENDP

    In this way, the whole boot loader will be running in SRAM.  You need to be careful to make sure that the data use by the boot loader is not in the same address as the instruction memory.

    regards,
    Joseph
  • Note: This was originally posted on 15th March 2012 at http://forums.arm.com

    Hi Rohit,

    In this case you could develop the bootloader and flash programming code as two separate projects.
    The flash programming project is compiled and link using SRAM as program address.
    Then you can generate hex image, and insert this into your boot loader project as a constant array.
    Inside your boot loader, you can copy this constant array into SRAM.

    To jump from boot loader to flash programming code, personally I got used to use embedded assembly:

    /* ARM RVDS or Keil MDK */
    __asm void jump_to_sram(void)
    {
       LDR   R0,=0x20000000  ; starting address of program in SRAM.
       LDR   R1,[R0]  ; Get initial MSP value
       MOV   SP, R1  ; Set SP value
       LDR   R1,[R0, #4] ; Get initial PC value
       BX R1
    }

    You can use function pointer to do the same.
    regards,
    Joseph