cancel
Showing results for 
Search instead for 
Did you mean: 

FLASH Copy / Vector Table Update / Core Reboot

nacnud_uk27
Associate II
Posted on October 19, 2009 at 08:08

FLASH Copy / Vector Table Update / Core Reboot

5 REPLIES 5
nacnud_uk27
Associate II
Posted on May 17, 2011 at 13:26

All,

I’m trying to copy blocks of flash around, including the vector table, and then reboot the MCU.

I’ve had no success so far. Does anyone have any pointers? The VERBOSE version of the code I have just now, is below.

1) g_strOTAUpdateBuffer is the source buffer ( downlaoded via HTTP over GPRS )

2) All functions that are called are located “above� strOTAUpdateBuffer in FLASH. So they never get erased.

// This is from part of the map file.

*******************************************************************************

*** PLACEMENT SUMMARY

***

''A1'': place at mem:0x8000000 { ro section .intvec };

''A2'': place at mem:0x8000800 { ro section .text };

''A3'': place at mem:0x807fbff { ro section UPDATES };

''A4'': place at mem:0x804dbff { rw section IMAGE };

g_strOTAUpdateBuffer 0x0804dc00 0x1 Data Gb ARMA_OTA_Updates.o [1]

// So the Buffer goes to 0x0804dc00 and the routines needed to copy go to 0x0807fc00

''A4'': 0x1

IMAGE zero 0x0804dc00 0x1 ARMA_OTA_Updates.o [1]

- 0x0804dc01 0x1

''A3'': 0x27c

UPDATES ro code 0x0807fc00 0xbc ARMA_OTA_Updates.o [1]

UPDATES ro code 0x0807fcbc 0x1ac stm32f10x_flash.o [1]

UPDATES ro code 0x0807fe68 0x14 stm32f10x_nvic.o [1]

- 0x0807fe7c 0x27c

#define G_INT_FLASH_MEMORY_BLOCK_SIZE 2048

#define INT_LIVE_READ_ADDRESS 0x8000000

I know I need

// Grant us access to writing flash memory

FLASH_Unlock();

To Write to the FLASH, before anyone says. And I’ve thought that to take the Interrupt table out of the loop I’d stop the interrupts

// Turn off interrupts.

OS_DI();

But then I had a feeing that I could “de-init� some hardware too.

RCC_DeInit();

NVIC_DeInit();

// Clear Down TIM4 Configuration

TIM_DeInit(TIM4);

USART_DeInit(USART1);

USART_DeInit(USART2);

None of this seems to work. Anyone got any procedural suggestions?

Oh, and the code. Anything really silly here?

// Now, Erase enough space in the FLASH system to store our downloaded data

intPages = intLen / G_INT_FLASH_MEMORY_BLOCK_SIZE;

intPages++;

intLastAddress = ( intPages * G_INT_FLASH_MEMORY_BLOCK_SIZE ) + INT_LIVE_READ_ADDRESS;

if ( intLastAddress < (int)&g_strOTAUpdateBuffer[0] )

{

// Here we have space. So get to clearing the space

pintSource = (int*)INT_LIVE_READ_ADDRESS;

for ( intCurPage = 0 ; intCurPage < intPages ; intCurPage ++ )

{

FLASH_ErasePage ( (u32)pintSource );

pintSource += G_INT_FLASH_MEMORY_BLOCK_SIZE;

}

// Now, we have to copy our new code over the old code! Page

// at a time. Take it easy 🙂 This section is critical.

pintSource = (int*)&g_strOTAUpdateBuffer[0];

pintStorage = (int*)INT_LIVE_READ_ADDRESS;

for ( intCurPage = 0; intCurPage < intPages ; intCurPage ++ )

{

for ( intCounter = 1; intCounter < (G_INT_FLASH_MEMORY_BLOCK_SIZE/4) ; intCounter ++ )

{

intTemp = *pintSource;

FLASH_ProgramWord ( (u32)pintStorage, intTemp );

pintStorage ++;

pintSource ++;

}

}

// NVIC_GenerateSystemReset();

NVIC_GenerateCoreReset();

}

hbliek
Associate II
Posted on May 17, 2011 at 13:26

Not sure if ''NVIC_GenerateCoreReset()'' works, at least I never got it working. Now I'm using the IWDG with a short timeout followed by a while(1).

clive2
Associate II
Posted on May 17, 2011 at 13:26

On a 64KB RAM part I use the following sequence to restart the system and get it into the system loader. I use different keys to perform other critical functions prior to enabling other features, or dropping into the main application. ie Instead of disabling features on a running system, I reboot and do the work in a very controlled set of conditions with no interrupts or anything else. I would do this in assembler, and avoid using library code, again to control the conditions, and limit the code called outside my control.

*((unsigned long *)0x2000FFF0) = 0xDEADBEEF;

NVIC_GenerateSystemReset();

Then very early in the restart in STM32F10x.s

Reset_Handler PROC

EXPORT Reset_Handler [WEAK]

IMPORT __main

LDR R0, =0x2000FFF0

LDR R1, =0xDEADBEEF

LDR R2, [R0, #0]

STR R0, [R0, #0] ; Invalidate

CMP R2, R1

BEQ Reboot_Loader

; ldr r1, =0xDEADxxxx

; cmp r2, r1

; beq Function_xxxx

LDR R0, =__initial_sp

LDR R1, =0x20010000

LDR R2, =0xE5E5E5E5

Clear_Heap

STR R2, [R0, #0]

ADD R0, #4

CMP R0, R1

BNE Clear_Heap

LDR R0, =__main

BX R0

ENDP

ALIGN

Reboot_Loader PROC

EXPORT Reboot_Loader

LDR R0, =0x1FFFF000 ; System Loader ROM

LDR SP,[R0, #0] ; Initial Stack

LDR R0,[R0, #4] ; Initial Program Counter

BX R0

ENDP

I also have other code, not shown, which copies some efficient self-contained assembler code to do the flashing from RAM. I'll note that is possible to program the entire flash page without toggling the PG bit for every word/half-word. I also blank check pages before erasing them, and skip writing pages which are full of 0xFF.

I have a GSM modem pulling new firmware using HTTP (scary huh?), which it sticks into a free region of flash, once it has a valid image it starts a reboot/flash/run sequence. The reboot checks for a startup signature, and validates the image before erasing/flashing a page at a time. Once it has that completed it executes the new code. I also export the vector address so the linker does the work and I don't have any #define's to screw up.

extern void * __Vectors; // exported, must be suitably aligned

NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location

The app code can be anywhere in FLASH/RAM provided the vector table is suitably aligned.

-Clive

clive2
Associate II
Posted on May 17, 2011 at 13:26

This code incorrectly determines the number of pages when the size is an exact multiple of the page size. It will be one too big when this occurs, erasing the page beyond the range you expect.

// Now, Erase enough space in the FLASH system to store our downloaded data

intPages = intLen / G_INT_FLASH_MEMORY_BLOCK_SIZE;

intPages++;

The code should be

intPages = (intLen + G_INT_FLASH_MEMORY_BLOCK_SIZE - 1) / G_INT_FLASH_MEMORY_BLOCK_SIZE;

This will round up correctly. ie 0x8000 would be 16 pages on a 512KB part.

-Clive

nacnud_uk27
Associate II
Posted on May 17, 2011 at 13:26

Clive1,

Thanks for your input in both your messages. That’s a good way of thinking of things that you have, vis-à-vis the boot process. The Atari-ST used to use a “magic� number to validate the reset vector and I was reminded of that approach by your comments.

As I know that my image is located at g_strOTAUpdateBuffer then I can use the said magic number business to do something with it at reset. That’s the approach I’ll use I feel. Nice one.

I hope I can get NVIC_GenerateSystemReset(); to actually do something. I’m using an RTOS too, so I have to quiet that down as well.

And as for the intPages business; one more is okay:) Thanks for the ''solution'' in any case though.

Most helpful all in. I’ll write back when I can’t get NVIC_GenerateSystemReset(); to anything 🙂 As hbliek said, NVIC_GenerateCoreReset() seems to do very little:)

Cheers man, and thanks hbliek.

Dunk