STM32 - CodeBench Lite - 64-bit Division

OP Persönliche Seite #2814585
Lesenswert?

Folgendes mir unerklärliche Verhalten:

Cross-Compiler: 2011.03 / 2011.09 und 2012.03 Versionen von Sourcery 
Codebench Lite.
Library: Newlib C Library (1.18.0-sg++) (stdlib.h) aus der Suite 
Sourcery CodeBench Lite.

Verhalten: sobald die Funktion "strtoull" im Programmcode eingebaut wird 
ist die Baudrate von USART1 vervierfacht. Keine Fehlermeldungen, keine 
Warnmeldungen beim compilieren, Programm läuft, Debugger läuft, evtl. 
geht das Programm manchmal in den HardFault_Handler interrupt.
Das selbe Verhalten tritt auf sobald folgendes irgendwo in das Programm 
eingebaut wird (also unabhängig davon ob dies auch ausgeführt wird):
1
long long test1 = 10, test2 = 4, test3;
2
test3 = test1 / test2;

Vermute, dass "strtoull" ebenfalls eine 64-bit Division enthält. Die 
64-Bit Division führt in jedem Falle zu dem Fehlverhalten.
Erhebliche Vergrößerung des Stacks erbringt keinerlei Veränderung des 
Verhaltens, selbst das Ergebnis der Division scheint korrekt (keine 
ausgiebigen Versuche, da eine Division dieser Art nicht benötigt wird).

Manual "Using the GNU Compiler Collection, chapter 6.9" sagt aus, dass: 
"(long long) divisions are open coded and are available only on machines
providing special support."

Die Frage ist:
Was passiert da? Schließlich ist die Baudrate unabhängig vom erzeugten 
Code und lediglich ein Wert in einem CPU-Register.
Erklärungen?
#2819316
Lesenswert?

>  Was passiert da? Schließlich ist die Baudrate unabhängig vom erzeugten
> Code und lediglich ein Wert in einem CPU-Register.

Die meisten Cortex_M3 Libs die ich kenne erzeugen den Wert für die 
Baudrate dynamisch aus der aktuellen CPU Frequenz. Und weil da relevante 
Nachkommastellen auftreten könnnen wird mit 64 Bits gerechnet.

Abhilfe: Bei bekanntem CPU Takt die entsprechenden Werte von Hand - oder 
vom Compiler - ausrechnen (lassen) und in die Register eintragen.

Es könnte sein dass die Funtion nicht reentrant ist - dann darf man 
diese Berechnung der Baudrate nicht im Interrupt ausführen.
Moderator Persönliche Seite #2820383
Lesenswert?

Ja, 64bit-Division ist augenscheinlich in strtoll. Quellcodeteil der 
newlib sieht aber wenig dramatisch aus: 
http://sourceware.org/cgi-bin/cvsweb.cgi/src/newlib/libc/stdlib/strtoll_r.c?rev=1.3&content-type=text/x-cvsweb-markup&cvsroot=src 
. Unter bestimmten Bedingungen wird jedoch ein Fehlercode gesetzt, dabei 
wird in einen Struktur vorm Type __reent geschrieben. Beim Aufruf der 
"normalen" Funktion (nicht der _r-Variante) wird dann in 
impure_data.errno geschrieben. _impure_ptr zeigt auf diese globale 
Stuktur impure_data. Man kann also evtl. hier per Debugger nachverfolgen 
- erscheint aber wenig erfolgversprechend.

Problem könnte auch im Zusammenhang mit der Fehlerüberprüfung einer 
Divisiononsroutine in der libgcc liegen. Gibt es im Linkerscript 
Einträge für ARM.extab und ARM.exidx? Einige Versionen der libgcc haben 
Abhängigkeiten zur C++-Ausnahmeverarbeitung mitgezogen, selbst wenn man 
"reines" C nutzt. Im Zweifel und falls nicht schon drin, die die beiden 
Sections in das Linkerscript eintragen (siehe Beispiele in CS 
Installationsverzeichnis) und anhand des Map-Files prüfen, ob dort etwas 
von libgcc (und/oder libc) abgelegt wird (siehe vor allem nach 
libgcc/_udivdi3 und libgcc/_divdi3 jeweils einträge in extab und exidx, 
in exidx zusätzlich noch für libgcc/bpabi).
#2820453
Lesenswert?

Jim Meba schrieb:
> Die meisten Cortex_M3 Libs die ich kenne erzeugen den Wert für die
> Baudrate dynamisch aus der aktuellen CPU Frequenz. Und weil da relevante
> Nachkommastellen auftreten könnnen wird mit 64 Bits gerechnet.

Sieht bei mir eher schlicht aus, STM32F1xx:
    unsigned apbclk = (info->dev == USART1) ? F_APB2 : F_APB1;
    info->dev->BRR = apbclk / baud;
Die 4 Nachkommstellen stehen im Baudratenregister. Ok, man könnte hier 
noch ein halbes Bit runden, aber ob das so wichtig ist? Weshalb man da 
64 Bits braucht erschliesst sich mir nicht.

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