Forum: Mikrocontroller und Digitale Elektronik Welcher Timer ist für die Dauer eines Ticks im SysTick verantwortlich?


von Max M. (koeltrad)


Angehängte Dateien:

Lesenswert?

STM32F407
Mit diesem Code habe ich herausgefunden, dass die Dauer eines Ticks 
1/16000000 == 62,5 ns beträgt
#include "main.h"
uint16_t delay_count=0;
void SysTick_Handler(void)
{
 if(delay_count>0)
 {
  delay_count--;
 }
}
void delay_ms(uint16_t delay_temp)
{
 delay_count=delay_temp;
 while(delay_count)
 {
 }
}
int main(void)
{
RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN;
GPIOD->MODER|=1<<(2*12);
SysTick_Config(16000000);
 while (1)
 {
 GPIOD->ODR^=(1<<12);
 delay_ms(5);
 GPIOD->ODR^=(1<<12);
 delay_ms(5);
 }
}
Das Intervall zwischen den LED-Blitzen beträgt genau 5 Sekunden.
Der SysTick-Timer zählt also in genau einer Sekunde von 16000000 auf 
Null.
Bei CubeMX habe ich die einzige Stelle gefunden, wo 16 Megahertz steht.
Dies ist SYSCLK. Aber selbst wenn ich SYSCLK mit einem externen Quarz 
auf 25 MHz ändere, ändert sich die Blinkfrequenz der LED nicht, mit dem 
gleichen Code SysTick_Config (16000000);

: Bearbeitet durch User
von Jochen (Gast)


Lesenswert?

Für den Systick ist der Systick-Timer zuständig. Ein extra 
24Bit-Countdown-Timer beim M3 und M4.

In Deine Clock-Configuration nutzt Du den internen 16Mhz 
RC-Schwingkreis, da ist es egal was für einen Quarz Du anschließt, der 
wird nicht benutzt.

Genaueres findest Du in den Datenblättern zu Deinem Controller

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Max M. schrieb:
> Welcher Timer ist für die Dauer eines Ticks im SysTick verantwortlich?

Das Systick ist ein Timer. Normalerweise stellt man den aber auf 
sinnvollers wie z.B. 1ms als intervall.


System timer: The system timer (SysTick) is a 24-bit count-down timer. 
Use this as a Real Time Operating System (RTOS) tick timer or as a 
simple counter...

Kap. "4.5 SysTick timer (STK)"
- 
https://www.st.com/resource/en/programming_manual/pm0214-stm32-cortexm4-mcus-and-mpus-programming-manual-stmicroelectronics.pdf

Kap. "6.2 Clocks"
- 
https://www.st.com/resource/en/reference_manual/rm0090-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

von Max M. (koeltrad)


Lesenswert?

Ich habe die Antwort auf das, was ich unten geschrieben habe gefunden. 
So sollte es sein. Die externe Taktung erfolgt mit einer Frequenz, die 
8-mal kleiner ist als die Prozessorfrequenz.
------------------------
Ok, die Dauer eines Ticks wird in den SysTick-Registern eingestellt.
Das CLKSOURCE-Bit im SysTick Control and Status Register bestimmt, 
welche Taktquelle verwendet werden soll.
0 - externe Taktung des Referenzoszillators, 1 - von der 
Prozessorfrequenz.
Aus irgendeinem Grund beträgt die Frequenz, die ich mit externer Taktung 
erhalte, 2 Megahertz, obwohl ich HSE bei 25 Megahertz haben sollte.
Ich überprüfe die Dauer eines Ticks mit dem Code aus der ersten 
Nachricht.
Einrichten von SysTick-Registern:
 SysTick->LOAD  = (uint32_t)(2000000-1);
 SysTick->VAL   = 0UL;
 SysTick->CTRL&= ~(1UL<<SysTick_CTRL_CLKSOURCE_Pos);//0-externe Taktung
 SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk  |
                   SysTick_CTRL_ENABLE_Msk;

: Bearbeitet durch User
von beo bachta (Gast)


Lesenswert?

Max M. schrieb:
> STM32F407

Wo ist der drauf? Selbstgebautes Board oder Discovery oder
Nucleo? Alles sehr verschwommen, solltest erst mal darstellen
wie du zu den 25MHz kommen willst.

Dann noch bitte:

>>Wichtige Regeln - erst lesen, dann posten!
>> ........
>> Formatierung (mehr Informationen...)

    [ c ]C-Code[ /c ]

von Walter T. (nicolas)


Lesenswert?

Es geht um den Abstand, nicht die Dauer, oder?

von Max M. (koeltrad)


Lesenswert?

Abstand ist Ticksdauer + Unterbrechungszeit(Interrupt).
Ich brauchte die Dauer eines Ticks. Nicht Abstand.

STM32F407VGT6
>>erst lesen, dann posten!
Ich habe gelesen, ich konnte es selbst nicht herausfinden, ihr habt mir 
geholfen.

: Bearbeitet durch User
von beo bachta (Gast)


Lesenswert?

Max M. schrieb:
> Ich brauchte die Dauer eines Ticks. Nicht Abstand.

beo bachta schrieb:
> Wo ist der drauf? Selbstgebautes Board oder Discovery oder
> Nucleo? Alles sehr verschwommen, solltest erst mal darstellen
> wie du zu den 25MHz kommen willst.

von Max M. (koeltrad)


Lesenswert?

> Wo ist der drauf? Selbstgebautes Board oder Discovery oder
Ich habe STM32F407VGT6. Das ist Discovery Board.
> wie du zu den 25MHz kommen willst.
Ich dachte, die externe Taktquelle für SysTick sei HSE, und die HSE auf 
meinem Discovery Board beträgt 25 MHz.
Es stellte sich heraus, dass dem nicht so ist. Die externe Taktquelle 
für SysTick hat eine Frequenz, die achtmal niedriger ist als die 
Prozessorfrequenz.

Jetzt ist mir alles klar. Ich wusste nicht, wo die Dauer eines Ticks für 
den SysTick-Timer eingestellt ist.

> Ich brauchte die Dauer eines Ticks. Nicht Abstand.
Abstand zwischen was und was?)
Es scheint mir, dass sie die Zeit meinten, für die der Zähler in SysTick 
Null erreicht + Interrupt-Zeit.
Ich brauchte nur die Dauer eines Ticks. Diese Zeit wird im CLKSOURCE-Bit 
im SysTick Control and Status Register gesetzt.

von beo bachta (Gast)


Lesenswert?

Max M. schrieb:
> Ich habe STM32F407VGT6. Das ist Discovery Board.

Auf dem Discovery Board gibt es keine 25 MHz. Man kann im
Schaltplan (RTFM) und auf dem Board sehen dass es einen
8MHz Quarz gibt.

von beo bachta (Gast)


Lesenswert?

Max M. schrieb:
> Die externe Taktquelle
> für SysTick hat eine Frequenz, die achtmal niedriger ist als die
> Prozessorfrequenz.

Du verwendest ja CubeMX. Warum lässt du dir nicht den Code für
die Initialisierung von CubeMX generieren, dort siehst du doch
wie alles gemacht wird. Natürlich musst du im CubeMX ein bisschen
herumclicken um alles zu konfigurieren, aber es ist doch ziem-
lich idiotensicher und für den Anfang genau der richtige Weg.

von Max M. (koeltrad)


Lesenswert?

>Warum lässt du dir nicht den Code für
>die Initialisierung von CubeMX generieren
Um nicht für immer in CubeMx stecken zu bleiben)
Ich will wissen, wie alles funktioniert.
>auf dem Board sehen dass es einen
>8MHz Quarz gibt.
Ok, ich habe gefunden, 8 Megahertz externer Quarz.

: Bearbeitet durch User
von beo bachta (Gast)


Lesenswert?

Max M. schrieb:
> Ich will wissen, wie alles funktioniert.

Dafür musst du aber sehr viel mehr wissen und tun als dein
Code im Eröffnungsbeitrag zeigt.
Vor allem musst du Wartezeiten einhalten damit PLL-Einstellungen
wirksam werden.

Max M. schrieb:
> 8 Megahertz externer Quarz

Es gibt als Pendant dazu keinen "internen Quarz".
Also: interner Takt vs. externer Takt, und was extern
gemacht wird steht auf einem anderen Blatt.

von Stefan F. (Gast)


Lesenswert?

Max M. schrieb:
> Ich dachte, die externe Taktquelle für SysTick sei HSE, und die HSE auf
> meinem Discovery Board beträgt 25 MHz.

Warum das? Cube MX zeigt dir doch an, woher der Timer seinen Takt 
erhält. Du hast es sogar rot markiert.

Nur hast du linke Hälfte nicht genauer angeschaut. Schau dir an, wie 
dein "System Clock Mux" eingestellt ist: Auf HSI, und der hat nunmal 
fest ca 16 Mhz.

Wenn du den Multiplexer auf HSE stellt, dann wird der Quarz verwendet. 
Das Board ist normalerweise mit einem 8 MHz Quarz bestückt, nicht 25!

Du kannst auch den PLL Schaltkreis nutzen, indem du den "System Clock 
Mux" auf PLL auf PLL stellst, den "PLL Source Mux" auch auf HSE und dann 
dahinter im PLL Block die gewünschten Teiler und Multiplikatoren.

von Stefan F. (Gast)


Lesenswert?

beo bachta schrieb:
> Warum lässt du dir nicht den Code für
> die Initialisierung von CubeMX generieren

Ich programmiere die Register lieber "zu Fuß" ohne HAL, einfach weil ich 
mich mehr mit den Grundlagen befassen will. Im Hobby besteht für mich 
keine Notwendigkeit, schnell zum Ziel zu kommen. Da ist eher der Weg und 
das Erforschen das Ziel.

Wie dem auch sei, ich benutze Cube MX aber gerne, um diese 
Taktkonfiguration vorher theoretisch durch zu spielen. Denn Cube MX 
zeigen einem komfortable an, was geht und was nicht. Mit den Registern 
sind nämlich durchaus einige Kombinationen möglich, die an nicht ganz so 
offensichtlichen Grenzen anstoßen. Die zeigt Cube MX in rot an.

von beo bachta (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich programmiere die Register lieber "zu Fuß" ohne HAL

Du warst überhaupt nicht gefragt.
Ich habe dich nicht gefragt, also warum zitierst du meinen
Betrag den ich dem TO geschrieben habe?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Nach wirklich zig Jahren an händischer Bitklempnerei bin ich 
mittlerweile auch ein großer Fan von STM32CubeMX geworden. Hierbei finde 
ich es äußerst lehrreich und ratsam, natürlich auch die generierten 
Quelltexten im Versionskontrollsystem (SVN, Git, ...) einzuchecken und 
nach jeder noch so kleinen Änderung am STM32CubeMX-Projekt ein Diff 
sowohl der IOC-Datei als auch der generierten Quelltexte durchzuführen. 
Dann sieht man sehr schön, was sich geändert hat und warum das der Fall 
ist. Ich hatte schon des öfteren ein Aha-Erlebnis, weil neben den 
erwarteten Änderungen manchmal auch noch an irgendeinem anderen 
Register, das ich nicht auf dem Plan gehabt hätte, das eine oder anderen 
Bit verändert wird. Bei rein händischer Programmierung sucht man sich 
wegen solcher Kleinigkeiten nämlich einen Wolf.

Mit Grausen muss ich noch an Atmel AT91RM9200 usw. zurückdenken. Bei der 
Gurke musste man sich ständig zwischen Pest und Cholera entscheiden, 
d.h. entweder passte der USB-Takt, aber dafür lagen die UART-Takte 
ziemlich daneben. Man konnte sich auch eine Konfiguration bauen, in der 
beides einigermaßen hinkam, aber dafür musste man eine PLL außerhalb des 
spezifizierten Bereichs betreiben, usw.. Ein sehr wichtiges Hilfsmittel 
für die Inbetriebnahme und auch spätere Konfigurationsänderungen war 
tatsächlich ein Spektrumanalysator. Ich klebte auf den Prozessor ein 
Stück Kupferfolie und konnte dann mit dem SA sehen, wie sich die 
Spektrallinien änderten, wenn ich an der Taktkonfiguration in den 
Bootloadern und im Linux-System herumschraubte.

Es war natürlich hochgradig lehrreich, so etwas mal wirklich en detail 
per Hand durchgeführt zu haben. Und bei meinem Kunden schauten auch die 
anderen Entwickler ziemlich blöd und konnte nicht nachvollziehen, was 
ich da überhaupt trieb. Aber wenn ich so etwas heutzutage bei jeder 
Inbetriebnahme eines jeden Microcontrollers wiederholen müsste, würde 
ich eher eine Umschulung zum Tischler oder Gärtner in Erwägung ziehen.

von Stefan F. (Gast)


Lesenswert?

beo bachta schrieb:
> Du warst überhaupt nicht gefragt.

Du auch nicht (Kopfschüttel)

Wenn du nicht zitiert werden möchtest, also wenn sich niemand auf deine 
Aussagen beziehen soll, dann mache keine öffentlichen Aussagen. So 
einfach ist das.

Ich glaube du hast nicht verstanden, dass das hier ein öffentliches 
Diskussionsforum ist. Sogar noch viel öffentlicher als die meisten 
anderen.

Gerne hätte dir diese pampige Antwort persönlich (nicht öffentlich) 
geschickt, aber das geht nicht, weil du dich nicht angemeldet hast.

von Markus M. (adrock)


Lesenswert?

Gerade am Anfang würde ich mir tatsächlich besonders die 
Clock-Configuration generieren lassen da es da einige Fallstricke gibt.

Wenn man es genau verstehen will, kann man sich ja den Quelltext dann 
ansehen.

Für den STM32F4 gibt es übrigens in der AN3988 eine Excel-Datei mit 
Makros die Dir ohne CubeMX genau den notwendigen Code erzeugt (auf Basis 
von der "alten" HAL, also nur den Includes):

https://www.st.com/resource/en/application_note/an3988-clock-configuration-tool-for-stm32f40xx41xx427x437x-microcontrollers-stmicroelectronics.pdf

Das hatte mir am Anfang auch geholfen das alles zu verstehen und 
richtig(!) zu initialisieren.

: Bearbeitet durch User
von Max M. (koeltrad)


Lesenswert?

>Wenn du den Multiplexer auf HSE stellt, dann wird der Quarz verwendet.
>Das Board ist normalerweise mit einem 8 MHz
Warum ist dann die SysTick-Frequenz bei externer Taktung 16/8=2 MHz?
Ich habe nirgendwo eine Antwort auf diese Frage gefunden. Es wird 
einfach berichtet, dass bei externer Taktung die SysTick-Frequenz ist: 
Prozessorfrequenz / 8.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Max M. schrieb:
> Warum ist dann die SysTick-Frequenz bei externer Taktung 16/8=2 MHz?
> Es wird einfach berichtet, dass bei externer Taktung die Frequenz
> 8-mal geringer ist.

Ich sage, dass der Systick Timer in deinem Eröffnungsbeitrag mit 1 Mhz 
getaktet wird, weil du im "System Clock Mux" den 16 Mhz HSI Oszillator 
gewählt hast und der AHB Prescaler auf "/2" gestellt ist. Dahinter kommt 
noch ein weiterer Teiler "/8".

Also: 16 MHz ÷ 2 ÷ 8

Den anderen Fall solltest du mal hier zeigen, damit die Konfiguration 
klar ist. Jedenfalls ist das Resultat nicht immer zwingend 2 MHz.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Andreas S. schrieb:
> Nach wirklich zig Jahren an händischer Bitklempnerei bin ich
> mittlerweile auch ein großer Fan von STM32CubeMX geworden.

Naja, hier sind eben die STM32-Fans unter sich.
Aber: Was macht ihr, wenn ihr mal einen anderen µC verwenden 
sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube.

Ich hänge hier mal eine alte (etwa 6 Jahre) Konfigurationsdatei dran - 
als Beispiel dafür, wie man's auch ganz ohne Cube und Konsorten machen 
kann und trotzdem flexibel bleibt. Und sogar eine recht einfache 
Debugmögichkeit per Oszi (Funktion 'monitor') ist mit dabei.

W.S.

von Stefan F. (Gast)


Lesenswert?

W.S. schrieb:
> Ich hänge hier mal eine alte (etwa 6 Jahre) Konfigurationsdatei dran -

Da haben wir wieder deine magischen Zahlen. ST liefert diese bereits in 
Header Dateien. Es ist mir ein Rätsel, dass du sie teilweise nicht 
verwendest. Sorry, aber dieser Programmierstil ist keine gute 
Empfehlung.

> Was macht ihr, wenn ihr mal einen anderen µC verwenden
> sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube.

Wenn ich in einem Projekt Cube MX bzw. HAL benutze, entsteht dadurch 
keinerlei Zwang, es in allen Projekten zu nutzen. Schon gar nicht, wenn 
ganz andere Mikrocontroller im Spiel sind.

Man nimmt das, was angeboten wird. Aber bitte erst nach dem Erlernen der 
Grundlagen. Der TO ist da schon auf dem richtigen Weg.

von Bernd (Gast)


Lesenswert?

W.S. schrieb:
> Aber: Was macht ihr, wenn ihr mal einen anderen µC verwenden
> sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube.
Da hilft dein Code aber auch nicht weiter.
So what?

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Da haben wir wieder deine magischen Zahlen. ST liefert diese bereits in
> Header Dateien. Es ist mir ein Rätsel, dass du sie teilweise nicht
> verwendest.

Dann erkläre ich es dir: Ich sehe in unnötigen Bezügen und einer damit 
verbundenen Schwemme von zusätzlichen Bezeichnern einen ernsthaften 
Grund für Programmierfehler. Wenn man Bit 7 für irgend etwas braucht, 
dann kann man schreiben
1
#define MeinBit  7
oder
1
#define MeinBit  (1<<7)
oder eines von beiden muß in einer referenzierten anderen Datei stehen. 
Von sowas wie 128 oder 0x80 wollen wir hier mal absehen. Um sicher zu 
sein, daß dort das drinsteht, was man braucht, muß man in der anderen 
Datei nachschauen. Und wenn jemand eine andere Toolchain hat, wo das 
gerade anders gehandhabt wird, dann handelt man sich einen Fehler ein, 
den man so schnell nicht bemerkt. Deshalb sollte man solche Dinge, die 
tatsächlich unbemerkt schiefgehen können, lieber nicht aus anderen 
Dateien beziehen, die obendrein nicht zum konkreten Projekt gehören. 
Maßhalten ist angesagt anstelle Extremismus. Headerdateien zu einem Chip 
sind OK, aber sie sollten nicht über das sinnvolle Maß aufgebläht sein.

Davon mal abgesehen ist es mir auch bei ST bereits einmal untergekommen, 
daß Bits, die in völlig verschiedenen Registern vorkommen, den gleichen 
Namen hatten. Dann mußten in der zugehörigen Headerdatei Modifikationen 
am Namen vorgenommen werden, woraus sich obendrein ein Unterschied zum 
Manual ergab. In diesem Falle war dann das Lesen der Headerdatei und 
Vergleich mit dem Manual fällig, um den richtigen Namen zu erwischen. 
Ich weiß, sowas ist selten, es kommt aber vor.

W.S.

von Stefan F. (Gast)


Lesenswert?

Siehst du, da sind wir wieder bei deinem Stil, lieber eigene Header 
Dateien zu schreiben, als bewährte wieder zu verwenden. Das kann man 
machen, aber empfehlen werde ich es wahrscheinlich niemals.

von Max M. (koeltrad)


Lesenswert?

>Ich sage, dass der Systick Timer in deinem Eröffnungsbeitrag mit 1 Mhz
>getaktet wird
Vielleicht verstehe ich etwas nicht, aber nein.
Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim 
externen Taktgeber auf 2 MHz eingestellt.
Ich überprüfe es mit dem Code, der in der ersten Nachricht geschrieben 
ist.
Den internen Generator habe ich so eingerichtet:
1
SysTick_Config(16000000);
Externen Generator wie folgt eingerichtet:
1
  SysTick->LOAD  = (uint32_t)(2000000-1);
2
  SysTick->VAL   = 0UL;                              
3
  SysTick->CTRL  &= ~(1UL << SysTick_CTRL_CLKSOURCE_Pos);    
4
  SysTick->CTRL  = SysTick_CTRL_TICKINT_Msk   |
5
                            SysTick_CTRL_ENABLE_Msk;

von W.S. (Gast)


Lesenswert?

Bernd schrieb:
> Da hilft dein Code aber auch nicht weiter.
> So what?

Da hilft die Herangehensweise aber sehr. So that . Sozusagen. Es ist 
eben das Können einer Initialisierung des Chips oder das Angebundensein 
an ein spezielles Herstellertool. Sollte eigentlich erkennbar sein.

So eine Konfigurationsdatei, die den Takt und die Pinverwendung 
aufsetzt, muß natürlich sowohl zum Chip als auch zum Projekt passen. 
Insofern ist das eine projektabhängige Datei, aber sie ist nicht 
maschinell erzeugt und braucht deshalb keine Herstellertools und 
obendrein hält man sich damit die anderen Dateien im Projekt von den 
hier gemachten Einstellungen frei. Was ich hier in diesem Forum 
allerdings oft sehe, sind Projekte, wo alles kreuz und quer 
durcheinander purzelt: Lowlevel-Einstellungen in main.c und so weiter.

W.S.

von Stefan F. (Gast)


Lesenswert?

Max M. schrieb:
> Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim
> externen Taktgeber auf 2 MHz eingestellt.

Mag sein. Das hängt alles davon ab, wie die Multiplexer, Teiler und PLL 
in deinem Fall konfiguriert sind. Ohne konkrete Angaben kann ich das 
nicht weiter kommentieren. Zeige doch mal das korrespondiere Bild von 
Cube MX. Ich bin ganz sicher, dass da nicht magisches im Hintergrund 
passiert.

von Max M. (koeltrad)


Lesenswert?

Ok habe es.
Gut, danke.
Ich lösche diesen Code, der diese Einstellungen vorgenommen hat.

von Stefan F. (Gast)


Lesenswert?

Max M. schrieb:
> Ich lösche diesen Code, der diese Einstellungen vorgenommen hat.

Zeige ihn doch mal! Das lässt sich sicher erklären.

von W.S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Siehst du, da sind wir wieder bei deinem Stil, lieber eigene Header
> Dateien zu schreiben, als bewährte wieder zu verwenden.

Ach nö, wenn irgend ein Hersteller für seine Chips passable 
Headerdateien liefert, dann nehme ich die auch. Aber das heißt nicht, 
grundsätzlich alles daraus zu verwenden. Es ist ST ja beileibe nicht der 
einzige Hersteller, dessen µC ich verwende. Ich hab da schon einige 
durch und ein jeder Hersteller hat da seine eigenen Macken. Nicht nur 
beim schieren Silizium.

W.S.

von Max M. (koeltrad)


Lesenswert?

1
#include "main.h"
2
void SystemClock_Config(void);
3
static void MX_GPIO_Init(void);
4
5
int main(void)
6
{
7
 
8
  HAL_Init();
9
10
   SystemClock_Config();
11
12
  MX_GPIO_Init();
13
  
14
  while (1)
15
  {
16
  
17
}
18
19
void SystemClock_Config(void)
20
{
21
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
22
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
23
24
  __HAL_RCC_PWR_CLK_ENABLE();
25
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
26
27
   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
28
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
29
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
30
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
31
  {
32
    Error_Handler();
33
  }
34
35
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
36
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
37
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
38
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
39
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
40
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
41
42
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
43
  {
44
    Error_Handler();
45
  }
46
}
47
48
static void MX_GPIO_Init(void)
49
{
50
51
  /* GPIO Ports Clock Enable */
52
  __HAL_RCC_GPIOH_CLK_ENABLE();
53
  __HAL_RCC_GPIOA_CLK_ENABLE();
54
55
}
56
void Error_Handler(void)
57
{
58
 
59
  __disable_irq();
60
  while (1)
61
  {
62
  }
63
}
64
65
#ifdef  USE_FULL_ASSERT
66
67
void assert_failed(uint8_t *file, uint32_t line)
68
{
69
}
Hier waren vielleicht void SystemClock_Config (void) alle 
Timer-Einstellungen, ich habe sie aus dem Code entfernt.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

In dem Zusammenhang ist neben dem RCC die Beschreibung des "SysTick 
control and status register" relevant, welche leider nicht im Reference 
Manual des Chips dokumentiert ist, sondern in einem weiteren Dokument, 
dem "STM32 Cortex-M4 programming manual".

Der Code, den du weiter oben mit "Externen Generator wie folgt 
eingerichtet:" hat nichts mit HSE (Quarz) versus HSI zu tun, sondern 
beeinflusst den Teiler an den ich den grünen Pfeil gemalt habe.

Zitat:
1
SysTick->LOAD  = (uint32_t)(2000000-1);
2
SysTick->VAL   = 0UL; 
3
SysTick->CTRL  &= ~(1UL << SysTick_CTRL_CLKSOURCE_Pos);  
4
SysTick->CTRL  = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;

von Stefan F. (Gast)


Lesenswert?

Max M. schrieb:
> C-Quelltext

Hier nutzt du also nun den HSE ohne PLL. Der AHB Bus hat bei deiner 
Einstellung Systemtakt geteilt durch 2. Also vermutlich 4 MHz, da ich 
von einem 8 MHz Quarz ausgehe.

Nun kann der Systick Timer am AHB Bus also wahlweise mit den 4 MHz oder 
0,5 MHz (4 MHz nochmal geteilt durch 8) getaktet werden.

von Bauform B. (bauformb)


Lesenswert?

Max M. schrieb:
> Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim
> externen Taktgeber auf 2 MHz eingestellt.

Die Verwirrung kommt daher, dass der SYSTICK nicht STM gehört, sondern 
ARM, wobei der Teiler /8 schon wieder STM gehört. Deshalb ist "extern" 
relativ. ARM meint damit "außerhalb des M4-Kerns". Im ARM v7-M 
Architecture ® Reference Manual ist es minimal verständlicher 
formuliert:
1
CLKSOURCE, bit[2] Indicates the SysTick clock source:
2
 0 SysTick uses the IMPLEMENTATION DEFINED external reference clock.
3
 1 SysTick uses the processor clock.
4
If no external clock is provided, this bit reads as 1 and ignores writes.

Solche kleinen Probleme mit der Doku werden dir noch öfter begegnen, 
z.B. Signalnamen aus der Chip-Design-Ecke, die sonst nirgendwo 
auftauchen. Woher soll auch der Entwickler von z.B. einem ADC wissen, 
auf welchen Chip und wie sein ADC-Modul mal eingebaut wird. Und der 
Autor der Doku erfährt es vielleicht nur nebenbei beim Kaffee ;)

von Stefan F. (Gast)


Lesenswert?

Wie ätzend. Aber es bestätigt meine Empfehlung mit AVR anzufangen, weil 
deren Doku erheblich Anfänger-freundlicher ist.

Gibt es eigentlich Cortex-M basierte Mikrocontroller mit ähnlich guter 
und einfacher Doku wie bei AVR?

von Ron T. (rontem)


Lesenswert?

Stefan ⛄ F. schrieb:
> Aber es bestätigt meine Empfehlung mit AVR anzufangen, weil deren Doku
> erheblich Anfänger-freundlicher ist.

Vor allem aber dürften diese denen für die meisten Zwecke ausreichen.

von Max M. (koeltrad)


Lesenswert?

In dem von CubeMx generierten Code werden Interrupts von einem anderen 
Timer behandelt, nicht von SysTick.
Und immer werden diese Interrupts für einen Tick auf 1 Millisekunde 
gesetzt. Also 1 Kilohertz.
Unabhängig von den Einstellungen, die ich in der CubeMx Clock 
Configuration vornehme, werden Interrupts immer auf 1 Millisekunde für 
einen Tick gesetzt.
Weiß jemand wo diese Interrupts gesetzt sind?
Ich denke, dass dies irgendwo in der Funktion HAL_RCC_ClockConfig ist, 
ich habe nicht gefunden, wo genau Interrupts in dieser Funktion 
konfiguriert sind.
1
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0)
HAL_RCC_ClockConfig passt sich an alle vorhandenen Teiler an und setzt 
Interrupts immer auf 1 Kilohertz, mit beliebigen 
HAL_RCC_ClockConfig-Einstellungen.

Beitrag #7081251 wurde vom Autor gelöscht.
von Max M. (koeltrad)


Lesenswert?

Ich habe nur den Frequenzteiler im Register RCC->CFGR gefunden.
Das RCC_CIR-Register kann Interrupts konfigurieren, aber ich habe dieses 
Register nicht in der HAL_RCC_ClockConfig-Funktion gesehen.

In der HAL_RCC_OscConfig-Funktion habe ich das RCC_CIR-Register 
gefunden.
Ich habe es noch nicht ganz verstanden, aber es scheint, dass Interrupts 
in dieser Funktion konfiguriert sind.

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Max M. schrieb:
> In dem von CubeMx generierten Code werden Interrupts von einem anderen
> Timer behandelt, nicht von SysTick.

Vielleicht so: auch von einem anderen Timer? Hast du nicht selbst 
irgendwas mit einem anderen Timer gemessen?

> Unabhängig von den Einstellungen, die ich in der CubeMx Clock
> Configuration vornehme, werden Interrupts immer auf 1 Millisekunde für
> einen Tick gesetzt.

Weil: 1ms sieht doch verdammt nach systick aus; genau dafür hat ARM den 
eingebaut.

> Weiß jemand wo diese Interrupts gesetzt sind?

Die systick-Interrupts werden mit dem Bit STK->TICKINT eingeschaltet, 
mehr ist dafür nicht nötig. Bei allen anderen Interrupts muss zusätzlich 
der NVIC programmiert werden.

Max M. schrieb:
> In der HAL_RCC_OscConfig-Funktion habe ich das RCC_CIR-Register
> gefunden.
> Ich habe es noch nicht ganz verstanden, aber es scheint, dass Interrupts
> in dieser Funktion konfiguriert sind.

In den RCC-Registern gibt es Interrupt-Enable-Bits für alles, was mit 
Oszillatoren und PLLs zu tun hat. Timer haben ihre eigenen Register. Die 
Hardware ist in der Hinsicht relativ aufgeräumt. Was man scheinbar vom 
HAL nicht sagen kann...

Diese Rätsel wären doch ein guter Anlass, den CubeMX- und HAL-Code zu 
entsorgen. Du musst ja sowieso die Hardware verstehen. Dafür reicht 
das Reference Manual und ggf. eine AppNote. Warum solltest du 
zusätzlich noch die HAL-Magie lernen? Immerhin:

Max M. schrieb:
>>Warum lässt du dir nicht den Code für
>>die Initialisierung von CubeMX generieren
> Um nicht für immer in CubeMx stecken zu bleiben)
> Ich will wissen, wie alles funktioniert.

von Max M. (koeltrad)


Lesenswert?

>mit beliebigen HAL_RCC_ClockConfig-Einstellungen.
Hier meinte: ich mit beliebigen CubeMx Clock Configuration Einstellungen

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Stefan ⛄ F. schrieb:
> es bestätigt meine Empfehlung mit AVR anzufangen, weil
> deren Doku erheblich Anfänger-freundlicher ist.

Es wäre ja schon viel gewonnen, wenn Anfänger unterscheiden könnten, 
welche Kapitel nur für Experten wichtig sind. Warum beschäftigen sich 
Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32 
völlig überflüssig, die Defaults nach Reset funktionieren einfach so. 
Oder Interrupt-Prioritäten -- total egal, es funktioniert von alleine. 
Aber nein, überall werden erstmal die sub priorities erklärt -- die 
braucht man vielleicht, wenn man ein Betriebssystem baut. Mit HAL 
kommt man aber kaum dran vorbei.

von W.S. (Gast)


Lesenswert?

Bauform B. schrieb:
> Warum beschäftigen sich
> Anfänger mit der Taktkonfiguration?

Weil der Takt wohl eines der grundlegenden Dinge in einem 
Mikrocontroller ist. Darum.

Und man sollte das Taktsystem auch zu verstehen lernen, bevor man 
irgendwelche anderen Teile eines µC benutzen will. Wer das nicht kann 
oder will oder aus anderen Gründen ablehnt, der sollte ein geeignetes 
Ingenieurbüro mit dem Projekt beauftragen. Dann kann man sich auf andere 
Dinge konzentrieren, BWL zum Beispiel.

Die Alternative für Leute die unbedingt programmieren wollen wäre, das 
nicht für einen µC zu tun, sondern auf dem PC zu bleiben. Dort hat man 
zumeist ein fertiges OS, was einem die Details der Hardware abnimmt.

Allerdings tut sich da ein weiteres Problem auf: Man lernt nix über die 
Hardware dazu. Und so kommt weitere Verwirrung auf, die letztlich zu 
solchen Dingen führt:

Max M. schrieb:
> Mit diesem Code habe ich herausgefunden, dass die Dauer eines Ticks
> 1/16000000 == 62,5 ns beträgt

Also, zum Verständnis: Es gibt diverse Teile auf dem Silizium deines 
Controllers, die einen Interrupt erzeugen können. Diese werden im 
Interruptcontroller verwaltet, der sie in geordneter Reihenfolge 
benutzt, um damit den gewöhnlichen Ablauf der Arbeit der CPU zu 
unterbrechen. Von da her kommt der Name 'Interrupt'. Bei den Cortexen 
ist es nun so, daß zu jedem möglichen Interrupt, der auf dem 
betreffenden Stück Silizium vorkommen kann, ein Adress-Zeiger im 
Programmspeicher gehört, der auf den zuständigen Interrupthandler 
hinzeigt. Diese Adress-Zeiger sind zu einer Tabelle zusammengefaßt, die 
gewöhnlich ab Adresse 0 beginnt. Bei manchen Cortexen kann diese Tabelle 
auch woanders hin verlegt werden, was hier aber nicht das Thema ist.
So.
Einer der Interupts ist der, welcher vom Systemtimer (Timertick) 
hervorgerufen wird. Dieser Timer wird selten von den Manuals der 
Chiphersteller behandelt, weil er Teil der CPU ist, die bekanntlich von 
Arm kommt. Um da nachzulesen, muß man eher die Dokumente lesen, die von 
Arm kommen.
Besagter Timertick arbeitet zumeist mit dem Takt, den auch die CPU 
benutzt, also dem Systemtakt. Kann aber bei manchen Chips auch von 
woanders getaktet werden. Sinn und eigentlicher Zweck dieses Timers ist, 
daß er Interrupts in geordneten zeilichen Abständen liefern soll, so daß 
man damit eine Systemuhr o.ä. machen kann. Normalerweise lädt man also 
diesen Timer mit einer solchen Zahl, daß sich ein Tick (d.h. ein 
Interrupt) alle 1 ms oder 10 ms ergibt und läßt ihn dann in Ruhe vor 
sich hin arbeiten.

Und wenn du Zweifel an der Frequenz des Systemtaktes hast, dann leite 
dir diesen Takt oder den heruntergeteilten Teil dieses Taktes auf den 
dafür vorgesehenen Pin deines Chips und schau ihn dir per Oszi oder 
Frequenzmesser an.

Walter T. schrieb:
> Es geht um den Abstand, nicht die Dauer, oder?

Ja, natürlich. Aber wie so oft hat man es auch hier mit unpräzisen 
Ausdrücken zu tun, die aus nur nebulösen Vorstellungen herrühren. Von da 
her tut Erklärung not.

W.S.

von Bauform B. (bauformb)


Lesenswert?

W.S. schrieb:
> Und man sollte das Taktsystem auch zu verstehen lernen, bevor man
> irgendwelche anderen Teile eines µC benutzen will.

Nein. Nicht, wenn es für das Programm völlig unwichtig ist.

von Ron T. (rontem)


Lesenswert?

W.S. schrieb:
> Die Alternative für Leute die unbedingt programmieren wollen wäre, das
> nicht für einen µC zu tun, sondern auf dem PC zu bleiben.

Die Alternative wären zunächst mal schlicht einfachere Mikrocontroller 
die es genauso tun.

von Stefan F. (Gast)


Lesenswert?

Bauform B. schrieb:
> Warum beschäftigen sich
> Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32
> völlig überflüssig, die Defaults nach Reset funktionieren einfach so.

Sehr gut, volle Zustimmung. In meinem STM32 Heft gehe ich genau diesen 
Weg.

W.S. schrieb:
> Die Alternative für Leute die unbedingt programmieren wollen wäre, das
> nicht für einen µC zu tun, sondern auf dem PC zu bleiben.

Ja, ich finde es auch nicht besonders geschickt, die Programmiersprache 
auf einem µC zu lernen. Anfassbare Hardware (z.B. einen Roboter) zu 
programmieren mag zwar verlockend klingen, aber da hat man rasch zu 
viele Baustellen gleichzeitig offen.

von Bob (Gast)


Lesenswert?

Bauform B. schrieb:
> Warum beschäftigen sich
> Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32
> völlig überflüssig, die Defaults nach Reset funktionieren einfach so.

Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen?
Also es werden ja wohl eher nicht alle STM32 per Default auf den 
maximalen Takt konfiguriert sein, so aus einem internen Oszillator?

Es werden aber auch nicht alle STM32 per Default mit 16MHz laufen?

Oder sind die Default-Werte individuell für jeden Typ?
Pro Familie wird das wohl eher auch nicht gelten, innerhalb einer 
Familie haben ja nicht alle Typen den gleichen Maximal-Takt.
Wenn ja, wo steht das im Reference-Manual?

Nehmen wir als Beispiel doch mal STM32F446, STM32L073 und STM32G081.

Ich habe jetzt mal kurz das Reference-Manual vom STM32F446 überflogen 
aber nicht direkt eine Tabelle mit den Default-Werten gefunden.

Ja, die Register haben Reset-Default-Werte und man könnte sich das 
zusammen suchen, die Aussage oben ist doch aber, das man das zunächst 
nicht braucht.

Wo steht das konkret?
Und ich meine das Ernst, ich habe keine Ahnung wie man STM32 
programmiert, bin aber geneigt das zu ändern wenn man die denn 2024 oder 
so wieder bekommen kann.

Eine HAL Funktion gibt es dafür auch nicht, oder?
Also sowas wie HAL_CLOCK_Init(48000000)?

von Stefan F. (Gast)


Lesenswert?

Bob schrieb:
> Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen?

Bei den mir bekannten STM32 läuft die L Serie standardmäßig auf 2 MHz 
und die F Serie auf 8 MHz.

> Wenn ja, wo steht das im Reference-Manual?

Die Info ist über die RESET Werte zahlreicher Register verstreut. In 
Cube MX kannst du es schneller sehen, da gibt es einen Button der den 
Standardfall nach Reset anzeigt.

Bob schrieb:
> Eine HAL Funktion gibt es dafür auch nicht, oder?
> Also sowas wie HAL_CLOCK_Init(48000000)?

Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem 
R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche 
Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB 
Takt synchronisiert werden?

Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine 
möchte sie vielleicht so schnell wie möglich takten, der andere nicht um 
z.B Strom zu sparen oder damit Timer langsame/länger laufen.

von W.S. (Gast)


Lesenswert?

Bob schrieb:
> Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen?

Du willst ne allgemeine Aussage?
OK: Im allgemeinen wird (sofern vorhanden) zu allererst ein interner 
RC-Oszillator als Taktquelle benutzt. Sofern vorhanden, wird die PLL und 
der dazu gehörige schnelle VCO am Anfang nicht benutzt. Gleiches gilt 
für einen externen Quarz oder sonstwie von außen zugeführtes Taktsignal.
Der µC kann damit erstmal arbeiten, aber er wird damit nicht seine 
vorgesehene Geschwindigkeit erreichen.

W.S.

von Bauform B. (bauformb)


Lesenswert?

Bob schrieb:
> Ich habe jetzt mal kurz das Reference-Manual vom STM32F446 überflogen
> aber nicht direkt eine Tabelle mit den Default-Werten gefunden.
>
> Ja, die Register haben Reset-Default-Werte und man könnte sich das
> zusammen suchen, die Aussage oben ist doch aber, das man das zunächst
> nicht braucht.
>
> Wo steht das konkret?

Im Datenblatt im Kapitel "Functional Overview", Abschnitt "Clocks and 
Startup". Das Datenblatt ist auch viel kürzer als das Reference Manual 
(falls man suchen muss). Und es ist die offizielle Quelle für Daten, die 
evt. von Baustein zu Baustein unterschiedlich sein könnten. Die 
Reference Manuals behandeln ja oft viele verschiedene Typen.

von Bob (Gast)


Lesenswert?

Top, danke.

Bauform B. schrieb:
>> Wo steht das konkret?
>
> Im Datenblatt im Kapitel "Functional Overview", Abschnitt "Clocks and
> Startup". Das Datenblatt ist auch viel kürzer als das Reference Manual
> (falls man suchen muss). Und es ist die offizielle Quelle für Daten, die
> evt. von Baustein zu Baustein unterschiedlich sein könnten. Die
> Reference Manuals behandeln ja oft viele verschiedene Typen.

STM32F446: 16MHz
STM32L073: 2,1MHz
STM32G081: scheinbar keine Angabe im Datenblatt, oder nicht direkt

Das ist ein guter Tipp, leider sind die Datenblätter von STM alles 
andere als konsistent zueinander.

Stefan ⛄ F. schrieb:
> In Cube MX kannst du es schneller sehen, da gibt es einen Button der den
> Standardfall nach Reset anzeigt.

Ok, ich habe ein neues Projekt für den STM32G081 aufgemacht, danach 
läuft der per Default mit 16MHz.

Stefan ⛄ F. schrieb:
>> Eine HAL Funktion gibt es dafür auch nicht, oder?
>> Also sowas wie HAL_CLOCK_Init(48000000)?
>
> Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem
> R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche
> Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB
> Takt synchronisiert werden?

Nun, um sowas aufzulösen gibt es die HAL doch?
Nur wohl eben nicht für den Takt.
Was schade ist, wenn man die entsprechenden HAL Includes einbinden 
würde, dann könnte man ja die gleichen Aufrufe für mehrere Targets 
verwenden.
Genau wie man eben LL_SPI_TransmitData8() querbeet durch den ganzen 
STM32 Zoo verwenden kann.

Stefan ⛄ F. schrieb:
> Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine
> möchte sie vielleicht so schnell wie möglich takten, der andere nicht um
> z.B Strom zu sparen oder damit Timer langsame/länger laufen.

Ja, nun, das gehört ja schon irgendwie zur Konfiguration der Peripherie.

Wobei ich gerade überrascht bin von der "Clock Configuration" vom 
STM32G081, ein großer Teil der Peripherie hängt wohl einfach so am "APB 
peripheral clock", etwa die SPI.
Auf den ersten Blick scheinen die Möglichkeiten üppig zu sein, auf den 
zweiten Blick ist das doch schon schwer eingeschränkt.
Der Prescaler für den SPI erinnert mich gerade an AVR, hmm.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Bob schrieb:
> Nun, um sowas aufzulösen gibt es die HAL doch?
> Nur wohl eben nicht für den Takt.

Doch klar, CubeMX generiert entsprechend den Einstellungen in dem 
grafischen Dialog einen Code, der komplett auf HAL basiert.

Zum Beispiel:
1
void SystemClock_Config(void)
2
{
3
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
4
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
5
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
6
7
  /** Configure the main internal regulator output voltage
8
  */
9
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
10
11
  /** Initializes the RCC Oscillators according to the specified parameters
12
  * in the RCC_OscInitTypeDef structure.
13
  */
14
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_HSI48;
15
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
16
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
17
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
18
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
19
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;
20
  RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
21
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
22
  {
23
    Error_Handler();
24
  }
25
26
  /** Initializes the CPU, AHB and APB buses clocks
27
  */
28
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
29
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
30
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
31
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
32
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
33
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
34
35
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
36
  {
37
    Error_Handler();
38
  }
39
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
40
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
41
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
42
  {
43
    Error_Handler();
44
  }
45
}

Du kannst diese HAL Funktionen (in diesem Fall HAL_RCC_OscConfig, 
HAL_RCC_ClockConfig und HAL_RCCEx_PeriphCLKConfig) selbstverständlich 
auch selbst benutzen, ohne den Code Generator von Cube MX zu benutzen.

Aber kopieren kann man diese Zeilen nur bedingt, denn das funktioniert 
ja bei jedem Modell (in Details) anders.

von stefanuswidersprecher (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Doch klar, CubeMX generiert entsprechend den Einstellungen in dem
> grafischen Dialog einen Code, der komplett auf HAL basiert.

Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut
dazu veranlassen, Low-Level-Code (also Code für die LL Library)
zu generieren.

Hier ein Beispiel für den F411. Generiert aus CubeMX. Es kommt
zwar einmal das Token HAL_OK vor aber sonst sind die Calls
alle für die LL Library ausgeführt.
1
void SystemClock_Config(void)
2
{
3
  LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
4
5
  if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
6
  {
7
    Error_Handler();
8
  }
9
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
10
  LL_RCC_HSE_Enable();
11
12
   /* Wait till HSE is ready */
13
  while(LL_RCC_HSE_IsReady() != 1)
14
  {
15
16
  }
17
  LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_25, 192, LL_RCC_PLLP_DIV_2);
18
  LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_25, 192, LL_RCC_PLLQ_DIV_4);
19
  LL_RCC_PLL_Enable();
20
21
   /* Wait till PLL is ready */
22
  while(LL_RCC_PLL_IsReady() != 1)
23
  {
24
25
  }
26
  LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
27
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
28
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
29
  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
30
31
   /* Wait till System clock is ready */
32
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
33
  {
34
35
  }
36
  LL_SetSystemCoreClock(96000000);
37
  I2C_SetSystemCoreClock(96000000);
38
39
   /* Update the time base */
40
  if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
41
  {
42
    Error_Handler();
43
  };
44
  LL_RCC_SetTIMPrescaler(LL_RCC_TIM_PRESCALER_TWICE);
45
}

von Stefan F. (Gast)


Lesenswert?

stefanuswidersprecher schrieb:
> Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut
> dazu veranlassen, Low-Level-Code (also Code für die LL Library)
> zu generieren.

Ja, aber Bob hatte ja nach HAL Funktionen zum Konfigurieren des Taktes 
gefragt. Also habe ich ihm gezeigt, wie es geht:

Bob schrieb:
> Eine HAL Funktion gibt es dafür auch nicht, oder?
> Also sowas wie HAL_CLOCK_Init(48000000)?

von Bob (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Bob schrieb:
>> Eine HAL Funktion gibt es dafür auch nicht, oder?
>> Also sowas wie HAL_CLOCK_Init(48000000)?
>
> Nein, weil es da ja viele weitere Optionen gibt.

Stefan ⛄ F. schrieb:
> if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
>   {
>     Error_Handler();
>   }

Schön, also die richtige Antwort wäre gewesen, ja, gibt es, aber 
deutlich komplizierter, da es viele weitere Optionen gibt.
Und statt HAL_CLOCK ist das HAL_RCC.

Ok, ja, das einfachste wird wirklich sein das zumindest am Anfang aus 
der STM32CubeIDE für jedes Target einzeln zu generieren.

stefanuswidersprecher schrieb:
> Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut
> dazu veranlassen, Low-Level-Code (also Code für die LL Library)
> zu generieren.

Interessant, spontan gefunden wo man das einstellt habe ich allerdings 
nicht.

https://www.e-tinkers.com/2022/04/a-bettery-way-to-setup-stm32cubeide/

Also falls die Webseite verschwinden sollte,
in der project.ioc den Project Manager Tab auswählen, Links auf 
"Advanced Settings" stellen und im "Driver Selector" da wo per Default 
"HAL" steht im DropDown Menü auf "LL" umstellen.

Ein weiterer Link in der Sammlung STM32 Links für "später".

von Stefan F. (Gast)


Lesenswert?

Bob schrieb:
> Schön, also die richtige Antwort wäre gewesen, ja, gibt es, aber
> deutlich komplizierter, da es viele weitere Optionen gibt.

Nein, doch, Oooh!

Schau mal wie ich die Frage beantwortet hatte:

Stefan ⛄ F. schrieb:
> Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem
> R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche
> Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB
> Takt synchronisiert werden?
> Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine
> möchte sie vielleicht so schnell wie möglich takten, der andere nicht um
> z.B Strom zu sparen oder damit Timer langsame/länger laufen.

von Andi B. (andi_b2)


Lesenswert?

Stefan ⛄ F. schrieb:
> Gibt es eigentlich Cortex-M basierte Mikrocontroller mit ähnlich guter
> und einfacher Doku wie bei AVR?

Einfach ist relativ. Bei den schier unendlich mehr Möglichkeiten von 
praktisch allen Cortex-M Prozessoren und deren gewaltig 
besserer/umfangreicherer Peripherie gegenüber den Atmel Dingern, muss 
zwangsweise auch die Dokumentation komplexer sein.

Persönlich war ich froh und erstaunt, als ich mich vor mehr als einer 
Dekade in die EnergyMicros (EFM32) eingearbeitet habe. Um Welten besser 
als Atmel, Microchip, Infineon, Freescale, Intel, ... Sauberer Aufbau 
der Dokus, Headers, Beispielprogramme, AppNotes, Peripherie, ...

Leider wurden auch da die Tools seit der Übernahme durch SiliconLabs IMO 
dann doch wieder komplizierter. Zumindest für Einsteiger. Es gibt 
mittlerweile auch bei den EFM32 schon wieder verschiedenen Subfamilien 
mit unzähligen Derivaten. Damit steigt automatisch die Komplexität. Auch 
der Tools und der Dokus.

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.