Keil Hardfault STM32 Jlink

Gast #5513062
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
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
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..
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
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 :)
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
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
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.
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.
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
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.
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
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
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.
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);
Gast
temp schrieb:
> Dafür sieht man die Spatzen vor lauter Kanonenkugeln nicht.

Damit kein Missverständnis aufkommt, das war allgemein auf einige der 
Vorschläge hier bezogen nicht auf den letzten von  Bauform B. Der ist 
zeitlich dazwischen gerutscht.
Beitrag #5514363 wurde von einem Moderator gelöscht.
Gast
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

Eine eigene Frage? Dieser Thread ist über 8 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.