Search code examples
flashstm32jump-table

Strategies to develop STM32 in application programming


I'm looking for ideas about how to develop a In Application Programming module.

We've developed in "C" a STM32F2xx connection box for our android system. In essence this is only an multi-device to bluetooth information bridge. Now I'm thinking in how to provide a "in application programming" module to upgrade this boxes in the future from the bluetooth serial port without need a physical connection.

For me read or write to the flash is not a problem, but I need to understand how the processor runs the program, how to divide the program in different flash locations and how to jump to a concrete address at the flash memory. Where can I search for this information?


Solution

  • I intended to leave a comment but I cant because I'm rookie. So I will try an answer, be gentle.

    The method I use for IAP is:

    • Load the new firmware in a safe location (in eeprom, ext flash etc...)
    • Check the integrity of the firmware against its hash for example
    • Copy the routines for FLASH-programming the internal CPU flash into SRAM.
    • Disable ALL interrupts
    • Call the FLASH-programming routines.
    • Trigger a software reset request to boot the new firmware

    Now the above method works if you upgrading the entire firmware of the CPU. Also assumes that you dont need interrupts during the flash programming. If you do need to have interrupts during the flash programming things are a bit more complicated. You have to do some extra steps before you call the flash programming routines in order to copy all the interrupt related code into SRAM also.

    • Load the new firmware in a safe location (in eeprom, ext flash etc...)
    • Check the integrity of the firmware against its hash for example
    • Copy the routines for FLASH-programming the internal CPU flash into SRAM.
    • Disable ALL interrupts
    • Allocate enough ram to fit the vectors in.
    • Copy vectors to that address
    • Enable the interrupts you need during the flash programming.
    • Call the FLASH-programming routines.
    • Trigger a software reset request to boot the new firmware

    One important thing

    This method has a very tricky part. It is the calls between the code you have in SRAM. The compiler associates the names of the functions to addresses in the 0x0800000 memory location (which is the flash). For example the function void flash_byte(uint32_t address, uint8_t byte); lives somewhere in flash. When you copy this function to ram lets say to 0x20001000 you have to be specific in the function call. Remember you try to erase the entire flash and re-write it you can not call functions from flash. The method I use is a call via function pointers. For ex:

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    /*
     * Function pointers
     */
    typedef void (*flash_write_ft) (void);
    typedef void (*flash_sub_call_ft) (uint32_t lala);
    
    flash_write_ft      flash_write_pointer = (flash_write_ft)0;
    flash_sub_call_ft   flash_sub_call_pointer = (flash_sub_call_ft)0;
    
    /*
     *  Helper functions
     */
    size_t get_function_size (uint32_t *address) {
        size_t s=0;
        // ...
        // s = calculate size;
        return s;
    }
    
    int copy_function (uint32_t *from, uint32_t *to, size_t s) {
        // ...
        return 0;   // OK!!
    }
    
    /*
     * Flash programming functions
     */
    void flash_sub_call (uint32_t lala) {
        // lala tata
    }
    
    void flash_write (void) {
        uint32_t foo;
        // ...
        flash_sub_call_pointer (foo);   // call via pointer here
        // ...
    }
    
    int main(void) {
        size_t s;
        uint32_t *add;
    
        // Get firmware, check integrity etc...
    
        // copy to ram
        s = get_function_size ((uint32_t*)&flash_sub_call);
        add = (uint32_t*)malloc (s);
        copy_function ((uint32_t*)&flash_sub_call, add, s);
        flash_sub_call_pointer = (flash_sub_call_ft)add;
    
        s = get_function_size ((uint32_t*)&flash_write);
        add = (uint32_t*)malloc (s);
        copy_function ((uint32_t*)&flash_write, add, s);
        flash_write_pointer = (flash_sub_call_ft)add;
    
        // IAP
        flash_write_pointer ();
    
        return EXIT_SUCCESS;
    }
    

    In this example all the function calls are via pointers pointing into RAM, so when you copy them to RAM they will work.

    For extra info:

    1) flash programming manual 2) Cortex-m3 programming manual