cancel
Showing results for 
Search instead for 
Did you mean: 

Flash and jump to code

luke2
Associate II
Posted on March 09, 2016 at 04:52

I am constructing a program on the STM32F030 and am trying to flash a small segment of code to an available area of flash and them executing it. Although I can get a whole bootloader to work from examples, this is not the solution I am after - all I want to do is flash a method that can be called from my main program and returns a value (using the same stack, heap, etc). Unfortunately though after I flash and try to jump to the code my program is hard faulting and I can't figure out what's going on. I tried to adapt some code I found on these forums but it still faults. My code is something like the following:

#define APPLICATION_ADDRESS     (uint32_t)0x08003000

typedef int (*pFunction)(void);

uint32_t FLASH_If_Erase(uint32_t StartSector) {

  uint32_t flashaddress;

  flashaddress = StartSector;

  while (flashaddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)

  {

    if (FLASH_ErasePage(flashaddress) == FLASH_COMPLETE)

    {

      flashaddress += FLASH_PAGE_SIZE;

    }

    else

    {

      /* Error occurred while page erase */

      return (1);

    }

  }

  return (0);

}

uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint16_t DataLength) {

  uint32_t i = 0;

  for (i = 0; (i < DataLength) && (*FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)

  {

    /* the operation will be done by word */

    if (FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i)) == FLASH_COMPLETE)

    {

     /* Check the written value */

      if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data+i))

      {

        /* Flash content doesn't match SRAM content */

        return(2);

      }

      /* Increment FLASH destination address */

      *FlashAddress += 4;

    }

    else

    {

      /* Error occurred while writing data in Flash memory */

      return (1);

    }

  }

  return (0);

}

void run() {

  FLASH_Unlock(); // Unlock the Program memory

  FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_BSY);   // Clear all FLASH flags

static const uint16_t code[] = { 0xF04F, 0x007B, 0x4770, 0x0000 }; // payload

int16_t size = 2; // Size of code in words

uint32_t flashdestination = APPLICATION_ADDRESS;

uint32_t ramsource = (uint32_t)code;

    FLASH_If_Erase(APPLICATION_ADDRESS);

    if (FLASH_If_Write(&flashdestination, (uint32_t*)ramsource, size)  == 0) {

     uart_print(''Flash success\n\r'');

pFunction RunCode;

uint8_t *Buffer = (uint8_t *)APPLICATION_ADDRESS;

RunCode = (pFunction)&Buffer[1]; // +1 for Thumb code

uint32_t v = RunCode();   // Hard fault occurs here...

   }

    else {

    uart_print(''Flash failed\n\r'');

    }

}

Thoughts?

3 REPLIES 3
Posted on March 09, 2016 at 06:00

Thoughts?

The opcodes in question would require a Cortex-M3 or M4

For the Cortex-M0 try

static const uint16_t code[] = { 0x4800, 0x4770, 0x007B, 0x0000 }; // payload

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
luke2
Associate II
Posted on March 09, 2016 at 06:31

That worked, but one question: if I want to write a C method and compile it into binary that can be flashed in this way how would I go about it? Is it possible to compile a method on its own and extract its binary? Presumably I would need to configure the linker to use appropriate memory locations (however that is done).

Thanks again

Posted on March 09, 2016 at 14:49

You can use the linker to provide address and context information, the object output can then be converter to a hex or binary image, usually with tools that complement the linker. You can also code your own tools to get it into a format you want. ie a payload array in C format.

The single entry/exit point really means that your code should be free standing, and not have other dependencies, or use RAM resources. You'd ideally want it to be a single function, that use auto/local variables on the stack, and doesn't call libraries. You could pass in a structure pointer that describes other functions in your primary code, like malloc(), and free(), if your routine needs to use RAM resources. It is going to take a different coding style, and awareness of the underlying execution environment.

You could also use an object file format, like ELF, or something else, where you load the image into RAM, and then fix-up external references to library and other functions, so they aren't part of the loaded image. The equivalent to how a DLL loads in the Windows environment.

I guess you'd want to review Compiler, Linker and Loader texts if these concepts are not familiar.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..