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

ST STM32 STM32F2 boot loader bootloader custom STM32F207ZGT6

STM32F20x custom bootloader

Hi Everyone!

I am writing a custom bootloader for STM32F207ZGT6. I divided the 1 Mb flash into 2 sections. The first one is 128 kbytes, my bootloader is loaded to this section. The second one is 896 kbytes, my main application is loaded here. I use the following code to the jump:

typedef  void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
.
.
.

                JumpAddress = 0x08020000 + 4;
                Jump_To_Application = (pFunction) JumpAddress;
                __set_MSP(0x20000000);
                Jump_To_Application();

I pasted the "+ 4" to the code because of endianness, but I may be wrong.
My main application starts from 0x08020000. I set this in uVision.
I ran to the following problem:
When the Jump_To_Application() function is called, a HardFault is generated and its handler is called.

Anyone has a tip?

I am all ears.

Parents
  • Sorry for my very limited technical ability and English ability.

    #include <stdint.h>
    #define FW_START 0x80000000
    
    static const uint16_t launch_fw_code[] =
    {
            0xF850, 0xDB04, /* LDR.W SP, [R0], #4   */
            0x6800,         /* LDR.W R0, [R0]       */
            0x4700,         /* BX R0                */
    };
    
    int main(void)
    {
            ((void (*)(uint32_t))(1+         (int)launch_fw_code))(FW_START);    // type_A
            ((void (*)(uint32_t))(1+(unsigned int)launch_fw_code))(FW_START);    // type_B
            ((void (*)(uint32_t))(1+              launch_fw_code))(FW_START);    // type_C
    
            return 0;
    }
    


    Why the (int) is needed?
    What is the difference between type_A, type_B, and type_C?

    launch_fw_code is an uint16_t array, so it is also a constant address. I guess it must be an even address, and the 1 is to make it odd.

Reply
  • Sorry for my very limited technical ability and English ability.

    #include <stdint.h>
    #define FW_START 0x80000000
    
    static const uint16_t launch_fw_code[] =
    {
            0xF850, 0xDB04, /* LDR.W SP, [R0], #4   */
            0x6800,         /* LDR.W R0, [R0]       */
            0x4700,         /* BX R0                */
    };
    
    int main(void)
    {
            ((void (*)(uint32_t))(1+         (int)launch_fw_code))(FW_START);    // type_A
            ((void (*)(uint32_t))(1+(unsigned int)launch_fw_code))(FW_START);    // type_B
            ((void (*)(uint32_t))(1+              launch_fw_code))(FW_START);    // type_C
    
            return 0;
    }
    


    Why the (int) is needed?
    What is the difference between type_A, type_B, and type_C?

    launch_fw_code is an uint16_t array, so it is also a constant address. I guess it must be an even address, and the 1 is to make it odd.

Children
  • Why the (int) is needed? What is the difference between type_A, type_B, and type_C?

    (int) is needed because we want to add 1 to the address. We could have used (uint8_t*) instead. If you use the address of launch_fw_code without a type cast, 2 will be added instead of 1, that is sizeof(uint16_t).
    There is no difference between type_A and type_B: they yield the same result.

    I guess it must be an even address, and the 1 is to make it odd.

    Exactly.

  • I completely forgot one more thing: of course, the calculated address of the entry point should be compatible with the type of the function argument. I should have used int everywhere: it's shorter and it does the job:

    ((void (*)(int))(1+(int)launch_fw_code))(FW_START);
    

    It's kind of misleading to pass a pointer to code as an int. But making it a pointer to a function would not clear things up much: we still would have to do some type casting in order to add 1 to the address. It's still a mess.

  • Hi Mike,

    Many thanks for your explanation.

    (I regularly discover that, I am not a good C programmer.)

    (1+launch_fw_code) == &launch_fw_code[1]