STM32: Division durch Null

OP #6098945
Lesenswert?
• ▲
▼
Guten Morgen,

ich stehe gerade vor einem Rätsel. Ich wollte nur die Fehler-Ausgabe 
testen. Als praktischste Stelle kam mir ein Bresenham-Algorithmus vor, 
weil der häufig aufgerufen wurde.
1
    typedef struct State32_s
2
    {
3
        int32_t z;  /**< Zaehler */
4
        int32_t n;  /**< Nenner */
5
        int32_t r;  /**< Rest */
6
    }
7
    State32_t;
8

9
    State32_t GState = {.z = 300, .r = 0};
10

11
    static int32_t foo(void)
12
    {
13
        State32_t *State = &GState;
14
        
15
        int32_t dy = ((int64_t) State->z * dx + State->r)/State->n;
16
        State->r = ((int64_t) State->z * dx + State->r)%State->n;
17

18
        return dy;
19
    }

Mit dem Debugger habe ich State->n auf Null gesetzt. Von mir wurden auch 
keine extra Fehler-Handler als der HardFault_Handler() implementiert. 
Trotzdem wird diese Funktion mit State->n == 0 mehrmals durchlaufen, 
ohne dass ein Fehler auftritt. Der Rückgabewert wird auch weiter 
verwendet.

Was passiert hier?
Kann man in __eabi_ldivmod() irgendwie hineingucken?
Gast #6098977
Lesenswert?
• ▲
▼
Walter T. schrieb:

> Mit dem Debugger habe ich State->n auf Null gesetzt. Von mir wurden auch
> keine extra Fehler-Handler als der HardFault_Handler() implementiert.
> Trotzdem wird diese Funktion mit State->n == 0 mehrmals durchlaufen,
> ohne dass ein Fehler auftritt. Der Rückgabewert wird auch weiter
> verwendet.
>
> Was passiert hier?

https://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/
Da steht: "To enable hardware reporting of div0 errors we need to 
configure the CCR"
#6099004
Lesenswert?
• ▲
▼
Unabhängig von der fehlenden Error-Meldung:
Kann das der type-cast von 64Bit auf 32Bit sein ?
angenommen mit geteilt durch Null geht der 64Bit Wert auf den maximal 
positiven Wert
0X7FFF FFFF FFFF FFFF
wenn der cast daraus ein
0XFFFF FFFF
macht, käme -1 dabei heraus.
OP #6099041
Lesenswert?
• ▲
▼
Das ließ sich ja einfach testen:
1
typedef struct State32_s
2
{
3
    int32_t z;  /**< Zaehler */
4
    int32_t n;  /**< Nenner */
5
    int32_t r;  /**< Rest */
6
}
7
State32_t;
8

9
State32_t GState = {.z = 300, .r = 0, .n = 0};
10

11

12
volatile int64_t temp = 0;
13

14
static int32_t foo(int32_t dx)
15
{
16
    State32_t *State = &GState;
17

18
    temp = ((int64_t) State->z * dx + State->r)/State->n;
19
    int32_t dy = temp;
20
    State->r = ((int64_t) State->z * dx + State->r)%State->n;
21

22
    return dy;
23
}
24

25

26
/* Funktion zum Testen von Sachen. */
27
exit_t runToShow(void)
28
{
29
    int32_t dx = 20000;
30
    volatile int32_t dy;
31

32
    dy = foo(dx);
33
    printf("dy = %i", dy);
34

35
    return EXIT_SUCCESS;
36
}

Ergebnis 1: Ja, Du hast Recht. Auf dem STM32 ist das tatsächlich ein von 
__eabi_ldivmod() bestmöglich behandelter Overflow.
temp = 0x7fffffffffffffff.

Ergebnis 2: Unter Windows (wo wahrscheinlich direkt die CPU den 
Divisionsbefehl bekommt) stürzt das wie erwartet gnadenlos ab.
(Firma: fritzler-avr.de) #6099785
Lesenswert?
• ▲
▼
Aus dem ARM Infocenter:
Integer division is implemented by calling the C library functions 
__aeabi_idiv and __aeabi_uidiv. These check for divison by zero. If 
integer division by zero is detected, a branch to __aeabi_idiv0 is made. 
So to trap the division by zero, all you need to do is place a 
breakpoint on __aeabi_idiv0.

Also für die 64Bit Version das Symbol im Linkerscript ersetzen und dann 
einen Hardfault selber aufrufen?

Ein 64Bit div kann der 32Bit ARM Kern ja nicht selber ausführen.
Aber wieso bläst du da auf 64Bit auf?
Der Bresenham ist ja zum Linien zeichnen auf Rastern für eine GUI oder?
Das wird dann ja recht langsam in Software.

Ansonsten hat ein gast schon geschrieben, dass auch das 32Bit HW Div0 
Trap erst aktiviert werden muss.
Weiteres hier dazu: Beitrag "ARM Cortex-M3/4/7 Faulthandler"
OP #6099807
Lesenswert?
• ▲
▼
Mw E. schrieb:
> So to trap the division by zero, all you need to do is place a
> breakpoint on __aeabi_idiv0.

Danke für den interessanten Aspekt.

Meine naive Frage: Wie setzt man denn einen Breakpoint in eine 
Library-Funktion mit einem grafischen Debugger? Mein erster Ansatz: 
Map-File aufrufen, nach der Funktion suchen und an die Adresse springen. 
(Erst einmal: Super, das das geht. Ein für mich neues und praktisches 
Hilfsmittel.) Geht es noch einfacher?

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.