Forum: Mikrocontroller und Digitale Elektronik CH32V003: Probleme mit Bootloaderspeicherbereich


von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

Ich möchte einen UART-Bootloader für den CH32V003 unter Linux haben. 
Zuerst dachte ich: aktiviert man den Bootloader, der im 
Auslieferungszustand gespeichert ist und es ist gut.

Nein, es ist nicht gut: denn wie es aussieht, wahrscheinlich mache ich 
einiges falsch), muß man den Bootloader aktivieren und aus der Firmware 
heraus starten.

Ich möchte aber einen Bootloader haben, an den ich eine serielle 
Schnittstelle anschließe (über USB2UART-Bridge) und mit dem ich dann den 
Chip flashen kann.

Also habe ich mich an's Werk gemacht, weil ich dachte, dass das nicht so 
schwierig sein kann, für AVR und STM8 habe ich so etwas ja auch schon 
gemacht (wobei: der Optiboot für den AVR nicht zu toppen ist).

Meine gemachten Schritte:
- Hostprogramm für andere Controllerfamilie zur Steuerung eines 
Bootloaders anpassen
- Bootloader Linkerscript von CH32FUN verwenden
- Kommunikationsfunktionen im Bootloader schreiben, läuft mit 48MHz int. 
Takt, 115200 Baud
- entsperren des Flashspeicherschreibschutz
- zur Fehlersuche im Bootloader eine kurze Hexdump-Funktion integrieren 
damit ich sehen kann, was im Flashspeicher passiert ist.
- Funktion zum löschen des Flashspeichers (Testweise gesamten Speicher 
löschen, Sektoren zu je 1 kByte löschen)
- Entgegennahme von zu schreibenden Bytes und schreiben dergleichen im 
Flashspeicher

Was funktioniert:
- Nach Poweron startet der Bootloader
- aktuell zur Fehlersuche gibt der Bootloader nach Nichteingehen des 
Kommandos zum Schreiben einer neuer Firmware einen (kurzen) 
Hexdump-Ausschnitt aus einem wählbaren Speicherbereich aus
- nach der Ausgabe des Hexdumps startet das Userprogramm

So, jetzt wird es "schwierig"
- es kann jeder Speichersektor mit Bytes beschrieben werden und werden 
dort auch korrekt abgelegt, Bootloader bleibt aktiv

Mit einer sehr fatalen Ausnahme: Ich kann die Programmbytes NICHT ab 
Adresse 0x8000000 (Bootvektor des Userprogramms) ablegen. Hierfür muß 
ich den Flashspeicher eben ab Adresse 0x8000000 löschen und das Programm 
dort hinschreiben. Lösche ich den Speicher dort bleibt der Bootloader 
hängen und der Chip macht nichts mehr.

Das Kuriose hier ist jetzt: Flashe ich ein x-beliebiges Programm (nicht 
den Bootloader) mittels RVSWDIO ist der Bootloader wieder da.

Gleiches gilt, wenn ich mittels minichlink -E den gesamten 
Firmwarespeicherbereich lösche, hängt sich der Bootloader auf. Wird ein 
x-beliebiges Programm aufgespielt, ist der Bootloader wieder da.

Wie bekomme ich das hin, dass ich den Speicherbereich ab 0x8000000 
löschen und dann beschreiben kann und ein installierter Bootloader aktiv 
bleibt (damit das Userprogramm dann startet)?

Versuche (aber eben eher verzweifelte Versuche) mit den Optionbytes die 
bspw. einen Bootloader erst aktivieren, haben nichts gebracht. Außerdem: 
wird einfach ein neues Userprogramm aufgespielt ohne die Optionbytes zu 
verändern, ist der Bootloader ja wieder aktiv.

Im Anhang:
- Screenshot der Terminalausgabe des Bootloaders, wenn ein 
Blinklichtprogramm an die Adresse 0x8002000 geschrieben wird (natürlich 
ist das ein Programm für 0x8000000, mir ging es hier nur darum zu sehen, 
ob auch alles richtig geschrieben wurde)
- die Funktionen die ich benutze um Flashspeicher zu löschen und zu 
schreiben.

Etwas zum Schluß noch:

Erstelle ich ein Linkerscript für ein Userprogramm ab 
Flashspeicheradresse 0x8000800
und schreibe ein Programm (an Adresse 0x8000000) das nichts anders 
macht, als das Userprogramm anzuspringen und schreibe ich mittels 
Bootloader eben an die Adresse 0x8000800 ein neues Programm wird dieses 
ausgeführt (solange ich keine Interrupts verwende, die müßten dann im 
Startprogramm angepasst werden).

Allerdings mag ich nicht wirklich mit 2 unterschiedlichen Linkerscripts 
arbeiten, die unterscheiden, ob ein Programm mittels SWDIO oder 
Bootloader geflasht wurde.

Das das Flashen über Bootloader grundsätzlich gehen muß ist an dem V-USB 
Bootloader in

https://github.com/cnlohr/rv003usb

zu sehen. Dieser Bootloader (habe ich im Einsatz) funktioniert super. 
Allerdings mag ich eben eine Schaltung haben, die nicht 2 USB-Buchsen 
hat (eine für den Bootloader und eine für die serielle Kommunikation). 
Außerdem wären hier dann insgesamt 4 (statt 2) der wenigen GPIO-Pins 
weg.

Natürlich habe ich auch versucht, mittels V-USB einen virtuellen 
tty-Port zu programmieren, aber da bin ich noch sehr weit davon entfernt 
dass das funktioniert, außerdem wäre das relativ langsam, belastet ein 
User-Programm und nimmt zudem auch noch Flashspeicher weg.

----------------------------------------------------

@an_alle_standard_negativ_bewerter: tut euch keinen Zwang an. Wenn nur 
ein einziger mir hier weiterhelfen kann ist das zig-millionenfach 
wertvoller als es euer Negativbewertungszwang einen ärgert

von Vanye R. (vanye_rijan)


Lesenswert?

Nicht das ich es fuer den CH32V003 selber schon gemacht habe, ich frage 
mich sogar warum man das machen sollte, aber benutze ja auch nur die 
Teile mit moeglichst wenig Pinnen, aber ich vermute mal das deine 
Flashsoftware im Ram laufen muss wenn du das Flash selber bearbeiten 
willst.

Vanye

von Harald K. (kirnbichler)


Lesenswert?

Ralph S. schrieb:
> Natürlich habe ich auch versucht, mittels V-USB einen virtuellen
> tty-Port zu programmieren, aber da bin ich noch sehr weit davon entfernt
> dass das funktioniert, außerdem wäre das relativ langsam, belastet ein
> User-Programm und nimmt zudem auch noch Flashspeicher weg.

Der rv003-USB-Bootloader macht doch genau das, kannst Du nicht die 
Routinen des Bootloaders aus Deinem Programm heraus nutzen? Du weißt, an 
welchen Stellen im Speicher das Ding liegt, also sollte es doch möglich 
sein, Funktionen daraus aufzurufen. Das würde dann keinen zusätzlichen 
Speicher benötigen und auch keine zusätzliche USB-Buchse.

von Thomas Z. (usbman)


Lesenswert?

Vanye R. schrieb:
> aber ich vermute mal das deine
> Flashsoftware im Ram laufen muss wenn du das Flash selber bearbeiten
> willst.

das denke ich auch. Bei allen Sektor orientierten Flashs müssen Erase 
und Flash Routinen normalerweise aus dem Ram gestartet werden.
Ich kenne nor wenige Systeme wo das nicht so ist.

also zumindest

- uint8_t flash_is_busy()
- void flash_wait_until_not_busy()
- void fmem_writeword(uint32_t addr, uint16_t data)
- void flash_erase_sector(uint32_t addr)

solten im Ram liegen.

An welcher Adresse liegt dein Bootloader?

Usb CDC zu implementieren kannst du vergessen, das braucht mindestens 
Fullspeed. Lowspeed Bulk Eps sind nicht durch die Spec abgedeckt.

: Bearbeitet durch User
von Ralph S. (jjflash)


Lesenswert?

Harald K. schrieb:
> Der rv003-USB-Bootloader macht doch genau das, kannst Du nicht die
> Routinen des Bootloaders aus Deinem Programm heraus nutzen? Du weißt, an
> welchen Stellen im Speicher das Ding liegt, also sollte es doch möglich
> sein, Funktionen daraus aufzurufen.

Das ist einer der Ansätze, warum ich mir dieses Ding ganz genau ansehe 
... und Asche über mein Haupt, ich bin noch nicht dahinter gekommen, wo 
denn jetzt das Schreiben des Flashs mit diesem USB-Bootloader 
funktioniert. Allerdings (und da studiere ich jetzt eben sehr genau den 
Code) ist das so meine Hoffnung, dass ich daraus schlau werde und da 
davon dann etwas adaptieren kann.

Vanye R. schrieb:
> ch frage
> mich sogar warum man das machen sollte,

Weil ich gerne sehr kleine Teile habe... und weil man dann daraus im 
Stile eines "CH32V003 nano" für das Steckbrett machen kann... oder als 
Modul für eine Schaltung (wie auch immer).

Vanye R. schrieb:
> aber ich vermute mal das deine
> Flashsoftware im Ram laufen muss wenn du das Flash selber bearbeiten
> willst.

Die Idee hatte ich auch schon (denn bspw. beim STM8 war das auch so), 
allerdings: ich kann das Flash ja schreiben nur hängt sich dann eben der 
Bootloader beim Start auf, wenn du den Flash ab 0x8000000 beschreibst 
(umkopieren der Codebytes ins Ram um von dort aus das Programm laufen zu 
lassen wird angesichts der 1920 Bytes die man zur Verfügung hat etwas 
"knapp").

Thomas Z. schrieb:
> An welcher Adresse liegt dein Bootloader?

Bootloader liegt an Adresse 0x00000000 !

Und wie ich jetzt festgestellt habe, kann ich von dort auch alles im 
Flash-Bereich schreiben... nur funktioniert der Loader nicht, wenn ich 
Sektor 0 Beschreibe (der liegt auf 0x8000000).

Außerdem: beim CH32V003 ist der Bootloaderbereich ein vom USER-Flash 
getrennter Bereich. Wird "angeblich" der gesamte Chip gelöscht, wird der 
Bootloader dennoch nicht gelöscht.

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.