Forum: Mikrocontroller und Digitale Elektronik STM32: Alternativen zu Semihosting


von Wibo (Gast)


Lesenswert?

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)?

von Kopfschüttel (Gast)


Lesenswert?

Bei Segger gibt es noch RTT. Das läuft komplett an der restlichen 
Sitzung vorbei. Ist ziemlich schnell und wohl auch unter Linux 
verfügbar.

von Wibo (Gast)


Lesenswert?

Guter Punkt, ich verwende SW4STM32. :-)

von Jim M. (turboj)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

: Bearbeitet durch User
von kyrk.5 (Gast)


Lesenswert?

"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.

von Wibo (Gast)


Lesenswert?

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.

von kyrk.5 (Gast)


Lesenswert?

"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...

von Vincent H. (vinci)


Angehängte Dateien:

Lesenswert?

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 ;)

: Bearbeitet durch User
von A. B. (Gast)


Lesenswert?

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.

von Andreas S. (igel1)


Lesenswert?

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

von Wibo (Gast)


Lesenswert?

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!

von Wibo (Gast)


Lesenswert?

Andreas S. schrieb:
> Segger stellt allerdings Anleitungen zur Verfügung,
> damit auch diese Kombi zusammenspielt:
>
> [Links]

Herzlichen Dank!

von Andreas S. (igel1)


Lesenswert?

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

von kyrk.5 (Gast)


Lesenswert?

"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.

von Johannes S. (Gast)


Lesenswert?

dieses Wiki ist zwar schon alt, aber der letzte Absatz ist sicher immer 
noch gültig und beschreibt das Problem mit dem semihosting:
http://www.support.code-red-tech.com/CodeRedWiki/UsingPrintf

von Stefan F. (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

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.