Forum: Mikrocontroller und Digitale Elektronik STM8 Interrupt Handling


von BS (Gast)


Lesenswert?

Hallo zusammen,
Ich möchte gerne auf meinem STM8 den Timer 1 im PWM-Betrieb und den 
Timer 4 im "normalen" Betrieb laufen lassen.
Timer 1 läuft ohne initialisieren von Timer 4 problemlos im PWM-Betrieb. 
Möchte ich aber nun auf Timer 4 einen InterruptHandler programmieren, so 
funktioniert weder Timer1 (PIN geht High und nicht wieder low) noch mein 
InterruptHandler auf Timer 4. Im Debug lande ich entweder direkt nach 
dem interruptEnable im NonHandledInterruptHandler() oder wenn ich diesen 
auskommentiere komme ich einmal in die ISR von Timer4, jedoch "hängt" 
sich das Programm dann am Ende der ISR auf.
Ich habe gefühlt schon alles probiert, mit dem folgenden Code komme ich 
wenigstens in die ISR, aber das kann ja auch nicht die Lösung sein, da 
die Pins auch nicht gesetzt werden...
it.c
1
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
2
 {
3
   GPIO_WriteReverse(GPIOD, GPIO_PIN_3);
4
   GPIO_WriteReverse(GPIOD, GPIO_PIN_4);
5
   TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
interrupt_vector.c
1
#include "stm8s_it.h"
2
3
typedef void @far (*interrupt_handler_t)(void);
4
5
struct interrupt_vector {
6
  unsigned char interrupt_instruction;
7
  interrupt_handler_t interrupt_handler;
8
};
9
10
//@far @interrupt void NonHandledInterrupt (void)
11
//{
12
  /* in order to detect unexpected events during development, 
13
     it is recommended to set a breakpoint on the following instruction
14
  */
15
//  return;
16
//}
17
18
extern void _stext();     /* startup routine */
19
20
struct interrupt_vector const _vectab[] = {
21
  //{0x82, (interrupt_handler_t)_stext}, /* reset */
22
  //{0x82, NonHandledInterrupt}, /* trap  */
23
  //{0x82, NonHandledInterrupt}, /* irq0  */
24
  //{0x82, NonHandledInterrupt}, /* irq1  */
25
  //{0x82, NonHandledInterrupt}, /* irq2  */
26
  //{0x82, NonHandledInterrupt}, /* irq3  */
27
  //{0x82, NonHandledInterrupt}, /* irq4  */
28
  //{0x82, NonHandledInterrupt}, /* irq5  */
29
  //{0x82, NonHandledInterrupt}, /* irq6  */
30
  //{0x82, NonHandledInterrupt}, /* irq7  */
31
  //{0x82, NonHandledInterrupt}, /* irq8  */
32
  //{0x82, NonHandledInterrupt}, /* irq9  */
33
  //{0x82, NonHandledInterrupt}, /* irq10 */
34
  //{0x82, NonHandledInterrupt}, /* irq11 */
35
  //{0x82, NonHandledInterrupt}, /* irq12 */
36
  //{0x82, NonHandledInterrupt}, /* irq13 */
37
  //{0x82, NonHandledInterrupt}, /* irq14 */
38
  //{0x82, NonHandledInterrupt}, /* irq15 */
39
  //{0x82, NonHandledInterrupt}, /* irq16 */
40
  //{0x82, NonHandledInterrupt}, /* irq17 */
41
  //{0x82, NonHandledInterrupt}, /* irq18 */
42
  //{0x82, NonHandledInterrupt}, /* irq19 */
43
  //{0x82, NonHandledInterrupt}, /* irq20 */
44
  //{0x82, NonHandledInterrupt}, /* irq21 */
45
  //{0x82, NonHandledInterrupt}, /* irq22 */
46
  {0x82, (interrupt_handler_t)TIM4_UPD_OVF_IRQHandler}, /* irq23 */
47
  //{0x82, NonHandledInterrupt}, /* irq24 */
48
  //{0x82, NonHandledInterrupt}, /* irq25 */
49
  //{0x82, NonHandledInterrupt}, /* irq26 */
50
  //{0x82, NonHandledInterrupt}, /* irq27 */
51
  //{0x82, NonHandledInterrupt}, /* irq28 */
52
  //{0x82, NonHandledInterrupt}, /* irq29 */
53
};
Wie oben schon erwähnt lande ich beim einkommentieren des 
NonHandledInterrupts direkt nach dem IER in dessen ISR und komme da auch 
nicht mehr raus.
Ich bin schon wirklich am verzweifeln, da weder das befolgen dieser 
Anleitung 
http://embedded-lab.com/blog/starting-stm8-microcontrollers/10/, noch 
kopieren aus dem StdPeriphLib Example (wobei hier keine 
Interrupt_vector.c existiert) zu einer Lösung führt.

von Auweia (Gast)


Lesenswert?

Komischer Compiler. Naja egal.

Musst du halt selber lesen:
http://blog.mark-stevens.co.uk/?cat=17

Das Interruptsystem des STM8 ist im hoechsten Masze einfach
zu benutzen.

von Auweia (Gast)


Lesenswert?

Deine _vectab[] ist fuers Popoechen.

Die // vor den Eintraegen verhindern mit Sicherheit, dass die
valide ist.

Das "Befolgen von Anleitungen" noch das "Kopieren von Beispielen"
ersetzt das Verstehen wie der Interruptmechanismus funktioniert.

Und ein Durchpermutieren durch Weglassen wird da auch nicht
zum Ziel fuehren.

von BS (Gast)


Lesenswert?

Ich denke ich verstehe ganz gut, wie ein Interrupt funktioniert ;), 
jedoch habe ich einfach nicht verstanden, wieso ich bei jedem IER direkt 
in der NonHandledInterrupt-Funktion lande und habe dann mit Fehlersuche 
halt mal alles probiert.
Letzendlich lags an einem GPIO, den ich als Floating-Input mit Interrupt 
definiert habe, der mir ständig einen Interrupt ausgelöst hat (was mir 
zwar nicht ganz eingeht, da nirgends am Board Signale anliegen).
Die Blogs habe ich auch schon gelesen, ansonsten hätte ich mich ja gar 
nicht hier ans Forum gewandt, aber trotzdem danke für die Hilfe.

von Axel S. (a-za-z0-9)


Lesenswert?

BS schrieb:
> Letzendlich lags an einem GPIO, den ich als Floating-Input mit
> Interrupt definiert habe

Ich habe den Fehler mal unterstrichen. Eingänge darf man nie floaten 
lassen. Entweder legt man den Pegel mit der externen Beschaltung fest 
oder man aktiviert einen internen Pullup/Pulldown oder man konfiguriert 
sie als Ausgang.

Der zweite Fehler besteht darin, einen Interrupt zu aktivieren, für den 
es keine ISR gibt.

Oh, und wenn man schon eine extra ISR für "non handled interrupt" hat, 
dann sollte die auch etwas sinnvolles tun. Zwar kann sie eigentlich 
nicht aufgerufen werden, wenn man sich an die Regel von eben hält. Aber 
manche Leute brauchen halt Gürtel und Hosenträger...

von M. K. (Gast)


Lesenswert?

BS schrieb:
> Floating-Input mit Interrupt
> definiert habe, der mir ständig einen Interrupt ausgelöst hat (was mir
> zwar nicht ganz eingeht, da nirgends am Board Signale anliegen

Ist Dir nicht klar?
Ein offener, unbeschalteter, floatender Cmos Input, der unmotiviert 
Zustände annimmt. Ach wie seltsam :-)))
Vielleicht im 50 bzw. 100 Hz Takt?
Oder im Khz Bereich, wenn Du Leuchtstoffröhren in der Nähe betreibst?

Wenn Du etwas als IRQ Quelle initialisierst, solltest Du im gleichen Zug 
auch eine IRQ Behandlung dazu schreiben.
Du kannst auch Breakpoints auf alle nicht genutzten IRQ Einspungadressen 
setzen, dann siehst Du sehr schnell wenn da etwas triggert das Du nicht 
erwartet hast.
Nette Fehler sind auch IRQ Flags die man selber rücksetzen muss, wenn 
man die IRQ je wieder verlassen will.

Die StdPeriphLib ist übrigens teilweise echt Mist.
Von Hinten durch die Brust ins Auge geschrieben und unterstützt auch 
nicht alles was die HW kann.
Als 'how to' wenn das DB schwammig formuliert ist, aber ganz brauchbar.

Wenn Dir der Prg-Speicher ausgeht oder der Du performance Probleme hast, 
ersetze mal die Wall of Text der StdPeriphLib Aufrufe durch direkte 
Manipulation der Handvoll Register die Du eigentlich setzen willst.
Wirkt Wunder!

von BS (Gast)


Lesenswert?

Axel S. schrieb:
> Entweder legt man den Pegel mit der externen Beschaltung fest
> oder man aktiviert einen internen Pullup/Pulldown oder man konfiguriert
> sie als Ausgang.
Teils sind sie über einen externen PullUp beschalten, da hatte ich bei 
einem nicht richtig aufgepasst und ein bisschen ohne Gedanken einfach 
copy-paste benutzt. Trotz allem hätte ich die ISRs wohl auch im 
Vornherein schon belegen sollen, das war ein bisschen dumm.

M. K. schrieb:
> Wenn Dir der Prg-Speicher ausgeht oder der Du performance Probleme hast,
> ersetze mal die Wall of Text der StdPeriphLib Aufrufe durch direkte
> Manipulation der Handvoll Register die Du eigentlich setzen willst.
> Wirkt Wunder!

Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph 
"gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber 
werde wohl wieder darauf zurück fallen.

Danke euch!

von BS (Gast)


Lesenswert?

BS schrieb:
> Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph
> "gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber
> werde wohl wieder darauf zurück fallen.

Da tut sich bei mir gleich die Frage auf, woher bekomme ich denn das 
iostm8s003.h-file, sodass ich meine Register korrekt beschrieben kann?
Weil wenn ich die stm8s.h und alle anderen header der STDPeriphLib 
trotzdem inkludieren muss macht das ja (vorallem speicherplatztechnisch) 
eher weniger Sinn oder?

von Tippgeber (Gast)


Lesenswert?

Ich nutze nur die mit dem Ref-Manual von ST übereinstimmenden 
Definitionen meines Compilers (IAR) für meinen konkreten STM8, z.B.:
1
#include <iostm8s105s4.h>

Alles andere im Programm mache ich dann selbst direkt an der Hardware. 
(also über die Register gemäß RefMan)

Solche include-Dateien gibt es meines Wissens bei der HAL auch.

von BS (Gast)


Lesenswert?

BS schrieb:
> BS schrieb:
>> Hatte ich anfangs so gemacht, dann bin aber über die StdPeriph
>> "gestolpert" & dachte mir, dass es dadurch übersichtlicher wird. Aber
>> werde wohl wieder darauf zurück fallen.
>
> Da tut sich bei mir gleich die Frage auf, woher bekomme ich denn das
> iostm8s003.h-file, sodass ich meine Register korrekt beschrieben kann?
> Weil wenn ich die stm8s.h und alle anderen header der STDPeriphLib
> trotzdem inkludieren muss macht das ja (vorallem speicherplatztechnisch)
> eher weniger Sinn oder?

Dumme Frage antwort: JA muss man trotzdem alles inkludieren, die hätte 
ich mir bei nur einem genaueren Blick auch sparen können, hab das nur 
bei Marc Steven Blog anders gesehen (also auch eine andere "Methode" zum 
ansprechen der Register), dieser hat aber anscheinend seine Header-Files 
von IAR, ich programmiere aber mit STVD.

von BS (Gast)


Lesenswert?

BS schrieb:
> trotzdem alles inkludieren

auch wieder falsch...in der stm8s.h kann man die Benutzung der StdPeriph 
auskommentieren und benötigt dann nur die stm8s.h, langsam wirds 
peinlich, aber falls mal jemand hierauf stößt möchte ich natürlich keine 
falschen Infos weitergeben.

von Auweia (Gast)


Lesenswert?

> Ich denke ich verstehe ganz gut, wie ein Interrupt funktioniert ;)

> struct interrupt_vector const _vectab[] = {
>  //{0x82, (interrupt_handler_t)_stext}, /* reset */
>  //{0x82, NonHandledInterrupt}, /* trap  */
>  //{0x82, NonHandledInterrupt}, /* irq0  */
> ...
>  //{0x82, NonHandledInterrupt}, /* irq22 */
>  {0x82, (interrupt_handler_t)TIM4_UPD_OVF_IRQHandler}, /* irq23 */
>  //{0x82, NonHandledInterrupt}, /* irq24 */

Du verstehst davon scheinbar gar nichts.
Bei deiner _vectab landet der TIM4_UPD_OVF_IRQHandler auf der
Position von Reset.
Da wo der TIM4_UPD_OVF_IRQHandler erwartet wird, steht
irgendwas. Aber nicht das, was da hingehoert.

> Letzendlich lags an einem GPIO, den ich als Floating-Input mit
> Interrupt definiert habe

Wohl kaum.

Mit z.B. IAR kann man weak Definitionen benutzen.
Wenn dein Compiler das nicht kann, dann entsorge ihn.

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.