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-M0: How to switch from one program to another

Hi,

In my Cortex-M0 project, there are two program images residing at different memory locations: 0x0000_0000 and 0x0010_0000.  Each program has its own vector table.  M0 will boot from the program at 0x0010_0000 then switch to the other program (0x0000_0000) at the end.

What is the correct way to switch to the porgram at 0x0000_0000?  I'm not sure whether the following instructions are correct or not.

     LDR     R6, =0x1                             ; set R6 to 0x0000_0001 due to Thumb mode

     LDR     R0, [R6]

     MOV     SP, R0

     LDR     R1, [R6, #4]

     BX      R1

Can someone please point me the right implementation?  Thanks a lot.

  • It looks that you are already having two vector tables as well. In that case, you change the VTOR and perform a reset. I am not sure if this is the correct way.

    By the way, what is really the need of having 2 images?

    jyiu's book Definitive guide to Cortex M3, M4 gives some similar examples (Chapter 7, section 7.5)

    Which MCU it is?

  • gopal.amlekar: It can be useful having two images, where image#1 may update image#2 (for firmware update purposes). If image#2 is not present, image#1 could be either waiting for firmware or execute a 'default' or 'bare minimum' firmware.

    Normally image#1 would execute image#2 almost immediately (right after verifying that it actually makes sense and is a valid image).

    jacobbeningo wrote an excellent document on the bootloader subject called Bootloader Design for MCU's in Embedded Systems.

    You may also be interested in Does anyone know how I can remotely update code to distant arm system?

  • Thanks jensbauer, So it is similar to bootloader app I guessed. Some MCUs have inbuilt bootloader, isn't it? I think STM32F4 has one.

    Also in this particular case, if VTOR is updated in the image #1, then it would later always execute image #2 when power cycled. It won't be able to get back to image #1 unless VTOR is again changed to vector table of image #1. 

  • Changing VTOR isn't permanent; it's just like any other hardware register, and has a default on startup.

    -So power-cycling will always execute image#1 in this particular case.

    Most microcontrollers have a boot-ROM, yes. This makes it possible to program the devices in other ways than JTAG and SWD, for instance via UART or USB, but this of course depends on the boot-ROM code.

  • Thanks. I had this misunderstanding of VTOR..

  • Hi wshen,

    I wonder how do you start from 0x0010_0000. If it is possible, I think the reset vector 0x0010_0000 is located at 0x0000_0004. When is the vector table on 0x0000_0000 replaced? Does your system have not flash but SRAM as the vector table?


    Best regards,
    Yasuhiko Koumoto.

  • Thank you, jensbauer.

    There is an issue while compiling this line: "ldr     sp,[r0]"

    Error: A1875E: Register Rt must be from R0 to R7 in this instruction

    The shorter code encounters a different issue at this line: "ldmia     r0!, {sp,pc}"

    Error: A1874E: Specified register list cannot be loaded or stored in target instruction set

    My toolchain is RVDS_4.1_sp1_build713 armcc/armasm/armlink.  Do I miss something here?

  • I think forgot that you're using Cortex-M0 for a while, sorry about that. To fix the ldr sp,[r0], you'll just need to do for instance...

                movs        r0,#0

                ldr         r1,=SC

                str         r0,[r1,#VTOR]

                ldr         r1,[r0]

                mov         sp,r1

                ldr         r1,[r0,#4]

                bx          r1

    ... I believe that should fix it. The shorter version, probably won't be fixable; I guess I got too used to Cortex-M3/Cortex-M4.

  • Yes I'm using Cortex-M0.  So there is no VTOR in the System Control block.  This leads to the compiling error of these two lines,,, 

                movs        r0,#0

                ldr         r1,=SC

  • According to the documentation, on Cortex-M0, the exception vector table is fixed at address 0x00000000.

    However, since a vendor can customize the behaviour of virtually anything, I know of one implementation, which allows you to change it, though; perhaps there are more.

    Fortunately, Cortex-M0+ has a VTOR.

    Which device in particular are you writing code for ?

  • Cortex-M0, not Cortex-M0+.

  • Hi wshen,

    I would like to ask you how you can have two set of vector tables.

    Best regards,
    Yasuhiko Koumoto.

  • Hi Yasuhiko,

    It appears I have misunderstanding of vector tables on M0.  There could be only one vector table existing on M0.

    Thanks,
    wshen

  • If you can replace the Cortex-M0 by a Cortex-M0+, you would have the VTOR, so you could change vector tables.

    Sometimes the vendor of the device makes a pin-compatible device that can replace it.

  • Now, this question keeps occupying my mind.

    If you're only going to copy code to the RAM, then you could also do one of these things:

    1. Create fixed addresses for interrupt service routines (not really a good solution).
    2. Create indirect interrupt service routines. These are not completely 'transparent' but will forward interrupt-invocations "manually".
    3. Create 'ramcode' or 'fastcode' sections in your linker-script, and then have your startup-code copy small code snippets from Flash-memory to SRAM when the microcontroller starts up. This requires no modifications of the vector tables, these will be fixed and point to the SRAM address.

    If you're interested in solution #3, I could send you an example linker-script and some startup-code. I could also write a document about it.