Skip to main content
stenasc
Associate III
Jun 20, 2016 9:21 PM UTC
Question

basic bootloader for M0

Posted on June 20, 2016 at 23:21

Hello Forum,

I've been reading on the forums about custom bootloaders stored in flash and I was wondering if there was another possibility (possibly because I want to avoid messing with stack pointers, reset vectors etc.)

In my main app, I have a bootloader function, that copies the new app stored in external flash to processor flash. This bootloader function contains a number of inline functions to read from external flash and copy to processor flash. Checking the .map file, this bootloader function looks to be all located in one place.

My thought process is to copy this bootloader function into RAM at say 0x20000100 and then jump to that address as shown below

void CopyLoaderToRam(void)

{

 //   uint32_t *Ram = (uint32_t *)RAM_ADDR;

    char *Ram = (char *)RAM_ADDR;///////////// Byte Alignment test

    typedef  void (*pFunction)(void);

    pFunction RunCode;

 ptr_bootloader_fn = &bootloader;    // Find the address of the bootloader function.  

   

//    memcpy(Ram, (void *)ptr_bootloader_fn, LOADER_FLASH_SIZE); // Copy bootloader into ram

   

    

      char *boot_byte;

      boot_byte = (char *)&bootloader;

      int i;

      for (i=0; i<= 4*LOADER_FLASH_SIZE; i++)

          {

                Ram[i] = *(boot_byte+i);    

                }

             

    RunCode = (pFunction)Ram[1];       // ResetHandler (PC in second vector)

     

    RunCode();

}

Well the first issue is it doesnt seem to work as I get a hard fault.My fears are that I am overwriting some necessary data in Ram or some alignment issue. I'm not sure. 

However, is it even technically feasible in the first place and if not, why? If it is a non-starter, I would rather know at this stage. Device is a STM32F051.

Kind Regards

Bob
    This topic has been closed for replies.

    43 replies

    Tesla DeLorean
    Guru
    Jun 29, 2016 12:04 AM UTC
    Posted on June 29, 2016 at 02:04

    int TestFunc(void)
    {
    return(123);
    }
    #define FUNC_SIZE 64
    typedef int (*pFunction)(void);
    int RamFunc(void)
    {
    uint8_t Buffer[FUNC_SIZE];
    pFunction RunFunc;
    memcpy(Buffer, (void *)((uint32_t)&TestFunc & ~1), FUNC_SIZE); // Copy code
    RunFunc = (pFunction)&Buffer[1]; // +1 for Thumb code
    return(RunFunc()); // sourcer32@gmail.com
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    stenasc
    stenascAuthor
    Associate III
    Jun 29, 2016 7:16 PM UTC
    Posted on June 29, 2016 at 21:16

    Clive,

    Thank you. That works. However if I add a puts statement into the TestFunc, then its back to the HardFault. I thought I could get away with..

    int TestFunc(void)

    {

    char messg[21] = ''Hello from Bootloader'';    

     puts(messg);

     return(789);

    }

    but alas no luck. It looks like I'm not including all the function literals and references. Getting there though. Much appreciate your help.

    Bob

    .

     

    Tesla DeLorean
    Guru
    Jun 29, 2016 7:44 PM UTC
    Posted on June 29, 2016 at 21:44

    As I said, I'd approach this differently..

    In terms of understand what's going on in your situation I'd recommend reviewing a .LST file or a disassembly of the code in question. Keil's FROMELF has a disassembly option

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    stenasc
    stenascAuthor
    Associate III
    Jun 30, 2016 8:25 AM UTC
    Posted on June 30, 2016 at 10:25

    Thanks Clive,

    Will give that a go. Many thanks for your help.

    Bob

    stenasc
    stenascAuthor
    Associate III
    Jul 1, 2016 8:55 AM UTC
    Posted on July 01, 2016 at 10:55

    Hi Clive,

    It looks as if you're correct. I do need different strategy. The bootloader calls some nested functions that interact with flash. I was able to place these functions in the .data section of memory. However, these in turn call some other nested function,...too many so that it still doesnt work.

    Is it possible to place one object file (bootloader.o) in the .data section so that the whole thing resides in Ram? If so, do you thing this is a reasonable option for a bootloader strategy or should I use the general method of moving the custom bootloader to a separate location in flash and manipulate the vector table as seems to be the preferred solution out there? I'd prefer not to waste any more time trying methods that take a lot of time without much success.

    Bob

       

    re.wolff9
    Senior
    Jul 1, 2016 9:45 AM UTC
    Posted on July 01, 2016 at 11:45

    What I would do is to compile the minimal bootloader as a standalone application. That gives you ''everything you need'' in the bootloader. Also you can for example link it to be run from the 0x20000100 address where you're going to put it. 

    Next you convert that to raw binary, and that in turn you convert into 

    const char bootloader[] = {0x1a, 0x.... };

    which you put into a ''bootloader.c'' file and you link with your main application. 

    Tesla DeLorean
    Guru
    Jul 1, 2016 10:34 AM UTC
    Posted on July 01, 2016 at 12:34

    As Roger indicates, you could make a small applet as a stand-alone project, and stuff that as the payload for the copy.

    Trying to have one C file, and keep the name-space/sections separate and the library dependencies in check, is a bit of a challenge. The M0 makes it worse due to it's use of functions to very basic tasks.

    A technique I've used successfully to work with a single source file/project is to code the flashing in assembler, where everything is address agnostic, and all the dependencies are kept internal. This code can then be copied into RAM and run from any valid address. This comes from a clear understanding of the Assembler and Linker, and a register level perspective to the CPU and FLASH Controller.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    stenasc
    stenascAuthor
    Associate III
    Jul 1, 2016 12:25 PM UTC
    Posted on July 01, 2016 at 14:25

    Hi Roger,

    I can certainly give that a go. My main app will call these bootloader functions. The linker should take care of this though ???

    Regards

    Bob

    stenasc
    stenascAuthor
    Associate III
    Jul 1, 2016 12:28 PM UTC
    Posted on July 01, 2016 at 14:28

    Hi Clive,

    Yes..another way to go. I will try Rogers method first as there is less necessity for me to write assembler. Depending on how, I get on, I may have to revert to your suggestion. A bit of work for the weekend. 

    Greatly appreciate all the suggestions and help

    Bob

    stenasc
    stenascAuthor
    Associate III
    Jul 4, 2016 9:57 AM UTC
    Posted on July 04, 2016 at 11:57

    Tried this over the weekend. Compiled, linked and converted a binary from a standalone file and can get it to work for the simplest functions as before. There are a lot of flash access functions that I need to integrate into this code, so this is going to be quite time consuming.

    Before working on the standalone version, I had compiled the loader into an object file as part of the main app compilation process. I thought I could use this object file and generate a standalone binary from it that I could convert to const char. However, when I run the linker on it, I get a load of link errors where it looks to reference functions in another file. Any way to get around this or will I have to pull all these functions into the local file?

    Regards

    Bob