STM32F2 - Flashloader

Gast #3106455
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
  }
Gast #3106480
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.
Gast #3106496
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 ?
#3106519
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 */
Gast #3106523
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
  }
Gast #3106550
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 ...
Gast #3106553
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
  }
#3106622
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?
Gast #3112014
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.
Gast #3112303
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?
#3116615
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren