CH32V003 HardFault IRQ

#7933005
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

#7933081
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

#7933300
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

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