Forum: Mikrocontroller und Digitale Elektronik STM32F3: IRQ-Prioritäten


von Michael (Gast)


Lesenswert?

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:
1
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
2
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
3
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);

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 */
4
#define  TICK_INT_PRIORITY            ((uint32_t)0)    /*!< tick interrupt priority (lowest by default)  */            
5
6
int main(void)
7
  HAL_Init();
8
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
9
    HAL_InitTick(TICK_INT_PRIORITY);
10
      HAL_SYSTICK_Config(SystemCoreClock / (1000U / 1U))
11
        SysTick_Config(SystemCoreClock / (1000U / 1U));
12
          NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
13
      HAL_NVIC_SetPriority(SysTick_IRQn, 0U, 0U);
14
        NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0U, 0U));
15
    HAL_MspInit();
16
      HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

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

von Harry L. (mysth)


Lesenswert?

Du kannst in der Systemview beim NVIC die Sub-Priority einstellen.
Die Premption-Priority kommt erst ins Spiel, wenn du FreeRTOS mit 
einbindest.

von Michael (Gast)


Lesenswert?

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.
12
  * @retval None
13
  */
14
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
15
{
16
  uint32_t prioritygroup = 0x00U;
17
  
18
  /* Check the parameters */
19
  assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
20
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
21
  
22
  prioritygroup = NVIC_GetPriorityGrouping();
23
  
24
  NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
25
}
26
27
/**
28
  \brief   Encode Priority
29
  \details Encodes the priority for an interrupt with the given priority group,
30
           preemptive priority value, and subpriority value.
31
           In case of a conflict between priority grouping and available
32
           priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
33
  \param [in]     PriorityGroup  Used priority group.
34
  \param [in]   PreemptPriority  Preemptive priority value (starting from 0).
35
  \param [in]       SubPriority  Subpriority value (starting from 0).
36
  \return                        Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
37
 */
38
__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
39
{
40
  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL);   /* only values 0..7 are used          */
41
  uint32_t PreemptPriorityBits;
42
  uint32_t SubPriorityBits;
43
44
  PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
45
  SubPriorityBits     = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
46
47
  return (
48
           ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
49
           ((SubPriority     & (uint32_t)((1UL << (SubPriorityBits    )) - 1UL)))
50
         );
51
}



Gruß
Michael

von W.S. (Gast)


Lesenswert?

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
extern void Systemtick_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.

von Harry L. (mysth)


Lesenswert?

...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.

: Bearbeitet durch User
von Tassilo H. (tassilo_h)


Lesenswert?

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.

von Harry L. (mysth)


Lesenswert?

Jaja, aber ausserhalb einer Multitasking-Umgebung kann man das auf die 
Sub-Priority reduzieren.

Insofern ist das schon korrekt, und CubeMX sieht das genauso.

von Michael (Gast)


Lesenswert?

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

von Tassilo H. (tassilo_h)


Lesenswert?

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?

von Michael (Gast)


Lesenswert?

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

von Christopher J. (christopher_j23)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Bernd K. (prof7bit)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

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ß".

von W.S. (Gast)


Lesenswert?

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.

von Harry L. (mysth)


Lesenswert?

@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/

von Stefan F. (Gast)


Lesenswert?

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.

von Jens (Gast)


Lesenswert?

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.
1
#define SET_ICPR(a) NVIC->ICPR[(a)/32] |= (1<<((a)%32));
2
#define SET_ISER(a) NVIC->ISER[(a)/32] |= (1<<((a)%32));
3
#define SET_IP(a,b) NVIC->IP[(a)/4] |= ((b<<4)<<(8*((a)%4)));
4
5
SET_ICPR(DMA1_Stream2_IRQn);        
6
SET_ISER(DMA1_Stream2_IRQn);
7
SET_IP(DMA1_Stream2_IRQn, 3);

Bei USB sähe die Sache durchaus schon etwas anders aus..

von m.n. (Gast)


Lesenswert?

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 :-(

von Stefan F. (Gast)


Lesenswert?

Ich glaube er hat einfach nur die Code-Zeilen gepostet und die 
hilfreichen Kommentare für sich behalten. Taktischer Vorteil.

von Christopher J. (christopher_j23)


Lesenswert?

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.

von Michael (Gast)


Lesenswert?

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

von Alex D. (daum)


Lesenswert?

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.

von Michael (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

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

von Christopher J. (christopher_j23)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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).

von Christopher J. (christopher_j23)


Lesenswert?

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
1
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

gleichwertig zu
1
NVIC_SetPriorityGrouping(0);

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.

von Jens (Gast)


Lesenswert?

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..).

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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...

: Bearbeitet durch User
von Christopher J. (christopher_j23)


Lesenswert?

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?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.
1
  /* MCU Configuration----------------------------------------------------------*/
2
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
3
  HAL_Init();
4
  /* Configure the system clock */
5
  SystemClock_Config();
6
  /* Initialize all configured peripherals */
7
  MX_GPIO_Init();
8
  ...
9
  ...
10
  MX_ADC2_Init();
11
12
  /* USER CODE BEGIN 2 */
13
  InitRut();  // Und hier stelle ich alles so, wie ich es brauche, je nach Anwendung

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

@W.S.
Dass du dich überhaupt traust die config.c hier zu posten.
Die ganzen Magic Numbers sind ja graunevoll!

Bitdefinitionen schön in enums packen.

von Michael (Gast)


Lesenswert?

Hallo

Vielen Dank für die vielen Antworten.
Ich komme mit I2C erstmal weiter.

Ich wünsche euch allen schöne Feiertage!

Michael

von Michael B. (zebi)


Lesenswert?

Ich habe mich übrigens jetzt auch mal richtig hier angemeldet.
Ab jetzt heiße ich Zebi. :-)

Gruß
Michael

von W.S. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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...

von Stefan F. (Gast)


Lesenswert?

> 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.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Nunja, was ist lesbarer?

W.S. Code:
1
RCC_CFGR  =  (1<<16) |        // Quarz-Oszi als Input für PLL
2
               (4<<11) |        // APB2 Vorteiler auf :2 (72-->36 MHz)
3
               (4<<8)  |        // APB1 Vorteiler auf :2 (72-->36 MHz)
4
               (0<<17) |        // Quarz nicht :2 teilen vor der PLL
5
         (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...)

von Stefan F. (Gast)


Lesenswert?

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.

von Christopher J. (christopher_j23)


Lesenswert?

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.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Mw E. schrieb:
> (Ich nutze die HAL privat nicht, muss es aber auf Arbeit, daher weis ich
> wie schlecht die ist...)

 Zum Beispiel ?

von Stefan F. (Gast)


Lesenswert?

Bitte lasst es, wir hatten schon genug Threads dazu, die allesamt mit 
Beleidungen endeten. Bleibt beim Thema!

von Bernd K. (prof7bit)


Lesenswert?

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.

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.