cancel
Showing results for 
Search instead for 
Did you mean: 

Programming independent regions in the flash

Stig Hornang
Associate II
Posted on September 26, 2014 at 15:04

I'm currently using emIDE (GNU ARM) with Segger J-Link on the discovery board STM32F407VG (1 MB flash).

To be able to store configuration data in sector 1 in the flash I have modified the linker script to not generate any data for the the 16 KB between 0x08004000 and 0x08008000. The map from the linker seems to show that stuff is placed correctly. The question is now. When programming the chip, I'm assuming that emIDE converts the ELF file to hex or similar before invoking the J-Link tool. But I guess a hex file is not descriptive enough to describe non-continuous/independent flash regions to be programmed? When I try to run my code after I modified the linker script the application jumps into totally unrelated code. I can also confirm using the J-link memory inspector that the sector 1 of the flash is not empty at all. To me there seems to be a limitation in emIDE's interface to J-link, not supporting ''multiple load regions''. I would expect multiple hex files. An alternative approach which actually works is to simply skip 16 KB in the linker script using . = 32K like this (snippet):

.text :
{
. = ALIGN(4);
KEEP(*(.isr_vector))
. = 32K;

But using this approach the debug probe will overwrite the config data during program upload which very inconvenient when developing the configuration code.

7 REPLIES 7
chen
Associate II
Posted on September 26, 2014 at 15:45

Hi

''The question is now. When programming the chip, I'm assuming that emIDE converts the ELF file to hex or similar before invoking the J-Link tool. But I guess a hex file is not descriptive enough to describe non-continuous/independent flash regions to be programmed?''

The ELF file definitely has absolute addressing in the format.

If by 'Hex' you mean Intel Hex file format - then YES this format definitely has absolute addressing.

Your debugger (emIDE) should convert the .ELF into the correct protocol to talk to the Segger J-Link and program you compiled program (binary) into the device.

I suspect that you have not configured emIDE to use the linker script you have modified.

Stig Hornang
Associate II
Posted on September 26, 2014 at 16:26

Ok, then it has to be something wrong when it gets uploaded as I can see the map file changes accordingly when I modify in the linker script (so it must be read). The flash memory segment (sector 1) that is supposed to be untouched by the programmer is still filled with data when I inspect the running target's memory.

I don't really see any hex file after the compilation is completed and emIDE gives me very little insight in how it talks to J-Link. The rest of the investigation might be J-Link specific.
Posted on September 26, 2014 at 16:37

It will depend on the tools, Keil can be set up to only erase the blocks it needs to, others a more blunt force approach of erasing all memory.

The .ELF and .HEX will describe sparse memory allocations properly, .BIN not so much.

You might also want to consider making a small boot loader to reside in the first flash block, and push you application code above the blocks you are using for configuration data. This might significantly help with code updates later, and reduce the chance of bricking the part in the field. ie the boot loader does integrity checks on the app code before jumping to it, and permits a recovery download mode.

Suggest review of ST's IAP examples for a template.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chen
Associate II
Posted on September 26, 2014 at 16:38

''Ok, then it has to be something wrong when it gets uploaded''

Possibly

''I can see the map file changes accordingly when I modify in the linker script (so it must be read).''

Have you checked the entire .map file - there is a LOT of it normally?

Are you sure there are no sections, code, constant or variable data in that region/sector?

''I don't really see any hex file after the compilation is completed and emIDE gives me very little insight in how it talks to J-Link.''

I think you said you are using GNU ARM - which means you are using the GNU compiler (I think it is gcc.exe)

The GNU compiler/linker is well documented. Look up how to output a .hex (intel hex) or .srec (motorola s-record). These formats have absolute addressing in their format, and you can inspect the files in a text editor.

Check to see if the region you say should be free actually is.

Stig Hornang
Associate II
Posted on September 26, 2014 at 16:55

Your comments made me focus more on the script. It looks like it was the linker script after all. The problem seem to be that I was using the same output section name

.text

for both the vector table and the program code. I believed that the code would end up in the right place since they were pointed to two different MEMORY segments, but not with the same output section name (makes sense...)

So within SECTIONS this does not work:

.text :

  {

    . = ALIGN(4);

    KEEP(*(.isr_vector))

  } > VECTOR

  

  .text :

  {

    . = ALIGN(4);

    /* Code section */

    *(.text*)

   etc.

  } > FLASH

Where as this does:

 

.vector :

  {

    . = ALIGN(4);

    KEEP(*(.isr_vector))

  } > VECTOR

  

  .text :

  {

    . = ALIGN(4);

    /* Code section */

    *(.text*)

 

 etc.

  } > FLASH

Stig Hornang
Associate II
Posted on September 26, 2014 at 17:38

It looks I was just lucky. The original problem of placing the code correctly to memory is not a problem anymore, however I'm still struggling to get the code to run properly when the application code is separated from the vector table. It seem to be just a lucky shot with how much printf's I had in the config code that it did not crash.

I getSIGTRAP without the debugger showing anything, but stepping through show that it fails out in a FreeRTOS function:

static void prvPortStartFirstTask( void )
{
__asm volatile(
'' ldr r0, =0xE000ED08 
'' /* Use the NVIC offset register to locate the stack. */
'' ldr r0, [r0] 
''
'' ldr r0, [r0] 
''
'' msr msp, r0 
'' /* Set the msp back to the start of the stack. */
'' cpsie i 
'' /* Globally enable interrupts. */
'' cpsie f 
''
'' dsb 
''
'' isb 
''
'' svc 0 
'' /* System call to start first task. */
'' nop 
''
);
}

I to look closer at this...
Posted on September 26, 2014 at 18:10

Or that you're running in User space, and touching System registers?

Normally, you'd set up the vector table address via SystemInit() prior to going RTOS, and the task stacks would then be set up by the RTOS.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..