STM32F4/L4 Hardfault bei Funktionsaufruf - verzweifelt..

OP #4619970
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
Gast #4619981
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.
Gast #4620051
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.
OP #4620163
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
Angehängte Dateien:
#4620264
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
OP #4620417
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
#4620485
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.
OP #4621090
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
OP #4621262
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
Angehängte Dateien:
OP #4623965
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
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