Hallo zusammen, vielleicht stelle ich mich momentan ja nur sau doof an, aber irgendwie komme ich nicht weiter. Ich suche einen Weg, wie ich einen STM32F1 über eine eigene Schnittstelle (in meinem Fall RS485) programmieren kann. Offenbar mache ich allerdings irgendetwas falsch, da ich nicht einen einzigen Ansatz im Web finden kann, bei dem jemand versucht hätte, diese Mikrocontroller über etwas Anderes als über JTAG/SWD zu programmieren... Kann den das sein? Gibt es denn wirklich keinen selbst geschriebenen Bootloader für den STM32? Ich hätte da nur zu gerne etwas abgekupfert, da ich noch nie einen Bootloader geschrieben habe. JTAG/SWD möchte ich allerdings umgehen, da ich meine Mikrocontroller später bevorzugt tief im System vergaben und verschraubt programmieren möchte ohne wieder das Gehäuse öffnen zu müssen. Und einen weiteren Stecker am Gehäuse möchte ich noch viel weniger. Vielen Dank Gruß Michaela
Schau mal im Ref. Manual auf Seite 60/61 unter Boot configuration (Embedded Bootloader) vielleicht hilft dir das weiter. http://www.st.com/web/en/resource/technical/document/reference_manual/CD00171190.pdf Gruß
Hallo Michaela, der STM hat standardmäßig einen Bootloader auf Usart1. Dieser kann über das Flash Downloader Tool von STM geflashed werden. Wenn du daran einen RS485 Treiber klemmst und USB zu RS485 an den Rechner klemmst, kannst du direkt flashen. Um in den bootloader modus zulangen musst du nur ein Pin (siehe Datenblatt) auf high ziehen. Gruß
Moin, > Gibt es denn wirklich keinen selbst geschriebenen Bootloader für den > STM32? Doch... hier! Wird sogar in weisser Ware von uns genutzt. Bootloader ist erstmal ein Programm wie jedes andere auch! Das einzig Interessante ist der Sprung in die Applikationssoftware (also die SW, die der Kundee nutzt. Vom Bootloader soll er vermutlich nichts mitbekommen.) Welche Fragen hast Du genau? ciao, Arne
Hi, Viel gesucht haben kannst Du nicht. Der SMT32 hat einein eigenen Bootloader mit verschiedenen Kommunikationswegeg onboard und bei ST gibt es verschiedene Application Notes und Beispiel Code wi so etwas über Ethernet, SPI, ... aussehen kann. Gruß Martin
Ein Bootloader beim STM32 ist vergleichsweise einfach. Du brauchst dich nicht damit herumzuschlagen, dass die Flashroutinen wie üblich im RAM laufen u.ä. Wenn Du magst, kannst Du direkt aus dem Flash heraus auf das Flash schreiben. Es sollte nur einen andere Erase Page sein als der Bootloader belegt. Du musst ja vorab den Flash löschen.
Hallo zusammen, also wenn ich dann jetzt alles was ihr schreibt und ich im Internet so finde zusammen bringe komme ich also zu folgendem Ergebnis: Wenn ich einen Bootloader für den STM schrieben möchte, dann ist das letztlich nichts anderes als ein normales Programm, bevorzugt am Anfang des Speichers, das beim Start des STM anläuft, prüft ob eine Programmierbedingung gegeben ist und wenn nicht, dann startet es das Benutzerprogramm, welches so compiliert werden muss, dass es ab Speicheradresse 0x8003000 läuft, vor dem Start des Programms muss natürlich noch die NVIC-Tabelle auf selbige Adresse umgebogen werden. Mit den BOOT-Pins hat das ganze allerdings nichts zu tun. Mir wird zwar nicht ganz klar, wofür die dann da sind, aber vielleicht komme ich irgendwann noch auf den Hund. Nur schade, dass es offenbar keinen fertigen Code im Internet gibt, hätte da ganz gerne einmal rein geschaut und dessen Idee versucht zu verstehen. Danke euch trotzdem Gruß Michaela
Michaela schrieb: > Mit den BOOT-Pins hat das ganze allerdings nichts zu tun. Mir wird zwar > nicht ganz klar, wofür die dann da sind, aber vielleicht komme ich > irgendwann noch auf den Hund. Nochmal ganz langsam zum mitschreiben: Die STM32 enthalten ab Werk schon einen fix und fertigen Bootloader, je nach Typ mindestens über UART. Der ist da schon drin. Immer. Und m.W. nicht löschbar. Die BOOT Pins sind dazu da, diesem Bootloader eine Chance zu geben. > Nur schade, dass es offenbar keinen fertigen Code im Internet gibt, Das könnte daran liegen, dass niemand Lust drauf hat, das Rad neu zu erfinden.
:
Bearbeitet durch User
A. K. schrieb: > Das könnte daran liegen, dass niemand Lust drauf hat, das Rad neu zu > erfinden. Es gibt in der Welt auch noch andere Wege als UART/RS485. Über CAN programmiere ich ein externes EEProm und der Bootloader überträgt die Firmware dann ins Flash. Da CAN so laaaaangsam ist, musste ich es leider so machen.
A. K. schrieb: > Das könnte daran liegen, dass niemand Lust drauf hat, das Rad neu zu > erfinden. Wenn man das Update/die Software verschlüsseln möchte, dann bleibt einem nichts anderes übrig.
Michaela schrieb: > dann startet es das > Benutzerprogramm, welches so compiliert werden muss, dass es ab > Speicheradresse 0x8003000 läuft, vor dem Start des Programms muss > natürlich noch die NVIC-Tabelle auf selbige Adresse umgebogen werden. Die konkrete Adresse kommt auf deinen Bootloader drauf an. Wie der Sprung in die Applikation auszusehen hat findest Du in den Applikation Notes. Soweit ich mich erinnere ist es kein reiner jump. > Mit den BOOT-Pins hat das ganze allerdings nichts zu tun. > Mir wird zwar nicht ganz klar, wofür die dann da sind, Mit den Boot-Pins kommst Du in den CPU internen Bootloader. Der liegt außerhalb des normalen Flashes und bleibt erhalten, auch wenn du einen eigenen Bootloader schreibst.
:
Bearbeitet durch User
Man kann den internen/eingebetteten Bootloader auch aus der eigenen Applikation anspringen ... ohne an den Pins zu ziehen.
OK hier kommt noch eine sehr konkrete Frage. Ich komme mit dem Text im Manual nicht klar: RM0008, 3.4 Boot configuration, p.60/61:
1 | The BOOT pins are also re-sampled when exiting from Standby mode. |
2 | Consequently they must be kept in the required Boot mode configuration |
3 | in Standby mode. |
Bis hier hin ist's klar, aber dann:
1 | After this startup delay has elapsed, the CPU fetches the top-of-stack |
2 | value from address 0x0000 0000, then starts code execution from the boot |
3 | memory starting from 0x0000 0004. |
Wenn mir das jemand übersetzen könnte? also nicht Englich->Deutsch, sondern... naja, Technik->Frau halt? Was passiert da? gefunden habe ich dazu bereits folgendes: Albert ... schrieb: > An Adresse 0x0000 0004 steht NUR die Adresse des Reset Handlers. Aber > die erste Aufgabe des Controllers ist es an die dort angegebene Adresse > zu springen. Er fängt also mit einem Sprung an diese Adresse an. Danach > (ab Adresse 0x0000 0008) folgen andere Interrupt Handler (die ersten 15 > sind Core spezifisch, danach folgen die Herstellerspezifischen für die > Peripherie). [...] Nur ungeklärt bleibt, was mit Adresse 0x0800 0000 passiert? Deren Inhalt wird als top-of-stack verwendet? also quasi die Initialisierung des Stack-Pointers. Und vielleicht ist mir nur der Begriff nicht geläufig aber "top-of-stack" wird das genannt, da der Stack ja "up-side-down" (im Vergleich zum Stapel Papier wie man es ja so schön beigebracht bekommt) im Speicher liegt, also sich von der höchsten Adresse abwärts aufbaut? Ist das richtig so?
Michaela schrieb: > Nur ungeklärt bleibt, was mit Adresse 0x0800 0000 passiert? Deren Inhalt > wird als top-of-stack verwendet? also quasi die Initialisierung des > Stack-Pointers. Ebendies. Bei den meisten Prozessoren findet diese Initialiserung in einem in Assembler geschriebenen Startup-Code statt. Weil man manches nicht in C machen kann, und dazu gehört die Initialisierung des Stackpointers. Eine Besonderheit der Cortex-M Prozessoren ist, dass bei Exceptions aber auch hier darauf geachtet wurde, dass alles in normalem C ohne besondere Attributierungen geschrieben werden kann. Daher erfolgt die Initialisierung des Stackpointers auf diese Art.
:
Bearbeitet durch User
A. K. schrieb: > Eine Besonderheit der Cortex-M Prozessoren ist, dass bei Exceptions aber > auch hier darauf geachtet wurde, dass alles in normalem C ohne besondere > Attributierungen geschrieben werden kann. Daher erfolgt die > Initialisierung des Stackpointers auf diese Art. Ok, wie sieht das denn dann aus? Hast du ein Beispiel dafür? Das kann ich mir gerade gar nicht vorstellen, wie man mit normalem C-Code dem Compiler mitteilen soll, dass an Adresse 0x0800 0000 ein bestimmter Wert stehen soll...
Michaela schrieb: > Das kann ich mir gerade gar nicht vorstellen, wie man mit normalem > C-Code dem Compiler mitteilen soll, dass an Adresse 0x0800 0000 ein > bestimmter Wert stehen soll... Erstens ist das kein Problem, zweitens bezog ich mich nicht auf den Code des Bootloaders, sondern auf den Code der Anwendung. *(unsigned *)0x08000000 = 0x12345678;
Michaela schrieb: > Ok, wie sieht das denn dann aus? Hast du ein Beispiel dafür? > Das kann ich mir gerade gar nicht vorstellen, wie man mit normalem > C-Code dem Compiler mitteilen soll, dass an Adresse 0x0800 0000 ein > bestimmter Wert stehen soll... A.K. hat zwar Deine Frage korrekt beantwortet, aber sie hilft in Deinem Fall wohl nicht weiter ;) Im Endeffekt willst Du die Vektortabelle ab 0x08000000 beginnen lassen. Dazu gibt es z.B. beim GCC folgenden Code
1 | |
2 | __attribute__ ((section("vectors"))) |
3 | void (* const __vector_table[]) (void) = { |
4 | |
5 | STACK_TBD, /* SP <<<<<< use linker skript definition here */ |
6 | start_cold, /* PC */ |
7 | ... /* vector #2 */ |
8 | /* etc */
|
9 | };
|
Wir benutzen den IAR, daher kann ich zu GCC nix sagen, aber das Anlegen der Section "vectors" muss dann im Linkerscript geschehen - das alles ist Compiler/Linker-abhängig. Und im Linkerscript passiert auch die Zuweisung, dass "vectors" ab 0x08000000 beginnt. Wie in einer normalen (nicht-Bootloader) Applikation auch. Einfach copy&paste! Mach Dir bewusst, welche Aufgaben Compiler bzw. Linker übernehmen, dann wird es vielleicht deutlicher. Deine Anwendungssoftware schreibst Du mit einer Vektortabelle, die sich formal von obiger nicht unterscheidet (natürlich stehen andere Startadressen zuz den ISRs drin). Im Linkerscript zur Anwendungssoftware legst Du "vectors" dann an 0x08003000 und die "text" und "data" sections dahinter. Finito! Ich weiss nicht, welchen Compiler/Linker Du nutzt, aber schau Dir mal das Linkerskript eines Beispieles irgendeiner Beispielapplikation dazu an. Den internen Bootloader konnte ich z.B. nicht nehmen, da ich noch externes SPI Flash/EEPROM über ihn füllen muss. Sowas geht mit dem internen nicht. Nochmal: der einzig interessante Aspekt m.E. ist der Sprung vom Bootloader in die Applikation in C. Wenn Du soweit bist, such ich meinen Code raus. ciao, Arne
Michaela schrieb: > Nur ungeklärt bleibt, was mit Adresse 0x0800 0000 passiert? Deren Inhalt > wird als top-of-stack verwendet? also quasi die Initialisierung des > Stack-Pointers. Der Prozessor kopiert die 32bit ab 0x08000000 in seinen Stackpointer, dann die 32bit ab 0x08000004 in den PC (Programcounter) und schon kann er loslaufen. Ab 0x08000004 steht auch nicht die Adresse von main(), sondern des StartUpCodes, den der Linker hinzupackt. Dieser Code nullt das BSS aus und kopiert das Data-Segment vom Flash ins RAM. Musst Du Dich i.d.R. nicht drum kümmern, wenn Du ein funktionierendes Linkerskript nimmst. > Und vielleicht ist mir nur der Begriff nicht geläufig aber > "top-of-stack" wird das genannt, da der Stack ja "up-side-down" (im > Vergleich zum Stapel Papier wie man es ja so schön beigebracht bekommt) > im Speicher liegt, also sich von der höchsten Adresse abwärts aufbaut? > Ist das richtig so? Ja.
Michaela schrieb: > Wenn mir das jemand übersetzen könnte? also nicht Englich->Deutsch, > sondern... naja, Technik->Frau halt? > Was passiert da? Der interne Bootloader steht im ROM, nicht im Flash, kann durch Dich nicht überschrieben werden! Er wird durch eine bestimmte Kombination von Spannungspegeln an den Bootpins in während der Resetphase aktiviert. Auch dieser interne Bootloader braucht natürlich einen SP (ab 0x00000000) und PC (ab 0x00000004). Auch er hat eine Vektortabelle, die formal wie alle anderen Vektortabellen für den M3 aufgebaut ist. Wenn Du Deinen eigenen Bootloader schreiben willst, musst Du nur darauf achten, dass die BOOT-Pins in der Resetphase nicht die Werte annehmen, dass der M3 in seinen internen Bootloader springt. Letztendlich ist die Frage: was willst Du mit einem Bootloader machen? Internes Flash löschen/schreiben? Andere Devices (I2C, SPI,...) über den Bootloader schreiben/lesen oder nur einen Bootloader schreiben, um was zu lernen?
Arne schrieb: > Der Prozessor kopiert die 32bit ab 0x08000000 in seinen Stackpointer, > dann die 32bit ab 0x08000004 in den PC (Programcounter) und schon kann > er loslaufen. Zu beachten ist, dass du dies natürlich "per Hand" nachbilden mußt, wenn Du aus deinem selbstgeschriebenen Bootloader in die Applikation springst. Die Applikation möchte ja ihre gewohnten Einstellungen vorfinden. Anmerkung: Desweiteren sollte deine Applikation die gesamte benötigte Hardware komplett initialisieren. Zumindest an einigen Stellen findet die Applikation nicht die Reset-Zustände nach Handbuch.
Steffen Rose schrieb: > Zu beachten ist, dass du dies natürlich "per Hand" nachbilden mußt Was meinst Du im Detail damit? Ich habe z.B. zwei IAR Projekte (Bootloader & Applikation). Bootloader ab 0x08000000 und Appl. ab 0x08006000. Jedes Projekt hat sein Linkerskript und gut ist. Und das funktioniert sogar in der Endanwendung damit. ;-)
Man merkt eher keinen Unterschied, wenn alles aus einer Hand kommt. Du wirst für den Bootloader und die Applikation auch den gleichen Compiler nutzen. Insofern stellt der Bootloader für sich genau das gleiche ein wie die Applikation erwartet. Wenn Du nur einen jump vom Bootloader in die Applikation aus einer Unterfunktion heraus machst, steht der Stackpointer nicht am Anfang des Stacks, wie ihn der Bootloader definiert hat. Nicht weiter schlimm. Sind ja nur ein paar Byte. Schlimm wird es erst, wenn die Applikation den Stack an anderer Stelle haben will als der Bootloader.
Steffen Rose schrieb: > Wenn Du nur einen jump vom Bootloader in die Applikation aus einer > Unterfunktion heraus machst, steht der Stackpointer nicht am Anfang des > Stacks, wie ihn der Bootloader definiert hat. Das ist richtig, korrigiere ich aber mit einem __MSR_MSP(..). Der Rest geht dann in C.
Gibt es einen Tutorial wo gezeigt wird wie man einen ganz einfachen Bootloader für STM32F1 oder F0 schreibt. ?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.