Forum: Compiler & IDEs arm gcc Arrayzugriff


von Marco W. (kniffeldi)


Angehängte Dateien:

Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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?

von Marco W. (kniffeldi)


Lesenswert?

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

von Marco W. (kniffeldi)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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.

von Marco W. (kniffeldi)


Lesenswert?

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

von Roland H. (batchman)


Lesenswert?

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.

von Marco W. (kniffeldi)


Lesenswert?

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

von Marco W. (kniffeldi)


Lesenswert?

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

von Roland H. (batchman)


Lesenswert?

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

von Marco W. (kniffeldi)


Lesenswert?

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

von Roland H. (batchman)


Lesenswert?

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

von Marco W. (kniffeldi)


Lesenswert?

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

von Marco W. (kniffeldi)


Angehängte Dateien:

Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.