So...ich habe mich mal an der Taktkonfiguration versucht.
Eine Frage vorweg: Kann ich bei der Taktkonfiguration irgendetwas so
zerhacken, daß der nachher nicht mehr lauffähig ist? Ich meine sowas wie
bei den AVRs, wenn man da die Fusebits unpassend wählt wars das-bis man
die eingestellte Taktquelle zuführt.
Ich habe mich an diesem Tutorial hier entlanggehangelt, allerdings mit
ein paar kleine Abweichungen.
https://github.com/jkerdels/stm32edu/blob/master/src/rcc.c
So läuft mein STM mit 180MHz, und nutzt den internen RC-Oszillator als
Taktquelle.
Meint ihr das läuft so? Ich hab vor der Taktkonfiguration doch noch
etwas Respekt.
1
//Initialize clock config
2
voidinitClock(){
3
//dont touch clock at the moment, use standard settings
Ich hab mein Nucleo F446 schon mit 100MHz und auch mit 250MHz
durchgetaktet. Da schließt du dich nicht so schnell aus.
Selbst mit nem Linkerskript von nem F401 nicht. Spiel damit bis du deine
Flashzyklen durch hast. Kann aber dauern :)
Konnte es nicht abwarten, habs mal kompiliert und (da waren doch
tatsächlich noch ein paar kleine Syntaxfehlerteufelchen) - und siehe da,
er hängt an dieser Stelle fest:
1
//Wait for HSI is stable running
2
while(RCC->CR&RCC_CR_HSIRDY){}
Warum kommt der da nicht aus der Schleife raus? Anscheind wird das
HSI-Ready-Flag nicht gesetzt...aber wieso?
Kleine Info am Rande - es gibt ein offizielles Excel-Sheet von ST, dort
stellt man alle gewünschten Takte und Parameter ein und dieses generiert
automatisch eine Datei. Aufgerufen wird diese dann über SystemInit().
Dadurch umgeht man die vielen möglichen Fehler, wenn man es selbst macht
(was bei der RCC bei ARMs doch sehr schnell passiert..)
Wühlhase schrieb:> Konnte es nicht abwarten, habs mal kompiliert und (da waren doch> tatsächlich noch ein paar kleine Syntaxfehlerteufelchen) - und siehe da,> er hängt an dieser Stelle fest:>>
1
>//Wait for HSI is stable running
2
>while(RCC->CR&RCC_CR_HSIRDY){}
3
>
>> Warum kommt der da nicht aus der Schleife raus? Anscheind wird das> HSI-Ready-Flag nicht gesetzt...aber wieso?
Hast du den Hinweis im RefMan beachtet? Siehe
https://stackoverflow.com/questions/31407505/pll-clock-configuration.
Ansonsten kann das auch auf einen Verdrahtungsfehler oder Hardwarefehler
rauslaufen, dass er die HSI nicht einschalten kann. Ist das ein eigenes
Board?
Mensch, daß mit der Excel wäre klasse...allerdings unterstützt die den
F446 anscheinend nicht. :(
Und Open Office zickt mit der Datei rum...kommt anscheinend mit den
Makros nicht zurecht.
Schade, dabei klang das so schlüssig in dem Link. Jetzt ist wohl
Fehlersuche angesagt...
Wenn ich die Funktion einfach kopiere beschwert sich der Compiler...und
findet Fehler in der stm32f446xx.h?
Wühlhase schrieb:> er hängt an dieser Stelle fest:>> //Wait for HSI is stable running> while(RCC -> CR & RCC_CR_HSIRDY){}>> Warum kommt der da nicht aus der Schleife raus? Anscheind wird das> HSI-Ready-Flag nicht gesetzt...aber wieso?
Naja, weil die Bedingung genau falsch herum ist: "Solange HSI ready ist
..."
JAAAAAAhahahaaaa...es klappt! :)
Die while-Schleife war das Problem....war wohl etwas spät geween, jetzt
klappts. :)
Ich stelle mal die laufende Funktion rein. Falls jemand anders die mal
braucht...
Nico W. schrieb:> Dann hoffen wir Mal dass er die anderen Stellen auch findet :)
Versteh ich nicht. Die Taktinit läuft jetzt. Und wenn ich einen Timer so
mißbrauche daß er als Taktteiler bis herunter in den Hertzbereich dient
(Einfaches Blinklicht) scheint das Teil zu tun was es soll.
Oder hast du noch Fehler gefunden...?
Nico W. steht immer noch im Raum mit seinem "ich sehe was, was Du nicht
siehst und das ist falsch ..."
Nur leider spendiert er uns keine Auflösung zu seinem Menetekel.
@Wühlhase:
Ich selber nutze zum Aufsetzen meines Clocktrees die Funktionen der
Standard Peripheral Library (SPL) von ST, weil ich einfach annehme, dass
die Funktionen darin inzwischen einen entsprechenden Reifegrad erreicht
haben.
In Deinem Fall könntest Du ggf. Deine Clock-Initialisierung einmal mit
der Funktion "static void SetSysClock(void)" aus dem File
"system_stm32f4xx.c" vergleichen.
Beim Überfliegen schienen mir in der SPL-Funktion noch ein paar Dinge
mehr beachtet zu sein, als es in Deiner Funktion der Fall ist. Auch
passiert dort einiges an "Casting", was bei Dir gänzlich fehlt. Aber
einen Detailvergleich habe ich nicht gemacht - dafür kenne ich mich
einfach nicht hinreichend gut in der Materie aus.
Viele Grüße
Igel1
@Andreas:
Die Standardbibliothek...als ich mich mit den STM32 das erste Mal
beschäftigt habe war die schon abgekündigt. Ich habe deren Sinn bisher
noch nie recht verstanden. Die Registerbezeichnungen nochmal hinter
einem Struct versteckt-ich hab nich gesehen wo mir das Arbeit erspart
hätte. Das Datenblatt hätte ich so oder so lesen müßen (ist ja kein
Arduino), und die Werte die ich sonst direkt in die Register geschrieben
hätte, werden dann halt stattdessen in eine Struktur gepackt.
Und dann ist die auch noch für jede Controllerfamilie unterschiedlich
(dieses Manko soll ja die HAL ausbügeln). Nee...in die SPL arbeite ich
mich lieber nicht mehr ein. Entweder HAL, wenn es sein muß, oder lieber
direkt Register...
Noch etwas:
Andreas S. schrieb:> Beim Überfliegen schienen mir in der SPL-Funktion noch ein paar Dinge> mehr beachtet zu sein, als es in Deiner Funktion der Fall ist. Auch> passiert dort einiges an "Casting", was bei Dir gänzlich fehlt. Aber> einen Detailvergleich habe ich nicht gemacht - dafür kenne ich mich> einfach nicht hinreichend gut in der Materie aus.
Die HAL macht sicher auch noch einiges mehr als mein Codeschnipsel da
oben. Ich hab mir das HAL-Pendant dazu auch noch nicht angesehen, aber
die Funktion um ein Byte aus der SPI rauszuschieben ist etwas über 100
Zeilen lang. Da wird dann noch geprüft ob die Hardware wirklich frei
ist, lauter Fehlerflags geprüft, auf Freigaben gewartet, und am Ende
alles wieder aufgeräumt und freigegeben.
Die STL ist zwar sicher nicht so überladen, ich kann mir aber vorstellen
daß da auch die ein oder andere Sicherung drin ist die man sich bei
direktem Registerzugriff selber baut oder wegläßt.
Wühlhase schrieb:> Die STL ist zwar sicher nicht so überladen, ich kann mir aber vorstellen> daß da auch die ein oder andere Sicherung drin ist die man sich bei> direktem Registerzugriff selber baut oder wegläßt.
Die Frage ist ja stets "Habe ich an alles gedacht, was manchmal quer
über die 1600 Seiten Reference Manual verstreut ist oder nicht?"
Denn wenn Code in meinem Test funktioniert, so heißt das noch lange
nicht, dass dieser Code auch in allen späteren
Lebenslagen/Programmzuständen funktionieren wird. Und deshalb schaue ich
mir der SPL-Funktionen gerne an.
Die besagte Funktion "static void SetSysClock(void)" aus dem File
"system_stm32f4xx.c" sollte für Dich als CMSIS-Nutzer ein offenes Buch
sein.
Dafür brauchst Du Dich definitiv nicht in die SPL einarbeiten und hast
trotzdem den Vorteil, Deinen Code mit dem Code von jemand anderem (der
mehr oder weniger dasselbe implementiert hat) vergleichen zu können.
Aber das ist nur meine ganz persönliche Meinung - selbstverständlich hat
da so jeder seine eigene Herangehensweise und ich möchte Dich zu nichts
zwingen ...
Viele Grüße
Igel1
Andreas S. schrieb:> Die besagte Funktion "static void SetSysClock(void)" aus dem File> "system_stm32f4xx.c" sollte für Dich als CMSIS-Nutzer ein offenes Buch> sein.
Hm...ich hab die Funktion mal eben gesucht, find sie im Projekt aber
nicht...?
Andreas S. schrieb:> Aber das ist nur meine ganz persönliche Meinung - selbstverständlich hat> da so jeder seine eigene Herangehensweise und ich möchte Dich zu nichts> zwingen ...
Nun, ich schätze mal daß sich in diesem Thread hier jeder mit dem STM32
besse auskennt als ich-ich stell hier ja nicht umsonst Fragen. Ich hab
dich da wohl falsch verstanden...
Wühlhase schrieb:> Andreas S. schrieb:>> Die besagte Funktion "static void SetSysClock(void)" aus dem File>> "system_stm32f4xx.c" sollte für Dich als CMSIS-Nutzer ein offenes Buch>> sein.> Hm...ich hab die Funktion mal eben gesucht, find sie im Projekt aber> nicht...?
In dem von Dir referenzierten Projekt wird kein SPL verwendet,
deshalb gibt es dort das File "system_stm32f4xx.c" nicht.
Wenn Du Dir das Teil anschauen möchtest, mußt Du zunächst die SPL hier
herunterladen: http://www.st.com/en/embedded-software/stsw-stm32065.html
(Letzter Link "Get Software").
Schön auspacken ...
Dann findest Du das File "system_stm32f4xx.c" hier:
STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Libraries\CMSIS\Device\ST\STM32F4xx\S
ource\Templates
> Andreas S. schrieb:>> Aber das ist nur meine ganz persönliche Meinung - selbstverständlich hat>> da so jeder seine eigene Herangehensweise und ich möchte Dich zu nichts>> zwingen ...> Nun, ich schätze mal daß sich in diesem Thread hier jeder mit dem STM32> besse auskennt als ich-ich stell hier ja nicht umsonst Fragen. Ich hab> dich da wohl falsch verstanden...
Ganz und gar nicht - ich bin ebenfalls nur STM32-Anfänger.
Meine Ratschläge sind also mit Vorsicht zu geniessen.
Viele Grüße
Igel1
Andreas S. schrieb:> Nico W. steht immer noch im Raum mit seinem "ich sehe was, was Du nicht> siehst und das ist falsch ...">> Nur leider spendiert er uns keine Auflösung zu seinem Menetekel.
Liegt auch daran, dass ich nicht mit F5 im Forum rumstöbere und manchmal
ein paar Tage auch was anderes zu tun habe.
Ich dachte, dass der TO nach dem Hint
A. B. schrieb:> Naja, weil die Bedingung genau falsch herum ist: "Solange HSI ready ist> ..."
und meiner Anmerkung, vielleicht einmal den Code genauer ansieht und den
gleichen Fehler ein paar Zeilen später wieder erkennt.
Ist vielleicht nur Zufall, dass das Init durchläuft.
Wühlhase schrieb:> //Wait for PLL is stable running> while(RCC -> CR & RCC_CR_PLLRDY){}
Weiter suche ich jetzt nicht. Aber das ist mir halt auch noch
aufgefallen.
Ich muß mich nochmal mit Schande zurückmelden. Die Clockinit läuft
längst nicht so wie sie soll.
Gemerkt hab ich es erst so richtig bei der UART-Benutzung. Wenn ich von
der Baudrate auf die Taktung zurückrechne, müßte APB1 mit etwa 18MHz
laufen statt mit 45MHz, wobei ich nicht weiß wie stark der FT232
überabtastet und dabei Fehler vermeidet.
Ich habe außerdem einen Timer, der eine LED im Sekundentakt toggelt, 1s
an, 1s aus. Ich zähle insgesamt 20 Perioden, und die parallel laufende
Stoppuhr zeigt knapp 1min (statt der zu erwartenden 40s).
Ich finde nichts mehr was ich noch einzustellen vergessen haben könnte.
Die Warteschleifen beim Warten auf HW-Konfiguration sollten auch korrekt
laufen. Hab ich irgendetwas in der falschen Reihenfolge gemacht?
Ich hab mir auch den Code angesehen den CubeMX generiert, aber auch da
nichts gefunden was mir aufgefallen wäre.
Hat noch jemand eine Idee? Die aktuelle Clockinit sieht so aus, das
Projekt in den Anhang gestopft falls es jemandem hilft:
Wühlhase schrieb:> //Set clock for APB1 to AHB/4 => 180MHz/4 -> 45MHz> RCC -> CFGR |= RCC_CFGR_PPRE1_DIV8;>> //Set clock for APB2 to AHB/2 => 180MHz/2 -> 90MHz> RCC -> CFGR |= RCC_CFGR_PPRE2_DIV8;
Ich hab jetzt keine Lust, mich durch die defines zu wühlen, aber
merkwürdig sieht das schon aus.
Wühlhase schrieb:> //Wait for PLL is stable running> while(RCC -> CR & !RCC_CR_PLLRDY){}
Das sieht auch nicht richtig aus. !RCC_CR_PLLRDY ist wahrscheinlich
nicht das worauf du testen willst. Das ist müsste normal zu 0 werden.
Guten Morgen
@Nop:
Argh...das ist ein Überbleibsel vom Testen, das ist keiensfalls der
"normale" Code.
Allerdings ist mir dabei eines aufgefallen was mich stutzig macht,
jedoch finde ich keine Erklärung dafür. Wenn ich beide Bustakte durch 8
teile, statt der Teiler in den Kommentaren, ändert sich an der
Blinkfrequenz der LED genau gar nichts.
Hatte jemand das Problem schon mal oder kennt jemand den STM32 gut genug
um zu wissen was da schief gegangen sein könnte? Kann das mit dem
Problem, das Nico noch entdeckt hat, zusammenhängen? (Ich hätte jetzt
nein gesagt, aber ich weiß es halt nicht.)
@Nico:
Allmählich schäme ich mich für mein C...danke fürs Finden.
Wühlhase schrieb:> //Switch SYSCLK to HSI, SW -> 00> RCC -> CFGR &= ~RCC_CFGR_SW_0;> RCC -> CFGR &= ~RCC_CFGR_SW_1;
Keine gute Idee, je nachdem, ob der Compiler das eventuell "in einem
Rutsch" macht. Alle zusammengehörenden Bits sollten in nur einem
Schreibzugriff gemeinsam verändert werden. Sonst gibt's u. U. ungültige
"Zwischenzustände".
> //Set AHB clock prescaler for main bus matrix, psc=1 for running with> maximum speed -> 180MHz, Presc. =1
Die max. Abweichung der HSI-Frequenz vom Soll beträgt -8%/+4.5%! Da
würde ich sicherheitshalber 10% unter den 180MHz bleiben. Auch wenn man
den Prozessor sicher problemlos etwas übertakten kann, solide sieht
anders aus.
Angesichts dieser Toleranz ist UART damit schon recht optimistisch. Na
gut, bei konstant Zimmertemperatur geht's ja aber ...
> RCC -> CFGR &= ~RCC_CFGR_HPRE_3 & ~RCC_CFGR_HPRE_2 & ~RCC_CFGR_HPRE_1> & ~RCC_CFGR_HPRE_0;>> //Set clock for APB1 to AHB/4 => 180MHz/4 -> 45MHz> RCC -> CFGR |= RCC_CFGR_PPRE1_DIV8;
Und hier werden plötzlich alle Bits gemeinsam gesetzt? Aber auch nur
gesetzt, eventuell zu löschende (da in RCC_CFGR_PPRE1_DIV8 eventuell =0,
eventuell vorher schon mal gesetzt) bleiben auf '1'! Wenig
änderungsfreundlich.
> //Set clock for APB2 to AHB/2 => 180MHz/2 -> 90MHz> RCC -> CFGR |= RCC_CFGR_PPRE2_DIV8;
S. o.
> //Select HSI for pll clock source> RCC -> PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSI;
Das macht keinen Sinn, denn das PLLSRC-Bit muss für HSI auf '0' gesetzt
werden. Ist zwar nach Reset sowieso '0', aber ...
> //Set prescaler for pll clock input: HSI(16MHz) -> input should be> 1-2MHz -> Prescaler =10, clock is set to 1,6MHz> RCC -> PLLCFGR |= RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_1;
Wieder Bitfeld, wo nur die Einsen passend gesetzt, aber die Nullen nicht
gelöscht werden ...
> //Clock = fin*(N/P) -> 1,6MHz*(225/2) for 180MHz> //Set N=225 -> 0b1110 0001> RCC -> PLLCFGR |= RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 |> RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLN_0;
dto.
> //Set P=2 0b00> RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLP_1 & ~RCC_PLLCFGR_PLLP_0;
und hier mal umgekehrt.
Wenn es Unklarheiten bzgl. des tatsächlichen Taktes gibt, bleiben zwei
offensichtliche Optionen:
1) Nach der Taktkonfiguration sieht man sich alle Registerwerte noch
einmal an und kontrolliert jedes einzelne(!) Bit anhand des Ref.Man. Es
gibt da übrigens auch noch ein paar Statusbits ...
Generell ist die Frage, was tatsächlich in den Registern steht, nicht
das, was man glaubt, hineingeschrieben zu haben.
2) MCO1 oder MCO2 aktivieren und Oszi / Frequenzzähler an den Ausgang.
Beim Teiler gibt's nur wenige Möglichkeiten, so dass man sich kaum
vertun kann.
Per Schleife ein Portbit togglen und messen oder ähnliche Methoden sind
angesichts der vielen Einflüsse (Wait-States, Prefetch, Pipeline,
GPIO-Eigenheiten ...) kaum praktikabel.
Oha...noch viel mehr was anders besser zu machen wäre.
Ich werde erst heute Nachmittag dazu kommen das zu ändern, aber trotzdem
eine Frage: Steht in den Registern grundsätzlich eine 0, wenn es nicht
überschrieben bzw. im Programm nichts anderes vorgesehen wird?
(Statusbits die von der HW geändert werden natürlich ausgenommen.)
Oder ist das auch anders...
>> RCC -> CFGR &= ~RCC_CFGR_SW_0;>> RCC -> CFGR &= ~RCC_CFGR_SW_1;> Keine gute Idee, je nachdem, ob der Compiler das eventuell> "in einem Rutsch" macht.
Das wird nie der Fall sein.
Wieso ist es heutzutage verpönt, sich die Herstellerdoku wenigstens mal
kurz anzusehen?
Ich rede hier nur vom kurzen Überfliegen und nicht vom Auswendiglernen?
Stattdessen wird irgendwo aus dem Netz abgekupfert und das auch noch von
Quellen, die entweder selber sich nicht mit Fachwissen belasten oder
aber wie hier von einem anderen Controller handeln.
Grundsätzlich:
Die Konfiguration ist kein Hexenwerk und dementsprechend auch nicht
schwer. Steht alles im Datenblatt und Reference Manual. Teils sogar sehr
detailliert. Muss man halt nur lesen.
Wer also die beiden Dokumente mal überflogen hat, merkt sofort, dass der
Controller, der hier mit 180MHz betrieben werden soll, anders als der
Controller aus der ungeeigneten Quelle (168MHz) konfiguriert werden
muss. @Wühlhase: Wieso berücksichtigst Du das nicht?
Datasheet September 2016, DocID027107 Rev 6, Seite 76 (auch Reference
Manual Seite 65):
Für 180MHz muss der Spannungsregler im Overdrive-Modus laufen. Wieso
programmierst Du den nicht entsprechend?
Detailliert beschrieben im Reference Manual July 2017, DocID026976 Rev
3, Seite 96.
Die HSI-Clocksource ist nach dem Reset aktiviert, die muss man gar nicht
konfigurieren, wie Du das machst (Reference Manual, Seite 126).
Das Lesen der Reset Werte empfiehlt sich auch für andere Register. Das
spart nämlich unnötigen Platz im Flash und Performance.
Daher mal ein Vorschlag hier (aus dem Bauch heraus, nicht getestet
mangels Controller):
Bei letzterem nimmst Du völlig krude Werte. Wieso die 1,6MHz als
VCO-Eingangsfrequenz, wenn das Reference Manual auf Seite 129
unmissverständlich schreibt:
"It is recommended to select a frequency of 2 MHz to limit PLL jitter."
?
1
RCC->CR|=(RCC_CR_PLLON);
2
while(!(RCC->CR&RCC_CR_PLLRDY))
3
asm("nop");
4
5
PWR-CR|=(PWR_CR_ODEN);
6
while(!(PWR->CR&PWR_CSR_ODRDY))
7
asm("nop");
8
9
RCC->CFGR|=(RCC_CFGR_SW_PLL);
10
while((RCC->CFGR&RCC_CFGR_SWS)!=RCC_CFGR_SWS_PLL)
11
asm("nop");
Es können noch ein paar kleinere Fehler drin sein, ausprobieren kann ich
das jetzt nicht.
Im Groben sollte das aber so reichen.
Für eine "richtige" Anwendung solltest Du in die while-Schleifen noch
einen Timeout einbauen, falls da was schiefgeht und dann entsprechend
eine Notfallroutine starten.
Zum Schluss nochmals die Empfehlung:
Überflieg kurz Datasheet und Reference Manual. Sieht erstmal nach viel
aus, aber die komplette Peripherie kannst Du ja am Anfang weglassen,
damit ist der größte Teil schonmal raus.
Wenn Du dann so einen Controller programmierst, schau Dir im Manual
jedes Register an und überlege, ob das für Dich Relevanz hat.
Falls ja, dann konfiguriere es entsprechend, falls es nicht eh schon den
benötigten Wert als Reset Wert hat. Doppelt hält in diesem Falle nicht
besser...
Nachdem Wühlhase von Nico W. und U. Rectum vor zwei Tagen die volle
Breitseite bekommen hat, möchte ich hier ein wenig mein Mitgefühl
ausdrücken:
Wer sich nur hobbymäßig mit einem solchen Prozessor beschäftigt und
dafür vielleicht 5h jeweils verteilt über die Woche investieren kann,
der ist mit 2000-3000 Seiten Doku (Ref + Datasheet + Application Notes)
wirklich am Limit (jedenfalls gilt das für mich).
Dem Vorwurf "Steht alles genau im RefMan." oder "Wieso ist es heutzutage
verpönt, sich die Herstellerdoku wenigstens mal kurz anzusehen?" steht
man da etwas sprachlos gegenüber: natürlich habt Ihr recht - aber was
soll ein Hobbymensch dagegen machen? Job an den Nagel hängen? Frau und
Kinder verkaufen? Hobby an den Nagel hängen? Oder sich vielleicht doch
in diesem Forum von hilfsbereiten Geistern unter die Arme greifen
lassen?
Ich bin für letztere Alternative ...
Und um auch etwas Inhaltliches beizutragen, hier an Wühlhase nochmals
den Tipp: schau Dir an, wie die Clock-Initialisierung in der Funktion
"SystemInit()" in der SPL (Standard Peripheral Library) realisiert
wurde.
Die ist von ST selbst publiziert worden, ist millionenfach erprobt und
sogar an Dinge wie "overclocking" ist dort gedacht worden.
Entgegen Deiner Befürchtungen brauchst Du Dich dafür nicht in die
komplette SPL einzuarbeiten. Es sollte ausreichen, wenn Du die Datei
"system_stm32f4xx.c" gut durcharbeitest.
Viele Grüße
Igel1
@U Rectum:
So verpönt ist DB-Lesen nicht...im Gegenteil. Und wenn im Kapitel zur
Taktungerzeugung auch was vom Spannungsstabilisator stehen würde,
wenigstens ein Hinweis in normaler Schriftgröße, hätte ich das bestimmt
schon ausprobiert.
Danke aber dennoch für den Hinweis, das sind genau die Kleinigkeiten
weswegen ich hier frage.
Trotzdem-ein normaler Umgangston würde die deutlich besser zu Gesicht
stehen. Mach ich denn echt den Eindruck, dieses Schreiben so komplett zu
ignorieren?
@Andreas:
Ich werd das mit der SPL wohl nochmal überdenken und sie mir mal
ansehen.
Danke
Breitseite?
Das war ein Hinweis! Nur weil ich nicht in jedem Satz einen Smiley nutze
und du das falsch interpretiert hast, heißt das noch lange nicht das
hier scharf geschossen wird.
Btw. Ich habe mit uC im Berufsleben wenig zu tun. Bei solchen Sachen
braucht man Zeit. Davon habe ich auch nur sehr begrenzt. Bis mein ADC
über DMA lief, verging ein halbes Jahr. Nicht weil ich zu blöd war,
vielleicht ein wenig, hätte ja abgucken können, vor allem weil ich wenig
Zeit habe und mir nicht alles vorkauen lassen möchte.
Wühlhase schrieb:> Ich werd das mit der SPL wohl nochmal überdenken und sie mir mal> ansehen.
Ich weiss auch gar nicht, warum SPL bei dir so tabu ist, zumal es sich
hier um Programmteile handelt, die ein einziges Mal beim Startup laufen
- das Argument mit den angeblich so langsamen Routinen zählt hier nicht.
Noch ein Hinweis - für z.B. stabile I²S Clocks werden z.B. 2MHz als
Raster der ersten PLL empfohlen, 1 Mhz jittert hier deutlich mehr.
Matthias S. schrieb:> Wühlhase schrieb:>> Ich werd das mit der SPL wohl nochmal überdenken und sie mir mal>> ansehen.>> Ich weiss auch gar nicht, warum SPL bei dir so tabu ist, zumal es sich> hier um Programmteile handelt, die ein einziges Mal beim Startup laufen
Weil gerade die system_xxx Maximal-Bloat ist. Für das bisschen
Register-Setzen?
Das Verständnis für die Controller wird dabei auch nicht besser.
Und nochmals: Auch wenn einen die Seitenanzahl der Doku erschreckt, wenn
man nur die relevanten Teile (Reset, Power, Clock) durchliest, weiss man
schnell Bescheid, wenn man zuvor schon AVR oder andere Controller
programmiert hat.
> Noch ein Hinweis - für z.B. stabile I²S Clocks werden z.B. 2MHz als> Raster der ersten PLL empfohlen, 1 Mhz jittert hier deutlich mehr.
Hatte ich oben bereits angemerkt:
U. Rectum schrieb:> Bei letzterem nimmst Du völlig krude Werte. Wieso die 1,6MHz als> VCO-Eingangsfrequenz, wenn das Reference Manual auf Seite 129> unmissverständlich schreibt:> "It is recommended to select a frequency of 2 MHz to limit PLL jitter."
Ich hab mir die SPL jetzt mal angesehen...das wirft aber mehr Fragen auf
als es mir beantwortet. Vielleicht ist das aber auch ganz gut...
Zum Beispiel: Gleich zu Beginn aktiviert die Funktion den HSE. Was
passiert da eigentlich, wenn gar kein Quarz angeschlossen ist?
Wühlhase schrieb:> Was> passiert da eigentlich, wenn gar kein Quarz angeschlossen ist?
Das steht zumindest bei mir in der SetSysClockToHSE() (STM32F10x):
1
else
2
{/* If HSE fails to start-up, the application will have wrong clock
3
configuration. User can add here some code to deal with this error */
Wühlhase schrieb:> Ich hab mir die SPL jetzt mal angesehen...das wirft aber mehr Fragen auf> als es mir beantwortet. Vielleicht ist das aber auch ganz gut...>> Zum Beispiel: Gleich zu Beginn aktiviert die Funktion den HSE. Was> passiert da eigentlich, wenn gar kein Quarz angeschlossen ist?>
Hiermit wird der externe Oszillator eingeschaltet:
1
/* Enable HSE */
2
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
Man könnte meinen, dass der STM32 anschließend stehenbleibt, wenn kein
Quarz angeschlossen ist ...
Wenn da nicht die folgenden 2 kleinen Sätze im Referenz Manual RM0090,
Revision 15 in Kapitel "6.2.1 HSE clock", page 154 unten ständen:
1
The HSERDY flag in the RCC clock control register (RCC_CR) indicates if the high-speed external oscillator is stable or not. At startup, the clock is not released until this bit is set by hardware.
Kurzum: der Prozessor ist schlau genug, sich nicht den Ast (HSI) selbst
abzusägen, auf dem er sitzt. Umgeschaltet wird nur, wenn:
1.) Du den Befehl erteilt hast (per HSEON bit)
2.) Der Prozessor mit dem HSE-Signal zufrieden ist (was er Dir
netterweise anzeigt, indem er das HSERDY bit setzt)
Dazu findet man in der Registerbeschreibung von RCC_CR unter dem Bit
HSERDY:
1
Set by hardware to indicate that the HSE oscillator is stable. [...]
Wenn also nach HSE_STARTUP_TIMEOUT while-Schleifendurchläufen (immerhin
0x05000 an der Zahl) das HSERDY-Bit noch immer nicht gesetzt ist, so
bleibt HSEStatus=0 und das Programm rennt weiter unter Nutzung seines
internen Oszillators.
Die anschließende Konfiguration von PLL & Co. wird übrigens nur dann
vorgenommen, wenn HSEStatus==1. Wenn das nicht der Fall ist, so landest
Du in der von Walter Tarpan in seinem letzten Posting zitierten
Code-Sektion.
Will sagen: das ist schon alles ganz gut durchdacht und genau deshalb
empfehle ich das Studium eben dieser SPL-Routinen.
Viele Grüße
Igel1