Hallo,
stehe wieder vor einem Problem, bei dem ich nicht weiter weiß. Und zwar
will ich mit dem Timer 2 nur raufzählen und beim Überlauf, soll eine LED
toggeln. Irgendwie will das ganze nicht so recht bzw. das Programm geht
nicht in die ISR.
Hier mal der Code
1
#include"ch.h"
2
#include"hal.h"
3
#include"test.h"
4
5
#define ARM_MATH_CM4
6
#include"arm_math.h"
7
8
#include"timconf.h"
9
10
staticuint32_ttim_cnt=0;
11
12
voidTIM2_IRQHandler(void){
13
if((TIM2->SR&TIM_SR_UIF)!=0){
14
palTogglePad(GPIOD,GPIOD_LED5);
15
tim_cnt++;
16
// Clear update interrupt flag
17
TIM2->SR&=~(TIM_SR_UIF);
18
}
19
}
20
21
intmain(void){
22
thread_t*shelltp=NULL;
23
24
/*
25
* System initializations.
26
* - HAL initialization, this also initializes the configured device drivers
27
* and performs the board-specific initializations.
28
* - Kernel initialization, the main() function becomes a thread and the
29
* RTOS is active.
30
*/
31
halInit();
32
chSysInit();
33
34
tim_init();
35
36
/*
37
* Normal main() thread activity, in this demo it just performs
38
* a shell respawn upon its termination.
39
*/
40
while(true){}
41
}
42
}
In tim_conf.c ist folgender Code enthalten:
1
#include"ch.h"
2
#include"hal.h"
3
4
voidtim_init(void)
5
{
6
TIM2->CR1&=~(TIM_CR1_CEN);
7
// TIM2 clock enable
8
RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
9
10
// Auto-reload value
11
TIM2->ARR=42000;
12
// Clear update interrupt flag
13
TIM2->SR&=~(TIM_SR_UIF);
14
// Update interrupt enable
15
TIM2->DIER|=TIM_DIER_UIE;
16
17
// Enable TIM2 for IRQ
18
NVIC_EnableIRQ(TIM2_IRQn);
19
20
// Enable timer counter
21
TIM2->CR1|=TIM_CR1_CEN;
22
23
//END OF IRQ STUFF
24
}
In timconf.h
1
#ifndef TIM_H
2
#define TIM_H
3
4
voidtim_init(void);
5
6
#endif /* TIM_H */
Sieht da einer von Euch den Fehler? Der Timer läuft über und fängt
wieder von 0 an, nur wird die ISR nicht aufgerufen. Bin über jede Hilfe
dankbar.
Lg Gabriel
Danke für die schnellen Rückmeldungen! Habe erst jetzt Zeit gefunden,
die Vorschläge auszuprobieren.
Matthias S. schrieb:> Und wieder einmal: Wo wird die Clock für GPIOD angeschaltet?
Hab den Code nun um folgende Zeile erweitert.
1
RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN;
Kannst du mir bitte sagen, warum es nötig ist, den Clock etxra
einzuschalten, wenn ich lediglich die on-board LED toggeln lasse? Was
mich auch noch etwas irritiert ist, dass immer alle GPIO's (von A bis I)
enabled sind, auch wenn ich es im Code nicht explizit angebe.
Ingo;
> PalTogglePad? Muss das evtl. HalTogglePad heissen?
Nein palTogglePad funktioniert einwandfrei (zumindest in einem anderern
Programmcode).
holger:
> Pack tim_init(); doch mal vor chSysInit();
Hat ebenso zu keiner Verbesserung geführt. Was mir durch diese Änderung
aufgefallen ist, ist, dass das Upadate Interrupt Enable (UIE) bit im
DIER Register nicht gesetzt ist, obwohl ich es im Code enable.
@all
Beim Überlauf wird das Update Interrupt Flag (UIF) bit im SR Register
als auch das CC2, CC3 und CC4 Interrupt Flag bit gesetzt. Kann mir da
jemand sagen, warum die gesetzt werden und warum das CC1IF bit nicht
gesetzt wird?
Danke schonmal im Voraus! Lg
Gabriel J. schrieb:> Kannst du mir bitte sagen, warum es nötig ist, den Clock etxra> einzuschalten, wenn ich lediglich die on-board LED toggeln lasse?
Weil sonst die I/O Logik des Ports nicht angeschubst wird. Es handelt
sich (vereinfacht gesagt) um getaktete Flipflops, die ohne Taktsignal
nix machen. Das steht aber auch in der Referenz.
Kannst du mir umgekehrt mal sagen, warum du mit HAL arbeitest, aber dann
alle Register zu Fuss beschreibst? Das ist am Sinn und Zweck von HAL
vorbei. Wenn du HAL benutzt, ist es nur konsequent, auch die Funktionen
zu benutzen, um mit der Peripherie zu sprechen.
Weiterhin solltest du mal schauen, ob der NVIC sinnvoll initialisiert
ist. Das betrifft vor allem die Prioritätsgruppen und -level.
Ich sehe das ähnlich. Wenn du BareMetal arbeiten willst, solltest du
auch konsequent keine HAL verwenden. (Oder umgekehrt, nur HAL verwenden)
Mit NVIC_EnableIRQ(TIM2_IRQn) schaltest du nur den Interrupt scharf,
denke ich. Es fehlt noch die initialisierung der Priority Grouping und
die Priorität deines Interrupts.
Danke für die Rückmeldung. Ok, das mit dem Clock für die GPIO's ist mir
jetzt klar. Danke
Matthias S. schrieb:> Kannst du mir umgekehrt mal sagen, warum du mit HAL arbeitest, aber dann> alle Register zu Fuss beschreibst? Das ist am Sinn und Zweck von HAL> vorbei. Wenn du HAL benutzt, ist es nur konsequent, auch die Funktionen> zu benutzen, um mit der Peripherie zu sprechen.
Weil ich irgendwie nicht so recht weiß, wie ich mit GPTD2 den Timer
genauso konfigurieren kann, wie mit den Registern. Wie man den clock
einstellt und die callback function alle x GPT clock cycles aufruft,
sehe ich schon raus.
1
staticGPTConfiggpt2cfg=
2
{
3
200000,//timer clock
4
callback//Timer callback
5
};
6
// Configure the GPT timer
7
gptStart(&GPTD2,&gpt2cfg);
8
gptStartContinuous(&GPTD2,100);
Aber wie stelle ich da zB. das Prescaler, Auto-Reload Register ein? Wie
kann ich sagen, ob er rauf oder runterzählen soll, im Center-aligned
oder Capture/Compare mode arbeiten soll. Da hab ich irgendwie nicht so
recht den Durchblick. Gibts da weitere Strukturen, um das alles
einzustellen? Wenn ich die Register zu Fuß beschreibe, ist es für mich
"etwas" übersichtlicher. Da spreche ich auch nur jene Register an, die
ich wirklich brauche. Gibts da nicht einen Vorteil in Sachen
Geschwindigkeit? In weiterer Folge soll nämlich eine Regelung mit 20kHz
betrieben werden.
> Weiterhin solltest du mal schauen, ob der NVIC sinnvoll initialisiert> ist. Das betrifft vor allem die Prioritätsgruppen und -level.
Werd den NVIC mal entsprechend initialisieren. Vllt klappt es ja
anschließend.
Lg
Gabriel J. schrieb:> Aber wie stelle ich da zB. das Prescaler, Auto-Reload Register ein? Wie> kann ich sagen, ob er rauf oder runterzählen soll, im Center-aligned> oder Capture/Compare mode arbeiten soll.
Schau einfach mal hier:
Beitrag "STM32 Timer Callback wird nicht aufgerufen?"
Dort hat der TE das alles mit HAL gemacht. Es gab nur ein kleines
Problem mit dem NVIC.
Und es ist eigentlich immer so, das man die Dokumentation vergessen kann
und sich einfach die Libraries durchliest, die man benutzen will. Dort
haben die eigentlichen Programmierer der Sachen meistens auch schon
Anleitungen reingeschrieben, die die Doku toppen.
Matthias S. schrieb:> Schau einfach mal hier:> Beitrag "STM32 Timer Callback wird nicht aufgerufen?">> Dort hat der TE das alles mit HAL gemacht. Es gab nur ein kleines> Problem mit dem NVIC.> Und es ist eigentlich immer so, das man die Dokumentation vergessen kann> und sich einfach die Libraries durchliest, die man benutzen will. Dort> haben die eigentlichen Programmierer der Sachen meistens auch schon> Anleitungen reingeschrieben, die die Doku toppen.
Danke für die Information! Werd ich demnächst wirklich mit HAL machen.
Hab meinen Fehler nun endlich gefunden. Es lag an den ST Driver System
Settings. Anscheinend tretten mehrerer Interrupts gleichzeitig auf und
irgendwie greift diese Struktur so auf den TIM2-Interrupt zu, dass bei
meinem Code der Handler nicht aufgerufen wird.
Lösung:
In mcuconf.h:
1
#define STM32_ST_USE_TIMER 5// vorher 2
Da Timer 5 und 2 identisch sind.
In main.c:
1
voidSTM32_TIM2_HANDLER(void){
2
if((TIM2->SR&TIM_SR_UIF)!=0){
3
palTogglePad(GPIOD,GPIOD_LED3);
4
tim_cnt++;
5
}
6
// Clear update interrupt flag
7
TIM2->SR&=~(0xffff);
8
}
Danke für die sehr hilfreichen Antworten/Informationen. Hat für das
Verständnis sehr geholfen!! Lg Gabriel