Hallo,
ich implementiere gerade einen Algorithmus auf einem STM32F103. Dabei
müssen leider großen Integer verarbeitet werden. Sobald ich allerdings
uint64_t statt uint32_t in meinem Programm verwende, läuft das ganze
Programm nicht mehr! Selbst der Teil vor der ersten Verwendung von
uint64_t wird nicht ausgeführt, der Mikrocontroller bleibt komplett
still.
Woran kann das liegen?
Ich benutze den arm-none-eabi-gcc und im Anhang ist mein makefile.
Vielen Dank für weiterführende Tipps.
Doran S. schrieb:> Woran könnte der Fehler liegen?
Kann man an diesem kleinen Schnipsel nicht sehen.
Zur Ratekiste würde ich hinzufügen: Speicherüberlauf
Eventuell hilft es, sich die Warnungen des Compilers anzuschauen.
Doran S. schrieb:> uint32_t FTW = (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) /> ((uint64_t)(125000)));
Sicher daß deine DDS mit 125kHz läuft? Oder sind es nicht eher 125 MHz?
Hallo,
Ja, der DDS läuft natürlich mit 125MHz. Ich rechne aber in kHz, daher
passt das. Der Fehler muss aber in der gezeigten Zeile liegen, denn wenn
ich diese Zeile z.B. durch
1
uint32_tFTW=0x5C28F5C3;
ersetze, dann geht alles.
Ich kann auch z.B. den Compiler-Output bereitstellen, oder den gesamten
Quellcode, falls dies hilft? Was benötigt ihr?
Am C-Code iegt es in der Zeile nicht. Wenn Ram insgesamt knapp ist,
könnten die 64-Bit-Routinen natürlich das Faß zum überlaufen bringen,
aber so wirklich glaube ich da nicht dran.
Oliver
Stefan F. schrieb:>> Woran kann das liegen?>> Am Makefile kann man das nicht erkennen.>> Abgesehen davon: Der Dateiname sollte mit einem "M" beginnen, nicht "m".
Die meisten Windows-User haben noch nie davon gehört, dass Dateinamen
case-sensitiv sein können. Bei Windows ist es egal, wie das (M/m)akefile
heißt.
Doran S. schrieb:> 8000d2e: 4629 mov r1, r5> 8000d30: 4620 mov r0, r4> 8000d32: f7ff f9e3 bl 80000fc <__aeabi_uldivmod>
Das ist sicher keine 64bit Operation. Aber dividiere mal freq und
125.000 vorher durch 1000, dann koennte es passen.
leo
Vincent H. schrieb:> (4294967296 * 14000) / 12500 != 1546188227 (0x5C28F5C3)
Das stimmt, aber:
(4294967296 * 14000) / 125000 = 481036337 (0x1CAC0831).
Und auch wenn ich
Doran S. schrieb:> der Mikrocontroller bleibt komplett still.
Glaub ich nicht. Springt in eine Exception (Hard Fault,...)?
Ich hatte mit uint64_t auf IAR EWARM nie Probleme mit dem F103.
Doran S. schrieb:> uint32_t FTW = (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) /> ((uint64_t)(125000)));
schreibe doch mal statt dessen folgendes:
uint32_t FTW = (uint32_t)(((uint64_t)(0x10000000) * (uint64_t)(freq))
/((uint64_t)(125000)));
...wenn es läuft: dann war ein Null zuviel dran
Vielleicht ist es das alte Stack-Alignment-Problem. Zeig mal das ganze
Linkerscript und den Startupcode. Was sagt der Debugger zum Crash?
Hard-Fault? Register-Inhalte, insb. SP? An welcher Stelle crasht es
genau?
Mit dem Debugger kann ich leider nicht ran, weil die Hardware nur einen
UART-Anschluss hat (über den ich flashe). Gibt es Alternativen? Kann man
das irgendwie simulieren?
Doran S. schrieb:> Was ist das "alte Stack-Alignment-Problem"? Das kenne ich nicht.
Bei manchen Beispiel-Linker-Scripten von ST ist der initiale
Stack-Pointer falsch gesetzt, sodass er ein falsches Alignment hat, und
dann das Speichern von 64bit-Werten auf dem Stack scheitert. Das scheint
hier aber nicht der Fall zu sein.
Doran S. schrieb:> Mit dem Debugger kann ich leider nicht ran, weil die Hardware nur einen> UART-Anschluss hat
Fehler Nr. 1 beim Hardware-Design...
Doran S. schrieb:> Gibt es Alternativen? Kann man> das irgendwie simulieren?
z.B. mit einem anderen STM32F103-Board. Keil µVision kann auch STM32
simulieren.
Wenn ich das gesamte Projekt als gepacktes Archiv hochlade, könnte dann
jemand, der eine Hardware mit Debug-Möglichkeit hat, das mal bei sich
ausprobieren? Vielleicht hat ja mein Controller einen Hardware-Schaden?
Doran S. schrieb:> Wenn ich das gesamte Projekt als gepacktes Archiv hochlade,
Ich schätze, der Betreiber des Forums würde sich freuen, wenn du das
über Dropbox oder einen ähnlichen Dienst machst, wegen der Größe.
Hallo,
ich komme einfach nicht weiter. In Keil uVision muss ich mich erst
einarbeiten. Anbei jedoch das komplette Programm als Disassemble. Wer
darin den Fehler findet und mir beibringen kann, was schief gelaufen
ist, bekommt von mir ein 1X16 LCD als Weihnachtsgeschenk zugesendet.
Doran S. schrieb:> ich komme einfach nicht weiter.
Welche IDE benutzt du?
Mache ein "clean" (allo *.obj, *.o, *.bin etc) und komprimiere
dein Projekt in ein Zip-File, setze es hier rein, es findet sich
sicher jemand der es nachprüfen kann. So gross kann dein Projekt
nicht sein dass es nicht hier up- und downloadbar sein könnte.
Doran S. schrieb:> Ich benutze keine IDE,> sondern gebe im Terminal "make" ein.
Gut, ich baue ein Projekt daraus und melde mich dann.
Vielleicht macht es jemand anders auch auf anderem Weg ....
Doran S. schrieb:> anbei das komplette Projekt als ZIP-Archiv.
Lässt sich leider nicht auf die Schnelle debuggen da ein Teil
des Codes die Ports der SWD Schnittstelle umprogrammiert und
man somit keinen Zugriff aufs Debuggen hat.
Doran S. schrieb:> oh, das habe ich übersehen. Im Anhang eine Version ohne Deaktivierung> der Debug-Schnittstelle.
Nein, ist immer noch der gleiche Code.
Tut mir leid, ich bin raus.
Hallo,
das tut mir Leid, ich habe aber tatsächlich in der letzten Version keine
Deaktivierung der Debug-Schnittstelle mehr drin. Die Datei STM32F100.c
ist entsprechend angepasst.
Vielen Dank aber trotzdem für Deine Mühe. Bin eh ganz durcheinander,
weil ich das heute den ganzen Tag versucht habe. Vielen Dank für die
Tipps von allen Seiten.
Das Angebot steht aber noch.
Doran S. schrieb:> das tut mir Leid, ich habe aber tatsächlich in der letzten Version keine> Deaktivierung der Debug-Schnittstelle mehr drin.
Diese Deaktivierung muss ja einen Sinn haben, wozu wird es
überhaupt gemacht wenn man es auch weglassen kann?
Hallo,
an PA13, PA14 und PA15 hängt Peripherie. Deshalb brauche ich diese als
"normale" Ausgänge. Wenn ich es wieder aktiviere, dann funktioniert
natürlich manche Peripherie nicht mehr, aber der Fehler, dass der
Mikrocontroller kein Programm mehr ausführt, besteht immer noch.
1
// PA13, PA14 and PA15 as normal GPIO
2
RCC->APB2ENR|=(0x01<<0);
3
AFIO->MAPR|=(0x04<<24);
Diese Zeilen habe ich darum in der zweiten Version auskommentiert.
Wenn Du noch weitere Infos brauchst, kann ich diese natürlich liefern.
Viele Grüße!
Gut, ich habe deine Sourcen in ein Projekt auf Basis des
BluePill Boards (F103C8T6) eingebunden. Es compiliert
einwandfrei, durchläuft die Initialisierung ohne Probleme,
ebenso wird die Hauptschleife zyklisch abgearbeitet. Keine
Hänger oder Hard Faults.
Anbei das lauffähige Projekt für Embitz. Verwende das, du
wirst sehen das geht relativ einfach und du hast den Debugger
gleich mit eingebaut.
Wenn es mit der Einstellung (F103C8T6) nicht gleich
funktioniert musst du noch den richtigen Controller im
Projekt einstellen.
Im Code ist also kein prinzipieller Fehler enthalten, es muss
dann wohl an deinem Linker Description File liegen, oder
was anderem was ich beim Bau des Projekts nicht berücksichtigt
habe.
Was passiert, wenn FTW = 0 ist?
Vielleicht entwickelt der Compiler (uint64_t)(0x100000000) zu Null?
Im verbesserten Code steht auch: (uint64_t)(0x100000000ul)...
OT512 schrieb:> Im verbesserten Code steht auch: (uint64_t)(0x100000000ul)...
Das habe ich sicherheitshalber hinzugefügt.
Sonst ist da nichts "verbessert".
Hallo,
vielen Dank für die hilfreichen Antworten an alle.
Also, wenn ich das EmBitz-Projekt von STM Apprentice kompiliere (und mit
"stm32flash -w F103_uint64_Test.hex -v -R -i -dtr,rts,-rts:dtr,rts,-rts
/dev/ttyUSB0") flashe, dann geht es! Es muss also irgendwie an den
Einstellungen (Compiler, Linker) liegen....
Habe mal wie von Dieter Graef vorgeschlagen -lgcc bei den Linker-Flags
hinzugefügt, aber das hat keine Änderung verursacht.
Auch macht es keinen Unterschied ob ich uint64_t oder int64_t
benutze....
Bin echt ratlos. Hat noch jemand eine Idee?
Doran S. schrieb:> ich komme einfach nicht weiter.
Hilf dir doch selbst. Reduziere das Programm auf ein Minimum, welches
immer noch den Fehler hat - idealerweise nur eine main()-Funktion mit
eine paar wenigen Zeilen, ganz ohne jegliche Ansteuerung externer
Peripherie. Du kannst ja ggf. eine LED einschalten o.ä. um zu sehen ob
es noch läuft, auf der tatsächlichen Hardware ohne Debug-Möglichkeit.
Stelle sicher dass die Division tatsächlich zur Laufzeit durchgeführt
wird, und nicht vom Compiler wegoptimiert. Eine Möglichkeit das zu
tricksen wäre z.B.:
Das Ergebnis-Programm mit Fehler spielst du dann auf ein
STM32F103-Eval-Board, debuggst es mit einem ST-Link und gehst es Schritt
für Schritt durch bis es abstürzt. Dieses Programm
(Code+Kompilat/ELF-Datei) kannst du dann auch hier hochladen damit wir
es auch ausprobieren können.
Warum steht im Code eigentlich was von STM32F100 während es aber ein
STM32F103 sein soll? Nicht dass der Takt oder Power-Management falsch
initialisiert wird oder so. Das kann alle möglichen kuriosen Effekte
haben.
Doran S. schrieb:> Bin echt ratlos. Hat noch jemand eine Idee?
Stack/heap?
die keil/iar IDEs haben ja in den einstellungen angaben für die
Stack/heapgrößen
Doran S. schrieb:> Cool, wie hast Du compiliert? (Welche Compiler- und> Linker-Einstellungen?)
ich habe das mit Mbed gemacht, den F407 habe ich gerade hier liegen und
die Zeilen sind da schnell reinkopiert.
Die Compileroptionen sind so gesetzt, hatte das debug Profil genutzt:
https://github.com/ARMmbed/mbed-os/blob/master/tools/profiles/debug.json
Gegenüber deinem Makefile sind hier wohl vor allem noch -WExtra wichtig
für striktere Prüfung, mit -Og ist die Optmimierung reduziert.
Wie die Vorredner glaube ich nicht das die long long Operationen das
Problem sind, es wird nur hier sichtbar. So Spätfolgen passieren bei
korupptem Stack oder Querschreibern, schreiben über Arraygrenzen hinweg
oder Zeigerfehler.
Auch die Newlib Nano kann long long rechnen, nur das printf ist da
reduziert und kann die nicht ausgeben. Führt aber auch nicht zu
Programmfehlern.
Evtl. mal als C++ übersetzen, das ist ja pingeliger und so Sachen wie
impliziete Funktionsdeklarationen sind Fehler und keine Warnungen.
Hallo,
bin nun einen Schritt weiter: Wenn ich mein Linker-Skript (STM32F100.ld)
und meinen Startup-Code (crt0.c) durch den vom Projekt von "STM
Apprentice" ersetze, dann geht es. Mein Fehler ist also entweder im
Startup-Code und/oder im Linker-Skript. Kann jemand erkennen, was im
einem Startup-Code oder Linker-Skript fehlt?
Doran S. schrieb:> Kann jemand erkennen, was im> einem Startup-Code oder Linker-Skript fehlt?
Im Linkerscript fehlt vor dem "_bss_section_start", dem
"_bss_section_end", "_data_section_start", "_data_section_end",
"__end__", "(*.stack)" jeweils ein ".=ALIGN(4)". Wo hast du das kaputte
Linkerscript her? Warum nimmst du nicht eins von der IDE oder aus
STM32Cube?
Ist denn die Definition des Interrupt-Vektor im Startup-Code korrekt und
für deinen Controller passend?
Hallo,
also, das Problem war letztendlich das Linker-Skript.
(Und als ich das korrekte von dem Projekt von "STM
Apprentice" zusammen mit einem Startup-Code "crt0.c" verwendet hatte,
hat es nicht funktioniert, weil ein paar Namen (von Sections) anders
sind. Nachdem ich das korrigiert hatte, hat es funktioniert.)
Um sowas in Zukunft besser zu können, möchte ich mehr über
Linker-Skripte lernen. Kann mir jemand Literatur oder ein Tutorial dazu
empfehlen?
Außerdem ist mir nicht so ganz klar, was die einzelnen Sections
bedeuten, also wozu der Prozessor diese benötigt.
Was liegt in .init? Was in .fini? Was ist das .eh_frame? .ARM.extab und
.ARM.exidx? Wo kann man diese Dinge lernen?
Vielen Dank an alle für die vielen Tipps, die dann zur Lösung geführt
haben.
Ein Problem bleibt: Wem schicke ich nun das Display? ;-)
Doran S. schrieb:> Ein Problem bleibt: Wem schicke ich nun das Display?
Du hast dich bei mir schon bedankt indem du geschrieben hast
wie es ausgegangen ist. Das wünschen sich alle die so einen
Thread verfolgen, und du hast es dankenswerter Weise getan.