Forum: Mikrocontroller und Digitale Elektronik STM32L0 startet nicht


von A. F. (artur-f) Benutzerseite


Lesenswert?

In meinem Fall würde ich gerne die uC's vorerst mit einem I2C Bootloader 
bespielen, so dass die User Application später nachgeladen werden kann.
Meine Bootloader Implementierung ist soweit fertig. Der STM32 läßt sich 
als I2C Slave ansprechen, empfängt Daten und schreib diese ins Flash.

Den Bootloader würde ich gerne auf die letzten Pages des Controllers 
platzieren. Der uC soll den Bootloader nur bei fehlender 
User-Application starten oder per Befehl aus der User-App zum Bootloader 
springen. Sobald ich dies im Linker umsetzen, läßt sich der uC nicht 
mehr über I2C ansprechen. Im Debug Modus scheint der aber zu laufen, 
zumindest wird mir angezeigt, dass der UC in der while(1) läuft (aber 
auch keine I2C Kommunikation möglich).

Woran kann es liegen? Muss die Firmware unbedingt bei der Adresse 
0x08000000 beginnen? Oder muss neben dem Linker noch was geändert 
werden? Hatte bis jetzt alle meine Bootloaderimplementierungen immer am 
Anfang vom Flash gehabt, was funktioniert hat.


/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20002000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN  = 0x20000000, LENGTH = 8K
FLASH (rx)      : ORIGIN = 0x08006C00, LENGTH = 5K
}

von Marvin M (Gast)


Lesenswert?

Moin,
die Firmware muss bei 08000000 beginnen, dort erwartet der Controller 
die Reset/Interrupt-Vektoren.

Man muss es umgekehrt machen: Bootloader ab 08000000 und die Applikation 
dahinter. Die Interrupt-Vektoren kann man nach dem Start umbiegen.

von pegel (Gast)


Lesenswert?

Wenn Du Interrupts benutzt, muss auch der Offset der Vector Tabelle 
angegeben werden.

von A. B. (Gast)


Lesenswert?

Die Vektortabelle (zumindest initialer SP und Reset-Vektor) muss an 
Adresse 0x0 beginnen!

In Abhängigkeit vom Boot-Modus wird ab Adresse 0x0 das RAM, System Mem. 
oder eben das Flash eingeblendet. Bei Booten vom Flash muss die 
Vektortabelle zunächst also bei Adresse 0x08000000 beginnen.

von A. F. (artur-f) Benutzerseite


Angehängte Dateien:

Lesenswert?

pegel schrieb:
> Wenn Du Interrupts benutzt, muss auch der Offset der Vector
> Tabelle
> angegeben werden.

Ja schon, I2C Slave benutzt Interrupts.
Danke für den Hinweis, habe es in der "system_stm32l0xx.c" geändert auf:
#define VECT_TAB_OFFSET  0x6C00

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN  = 0x20000000, LENGTH = 8K
FLASH (rx)      : ORIGIN = 0x08006C00, LENGTH = 5K
}

Die Änderung wird im Map File auch angezeigt, leider noch ohne Erfolg. 
Der I2C Slave antwortet noch nicht.

: Bearbeitet durch User
von Mathias M. (matjes)


Lesenswert?

Für mich klingt das so, als wenn am Linker vom Bootloader irgendwas 
geändert hast. Du musst aber vor allem am Linker der Applikation was 
ändern...
(Du darfst dem Bootloader linker ruhig mitteilen, dass er nur ein paar 
kb zur Verfügung hat...)

von pegel (Gast)


Lesenswert?

https://stackoverflow.com/questions/56896375/how-can-i-change-the-start-address-on-flash

Die erste Antwort sollte passen, um nicht bei 0x08000000 starten zu 
müssen.

von pegel (Gast)


Lesenswert?

Ich nehme das zurück.
Der L0 kann die Boot Adresse offenbar nicht ändern.

von A. F. (artur-f) Benutzerseite


Lesenswert?

Mathias M. schrieb:
> Für mich klingt das so, als wenn am Linker vom Bootloader irgendwas
> geändert hast. Du musst aber vor allem am Linker der Applikation was
> ändern...

Ich habe noch keine User-Application, sondern vorerst nur den 
Bootloader.
Den möchte ich hinten im Flash haben. Später muss es möglich sein als 
der App zum BL zu springen. BL muss aber auch starten, falls keine App 
vorhanden ist.

Wenn der Reset Vector auf der Addr. 0 erwartet wird ok, aber in der 
Initphase des uCs VTOR Register zu ändern scheint auch nicht zu 
funktionieren. I2C läuft immer noch nicht.

SCB->VTOR = (FLASH_BASE | 0x6C00);

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

A. F. schrieb:
> Den möchte ich hinten im Flash haben.

Wie kommst Du da hin, wenn der L0 die Wahl der Boot Adresse nicht 
anbietet?

Bleibt eigentlich wirklich nur den BL an den Flash Anfang zu setzen.

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> Wie kommst Du da hin, wenn der L0 die Wahl der Boot Adresse nicht
> anbietet?

A. F. schrieb:
> Muss die Firmware unbedingt bei der Adresse
> 0x08000000 beginnen?


Ds ist ja die eigentliche Frage, ob es überhaupt möglich ist.

von pegel (Gast)


Lesenswert?

Wenn Du die Versorgungsspannung einschaltest, bleibt dir nur von Flash 
ab 0x08000000 oder falls vorhanden, vom Internen BL zu starten.

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> Wenn Du die Versorgungsspannung einschaltest, bleibt dir nur von
> Flash
> ab 0x08000000 oder falls vorhanden, vom Internen BL zu starten.

Und das kann man beim STM32 nicht umgehen? Schade...
Das heißt die User-App sollte für die Debugging-Zwecke auch bei 
0x08000000 starten, weil sonst die Interrupts nicht laufen werden?

von pegel (Gast)


Lesenswert?

Für das Debuging ist das egal.
Da kann deine "User-App" auch im RAM liegen.

von pegel (Gast)


Lesenswert?

A. F. schrieb:
> Und das kann man beim STM32 nicht umgehen?

Bei einigen schon, siehe oben.

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> Für das Debuging ist das egal.
> Da kann deine "User-App" auch im RAM liegen.


Ok, vielen Dank euch allen.


PS: dann funktionieren komischerweise die Interrupts nicht, wenn ich den 
Bootloader auf einer Adresse mit dem Offset starte.

: Bearbeitet durch User
von pegel (Gast)


Lesenswert?

A. F. schrieb:
> FLASH (rx)      : ORIGIN = 0x08006C00, LENGTH = 5K

Wie ist denn die letzte Flash Adresse? Welcher F0 ist es genau?

von pegel (Gast)


Lesenswert?

Ich meinte L0, wie viel Flash hat deiner?

von pegel (Gast)


Lesenswert?

Du kannst auch alles selber testen.

Leg doch mal ein Blinky auf verschiedene Positionen im Flash und im RAM.
Damit kannst Du I2C Fehler ausschließen.

von pegel (Gast)


Lesenswert?

Ich habe eben mit HAL ein Blinky auf 0x08006C00 (Größe 5k) gelegt und 
ein Offset mit:
#define VECT_TAB_OFFSET  0x00006C00U
angegeben.

Damit gibt es keine Probleme.

von pegel (Gast)


Lesenswert?

Auf einem BluePill F103.

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> Ich habe eben mit HAL ein Blinky auf 0x08006C00 (Größe 5k) gelegt und
> ein Offset mit:
> #define VECT_TAB_OFFSET  0x00006C00U
> angegeben.
>
> Damit gibt es keine Probleme.

Ich habe einen STM32L031 mit 32K, mein BL ist 4k groß. Beim Debuggen 
scheint die FW zu laufen, wenn ich auf den I2C Slave zugreife, ändern 
sich auch die SFRs für I2C, aber es erfolgt kein Sprung in die ISR. Wenn 
ich die FW auf 0x08000000 lege, läuft alles...

von pegel (Gast)


Lesenswert?

A. F. schrieb:
> Wenn ich die FW auf 0x08000000 lege, läuft alles...

Das hatte ich leider vorhin schon verstanden.
Jetzt habe ich den Flash gelöscht, ein neues Projekt angelegt und nun 
ist es bei mir auch so!

Selbst wenn ich schöne runde Werte nehme, läuft das Debug in einen 
Fehler.

Den Start von Adresse 0x08002000 hatte ich in früheren Projekten öfter 
verwendet.

Ist aber schon ein paar Updates her.

Jetzt kriege ich mein Blinky da nicht hin.

Im Moment bin ich überfragt.

Vielleicht kann noch einmal jemand anders testen?

von pegel (Gast)


Lesenswert?

Der STM32L031 hat nach AN2606 einen BL über USART2 und SPI1.
Leider keinen über I2C.

von pegel (Gast)


Lesenswert?

pegel schrieb:
> Selbst wenn ich schöne runde Werte nehme, läuft das Debug in einen
> Fehler.

Aktuell funktioniert es wieder.

Ich verstehe das nicht mehr. Reicht erst mal für heute.

von pegel (Gast)


Lesenswert?

Ich fürchte, es liegt an meinem BluePill in Kombi mit dem CubeProg.

von Mee (Gast)


Lesenswert?

pegel schrieb:
> Ich fürchte, es liegt an meinem BluePill in Kombi mit dem CubeProg.

Fake oder Original?

von pegel (Gast)


Lesenswert?

Der Gute fürn Euro. ;)

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> Ich fürchte, es liegt an meinem BluePill in Kombi mit dem CubeProg.

Bei mir laufen die Interrupts, wenn ich die gleiche FW zuvor auf Addr. 0 
starte und danach mit dem Offset (ohne full chip errase).

Ich vermute dass der uC immer auf Adresse 0 Startet...
Der einzige Weg ist wohl entweder den Bootloader tatsächlich am Anfang 
vom Flash zu haben, oder eine mini App die danach zum Bootloader oder 
der User App springt.

von pegel (Gast)


Lesenswert?

A. F. schrieb:
> den Bootloader tatsächlich am Anfang

Würde ich auch machen. Das funktioniert immer, auch wenn deine App den 
Sprung nicht schafft.

von A. F. (artur-f) Benutzerseite


Lesenswert?

pegel schrieb:
> A. F. schrieb:
>> den Bootloader tatsächlich am Anfang
>
> Würde ich auch machen. Das funktioniert immer, auch wenn deine App den
> Sprung nicht schafft.

Bin leider noch kein Stück weiter gekommen. Sobald ich das Hauptprogramm 
auf einer anderen Flashadresse im Debug-Modus laufen lassen, 
funktionieren die Interrupts nicht. Das Programm bleibt in der delay 
Funktion hängen, weil die auf SysTickCouner aufsetzt....

Vielleicht weiß es jemand, was ich evtl. übersehe?

von A. F. (artur-f) Benutzerseite


Lesenswert?

Jetzt läuft.....
Falls jemand noch die Probleme bekommen sollte:

VECT_TAB_OFFSET muss App Flash Adresse sein +4...

von Stefan F. (Gast)


Lesenswert?

Ich hatte beim Debuggen mal stundenlang einen verstecken Fehler gesucht 
der plötzlich beim Durchsteppen auftrat obwohl die gleiche Stelle wenige 
Minuten vorher noch richtig funktionierte.

Letztendlich war des Rätsels Lösung, dass ich den µC einmal kurz 
Stromlos machen musste. Was ich komisch finde, ich dachte bisher immer, 
dass der Reset Taster alles zurücksetzt.

von Ingo S. (ingo-s)


Lesenswert?

Beim M0 die Vectortable ins RAM copieren und Remap durchführen:

#ifdef BOOLOADER_START
     uint32_t *VectorTable = (uint32_t *)0x20000000;

    uint32_t i = 0;
    for(i = 0; i < 48; i++)
      VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
    //  Enable the SYSCFG peripheral clock
    LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SYSCFG);
    //   Remap SRAM at 0x00000000
    LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);
#endif

von pegel (Gast)


Lesenswert?

A. F. schrieb:
> Bei mir laufen die Interrupts, wenn ich die gleiche FW zuvor auf Addr. 0
> starte und danach mit dem Offset (ohne full chip errase).

Bei mir auch. Habe mein CN BP wohl zu Unrecht angezweifelt.

A. F. schrieb:
> Bin leider noch kein Stück weiter gekommen. Sobald ich das Hauptprogramm
> auf einer anderen Flashadresse im Debug-Modus laufen lassen,
> funktionieren die Interrupts nicht.

Ich vermute ganz stark, dass das Problem in der neu dazu gekommenen 
Datei:
1
* Debug.launch

liegt. Die Zeile:
1
<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>

hat bei mir schon mal neben value="" auch value="0x08008004" automatisch 
enthalten. Vielleicht fehlt in dieser Datei noch die Verwaltung des 
Stack Pointers o.ä.?

von Bauform B. (bauformb)


Lesenswert?

A. F. schrieb:
> Jetzt läuft.....
> Falls jemand noch die Probleme bekommen sollte:
>
> VECT_TAB_OFFSET muss App Flash Adresse sein +4...

Beim Cortex-M muss die Tabelle immer auf einer durch 128 teilbaren 
Adresse beginnen (bei größeren CPUs auch 256, 512,...). So ein offset 
ist doch Programmierer-Verarschung vom Feinsten. Sagt mal, welche IDE 
das ist, damit die niemand versehentlich installiert.

von pegel (Gast)


Lesenswert?

Ich habe jetzt für mich die Lösung gefunden.

Ich flashe auf die gewünschte Adresse (vielfaches von 0x200).
Z.B.: 0x08008000
Setze Offset der Vector Tabelle.
passend dazu: 0x8000

Kopiere die Inhalte von 0x08008000-0x08008007 nach 
0x08000000-0x08000007, also an den leeren Flash Anfang.

So lange ich die Größe der Vector Tabelle oder die Stack Obergrenze 
nicht ändere bleiben diese Werte gültig.

Falls jemand in der Lage ist, das Kopieren der 8Byte im Debug Startup 
als Befehle oder Script zu schreiben, nur her damit.

Damit würde es für alle funktionieren, ohne das man darüber nachdenken 
müsste.

von pegel (Gast)


Lesenswert?

pegel schrieb:
> Wie kommst Du da hin, wenn der L0 die Wahl der Boot Adresse nicht
> anbietet?
>
> Bleibt eigentlich wirklich nur den BL an den Flash Anfang zu setzen.

Das Problem ist mit meiner aktuellen Kopiermethode auch gelöst.
Dann wird kein Bootloader benötigt und er springt auch beim Einschalten 
zum Reset_Handler an der richtigen Position.
Damit läuft das Programm, egal wo es liegt (0x200 Schritte).

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.