Keil Hardfault STM32 Jlink

Gast #5513062
Lesenswert?

Hallo, ich hab schon auf google viel Zeit verbracht, aber ich verstehe 
es noch nicht ganz.

Mein Code erzeugt einen Hardfault, diesen Fehler konnte ich mit 
"auskommentiern" finden.
1
void uart_get_time(void)
2
{
3
 char str[10]; //zu klein
4
 uint32_t rtc_time=rtc_get_day_time();
5
 uint8_t stu,min,sek;
6
  
7
 rtc_calc_time(&stu,&min,&sek,rtc_time);
8
  
9
 sprintf(str,"System-Uhrzeit %0.2d:%0.2d:%0.2dUhr \n", stu, min, sek);
10
 uart_send_s(str);
11
}

Aber wie findet man das ganze eleganter/schneller? Ich hab einen J-Link 
ohne ETM-Trace und die Keil EDU. Der Controller ist ein 
STM32F103C8/M3-Core.

IBUSERR heißt, dass der M3 den Fehler beim prefetch erkannt hat?
BFARVALID ist nicht gesetzt, also BFAR ignorieren oder?
Angehängte Dateien:
Gast #5513352
Lesenswert?

step one schrieb:

> In dem man immer selber eine Routine für den Hard Fault definiert und
> dort einen Breakpoint platziert. Den Grund für den Hard Fault kann man
> dann auslesen.

Und an SP+24 auch die Faultadresse, was einem zusammen mit dem Mapfile 
verrät, wo der Fehler passiert ist.
Gast #5513762
Lesenswert?

Wenn deine Entwicklungsumgebung kein einfaches 'Backtrace' hat, dass 
auch aus einem Hardfault funktioniert, wechsle zu einer die das kann, 
oder baue dir ein Workaround das auf Kommando ein Backtrace liefert.

Alles andere ist doch sehr suboptimal..
#5513794
Lesenswert?

Peter Trace schrieb:
> void uart_get_time(void)
> {
>  sprintf(str,"System-Uhrzeit %0.2d:%0.2d:%0.2dUhr \n", stu, min, sek);
> }
>
> Aber wie findet man das ganze eleganter/schneller?

Indem man snprintf() (mit der Betonung auf 'n') verwendet. Dass es 
sprintf() immer noch gibt ist eine Gemeinheit.

Manche Stack-Fehler kann man mit der MPU abfangen. Aber auch ohne MPU 
kann man den Stack auf der niedrigsten RAM-Adresse beginnen lassen. Dann 
gibt es einen Bus Error, wenn der Stack zu voll wird. Ich werde nie 
verstehen, was so toll daran ist, wenn der Stack den Heap überschreibt. 
Masochismus?

> Ich hab einen J-Link ohne ETM-Trace und die Keil EDU.

Mit dem GCC und den binutils bekommst du das Kommandozeilen Tools 
addr2line, das zeigt dir die Quelltextzeile passend zur Fault Adresse 
bei SP+24 an. Wenn allerdings der Stack überschrieben wurde... Aber das 
passiert dank snprintf() ja nicht :)
Gast #5513919
Lesenswert?

Hmm, wenn man C++ nutzt kann man einen kleinen Trick machen um den 
sprintf-Fehler zu vermeiden:
1
template <std::size_t N, typename... Args>
2
inline int autosprintf (char (&str) [N], const char* fmt, Args&&... args) __attribute__ ((format (printf, 2, 3)));
3

4
template <std::size_t N, typename... Args>
5
inline int autosprintf (char (&str) [N], const char* fmt, Args&&... args) {
6
  return snprintf (str, N, fmt, std::forward<Args> (args)...);
7
}
8

9
int main () {
10
  char str[10]; //zu klein
11
  autosprintf(str,"System-Uhrzeit %0.2d:%0.2d:%0.2dUhr \n", stu, min, sek);
12
}

Dann wird die Array-Größe automatisch übergeben; man kann sie nicht 
vergessen, und auch nicht falsch angeben. Ungetestet :)
#5513993
Lesenswert?

Dr. Sommer schrieb:
> Hmm, wenn man C++ nutzt kann man einen kleinen Trick machen um den
> sprintf-Fehler zu vermeiden:
> ...
> Dann wird die Array-Größe automatisch übergeben; man kann sie nicht
> vergessen, und auch nicht falsch angeben. Ungetestet :)


Ja, oder man nimmt dann gleich die string-Klasse ala:
1
my_text << "Hallo";

Aber das wäre dann wohl zu einfach für dich oder?

mfg
#5514055
Lesenswert?

Dr. Sommer schrieb:
> Felix F. schrieb:
>> Ja, oder man nimmt dann gleich die string-Klasse ala:
>
> Welche string-Klasse kann das, und kommt die ohne dynamischen Speicher
> aus, so wie s(n)printf?

So weit mir bekannt, gibt es nur 1 std::string Klasse und die kann 
natürlich alles, was auch im Standard definiert ist. Worauf willst du 
hinaus?

Wenn ich keine dyn. Speicherallokierung will, dann verwendet man halt 
Plain-C wie snprintf (wie bereits genannt) und keine auf irgendwelche 
Spezialfälle zusammengeschusterten Mixes die deine Speicherfehler 
verschleiern.

mfg
Gast #5514061
Lesenswert?

Felix F. schrieb:
> So weit mir bekannt, gibt es nur 1 std::string Klasse und die kann
> natürlich alles, was auch im Standard definiert ist. Worauf willst du
> hinaus?

Darauf, dass sie nicht das kann, was du vorgeschlagen hast (Operator 
<<).

Felix F. schrieb:
> Wenn ich keine dyn. Speicherallokierung will, dann verwendet man halt
> Plain-C wie snprintf (wie bereits genannt) und keine auf irgendwelche
> Spezialfälle zusammengeschusterten Mixes die deine Speicherfehler
> verschleiern.
Begründung? Der Speicherfehler wird verhindert, nicht verschleiert.
#5514070
Lesenswert?

Peter Trace schrieb:
> Hallo, ich hab schon auf google viel Zeit verbracht, aber ich verstehe
> es noch nicht ganz.
>
> Mein Code erzeugt einen Hardfault, diesen Fehler konnte ich mit
> "auskommentiern" finden.
>
> Aber wie findet man das ganze eleganter/schneller? Ich hab einen J-Link
> ohne ETM-Trace und die Keil EDU. Der Controller ist ein
> STM32F103C8/M3-Core.
>
> IBUSERR heißt, dass der M3 den Fehler beim prefetch erkannt hat?
> BFARVALID ist nicht gesetzt, also BFAR ignorieren oder?

Du landest ja im hard fault handler mit der Endlosschleife. Dann gehst 
du in callstack and locals und wählst den Händler aus und lässt dir im 
Kontextmenü den caller geben. Dann wird dir die Stelle in code und 
disassembly gezeigt.
#5514106
Lesenswert?

Dr. Sommer schrieb:
> Felix F. schrieb:
>> So weit mir bekannt, gibt es nur 1 std::string Klasse und die kann
>> natürlich alles, was auch im Standard definiert ist. Worauf willst du
>> hinaus?
>
> Darauf, dass sie nicht das kann, was du vorgeschlagen hast (Operator
> <<).
>
> Felix F. schrieb:
>> Wenn ich keine dyn. Speicherallokierung will, dann verwendet man halt
>> Plain-C wie snprintf (wie bereits genannt) und keine auf irgendwelche
>> Spezialfälle zusammengeschusterten Mixes die deine Speicherfehler
>> verschleiern.
> Begründung? Der Speicherfehler wird verhindert, nicht verschleiert.

Oh, stimmt. Habe das mit stringstream verwechselt. Muss natürlich '=' 
lauten. Ändert aber jetzt vom Prinzip der automatischen Größenanpassung 
nichts.

Wenn ich in str[10] mehr als 10 Zeichen schreiben kann, wird der Fehler 
verschleiert. Wenn ich dahinter einfach reserved[10] schreibe, ist der 
Fehler auch behoben, weil ich jetzt in reserved schreibe. Schöner wirds 
dadurch aber auch nicht.

mfg
Gast #5514115
Lesenswert?

Felix F. schrieb:
> Wenn ich in str[10] mehr als 10 Zeichen schreiben kann, wird der Fehler
> verschleiert.

Kannst du nicht. Die autosprintf-Funktion übergibt automatisch "10" an 
snprintf, und der String wird abgeschnitten, es wird nichts in 
"reserved" geschrieben, es tritt kein Buffer Overflow ein.
#5514126
Lesenswert?

Dr. Sommer schrieb:
> Felix F. schrieb:
>> Wenn ich in str[10] mehr als 10 Zeichen schreiben kann, wird der Fehler
>> verschleiert.
>
> Kannst du nicht. Die autosprintf-Funktion übergibt automatisch "10" an
> snprintf, und der String wird abgeschnitten, es wird nichts in
> "reserved" geschrieben, es tritt kein Buffer Overflow ein.

Achso, dann habe ich da was falsch verstanden.

Dann würde ich aber gleich zum korrekten Ansatz raten:
1
char str[MAX];
2
snprintf(str, MAX, "bla bla");

mfg
Gast #5514132
Lesenswert?

Felix F. schrieb:
> Dann würde ich aber gleich zum korrekten Ansatz raten:

Wenn man jetzt aber die Array-Größe auf "MAX-3" ändert muss man dran 
denken, das bei snprintf auch zu tun. Mit dem template entfällt das, 
weil automatisch immer die tatsächliche Array-Größe genutzt wird.
Gast #5514291
Lesenswert?

Peter Trace schrieb:
> Hallo, ich hab schon auf google viel Zeit verbracht, aber ich verstehe
> es noch nicht ganz.

Tja. Das sind die Leiden der jungen Ignoranten, die partout sich auf 
einem µC genau so benehmen wollen wie auf dem PC, wo sie ein 
fürsorgliches Betriebssystem und schier unendlich viel RAM haben.

Aber der TO hat wohl sein Problem aus den Augen verloren, also was 
soll's.

W.S.
#5514317
Lesenswert?

Dr. Sommer schrieb:
> Felix F. schrieb:
>> Dann würde ich aber gleich zum korrekten Ansatz raten:
>
> Wenn man jetzt aber die Array-Größe auf "MAX-3" ändert muss man dran
> denken, das bei snprintf auch zu tun. Mit dem template entfällt das,
> weil automatisch immer die tatsächliche Array-Größe genutzt wird.

das kann man in C auch haben, normalerweise schreibt man ja
1
char str[MAX];
2

3
   snprintf (str, sizeof str, "%s\n", blafasel);
Beitrag #5514363 wurde von einem Moderator gelöscht.
Gast #5515622
Lesenswert?

Vielen Dank für die zahlreichen Antworten.
Mir geht es bei dieser Frage nicht um die Vermeidung von Fehlern bei 
"printf", sondern nur um die Fehlerlokalisierung.
Witziger weise wurde under "Stack-Caller" keine Funktion angezeigt, das 
hat mich zum grübeln gebracht.

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