Forum: Mikrocontroller und Digitale Elektronik STM32F051 Problem beim Debuggen mit Timer IRQ


von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

habe ein Problem beim Debuggen der Firmware auf einem STM32F051 µC.
IDE ist CooCox 1.7.6, Toolchain ARM GCC 4.9 2015q2 und der Debug Adapter 
ST Link V2.

Bisher laufen ein paar Hardware PWMs mit TIM 1, TIM 2 und TIM 3 auf dem 
Controller. Nun wollte ich einen weiteren Timer nutzen (TIM 16) der mit 
ca 300 Hz läuft um ein paar 7 Segment Displays zu multiplexen.

Die Firmware scheint auch problemlos zu laufen. Die LEDs faden wie sie 
sollen und die 7 Segment Anzeige tut auch.

Das Problem besteht beim Debuggen. Bis zum Init vom NVIC für den Timer 
ist alles normal. Also ich kann z.B. mit step into in Funktionen gehen 
und single steppen. Nach dem Init vom NVIC sobald der Update Interrupt 
vom Timer scharf ist lande ich bei jedem single step in der Timer ISR. 
Was das debuggen von anderen Funktionen unmöglich macht.
Was mir etwas komisch vorkommt ist der Eintrag 3 im Function Backtrace 
(Siehe Bild). Ist das normal oder kann das ein Hardfault sein ?

Verstehe nicht ganz woher das kommt. Auf einem STM32F407 nutze ich mit 
dem selben Debug Adapter / IDE ebenfalls Timer mit ISRs und da läuft 
alles wie es soll. Ist das vielleicht auch eine Einstellungssache, also 
irgendwelche compiler flags oder so was ?

Ich nutze diesen Code zum Init vom Timer und NVIC:
1
  TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
2
3
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);
4
5
  TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
6
  TIM_TimeBase_InitStructure.TIM_Period = 40000;
7
  TIM_TimeBase_InitStructure.TIM_Prescaler = 3;
8
  TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
9
10
  TIM_TimeBaseInit(TIM16, &TIM_TimeBase_InitStructure);
11
12
  TIM_ITConfig(TIM16,TIM_IT_Update, ENABLE);
13
14
  TIM_Cmd(TIM16, ENABLE);
15
16
17
  NVIC_InitTypeDef NVIC_InitStructure;
18
19
  NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn;
20
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
21
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
22
  NVIC_Init(&NVIC_InitStructure);

Hat jemand eine Idee was da schiefläuft oder Tipps was ich machen kann 
um normal zu debuggen ?

Vielen Dank schonmal und viele Grüße,
Stefan

von Jim M. (turboj)


Lesenswert?

Stefan schrieb:
> Was mir etwas komisch vorkommt ist der Eintrag 3 im Function Backtrace
> (Siehe Bild). Ist das normal oder kann das ein Hardfault sein ?

Normal. Das ist einer der "Excpetion Return" Werte, der liegt da an 
Stelle einer Rückkehraddresse auf dem Stack.

Stefan schrieb:
> Nach dem Init vom NVIC sobald der Update Interrupt
> vom Timer scharf ist lande ich bei jedem single step in der Timer ISR.
> Was das debuggen von anderen Funktionen unmöglich macht.

Man muss dann (eventuell im Disassembly) manuell Breakpoints setzen.

Bei OpenOCD kann man im Single Step Mode Interrupts deaktivieren, 
vielleicht kann CooCox das auch.

von Stefan (Gast)


Lesenswert?

Jim M. schrieb:
>> Nach dem Init vom NVIC sobald der Update Interrupt
>> vom Timer scharf ist lande ich bei jedem single step in der Timer ISR.
>> Was das debuggen von anderen Funktionen unmöglich macht.
>
> Man muss dann (eventuell im Disassembly) manuell Breakpoints setzen.
>
> Bei OpenOCD kann man im Single Step Mode Interrupts deaktivieren,
> vielleicht kann CooCox das auch.

Was ich nicht versteh ist das es bei dem STM23F407 problemlos klappt.
Da lässt sich ganz gewohnt debuggen auch wenn mehrere Interrupts aktiv 
sind.

von Little B. (lil-b)


Lesenswert?

Was du dir anschaun solltest:
Reference Manual des STM32F4, Kapitel 38.16.2
Reference Manual des STM32F0, Kapitel 32.9.2

Hier ist beschrieben, dass man beim erreichen eines Breakpoints die 
Timers anhalten kann. Das lässt sich einstellen in den Registern 
DBGMCU_APBx_FZ (x=1..2)

Während deines Breakpoints laufen deine Timer weiter, und erzeugen 
natürlich Interrupts. Diese werden dann mit dem nächsten "Single Step" 
aufgerufen.

Single Step ist dabei mehrdeutig, wenn man C-Code debuggt. Debugger 
können sich hierbei unterschiedlich verhalten. openOCD z.B. macht 
tatsächlich mehrere Single Steps über alle ASM-Anweißungen eines 
einzelnen C-Statements. So wird ein anspringen einer ISR unterbunden. 
Andere Debugger setzen einfach einen Breakpoint an die nächste 
gewünschte Adresse und lassen den Prozessor laufen. Dann wird die ISR 
angesprungen.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Danke schonmal für die Antworten.

Das mit dem DBGMCU Register scheint die richtige Richtung zu sein.

Bei dem F4 lässt sich da auch problemlos das jeweilige Bit zum disablen 
setzen.
Leider funktioniert diese Methode nicht bei dem F0..
Probiert hab ich es damit:
1
DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM16_STOP;
und damit:
1
#define REG  (*((volatile unsigned long *) 0x4001580c))
2
REG = DBGMCU_APB2_FZ_DBG_TIM16_STOP;

Im Gegensatz zum F4 ändert das Ausführen dieser Codezeile nichts in den 
Registern.
Seltsam ist auch das die Register in der Coocox Register view anders 
heißen als die Defines. Siehe Bild im Anhang.

Ist das ein Bug in Coocox oder muss ich den Zugriff auf diese Register 
erst irgendwie erlauben ? (Was vielleicht im Startupcode vom F4 gemacht 
wird und beim F0 nicht)

Viele Grüße,
Stefan

von Stefan (Gast)


Lesenswert?

Ok problem solved...
1
  RCC_APB2PeriphClockCmd (RCC_APB2Periph_DBGMCU, ENABLE);
2
  DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM16_STOP;

Damit tuts. Muss man auch erstmal drauf kommen das das DBG Register als 
peripheral anzusehn ist dem man erstmal den clock anschalten muss....

von STM (Gast)


Lesenswert?

Kann nochmal einer sortieren, was genau alles eingestellt werden muss?

Bei mir laufen meine Timer leider ebenfalls weiiter, obwohl ich mich im 
Interrupt befinde.

von Frank (Gast)


Lesenswert?

STM schrieb:
> Bei mir laufen meine Timer leider ebenfalls weiiter, obwohl ich mich im
> Interrupt befinde.

Das ist so gewollt. In vielen Applikationen ist es wichtig das z.B. eine 
PWM auch im Breakpoint weiter läuft. Deshalb muss auch der Timer weiter 
laufen.

> Kann nochmal einer sortieren, was genau alles eingestellt werden
> muss?

Wenn man dies nicht will muss man anscheinend folgendes Bit setzen:
1
DBGMCU->APB2FZ |= DBGMCU_APB2_FZ_DBG_TIM16_STOP;

Über das Konstrukt wird wahrscheinlich vorher das schreiben auf das 
Register freigegeben:
1
RCC_APB2PeriphClockCmd (RCC_APB2Periph_DBGMCU, ENABLE);

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.