cancel
Showing results for 
Search instead for 
Did you mean: 

basic bootloader for M0

stenasc
Senior
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
43 REPLIES 43
Posted on June 29, 2016 at 01:06

It's not going to be *that* different, I'd have to code something specific as that's not how I solve this kind of problem, and I'm not using M0's

Use a debugger to understand the fault.

Make sure the base address of the function into the memcpy() is EVEN, as is the destination address.

Make sure it copies the entire function and any literals it references.

Make sure it doesn't have any external references, relative address references only work when they all remain in scope.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
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
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
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

.

 

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
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on June 30, 2016 at 10:25

Thanks Clive,

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

Bob

stenasc
Senior
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
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. 

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
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
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
Senior
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