Forum: Mikrocontroller und Digitale Elektronik STM32 Interruptproblem - Interrupt geht, aber Main nicht -


von Markus F. (dr-ice)


Lesenswert?

Hallo,

ich experimentiere mit einem STM32F103RBT6 mit einem TFT mit Touchscreen 
unter CooCox-IDE.

Ich habe jetzt versucht, den Touchscreencontroller zu benutzen und habe 
dazu eines der Beispielprogramme zu meinem Board hergenommen.

Beim Debuggen habe ich jetzt gesehen, dass das Programm bis in den 
Interrupt-Handler springt, dort aber nicht mehr heraus kommt.

Der Interrupt funktioniert weiterhin, nur die Main-Schleife läuft nicht 
weiter. In der IRQ-Routine wird nur geblinkt, das funktioniert auch noch 
nach dem 20ten Mal drücken auf den Touchscreen.

Ich bastel da jetzt schon länger dran rum, vielleicht könnt Ihr mir ja 
einen Tip geben ?

Gruß Markus

Hier meine IRQ-Routine:
1
void EXTI15_10_IRQHandler()
2
{
3
  if (EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
4
  {
5
    Delay(500000);
6
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_SET);
7
    Delay(500000);
8
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_RESET);
9
10
    Delay(500000);
11
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_SET);
12
    Delay(500000);
13
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_RESET);
14
15
    Delay(500000);
16
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_SET);
17
    Delay(500000);
18
    GPIO_WriteBit(LED_PORT, GPIO_Pin_2, Bit_RESET);
19
20
    //
21
    //Clear the EXTI line 9 pending bit
22
    //
23
    EXTI_ClearITPendingBit(EXTI_Line13);
24
    EXTI_ClearITPendingBit(0);
25
  }
26
}

Und meine NVIC-Konfig :
1
    NVIC_InitTypeDef NVIC_InitStructure;
2
3
  #ifdef  VECT_TAB_RAM
4
    /* Set the Vector Table base location at 0x20000000 */
5
    NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
6
  #else  /* VECT_TAB_FLASH  */
7
    /* Set the Vector Table base location at 0x08000000 */
8
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
9
  #endif
10
11
  /* Configure one bit for preemption priority */
12
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);     
13
14
  /* Enable the EXTI15_10_IRQn Interrupt */
15
  NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;  
16
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
17
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      
18
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        
19
  NVIC_Init(&NVIC_InitStructure);            
20
}




Wenn zur Klärung noch was fehlt, sagt Bescheid, bin noch nich so fit in 
C mit STM32.

Gruß Markus

von A. B. (funky)


Lesenswert?

Line 13 ist laut meiner Doku EXTI_Line13.
Du benutzt da ein define für eine Event Maske. Ich hab die EXIT IRQs 
noch nicht benutzt aber das das so stimmt glaub ich nicht.

Desweiteren musst du nicht noch irgendwo dein EXTI_InitTypeDef Struct 
initialisieren, wo dann auch festgelegt wird, worauf du triggerst, ob du 
Events benutzt usw.

http://stm32.kosyak.info/doc/group___e_x_t_i___private___functions.html 
könnte weiterhelfen

von A. B. (funky)


Lesenswert?

achso und deine delays solltest du mal zackig aus deiner IRQ routine 
rausnehmen...

von holger (Gast)


Lesenswert?

>Du benutzt da ein define für eine Event Maske. Ich hab die EXIT IRQs
>noch nicht benutzt aber das das so stimmt glaub ich nicht.

Ich auch nicht. Wenn der Interrupt dauernd feuert wird wohl
das falsche Interrupt Flag zurückgesetzt.

Wenn man sich das ansieht:

  if (EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
  {
    EXTI_ClearITPendingBit(EXTI_Line13);

könnte man auf die Idee kommen das es so sein sollte:

  if (EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
  {
    EXTI_ClearITPendingBit(EXTI_IMR_MR13);

Hab jetzt aber auch nicht weiter nachgeforscht;)

von holger (Gast)


Lesenswert?

>Hab jetzt aber auch nicht weiter nachgeforscht;)

Jetzt schon;) Laut Examples aus der ST Lib passt das wohl:
1
/******************************************************************************/
2
/*            STM32F10x Peripherals Interrupt Handlers                        */
3
/******************************************************************************/
4
5
/**
6
  * @brief  This function handles External lines 9 to 5 interrupt request.
7
  * @param  None
8
  * @retval None
9
  */
10
void EXTI9_5_IRQHandler(void)
11
{
12
  if(EXTI_GetITStatus(KEY_BUTTON_EXTI_LINE) != RESET)
13
  {
14
    /* Toggle LED1 */
15
     STM_EVAL_LEDToggle(LED1);
16
17
    /* Clear the Key Button EXTI line pending bit */
18
    EXTI_ClearITPendingBit(KEY_BUTTON_EXTI_LINE);
19
  }
20
}

von Markus F. (dr-ice)


Angehängte Dateien:

Lesenswert?

Hi,

Danke erst mal für die vielen Antworten ! Ich habe mal das komplette 
touch - script angehangen, aber ich finde meinen fehler nicht. Das 
Script im Anhang funktioniert mit dem mitgelieferten Projekt 
einwandfrei, also muss mein Fehler irgendwo in der initialisierung 
liegen.

Das Projekt wurde für den Keil Compiler gebaut und ich versuche das 
jetzt mit CooCox zum laufen zu bringen.

Merkwürdig..

Gruß Markus

von holger (Gast)


Lesenswert?

>Ich habe mal das komplette touch - script angehangen,

Das schmeisst du jetzt am besten mal in die Tonne und versuchst
ein Programm zu schreiben das einen EXTI auslöst der der
main() auch wieder Rechenzeit gibt.

Ich hab echt kein Bock mich durch deinen geklauten Code zu kauen.

von A. B. (funky)


Lesenswert?

holger schrieb:
>>Du benutzt da ein define für eine Event Maske. Ich hab die EXIT IRQs
>>noch nicht benutzt aber das das so stimmt glaub ich nicht.
>
> Ich auch nicht. Wenn der Interrupt dauernd feuert wird wohl
> das falsche Interrupt Flag zurückgesetzt.
>
> Wenn man sich das ansieht:
>
>   if (EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
>   {
>     EXTI_ClearITPendingBit(EXTI_Line13);
>
> könnte man auf die Idee kommen das es so sein sollte:
>
>   if (EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
>   {
>     EXTI_ClearITPendingBit(EXTI_IMR_MR13);
>
> Hab jetzt aber auch nicht weiter nachgeforscht;)

ich würde eher
1
 if (EXTI_GetITStatus(EXTI_Line13) != RESET)
2
   {
3
     EXTI_ClearITPendingBit(EXTI_Line13);

benutzen.

Desweiteren habe ich mal nach KEY_BUTTON_EXTI_LINE gesucht, und in den 
Beispielen von ST steht da:
1
#define KEY_BUTTON_EXTI_LINE EXTI_Line9

was auch eher zum oben vorgeschlagenen passt.

Was auch noch sein kann:
Sind die IRQs Pegel oder Flanken basiert? Ich habs jetzt nicht 
nachgeschaut...du musst mal schauen was dein Touchpanel im Normalzustand 
für einen Pegel ausgibt. Nicht dass das unberührt einen Low-Pegel 
ausgibt und du auf low triggerst. Könnte ja auch noch ein Problem sein

von A. B. (funky)


Lesenswert?

Und wie ich weiter oben schon schrieb:

wie initialisiert du deinen EXTI?
Mit NVIC ist es ja noch nicht getan

von Markus F. (dr-ice)


Lesenswert?

Hi,

Danke nochmal an Alle !
1
    /* Connect PEN EXTI Line to Key Button GPIO Pin */
2
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
3
4
    /* Configure PEN EXTI Line to generate an interrupt on falling edge */
5
    EXTI_InitStructure.EXTI_Line = EXTI_Line13;
6
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
7
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
8
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
9
    EXTI_Init(&EXTI_InitStructure);
10
11
    /* Generate software interrupt: simulate a falling edge applied on PEN EXTI line */
12
    EXTI_GenerateSWInterrupt(EXTI_Line13);

Gruß Markus

P.S.: Der "geklaute Code" ist vom Hersteller mitgeliefert !

von Lueger (Gast)


Lesenswert?

Wie schon genannt: keine Delay's in der Int Routine! Arger Fehler!
Der Coocox Debugger ist kein Allheilmittel! Nimm lieber breaakpoints 
über die UART!

Du arbeitest viel zu viel Code in der Interruptroutine ab. Kein Aufruf 
von
Subroutinen! Setze lieber ein Bit in der IR Routine und lass main das 
abarbeiten.

Die Definition deines Ex Int fehlt (schon genannt)

Lass deine main auch was tun.

Sonst noch mal mit der Keil Entwicklungsumgebung probieren.

Das Debuggen mit JTag/SWD ist nicht mein Freund....

Ein Osci knnn auch viele Probleme lösen..



Lueger

von holger (Gast)


Lesenswert?

>achso und deine delays solltest du mal zackig aus deiner IRQ routine
>rausnehmen...

Dein Wort in Gottes Ohr.

void EXTI15_10_IRQHandler()
{
....
// Noch so eine Drecksschleife in einer ISR
    for(i=1000;i>0;i--);       //ÑÓʱȥ¶¶¶¯
....
}

Was bedeutet der Kommentar hinter der Schleife eigentlich?
"Vollidioten aller Länder vereinigt euch"? Verbrennt
Rechenzeit in einer ISR. Oder ist das ein schwachsinniger
Versuch einer Entprellung? Ich weiss es nicht und möchte es eigentlich
auch nicht wissen.

von Markus F. (dr-ice)


Lesenswert?

Hallo Holger,

da Du ja soo gut bist, könntest Du mir ja auch ganz kurz schreiben, wie 
ich den Mist richtig initialisiere.

Gruß Markus

von holger (Gast)


Lesenswert?

>da Du ja soo gut bist, könntest Du mir ja auch ganz kurz schreiben, wie
>ich den Mist richtig initialisiere.

Sag mir erst mal was das bedeutet
//ÑÓʱȥ¶¶¶¯

von Spinner (Gast)


Lesenswert?

An den Marterpfahl und danach in den Büserstuhl mit denen, die in einer 
INT Routine mehr wie ein Bit setzen....;-)

von A. B. (funky)


Lesenswert?

Wobei ich mich im Zuge dessen jetzt doch Frage, wofür genau die Events 
sind?
Ich habe mal die Erklärung gefunden, das ein Event nicht abgearbeitet 
werden muss, ein IRQ hingegen schon. Bzw. bei einem Event die IRQ 
Routine nicht angesprungen werden muss. Ist dem so?
Ich habe jetzt noch nicht sehr kräftig nachgeschaut aber ein kurzes 
überfliegen brachte keine Erleuchtung. Weiss jemand auf die schnelle 
mehr?


Und an den Threadersteller: gehts jetzt oder nicht?
Wenn ich mir den Beispielcode mal überfliege:

Pin 13 daran hängt das Touchpad.
Den Pin musst du auch noch konfigurieren. Mit dem Code unte wird ein Pin 
mit Pullup Widerstand definiert. Würde ja zu deinem Touchpad und trigger 
auf die fallende Flanke passen
1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC);
2
//Configure PC13 pin: TP_INT pin 
3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 
4
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //ÉÏÀ­ÊäÈë
6
GPIO_Init(GPIOC,&GPIO_InitStructure);

Aber was mir nicht ganz klar ist:
1
if(EXTI_GetITStatus(EXTI_IMR_MR13) != RESET)
2
{
3
EXTI_ClearITPendingBit(EXTI_IMR_MR13);

Das benutzt diese Event Bits während der EXTI als Interrupt und nicht 
als Event konfiguriert ist. Ich weiss jetzt nicht was das genau bedeutet 
wie ich oben schon schrieb, aber wenns funktioniert im Beispiel Code 
könntest du das ja auch nochmal in deiner IRQ Routine testen. Ich weiss 
nicht ob die Eventflags und die IRQ Flags gleichzeitig gesetzt werden 
und äquivalent benutzt werden können.
Nur muss es ja irgendeinen Sinn machen, das man den EXTI IRQ Mode als 
EXTI_Mode_Interrupt
oder
EXTI_Mode_Event
definieren kann.

von Markus F. (dr-ice)


Lesenswert?

Hallo A. B.,

nein es geht noch nicht, aber ich habe beschlossen die ganze Geschichte 
in ein RTOS zu stricken, damit kenne ich mich aus und kann auch 
verschiedene fertige Grafikroutinen nutzen, ohne was umbauen zu müssen.

Vielen Dank nochmal

Markus

von A. B. (funky)


Lesenswert?

naja, die Interrupts funktionieren dann aber trotzdem noch nicht ;)

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.