Hallo lieber Forumgemeinde,
nachdem ich bei meinem letzten Projekt (PC Kommunikation zum STM32 M3
mittels USB) viele tolle Antworten erhalten habe, versuche ich es
nochmals auf diesem Weg in der Hoffnung, dass jemand die Zeit findet mir
zu helfen.
Ich habe die hier verbreitete Routine von "W.S." genommen, um eine USB
Virtual Com Port Kommunikation zu meinem PC ("Visual Studio")
herzustellen.
Ich konnte ich die HAL Library von STM Cube nicht verwenden, da mein,
für meine Verhältnisse doch recht komplexes Programm schon annähernd
fertig und ohne HAL-Libraries geschrieben war.
Hier bot die USB.c und USB.h von W.S. (hier im Forum viel diskutiert)
eine wirklich tolle Alternative.
Jetzt stehe ich vor dem Problem, dass für eben dieses fertige Programm
DFU funktionieren soll. Ich könnte über das Touch Panel gezielt in den
Firmware Modus wechseln, also in die entsprechenden Routinen springen
und dann im DFU Modus die HEX File über den PC übertragen (entsprechende
PC Software ist vorhanden)
Hat irgend jemand diesbezüglich einen Hinweis oder Software für mich die
diese Option ohne HAL ermöglicht?
Für jeden Tip bin ich dankbar...
Hallo 23mts,
danke, aber was mache ich jetzt mit den 100 Dateien?
Die überschneiden sich ja auch z.T mit meinen clock Einstellungen tec.
Am liebsten wäre mir lediglich eine DFU.c und EINE dfu.h mit einer
Funktion namens "EnterDFUMode"...
Ich würde ein neues Projekt mit der HAL erstellen und dann deine ganzen
Files dazu kopieren. Schau mal wie einfach ein hello-World mit der HAL
aussieht:
http://stefanfrings.de/stm32/index.html#vcphal
no Chance,
ich habe canbus, USB, SPI1,SPI2 am laufen incl. diverser schneller
Zähler, PWM und Timer.
Das alles jetzt nochmal zur HAL zu übertragen halte ich für schlichtweg
unmöglich, da ALLE SETTINGS neu gemacht werden müssen. Eine Katastrophe.
Das hatte ich bei der Implementierung von USB schonmal mit mäßigem
Erfolg probiert...
Die DFU-Funktionalität packt man am besten in einen eigenen Bootloader,
d.h. ein eigenes Programm und damit oft ein eigenes Binary, was vor
deiner eigentlichen Applikation im Flash liegt und als erstes ausgeführt
wird. Dieser Bootloader kann dann entweder per DFU eine neue Applikation
ins Flash laden oder wenn das nicht gewünscht ist (meist nach einem
Timeout) einfach die normale Applikation laden, die hinter deinem
Bootloader liegt. DFU-Bootloader für den F1 gibt es relativ viele. Neben
dem bereits erwähnten STM32duino/Maple Bootloader z.B.
https://github.com/PX4/Bootloader oder
https://github.com/paparazzi/luftboot .
Der Bootloader muss natürlich zu deiner Hardware passen, d.h. du musst
HSE-Frequenz und USB-Reenumerationsmethode anpassen. Ggf. dann noch
Status-LED oder was auch immer. Dann deine eigentliche Applikation an
die neue Adresse linken und den Offset der Vektortabelle setzen (VTOR).
Halli Hallo Christopher,
viiielen Dank für die ausführliche Beschriebung.
Aber leider habe ich nur ca 10% deiner Ausführungen verstanden. Ich
arbeite seit ca 2 Jahren mit dem STM und bin froh die "normalen
Funktionen" wie SPI, CAN, UART etc ans laufen gebracht zu haben.
(Arbeite mit EmBitz als Programmierumgebung und Programmiere über SWD.
Wie das flashen eines eigenen Bootloaders funktioniert weiß ich leider
nicht. Auch nicht das Einfügen der bin Datei.
Könntest du das, auch wenn es sehr ätzend für dich sein mag, ein
bisschen für blonde erklären?
Hanna schrieb:> Ich konnte ich die HAL Library von STM Cube nicht verwenden, da mein,> für meine Verhältnisse doch recht komplexes Programm schon annähernd> fertig und ohne HAL-Libraries geschrieben war.
Wenn du das alles ohne HAL hinbekommen hast, sollte es doch auch kein
Problem sein, das DFU auch noch ohne HAL umzusetzen? Du könntest dir
einen eigenen Request für den Control Endpoint bauen, bei dessen Empfang
sich das Gerät trennt und wieder als DFU-Gerät anmeldet. Alternativ
schaltest du zwischen verschiedenen Configurations um. Wenn USB an sich
schon läuft, ist doch der Empfang von Daten und das Schreiben in den
Flash machbar. Siehe z.B. auch hier USB-Tutorial mit STM32 zur
Programmierung des USB ohne HAL.
Ich glaube, jetzt hast du ihn erschreckt.
Niklas, deine Library mag eine gute Lösung sein. Doch wenn der TO sein
eigenes Projekt nicht in ein HAL Rahmengerüst hinein bekommen kann, dann
kommt er mit deiner Implementierung vermutlich auch nicht zurecht.
Hanna,
hast du schon einmal daran gedacht, einfach einen ST-Link Adapter
zusammen mit deinem Gerät auszuliefern (evtl. fest eingebaut)?
Wenn du einen mit Firmware Version 2.1 nimmst, kann man Firmware
Upgrades ganz ohne Zusatz-Software hochladen - einfach per Drag&Drop mit
dem Dateimanager.
Stefan U. schrieb:> Doch wenn der TO sein> eigenes Projekt nicht in ein HAL Rahmengerüst hinein bekommen kann, dann> kommt er mit deiner Implementierung vermutlich auch nicht zurecht.
Die Idee war mehr, dass man W.S.' Implementierung mithilfe der im
Tutorial übersichtlicher dargestellten Informationen umbaut, weniger
einfach meinen Code zu übernehmen. Es wird wohl kaum einen fertigen Code
geben, der direkt perfekt zu W.S.' VCP-Implementation passt.
Wenn man es schafft alles ohne HAL zu machen hat man offenbar schon
einiges an Verständnis. Die USB-Peripherie ist einfacher als z.B. die
vom USART...
> Die USB-Peripherie ist einfacher als z.B. die> vom USART...
Das sehe ich anders. Meine erste Hello-World Meldung hatte ich schon
nach wenigen Minuten gesendet. Man muss ja nicht gleich mit DMA
anfangen.
Hallo,
mit ST Adapter ausliefern ist zwar möglich, die SWD Anschlüsse sind
jetzt im Gehäusedesign nicht nach außen geführt :-(
Ich dachte das alles wäre einfacher. Ich verstehe hier wirklich zu 80%
nur Bahnhof :-(
Stefan U. schrieb:> Das sehe ich anders. Meine erste Hello-World Meldung hatte ich schon> nach wenigen Minuten gesendet. Man muss ja nicht gleich mit DMA> anfangen.
Ja so schnell geht es per USB nicht. Aber zähl mal die Seiten im
Reference Manual für USART und die für USB, und wie viele
Einstellungs-Register die jeweils haben...
Es sollte eigentlich ohne größere Probleme möglich sein, HAL-Code für
einzelne Komponenten ins Projekt einzubinden. Das Einbinden der HAL
zwingt einen nicht dazu, alles damit zu machen. Das Hauptproblem besteht
in eventuellen Namenskonflikten mit der Unzahl an Makros in der HAL -
aber die lassen sich durch Suchen&Ersetzen lösen. Ich habe schon HAL mit
direkten Registerzugriffen gemischt, teilweise auch beim selben
Peripherie-Modul.
Der Bootloader und die Application sind verschiedene Baustellen.
Man kann auch das HAL Beispiel für DFU_Standalone oder DFU einfach für
den Lader verwenden und das eigene Prog auf die Adresse nach dem Lader
linken.
Hanna schrieb:> Wie das flashen eines eigenen Bootloaders funktioniert weiß ich leider> nicht. Auch nicht das Einfügen der bin Datei.> Könntest du das, auch wenn es sehr ätzend für dich sein mag, ein> bisschen für blonde erklären?
Ich kann es mal versuchen.
Erstmal ist es wichtig zu wissen, wo überhaupt so ein Cortex-M anfängt
zu arbeiten. Am Anfang des Flash-Speichers liegt die
Interrupt-Vektortabelle, d.h. eine Tabelle von Funktionszeigern, welche
auf die Funktionen zeigen, die ausgeführt werden sollen, wenn ein
entsprechender Interrupt ausgelöst wurde. Der allererste Eintrag in
dieser Tabelle ist jedoch genau genommen kein Funktionszeiger, sondern
der initiale Stackpointer. Der zweite Eintrag ist dann jedoch schon
gleich der Reset-Handler und dieser wird dann auch direkt angesprungen.
Im Reset-Handler wird unter anderem die SystemInit-Funktion aufgerufen,
welche typischerweise die Clock-Konfiguration vornimmt, bevor am Ende
des Reset-Handlers die eigentliche main-Funktion angesprungen wird.
Wie schon gesagt ist die DFU-Funktionalität (in Software) in Form eines
Bootloaders (kurz BL) ein eigenes Programm. Beim von dir eingesetzten
Controller beginnt der Flash an der Adresse 0x8000000. Mal angenommen
der Bootloader hat (auf volle kB aufgerundet) 8192 Byte, dann ist der
Bereich von 0x8000000 bis 0x8001FFF mit deinem BL belegt. Wenn dein
Controller startet, dann startet er also erstmal (über den
Reset-Handler) in die main des BL. Typischerweise lauscht der BL dann
für eine bestimmte Zeit ob eine Verbindung mit DFU zu Stande gekommen
ist. Ist das der Fall, dann kann der BL deine eigentliche Applikation
(App) per USB laden und sie in den Flash schreiben und zwar hinter den
BL, d.h. in diesem Beispiel beginnend bei 0x8002000. Ist keine
DFU-Verbindung zu einem PC zu Stande gekommen, sorgt der Bootloader
dafür, dass die Applikation, welche hinter dem Bootloader liegt
ausgeführt wird, d.h. er lädt den Stackpointer wieder auf das Ende des
RAM und springt den Reset-Vektor an (den deiner App bei 0x8002000). Nun
folgt wieder das Prozedere vom Anfang, d.h. der (App-)Reset-Handler ruft
die (App-)SystemInit und (App-)main auf.
Damit deine App bei 0x8002000 überhaupt funktionieren kann muss diese
erstmal an diese Adresse gelinkt werden (statt 0x8000000). Dazu musst du
das Linkerscript anpassen (xyz.ld). Normalerweise steht da so etwas wie
1
MEMORY
2
{
3
flash (rx) : ORIGIN = 0x08000000, LENGTH = 64K
4
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
5
}
in dem Beispiel mit dem 8kB großen BL wird daraus dann
1
MEMORY
2
{
3
flash (rx) : ORIGIN = 0x08002000, LENGTH = 56K
4
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
5
}
d.h. statt 0x8000000 ist der "origin" nun bei 0x8002000 und die größe
des Flashs ist von diesem Punkt betrachtet nur noch 56kB (weil ja die
ersten 8kB vom BL belegt sind).
Jetzt hast du also den BL bei 0x8000000 und deine App bei 0x8002000
jedoch hast du jetzt auch zwei Interrupt-Vektortabellen. Ohne weiteres
Zutun würde jetzt ein Interrupt in deiner App den Interrupt-Handler des
BL aufrufen, weil dessen Tabelle nunmal am Beginn des Flash liegt. Um
das zu ändern gibt es bei den Cortex-M3 ein "Vector Table Offset
Register". In dieses Register schreibt man dann den Wert, an welchem die
"neue" Vektortabelle liegt, d.h. in diesem Fall 0x8002000, d.h.
1
SCB->VTOR=0x8002000;
Das packst du in die SystemInit deiner App oder zumindest an den Anfang
deiner (App-)main aber jedenfalls bevor irgendein Interrupt feuern kann.
Falls du die SPL nutzt, dann gibt es in der SystemInit schon ein #define
VECT_TAB_OFFSET, welches du nur anpassen musst (auf 0x2000 statt 0x0).
Wie man mit dem ST-Link Utility (mit dem Embitz daherkommt) eine Binary
an eine bestimmte Adresse flashen kann weiß ich nicht, weil ich das
Programm noch nie genutzt habe aber das ist ganz sicher möglich. Den
Bootloader flashst du ja auch ganz normal wie jedes andere Programm auch
an den Anfang des Flashes. Lediglich deine Applikation landet an anderer
Stelle.
Die STM32, die ich kenne, können USB-DFU ganz ohne eine einzige
Codezeile.
Man muss nur BOOT0 auf HIGH ziehen, zack, los gehts. Man muss natürlich
die Beschaltung haben, die im Datenblatt steht.
Der interne Bootloader macht das.
Beispielweise bei den Typen STM32F072 und STM32F303ZE ist das so. Hast
du mal geprüft, ob deine das nicht eh auch kann?
Dann kannst du die die ganze Aktion nämlich schenken. Vor allem benötigt
der interne Bootloader genau 0,0 Flash.
Wollte noch diesen Bootloader in die Runde werfen:
https://github.com/devanlai/dapboot
Habe keine Erfahrung damit, aber diese WebUSB-Geschichte klingt ganz
interessant.
Stefan U. schrieb:>> Man muss nur BOOT0 auf HIGH ziehen, zack, los gehts>> Das trifft nur auf die größeren Modelle zu.
Mir riecht das zuviel nach Bauernregel. Und Bauernregeln haben in der
Elektronik nichts zu suchen.
Der STM32F072 ist ein F0, d.h. von der Billigserie. Als "größeres
Modell" würde ich den nicht sehen. Bei uns hat der ATMEGAs ersetzt. Der
STM32F072 kann das. So ganz stimmen kann deine Aussage also nicht.
@Hanna:
Bitte nenne doch mal das konkrete Device. Dann kann man nachsehen und
Klarheit schaffen.
> Mir riecht das zuviel nach Bauernregel.
Du hast Recht, ich denke immer nur an die STM32F1 Serie weil ich mit
allen anderen STM32 Serien noch nie zu tun hatte.
Hmm schrieb:> Mir riecht das zuviel nach Bauernregel. Und Bauernregeln haben in der> Elektronik nichts zu suchen.
Der Thread-Titel klingt nach einem verunglückten Versuch, STM32F103C8T6
zu schreiben. Der ist auch sehr verbreitet bei China-Billig-Boards. Im
Titel des Datasheet steht "Medium Density". Im Reference Manual steht
auf S. 60:
* In low-, medium- and high-density devices the bootoader is activated
through the USART1 interface.
* In XL-density devices the boot loader is activated through the
following interfaces: USART1 or USART2 (remapped).
* In connectivity line devices the boot loader can be activated through
one of the following interfaces: USART1, USART2 (remapped), CAN2
(remapped) or USB OTG FS in Device mode (DFU: device firmware upgrade).
Also nur USART1.
Hanna schrieb:> Hat irgend jemand diesbezüglich einen Hinweis oder Software für mich die> diese Option ohne HAL ermöglicht?
Also nochmal alles ganz in Ruhe:
1. Du hast einen STM32Fxxx (den genauen Typ hast du nicht genannt).
2. Also sieh in den Appnotes von ST zu den Bootladern (Nummern hab ich
nicht auswendig gelernt) nach, welcher Chip welchen Bootlader
tatsächlich enthält.
3. Wenn dein Chip einen Bootlader enthält, der mit dem USB umgehen kann,
dann kümmere dich darum, wie dein Kunde diesen gezielt gestartet bekommt
- und zwar auch dann, wenn beim Firmware-Update etwas schief gelaufen
ist und die alte Firmware perdü ist.
4. Wenn dein Chip einen Bootlader enthält, der USB eben NICHT kann,
dann gehst du anders vor:
5a) du schreibst ein Programm für den PC, das per irgendeiner sinnvollen
Übertragung (heutzutage zumeist USB-->Seriell) mit dem Botlader umgehen
kann. Und dieses Programm zusammenmit einem billigen Adapter USB-Seriell
gibst du deinem Kunden.
5b) du schreibst dir einen eigenen Bootlader, der etwa so, wie
Christopher es weiter oben bereits umrissen hat, am Anfang deines
Flashes steht und in der Lage ist, den Rest deiner Firmware zu löschen
und mit neuem Zeug zu beschreiben. Dessen Speicherplatz geht natürlich
von dem Umfang des Flashes ab, so daß deine FW halt ein bissel kleiner
sein muß - und obendrein mußt du dir Gedanken machen über die benötigten
Interrupts, denn es wäre extrem töricht, beim FW-Update den gesamten
Flash neu zu schreiben. Es könnte nämlich was schief gehen und dann ist
dein Gerät erstmal gebrickt. Klaro?
Es gibt noch was zu beachten:
6. Entweder kann dein Bootlader nicht nur VCP, sondern auch
Massenspeicher, dann hat es dein Kunde leichter, weil er bloß per
Dateimanager oder so die FW auf diesen externen Massenspeicher kopieren
muß. Oder dein Bootlader kann eben nur VCP, dann mußt du wieder ein
Programm für den PC schreiben, was mit dem BL geeignet kommuniziert.
7. Gehe mal in dich und frage dich, ob es denn UNBEDINGT ein STM32 sein
soll. Grund: Bei NXP gibt es einige µC, die einen solchen Bootlader
drinhaben, der mit USB klarkommt und sich als Massenspeicher ausgeben
kann. Damit hast du das Updateproblem für deinen Kunden sehr
vereinfacht. Nen passenden USB-VCP-Treiber für den Normalbetrieb für
z.B. die LPC13.. und LPC17.. hab ich grad vor kurzem hier irgendwo
gepostet.
W.S.