Forum: Mikrocontroller und Digitale Elektronik CH32V003 HardFault IRQ


von Vanye R. (vanye_rijan)


Lesenswert?

Weisst einer was es fuer einen Grund geben kann damit der CH32
einen HardFaul IRQ wirft?
Und falls es mehrere Gruende gibt, kann man die im Handler 
unterscheiden?

Leider ist das Datenblatt an der Stelle sehr duenn.

Vanye

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Vanye R. schrieb:
> Und falls es mehrere Gruende gibt, kann man die im Handler
> unterscheiden?

Ein Core Dump könnte dir einen Hinweis auf den Ort liefern.

Meine Erfahrung/Wissen um den CH32V003 ist nahe Null.
Aber einer der häufigsten Fehler sind Null Pointer.
Oder eben Pointer welche in den Irrsinn zeigen.

von Bauform B. (bauformb)


Lesenswert?

Vanye R. schrieb:
> Leider ist das Datenblatt an der Stelle sehr duenn.

Verwöhnt von der VMS-Doku oder wie? Nicht ganz so dick, aber auch nicht 
sehr duenn:

https://www.wch-ic.com/downloads/QingKeV2_Processor_Manual_PDF.html

Edit: via https://www.mikrocontroller.net/articles/CH32V003

: Bearbeitet durch User
von Vanye R. (vanye_rijan)


Lesenswert?

> Ein Core Dump könnte dir einen Hinweis auf den Ort liefern.

Du meinst der liegt irgendwo im 2k Ram? :-D


> https://www.wch-ic.com/downloads/QingKeV2_Processor_Manual_PDF.html

Okay, ich hatte nur das Referenzmanual und das Datesheet gelesen, dann 
hole ich das hier mal nach....

Vanye

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Vanye R. schrieb:
> Du meinst der liegt irgendwo im 2k Ram? :-D

Ich dachte eher an den Stack....

Dein HardFault Handler sollte den Stackinhalt ausgeben können/sollen.
Und schon solltest du einen Hinweis(Adresse) haben, wo dein HardFault 
geworfen wird.

: Bearbeitet durch User
von Vanye R. (vanye_rijan)


Lesenswert?

> Ich dachte eher an den Stack....

Ja, daran koennte man auch nochmal denken! Aber ich hab erstmal
das Dokument von oben ueberflogen und lass mir mal das mcause
Register ausgeben. Auch schon interessant weil ich das wohl
mit einer LED rausmorsen muss und dabei hoffe das mein Programm
nicht in einen funktionierenden Zustand kommt...

Vanye

von Vanye R. (vanye_rijan)



Lesenswert?

So, ich hab mir mal schnell was zusammengehackt um einen 32bit uint in 
1200B seriell auszugeben. Hier der Source:
1
#define BITTIME  740  /* fuer 1200Baud */
2
#define BIT_DELAY myI=BITTIME; while(myI-- > 0)
3
#define START_DELAY myI=790; while(myI-- > 0)
4
#define BIT_LOW  GPIOA->BSHR = (1<<16) | (1<<(16+2))
5
#define BIT_HIGH GPIOA->BSHR = (1<<2)
6
7
void HardFault_Handler(void)
8
{
9
10
  //Port PA2 als Ausgang für LED initialisieren                                                            
11
  RCC->APB2PCENR |= RCC_APB2Periph_GPIOA;
12
  GPIOA->CFGLR &= ~(0xf<<(4*2));
13
  GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*2);
14
15
 loop:
16
  mymcause = __get_MCAUSE();
17
  //  mymcause = 0x80808086;  /* Gegencheck */                                                             
18
  //mymcause = 0x12345678;    /* Testwert */                                                               
19
  //  mymcause = 0x55555555;  /* Baudratetest */   
20
21
  //Stattbit                                                                                               
22
  BIT_LOW;  START_DELAY;
23
  for (myCNT=0; myCNT<8; myCNT++)
24
    {
25
      if (mymcause & 0x00000001UL) BIT_HIGH; else BIT_LOW;
26
      mymcause = mymcause>>1;
27
      BIT_DELAY;
28
    };
29
  BIT_HIGH;  BIT_DELAY;  BIT_DELAY;  BIT_DELAY; //Stopbit  
30
31
  //Startbit                                                                                               
32
  BIT_LOW;  START_DELAY;
33
  for (myCNT=0; myCNT<8; myCNT++)
34
    {
35
      if (mymcause & 0x00000001UL) BIT_HIGH; else BIT_LOW;
36
      mymcause = mymcause>>1;
37
      BIT_DELAY;
38
    };
39
  BIT_HIGH;  BIT_DELAY;  BIT_DELAY; BIT_DELAY;
40
41
  //Startbit                                                                                               
42
  BIT_LOW;  START_DELAY;
43
  for (myCNT=0; myCNT<8; myCNT++)
44
    {
45
      if (mymcause & 0x00000001UL) BIT_HIGH; else BIT_LOW;
46
      mymcause = mymcause>>1;
47
      BIT_DELAY;
48
    };
49
  BIT_HIGH;  BIT_DELAY;  BIT_DELAY;  BIT_DELAY; //Stopbit                                                  
50
51
  //Startbit                                                                                               
52
  BIT_LOW;
53
  START_DELAY;
54
  for (myCNT=0; myCNT<8; myCNT++)
55
    {
56
      if (mymcause & 0x00000001UL) BIT_HIGH; else BIT_LOW;
57
      mymcause = mymcause>>1;
58
      BIT_DELAY;
59
    };
60
  BIT_HIGH;  BIT_DELAY;  BIT_DELAY;  BIT_DELAY; //Stopbit                                                  
61
62
  myI=100000; while(myI-- > 0); //Bessere Lesbarkeit am Oszi                                               
63
64
  goto loop;
65
}

Die verwendeten Variablen sind alle global deklariert. Ich wollte nicht 
mit dem Stack rummachen soweit es sich vermeiden laesst.

Ihr seht ich sende erst zwei Testwerte, also 0x12345678 und 0x55555555 
die werden dann auch vom Oszi korrekt erkannt. Dann lese ich mcause aus 
und das Register ist

0x80808086

Zur Sicherheit habe ich diesen Wert auch nochmal bewusst ausgegeben und 
bekommen dann dasselbe Ergebnis.

Laut der oben angefuehrten Doku sollte dann mcause[30:0] = 0x808086 
sein. Wenn ich die Doku richtig verstehe dann sollte es so einen Wert 
aber garnicht geben. Da sollte sich doch alles im Bereich 0 bis 255 
abspielen.

Vanye

von F. P. (fail)


Lesenswert?

Wenn Bit 31 wie hier gesetzt ist, dann ist das doch ein Interrupt, keine 
Exception...

Prüfe auch mal den erzeugten Binärcode, vielleicht wird das falsche CSR 
gelesen.

von Vanye R. (vanye_rijan)


Lesenswert?

> Wenn Bit 31 wie hier gesetzt ist, dann ist das doch ein Interrupt, keine
> Exception...

Ja, darueber habe ich mich auch schon gewundert. Aber ich schalte doch 
keinen ein ausser Systick und dafuer gibt es einen Handler.

> Prüfe auch mal den erzeugten Binärcode, vielleicht wird das falsche CSR
> gelesen.

Der Gedanke hat mich auch schon beschlichen. Muss ich noch machen.

Ich dachte gestern aber noch was anderes. Wo ich doch schon mal einen 
Source habe der im HardFault eine Zahl ausgeben kann, dann koennte ich 
doch auch eine globale Variable ausgeben welche beim starten auf 1 
initialisiert wird und die an verschiedenen Stellen erhoeht wird.
So muesste man ja sehen wie weit das Programm kommt. Ergebnis war das 
ein Zufallswert ausgegeben wurde, also schon die Initialisierung im 
Startcode laeuft nicht. Ausserdem habe ich mein Programm mehrmals 
uebersetzt und getestet waehrend ich die Zuweisungen in das Programm 
eingefuegt habe. Es wurde also immer mal etwas laenger. Ergebnis war 
dann das ich manchmal ein lauffaehiges Programm hatte und dann wieder 
nicht.
Ich wuerde also vermuten das es da irgendeinen Align fehler gibt falls 
Teil des Programms auf einer falschen Adresse liegt.

Vanye

von Vanye R. (vanye_rijan)


Lesenswert?

Problem ist gefunden. Loesung am ende von hier:

Beitrag "CH32V003 gcc und Codegenerierung"

Hatte mich da irgendwie gerade im Thread vertan. (Aerger)

Beim finden des Problems war es SEHR hilfreich obigen HardFault Haendler 
zu haben der einem eine Variable ausgeben kann! Werde ich mir fuer die 
Zukunft gleich mal vormerken!

Vanye

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.