Forum: Mikrocontroller und Digitale Elektronik STM8S - Timer4 Overflow Interrupt führt zu unhandled exception


von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

Ich versuche gerade, den Overflow Interrupt des Timer4 vom STM8S zum 
laufen zu kriegen. Nach dem der Timer voll ist, läuft das Programm in 
eine "_iar_unhandled_exception" (siehe Anhang). Meine Timer 
Initialisierung:
1
void initTimer(){
2
  CLK_PCKENR1 |= (1<<4); //Enable Clock for Timer 4
3
  TIM4_PSCR = (0x07);    //Prescaler, Divide Clock by 7
4
  TIM4_IER = 1;          //Enable Update Interrupt
5
  TIM4_CR1 |= 1;         //Enable Timer
6
  asm("rim");           //Enable Interrupts        
7
}

Meine Interrupt Funktion:
1
#pragma vector = 23
2
__interrupt void TIM4_UPD_OVF_IRQHandler(void){
3
  displayInit();
4
  show();
5
  TIM4_SR &=~(1<<0);    //Clear Update interrupt
6
}

Woran liegt das?

von STM8 (Gast)


Lesenswert?

Max M. schrieb:
> #pragma vector = 23

Meine Meinung: Das ist falsch, der Interrupt hat die Nummer 11.

von STM8 (Gast)


Lesenswert?

Oh sorry, Timer4 hab ich übersehen.

von Stefan F. (Gast)


Lesenswert?

Die Initialisierung des Displays in der Interrupt Routine lässt mich 
ahnen, dass das Programm strukturelle Mängel hat. Falls du keinen 
wirklich wichtigen Grund dafür hast, schlage ich Dir vor, den gesamten 
Quelltext zu zeigen, dann können wir Dir helfen, ihn zu verbessern.

von Max M. (maxmicr)


Lesenswert?

Wenn ich die Zeile:
1
asm("rim");

auskommentiere lande ich nach dem Overflow nicht in der Exception, 
allerdings auch nicht in der Interrupt Funktion. Der Timerwert erhöht 
sich nun nur nach jedem 21. Step im Debug-Modus (aber auch erst, nach 
dem er einmal mit +6 / Step durchgelaufen ist). Das UIF-Bit wird nach 
dem Overflow gesetzt.

: Bearbeitet durch User
von STM8 (Gast)


Lesenswert?

Max M. schrieb:
> Wenn ich die Zeile:asm("rim");
>
> auskommentiere

Dann gibt es auch keine Interrupts ...

von STM8 (Gast)


Lesenswert?

Stefan U. schrieb:
> schlage ich Dir vor, den gesamten
> Quelltext zu zeigen, dann können wir Dir helfen, ihn zu verbessern

von Max M. (maxmicr)


Lesenswert?

Stefan U. schrieb:
> Falls du keinen
> wirklich wichtigen Grund dafür hast, schlage ich Dir vor, den gesamten
> Quelltext zu zeigen, dann können wir Dir helfen, ihn zu verbessern.

Ich hab die Funktionen von oben nochmal umbenannt, nicht wundern:
1
/*
2
* main.c - Datei
3
*/
4
#include "MAX7219SPI.c"
5
#include "stdbool.h"
6
#define H 0x0C
7
#define E 0x0B
8
#define L 0x0D
9
#define S 0x0A
10
11
bool didInit = false;
12
13
uint8_t buffer[] = {
14
  H,E,L,L,0,S,S,S,S,1,3,3,7,S,S,S,S
15
};
16
17
void applyBuffer(){
18
  uint8_t counter;
19
  for(counter = 0; counter < 8; counter++){
20
    SPISendData(counter+1,buffer[8-counter]);
21
  }
22
}
23
24
void shuffleRight(){
25
  uint8_t counter, temp;
26
  for(counter = 0; counter < sizeof(buffer); counter++){
27
    if(counter != 0){
28
      uint8_t temp2 = buffer[counter];
29
      buffer[counter] = temp;
30
      temp = temp2;
31
    } else {
32
      temp = buffer[counter];
33
      buffer[counter] = buffer[sizeof(buffer)-1];
34
    }
35
  }
36
}
37
38
#pragma vector = 23
39
__interrupt void TIM4_UPD_OVF_IRQHandler(void){
40
  if(!didInit){
41
    initMAX7219();
42
    didInit = true;
43
  }
44
  applyBuffer();
45
  shuffleRight();
46
  TIM4_SR &=~(1<<0);    //Clear Interrupt
47
}
48
void initGPIOs(){
49
  PD_DDR = (1<<MOSI) | (1<<SCK) | (1<<CS);
50
  PD_CR1 = (1<<MOSI) | (1<<SCK) | (1<<CS);
51
  PD_ODR |= (1<<MOSI) | (1<<CS);
52
  PD_ODR &=~(1<<SCK);   //set SCK to low otherwise first clock isn't generated
53
}
54
55
void initTimer(){
56
  CLK_PCKENR1 |= (1<<4); //Enable Clock for Timer 4
57
  TIM4_PSCR = (0x07);    //Prescaler, Divide Clock by 7
58
  TIM4_IER = 1;          //Enable Update Interrupt
59
  TIM4_CR1 |= 1;         //Enable Timer
60
  asm("rim");           //Enable Interrupts        
61
}
62
63
int main(){
64
  initGPIOs();
65
  initTimer();
66
  while(1){
67
  }
68
}
69
/*
70
* MAX7219SPI.c Datei
71
*/
72
#include "iostm8s103f3.h"
73
#include "stdint.h"
74
75
#define MOSI    6
76
#define SCK     5
77
#define CS      4
78
79
void delay(uint16_t value){
80
  while(value != 0)
81
    value--;
82
}
83
84
void SPISendByte(uint8_t data){
85
  uint8_t mask;
86
  for(mask = 0x80; mask; mask >>=1){
87
    if(data & mask)
88
      PD_ODR |= (1<<MOSI);
89
    else
90
      PD_ODR &=~(1<<MOSI);
91
    delay(4);
92
    PD_ODR |= (1<<SCK);
93
    delay(12);
94
    PD_ODR &=~(1<<SCK);
95
    delay(2);
96
    PD_ODR &=~(1<<MOSI);
97
    delay(2);    
98
  }
99
}
100
101
void SPISendData(uint8_t regAddr, uint8_t data){
102
  delay(4);
103
  PD_ODR &=~(1<<CS);
104
  SPISendByte(regAddr);
105
  SPISendByte(data);
106
  PD_ODR |= (1<<CS);
107
  delay(4);
108
}
109
110
void initMAX7219(){
111
  SPISendData(0x0B,0x0F);               //Scan Limit
112
  delay(2);
113
  SPISendData(0x0A,0x0F);                //Max Intensity
114
  delay(2);
115
  SPISendData(0x0C,0x01);               //Normal Operation Mode
116
  delay(2);
117
  SPISendData(0x09,0xFF);               //Decode
118
  delay(2);
119
  SPISendData(0x0F,0x00);               //Normal Operation Mode
120
}

: Bearbeitet durch User
von STM8 (Gast)


Lesenswert?

Das fehlerträchtige Konstrukt würde ich nochmals überdenken:

#include "MAX7219SPI.c"

Ich habe mal Deine Version übernommen und im IAR kompiliert. Laut 
map-file landet die Interrupt-Routine an der richtigen Stelle. Im 
Simulator passiert nichts. Damit kenne ich mich allerdings auch nicht 
gut aus. Was macht Dein Programm auf der realen Hardware?

von Max M. (maxmicr)


Lesenswert?

Okay, ich habs gelöst. Etwas seltsam...
Die Interrupt-Funktion wurde als solche erkannt allerdings hat der 
Vector nicht gestimmt 
(http://www.st.com/content/ccc/resource/technical/document/datasheet/ce/13/13/03/a9/a4/42/8f/CD00226640.pdf/files/CD00226640.pdf/jcr:content/translations/en.CD00226640.pdf 
[S.43]). Im Datenblatt steht als Nummer "23", in der Headerdatei hat der 
define "TIM4_OVR_UIF_vector" den Wert "25", wahrscheinlich, weil die 2 
obersten Interrupts "Reset" und "TRAP" nicht mitgezählt wurden. So 
funktioniert es nun:
1
#pragma vector = TIM4_OVR_UIF_vector
2
__interrupt void TIM4_UPD_OVF_IRQHandler(void){
3
  if(!didInit){
4
    initMAX7219();
5
    didInit = true;
6
  }
7
  applyBuffer();
8
  shuffleRight();
9
  TIM4_SR &=~(1<<0);    //Clear Update interrupt flag
10
}

Allerdings hätte ich dann erwartet, dass an der Adresse des 
Interrupt-Vektors mit der Nr. 23 die Sprungadresse meiner Funktion 
steht, aber die ganze Interrupt-Tabelle zeigte im Disassembly auf die 
unhandled-exception. Das
1
asm("rim");
 ist auch schwer bis unmöglich im Datenblatt zu finden. Naja, STM 
typisch.

: Bearbeitet durch User
von STM8 (Gast)


Lesenswert?

Max M. schrieb:
> asm("rim"); ist auch schwer bis unmöglich im Datenblatt zu finden. Naja,
> STM

schau Dir mal intrinsics.h an ...

von Stefan F. (Gast)


Lesenswert?

Falls du später mal die Variable didInit  außerhalb der ISR verwenden 
wirst, musst du sie als volatile deklarieren.

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.