Forum: Mikrocontroller und Digitale Elektronik stm32 SysTickFunction wird nie ausgeführt


von Steph M. (stephh)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

warscheinlich ein trivialer Fehler aber ich find ihn einfach nicht.

Mein angehängts Programm soll auf einem STM32F030F4P6 laufen. Leider 
springt der Controller nie in void SysTickFunction(void) und auch nie in 
void TIM16_IRQHandler(void). Daher, es wird kein Interrupt ausgelöst. 
Aber warum nicht?

Aktiviere ich den Port der jetzt gerade im Systick steht über die 
main-Funktion, dann gehts. Daher muss die Initalisierung des Pins 
richtig sein. Die Variable "SystemCoreClock" liefert mir beim Debuggen 
48mHz zurück, daher gehe ich davon aus, dass der stm32 auch mit 48mHz 
läuft.

Entwicklungsumgebung ist CoIDE.

Vielen Dank schon mal für eure Vorschläge.

Grüße
Stephan

von Guest (Gast)


Lesenswert?

Steph M. schrieb:
> Leider springt der Controller nie in void SysTickFunction(void)

Wieso sollte er? Oder hast du die Funktion in die Vectortabelle 
eingetragen?
Ich sehe auch keine Initialisierung vom System Tick.

Sind Interrupts überhaupt enabled? Was steht im Primask und Basepri 
Register? Sollten beide 0 sein, damit du Interrupts egal welcher 
Priorität bekommen kannst.

von Andreas H. (ahz)


Lesenswert?

Steph M. schrieb:
> Hallo Leute,
>
> warscheinlich ein trivialer Fehler aber ich find ihn einfach nicht.
>


Müsste
1
TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CKD_DIV1;
nicht eher
1
TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
sein ?

Grüße
Andreas

von W.S. (Gast)


Lesenswert?

Steph M. schrieb:
> warscheinlich ein trivialer Fehler aber ich find ihn einfach nicht.

Ja.

Dein Fehler ist es, daß du nicht selbst die nötigen Dinge tust, sondern 
ständig nur irgendwelche ominösen Systembibliotheken und deren 
Funktionen bemühst.

Vermutlich hast du auch keinen echten Startupcode in Assembler, sondern 
nur so ein C-Konstrukt, wo du wirklich NICHT weißt, ob es Compiler und 
Linker so machen, wie du es benötigst - weil du wegen einer IDE nicht 
genau sehen kannst, was da alles an Parametern auf der Kommandozeile der 
Tools tatsächlich steht. Aber das ist nnur ne Vermutung meinerseits.

Also:
1. Im Startupcode hat der Dummy-Handler das [WEAK] Kennzeichen zu 
tragen, damit er vom Linker bei Vorliegen eines genau namensgleichen 
echten Handlers ignoriert wird und statt seiner die Adresse des echten 
Handlers eingetragen wird.

Das sieht dann etwa so aus:
1
   DCD  SysTick_Handler    ; Cortex-M4 System Tick Interrupt
2
...
3
...
4
5
SysTick_Handler PROC
6
                EXPORT  SysTick_Handler   [WEAK]
7
                LDR     R1, =512              ; war SysTick
8
                B       Restart
9
                ENDP


2. Zum Setup des Systicks greift man in die Register der Cortex-CPU wie 
folgt:
1
/* Cortex M4 Systick als System-Uhr einrichten,
2
   der Systemtakt ist 100 MHz,
3
   und alle 1 ms sollte ein Interrupt erfolgen.
4
 */
5
void Systemtick_Init (void)
6
{  Ticks = iTicks = SecTicks = 0;
7
   SYST_RVR = 100000-1;                 // 100 MHz, 1 ms
8
   SYST_CSR = 7;                        // enabled, cclk als Takt
9
}
10
11
void  __irq  SysTick_Handler (void)
12
{ .... }

Damit läuft der SysTick auf allen Cortexen zuverlässig. Die Anpassung 
wegen Systemtakt und gewünschtem Tick kannst du ja hoffentlich selbst.

W.S.

von (prx) A. K. (prx)


Lesenswert?

Steph M. schrieb:
> springt der Controller nie in void SysTickFunction(void)

Bei den Cortex-M haben die Interrupt-Handler fest vom CMSIS vorgegebene 
Namen. Wenn der Name deines Handlers nicht mit dieser Vorgabe 
übereinstimmt, dann weiss das System überhaupt nicht, dass deine 
Funktion ein Handler dafür sein soll.

Assembler-Code oder ein spezielles Attribut für Handler-Funktionen 
benötigt man bei den Cortex-M nicht.

von (prx) A. K. (prx)


Lesenswert?

Interrupt-Flags setzen sich nicht von allein zurück (wie bei den AVRs). 
Das muss man im Handler schon selber machen.

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Bei den Cortex-M haben die Interrupt-Handler fest vom CMSIS vorgegebene
> Namen.
> Assembler-Code oder ein spezielles Attribut für Handler-Funktionen
> benötigt man bei den Cortex-M nicht.

Du schreibst Stuß.

Man kann bei jedem Cortex beliebige Handler-Namen benutzen - sofern man 
weiß, was man tut und dazu sowohl in der Lage ist als auch den Willen 
dazu hat. Alles Andere ist simple Konvention und in keinster Weise durch 
die Tools oder sonstwas vorgegeben.

W.S.

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Interrupt-Flags setzen sich nicht von allein zurück (wie bei den AVRs).
> Das muss man im Handler schon selber machen.

Du schreibst schon wieder Stuß.

Speziell beim SysTick ist keinerlei dediziertes Flag-Rücksetzen nötig 
oder überhaupt vorgesehen.

Wenn du schon nix weißt, dann lies bei arm.com 
"DDI0439C_cortex_m4_r0p1_trm.pdf" oder Nachfolger, damit du was dazu 
lernst.

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Alles Andere ist simple Konvention und in keinster Weise durch
> die Tools oder sonstwas vorgegeben.

Diese Konvention gibt es und sie heisst CMSIS. Mit der ST Library hat 
das nichts zu tun, CMSIS ist von ARM.

Selbstverständlich kann man auch bei den CM von Adam und Eva weg mitsamt 
Startup-Code alles selber schreiben. Muss man aber meist nicht, weil 
IDEs entsprechendes meist schon mitbringen.

Tipps wie den Startup und die Interrupt-Weaks in Assembler selber zu 
schreiben, gehört genau zu den Dingen, die ein Anfänger nicht brauchen 
kann. Soviel zu "Stuss".

Auch bei AVRs ist es in C nicht üblich, Startup und Interrupt-Tabelle 
selbst zu schreiben. Üblicherweise verwendet man das, was die 
Entwicklungsumgebung vorgibt, im hiesigen Kontext also meist die 
Konvention der avrlibc. Die arbeitet praktisch genauso, d.h. gibt die 
Namen fest vor.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Speziell beim SysTick ist keinerlei dediziertes Flag-Rücksetzen nötig
> oder überhaupt vorgesehen.

Aber beim Timer, und der ist hier auch mit drin.

von Steph M. (stephh)


Angehängte Dateien:

Lesenswert?

Leute,
bitte nicht streiten.

Ich danke vielmals für eure Vorschläge. Dass SysTickFunction(void) nicht 
gehen kann darauf hätte ich selber kommen können. Muss natürlich 
SysTick_Handler heißen.
Interruptflags muss man in der Tat zurücksetzen (ausgenommen beim 
SysTick) => "TIM_ClearITPendingBit(TIM16, TIM_IT_Update);" eingefügt.
Der Hinweis von Andreas ist natürlcih auch korrekt. Was hab ich hier 
bitte verbrochen...

Der Systick tut nun. Der IRQ mit TIM16 will aber immer noch nicht. Anbei 
die aktuelle Version.

Es tut mir sehr leid, dass ich euch hier mit meinen Anfängerfragen 
nerve. Ich beschäftige mich erst seit 3Tagen mit stm32f429 und seit 
knapp 1,5Stunden jetzt mit dem stmf030.

Vielen Dank!

Grüße
Steph

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> Du schreibst Stuß.
W.S. schrieb:
> Du schreibst schon wieder Stuß.

Hat dir grad jemand weh getan, dass du hier so aggressiv rumkrakelen 
musst? Man kann unterschiedliche Ansichten auch in vernünftiger Form 
ausdrücken.

von Steph M. (stephh)


Lesenswert?

So Fehler gefunden. Ich hab den Code vom f429 übernommen, aber hier beim 
f030 liegt der TIM16 an APB2 nicht an APB1... Jetzt läufts wie ichs mir 
vorstelle. Nur der Tackt muss noch angepasst werden.

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
> Man kann unterschiedliche Ansichten auch in vernünftiger Form
> ausdrücken.

Es handelt sich nicht um unterschiedliche Ansichten, sondern um Sinn 
oder Unsinn. Über 3x3=9 kann man zwar auch unterschiedliche Meinungen 
haben, aber jede, ber der nicht 9 rauskommt, ist offensichtlicher Stuß. 
Selbiger war bei dir nicht so offensichtlich, jedoch vorhanden.

Ich habe dem TO erklärt, wie es sich mit dem SysTick verhält, hab ihm 
sogar ein funktionables Beispiel gegeben.

Da hättest du besser getan, dem TO zu erklären, wie man nen 
Timer-Interrupt in Gang kriegt - anstatt an mir herumzunörgeln.

Hier nur ein paar Hinweise für den TO:

- Timer sind nicht in der CPU, sondern irgendwo "draußen" an einem 
peripheren Bus. Deshalb ist oftmals der Takt dorthin ab Systemstart 
abgeschaltet und der ganze Timer tot, bis man in irgend einem 
System-Steuer-Block den Takt dorthin einschaltet.

- bei Timern ist eigentlich immer vorgesehen, daß sie ihr "bin am Ende" 
Signal entweder zum Auslösen eines Interrupts oder zum Auslösen einer 
DMA-Aktion verwenden können. Details muß man im RefMan nachlesen, denn 
gerade Timer sind von Hersteller zu Hersteller (und oft von einer 
Chipfamilie zur anderen)  sehr unterschiedlich gestaltet. Eigentlich 
fast immer braucht dabei gar kein Flag zurückgestellt zu werden, denn 
der DMA macht sowas ja auch nicht.

- beim NVIC der Cortexe gibt es eine nette Möglichkeit, die Interrupts 
zu testen, indem man testeshalber sowas per Software auslöst.
Beispiel:
  NVIC_STIR = 31;   /* Interrupt Nr.31 auslösen */
Bei manchen Situationen ist das auch bitter nötig, so z.B. bei 
gepufferten interruptgesteuerten UART's, denn dort kommt der 
Sende-Interrupt nur dann, wenn der Fifo leer wird - und wenn es dann 
momentan nix zu senden gibt, kann man ihn auch nicht mehr auffüllen. 
Wenn dann später was gesendet werden soll, müßte man ihn wieder 
aktivieren und das geht nur dann ohne Komplikationen, wenn es der 
Interrupt-Handler selbst tut. Aber der muß erstmal ausgelöst werde. Dazu 
dann der NVIC_STIR...

W.S.

von S. R. (svenska)


Lesenswert?

A. K. schrieb:
> Bei den Cortex-M haben die Interrupt-Handler fest vom CMSIS vorgegebene
> Namen. Wenn der Name deines Handlers nicht mit dieser Vorgabe
> übereinstimmt, dann weiss das System überhaupt nicht, dass deine
> Funktion ein Handler dafür sein soll.

Richtig. Daher sollte man am besten auch im Startup-Code nachschauen, ob 
der Name auch wirklich stimmt (oder ob man sich vertippt hat).

> Assembler-Code oder ein spezielles Attribut für Handler-Funktionen
> benötigt man bei den Cortex-M nicht.

Jaein. Der Startup-Code muss alle Handler schon weak irgendwo definiert 
haben, um die Vektortabelle automatisch zu erzeugen. Und da die 
Vektortabelle nicht vom ARM vorgegeben wird, sondern vom Hersteller des 
Chips (nur der kennt alle möglichen Interrupts), findet man die 
Definitionen in der Regel nicht im CMSIS, sondern in der 
Herstellerbibliothek.

Und gegen einen Vertipper dort hilft nachschauen auch.

A. K. schrieb:
> Interrupt-Flags setzen sich nicht von allein zurück (wie bei den
> AVRs). Das muss man im Handler schon selber machen.

Falsch. Das Interrupt-Flag (im NVIC) setzt sich sehr wohl automatisch 
zurück. Es hängt von der Peripherie ab, ob man dort zusätzlich noch 
einmal bestätigen muss. Beim SysTick ist das nicht der Fall, z.b. bei 
Atmels PIO schon.

von (prx) A. K. (prx)


Lesenswert?

S. R. schrieb:
> Es hängt von der Peripherie ab, ob man dort zusätzlich noch
> einmal bestätigen muss.

Korrekt. Und genau das fehlte hier. Q.E.D.

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.