Forum: Mikrocontroller und Digitale Elektronik STM32F103 System Workbench


von Nils X. (xenon185)


Lesenswert?

Hallo zusammen,

ich habe in der UNI ein Projekt bei dem wir den Controller STM32F103 
benutzen sollen.

Ich habe den zu verwendenden Code bereits auf dem PC in Visual Studio 
getestet und möchte ihn jetzt auf den Controller bringen.

Leider klappt dies wie nicht anders zu erwarten war.

Beim Aufrufen einer Funktion springt der Controller in einen 
Fehlerzustand.

---------------
    .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b Infinite_Loop
  .size Default_Handler, .-Default_Handler
---------------

Meine Vermutung ist das es mit dem Stack oder den Speicher des 
Controllers zu tun hat.

Als IDE benutze ich die "System Workbench"

Kann mir jemand sagen wie ich den benutzen Programmspeicher mir anzeigen 
lassen kann?
Und wie kann ich mir im Debugging den aktuellen Zustand des 
Stack-Pointers ausgeben?
[Register -> SP ] zeigt mir die aktuell auf den Stack liegende Adresse?

Vielen Dank für eure Hilfe

von Max M. (maxmicr)


Lesenswert?

Sieht so aus als verwendest du einen Interrupt dessen Vektor nicht an 
die eigentliche Funktion sondern an einen Default-Handler springt - hast 
du ein Startup File für den STM32F103?

von Mr. Big (Gast)


Lesenswert?

Nils X. schrieb:
> Leider klappt dies wie nicht anders zu erwarten war.


Na dann ist ja alles gut!

von Viktor B. (coldlogic)


Lesenswert?

Ist die Funktion eine Interrupt Service Routine? Oder wird in der 
Funktion irgendwas von der Hardware so initialisiert, dass ein 
Interruptvector eingeschaltet wird, der aber keine zugewiesene ISR hat?

von dasrotemopped (Gast)


Lesenswert?

https://community.st.com/docs/DOC-1644-sw4stm32-full-user-training

SW4MCU_User_Training-full-v1.1.pdf
schon gelesen ?

von Stefan F. (Gast)


Lesenswert?

Meinst du nicht, dass du mindestens den fragwürdigen Code vorzeigen 
solltest?

Stack und Heap sind normalerweise 1) so angelegt, dass sie beide 
aufeinander zu wachsen. Dann ist die Menge an freiem Heap gleich der 
Menge an freiem Stack.

Mit der Funktion malloc() kannst du zyklisch ausprobieren, wie viel 
Speicher maximal an einem Stück belegbar ist 2) und diese Zahl dann als 
Trace Meldung ausgeben. So bekommst du ein grobes Gefühl dafür, wie viel 
Speicher noch frei ist.

Du solltest Dich diesbezüglich auch über das Thema "Heap Fragmentierung" 
informieren.

1) Aber das kann in deinem uns unbekannten Projekt auch völlig anders 
sein!
2) Entsprechende Code-Beispiele findest du mit Google.

> Und wie kann ich mir im Debugging den aktuellen Zustand
> des Stack-Pointers ausgeben?
> [Register -> SP ] zeigt mir die aktuell auf den Stack liegende Adresse?

Ja sicher doch. Aber ohne Kenntnis der aktuellen Größe des Heap nützt 
Dir das nicht viel. Wenn du den Heap untersuchen willst, musst du 
erstmal heraus finden, wie die von Dir verwendete C Library damit umgeht 
und wo sie ihre Pointer und Größen speichert.

von Nils X. (xenon185)


Angehängte Dateien:

Lesenswert?

@ Max MMM:
Startup File liegt im Anhang bei.

@Mr. Big: Danke für deinen  Post.

@Viktor B.:
Die Funktion heisst inv_l() und stammt aus der Library flint.c
Ist somit keine eigene Funktion. In der Funktion werden nur Berechnungen 
durchgeführt und keine Hardware angesprochen.

@dasrotemopped: Danke für das Dokument. Kannte ich noch nicht und werde 
ich mir mal durchlesen.


Stefanus F.:
Ich benutzte die Bibliothek flint.h und dabei taucht der Fehler beim 
aufruf der Funtion inv_l() auf.
In dem Projekt soll eine Implementierung eines RSA zu testzwecken auf 
einen Controller umgesetzt werden.
Der Programmcode funktioniert soweit auf dem PC. Somit sollte es da kein 
Problem mit dem Syntax geben.


Ich bin mit dem Controller und der IDE noch nicht so vertraut. Hab von 
euch aber schon ein paar Ansätze um ein Stückchen voran zu kommen.

von W.S. (Gast)


Lesenswert?

Nils X. schrieb:
> Ich habe den zu verwendenden Code bereits auf dem PC in Visual Studio
> getestet und möchte ihn jetzt auf den Controller bringen.
>
> Leider klappt dies wie nicht anders zu erwarten war.

Tja.
Was hast du denn da auf dem PC getestet? Dir sollte klar sein, daß es 
auf einem µC etwas anders zugeht als auf deinem PC.

Ich vermute mal, daß du auf dem PC so einiges an dortigen 
Bibliotheksfunktionen benutzt hast, für die du auf deinem µC keine Basis 
hast. Beispiel ist sowas wie malloc oder printf, wenn man nicht die 
passenden Lowlevel-Treiber für das tatsächliche RAM-Verwalten oder die 
tatsächliche Ausgabe vorgehalten hat. Auf dem PC macht sowas das BS, 
aber auf dem µC eben nicht, da gibt's kein BS.

Also laß erst mal deinen "vorgetesteten" Code links liegen und fange 
zunächst ganz klein an mit einem Minimal-Programm. Gerade für die 
STM32F103C8T6 hab ich hier schon des öfteren was gepostet, mit dem du 
zunächst mal einen funktionablen Programm-Rumpf für diese µC hast, der 
per seriell oder usb-cdc mit dem PC kommunizieren kann, ne Systemuhr 
hat, ne Reihe von an µC's angepaßten Hilfsroutinen usw. hat, kurzum dir 
eine funktionierende Infrastruktur bietet.

Die Unterschiede in der HW bei den verschiedenen Geschmacksrichtungen 
innerhalb der STM32F103xxxx Familie sind nicht groß, aber vorhanden. 
Also schreibe wenigstens, mit welchem konkreten Typ du in deiner Uni 
basteln willst. Irgendwo hab ich auch noch etwas für den STM32F103ZET6 
herumliegen, so etwa aus 2013.

W.S.

von Nils X. (xenon185)


Lesenswert?

@W.S.:

Wir sollen eine RSA Verschlüsselung auf einem Mikrocontroller umsetzen. 
Als ersten Schritt haben wir eine Umsetzung der Funktionalität auf dem 
PC getestet.

---
Die genaue Controllerbezeichnung lautet: STM32F103R8T6
---

Ich werde mal deinen Rat annehmen und im ganz kleinen beginnen.
Kannst du eventuell deine Codebeispiele hier kurz als Link posten. Dann 
hab ich schonmal eine Basis?

thx

von Stefan F. (Gast)


Lesenswert?

Der Code für die Verschlüsselung müsste auf den µC prinzipiell der selbe 
sein, wie auf dem PC. Spannend wird hier allerdings der Umgang mit dem 
knapperen Arbeitsspeicher.

Also solltest du zuerst mal analysieren, wie dein Code auf dem PC mit 
dem Arbeitsspeicher umgeht. Dann schaust du, ob das zum viel kleineren 
Speicher des µC passt. Wenn nicht (womit ich rechne), schreibst du den 
Code um.

Ein fertiges Beispiel wird Dir bei deiner Aufgabe nichts nützen. Du 
würdest damit vielleicht ein funktionierendes Programm erstellen können, 
aber das Ergebnis wäre mit Sicherheit völlig an der Aufgabe vorbei. Denn 
der Weg ist hier das Ziel.

Dein Lehrer will sehen, wie du die Unterschiede zwischen den beiden 
Computern ermittelt hast und sicher wirst du deine Anpassungen am Code 
auch begründen müssen.

> Ich benutzte die Bibliothek flint.h und dabei taucht der Fehler
> beim aufruf der Funtion inv_l() auf.

Es liegt nahe, sich den Quelltext dieser Funktion anzuschauen und 
insbesondere hinsichtlich der Verwendung von Arbeitsspeicher zu 
untersuchen. Eventuell muss man auch die Stellen betrachten, wo die 
Funktion aufgerufen wird.

von Nils X. (xenon185)


Lesenswert?

@Stefanus F.:

Danke für die Tipps.
Ich denke mittlerweile auch, dass es anfangs etwas blauäugig war einfach 
nach dem Prinzip "copy and past" - Verfahren vorzugehen.

Ich werde dann mal den Code stückweise analysieren.

Wenn ich was essenzielles rausgefunden habe poste ich das mal hier.

von Stefan F. (Gast)


Lesenswert?

Was mir ab und zu mal passiert:

Ich schreibe Code unter der schlechten Annahme, dass eine Integer 
Variable eine bestimmte Größe (z.B. 32bit oder 64bit) hat. Wenn man das 
dann auf eine andere Architektur überträgt, kommt es Rechenfehlern oder 
gar fehlerhaften Speicherzugriffen in Kombination mit Pointern und 
type-casting.

von A. (Gast)


Lesenswert?

Warum verwendest du dann nicht von anfang an Typen wie uint32_t + 
stdint.h etc.?

von Stefan F. (Gast)


Lesenswert?

> Warum verwendest du dann nicht von anfang an Typen wie
> uint32_t + stdint.h etc.?

Weil ich blöd bin. Ich weiß ja längst, dass man es so machen soll. Aber 
man bessert sich im Laufe der zeit.

von W.S. (Gast)


Lesenswert?

Nils X. schrieb:
> Kannst du eventuell...

Ja.
Beitrag "Re: STM32 USART mit falscher Baudrate"

war ein Beitrag zum Thread "STM32 USART mit falscher Baudrate".

Und was kriegst du damit: Ne Basis für die STM32F103, passend zum 
Keil-MDK. Wer nen GCC benutzen will, muß sich das halt umschreiben.
Also:

- Startupcode
(aber ohne Vorbelegungen im RAM)

- Config-Unit
zum Konfigurieren der Pins und zum Aufsetzen der Takte etc.

- Conv
I/O-Konvertierungen
Zum Vermeiden von Ballast a la printf und so, aber auch zu 
Eingabe-Konvertierungen

- Cmd
eine einfache Kommandozeile

- Events
eben die Event-Verwaltung. Letztlich zum Organisieren von Zeitabläufen 
und zum Entkoppeln von lowlevel- und hilevel-Schichten im Programm

- Gio
zum Vereinheitlichen von seriellen Strömen (reals und virtuelle UARTs, 
usw.)

- main
eben für die Grundschleife, quasi der Idle-Zustand in der ganzen 
Firmware

- serial
eben die UART's

- Systick
die System-Uhr

- Usb
noch ne serielle Schnittstelle, diesmal als USB-VCP
(Headerdatei lesen!)

... und das Ganze braucht nur 11508 Bytes. Da kann man mit dem Keil 
(frei bis 32K) noch ne Menge dazufügen.

- EAGLE-Files für die Hardware. Die ist im Übrigen weitgehend kompatibel 
zu den ST-Link's gehalten, so daß man bei Bedarf nen ST-Link-Lader 
draufladen kann, dann mit dem Utility von ST daraus einen eigentlichen 
ST-Link machen kann. Ist nicht mein Fall, ich benutze lieber den 
eingebauten Bootlader. Dazu gibt's (auch von mir) ein kleines 
Delphi-Brennprogramm, das auch ein Terminalfenster eingebaut hat. Damit 
kann man nach dem Flashen sogleich mit dem µC über dieselbe serielle 
Schnittstelle kommunizieren, über die man ihn programmiert hat. Passende 
Usb-Seriell-Adapter mit TTL-Pegel sollten ja keine Hürde sein.

Klaro?


Stefanus F. schrieb:
> Was mir ab und zu mal passiert:
>
> Ich schreibe Code unter der schlechten Annahme, dass eine Integer
> Variable eine bestimmte Größe (z.B. 32bit oder 64bit) hat.

Ja, das ist eine ganz schlechte Angewohnheit - und sie ist von hause aus 
fehlerhaft.

Von einem int mehr als 16 Bit zu erwarten, ist grob fahrlässig - auch 
dann, wenn sowas auf einem ARM in der CPU mit 32 Bit gerechnet wird.

Also:
- wenn du mit 16 Bit für ne globale Variable auskommst, dann nimm int
- wenn es eine lokale Variable ist, dann nimm lieber long
- für alles, was mehr als 16 Bit zu brauchen scheint, nimm immer long
- für alles darüber nimm int64 oder (falls dein Compiler das nicht 
kennt, schreibe long long)

W.S.

von Dr. Sommer (Gast)


Lesenswert?

W.S. schrieb:
> - wenn du mit 16 Bit für ne globale Variable auskommst, dann nimm int

Bei int16_t ist klarer was gemeint ist. Sonst aber richtig.

W.S. schrieb:
> - wenn es eine lokale Variable ist, dann nimm lieber long

Was hat der Speicherort damit zu tun? Wenn 16 Bit oder Mehr reichen, 
nimmt man int_least16_t. Da wird automatisch was effizientes genommen.

W.S. schrieb:
> - für alles, was mehr als 16 Bit zu brauchen scheint, nimm immer long

Warum nicht int(_least)32_t? Ist auch wieder klarer.

Diese komplizierten Regeln kann man sich sparen. Das geht einfacher:
1. Überlegen wir viele Bits man braucht
2. Auf 2er-Potenz aufrunden
3. Überlegen ob der Algorithmus mit mehr Bits auch noch geht (Überlauf 
also nicht wichtig ist)
4. (u)intXX_t bzw (u)int_leastXX_t nehmen
Dann muss man sich nicht mehr merken, wie viele Bits short, int, long, 
long long, und Hersteller spezifische Erweiterungen jetzt haben.

W.S. schrieb:
> falls dein Compiler das nicht kennt,
Nimmt man einen der nicht auf dem Stand von vor 20 stehen geblieben ist.

von W.S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Was hat der Speicherort damit zu tun?

Ach unser Forums-Beckmesser ist mal wieder mit seinem Regel-Buch unter'm 
Arm unterwegs.

Aber du kapierst es trotzdem nicht, sonst hättest du eben diese Frage 
nicht gestellt.

Ach ja, da du schon gefragt hast, erklär ich's dir:

Der Beckmesser ist der Versager in Wagners Oper von den Nürnberger 
Meistersingern. Die Meister können meisterlich singen und Lieder 
komponieren, da möchte Beckmesser gern mitmischen - aber er hat dafür 
halt nicht die Eier in der Hose. Also rennt er im Forum herum, mit dem 
Vorschriften-Buch unter'm Arm und versucht jedem Meister irgendwelche 
angeblichen Regelverstöße anzukreiden. Selbst als er dem Hans Sachs nen 
Quellcode (vom Junker geschrieben) geklaut hatte, war er zu doof, damit 
ein schönes Lied zu singen und hat sich vor dem Auditorium blamiert. 
Aber als der Junker eben diesen Quellcode vor versammeltem Auditorium 
nochmal vorsang, da erstrahlte die schöne Melodie - eben meisterlich.

So, nun weißt du, warum du der Beckmesser dieses Forums bist.

Schau mal, dieses Forum lebt von positiven Beiträgen. Deshalb habe ich 
dir vor geraumer Zeit dringend angeraten, von solchen scheuklappigen 
Kritteleien abzulassen und hier in diesem Forum etwas Eigenes 
vorzutragen, also irgend ein Werk, das weinigstens ein bißchen deines 
eigenen Entwicklerschweißes gekostet hat. Das nützt dem Forum und auf 
lange Sicht nützt es auch dir selber.

Deshalb wiederhole ich hier meinen damaligen Rat an dich.

W.S.

von Dr. Sommer (Gast)


Lesenswert?

Hahaha, du bist also ein Meister, ja? Wohl eher der Frickelmeister!
In der Mathematik und Informatik sind Regeln nun mal das ein und alles. 
Ignoriert man die, kommt's zum Chaos. Programmieren ist halt doch was 
anderes als Singen. Da kommt's auf Korrektheit an, nicht was du mit 
deiner Wirth-Brille "schöner" findest.

W.S. schrieb:
> und hier in diesem Forum etwas Eigenes vorzutragen, also irgend ein
> Werk, das weinigstens ein bißchen deines eigenen Entwicklerschweißes
> gekostet hat.

Wie bereits gesagt habe ich das, aber eben nicht unter diesem Namen (du 
dozierst hier ja auch anonym!). Natürlich hast du es dir nicht nehmen 
lassen völlig unqualifiziertes und unbegründetes Geläster darunter 
abzulassen; nach Widerlegen desselben kam keine Antwort mehr. Peinlich 
für einen Meister!

von Nop (Gast)


Lesenswert?

W.S. schrieb:

> So, nun weißt du, warum du der Beckmesser dieses Forums bist.

Deine Beiträge zum Thema C sind regelmäßig von Halbwissen geprägt, 
oftmals auch schlichtweg falsch. Insofern solltest gerade Du Dich bei 
diesem Thema nicht soweit aus dem Fenster lehnen.

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.