Mein Projekt läuft momentan auf einem Nucleo STM32F722ZE-144. Zwecks
Debugging möchte ich gerne Log-Nachrichtugen auf der Konsole o.ä.
ausgeben.
Dazu habe ich Semihosting (also Umleitung von printf-Nachrichten auf die
IDE-Konsole) erfolgreich ausprobiert, aber leider stört das Semihosting
den normalen Programmfluß. Also suche ich eine andere Möglichkeit.
Laut ST-Dokument soll man über den SWO-Pin ebenfalls Nachrichten senden
können. Ich habe dazu die Funktionen __io_putchar und _write wie
beschrieben implementiert, der Debug-Modus ist Debug Async SW.
Da ich unter Linux das ST-Link-Tool nicht benutzen kann, versuche ich
die Nachrichten mit einem FTDI232 direkt an UART3 abzugreifen.
Allerdings bleibt mein Terminal-Fenster leer.
Wie komme ich an die gesendeten Daten heran? Stimmt UART3 überhaupt (die
Angabe stammt aus einem zufälligen ST-Dokument und soll für alle
Nucleo-144 gelten)? Gibt es eine weitere Möglichkeit, effizient
Nachrichten nach extern zu senden (vom expliziten Betreiben einer
seriellen Schnittstelle abgesehen)?
Wibo schrieb:> Da ich unter Linux das ST-Link-Tool nicht benutzen kann
OpenOCD existiert und kennt ST-Links. Ich habe da allerdings nie mit SWO
gearbeitet.
Manche ST-Links kann man auf J-Link umflashen, mit der JLink Software
geht sowohl SWO als auch das in meinen Augen noch bessere Segger RTT.
UART ist eine gern gewählte leichtgewichtige und schnell implementierte
Methode um so etwas zu machen.
Und was auch gut geht wenn man den zeitlichen Verlauf des Inhalts einer
oder mehrerer Variablen plotten will ist J-Scope von J-Link. Das
beeinflusst den Ablauf des Programms überhaupt nicht und man muss seinen
Code auch nicht instrumentieren. Das benötigt aber einen J-Link statt
eines ST-Link (aber man kann den onboard ST-Link auf J-Link umflashen
und dann die ganze Funktionsviefalt von Segger genießen und nie wieder
zurück blicken)
Wibo schrieb:> Stimmt UART3 überhaupt (die> Angabe stammt aus einem zufälligen ST-Dokument und soll für alle> Nucleo-144 gelten)?
Ein Blick in den Schaltplan hilft um zu sehen was wo angeschlossen ist.
"aber leider stört das Semihosting den normalen Programmfluß"
Wie wird das gestört? Zeitlich? Funktional? Was tut dann nicht? Hast du
das Problem hier verstanden und siehst so dass eine Alternativlösung
viel einfacher ist als das Problem selbst zu lösen?
Normaler weise implementiert den printf so dass er in ein RingSpeicher
seine chars rein tun kann. Der sollte dann aus der Interrupt geleert
werden. Ringspeicher sollte dann so groß sein dass da nie Probleme
auftauchen. Am besten nur aus einem Kontext den printf verwenden, denn
wenn mehrere kontexte gleichzeitig drauf zugreifen wollen dann werden
die Nachrichten komisch aussehen.
kyrk.5 schrieb:> "aber leider stört das Semihosting den normalen Programmfluß"> Wie wird das gestört? Zeitlich? Funktional? Was tut dann nicht? Hast du> das Problem hier verstanden und siehst so dass eine Alternativlösung> viel einfacher ist als das Problem selbst zu lösen?
Das Problem schien auf den ersten Blick zu sein, daß Interrupts nicht
rechtzeitig und/oder gar nicht bedient werden.
"Das Problem schien auf den ersten Blick zu sein, daß Interrupts nicht
rechtzeitig und/oder gar nicht bedient werden."
Je nach dem wie der Printf dann auf den UART umgeleitet wurde kann sein
dass der einfach die Interrupts zu lange sperrt.
Selber implementiert oder aus der IDE/Compiler etwas genommen? Lässt
sich der Code debuggen?
Wenn selber implementiert dann kann auch vorkommen dass die Interrupts
nie wieder freigegeben werden. Interrupt gesperrt dann im IF abfrage
wieder entsperrt.
Wenn interrupts gar nicht mehr kommen, dann mit debugger stop machen und
angucken ob alles noch richtig ist. Sind die interrupts immer noch
enabled? Sind irgendwelche interrupt flags sichtbar? Und angucken ob der
Code noch richtig läuft.
Könnte auch ein Stack Problem sein. Der printf verbraucht zu viel Stack
und es wird irgendetwas überschrieben. Wie ist der Stack konfiguriert?
Wie viel gibt es denn?
Arbeitet der Printf auf einer Ringspeicher? Ich hoffe mal ja, denn sonst
wird ja ein Printf ein Laufzeitfresser...
kyrk.5 schrieb:> "aber leider stört das Semihosting den normalen Programmfluß"> Wie wird das gestört? Zeitlich? Funktional? Was tut dann nicht? Hast du> das Problem hier verstanden und siehst so dass eine Alternativlösung> viel einfacher ist als das Problem selbst zu lösen?>> Normaler weise implementiert den printf so dass er in ein RingSpeicher> seine chars rein tun kann. Der sollte dann aus der Interrupt geleert> werden. Ringspeicher sollte dann so groß sein dass da nie Probleme> auftauchen. Am besten nur aus einem Kontext den printf verwenden, denn> wenn mehrere kontexte gleichzeitig drauf zugreifen wollen dann werden> die Nachrichten komisch aussehen.
Mit Semihosting? Bitte post doch mal ein Beispiel davon...
Ich glaub ehrlich gesagt du weißt nicht so richtig wie semihosting
funktioniert?
@Wibo
SWO ist eine Hausnummer schneller als semihosting, aber immer noch
blockend. Der ITM Port lässt sich auch nicht via DMA ansprechen... Wenn
es wirklich zeitkritisch ist bleibt nur UART via DMA.
Anbei übrigens die trace Implementierung des GNU ARM Eclipse plugins.
Weil... wozu selbst schreiben ;)
Wibo schrieb:> Wie komme ich an die gesendeten Daten heran? Stimmt UART3 überhaupt (die> Angabe stammt aus einem zufälligen ST-Dokument und soll für alle> Nucleo-144 gelten)? Gibt es eine weitere Möglichkeit, effizient
Nein, SWO hat nichts mit den normalen U(S)ARTs zu tun. Beim F722ZE ist
SWO auf Pin PB03, AF00, s. Datenblatt.
Habe nicht den ganzen Thread gelesen, nur so viel von mir:
Ich habe den ST-Link auf meinem STM32F4-Discovery Board von
ST-Link auf J-Link umgeflasht. Danach konnte ich sowohl
Semihosting als auch SWO benutzen.
Außerdem ist das Flashen mit dem J-Link um Längen schneller
geworden. Kurzum, es war eine meiner besten Entscheidungen.
Mit der Kombination SW4STM32 / J-Link kenne ich mich allerdings
nicht aus. Segger stellt allerdings Anleitungen zur Verfügung,
damit auch diese Kombi zusammenspielt:
https://www.segger.com/products/debug-probes/j-link/technology/ides/system-workbench-for-stm32/
Außerdem hier ein Link auf die Anleitung, nach der ich erfolgreich
mein ST-Link in einen J-Link umgeflasht habe (ein Rollback wird
darin nach meiner Erinnerung ebenfalls beschrieben):
https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/
Good luck
Igel1
A. B. schrieb:> Nein, SWO hat nichts mit den normalen U(S)ARTs zu tun. Beim F722ZE ist> SWO auf Pin PB03, AF00, s. Datenblatt.
Jetzt, wo Du es sagst ... Ich habe in dem Dokument (AN4989) zwei
aufeinanderfolgende Verfahren zusammengeschmissen.
Die hier genannten Verfahren sind alle interessant, insb. der Upgrade
auf J-Link, aber ich benutze jetzt doch erstmal die einfachste Methode:
Schreiben an einen UART. Das Log ist dann zwar nicht in der Konsole,
sondern in einem separaten Fenster, aber das genügt mir im Moment.
Danke für alle Vorschläge!
Wibo schrieb:> Andreas S. schrieb:>> Segger stellt allerdings Anleitungen zur Verfügung,>> damit auch diese Kombi zusammenspielt:>>>> [Links]>> Herzlichen Dank!
Gern geschehen.
Das ist der Geist in diesem Forum: Hilf und Dir wird geholfen ...
Und wenn dann noch - wie in Deinem Falle - ein Dankeschön zurückkommt,
so freut man sich besonders :-)
Viele Grüße
Igel1
"Mit Semihosting? Bitte post doch mal ein Beispiel davon...
Ich glaub ehrlich gesagt du weißt nicht so richtig wie semihosting
funktioniert?"
Ja da hast du recht. Habe eben kurz nach geguckt. Wenn der printf aber
nach dem C Standard geht und den putc als Ausgang weiter aufruft, könnte
der Kontextwechsel Problem immer noch bestehen.
https://stackoverflow.com/questions/467938/stdout-thread-safe-in-c-on-linux
Prinzipiell ist der printf thread safe, dass heißt aber nicht, dass die
ausgaben nicht unterbrochen werden können. Also main context macht ein
printf und dann kommt ein interrupt dazwischen und macht auch ein
printf.
So wie ich es mir vorstelle wird sich der Semihosting sich in den putc
einhängen. Wenn nicht dann bitte korrigieren. Daher denke ich, dass die
ausgaben von printf unterbrochen werden können.
Hier werden sie geholfen:
http://stefanfrings.de/stm32/index.html#traceswo
Trace Ausgaben kann die System Workbench nicht direkt anzeigen, aber man
kann sie wahlweise im UART Format ausgeben und mit einem USB-UART
Adapter empfangen oder mit openocd in eine Datei schreiben und diese
dann anzeigen.
Was ich auch ab und zu mache wenn das Timing kritisch ist (zum Beispiel
ich will das Protokollhandling in einem Slave debuggen und der Master
ist leider eine Black Box die ich nicht anhalten kann oder anderer
nebenläufiger Kram ist im Spiel der sich nicht verlangsamen lässt):
* Ich logge ins RAM!
Ich überleg mir was ich eigentlich genau wissen will, also zum Beispiel
reichen meist ein oder zwei Byte pro Ereignis um zu sehen ob alles mit
rechten Dingen zugeht, dann mach ich mir ein Array um diese Daten
aufzunehmen, einen Schreibzeiger und eine Logfunktion die meine Logdaten
da reinschreibt. Dann lass ichs laufen bis das zu untersuchende Problem
auftritt, lass es im Debugger anhalten und schau mir das Array an.
Wenn ich an den aufgezeichneten Daten ein Muster finde das mit dem
Auftreten des Problems korreliert kann ich im nächsten Schritt mehr
relevante Daten pro Ereignis loggen, dafür irrelevante Datensätze gar
nicht erst loggen oder das Loggen erst starten wenn ein bestimmter
Zustand eintritt oder wenn ich dann schon eine Ahnung habe womit es
zusammenhängt gezielt an der richtigen Stelle auf einen Breakpoint
laufen lassen wenn diese oder jene Bedingung erfüllt ist und dann im
Einzelschritt weiter debuggen, etc. etc.