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
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.
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
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.
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.
Interrupt-Flags setzen sich nicht von allein zurück (wie bei den AVRs). Das muss man im Handler schon selber machen.
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.
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.
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.
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.
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
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.
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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.