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);
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
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;
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 ]
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.
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.
> 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.
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.
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.
>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.
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.
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.
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.
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?
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.
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.
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.
>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.
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.
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.
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.
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?
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.
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.
>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:
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.
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.
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.
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:
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.
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 ;)
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?
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.
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.
HAL_RCC_ClockConfig passt sich an alle vorhandenen Teiler an und setzt
Interrupts immer auf 1 Kilohertz, mit beliebigen
HAL_RCC_ClockConfig-Einstellungen.
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.
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.
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.
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.
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.
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.
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.
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)?
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.
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.
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.
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.
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
voidSystemClock_Config(void)
2
{
3
RCC_OscInitTypeDefRCC_OscInitStruct={0};
4
RCC_ClkInitTypeDefRCC_ClkInitStruct={0};
5
RCC_PeriphCLKInitTypeDefPeriphClkInit={0};
6
7
/** Configure the main internal regulator output voltage
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.
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.
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)?
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".
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.
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.