STM32: Alternativen zu Semihosting

Gast #5419083
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)?
#5419101
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.
Gast #5419107
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.
Gast #5419115
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.
Gast #5419118
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...
#5419119
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 ;)
Angehängte Dateien:
Gast #5419134
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.
#5419143
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
Gast #5419149
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!
#5419167
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
Gast #5419223
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.
#5420159
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren