uint64_t auf STM32F103

OP #6078115
Lesenswert?

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.
Angehängte Dateien:
OP #6078129
Lesenswert?

Hallo,

hatte vermutet, dass eventuell eine Compiler-Option fehlerhaft sein 
könnte, daher das Makefile...

Der Code, der Ärger macht sieht so aus:
1
write_byte(0x04);    // FTWO 45.01MHz
2
write_byte(0x5C);
3
write_byte(0x2E);
4
write_byte(0x33);
5
write_byte(0xF0);
6

7
uint32_t FTW = (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) / ((uint64_t)(125000)));
8
write_byte(0x04);    // FTWO
9
write_byte(0xFF & (FTW >> 24));
10
write_byte(0xFF & (FTW >> 16));
11
write_byte(0xFF & (FTW >> 8));
12
write_byte(0xFF & FTW);

Die stdint.h ist natürlich eingebunden. Woran könnte der Fehler liegen?
OP #6078202
Lesenswert?

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_t FTW = 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?
OP #6078222
Lesenswert?

Hallo,

der RAM ist sehr gering ausgelastet, der Linker gibt folgendes aus:
1
Memory region         Used Size  Region Size  %age Used
2
           Flash:        5312 B       256 KB      2.03%
3
           SRAM0:          28 B        64 KB      0.04%

freq = 14000.

Hat sonst noch jemand Tipps?
So sieht die entsprechende Stelle disassembliert aus:
1
    uint32_t FTW = (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) / ((uint64_t)(125000)));
2
 8000d2a:  2300        movs  r3, #0
3
 8000d2c:  4a1a        ldr  r2, [pc, #104]  ; (8000d98 <configure_AD9951+0xd8>)
4
 8000d2e:  4629        mov  r1, r5
5
 8000d30:  4620        mov  r0, r4
6
 8000d32:  f7ff f9e3   bl  80000fc <__aeabi_uldivmod>
7
 8000d36:  4605        mov  r5, r0

Vielen Dank schon mal.
Gast #6078223
Lesenswert?

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.
OP #6078253
Lesenswert?

Vincent H. schrieb:
> (4294967296 * 14000) / 12500 != 1546188227 (0x5C28F5C3)

Das stimmt, aber:
(4294967296 * 14000) / 125000 = 481036337 (0x1CAC0831).
Und auch wenn ich
1
uint32_t FTW = (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) / ((uint64_t)(125000)));
durch
1
uint32_t FTW = 0x1CAC0831;
ersetze, funktioniert es. Das Problem muss deshalb in der Berechnung 
liegen...

Hat noch jemand einen Tipp?
OP #6078288
Lesenswert?

An Adresse 080000fc steht:
1
080000fc <__aeabi_uldivmod>:
2
 80000fc:  b953        cbnz  r3, 8000114 <__aeabi_uldivmod+0x18>
3
 80000fe:  b94a        cbnz  r2, 8000114 <__aeabi_uldivmod+0x18>
4
 8000100:  2900        cmp  r1, #0
5
 8000102:  bf08        it  eq
6
 8000104:  2800        cmpeq  r0, #0
7
 8000106:  bf1c        itt  ne
8
 8000108:  f04f 31ff   movne.w  r1, #4294967295  ; 0xffffffff
9
 800010c:  f04f 30ff   movne.w  r0, #4294967295  ; 0xffffffff
10
 8000110:  f000 b97a   b.w  8000408 <__aeabi_idiv0>
11
 8000114:  f1ad 0c08   sub.w  ip, sp, #8
12
 8000118:  e96d ce04   strd  ip, lr, [sp, #-16]!
13
 800011c:  f000 f806   bl  800012c <__udivmoddi4>
14
 8000120:  f8dd e004   ldr.w  lr, [sp, #4]
15
 8000124:  e9dd 2302   ldrd  r2, r3, [sp, #8]
16
 8000128:  b004        add  sp, #16
17
 800012a:  4770        bx  lr

Leider kenne ich mich mit Assembler nicht so aus. Hilft dies weiter?
Beitrag #6078295 wurde von einem Moderator gelöscht.
Gast #6078308
Lesenswert?

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
OP #6078322
Lesenswert?

Was ist das "alte Stack-Alignment-Problem"? Das kenne ich nicht.

Das Linker-Skript sieht so aus:
1
ENTRY(_reset)
2

3
MEMORY {
4
  Flash (rx):  ORIGIN = 0x08000000, LENGTH = 256K
5
  SRAM0 (rwx): ORIGIN = 0x20000000, LENGTH = 64K
6
}
7

8
_stack_end = ORIGIN(SRAM0) + LENGTH(SRAM0);
9

10
SECTIONS {
11
  .text : {
12
    _text_section_start = .;
13
    KEEP(*(._vectors))
14
    *(.text)
15
    *(.text*)
16
    *(.rodata .rodata.* .constdata .constdata.*)
17
    _text_section_end = .;
18
  } > Flash
19
  
20
  . = ALIGN(4);
21
  
22
  .bss : {
23
    _bss_section_start = .;
24
    *(.bss)
25
    *(.bss*)
26
    _bss_section_end = .;
27
  } > SRAM0
28
    
29
  . = ALIGN(4);
30
    
31
  .data : {
32
    _data_section_start = .;
33
    *(.data)
34
    *(.data*)
35
    _data_section_end = .;
36
  } > SRAM0 AT > Flash
37
}
Persönliche Seite #6078343
Lesenswert?

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.
OP #6078635
Lesenswert?

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.
Angehängte Dateien:
Gast #6078637
Lesenswert?

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.
OP #6078711
Lesenswert?

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.
OP #6078733
Lesenswert?

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!
Gast #6078770
Lesenswert?

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.
Angehängte Dateien:
Gast #6078899
Lesenswert?

beim gcc auf einem F407 mit gcc kompiliert wird das richtig gerechnet:
1
    uint64_t freq = 14000;
2
    uint32_t FTW = (uint32_t)((0x100000000ULL * freq) / 125000ULL);
3
    printf("testvar: %lx\n", FTW);
output:
testvar: 1cac0831
OP #6079152
Lesenswert?

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?
Persönliche Seite #6079164
Lesenswert?

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.:
1
uint32_t test (uint32_t freq) __attribute__ ((noinline));
2
uint32_t test (uint32_t freq) {
3
  return (uint32_t)(((uint64_t)(0x100000000) * (uint64_t)(freq)) / ((uint64_t)(125000)));
4
}
5

6
int main () {
7
  test (1234);
8
}

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.
Gast #6079234
Lesenswert?

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.
OP #6079315
Lesenswert?

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?
Angehängte Dateien:
Persönliche Seite #6079339
Lesenswert?

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?
OP #6079975
Lesenswert?

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? ;-)
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren