Hallo
Ich portiere momentan ein Projekt von Arduino auf STM32 (STM32F302R8)
und arbeite mich dabei in die Plattform ein. Im Moment bin ich mit der
I2C-Implementierung beschäftigt und wieder über ein Thema gestolpert,
das mir schon bei den Timern, den ADCs und der Systemuhr aufgefallen
ist:
STM32CubeMX erzeugt Code zur Konfiguration der beteiligten Interrupts
und setzt dabei die Prioritäten sämtlicher konfigurierter IRQs auf 0:
In der Programmoberfläche sind die Werte für Preemption Priority und Sub
Priority zwar sichtbar aber nicht bearbeitbar.
Verstehe ich das richtig, dass alle diese Interrupts mit höchster
Priorität stattfinden?
Warum ist das so?
Warum möchten die Entwickler nicht, dass man davon abweicht?
Zusätzlich ist mir aufgefallen, dass die Konfiguration für die
Bit-Verteilung zwischen Preemption-Priorität und Sub-Priorität nicht nur
im Laufe des Initialisierungsprozesses mehrmals geändert wird, sondern
auch so mit Zuweisungen von IRQ-Prioritäten verschachtelt ist, dass ich
mir nicht sicher bin, was beim SysTick-IRQ überhaupt am Ende eingestellt
ist.
Um zu zeigen was ich meine habe ich sämtliche dieser Funktionsaufrufe
zusammengesucht, in der Reihenfolge, in der sie stattfinden werden.
Welche Funktion durch welche aufgerufne wird habe ich durch Einrückung
dargestellt.
1
#define NVIC_PRIORITYGROUP_0 (0x00000007U) /*!< 0 bits for pre-emption priority
2
#define NVIC_PRIORITYGROUP_4 (0x00000003U) /*!< 4 bits for pre-emption priority
3
#define __NVIC_PRIO_BITS 4U /*!< STM32F302x8 devices use 4 Bits for the Priority Levels */
Wie man sieht findet der letzte Aufruf von
"NVIC_SetPriority(SysTick_IRQn,..." statt, während PriorityGrouping, auf
4 eingestellt ist. Danach wird PriorityGrouping aber auf 0 gestellt. Da
dieser Wert beim Schreiben wie eine Bitmaske auf die Prioritätswerte
angewand wird müsste der Prioritätswert für Systick jetzt nicht mehr
gültig sein oder zumindest einen ungültigen Wert haben können, weil er
ja nicht mit der jetzt gültigen Bitmaske geschrieben worden ist.
Sehe ich das richtig?
Wenn nicht, was kommt denn nach dieser Kette als Prirität für
Systick_IRQn heraus?
Und warum wird PriorityGrouping überhaupt mehrmals verändert?
Danke für Erleuchtung
Michael
Hallo
Danke, aber leider steht auch in dieser Ansicht bei Preemption Priority
nur 0 zur Auswahl. Sub Priority kann man da zwar auswählen, aber die
wird ja mit der Konfiguration, die bei der HAL-Initialisierung gesetzt
wird, gar nicht benutzt.
Durch die Konfiguration NVIC_PRIORITYGROUP_0 werden ja alle 4 Bits für
den Wert der Sub Priority benutzt.
Leider kann ich diese Annahme nicht so leicht prüfen, weil ich die
Funktion NVIC_EncodePriority nicht im Kopf durchrechnen kann. Ich
verliere immer bei den Bitoperationen den Überblick. :-/
core_cm4.h:
1
/**
2
* @brief Sets the priority of an interrupt.
3
* @param IRQn External interrupt number
4
* This parameter can be an enumerator of IRQn_Type enumeration
5
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f3xxxx.h))
6
* @param PreemptPriority The pre-emption priority for the IRQn channel.
7
* This parameter can be a value between 0 and 15 as described in the table CORTEX_NVIC_Priority_Table
8
* A lower priority value indicates a higher priority
9
* @param SubPriority the subpriority level for the IRQ channel.
10
* This parameter can be a value between 0 and 15 as described in the table CORTEX_NVIC_Priority_Table
11
* A lower priority value indicates a higher priority.
Michael schrieb:> und arbeite mich dabei in die Plattform ein.
Nein, das tust du nicht. Stattdessen versuchst du, mit der Software von
ST irgendwie klarzukommen. Das ist ein großer Unterschied.
Vielleicht schilderst du mal, warum du Cube und Konsorten überhaupt
verwendest. Ist es deshalb, weil es halt da ist? Oder weil du das aus
Sicht der Arduinos so brauchst oder zumindest haben willst?
Mir kommt das gepostete Beispiel ausgesprochen aufgedunsen vor, aber
damit muß man vermutlich leben, wenn man sich seine halbe Firmware von
einem Programm generieren läßt.
Wahrscheinlich ist das ganze Prioritäts-Gefummel beim generierten Code
nur auf irgendwelche Default-Einstellungen des Cube-Programms
zurückzuführen und hat sachlich gar keine Begründung. Schlußendlich
wirst du dir selber Gedanken machen müssen, ob unter deinen vielen
Interrupthandlern welche dabei sind, die besonders oder ganz besonders
wichtig sind und deshalb höher zu priorisieren sind.
Aber das ist DEINE Entwicklungs-Vorarbeit, die dir keiner abnehmen kann.
Aus meinem Text hast du sicherlich bereits herausgelesen, daß ich von
Cube und Konsorten nix halte, sondern dedizierte und in sich gekapselte
Lowlevel-Treiber bevorzuge. Das ergibt dann sehr übersichtliche
Headerfiles, wo z.B. nur sowas drinsteht:
1
externvoidSystemtick_Init(void);
Und damit wäre der ganze Systick für's aktuelle Projekt erledigt.
btw: der Systick braucht normalerweise keine hohe Priorität, sondern die
zweitniedrigste. Der SVC kriegt dann die allerniedrigste.
W.S.
...tja...wenn man HAL nicht verstanden hat bleibt nur Meckern und/oder
zweifeln....
@Michael
Die SubPriority ist genau was du suchst.
Die Preemption-Priority bezieht sich auf nur auf RTOS-Tasks.
Die Bezeichnung ist -zugegebenermassen- irreführend.
Harry L. schrieb:> Die Preemption-Priority bezieht sich auf nur auf RTOS-Tasks.> Die Bezeichnung ist -zugegebenermassen- irreführend.
Nene, auch ohne RTOS hat die Preemption-Priority eine Bedeutung:
Ein Interrupt mit einer höheren Preemption-Priority kann eine laufende
Interruptroutine mit einer niedrigeren Preemption-Priority unterbrechen
(höher bedeutet kleinere Zahl).
Die Sub-priority spielt eine Rolle, wenn mehrere Interrupts gleicher
Preemption-Priority gleichzeitig auflaufen, oder aufgelaufen sind
während ein anderer Interrupt ausgeführt wurde oder die Interrupts
gesperrt waren. Dann wird die zuerst auszuführende ISR nach der
Sub-Priority ausgewählt.
Jaja, aber ausserhalb einer Multitasking-Umgebung kann man das auf die
Sub-Priority reduzieren.
Insofern ist das schon korrekt, und CubeMX sieht das genauso.
Harry L. schrieb:> @Michael> Die SubPriority ist genau was du suchst.> Die Preemption-Priority bezieht sich auf nur auf RTOS-Tasks.> Die Bezeichnung ist -zugegebenermassen- irreführend.
Ich nehme jetzt einfach mal an, dass du Recht hast und ich etwas falsch
verstehe oder in eine falsche Richtung recherchiere.
Laut Dokumentation bestimmt ja die Preemption Priority ob Interrupts von
anderen Interrupts unterbrochen werden können, während die Sub-Priority
nur die Reihenfolge in der Warteschlange bestimmt, wenn Interrupts mit
gleichem Preemption Priority Wert schneller anfallen, als sie
abgearbeitet werden können.
Wenn es also stimmt, dass Preemption-Priority ohne RTOS keine Rolle
spielt, dann heißt das ja, dass ohne RTOS Interrupts einander
grundsätzlich nicht unterbrechen können und nur die Warteschlange
betrachtet wird.
Ist das richtig?
Wenn ja, woran liegt das?
Ich habe die Funktionen durch alle Ebenen bis zu den Registern
durchgewühlt und frage mich z.B. ob der Wert, der in SCB->AIRCR
gespeichert wird irgendeine direkte Auswirkung hat oder ob er da nur
liegt um von anderen Funktionen ausgelesen und zur Berechnung des Wertes
für SCB->SHP oder NVIC->IP benutzt wird.
Mir geht es dabei um die Frage, ob die Funktion NVIC_SetPriorityGrouping
trotzdem noch gebraucht wird, wenn man die ganze Rechnerei überspringen
und statt HAL_NVIC_SetPriority die Funktion NVIC_SetPriority benutzen
möchte. Mit den beiden Extremwerten 0 oder 4 für Prioritygroup werden ja
jeweils alle 4 Bits für einen der beiden Prioritätstypen benutzt, sodass
die Verteilung der Bits per Bitmaske nicht nötig ist.
Gruß
Michael
Harry L. schrieb:> Jaja, aber ausserhalb einer Multitasking-Umgebung kann man das auf die> Sub-Priority reduzieren.
Was soll das eigentlich heißen? Warum sollte man bare-metal nicht
wollen, daß ein IRQ einen anderen unterbricht, wenn der Stack reicht und
die eine ISR kurz und zeitkritisch ist, die andere eher unkritisch? Und
wozu sollte man dabei eine Multitasking-Umgebung brauchen?
W.S. schrieb:> Michael schrieb:>> und arbeite mich dabei in die Plattform ein.>> Nein, das tust du nicht. Stattdessen versuchst du, mit der Software von> ST irgendwie klarzukommen. Das ist ein großer Unterschied.
Sich für eine Plattform zu entscheiden heißt nun einmal, mit den
zugehörigen Tools irgendwie klarkommen zu müssen. Du brauchst nicht zu
glauben, dass ich STM32CubeMX schön fände. Mich nervt es schon, den
komplizierten Namen zu tippen und seit dem letzten Update könnte es das
hässlichste Programm auf meinem PC sein.
> Vielleicht schilderst du mal, warum du Cube und Konsorten überhaupt> verwendest. Ist es deshalb, weil es halt da ist?
Weil HAL die von ST empfohlene und zumindest rudimentär dokumentierte
API ist. Dinge die HAL nicht kann mache ich mit LL. Da ist die Doku noch
magerer, aber durch die geringere Abstaktion kann ich mir das meiste aus
der Registerdokumentation herleiten.
Weshalb ich überhaupt eine API benutze hat denselben Grund weshalb ich
auch meinen PC nicht aus selbstentwickelten Chips zusammengelötet habe:
Ich kann nicht jedes Rad für mich neu erfinden. Dafür reicht meine
Lebenszeit nicht.
Deshalb nutze ich für die Dinge, die gut unterstützt werden, hohe
Abstraktionslevel und gehe schichtweise nach unten, wenn Dinge, die ich
brauche, nicht richtig unterstützt werden oder die Abstraktion mir mehr
Arbeit macht als sie einspart.
> Oder weil du das aus> Sicht der Arduinos so brauchst oder zumindest haben willst?
Weil Abstraktion heutzutage überall benutzt wird und viel Zeit sparen
kann. Die Arduino-Umgebung verlasse ich auch nur deshalb, weil die
Einschränkungen mittlerweile die Vorteile aufwiegen und ich mich
entscheiden musste, ob ich das halbe Framework neuschreibe (blocking!
alles ist blocking implementiert! die Hauptschleife ruckelt von einer
blockenden Operation zur nächsten!) oder bei der Gelegenheit auch auf
eine leistungsfähigere Controllerfamilie wechsle.
> Mir kommt das gepostete Beispiel ausgesprochen aufgedunsen vor, aber> damit muß man vermutlich leben, wenn man sich seine halbe Firmware von> einem Programm generieren läßt.
Wie gesagt: Ich bin den kompletten Initialisierungscode durchgegangen
und habe gezielt die Funktionsaufrufe herausgeschrieben, die am Ende
darüber bestimmen, wie die Priorität des Systick-IRQs konfiguriert ist,
um mein Verständnisproblem aufzuzeigen.
Ich weiß nicht, ob das mehrfache Umschreiben der Werte nur Nebenwirkung
der geschichteten Abstraktionsebenen ist oder ob es dafür einen
technischen Grund gibt. Das war eine meiner Fragen aus dem
Ursprungsbeitrag, die bisher leider noch niemand beantworten konnte.
> Wahrscheinlich ist das ganze Prioritäts-Gefummel beim generierten Code> nur auf irgendwelche Default-Einstellungen des Cube-Programms> zurückzuführen und hat sachlich gar keine Begründung. Schlußendlich> wirst du dir selber Gedanken machen müssen, ob unter deinen vielen> Interrupthandlern welche dabei sind, die besonders oder ganz besonders> wichtig sind und deshalb höher zu priorisieren sind.>> Aber das ist DEINE Entwicklungs-Vorarbeit, die dir keiner abnehmen kann.
Das habe ich getan. Meinst du, ich hätte sonst so präzise fragen und
Auszüge aus dem API-Code zusammenstellen können?
Kann es sein, dass das Wort Arduino dich ein bisschen triggert? ;-)
> Aus meinem Text hast du sicherlich bereits herausgelesen, daß ich von> Cube und Konsorten nix halte, sondern dedizierte und in sich gekapselte> Lowlevel-Treiber bevorzuge. Das ergibt dann sehr übersichtliche> Headerfiles, wo z.B. nur sowas drinsteht:extern void Systemtick_Init> (void);
Früher hätte ich das sofort unterschrieben. Allerdings wäre ich heute
arbeitslos, wenn ich mich nicht an die Realität in der modernen
Softwareentwicklung angepasst hätte.
Keine Sorge: Ich bin von Beruf kein Mikrontrollerentwickler.
> Und damit wäre der ganze Systick für's aktuelle Projekt erledigt.> btw: der Systick braucht normalerweise keine hohe Priorität, sondern die> zweitniedrigste. Der SVC kriegt dann die allerniedrigste.
Ich brauche neben Systick auch I2C und Timer. Jeweils mit Interrupts,
weil ich die CPU-Zeit möglichst effizient nutzen will und z.B. nicht
will, dass für die Dauer einer I2C-Übertragung die Hauptschleife hängt,
wie das bei Arduino ja der Fall ist.
Für ADCs nehme ich z.B. deshalb DMA ohne Interrupts. Das mag HAL
übrigens auch nicht. Ist aber kein Problem, man kann ja alles
überschreiben.
Gruß
Michael
W.S. schrieb:> Wahrscheinlich ist das ganze Prioritäts-Gefummel beim generierten Code> nur auf irgendwelche Default-Einstellungen des Cube-Programms> zurückzuführen und hat sachlich gar keine Begründung.
Das sehe ich ganz genauso. Der ganze HAL-Kram ist für den NVIC komplett
überflüssig, weil der NVIC sowieso bei allen Cortex-M (in einem gewissen
Rahmen, z.B. bis auf die Prio-Bits) gleich ist und dafür bereits
CMSIS-Funktionen existieren. Zu welcher Verwirrung diese völlig
überflüssige Kapselung führt sieht man an folgender Aussage:
Harry L. schrieb:> Jaja, aber ausserhalb einer Multitasking-Umgebung kann man das auf die> Sub-Priority reduzieren.>> Insofern ist das schon korrekt, und CubeMX sieht das genauso.
Ich empfehle unbedingt das Priority-Grouping auf 0 zu stellen und
Subpriorities außen vor zu lassen. Das alles wurde hier auch schon
einmal durchgekaut: Beitrag "STM32 Interrupt-Prioritäten - mal wieder"
Ich empfehle auch unbedingt den dort von mir verlinkten Blog-Artikel von
Miro Samek mal zu studieren und ansonsten natürlich den Cortex-M Guide
von Joseph Yiu.
Harry L. schrieb:> Jaja, aber ausserhalb einer Multitasking-Umgebung kann man das auf die> Sub-Priority reduzieren.
Sobald man einen Interrupt enabled hat man eine Multitasking-Umgebung.
Das liegt in der Natur der Sache.
Ich habe mich bisher mit den Interrupt Prioritäten nur theoretisch
beschäftigt, weil die Default Vorgaben der NVIC Register bisher für alle
meine Basteleien passten.
Michael schrieb:> Sich für eine Plattform zu entscheiden heißt nun einmal, mit den> zugehörigen Tools irgendwie klarkommen zu müssen.
Nein, das sind optionale Tools und in dem speziellen Fall sind es Tools
die dafür gedacht sind daß Du Dich eben nicht mit der eigentlichen
Platform beschäftigen mußt. Unterm Strich gelingt diesen Tools das aber
nicht und Du kämpfst dann an zwei Fronten.
Lass das also weg und fang mit nem einfachen "Hello world" ohne HAL und
ohne Cube an, nimm eine generische IDE für ARM Controller, arbeite Dich
von dort aus hoch, gerne auch durch Stellen der richtigen Fragen,
benutze als einzige Doku das Reference Manual des Chips und ergänzend
das Manual des ARM-Cores.
Nach dem Einstiegsschock der maximal eine Woche andauert macht sich ein
Gefühl der Erleichterung breit, sehr viele Konzepte werden Dir auch
seltsam vertraut vorkommen von kleineren oder älteren Controllern mit
denen Du früher gearbeitet hast, Lichter werden Dir aufgehen von denen
Du gar nicht wußtest daß sie existieren, DANN (und nur dann) wirst Du
bemerken was es wirklich bedeutet die Plattform kennengelernt zu haben,
Kontrolle zu haben, zu wissen was zu tun ist und wie es zu tun ist.
All diese Erfahrungen kann Dir dieses Ganzkörperkondom namens CubeMX/HAL
niemals bieten, da stocherst Du nur auf einer Gummioberfläche herum und
kannst die darunter liegenden Formen nur schwer erahnen, nicht richtig
greifen und nicht richtig damit interagieren.
Bernd K. schrieb:> benutze als einzige Doku das Reference Manual des Chips und ergänzend> das Manual des ARM-Cores.
Bitte auch das Datenblatt und das Errata Sheet. Die Drei Dokumente
gehören zusammen.
Hier wird oft hervorgehoben, dass die Konfiguration der Takt-Versorgung
extrem kompliziert sei. Dem möchte ich widersprechen. Für den Einstieg
hilft es zu wissen, dass der CPU Kern standardmäßig mit dem 8MHz R/C
Oszillator getaktet wird. Takt für Peripherie muss man je nach Bedarf in
den RCC Registern einschalten. Damit kann man schon viele nützliche
Programme schreiben.
Wenn man damit klar kommt, kann man mal als nächstes versuchen, auf
externen Quarz umzuschalten. Dazu muss man wissen, dass der Oszillator
nach dem Start eine Weile braucht, bis er verwendbar ist. Also starten,
warten, dann als Taktquelle verwenden.
Nächster Schritt wäre, den Takt mittels PLL zu vervielfachen. Auch hier
muss man abwarten, bis die PLL bereit ist, bevor man sie verwendet.
Dann sollte man bedenken, dass der Flash Speicher nicht die maximale
Taktfrequenz unterstützt. Man muss ab einer gewissen Takrfrequenz im
FLASH->ACR Register Waitstates einstellen.
Auch die Taktfrequenz der Peripherie ist teilweise eingeschränkt, so
dass man einen Teilerfaktor einstellen muss.
Ich gucke mir die grafische Darstellung der Takt-Konfiguration gerne im
CubeMX an, programmiere es danach aber "zu fuß".
Bernd K. schrieb:> Nein, das sind optionale Tools und in dem speziellen Fall sind es Tools> die dafür gedacht sind daß Du Dich eben nicht mit der eigentlichen> Platform beschäftigen mußt. Unterm Strich gelingt diesen Tools das aber> nicht und Du kämpfst dann an zwei Fronten.>> Lass das also weg und fang mit nem einfachen "Hello world" ohne HAL und> ohne Cube an, nimm eine generische IDE für ARM Controller, arbeite Dich> von dort aus hoch, gerne auch durch Stellen der richtigen Fragen,> benutze als einzige Doku das Reference Manual des Chips und ergänzend> das Manual des ARM-Cores.>> Nach dem Einstiegsschock der maximal eine Woche andauert macht sich ein> Gefühl der Erleichterung breit, sehr viele Konzepte werden Dir auch> seltsam vertraut vorkommen von kleineren oder älteren Controllern mit> denen Du früher gearbeitet hast, Lichter werden Dir aufgehen von denen> Du gar nicht wußtest daß sie existieren, DANN (und nur dann) wirst Du> bemerken was es wirklich bedeutet die Plattform kennengelernt zu haben,> Kontrolle zu haben, zu wissen was zu tun ist und wie es zu tun ist.>> All diese Erfahrungen kann Dir dieses Ganzkörperkondom namens CubeMX/HAL> niemals bieten, da stocherst Du nur auf einer Gummioberfläche herum und> kannst die darunter liegenden Formen nur schwer erahnen, nicht richtig> greifen und nicht richtig damit interagieren.
Bernd, deinen Beitrag möchte ich am liebsten DOPPELT und DREIFACH
unterstrichen einem jeglichen Entwickler in großen Lettern an die Wand
gepinnt haben! Du hast es genau getroffen, also danke dafür.
Michael schrieb:>> Nein, das tust du nicht. Stattdessen versuchst du, mit der Software von>> ST irgendwie klarzukommen. Das ist ein großer Unterschied.>> Sich für eine Plattform zu entscheiden heißt nun einmal, mit den> zugehörigen Tools irgendwie klarkommen zu müssen. Du brauchst nicht zu> glauben, dass ich STM32CubeMX schön fände. Mich nervt es schon, den> komplizierten Namen zu tippen und seit dem letzten Update könnte es das> hässlichste Programm auf meinem PC sein.
Warum benutzt du dann sowas? Bernd hat das Ganze schon sehr treffend
"Ganzkörper-Kondom" genannt. Bissel frech, aber sehr treffend.
Ich habe hier schon ein paarmal Zeugs gepostet, wo ich vorgeturnt habe,
wie man:
- ohne Software von ST oder andere Firmen und
- ohne Cmsis und
- ohne irgend eine IDE und
- ohne Fremdcode und
- bei manchen Chips sogar ohne JTAG/SWD
zu einer übersichtlichen und funktionalen Basis-Firmware kommt, die in
weiten Teilen sogar plattform- und projekt-unabhängig ist. Lediglich die
Lowlevel-Treiber müssen an die Plattform angepaßt werden und der
Konfigurationsunit an das aktulle Projekt. So macht man das, wenn man
jahrelang zwischen den Chips von NEC, Fujitsu, NXP nen Spagat machen muß
und obendrein nicht nur Software macht, sondern eigentlich
Geräteentwickler ist.
Also stell dich nicht so an - und laß dich nicht von Herstellerfirmen
auf deren Produkte festnageln.
W.S.
Harry L. schrieb:> Hier kommen bei HAL-Themen nur regelmässig die selben Dogmen von vor> 20J.
Vor 20 Jahren gab es ganz ohne Dogma weder die SPL noch die HAL.
Michael schrieb:> Deshalb nutze ich für die Dinge, die gut unterstützt werden, hohe> Abstraktionslevel und gehe schichtweise nach unten, wenn Dinge, die ich> brauche, nicht richtig unterstützt werden oder die Abstraktion mir mehr> Arbeit macht als sie einspart.
NVIC sind bei mir per default ganze drei Zeilen Code. Aber im Gegensatz
zu HAL habe ich verstanden, wie es funktioniert udn somit Lebenszeit
gewonnen.
Jens schrieb:> #define SET_ICPR(a) NVIC->ICPR[(a)/32] |= (1<<((a)%32));> #define SET_ISER(a) NVIC->ISER[(a)/32] |= (1<<((a)%32));> #define SET_IP(a,b) NVIC->IP[(a)/4] |= ((b<<4)<<(8*((a)%4)));>> SET_ICPR(DMA1_Stream2_IRQn);> SET_ISER(DMA1_Stream2_IRQn);> SET_IP(DMA1_Stream2_IRQn, 3);
Klasse!
Das ist so sauber dokumentiert, daß jeder sofort weiß, was dort abgeht
und es für jeden Anfänger ein Genuss ist :-(
Harry L. schrieb:> @Michael, stell deine Fragen besser im ST-Forum!> Hier kommen bei HAL-Themen nur regelmässig die selben Dogmen von vor> 20J.
Es geht hier nicht um Dogmen, sondern darum, dass HAL die Sache mit den
IRQ-Prios komplizierter macht als sie (ohnehin schon) ist und deine
Aussage bezüglich Subpriorities und Multitasking einfach nicht richtig
war.
Christopher J. schrieb:> Ich empfehle unbedingt das Priority-Grouping auf 0 zu stellen und> Subpriorities außen vor zu lassen. Das alles wurde hier auch schon> einmal durchgekaut: Beitrag "STM32 Interrupt-Prioritäten - mal wieder"
Wenn das Grouping auf 0 steht werden doch ausschließlich Sub-Priorities
benutzt. Meinstest du 4?
> Ich empfehle auch unbedingt den dort von mir verlinkten Blog-Artikel von> Miro Samek mal zu studieren und ansonsten natürlich den Cortex-M Guide> von Joseph Yiu.
Inwiefern kann man eine generische Cortex-M Dokumentation eigentlich auf
STM32 Mikrocontroller anwenden? Ist das immer eine untermenge dessen was
der controller bietet oder implementiert ST eine Untermenge der Cortex-M
Funktionalität? Ich möchte vermeiden, mich in Dokumentation zu
verlaufen, die sich zwar mit meinem System überschneidet und dadurch
oberflächlich passend aussieht, aber in den Details hinten und vorne
nicht stimmt.
Gruß
Michael
Michael schrieb:> Inwiefern kann man eine generische Cortex-M Dokumentation eigentlich auf> STM32 Mikrocontroller anwenden? Ist das immer eine untermenge dessen was> der controller bietet oder implementiert ST eine Untermenge der Cortex-M> Funktionalität? Ich möchte vermeiden, mich in Dokumentation zu> verlaufen, die sich zwar mit meinem System überschneidet und dadurch> oberflächlich passend aussieht, aber in den Details hinten und vorne> nicht stimmt.
Die Cortex-M Dokumentation kannst du voll auf den STM32 Controller
anwenden, allerdings ist da ja nur der Kern Dokumentiert, der von ST
lizenziert und eingebaut wird.
Die Peripherals sind von ST entwickelt und sind im ReferenceManual
dokumentiert.
Bernd K. schrieb:> Michael schrieb:>> Sich für eine Plattform zu entscheiden heißt nun einmal, mit den>> zugehörigen Tools irgendwie klarkommen zu müssen.>> Nein, das sind optionale Tools und in dem speziellen Fall sind es Tools> die dafür gedacht sind daß Du Dich eben nicht mit der eigentlichen> Platform beschäftigen mußt. Unterm Strich gelingt diesen Tools das aber> nicht und Du kämpfst dann an zwei Fronten.
Z.B. die Clock Configuration bekäme ich zu Fuß auf keinen Fall hin.
Alleine der Anblick davon in der grafischen Darstellung löst schon
Fluchtgedanken aus. Sowas kompliziertes mit so vielen Abhängigkeiten
hätte ich nie erwartet. Ich sehe ja beim Probieren mit STM32CubeMX, dass
fast jede Änderung eines Wertes an 2 anderen Stellen zu Inkompatibilität
führt. Wenn ich das im Code machen würde, hätte der Controller
wahrscheinlich niemals funktioniert und ich hätte irgendwann aufgegeben.
Deshalb denke ich, dass ST, wenn man schon ein derart kompliziertres
Taktsystem baut, auch ein Werkzeug liefern muss, um damit umzugehen.
> Lass das also weg und fang mit nem einfachen "Hello world" ohne HAL und> ohne Cube an, nimm eine generische IDE für ARM Controller, arbeite Dich> von dort aus hoch, gerne auch durch Stellen der richtigen Fragen,> benutze als einzige Doku das Reference Manual des Chips und ergänzend> das Manual des ARM-Cores.
Im Prinzip tue ich das ja, nur dass ich zusätzlich nach der optimalen
Abstraktionsstufe suche, um mir das Leben nicht schwerer als nötig zu
machen.
Ich bin jetzt schon einige Tage nur damit beschäftigt, den besten Ansatz
für die I2C-Kommunikation zu finden. Vorher habe ich viel Zeit mit den
Timern verbracht. Habe HAL probiert, auch probeweise rein auf
Registerebene etwas gebaut und mich dann für LL als am besten passende
API für die Timer entschieden. Dabei habe ich einen Bug in STM32CubeMX
gefunden, gemeldet und bestätigt bekommen und konnte das Thema Timer
erstmal abhaken.
Das nächste Thema waren ADCs. Da ist die Dokumentation besonders
schlecht. Ich weiß bis heute noch nicht, warum man bei programmatischem
Kanalwechsel nach jedem Wechsel die Kalibrierung neu laufen lassen muss,
während bei DMA-gesteuertem Durchschalten der Kanäle keine Kalibirerung
zwischen den Messungen nötig ist. Wahrscheinlich ist die Kalibirierung
überhaupt nicht zwischen den Kanalwechseln nötig und die Dokumentation
ist einfach nur falsch. Ist aber egal, DMA funktioniert prima.
Jetzt bin ich eben mit I2C beschäftigt. Wenn ich das habe, habe ich
alles zusammen, was ich brauche, um mein Projekt zu übertragen.
> Nach dem Einstiegsschock der maximal eine Woche andauert macht sich ein> Gefühl der Erleichterung breit, sehr viele Konzepte werden Dir auch> seltsam vertraut vorkommen von kleineren oder älteren Controllern mit> denen Du früher gearbeitet hast, Lichter werden Dir aufgehen von denen> Du gar nicht wußtest daß sie existieren, DANN (und nur dann) wirst Du> bemerken was es wirklich bedeutet die Plattform kennengelernt zu haben,> Kontrolle zu haben, zu wissen was zu tun ist und wie es zu tun ist.
Das Gefühl kenne ich. Es kam mit Arduino und Atmel aber nicht nach einer
Woche, sondern nach 1,5 Jahren. Ich bin wahrscheinlich einfach ein
Bisschen langsam. Deshalb muss ich damit leben, nicht alles von unten
aufrollen zu können. Irgendwann werde ich aber STM32 mindestens so weit
verstanden haben wie Atmel AVR. Das heißt, ich werde API-Funktionen bei
Problemen einfach um- oder neuschreiben können.
> All diese Erfahrungen kann Dir dieses Ganzkörperkondom namens CubeMX/HAL> niemals bieten, da stocherst Du nur auf einer Gummioberfläche herum und> kannst die darunter liegenden Formen nur schwer erahnen, nicht richtig> greifen und nicht richtig damit interagieren.
Die Clock-Konfiguration ist ein blutrünstiges Monster, das in seinem
Käfig nur darauf wartet, freigelassen zu werden und Chaos und Verderben
über mein Projekt zu bringen. - Glaube ich...
Gruß
Michael
Harry L. schrieb:> @Michael, stell deine Fragen besser im ST-Forum!> Hier kommen bei HAL-Themen nur regelmässig die selben Dogmen von vor> 20J.>> https://community.st.com/
Tue ich ja auch. Aber mit einem Forum, in dem man immer nur die Threads
der letzten paar Stunden sieht und alles weitere nur häppchenweise durch
Klickerei auf "Read More" erreicht, sodass jede Diskussion nach 2 Tagen
zwangfsläufig tot ist kann ich mich nicht anfreunden.
Außerdem habe ich im ST-Forum auch schon die Empfehlung bekommen, mit
meinen komplizierten Timersachen besser auf HAL zu verzichten.
Irgendwann mache ich das auch mal. Im Moment brauche ich die
Hilfestellungen aber noch, um durch gelegentliche Erfolgserlebnisse
meine Motivation zu erhalten.
Gruß
Michael
Stefanus F. schrieb:> Harry L. schrieb:>> Hier kommen bei HAL-Themen nur regelmässig die selben Dogmen von vor>> 20J.>> Vor 20 Jahren gab es ganz ohne Dogma weder die SPL noch die HAL.
Damals wurden aber schon C++ Fans verdammt, weil C besser sei, woraufhin
die Assembler-Fans über die C-Fans hergefallen sind, nur um die echten
Profis auf den Plan zu rufen, die erklätren, dass Programme nicht
getippt, sondern geätzt werden.
Jens schrieb:> NVIC sind bei mir per default ganze drei Zeilen Code. Aber im Gegensatz> zu HAL habe ich verstanden, wie es funktioniert udn somit Lebenszeit> gewonnen.> #define SET_ICPR(a) NVIC->ICPR[(a)/32] |= (1<<((a)%32));> #define SET_ISER(a) NVIC->ISER[(a)/32] |= (1<<((a)%32));> #define SET_IP(a,b) NVIC->IP[(a)/4] |= ((b<<4)<<(8*((a)%4)));>> SET_ICPR(DMA1_Stream2_IRQn);> SET_ISER(DMA1_Stream2_IRQn);> SET_IP(DMA1_Stream2_IRQn, 3);
Wenn ich mal so weit bin, werde ich das tun. Im Moment schaffe ich das
noch nicht. Aber ich lerne.
Christopher J. schrieb:> Harry L. schrieb:>> @Michael, stell deine Fragen besser im ST-Forum!>> Hier kommen bei HAL-Themen nur regelmässig die selben Dogmen von vor>> 20J.>> Es geht hier nicht um Dogmen, sondern darum, dass HAL die Sache mit den> IRQ-Prios komplizierter macht als sie (ohnehin schon) ist und deine> Aussage bezüglich Subpriorities und Multitasking einfach nicht richtig> war.
Ist meine Ansicht denn richtig, dass man, wenn man für die Gruppierung
einen der beiden Extremwerte (0 oder 4) benutzt, auch einfach statt
HAL_NVIC_SetPriority die Funktion NVIC_SetPriority benutzen kann,
wodurch ein großer Teil der undurchsichtigen Bit-Rechnerei entfällt?
Gruß
Michael
Michael schrieb:> Inwiefern kann man eine generische Cortex-M Dokumentation eigentlich auf> STM32 Mikrocontroller anwenden? Ist das immer eine untermenge dessen was> der controller bietet oder implementiert ST eine Untermenge der Cortex-M> Funktionalität?
In deinem Fall, also wenn es um den NVIC geht, dann kannst du getrost zu
einer generischen Doku greifen. Der einzige Punkt in dem sich die
Hersteller und deren Produktfamilien unterscheiden ist die Anzahl der
implementierten Prio-Bits. Subpriorities braucht man in 99% der Fälle
nicht. Ein NVIC_SetPriorityGrouping(0); beendet den ganzen Spuk und
setzt den Controller auf die sinnvollen Default-Werte. Ab da gibt es nur
noch Preempt-Priorities, die man mit NVIC_SetPriority() setzen kann.
Hier ist nochmal der direkte Link zum Blog-Artikel:
https://embeddedgurus.com/state-space/2014/02/cutting-through-the-confusion-with-arm-cortex-m-interrupt-priorities/
Lies dir aber am besten nochmal den von mir verlinkten Thread komplett
durch.
Michael schrieb:> Z.B. die Clock Configuration bekäme ich zu Fuß auf keinen Fall hin.> Alleine der Anblick davon in der grafischen Darstellung löst schon> Fluchtgedanken aus.> Die Clock-Konfiguration ist ein blutrünstiges Monster, das in seinem> Käfig nur darauf wartet, freigelassen zu werden und Chaos und Verderben> über mein Projekt zu bringen.
Dann fange doch mal mit einem einfacheren STM32 Modell an. Beim
STM32F103 ist das durchaus überschaubar.
>Ich bin jetzt schon einige Tage nur damit beschäftigt,
> den besten Ansatz für die I2C-Kommunikation zu finden.
Selbst Schuld, bei der Einstellung. Es gibt nicht den einen besten
Ansatz. Zudem kann eine technisch super ausgefuchste Software ziemlich
wertlos sein, wenn du sie nicht durchblickst.
Für das aktuelle Projekt ist immer der einfachste funktionierende Ansatz
der Beste. Was am einfachsten ist, hängt von dem Know-How der
Projektmitglieder ab. Das ist mein Stil, nach dem ich Software
entwickle.
Michael schrieb:> Ist meine Ansicht denn richtig, dass man, wenn man für die Gruppierung> einen der beiden Extremwerte (0 oder 4) benutzt, auch einfach statt> HAL_NVIC_SetPriority die Funktion NVIC_SetPriority benutzen kann,> wodurch ein großer Teil der undurchsichtigen Bit-Rechnerei entfällt?
Standardmässig ist die Gruppierung deaktiviert. Ich kann mir allerdings
vorstellen, dass die HAL ein anderes Verständnis von "Standard" hat, als
der Chip selbst (via NRST).
Stefanus F. schrieb:> Standardmässig ist die Gruppierung deaktiviert. Ich kann mir allerdings> vorstellen, dass die HAL ein anderes Verständnis von "Standard" hat, als> der Chip selbst (via NRST).
Das war ja doch das eigentliche Thema. Scheinbar ist es auch noch so,
dass ST die Bedeutung des Priority-Groupings gegenüber den
CMSIS-Funktionen umgedreht hat, d.h. bei vier Prio-Bits, wie etwa beim
F3 ist
Während also in der CMSIS-Funktion die Subprio-Bits angegeben werden,
sind es in der HAL-Funktion die Preempt-Bits. Wenn man nun also von
"PriorityGrouping von vier" spricht, dann muss man explizit angeben in
welcher Art man das meint. Na herzlichen Glückwunsch ST.
m.n. schrieb:> Klasse!> Das ist so sauber dokumentiert, daß jeder sofort weiß, was dort abgeht> und es für jeden Anfänger ein Genuss ist :-(
Die Dokumentation steht im Datenblatt des Controllers. Von mir aus
benennt man noch die Makros um, so dass diese lesbarer werden. Der Rest
hat dort im Quellcode wirklich gar nichts zu suchen.
Pending Interrupt zurücksetzen. Interrupt aktivieren und Priorität
festlegen (mit einer Zahl..).
Michael schrieb:> Z.B. die Clock Configuration bekäme ich zu Fuß auf keinen Fall hin.> Alleine der Anblick davon in der grafischen Darstellung löst schon> Fluchtgedanken aus. Sowas kompliziertes mit so vielen Abhängigkeiten> hätte ich nie erwartet.
...
> Ich bin wahrscheinlich einfach ein> Bisschen langsam. Deshalb muss ich damit leben, nicht alles von unten> aufrollen zu können.
...
> Die Clock-Konfiguration ist ein blutrünstiges Monster, das in seinem> Käfig nur darauf wartet, freigelassen zu werden und Chaos und Verderben> über mein Projekt zu bringen. - Glaube ich...
Das hat nichts mit Langsamkeit zu tun, sondern einfach nur mit ein
bissel innerer Disziplin und Gründlichkeit.
Und die Clock-Konfiguration ist auch kein blutrünstiges Monster. Ich
hänge dir mal ein Beispiel dran, woan du sehen kannst, wie man so etwas
anpacken kann - was du aber auch in diesem Falle als generische
Konfiguration für deine Projekte mit dem STM32F302 benutzen kannst. Das
geht von einem 12 MHz Quarz aus und bringt die Systemclock auf 72 MHz
und die USB-Clock auf 48 MHz.
Einen passenden USB-VCP Treiber für diesen Chip hab ich auch schon mal
hier gepostet. Und die üblichen Verdächtigen wie Treiber für UART und
SysTick usw. hab ich auch vorrätig. Mit der Zeit sammelt sich nämlich so
ein Portfolio an Quellen an und macht dann das Aufsetzen eines neuen
Projektes leicht.
Das ist quasi ne Steilvorlage für dich und damit solltest du
eigentlich aus dem Knick kommen. Also nochmal: stell dich nicht so an.
Und vor dem Ausprobieren von I2C und ADC's kommt erstmal der Systemstart
und das Aufsetzen der Pins und der Takte, dann die Kommunikation mit dem
PC (um ohne intrusiven Debugger mit dem Chip kommunizieren zu können).
So herum!
W.S.
Bernd K. schrieb:> Lass das also weg und fang mit nem einfachen "Hello world" ohne HAL und> ohne Cube an, nimm eine generische IDE für ARM Controller, arbeite Dich> von dort aus hoch, gerne auch durch Stellen der richtigen Fragen,> All diese Erfahrungen kann Dir dieses Ganzkörperkondom namens CubeMX/HAL> niemals bieten, da stocherst Du nur auf einer Gummioberfläche herum und> kannst die darunter liegenden Formen nur schwer erahnen, nicht richtig> greifen und nicht richtig damit interagieren.
Sure.
Lass beim PC Windows auch weg, ist ja eh nur ein Ganzkörperkondom, mach
dir selbst einen übersichtlichen und viel schnelleren Graphic OS,
arbeite dich dann langsam hoch etc...
Was für ein Blödsinn.
In DOS hat man die InterruptsVectors noch auf eigene Routinen
umgeleitet, diese Routinen meistens selber in Assembler geschrieben,
aber:
In PC-VisualStudio programmierst du die Buttons, ServiceControllers,
Timers etc. auch nicht selbst, sondern nimmst die fertig aus der
Bibliothek, von den untenliegenden Layers (und deren Verständnis) gar
nicht zu reden.
80% der Dinge macht der HAL gut und mehr als gut genug. Wer sich für
einen sooo großen Spezialisten hält und unbedingt die restlichen 20%
ausreizen muss, kann die entsprechenden HAL Routinen und Definitionen
ganz schnell seinen Bedürfnisen anpassen und das ohne CubeMX und HAL
so großspurig (und unnötig) anzuspucken.
Vor allem da CubeMX und HAL das alles mit einem einzigen Mausclick
machen...
Marc V. schrieb:> In DOS ...
Darum geht es hier nicht.
Marc V. schrieb:> 80% der Dinge macht der HAL gut
Mag sein. Hier geht es um die anderen 20%.
Marc V. schrieb:> ohne CubeMX und HAL> so großspurig (und unnötig) anzuspucken.
Ich finde es ja wirklich faszinierend wie manche Leute sich persönlich
angegriffen fühlen, blos weil man die HAL-NVIC-Routinen für überflüssig
und zu kompliziert erklärt.
Wo genau ist denn jetzt der Vorteil gegenüber den (ohnehin vorhandenen)
CMSIS-Funktionen?
Christopher J. schrieb:> Ich finde es ja wirklich faszinierend wie manche Leute sich persönlich> angegriffen fühlen, blos weil man die HAL-NVIC-Routinen für überflüssig> und zu kompliziert erklärt.
Es ging um die Init Routinen, also nur einmal am Anfang, deswegen ist
es auch ziemlich egal was HAL da vorher rumfummelt.
Und eine eigene Init-Routine am Programmanfang macht das alles wie
gewünscht, unabhängig davon, was HAL vorher gemacht hat.
Kostet schlimmstenfalls einige dutzend Bytes und ein paar us mehr
einmal am Anfang.
Mw E. schrieb:> Die ganzen Magic Numbers sind ja graunevoll!
Ich werde dich bei passender Gelegenheit mal gebührend bedauern. Schade,
daß du Zahlen nicht lesen kannst. Mußt halt ein bissel üben, dann gibt
sich das vielleicht.
So eine Art der Dyslexie ist schon seltsam. Aber sie paßt irgendwie zu
C-Programmierern, die besser mit Interpunktionszeichen als mit richtigen
Wörtern zurechtkommen.
W.S.
Leute, müsst ihr euch denn immer nur ampampen?
Ich finde es sehr nett, dass W.S. uns hier Starthilfe für die
Programmierung ohne HAL gibt. Wer lieber die HAL verwenden möchte soll
das ruhig tun. Und wem sein Programmierstil nicht gefällt, kann es ja
umschreiben.
Einem geschenkten Gaul schau mal nicht ins Maul. Vor allem aber
beschimpft man nicht den Wohltäter!
An W.S.: Lass die Undankbaren doch meckern, du kann sie ohnehin nicht
zufrieden stellen. Es sind doch immer die gleichen, die aus ihrer Sicht
alles besser wissen und andere unfreiwillig missionieren.
So, und jetzt setze ich einen 10er Dübel um eine Jacke aufzuhängen. Wer
mich jetzt dafür beschimpfen will - bitte, aber dann bei mir zuhause,
dann sieht er auch den Grund dafür.
Wer es erstmal überschaubar halten will und mit 14 Prioritäten klarkommt
(plus Systick), kann auch einfach Priority_Group_4 wählen und dann mit
den Subprioritäten von 0 bis 0x0F arbeiten.
Austesten lässt sich das (so mir unfreiwillig passiert) mit dem Systick.
Wer eine Delay Routine z.B. in einer EXTI ISR aufruft, blockiert sich
das ganze Programm,hehehe.
Dreht man dann Systick auf Priorität 0, gehts wieder :-)
Macht man natürlich nicht, ist aber lehrreich.
Stefanus F. schrieb:> Ich finde es sehr nett, dass W.S. uns hier Starthilfe für die> Programmierung ohne HAL gibt. Wer lieber die HAL verwenden möchte soll> das ruhig tun. Und wem sein Programmierstil nicht gefällt, kann es ja> umschreiben.
Natürlich.
Nur soll man nicht so abschätzend über HAL und CubeMX reden.
Und noch einmal:
a) Es wird in C programmiert, nicht in Assembler.
b) Es ging um die Init Routinen.
Zu a) Bei 99% des Programms kommt es auf die Programmierfähigkeiten
in C und nicht auf die paar dutzend Bytes beim Init.
Zu b) Nicht alle Programme benutzen die selben Einstellungen, also
muß man das in jedem Einzelfall doch anders machen, da steht man mit
W.S. header und HAL header genauso dumm da und muß gewisse Sachen
sowieso ändern.
Aber es wird doch nur einmal am Anfang gemacht, nicht dauernd.
Und mit CubeMX sehe ich sofort wo ich was ändern muss und muß mich
nicht erst durch tausende von Linien durchkämpfen.
Außerdem werden mir in CubeMX ev. Konflikte sofort in Rot angezeigt
und die kommen beim STM ziemlich oft vor.
Aber wie gesagt - jedem das seine, nur bitte nicht behaupten, daß
ihre Lösung die beste und einzig richtige ist...
> Nicht alle Programme benutzen die selben Einstellungen, also> muß man das in jedem Einzelfall doch anders machen, da steht man mit> W.S. header und HAL header genauso dumm da
Das sind ja auch nur Beispielprogramme. Die kann und darf man editieren.
(4<<18)|// PLL Teiler: 4--> x6, also 12MHz*6-->72MHz
6
(7<<24)|// 7 = PLL:2 an MCO = PA.8 zur Beobachtung
7
(1<<22)|// USBPRES, 72MHz/1.5-->48MHz
8
0;
Da darfste bei jeder Änderung ins Datenblatt gucken um für ein neues
Projekt was zu ändern.
Irgendwann zieht man dann auch mal ausversehen die Kommentare nicht mit,
dann sagen Code und Kommentare was anderes.
Da hat man dann richtig Spaß den Fehler zu finden.
Das tut doch nicht weh zB (1<<16) als define/enum zu setzen damit es nen
Namen hat und einmal draufgucken sagt was es tut.
Oder die 11 als APB2_TEILER_SHIFT zu setzen oder noch besser die (4<<11)
als APB2_DIV2 zu definieren/enumerieren.
Bei uns an der Uni gibts für sone Magic Numbers direkt mal Punktabzug.
P.S.
Warum ich so bissig reagiere @Stefanus?
Naja wer schreibt denn hier andauernd Leuten vor wie sie zu coden haben
und versucht zu missionieren?
Da erinnere ich mich an den Fred von dem projekt eines Moderatirs, wo er
diesen dann gekapert und versaubeutelt hat.
Ja das war W.S., erst sowas machen aber dann selber sone Grütze
hochladen ;)
P.P.S.
Diskussionen zu HAL oder Selbstbau waren vom TE nicht erwünscht, daher
werde ich dazu auch nix sagen ;)
(Ich nutze die HAL privat nicht, muss es aber auf Arbeit, daher weis ich
wie schlecht die ist...)
Mw E. schrieb:> Da darfste bei jeder Änderung ins Datenblatt gucken
Was ich ohnehin empfehlen würde.
> Irgendwann zieht man dann auch mal ausversehen die Kommentare nicht mit
Ganz schlecht. Irreführende Kommentare sind schlimmer, als keine.
Dennoch würde ich nicht dazu raten, auf Kommentare zu verzichten.
> Naja wer schreibt denn hier andauernd Leuten vor wie> sie zu coden haben und versucht zu missionieren?
Die Texte von W.S. kommen häufig so an, als ob er alle Leute die es
anders machen für doof hält. Aber so meint er es nicht. Ich kenne ihn
inzwischen lange genug, um das mit Sicherheit zu wissen. Es fällt ihm
genau wie mir nur schwer, sich diplomatisch/angemessen auszudrücken.
Matthias S. schrieb:> Wer es erstmal überschaubar halten will und mit 14 Prioritäten klarkommt> (plus Systick), kann auch einfach Priority_Group_4 wählen und dann mit> den Subprioritäten von 0 bis 0x0F arbeiten. Austesten lässt sich das (so> mir unfreiwillig passiert) mit dem Systick. Wer eine Delay Routine z.B.> in einer EXTI ISR aufruft, blockiert sich das ganze Programm,hehehe.> Dreht man dann Systick auf Priorität 0, gehts wieder :-)> Macht man natürlich nicht, ist aber lehrreich.
In STs HAL-Sprech bedeutet Priority_Group_4 aber, dass alle vier Bits
für Preemption sind. Zwei ISRs mit gleicher Preempt- und
unterschiedlicher Subpriority können sich nämlich nicht gegenseitig
unterbrechen. Wenn es nur Subpriorities wären, dann würde der EXTI bis
zum Sanktnimmerleinstag auf den Systick warten. Subpriorities sind nur
dafür da, dass wenn zwei Interrupts mit gleicher Preemptionpriority
gleichzeitig anstehen, der eine Interrupt gegenüber dem anderen
bevorzugt wird. Es gibt ohnehin nur sehr wenige Fälle, wann so etwas
auftreten kann, etwa wenn eine ISR mit höherer Dringlichkeit
abgearbeitet wird. Wenn man jedoch möchte, dass die eine ISR vor der
anderen abgearbeitet wird, dann kann man eben genauso gut auf Preemption
setzen und das mit den Subpriorities komplett sein lassen. Das war
übrigens auch die Quintessenz des Blogartikels den ich hier schon
mehrfach verlinkt hatte.
W.S. schrieb:> Ich> hänge dir mal ein Beispiel dran,
Das ist ein ausgesprochen schlechtes Beispiel. Ich kann zwar erahnen daß
Du versuchst ohne generierten Code auszukommen und selbst zu verstehen
wie es funktioniert aber wie Du den hingeschrieben hast graust es die
Sau. Echt, wirklich. Davon bekomm ich Hautausschlag.
Wir können das aber schrittweise verbessern: Als erstes fängst Du mal an
alle literalen Konstanten die ungleich 1 oder 0 sind zu eliminieren. Ich
spreche über so gruselige unwartbare Monstrositäten wie zum Beispiel
sowas:
1
// RCC_CFGR fertig setzen bis auf PLL-Auswahl
2
RCC_CFGR=(1<<16)|// Quarz-Oszi als Input für PLL
3
(4<<11)|// APB2 Vorteiler auf :2 (72-->36 MHz)
4
(4<<8)|// APB1 Vorteiler auf :2 (72-->36 MHz)
5
(0<<17)|// Quarz nicht :2 teilen vor der PLL
6
(4<<18)|// PLL Teiler: 4--> x6, also 12MHz*6-->72MHz
7
(7<<24)|// 7 = PLL:2 an MCO = PA.8 zur Beobachtung
8
(1<<22)|// USBPRES, 72MHz/1.5-->48MHz
9
0;
Diesen ganzen Bits sind bereits in den CMSIS-Headern namentlich
definiert, und zwar unter den selben Namen wie sie im Handbuch stehen.
Es ist vollkommen unleserlich und inakzeptabel das als magische
Konstanten mitten in den Code reinzuschreiben.
Also räum das bitte erst mal auf und mach das richtig. Vorher braucht
man da gar nicht weiter drüber zu diskutieren.