Forum: Mikrocontroller und Digitale Elektronik STM32F2 - Flashloader


von Leon (Gast)


Lesenswert?

Hallo,

ich habe für einen STM32F2 eine Flashloader Applikation erstellt.
Diese Applikation liegt ab der Adresse 0x08006000 im Flashspeicher.
Meine Hauptapplikation beginnt ab der Adresse 0x08000000. Bei 
Updatevorgang wird von der Hauptapplikation in die Flashloader 
Applikation gesprungen. Dort werden die Daten (befinden sich zunächst im 
RAM) ab der Adresse 0x08000000 kopiert. Anschließend erfolgt der Sprung 
auf die Adresse 0x08000000. Wenn ich nun die neue Firmware starten 
möchte. muss ich immer die Spannungsversorgung entfernen und wieder 
anschließen. Danach läuft erst die neue Firmware. Wie kann der 
Mikrocontroller einen Software Reset ausführen ?

1
  if (((*(__IO uint32_t*)0x08000000) & 0x2FFE0000 ) == 0x20000000)
2
  {
3
    JumpAddress = *(__IO uint32_t*) (0x08000000 + 4);
4
    /* Jump to user application */
5
    Jump_To_Application = (pFunction) JumpAddress;
6
    /* Initialize user application's Stack Pointer */
7
    __set_MSP(*(__IO uint32_t*) 0x08000000);
8
    Jump_To_Application();
9
  }

von Leon (Gast)


Lesenswert?

Es gibt eine Möglichkeit den STM32 Mikrocontroller per Software neu zu 
starten:
1
 // restart system
2
 NVIC_SystemReset();

Ich habe die Funktion in meiner Flashloader Applikation eingebaut.

Variante 1:
1
  if (((*(__IO uint32_t*)0x08000000) & 0x2FFE0000 ) == 0x20000000)
2
  {
3
    JumpAddress = *(__IO uint32_t*) (0x08000000 + 4);
4
    /* Jump to user application */
5
    Jump_To_Application = (pFunction) JumpAddress;
6
    /* Initialize user application's Stack Pointer */
7
    __set_MSP(*(__IO uint32_t*) 0x08000000);
8
 
9
    // restart system
10
    NVIC_SystemReset();
11
12
    Jump_To_Application();
13
  }

Variante 2:
1
  if (((*(__IO uint32_t*)0x08000000) & 0x2FFE0000 ) == 0x20000000)
2
  {
3
    JumpAddress = *(__IO uint32_t*) (0x08000000 + 4);
4
    /* Jump to user application */
5
    Jump_To_Application = (pFunction) JumpAddress;
6
    /* Initialize user application's Stack Pointer */
7
    __set_MSP(*(__IO uint32_t*) 0x08000000);
8
     Jump_To_Application();
9
10
    // restart system
11
    NVIC_SystemReset();
12
  }

In Variante 1 vor Jump_To_Application macht dieser Funktionsaufruf 
keinen Sinn auch die zweite Variante macht auch keinen Sinn.

von Peter P. (Gast)


Lesenswert?

Hi Leon,
ich arbeite gerade an einem ähnlichen Projekt. Vielleicht ist dein 
Fehler, dass du nicht alle Interrupts und die RCC zurücksetzt bevor du 
in die Application springst? Was ich auch noch sehe du springst ja zum 
Bootloade 0x80000000 und nicht zur user App, ist das gewollt? Hast du 
dir das so gedacht, dass du nach dem Flashen wieder zum Anfang springst, 
der Bootloade keinen Input bekommt und denn von dort zur Userapp 
springt? Oder liegt dein Bootloader an einer anderen Stelle im Speicher 
und die UserApp ist an 0x8000000?

Hast du ne Mailadresse unter der man dich erreichen kann oder kannst du 
dich anmelden? Denn können wir vielleciht etwas code hin und her 
schicken? welche Schnittstelle benutzt du ?

von Peter P. (Gast)


Lesenswert?

ahh gerade gesehen.. die app liegt an 0x8006000-> Denn musst du da auch 
hinspringen nah deinem Bootloader.. und vorher hinter dir aufräumen also 
interrupts aus..etc

von Phantomix X. (phantomix)


Lesenswert?

NVIC_SystemReset();


Der Aufruf macht natürlich auch keinen Sinn, wenn du dir die Funktion 
weggelöscht hast und sie in der neuen Firmware-Version ganz woanders 
liegt. Besser kopier dir den Inhalt dieser Funktion an die Stelle wo 
du's brauchst:
1
  //NVIC_SystemReset();
2
3
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
4
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
5
                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
6
  __ASM volatile ("dsb");//__DSB();                            /* Ensure completion of memory access */
7
  while(1);                                                    /* wait until reset */

von Leon (Gast)


Lesenswert?

Hallo Peter die Flashloder Applikation befindet sich immer ab der 
Adresse 0x80006000. Die User Applikation befindet sich ab der Adresse 
0x80000000.
In der User Applikation kopiere ich zunächst die neue Firmware in das 
interne RAM. Die Daten werden via CAN an den Mikrocontroller gesendet.
Nachdem die Daten im RAM kopiert wurden, wird in die Flashloader 
Applikation Adresse 0x80006000 gesprungen. In der Flashloader 
Applikation wird dann die neue Firmware, die sich im RAm befindet, in 
den Flashbereich ab Adresse 0x80000000 kopiert. Im Anschluss erfolgt 
dann ein Sprung von 0x80006000 an die Adresse 0x80000000. (Siehe unterer 
Codeausschnitt)
1
  if (((*(__IO uint32_t*)0x08000000) & 0x2FFE0000 ) == 0x20000000)
2
  {
3
    JumpAddress = *(__IO uint32_t*) (0x08000000 + 4);
4
    /* Jump to user application */
5
    Jump_To_Application = (pFunction) JumpAddress;
6
    /* Initialize user application's Stack Pointer */
7
    __set_MSP(*(__IO uint32_t*) 0x08000000);
8
    Jump_To_Application();
9
  }

von Peter P. (Gast)


Lesenswert?

Hmm dadurch, dass du mit deinem von deinem Bootloader ja auch zum 
resetHandler springst, genau wie es bei strom aus und wieder an der Fall 
ist, kann es nur daran liegen, dass du in deinem Bootloade irgendetwas 
verstellst?? Probiers mal damit vor dem setzen des pointers alle 
interrupts auszuschalten, die benutzt du ja wahrscheinlich für can ...

von Leon (Gast)


Lesenswert?

Hab ich bereits getestet. Funktioniert immer noch nicht.
1
  __disable_interrupt();
2
3
  if (((*(__IO uint32_t*)0x08000000) & 0x2FFE0000 ) == 0x20000000)
4
  {
5
    JumpAddress = *(__IO uint32_t*) (0x08000000 + 4);
6
    /* Jump to user application */
7
    Jump_To_Application = (pFunction) JumpAddress;
8
    /* Initialize user application's Stack Pointer */
9
    __set_MSP(*(__IO uint32_t*) 0x08000000);
10
11
    Jump_To_Application();
12
  }

von Peter P. (Gast)


Lesenswert?

hat dein versuch mit :
NVIC_SystemReset();
denn funktioniert?

von Leon (Gast)


Lesenswert?

Hab die Funktion bereits eingesetzt und getestet. Siehe Post Datum: 
28.03.2013 13:09. Wo müsste ich diese Funktion aufrufen ?

von Peter P. (peter---p)


Lesenswert?

Ja eingesetzt... aber nicht gesagt was dabei rauskommt ;)

Nach nochmaliger überlegung bringt die Funktion allerdings nichts weil 
du ja wahrscheinlich den Vectortableoffset auf 0x6000 gesetzt hast...

Du könntest es höchstens nochmal mit :
myadress=0x08000000;
NVIC_SetVectorTable(NVIC_VectTab_FLASH,
(uint32_t)&myadress);

versuchen bevor du den rest durchführst..

Habe mich jetzt mal angemeldet. Am besten du schickst mir oder postest 
hier mal den gesamten bootloadercode vielleicht sieht man denn was 
schief geht....


PS: hast du mal mit dem Debugger geschaut? Welche IDE benutzt du und 
welche optimierung hast du beim compiler eingeschaltet?

von Leon (Gast)


Lesenswert?

Hallo,

wo müsste ich diesen Code einfügen ?
1
uint32_t myadress=0x08000000;
2
NVIC_SetVectorTable(NVIC_VectTab_FLASH,(uint32_t)&myadress);

von Leon (Gast)


Lesenswert?

Hallo,

wo müsste ich diesen Code genau einfügen ?
1
uint32_t myadress=0x08000000;
2
NVIC_SetVectorTable(NVIC_VectTab_FLASH,(uint32_t)&myadress);

von Leon (Gast)


Lesenswert?

Nun habe ich mal folgendes getestet:
1
  uint32_t myadress=0x08000000;
2
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, (uint32_t)&myadress);
3
4
  //jump to application via function pointer
5
  int * address = (int *)0x08000004;
6
  // jump; actually call
7
  __set_MSP(*(int*)0x08000000);
8
  *(int*)0xE000ED08 = 0x08000000; // VTOR: set the vector table of app
9
  ((void (*)())(*address))();

Das Verhalten dies gleich. Es wird kein Reset ausgeführt.

von Leon (Gast)


Angehängte Dateien:

Lesenswert?

Wenn ich in IAR den Reset Button betäütige, erscheint folgende Meldung:
(siehe Bild im Anhang)

von Leon (Gast)


Lesenswert?

Mit folgenden Codezeilen funktioniert der Software-Reset:
1
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
2
3
  NVIC_SystemReset();

Allerdings funktioniert die neue Applikation nicht ganz so wie sie 
sollte.
Zuvor in der alten Applikation wird alle 200ms eine CAN Botschaft 
gesendet. Nachdem Flashvorgang wird zwar die neue Applikation gestartet, 
die CAN Botschaft sollte nun alle 50ms gesendet werden. In dem CAN Trace 
Fenster siehe ich die CAN Botschaft mal mit einer Zykluszeit von 50ms 
bzw. 200ms. Wahrscheinlich wurde der RAM Bereich nicht neu 
initialisiert. Was mache ich da möglicherweise noch falsch?

von Leon (Gast)


Lesenswert?

Schade, dass sich bis jetzt keiner gemeldet hat. Ich komme nicht 
weiter.Für jeden Ratschlag bin ich sehr dankbar.

von peter m. (bastler788)


Lesenswert?

hallo,
hab deinen beitrag erst jetzt gesehen. ich bin an einem ähnlichen 
program dran. ich möchte einen bootloader schreiben den ich an die 
adresse 0x08000000 schreibe, wenn ich hierbei eine andere adresse wähle 
bekomm ich von der entwicklungsumgebung keil eine fehlermeldung, 
deswegen auf diese. das hex file schreibe ich ab der adresse 0x08004000 
ins flash. das funktioniert auch, also alles steht richtig im flash. 
anschließend möchte ich an die adresse 0x08004000 springen, aber hierbei 
passiert nichts, also das programm ab der adresse 0x08004000 wird nicht 
ausgeführt. die IRQ Vektor tabelle änder ich.

kannst du vlt mal deinen code hochladen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.