Forum: Compiler & IDEs memset führt zum crash


von Mehmet K. (mkmk)


Lesenswert?

Servus allerseits

Seit gestern fische ich im Trüben und komme nicht vom Fleck.
D.h., das "wo" konnte ich ermitteln, aber ich weiss nicht das "wieso" 
und befürchte, dass da prizipiell was in der Schieflage ist.

- STM32F407
- Em::Blocks mit arm-none-eabi v4.7.3
- ChibiOS v2.6.5
- St-Link V2 (aber dasselbe mit J-Link)
- Prg-Size z.Zt. 120kB

Ich arbeite z.Zt. an einem Program für ein STM32F407-Board und setze zum 
ersten mal ChibiOS ein.
Dabei waehle ich SRAM als Target, wobei ich so alle paar Tage das Ganze 
mit Flash-Debug und Flash-Release teste.

Gestern habe ich das Programm um eine zusaetliche Funktion erweitert.
SRAM-Debug : keine Probleme sowohl in Single-Step als auch in Run-Mode
Flash-Debug: in Single-Step keine Probleme, aber in Run-Mode haengt sich 
das Program auf, sobald ich diese Funktion aufrufe
Release    : das Program haengt sich auf

Nach unzaehligen Try-and-Error Versuchen stellte ich fest, dass die 
Lib-Funktion memset die Ursache ist. Und tatsaechlich: wenn ich diese 
ausklammere, dann funktioniert das Ganze so wie gehabt. Kann ja wohl 
nicht sein, wo doch memset in anderen Funktionen ohne Probleme zum 
Einsatz kommt! Also habe ich memset zu Testzwecken gleich als 1. 
Anweisung im main() gesetzt. Also noch bevor ChibiOs und die Hardware 
initialisiert werden.
Und wieder: im Sgl-Step keine Probleme, aber sobald ich Run drücke, 
haengt sich das Program auf.
Neugierig geworden habe ich mit menset etwas herumgespielt. Heraus kam:
1
//========================
2
// main
3
//========================
4
int main(void)
5
{
6
    static uint8_t test_buf[64];
7
8
// memset(test_buf, 0x00,  1); // okay
9
// memset(test_buf, 0x00,  2); // okay
10
// memset(test_buf, 0x00,  3); // okay
11
// memset(test_buf, 0x00,  4); // okay
12
// memset(test_buf, 0x00,  5); // okay
13
// memset(test_buf, 0x00, 16); // okay
14
// memset(test_buf, 0x00, 24); // okay
15
    memset(test_buf, 0x00, 25); // okay
16
// memset(test_buf, 0x00, 26); // Crash
17
// memset(test_buf, 0x00, 27); // Crash
18
// memset(test_buf, 0x00, 28); // Crash
19
// memset(test_buf, 0x00, 29); // Crash
20
// memset(test_buf, 0x00, 31); // Crash
21
// memset(test_buf, 0x00, 32); // Crash
22
// memset(test_buf, 0x00, 62); // Crash
23
// memset(test_buf, 0x00, 63); // Crash
24
// memset(test_buf, 0x00, 64); // Crash
25
26
  :
27
  hier kommen die verschiedenen Inits
28
  :
29
}

Haengt sich auf heisst: hin und wieder lande ich im 
"_unhandled_exception" interrupt. Aber meist ist halt nur Funkstille. 
Wenn ich Glück habe, kann ich von der IDE aus reseten, sonst halt 
Debug-Session beenden und neu starten.

Help! \o/

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Hm...

Ich habe zwar keine Lösung, würde aber variieren, um den Fehler 
einzugrenzen:
1. Das Feld mal nicht static machen und in der Größe ändern
2. eine eigene memset()-Version (geht ja schnell) probieren, wenn es 
damit klappt hat das memset() einen Schuß weg?

von Mehmet K. (mkmk)


Lesenswert?

Diese Punkte hatte ich schon alle durchgekaut, aber vergass, sie zu 
erwaehnen. Sorry

- static, nicht static, global: keine Aenderung des Verhaltens.
- Beim Einsatz eines eigenen memset kommt es zu keinem Haenger
1
 for (unsigned i = 0; i < 64; i++)
2
       test_buf[i] = 0x00;   // Okay

Mit der Grösse hatte ich noch nicht herumexperimentiert. Hat aber keine 
Wirkung zur Folge gehabt.
test_buf auf 128 vergrössert und versucht, mit memset(test_buf, 0x00, 
64) zu initialisieren: Haenger!

Also dass memset einen Fehler haben sollte ... na, ich weiss nicht :)

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Kompiliere das Programm mal als Release und starte das im Debugger. Die 
Kombination ist oben nicht erwähnt?

Falls das nichts bringt (kein Crash), dann:

Mehmet Kendi schrieb:
> Haengt sich auf heisst: hin und wieder lande ich im
> "_unhandled_exception" interrupt.
So einen Interrupt gibt es nicht. Es gibt nur eine Funktion in deinem 
Code diesen Namens, die als Handler für alle Interrupts eingetragen ist, 
für die sonst keiner im Code angegeben ist. Gebe in dieser Funktion mal 
über UART oder so den Stack, die Register IPSR, CFSR, MMFSR, BFSR, UFSR 
aus.

Wäre es ein simpler bug in memset() müsste der auch mit Debugger 
auftreten.

von Mehmet K. (mkmk)


Lesenswert?

Release hatte ich immer separat geflasht.
Hab's nun aber mit dem Debugger gemacht, aber auch hier hat es sich 
aufgehaengt.

Werde versuchen an die Registerinhalte heranzukommen.

von Dr. Sommer (Gast)


Lesenswert?

Mehmet Kendi schrieb:
> Hab's nun aber mit dem Debugger gemacht, aber auch hier hat es sich
> aufgehaengt.
Das ist doch super, da kannst du mit dem Debugger ja genau gucken was 
verkehrt ist.

von Ralf G. (ralg)


Lesenswert?

Ein normales 'memset()' löst doch keinen Interrupt aus. :-/ Nichtmal 
einen falschen...
Ich würde wo anders suchen:
- Stacküberlauf
- anderer Speicherzugriffsfehler

von Mehmet K. (mkmk)


Lesenswert?

Dr. Sommer schrieb:
> Das ist doch super
Irgendwas scheine ich verpasst zu haben: im Release-Mode habe ich doch 
gar keinen Zugriff auf den  Debugger.
Ich habe nun im Flash-Debug Mode die gewünschten Infos herausgefischt:

1
static volatile uint32_t x_cfsr ;
2
static volatile uint32_t x_ipsr;
3
4
//====================================
5
// __get_IPSR   siehe core_cmFunc.h in CMSIS
6
//====================================
7
static __inline uint32_t __get_IPSR(void)
8
{
9
  static volatile uint32_t __regIPSR     __asm("ipsr");
10
  return(__regIPSR);
11
}
12
13
//====================================
14
// _unhandled_exception
15
//====================================
16
void _unhandled_exception(void)
17
{
18
    x_cfsr = (*((volatile uint32_t *)(0xE000ED28))) ;
19
    x_ipsr = __get_IPSR();
20
21
}

x_ipsr: 0x00

0xE000ED28  0x00010000
MMFSR:   0x00
BFSR :   0x00
UFSR : 0x0001 -> UNDEFINSTR the processor has attempted to execute an 
undefined instruction

: Bearbeitet durch User
von Mehmet K. (mkmk)


Lesenswert?

Ralf G. schrieb:
> - Stacküberlauf

Der Meinung war ich anfaenglich auch. Und habe alle möglichen Werte 
erhöht und erhöht. Denn dies ja bei RTOS der Lieblingsfehler. Hat nichts 
gebracht.
Aber ohne memset funktioniert ein ziemlich komplexes Program ohne 
irgendwelche Zicken.
Werde diesbezüglich nochmals über die Bücher gehen.

von Dr. Sommer (Gast)


Lesenswert?

Mehmet Kendi schrieb:
> Irgendwas scheine ich verpasst zu haben: im Release-Mode habe ich doch
> gar keinen Zugriff auf den  Debugger.
Wieso das denn nicht? Nur weil der Compiler mit Optimierungen 
kompiliert heißt das doch nicht dass der Debugger nicht funktioniert?!

Mehmet Kendi schrieb:
> UFSR : 0x0001 -> UNDEFINSTR the processor has attempted to execute an
> undefined instruction
Sehr verdächtig. Klingt als wäre die memset() Funktion verkehrt 
kompiliert worden, sodass da ungeeignete Instruktionen drin sind. Schaue 
mal ins Disassembly des Programmimages und in die Disassembly der 
Funktion wenn sie im Speicher des Prozessors ist. Verwende den Stack um 
herauszufinden, an welcher Stelle genau die Exception aufgerufen wird.

Versuche mal einen anderen Compiler, zB den neuesten gcc-arm-embedded ( 
https://launchpad.net/gcc-arm-embedded ), bei dem ist die memset 
Funktion vielleicht korrekt kompiliert.

von Klaus W. (mfgkw)


Lesenswert?

oder falsche Compileroptionen?
thumb.../neon/...

von Mehmet K. (mkmk)


Lesenswert?

Dr. Sommer schrieb:
> Wieso das denn nicht? Nur weil der Compiler mit Optimierungen
> kompiliert heißt das doch nicht dass der Debugger nicht funktioniert?!

Genau dafür habe ich mein Target Flash-Debug :)

Dass es am memset liegen könnte, ziehe also echt nicht in Betracht. 
Waere es dem so, müsste dieser Fehler nicht auch im Target SRAM 
auftreten?
Und im SRAM laeuft die Kiste absolut stabil.
Werde aber trozdem mal mein Glück mit dem neueren gcc-arm-embedded 
versuchen.

Danke für all die Antworten. Hat zwar nichts gebracht, aber man fühlt 
sich nicht ganz allein gelassen auf weiter Flur :)

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Mehmet Kendi schrieb:
> Danke für all die Antworten. Hat zwar nichts gebracht, aber man fühlt
> sich nicht ganz allein gelassen auf weiter Flur :)

Wir sind Alle bei Dir :-)

Probiere auch mal, die Flash wait-states auf maximalen Wert zu setzen.
Die Pferde vor der Apotheke können ein Lied davon singen!

von Dr. Sommer (Gast)


Lesenswert?

Mehmet Kendi schrieb:
> Genau dafür habe ich mein Target Flash-Debug :)
Ja hoffentlich ist dann auch mit Release Einstellungen kompiliert, also 
mit Optimierungen. Bringt ja nichts wenn du nur ohne Optimierungen 
debuggst, aber mit Optimierungen der Fehler auftritt.

Mehmet Kendi schrieb:
> Dass es am memset liegen könnte, ziehe also echt nicht in Betracht.
Nicht unbedingt an memset() selbst. Möglicherweise aber daran, wie dein 
memset (libc) kompiliert wurde!

m.n. schrieb:
> Probiere auch mal, die Flash wait-states auf maximalen Wert zu setzen.
> Die Pferde vor der Apotheke können ein Lied davon singen!
DAS ist eine sehr gute Idee...

von Ingo (Gast)


Lesenswert?

Dr. Sommer schrieb:
>> Probiere auch mal, die Flash wait-states auf maximalen Wert zu setzen.
>> Die Pferde vor der Apotheke können ein Lied davon singen!
> DAS ist eine sehr gute Idee...
Wie ginge das? Würde mich auch interessieren!

von Mehmet K. (mkmk)


Lesenswert?

m.n.!!! Ich weiss zwar nicht wie schwer Du bist, und besonders kraeftig 
bin ich auch nicht; aber zumindest auf virtueller Ebene hast Du es 
verdient auf die Schulter genommen und 'ne Ehrenrunde gedreht zu 
bekommen.
Herzlichen Dank!
War auf auf 5 Waitstates. Habe es auf 6 erhöht ... und alles laeuft wie 
es soll.
So im nachhinein, eigentlich ganz logisch. Im SRAM, mit schnellem 
Zugriff, laeuft es ohne Probleme. Und im Flash, wo man natürlich ganz 
schnell vergisst, dass es sowas wie Waitstates gibt, knallt man an die 
Mauer und weiss nicht warum.
Okay, das reicht. Runder von meinen Schultern! :)

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Mehmet Kendi schrieb:
> So im nachhinein, eigentlich ganz logisch.

Es ist leider überhaupt nicht logisch, dass der STM32 seine 
Spezifikationen nicht einhält! Für mich war es eine sehr mühevolle 
Erfahrung, unergründliche Fehler zu beseitigen, die spontan an 
unmöglichen Stellen auftraten.

Daher freut es mich sehr, dass ich Dir helfen konnte.

von Mehmet K. (mkmk)


Lesenswert?

Zur Ehrenrettung von ST sollte ich vielleicht erwaehnen, dass ich mit 
einer A-Serie MCU arbeite und nicht Z-Serie.
Ist mir aber auch erst jetzt aufgefallen.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

m.n. schrieb:
> Es ist leider überhaupt nicht logisch, dass der STM32 seine
> Spezifikationen nicht einhält!
Welche genau ist denn hier verletzt? zB bei 2.3V und 154MHz werden 7 
Waitstates benötigt laut Spezifikation. Und da wir nicht wissen welche 
Frequenz & Spannung der OP verwendet...

von Mehmet K. (mkmk)


Lesenswert?

Dr. Sommer schrieb:
> Und da wir nicht wissen welche Frequenz & Spannung der OP verwendet...
168Mhz @ 3.3V

Aber wie gesagt: mein MCU ist einer von der A-Serie und das Problem war 
nebst den Waitstaites, dass bei dieser Serie der Data- und Instruction 
Cache nicht aktiviert werden darf.

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.