Forum: Mikrocontroller und Digitale Elektronik STM32F103 Timeout und interrupt


von Joerg V. (joe535)


Lesenswert?

Hallo,

ich bin ein Neuling auf dem ST32F103...

Nun möchte ich folgendes erreichen:

Ich erwarte ein Hardwaresignal auf einer Leitung alle 5 Sekunden. Dies 
Signal wird auf der Leitung ein ca. 10 ms langer puls sein, es soll also 
ein interrupt generiert werden.

Erfolgt der Puls nicht rechzeitig, möchte ich via timer-interrupt eine 
Aktion triggern.

Ich programmiere in ANSI C und (falls es nicht anders geht) in 
Assembler.


Hat da jemand Erfahrung und (besser) ein Codebeispiel?

Danke & Gruss

Joe

von Ulrich P. (uprinz)


Lesenswert?

Schönes Beispiel für eine Gedankliche Oversized-Lösung :)

Also Du möchtest mit einem 72MHz Prozessor eine Sache erledigen, die mit 
5s Auflösung etwas tut, das auch noch etw 10ms lang sein darf.

Gehen wir mal vom Worst-Case aus, dass der Core und Code ineffektiv 
zusammen arbeiten, weil man als Anfänger die Tricks und Kniffe noch 
nicht kennt.
Dann wird ein Befehl in 1/4 der Taktrate laufen.
Du hast also 90Mio Befehle in 5s, und 180000 Befehle in 10ms zur 
Verfügung.

Was Du machen möchtest ist am Einfachsten in einem kleinen (Real-Time-) 
Operating-System zu erledigen, das Dir Tasks zur Verfügung stellt. Dann 
startest Du einen Task, der alle 1ms nachschaut, ob entweder ein Signal 
anliegt oder 5s vergangen sind. Dafür braucht man weder Interrupts noch 
Timer, ausser dem SysTick-Timer, den Dir aber ein gutes OS sowieso schon 
zur Verfügung stellt und den es dann als Zeitbasis für die Tasks 
verwendet.

Obiges funktioniert sehr einfach mit Nut/OS in der STM32 Version. Zu 
finden unter ethernut.de, Quellen des STM32 branch unter 
https://ethernut.svn.sourceforge.net/svnroot/ethernut/branches/devnut_m3n.

Mailingliste und weitere Infos zum wie und wo auf der Webseite.

Gruß, Ulrich

von Joerg V. (joe535)


Lesenswert?

Hallo Ulrich,

es ist ja nicht so, dass die CPU nur dafür da ist, diesen Input zu 
überwachen, das ist nur eine von vielen Aufgaben.
Ein OS wird es auf dem System nicht geben. Pollen möchte ich nicht, das 
wäre ja Dein Vorschlag.

Nur als Anhaltspunkt, das System muss "nebenbei" (ist eher seine 
Hauptaufgabe) noch die Konzentration versch. Gase messen und dies noch 
filtern. Das sind einige hundert Messungen pro Sekunde... Die Anwendung 
ansich ist eine professionelle, nur ich hab eben auf dem Cortex M3 noch 
nie programmiert...

Drum frage ich nach einem Beispiel, wie ich so einen Timeout-timer 
aufsetze und eine Interrupt Routine dem system bekannt mache, sprich in 
die Interrupt-Tabelle eintrage usw.

Beste Grüsse,

Jörg

von Ulrich P. (uprinz)


Lesenswert?

Also das ganze klingt wirklich immer noch nach einer Aufgabe, die durch 
ein (einfaches) OS erledigt werden sollte.

Die Hauptaufgabe ist ja das Erfassen der Messwerte, was beim CM3 recht 
einfach ist, da der ADC per DMA und Abhängig von einem Timer die 
Messwerte automatisch im RAM ablegt.
Sind die Sensoren per Datenschnittstelle angeschlossen, so kann auch 
dies von einem OS recht einfach verwaltet werden.

Auch in einem OS kann man Timer nutzen, die dann Interrupts auslösen, 
oder man kann einen Timer nutzen, der zu verschiedenen Zeiten 
verschiedene Tasks aufweckt. Und man kann diese Timer und Tasks mit 
verschiedenen Prioritäten versehen, je nachdem, ob es einem Wichtiger 
ist, nach genauen Zyklen zu messen oder exakt zu erkennen, ob ein Sensor 
verloren ging.

Ich spreche ja nicht von einem OS im Sinne von (uC-)Linux sondern etwas, 
dass Dir ein paar Werkzeuge zur Verfügung stellt, damit Du es einfacher 
hast die verschiedenen Aufgaben zu paralelisieren.

Schau doch mal nach CooCox, Free-RTOS oder Nut/OS (Ich bevorzuge 
letzteres, da ich den STM32 dafür portiert habe :) )

Ich mach damit genau das, was Du tun willst, nämlich Sensoren auswerten, 
Grenzwerte überwachen und das ganze per CAN an einen Master senden oder 
per Funk übertragen.
Das OS nimmt es Dir schon mal ab, Dich um die Initialisierung zu 
kümmern, Speicher anzubinden, Heap und Stack zu überwachen und es stellt 
Dir eine ganze Reihe fertiger Schnittstellen (USART, SPI, I2C, ADC...) 
und die Ansteuerung von üblichen vorhandenen externen Chips zur Seite 
(EEPROM, RTC, Tasten, LEDs...). Das ganze passt in die 64k Varianten der 
STM32F103 rein, sogar inkl. eines separat laufenden Bootloaders für CAN.
Für 9 von 10 Sensoren war es zudem möglich mit dem Takt auf 16MHz runter 
zu gehen und damit drastisch Strom zu sparen und trotzdem Messzyklen < 
1s einzuhalten und ein komplettes CANopen Profil zu bedienen.

Du solltest Dir also in Ruhe noch mal überlegen, ob Du aus einem 
fertigen Set schöpfen willst, oder alles (nocheinmal) selber erfinden 
musst.

Ps: Nut/OS ist unter BSD Lizenz, die kommerzielle Nutzung ist also ohne 
weitere Besonderheiten gestattet. Wir freuen uns aber über jeden 
Beitrag, Verbesserung oder Treiber, der beigesteuert wird. Ich setze es 
selber kommerziell ein.

Schau halt mal bei ethernut.de, der STM32 Branch ist hier: (SVN)
https://ethernut.svn.sourceforge.net/svnroot/ethernut/branches/devnut_m3n

von Rangi J. (rangi)


Lesenswert?

Das mit dem Interrupt ist ein wenig knifflig, du musst dazu in 
unterschiedlichen Datenblättern suchen.
1
/* PC9 als IRQ Input */
2
STM32_RCC_APB2ENR_IOPC = 1;        /* Port C anschalten*/
3
STM32_GPIOC_CRL |= 1 << 9;         /* PC9 muss als Input eingestellt sein */
4
5
STM32_NVIC->dwEnable[0] = 1 << 23; /* EXTI9 IRQ Channel disable */
6
STM32_AFIO_dwEXTICR3 &= 0xFF0F;    /* EXTI9-Bits loeschen */
7
STM32_AFIO_dwEXTICR3 |= 0x0020;    /* */
8
9
STM32_EXTI->dwIMR  |= IO_EXTI_Line9; /* EXTI9: Interrupt Mask setzen*/
10
STM32_EXTI_EMR_MR9 = 0;            /* EXTI9: keine Event Mask */
11
STM32_EXTI_RTSR_TR9 = 1;           /* EXTI9: steigende Flanke */
12
STM32_EXTI_FTSR_TR9 = 1;           /* EXTI9: 0-keine fallende Flanke 1-fallende Flanke   */


und nicht vergessen im Interrupt das EXTI-Flag loeschen
1
void EXTI9_5_ISR(void)
2
{
3
  some_code
4
  STM32_EXTI_PR_PR9 = 1;           /* Bit set: Clear the EXTI line 2 pending bit */
5
}
ich das hilft etwas, schau dir auf jeden fall die doku dazu durch, 
einfach nur portieren wird nicht einfach sein
RTFM

von Joerg V. (joe535)


Lesenswert?

Hallo Ulrich,

danke für die detaillierte Ausführung.

Es gibt nur ein Problem: Da bereits ein Teil implementiert wurde, OHNE 
OS und ich den Teil verwenden soll/muss, bleibt mir leider gar nicht die 
Wahl..
Ich muss das ohne OS machen.

Blöderweise gibt es im beisherigen code noch keine Nutzung von 
Interrupts oder timern, sonst hätte ich wenigstens dort "kopieren" 
können..

Naja - ich werd mich mal durch die Doku lesen müssen..


Danke nochmal und Gruss
Jörg

von peterguy (Gast)


Lesenswert?

Für deine Aufgabe bauchst du kein OS und keinen externen Interrupt.

Ein einfacher Timer Interrupt, der alles 5ms ausgelöst wird, reicht aus. 
Siehe Pseudocode:
1
#define ALARM_THRESHOLD 1000 //  5sec / 5ms = 1000
2
3
// Timer Interruptroutine, wird alles 5ms aufgerufen
4
void timer_isr()
5
{
6
static uint32 counter = 0;
7
8
counter++;
9
// Resette den counter wenn am pin ein high gemessen wird
10
if (INPUT_PIN == high)
11
{
12
  counter = 0;
13
}
14
15
// wenn der counter den grenzwert (hier 5 sec)überschreitet soll die Aktion ausgeführt werden
16
if (counter > ALARM_THRESHOLD)
17
{
18
  do_alarm_action();
19
}
20
}

ALARM_THRESHOLD sollte vielleicht größer als 1000 sein, z.B. 1500 würde 
7,5 sec bedeuten.

Und den timer interrupt musst du natürlich noch entsprechend 
konfigurieren, da kann ich nicht helfen weil noch nie gemacht beim 
STM32.

von Ulrich P. (uprinz)


Lesenswert?

Hi!

Wenn Du Dir bei dem CooCox nicht ganz sicher bist und vielleicht doch 
etwas Arbeit sparen willst, dann kannst Du getrost Nut/OS einsetzen.
Als Mitentwickler von Nut/OS kann ich Dir versprechen, dass Du es 
kommerziell ohne weitere Verpflichtungen einsetzen kannst. Als Gebühr 
nehmen wir gerne Bugfixes, Treiber oder gute Ideen :)

Für CortexM3 und die ganze STM32F10x Familie wäre der devnut_m3n branch 
für Dich der richtige. Der trunk wird in den nächsten Wochen umgebaut 
und alle neuen Architekturen hinein gemerged. der Branch sollte dabei 
stable bleiben, denn ich setze ihn ebenfalls kommerziell ein.

Gruß, Ulrich

von Daniel B. (dbuergin)


Lesenswert?

Hallo

@Ulrich

Du scheinst Dich ja mit den RTOS'en etwas auszukennen ;-)
Ich suche ein RTOS für den LPC1769, wie sieht es mit Nut/OS hier aus ? 
Bei
CooCox scheint es ja einen Build zu geben. Im Moment traue ich mir eine
Eigenportierung noch nicht zu.

Daniel

von Ulrich P. (uprinz)


Lesenswert?

Hi Daniel,

Leider stehen LPCs bei Nut/OS noch auf der ToDo Liste. Habe auch schon 
ein paar Exemplare ARM7 und CortexM3 bei mir herum liegen. Außerdem gab 
es in der Mailingliste Meldungen das da Bedarf besteht. Aber bisher 
keine Zeit :(

Wenn man etwas C Erfahrung hat ist es aber sehr einfach einen weiteren 
CortexM3, wie den LPC17xx zu Nut/OS hinzu zu fügen. Das schwere an der 
Portierung ist ja, den Chip erst mal zu initialisieren. Und das geht bei 
allen Cortex gleich, dank CMSIS. D.h. Du musst nur eine Funktion 
schreiben, die die PLL korrekt startet und kannst dann gleich mit dem 
USART weiter machen, damit er sich melden kann.

Das ganz Linkerscripte und Init Schreiben kannst Du Dir sparen und sie 
von meinem STM32 kopieren. Wenn es für den LPC ebenfalls ein kompaktes 
Header File gibt, in dem alle Peripherie-Register und deren Flags 
definiert sind, dann kannst Du auch USARTs und so weiter einfach nur die 
Register und Bit-Namen anpassen.
Du darfst Dich da bei allen Dateien bedienen, die stm32_xxx.y heißen, 
denn diese habe ich komplett um-/neu geschrieben. Dateien mit 
stm32f10x_xxx.y sind noch mehr oder weniger STM-Library und daher an den 
STM32 gekoppelt.

Das Einzige, was etwas kompliziert erscheint, wenn man nicht drinn 
steckt, ist das nutconfig. Die Scripte anzupasssen, dass eine neue 
Chip-Generation, oder ein weiterer Typ einer bekannten Architektur 
erkannt wird, ist etwas kniffelig. Auf der anderen Seite haben wir das 
im devnut_m3n bereits weiter aufgedröselt, so dass es übersichtlicher 
wird.

Ich bin in die CM3 Portierung auch mit Respekt eingestiegen, war aber in 
netto 14 Tagen durch. Das schwere war in meinem Fall, die Unterschiede 
der neuen Architektur kompatibel mit den bestehenden Strukturen in 
Nut/OS zu halten. Nun sollte das Einbinden eines weiteren CortexM3 in 
einer Mann-Woche zu machen sein.

Gruß, Ulrich

von Daniel B. (dbuergin)


Lesenswert?

Hm, tönt ja vielversprechend, mal schauen, ob ich die Zeit dazu finde.

Danke

Daniel

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.