Guten Abend,
ich habe vor kurzem, nach ein paar Jahren AVR, den Schritt zum
STM32 gewagt.
Die Toolchain (arm-none-eabi) habe ich unter Linux gebaut, Linkerscript
Startupcode und Makefile funktionieren, das Kompileren klappt ohne
Probleme.
Ich bekomme es aber nicht hin, in einer Schleife nacheinander die
Arrayelemnte auszulesen.
Die Arryelemente nacheinander ohne Schleife auszulesen funktioniert
problemlos.
Beim Zugriff in der Schleife hängt sich der Controller auf.
1 | int main(void)
| 2 | {
| 3 |
| 4 | u16 i;
| 5 | u8 len = 4;
| 6 | u16 StartX;
| 7 |
| 8 | const u8 wert[4] = {'T','e','s','t'};
| 9 |
| 10 | ....
| 11 | ....
| 12 |
| 13 | // funktioniert !
| 14 | ili9320_PutChar((StartX+8*0),120,wert[0],Black, Green);
| 15 | ili9320_PutChar((StartX+8*1),120,wert[1],Black, Green);
| 16 | ili9320_PutChar((StartX+8*2),120,wert[2],Black, Green);
| 17 | ili9320_PutChar((StartX+8*3),120,wert[3],Black, Green);
| 18 |
| 19 | // funktioniert nicht !
| 20 | for (i=0;i<4;i++)
| 21 | {
| 22 | ili9320_PutChar((StartX+8*i),120,wert[i],Black, Green);
| 23 | }
| 24 | }
|
Hat jemand einen Tipp was ich falsch gemacht habe??
Das komplette Projekt habe ich angehangen.
Vielen Dank im Voraus
Gruß Marco
An diesem Code sehe ich kein Problem, und das ganze Programm ist eher
etwas unübersichtlich und ohne die Hardware nicht nachvollziehbar.
Lässt sich der Fehler auf ein deutlich kleineres Programm reduzieren,
evtl. ohne deine LCD-Geschichte?
Habe eben die LCD-Aufrufe entfernt, und mittels Schleife die
Arrayelemente
in eine andere Variable kopiert.
Das funktioniert einwandfrei, scheint also an der LCD-Geschichte zu
liegen.
Vielen Dank für Deine Hilfe Klaus.
Gruß Marco
Hallo,
habe bei dem Problen weiter gebohrt, und etwas festgestellt.
Deklariere ich das Array global, funktioniert es , wie es soll.
Kann mir bitte jemand erklären warum?
Gruß Marco
Nein, nicht wirklich.
Die Standardreaktion wäre "zuwenig Platz auf dem Stack", aber bei einem
ARM und einem so kleinen Feld kann das kaum sein.
Was natürlich eine Möglichkeit wäre, daß in einer der aufgerufenen
Funktionen jemand den Speicher überschreibt.
Wenn dein Feld lokal ist, wird es zufällig getroffen bzw. eine
Rücksprungadresse oder ähnliches überschrieben, global wird etwas
anderes erwischt, was dich zufällig (noch?) nicht stört.
Danke Klaus für Deine Ausführungen.
Mir ist noch aufgefallen, daß wenn das Array nicht global ist,
der Controller schon lange vor dem 1. Arrayzugriff hängen muß.
Denn dann wird das Display noch nich einmal ansatzweise initalisiert.
Gruß Marco
Welche GCC-Version kommt zum Einsatz?
Mit welchem Programm wird das Programm auf den µC geladen?
Ist es zufällig das stm32vldiscovery?
Steht ein Debugger zur Verfügung?
Marco Weinrich schrieb:
> ich habe vor kurzem, nach ein paar Jahren AVR, den Schritt zum
> STM32 gewagt.
... wodurch sich die Diagnosemöglichkeiten auch ohne Debugger verbessert
haben.
Im ersten Schritt alle Fault-Handler so befüllen, dass z. B. mittels
LEDs der Fault erkannt wird. Wenn's ein HardFault ist, die Escalation
abschalten.
Falls ohne Debugger: Ist eine USART angebunden, dann kann im Fault die
Adresse der Stelle berechnet werden. Benötigt m. W. nach etwas
Assembler, einfach mal googeln.
Mit Debugger sollte die Stelle beim Durchsteppen einfach zu finden sein.
Ansonsten ein breakpoint in den Fault-Handler, und die Adresse mit dem
Fehler zurückrechnen.
Dann sieht man weiter.
Hallo Roland,
ich benutze den gcc Version 4.5.2 unter Linux.
Einen Debugger besitze ich keinen, und auf dem Board sitzt ein
STM32F103RBT6.Flashen tue ich mit stm32flash.
Wie schalte ich die Escalation ab? (bin noch Arm-Anfänger)
Werde morgen Deine Tipps auspobieren.
Danke für die Tipps.
Gruß Marco
Hallo,
habe gerade versucht die Tipps von Roland umzusetzen.
Leider funktioniert daß mit den Led's und Uart nicht, da der
Controller hängt bevor die Ports/Uart initalisiert werden.
Ich habe das Gefühl, daß der Controller nicht gestartet wird
(kann es leider nicht prüfen).
Mir ist noch etwas aufgefallen: 1 | int main(void)
| 2 | {
| 3 |
| 4 | u16 i,j;
| 5 | u8 len = 4;
| 6 | u16 StartX;
| 7 |
| 8 | const u8 wert[4] = {'T','e','s','t'};
| 9 |
| 10 | ....
| 11 | ....
| 12 |
| 13 |
| 14 | // funktioniert nicht !
| 15 | for (i=0;i<4;i++)
| 16 | {
| 17 | ili9320_PutChar((StartX+8*i),120,wert[i],Black, Green);
| 18 | }
| 19 |
| 20 | // funktioniert !
| 21 | for (i=0;i<4;i++)
| 22 | {
| 23 | ili9320_PutChar((StartX+8*i),120,wert[1],Black, Green);
| 24 | }
| 25 |
| 26 | // funktioniert !
| 27 | for (i=0;i<4;i++)
| 28 | {
| 29 | j = wert[i];
| 30 | }
| 31 | }
|
Wird die Funktion nicht mit der Schleifenvariablen aufgerufen,
ist alles ok.
Eine Wertzuweisung mit Array/Schleifenvaiabe funktioniert auch.
Bin noch immer ratlos.
Gruß Marco
Marco Weinrich schrieb:
> Leider funktioniert daß mit den Led's und Uart nicht, da der
> Controller hängt bevor die Ports/Uart initalisiert werden.
Woher weißt Du das?
Die LCD-Funktionen nutzen auch GPIO ?!
Was bedeutet eigentlich "geht" und "geht nicht"?
Sei mir nicht bös', aber Du machst den dritten Schritt vor dem ersten.
Irgendetwas benötigst Du zum Debuggen. Es ist schwierig genug, ein LCD
mit Debug-Möglichkeiten ans Laufen zu kriegen. Im Blindflug wird das
nix.
Ich mach's immer so, bei einer unbekannten CPU:
1. GPIO toggle, irgendwie, z. B. mit "busy delay"
2. UART-Ausgabe - verbunden mit den richtigen Clock-Einstellungen.
3. GPIO toggle im exakten Sekundentakt, unter Verwendung eines Timers.
Danach hat man eine stabile Basis.
Dann kannst Du ohne Debugger die LCD-Lib mit log statements zu
pflastern. Nicht gerade die timing-kritischen Dinge, aber den Rest.
Die Delay-Funktion in der LCD-Lib zählt einfach eine Variable 'runter.
Wie soll das funktionieren, der stm32f103 wird vermutlich mit 72 MHz
laufen. Kann gehen, muss aber nicht. Timer wäre besser.
Die Sache mit den Fault-Handlern ist für die härteren Fälle. Ohne
sonstige Debug-Möglichkeiten als Unterbau bringt das vermutlich nix. Du
kannst die Handler in startup.c so füllen, dass er pro Fault mittels
LED-Kombination den Fault anzeigt.
Marco Weinrich schrieb:
> Habe eben die LCD-Aufrufe entfernt, und mittels Schleife die
> Arrayelemente
> in eine andere Variable kopiert.
> Das funktioniert einwandfrei, scheint also an der LCD-Geschichte zu
> liegen.
Wie siehst Du das?
Zum letzten Code-Beispiel ... die gleiche Frage ... das Ding rennt mit
72 MHz los ... über die erste Schleife, die letzte macht nichts, also
gewinnt die mittlere, 4x 'e' auf dem Display (?), funktioniert die
deshalb? ... woher weißt Du, dass die letzte Schleife funktioniert? ...
main() plumpst einfach durch, und der µC wird im startup.c über Wasser
gehalten ... mach doch mal wenigstens eine Schleife 'drumrum und
verwende das "rustikale" Delay().
Suchst Du den "lucky punch" ? :-) Den gibt's beim Boxen, aber µCs sind
zäh und stur :-)
Hallo Roland
>> Leider funktioniert daß mit den Led's und Uart nicht, da der
>> Controller hängt bevor die Ports/Uart initalisiert werden.
>
> Woher weißt Du das?
>
> Die LCD-Funktionen nutzen auch GPIO ?!
Auf dem Bord sind 3 Led's , sind die daran angeschlossen Ports noch
nicht initlisiert, "glimmem" die Led's ein wenig.
Sind die Ports initalisiert gehen die Led'S an, da sie gegen Plus
geschaltet sind.
An den "glimmenden" Led's erkenne ich, daß der Controller hängt,
und und die Ports noch nicht initalisiert sind.
> Was bedeutet eigentlich "geht" und "geht nicht"?
"funktioniert" heiß, das Programm funktioniert so wie ich mir das
vorstelle.
Das Lcd wird richtig initalisert, der Text steht da wo er soll, und ist
auch nicht spiegelverkehrt.
Die zu Debugzwecken eingebaute Uartausgabe funktioniert auch tadellos.
Led toggeln mit SysTick_Handler geht auch ohne Probleme und das in
einem Programm.
Verschiebe ich im selben Programm die globale Arraydeklaration nach
main()
hängt der Controller, die Led's glimmen nur.
(Bei der globalen Arraydeklaration funktioniert alles wie es soll,
auch das Arrayauslesen mittels Schleife.)
Im letzten Codeschnipsel war jeweils nur eine Schleife aktiv, die
anderen
beiden waren auskommentiert.(..unglücklich ausgedrückt!)
Die letze Schleife funktioniert, meine Led blinkt noch, Uartausgaben
danach funktionieren.
Möchte ich allerdings wert[i] per Uart ausgeben hängt der Controller
und die Led's glimmen nur.
Ich hoffe, ich habe Deine Fragen ausreichend beantwortet.
Mir leuchtet nicht ein warum das globale Array funktioniert,
das selbe lokal aber nicht mehr.Sobald ich in irgend einer Weise
auf wert[i] in einer Schleife zugreife hängt der Controller(lokales
Array)
Außerhalb einer Schleife geht es problemlos.(lokales Array)
Der Rest funtioniert wie ich das möchte.
Danke Roland, für Deine Bemühungen mit mir.
Gruß Marco
> Auf dem Bord sind 3 Led's , sind die daran angeschlossen Ports noch
> nicht initlisiert, "glimmem" die Led's ein wenig.
> Sind die Ports initalisiert gehen die Led'S an, da sie gegen Plus
> geschaltet sind.
> An den "glimmenden" Led's erkenne ich, daß der Controller hängt,
> und und die Ports noch nicht initalisiert sind.
Das passt aber nicht zum main.c: Dort wird GPIO_Configuration vor den
LCD-Zugriffen aufgerufen. Wie dem auch sei, zumindest drei LEDs sind
vorhanden.
> Die zu Debugzwecken eingebaute Uartausgabe funktioniert auch tadellos.
UART geht auch?
Dann mach bitte zwei Varianten: Eine die geht. Und eine, welche nicht
geht. In beiden Varianten gibst Du vor der Schleife, in der Schleife vor
und nach dem Zugriff und nach der Schleife das Feld aus. In der Schleife
auch die Schleifenvariable und am besten auch die restlichen
globalen/lokalen Variablen.
In der Schleife zu Beginn eine der LEDs auf hi, am Ende der Schleife auf
lo.
Um die Schleife herum ein while (1) { ... }. main soll nicht verlassen
werden!
Am Ende der while - Schleife noch ein delay, so dass man das Blinken der
2. LED wahrnehmen kann.
Du verwendest -Os. Es könnte ein anderes Fehlerbild ergeben, wenn Du die
Optimierung abschaltest.
Versuch auch mal, ohne den SysTick-Handler auszukommen. Die LED kannst
Du auch in main() togglen.
> Mir leuchtet nicht ein warum das globale Array funktioniert,
> das selbe lokal aber nicht mehr.Sobald ich in irgend einer Weise
> auf wert[i] in einer Schleife zugreife hängt der Controller(lokales
> Array)
Das hat Klaus schon beschrieben. Da geht dann etwas kaputt, was keine
Rolle spielt. Entweder wird beim Funktionsaufruf die Rücksprungadresse
zerstört oder die Schleifenvariable i ist betroffen, und wert[i] zeigt
ins Nirwana. Oder wert[i] ist zu groß, dann schlägt der Zugriff auf das
Array in PutChar() fehl. Das ist alles Spekulation.
> Außerhalb einer Schleife geht es problemlos.(lokales Array)
> Der Rest funtioniert wie ich das möchte.
Das ist schon möglich, aber auch diese Variante hat wahrscheinlich einen
Fehler, er kommt nur nicht zum Tragen.
> Leider funktioniert daß mit den Led's und Uart nicht, da der
> Controller hängt bevor die Ports/Uart initalisiert werden.
Aber die Initialisierung ist doch vor der problematischen Stelle?
Wie kann diese Initialisierung "übersprungen" werden?
Der einzige Code, der "überholen" kann, wäre der SysTick_Handler.
Hallo Roland,
habe eben auf die Schnelle den Optimierungsgrad von -Os
auf -O2 gesetzt.
Jetzt läuft es auch mit lokalem Array. Huhuuu!!!
Melde mich in ein paar Tagen ausführlicher, da ich jetzt
verreise.
Danke, und ein frohes Fest.
Gruß Marco
Hallo,
ich habe das Problem mit dem Optimierungsgrad noch einmal ausgiebig
getestet.
Die main.o darf nicht mit Optimierungsgrad -Os kompiliert werden,
-O0, -O1, -O2 und -O3 funktionieren problemlos.
Alle anderen Objektdateien funktionieren auch mit -Os.
Beim AVR habe ich nie Probleme mit -Os gehabt.
Das funktionierende Ergebnis habe ich angehangen.
Vielen Dank für Eure Hilfe.
Gruß Marco
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|