Regel#1 hier im Forum und auch anderswo: immer den Original-Quellcode zeigen.
Regel#2 hier im Forum und auch anderswo: immer den ganzen Quellcode zeigen.
Stackoverflow, Array out of bounds, oder wie auch immer du die Daten überschreibst.
Entweder dein Startupcode oder Linkerscript ist defekt, oder die Variable Arial_7x10 wird von einem "wilden Pointer" überschrieben (Buffer Overflow o.ä.).
Wenn das Programm ganz am Anfang ist (Anfang der main()), sind die Daten dann richtig? -> Watchpoint drauf setzen und laufen lassen.
Sind die Daten da schon falsch? Breakpoint im Startupcode NACH das " bcc CopyDataInit" setzen und schauen ob es dann stimmt - wenn ja, Watchpoint setzen und laufen lassen. Wenn nein, ist was am Startupcode/Linkerscript kaputt.
Wenn das Programm ganz am Anfang ist (Anfang der main()), sind die Daten
dann richtig? -> Watchpoint drauf setzen und laufen lassen.
von Oliver S. (oliverso)
Stackoverflow, Array out of bounds, oder wie auch immer du die Daten
überschreibst.
Danke für den Tipp.
Hab einen kleine Struct erzeugt und diesen intialisiert an der gleichen Stelle mit dem alten Struct - auch der neuer Strukt wurde falsch initialisiert.
Am Anfang des Programms (Anfang der main()) hat alles sauber geklappt.
Muss mal sehen wie ich den Stack checken kann.
Am Anfang des Programms (Anfang der main()) hat alles sauber geklappt.
Die Structs werden nicht durch "Magie" befüllt, das macht der µC schon schön selber in seinem Startup-Code. Wenn du deinen Breakpoint zu früh hast, kannst du dem µC zuschauen, wie er der Reihe nach seine globalen Variablen und Structs initialisiert. Am Anfang von "main" ist er damit fertig...
Setze einfach einen Watchpoint auf das struct und lasse das Programm laufen. Das Programm wird dann genau an der Stelle unterbrechen wo der fehlerhafte Zugriff ist. Geht blitzschnell.
Warum ist der Font für das Display "Short" (das sind Bytes), und warum sollte die Struct erst initialisiert werden müssen? Die ist doch wohl hoffentlich im Flash? Oder ist der Prozessor behindert und kann Displaydaten nur aus dem RAM lesen?
Nein, weil kein "const" dran steht kommt es in den RAM und muss erst
kopiert werden.
Soweit mir bekannt wird auch const bei manchen Prozessoren im RAM (oder gar in Registern) gelagert, weil schneller/kürzer zugreifbar.
Zumindest bei AVRs muss man auch noch PROGMEM angeben, um es sicher ins Flash zu packen.
Erst jetzt wurde der Struct ordentlich initialisiert - alle Werte in den Variable richtig eingetragen.
Definition der Struktur aus main() in "Display.h" versetzt - funktionierte auch.
komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen).
Compiler hat sich "verschluckt" und ist mit der Meldung "undefined reference to memcpy'" ausgestiegen.
Der Eintrag #include "string.h" hat nicht geholfen.
Erst eine weitere Ergänzung der Tabellendefinition mit "static" hat mich weitergebracht
1
"static const unsigned short Arial_7x10_Table[95][10] . . . "
Die gesamte Tabelle ins "Display.h" verschoben - geht auch :-)
Also mit einer Schrift (Font) könnte man es so belassen.
Wenn man aber 2 - 3 Fonts hat, wird die Header "überladen" wirken.
Geschickter wäre es pro Font eine Separate Datei zu haben - aber genau das funktioniert noch nicht hinbekommen.
komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen).
Compiler hat sich "verschluckt" und ist mit der Meldung "undefined
reference to memcpy'" ausgestiegen.
Spätestens an der Stelle sollte klar sein, daß deine toolchain kaputt ist.
Du doktorst an den Symptomen rum. Du hast irgendwo einen Buffer Overflow o.ä. Den findest du so nicht. Der wird dich später anderweitig in den allerwertesten beißen, du hast so eine Zeitbombe im Code.
Auf die Gefahr mich zu wiederholen: Benutze einen Data Watchpoint. Damit hast du das eigentliche Problem in 2 Minuten gefunden. Ohne Rätselraten und Rumprobieren.
Es ist extremst unwahrscheinlich, das eine intakte toolchain ein
„undefined
reference to memcpy“ auswirft.
Das ist sogar sehr wahrscheinlich. Intakte toolchains tun das ständig. Bei fehlerhaftem Code eben. Der hier sehr wahrscheinlich vorliegt. Aber diesen kennen wir ja nicht.
komplette Tabelle am Anfang der Main() eingetragen (95 Zeilen).
Wenn man die Tabelle als lokale Variable in die main() schreibt MUSS eine intakte Toolchain diesen Fehler liefern, wenn man versucht von anderen Stellen aus "direkt" darauf zuzugreifen.
Spätestens an der Stelle sollte klar sein, daß deine toolchain kaputt
ist.
Könnte gut sein. Leider hab ich von Einstellungen in "Eclipse" nicht viel Ahnung. Die IDE wurde mir vor Jahren vom Arbeiskollegen in Frankfurt eingerichtet. Ich bin "weit weg" aus Frankfurt nach Paderborn umgezogen und den Kontakt verloren. So programmiere ich immer noch Hobbymäßig mit der alten Einrichtung / Umgebung.
Leider, sind Programmierer "meiner Klasse"(Über 70 und immer noch in "C") in meiner Umgebung nicht zu finden. Würde mich tierisch freuen eine "verwandte Sehle" in der Nähe zu haben.
Könnte aber auch gut sein dass die IDE sehr "mager" eingerichtet ist so dass die Programme auf mehreren MK laufen werden.
So programmiere ich immer noch
Hobbymäßig mit der alten Einrichtung / Umgebung.
.... und stopselt tage- und wochenlang vor sich hin anstatt
sich richtig helfen zu lassen - mit einem kompletten, nach-
vollziehbaren Code den man zur Verfügung stellt.
Die IDE wurde mir vor Jahren vom Arbeiskollegen in
Frankfurt eingerichtet.
PS: Mittlerweile kommt die STM32CubeIDE mit einem simplen Installer. Da bekommt man mit wenigen Klicks ein aktuelles (!) funktionsfähiges Gesamtpaket und muss auch nix konfigurieren. Man hat sehr schnell ein Projekt für den gewünschten Controller angelegt, kann sich grafisch die Takt- und Pin-Konfiguration zusammenklicken und bekommt den entsprechenden Code generiert. Das kann sich jeder selbst einrichten.
Man hat sehr schnell ein
Projekt für den gewünschten Controller angelegt, kann sich grafisch die
Takt- und Pin-Konfiguration zusammenklicken
Naja, das ist für einen "Anfänger" schon eine kleine Herausforderung
da es beim "Zusammenklicken" schon einige Sachen zu beachten gibt
die sich als kleine Fallstricke herausstellen können. Aber man
muss ja nicht die graphische Initialisierung wählen sondern kann
sich nach herkömmlicher Art sein Projekt in der CubeIDE zusammen-
stellen - einfach alle Sourcen in ein neues leeres Projekt herein-
kopieren. Das würde sich auch anbieten wenn der TO mal sein
komplettes Projekt posten würde.
Die CubeIDE zu verwenden ist auf jeden Fall empfehlenswert um von
der halbgaren Eclipse-Installation wegzukommen. Ja ich weiss,
Eclipse ist dann immer noch präsent ...
Pas Projekt ist inzwischen "etwas" gröser geworden(siehe Bild). Ein Paar Verzeichnisse fehlen noch. Ich versuche den "Sieben Segment Display" mit einen "graphischen Display" zu ersetzen.
Würde es helfen die main(), Display.c und die Display.h zur Verfühgung zu stellen?
Soll ich den Code direkt hier einfügen?
Oder ich kann auch das Projekt komplett mal zippen.
Das ist pöhse, das tut man nicht und es fällt einem irgendwann
auf die Füsse. Daten und Code in *.h Dateien tut man nicht.
Nein das tut man nicht! Bunkt.
Das ist mir im Nachhinen klar: die grosse Struct in Main anzulegen
sprengt die Grösse des Stacks die per default irgendwo festgelegt
wird.
Naja weil Stack und .data beim Default Setup vom STM32 sich entgegen wachsen, sollte es effektiv keinen Unterschied machen... Besonders schön ist es aber wirklich nicht.
weitere Ergänzung der Tabellendefinition mit "static" hat mich
weitergebracht
"static const unsigned short Arial_7x10_Table[95][10] . . . "
Die gesamte Tabelle ins "Display.h" verschoben - geht auch :-)
Du hast offenbar keine Ahnung, was Du da tust.
Durch "static" beschränkst Du den Scope für die Tabelle auf die aktuelle Übersetzungseinheit. Wenn Du dann zusätzlich noch die Tabelle ins Display.h verschiebst, ist das ein Doppel-Eigentor.
Folge ist nämlich, dass die Tabelle damit für jede Übersetzungseinheit, in welcher Du Display.h inkludierst, noch einmal neu erzeugt wird. Wenn also ein Dutzend von C-Sources
1
#include"Display.h"
aufrufen, hast Du auch ein dutzendmal die Tabelle im Speicher - ob Flash oder auch RAM... siehe oben.
Mit Deinen Aktionen dokterst Du nur an den Symptomen, ohne den eigentlichen Fehler auszumerzen. Du hast höchstwahrscheinlich einen Buffer-Overflow für die Variable, die im Source vor Deiner Array-Definition liegt. (*1)
Beispiel:
1
#include<stdio.h>
2
#include<string.h>
3
4
charbuffer[4];
5
intvariable;
6
7
intmain()
8
{
9
strcpy(buffer,"hello");// Dieser Befehl überschreibt variable
10
11
printf("%d\n",variable);
12
}
(*1) Muss nicht zwingend so sein, je nach Compiler oder Optimierung kann die Reihenfolge der Variablen im RAM abweichen. Wenn man beide Variablen in eine Struct packt, dann passierts aber ziemlich sicher.