Forum: Mikrocontroller und Digitale Elektronik STM32F4/L4 Hardfault bei Funktionsaufruf - verzweifelt..


von Thomas T. (runout)


Lesenswert?

Hallo Gemeinde,

ich habe jetzt ein komplettes Wochenende verbraten und komme nicht 
weiter.

Ich habe ein Nucleo-Board mit einem STM32L476RG.
Entwicklung mit EmBitz (Em:Blocks) 0.42. mit arm-none-eabi.

Der Controller hat 1M Flash und 96k RAM
stack=0x0400
heap=0x0200

Das Prolem:

Beim Aufruf einer pobligen Init-Routine geht direkt
beim Step in die Funktion der Controller in Hard_Fault!
Das ganze sieht so aus:


       /* initialize CANopen */
        int32_t                 CANbaseAddress = 0;
        uint8_t                 nodeId = 1;
        uint16_t                bitRate = 500;

        err = CO_init(CANbaseAddress, nodeId, bitRate);
        if(err != CO_ERROR_NO) {

Ich bin ARM Cortex Anfänger aber solche Themen konnte ich eigentlich 
immer selber erschlagen.

Den Hard_Fault_Handler habe ich mal bisschen "verbose" gemacht...
Über Semi-Hosting spuckt der jetzt folgendes aus:

R0 = 0
R1 = 2000057c
R2 = 0
R3 = 0
R12 = 0
LR [R14] = 8002375  subroutine call return address
PC [R15] = 800a0a0  program counter
PSR = 41000000
BFAR = e000ed38
CFSR = 400
HFSR = 40000000
DFSR = a
AFSR = 0
SCB_SHCSR = 0

Sieht man jetzt hier warum der Controller strauchelt?
Ich bin mir auch nicht ganz sicher, ob vlt. ein Interrupt (1ms Tick)
das Problem verursacht.

Das Projekt ist mit "CubeMx/HAL" aufgesetzt.

Bin für jeden Tipp dankbar

von Karl (Gast)


Lesenswert?

Besorg dir das Manual zum Cortex M4 (bei gurgel)!
Dann könntest Du z.B. herausfinden, dass Dein "Verbose"-Code nicht die 
Inhalte sondern die Adressen der Register ausspuckt (z.B. bei BFAR).
Und dann kann man auch einfach nachsehen, was die vielen Bits bedeuten.

von Thomas T. (runout)


Lesenswert?

danke, ich habe jetzt das hier:

http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/DUI0553A_cortex_m4_dgug.pdf

"ergurgelt".

Hoffe es gibt keine Core(!)-Unterschiede zwischen M4 und L4 -Series.

Grüße Runout

von Dr. Sommer (Gast)


Lesenswert?

Finde mal heraus, was vor dem Fubktionsaufruf im Stack Pointer steht. 
Debugge das Programm mal in einzelnen Assembler Befehlen (stepi im GDB, 
kA wie das in deiner IDE geht) um zu sehen bei welcher Instruktion es 
hakt. Vielleicht ist's doch gar nicht der Fubktionsaufruf.

von Jim M. (turboj)


Lesenswert?

Ist bei Dir CANbaseAddress wirklich gleich Null? Klingt für mich nicht 
richtig und könnte die Ursache des Hardfaults sein. Würde man im Single 
Step aber IMHO sehen (mit Step into).

von Thomas T. (runout)


Angehängte Dateien:

Lesenswert?

danke für die Hinweise.
Ich habe das Disassembly-Fenster offen (s. Anhang)
und sehe eigentlich genau was passiert.
Ob ich die Funktion mit Variablen oder Konstanten aufrufe,
spielt auch keine Rolle.

"CANbaseAddress" ist nur die Basisadresse eines "CO_t"-Objekts,
hat also nix mit der Teilnehmeradresse (noteId) zu tun.
Dieses ist in meinem Fall (CANopen-Master) = 1.

Aber wie "Karl" schon sagte: Systematisch vorgehen
und die Register auswerten.
Ich berichte, wenn ich den (Noob)Fehler gefunden habe.

Mit'ner neuen Plattform ist es so ähnlich wie mit ner neuen Frau...

**duck und wech**

Runout

von Stefan (Gast)


Lesenswert?

Hast du überprüft, ob für den Hardwareteil auch die Clock und Power 
konfiguriert sind?

von Thomas H. (flaretom)


Lesenswert?

Hi,

Bist Du sicher, dass CANbaseAddress nicht die Adresse des CAN-HW-Blocks 
im STM ist. sieht mir nach einem Blick in CO_Driver.h so aus:
1
typedef struct{
2
    CAN_TypeDef        *CANbaseAddress;         /* STM32F4xx specific */
3
    CO_CANrx_t         *rxArray;
4
    uint16_t            rxSize;
5
    CO_CANtx_t         *txArray;
6
    uint16_t            txSize;
7
    volatile uint8_t    useCANrxFilters;
8
    volatile uint8_t    bufferInhibitFlag;
9
    volatile uint8_t    firstCANtxMessage;
10
    volatile uint16_t   CANtxCount;
11
    uint32_t            errOld;
12
    void               *em;
13
}CO_CANmodule_t;

CAN_TypeDef ist im CMSIS beschrieben:
1
typedef struct
2
{
3
  __IO uint32_t MCR;
4
  __IO uint32_t MSR;
5
  __IO uint32_t TSR;
6
  __IO uint32_t RF0R;
7
  __IO uint32_t RF1R;
8
  __IO uint32_t IER;
9
  __IO uint32_t ESR;
10
  __IO uint32_t BTR;
11
  uint32_t  RESERVED0[88];
12
  CAN_TxMailBox_TypeDef sTxMailBox[3];
13
  CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];
14
  uint32_t  RESERVED1[12];
15
  __IO uint32_t FMR;
16
  __IO uint32_t FM1R;
17
  uint32_t  RESERVED2;
18
  __IO uint32_t FS1R;
19
  uint32_t  RESERVED3;
20
  __IO uint32_t FFA1R;
21
  uint32_t  RESERVED4;
22
  __IO uint32_t FA1R;
23
  uint32_t  RESERVED5[8];
24
  CAN_FilterRegister_TypeDef sFilterRegister[14];
25
} CAN_TypeDef;
BG, Tom

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Du musst die Clocks für die Peripherals "CAN" und "Alternate Peripheral" 
(ggf. auch den GPIO, wo der CAN gemapped ist) einschalten. RCC->APB2ENR 
oder so...

Ist ein Peri nicht geclockt, so geht der Core zwangsläufig in den 
HardFault.

Nicht vergessen: Beim Alternate Peripheral die entsprechenden Pins auf 
CAN konfigurieren.

: Bearbeitet durch User
von Thomas T. (runout)


Lesenswert?

Danke schon mal für die vielen Antworten.

ja, die Funktion "SystemClock_Config()" von CubMx
macht alle Initialisierungen.
Ich kann auch über die HAL_Funktionen auf dem CAN senden und empfangen.

Habe auch mal die "CANbaseAddress" auf "(APB1PERIPH_BASE + 0x6400U)"
gesetzt, ohne Erfolg.
Ziel der ganzen Übung ist ein STM32M4/L4-HAL!!-Treiber für das 
CANopenNode-Projekt.
Der CANopenNode-Stack darf nirgends auf die Register zugreifen das macht 
HAL.

ABER:
CFSR = 00000400 heisst BusFaultStatusRegister = 0x04 = IMPRECISERR
Imprecise data bus error

1 = a data bus error has occurred, but the return address in the stack 
frame is not related to the instruction that caused the error.
When the processor sets this bit to 1, it does not write a fault address 
to the BFAR.
This is an asynchronous fault. Therefore, if it is detected when the 
priority of the current process is higher than the BusFault priority, 
the BusFault becomes pending and becomes active only when the processor 
returns from all higher priority processes. If a precise fault occurs 
before the processor enters the handler for the imprecise BusFault, the 
handler detects both IMPRECISERR set to 1 and one of the precise fault 
status bits set to 1.

Dort muss ich jetzt weitersuchen.

Grüße Runout

von Jim M. (turboj)


Lesenswert?

Thomas T. schrieb:
> Ich habe das Disassembly-Fenster offen (s. Anhang)
> und sehe eigentlich genau was passiert.
> Ob ich die Funktion mit Variablen oder Konstanten aufrufe,
> spielt auch keine Rolle.


Mach mal bei der BL Instruktion ein "step into" anstelle eines "Step 
over". Damit müsstest Du eigentlich rausfinden wo er genau aussteigt. 
Ist aber vermutlich ein Schreibzugriff auf "CANbaseAddress + X", d.h. 
auf die CAN Hardware.

von Galaxy (Gast)


Lesenswert?

Das Problem, bzw die Lösung, also die Antwort auf Deine Frage ist in 
Zeile 42.

von Thomas T. (runout)


Lesenswert?

ja, mittlerweile wird's lustig.

Ich kann die ganze Funktion "leer" machen und trotzdem knallts...
Es gibt aber ein "Auxiliary Control Register".
Dort kann man  mit "DISDEFWBUF" aus dem asynchronen "Imprecise data bus 
error" einen präzisen Error erzwingen welcher leichter zu debuggen sein 
soll ;-)
Soweit die Theorie.

Hätte nicht gedacht, dass ich soviel "Prozessorleergeld" bezahlen muss 
;-)

Wenn jemand das Nucleo-Board mit einem STM32L476RG hat,
kann ich auch das ganze EmBitz-Projektchen mal hier rein stellen.

Gute Nacht
Runout

von stromtuner (Gast)


Lesenswert?

>Wenn jemand das Nucleo-Board mit einem STM32L476RG hat,
>kann ich auch das ganze EmBitz-Projektchen mal hier rein stellen.

Darum bat man DICH bereits. Nicht mitbekommen?

von Thomas T. (runout)


Angehängte Dateien:

Lesenswert?

Nein, nicht mitbekommen.

Hier das Projekt.
Kompiliert/Linked ohne Fehler/Warnungen durch.
Die (wichtigsten) EmBitz-Stettings stehen im root.

Wenn ein williges Opfer noch eine HAL-basierende
EEPROM-Emulation aus der Schublade ziehen, könnte wäre das...
Die aktuellen ST-Appnotes wurden alle unter Verwendung
von CMSIS oder StdPeriphLibs erstellt.

Grüße Runout

von Thomas T. (runout)


Angehängte Dateien:

Lesenswert?

sou, Problem NICHT gelöst, aber Ursache klar...

im ACTLR den WriteBuffer ausgeschaltet:
*((volatile unsigned long *)(0xE000E008)) |= 
SCnSCB_ACTLR_DISDEFWBUF_Msk;

und siehe da:
Das Programm ist "out-of-memory" (SRAM)
die 98k RAM gehen von 20000000 - 20017FFF.
Ein Zugriff auf 20018012 langt ins Datennirvana.

Der STM32L476RG hat nun mal "nur" 1MB-Flash + 98k SRAM.

Habt ihr eine Empfehlung, was ein etwas fetterer STM32F4/L4 wäre?

Grüße Runout

: Bearbeitet durch User
von hp-freund (Gast)


Lesenswert?

Thomas T. schrieb:
> Habt ihr eine Empfehlung, was ein etwas fetterer STM32F4/L4 wäre?

Du benutzt doch schon STM32CubeMX.
Erstelle ein neues Projekt und wähle einen Controller/ ein Board nach 
deinen Wünschen.

von Jürgen H. (nobody)


Lesenswert?

Setzen bei uns den STM32-F417 ein.

Der hat "up to 1MB Flash/192+4KB RAM". Wenn das nicht reicht brauchst du 
eh ne andere Maschine ;-)

von Peter D. (peda)


Lesenswert?

Thomas T. schrieb:
> Der STM32L476RG hat nun mal "nur" 1MB-Flash + 98k SRAM.
>
> Habt ihr eine Empfehlung, was ein etwas fetterer STM32F4/L4 wäre?

98kB ist doch schon riesig.
Guck doch einfach mal ins map-File, wo dieser riesige RAM versickert.

Ist eben kein Windosw-PC wo man für jedes Array erstmal 1MB reserviert.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.