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
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
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
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
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
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
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.
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.