Ich benutze das Nucleo L073RZ Board mit der Arduino IDE und lasse eine
LED blinken:
1
voidsetup(){
2
pinMode(PA5,OUTPUT);
3
}
4
5
voidloop(){
6
digitalWrite(PA5,LOW);
7
delay(500);
8
9
digitalWrite(PA5,HIGH);
10
delay(500);
11
}
Funktioniert bis dahin. Die Blink-Frequenz der LED bestätigt, dass das
Setup korrekt funktioniert.
Dann habe ich mir den Quelltext der Taktkonfiguration angeschaut und
gesehen, dass der Systemtakt vom internen Oszillator HSI (= 16 MHz)
bezogen wird. Das möchte ich auf HSE (= 8 MHz vom ST-Link) umstellen.
Aber egal wie ich es versuche, die CPU läuft immer nur halb so schnell
wie sie soll.
Versuch 1:
Zuerst habe ich den Code von STM32duino kopiert und modifiziert. Ich
habe HSI durch HSE ersetzt und die PLL verdoppelt. Das sollte wieder 32
MHz ergeben, läuft aber nur halb so schnell.
1
voidSystemClock_Config(void)
2
{
3
4
RCC_OscInitTypeDefRCC_OscInitStruct={};
5
RCC_ClkInitTypeDefRCC_ClkInitStruct={};
6
RCC_PeriphCLKInitTypeDefPeriphClkInit={};
7
8
/* Configure the main internal regulator output voltage */
Hans W. schrieb:> Was übersehe ich?
Zunächst übersiehst du mal dass dir bei jedem Beitrag, den du
schreibst, gesagt wird dass:
"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"
Länger bedeuted in diesem Zusammenhang "mehr als eine Bildschirmseite".
Das ist ein Gebot der Freundlichkeit und der Netiquette.
Siehe dazu speziell auch "Äußere Form".
Hallo,
Hans W. schrieb:> Was übersehe ich?
Du hast die Hardwarekonfiguration geändert, nur das Programm selbst weiß
noch nichts davon. Funktionen wie delay() beruhen auf der Definition vom
CPU Takt.
Du müsstest noch #define F_CPU anpassen. Heißt bei AVR so, ob der Name
bei STM gleich lautet weiß ich nicht, nehme ich aber stark an.
Edit:
Wenn bei STM 'SystemCoreClock' dem AVR 'F_CPU' entspricht und du das
geändert hast, dann weiß ich es nicht.
Veit D. schrieb:> Du hast die Hardwarekonfiguration geändert, nur das Programm selbst weiß> noch nichts davon. Funktionen wie delay() beruhen auf der Definition vom> CPU Takt.
Daran liegt es nicht. Diese Zeilen erledigen das:
> SystemCoreClock=72000000;> SysTick_Config(SystemCoreClock/1000);
Habe ich mit anderen Frequenzen auf Basis des HSI gegen getestet.
> Du müsstest noch #define F_CPU anpassen. Heißt bei AVR so, ob der Name> bei STM gleich lautet weiß ich nicht, nehme ich aber stark an.
F_CPU ist als Alias für SystemCoreClock definiert.
Ich habe das Problem auch unabhängig von allen Frameworks mit einem
minimalen Projekt in der Cube IDE. Auch dieses Programm läuft nur halb
so schnell, wie es sollte.
Das ist aber echt schräg, dass durch diesen Fehler exakt die halbe
Taktfrequenz entsteht. Ich habe dieses HSEBYP Bit noch nie zuvor
benutzen müssen. Werde mich jetzt dazu einlesen.
Alexander schrieb:> Was übersehe ich?> SET_BIT(RCC->CR, RCC_CR_HSEBYP);
Haha, echt witzig. Als wäre ich nicht kurz vorher selbst drauf gekommen.
Bonusfrage extra für dich:
Warum ist die Taktfrequenz ohne dieses bit exakt halb so hoch?
Alexander schrieb:> Beitrag "STM32 HSE bypass mode"
Danke für den Link. Ich hatte den Thread trotz intensiver Suche nicht
gefunden. Dort hat Gerd eine mögliche Ursache beschrieben und jemand
hatte den gleichen Effekt.
Nur die Erklärung habe ich nicht verstanden. Die Schmitt‑Trigger
Hysterese des OPV teilt die Frequenz da nur steigende Flanken überhaupt
erkannt werden. Bei jeder Flanke wird getoggelt. Liegt es daran dass ein
PWM ein über 0 geschobenes Signal ist und die negative Welle unter 0 vom
echten Sinus die man von einem schwingenden Quarz erwarten würde einfach
ausbleibt?
Eine andere mögliche Erklärung wäre, dass der Oszillator das rechteck
Signal als Fehler interpretiert und wiederholt Neustarts versucht.
Mein Chef hat angeregt, mal das Ausgangssignal des Oszillators zu
messen. Das werde ich heute Abend tun. Bin gespannt, was wir dort zu
sehen bekommen.
Hans W. schrieb:> Ich habe das Problem auch unabhängig von allen Frameworks mit einem> minimalen Projekt in der Cube IDE. Auch dieses Programm läuft nur halb> so schnell, wie es sollte.
Aus deinem Code:
// 32 MHz using the 8 MHz HSE oscillator multiply by 8 divide by 2
RCC->CFGR = RCC_CFGR_PLLSRC_HSE + RCC_CFGR_PLLMUL8 + RCC_CFGR_PLLDIV2;
Schau dir mal das Register im Debugger an was da für bits gesetzt wurden
und dann das gleiche mit:
RCC->CFGR = RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL8 | RCC_CFGR_PLLDIV2;
Hans-Georg L. schrieb:> Schau dir mal das Register im Debugger an was da für bits gesetzt wurden> und dann das gleiche mit
Macht keinen Unterschied.
Hans W. schrieb:> mal das Ausgangssignal des Oszillators zu> messen. Das werde ich heute Abend tun.
Blöderweise tritt der Fehler heute nicht mehr auf (mit HSEBYP=0).
Ron-Hardy G. schrieb:> Bitte mit 2-Kanal-Oszi damit man Ein-und Ausgang gegenüberstellen kann.
Ich habe einzeln gemessen, weil ich die Tastköpfe sonst nicht sicher
hätte halten können. Interessant, dass das Ausgangssignal (2) so einen
geringen Pegel hat.
Ich lass das mal eine Weile laufen und behalte die blinkende LED im
Blick. Vielleicht kommt der Fehler später doch wieder.
Ich habe nicht bedacht, dass dieses HSEBYP Bit nur mit einem Power-Cycle
zurück gesetzt werden kann. Meine Änderung im Code hatte deswegen keine
Auswirkung.
Fehler ist wieder da, und jetzt gibt es auch was interessantes zu sehen.
Die Messpunkte sind wieder die gleichen wie in meinem vorherigen
Beitrag.
Hans W. schrieb:> Hans-Georg L. schrieb:>> Schau dir mal das Register im Debugger an was da für bits gesetzt wurden>> und dann das gleiche mit>> Macht keinen Unterschied.>
Glaube ich nicht, denn A+B+C ist ungleich A|B|C
Da fehlt auch noch das verunden mit der Maske die alle PLL Bits (Bit 16
bis 23) vorher löscht. Wahrscheinlich hast du irgendwelche MUX im
gleichen Register überbügelt und der Takt kommt vielleicht nicht von der
PLL. Vergleiche das komplette Register mit Ref Manual ob alle Bits
richtig sind.
Wenn der Chip einen MCO Ausgang hat kannst du den Systemtakt auch
ausgeben.
Hans-Georg L. schrieb:> A+B+C ist ungleich A|B|C
Trifft hier nicht zu, weil in A B und C keine überlappenden Bits gesetzt
sind.
> Da fehlt auch noch das verunden mit der Maske die alle PLL> Bits (Bit 16 bis 23) vorher löscht.
Nein. Die Zuweisung benutzt keine alten Bits auf dem Register.
> Wahrscheinlich hast du irgendwelche MUX im gleichen Register> überbügelt und der Takt kommt vielleicht nicht von der PLL.
Nein. Siehe ganz oben mein Gegentest "Versuch 3:".
> Vergleiche das komplette Register mit Ref Manual ob alle> Bits richtig sind.
Habe ich doch alles gemacht, wozu hat man sonst einen Debugger?
> Wenn der Chip einen MCO Ausgang hat kannst du den> Systemtakt auch ausgeben.
Damit ich einen dritten Indikator für die halbe Taktfrequenz bekomme?
Brauche ich nicht. Der Systick timer und eine einfache erprobte
delay-loop genügen mir als Beweis.
Und dann haben wir noch den Screenshot vom Oszilloskop, den ich gerade
in Beitrag "Re: STM32L073RZ läuft auf HSE nur halb so schnell wie erwartet"
nachgereicht habe.
Können wir jetzt bitte aufhören, von dem eigentlichen Problem
abzulenken?
Alexander schrieb:> Ist das die Rückkopplung am Eingang? Da ist wohl nur jeder zweite Peak> über der Schaltschwelle.
Habe ich im Schaltplan mit (2) beschriftet. Das ist der OSC_OUT
Anschluss.
Ich weiß nicht, was du mit "Rückkopplung" und "Hysterese des OPV"
meinst. Ich kann den Chip nicht aufsägen und hinein kriechen.
Aber da dies der Ausgang des Oszillators ist, kann man wohl deutlich
sehen, dass er gerade versagt.
Alexander schrieb:> Ich bin einfach mal von einem Pierce-Oszillator ausgegangen. Die> Rückkopplung erfolgt über den Widerstand von Ausgang zu Eingang des> Operationsverstärkers.
Das Eingangssignal habe ich ja auch dargestellt - ein sauberer Rechteck
mit 3,3V Pegeln.
Schau dir nochmal die Bilder in
Beitrag "Re: STM32L073RZ läuft auf HSE nur halb so schnell wie erwartet" an. 1=Eingang,
2=Ausgang
Ich denke, damit ist offensichtlich, dass der Oszillator anders
aufgebaut ist.
Alexander schrieb:> Muss ja nicht derselbe Eingang sein. OPV haben doch zwei Eingänge, die> Abbildung ist nur ein Schaltsymbol.
Das Ding im Pierce-Oszillator (den wir hier offensichtlich NICHT haben)
ist kein OPV, sondern ein CMOS Inverter.
Okay. Das Schaltzeichen habe ich dann wohl verwechselt. Hatte mich
bisher nur mit OPV auseinandergesetzt.
https://www.elektronik-kompendium.de/sites/bau/0209241.htm
Jedenfalls ist mir noch nicht klar wie genau diese Dreiecksspitzen
rauskommen können, immer schön ein großer und ein kleiner Peak im
Wechsel, wenn das Eingangssignal doch ein Rechtecksignal ist. Da muss es
eine Form von Rückkopplung/Verzerrung geben.
Alexander schrieb:> Jedenfalls ist mir noch nicht klar wie genau diese Dreiecksspitzen> rauskommen können
Das werden wir wohl nie erfahren, ohne die Innenschaltung des
Oszillators zu kennen.
Hans W. schrieb:> Ich habe nicht bedacht, dass dieses HSEBYP Bit nur mit einem Power-Cycle> zurück gesetzt werden kann. Meine Änderung im Code hatte deswegen keine> Auswirkung.>> Fehler ist wieder da, und jetzt gibt es auch was interessantes zu sehen.>> Die Messpunkte sind wieder die gleichen wie in meinem vorherigen> Beitrag.
Und HSEBYP kann nur geschaltet werden wenn HSE aus ist.
Ist der OSC_OUT GPIO richtig geschaltet ?. Sollte kein Ausgang mehr sein
und HiZ haben.
Alexander schrieb:> Jedenfalls ist mir noch nicht klar wie genau diese Dreiecksspitzen> rauskommen können
deswegen bat ich um eine 2-Kanal-Erfassung um die zeitlichen
Verhältnisse zu sehen.
Hans W. schrieb:> Hans-Georg L. schrieb:>> Ist der OSC_OUT GPIO richtig geschaltet ?.>> Habe ich nicht geändert, also im Zustand wie vom Reset vorgegeben.
Mir kam der Pegel der da rauskommt für reines internes Übersprechen
etwas hoch vor ...
Vielleicht probierst du es nochmal mit der HAL. Ich lasse für meine
Bords den RCC den Code durch CubeMX als makefile erzeugen, und hatte
noch nie Probleme. Habe aber auch kein L073RZ Nucleo-Board nur
G4,H4,H7,H7R als Nucleo und andere.
Das würde dann etwa so aus sehen (H7):
Hans-Georg L. schrieb:> Vielleicht probierst du es nochmal mit der HAL.
Habe ich doch, mit Cube MX generiert. Damit tritt der gleiche Fehler
auf, wenn ich das HSEBYP Bit falsch (nicht) setze. Und mit Arduino
ebenso. Und auch ohne Framework.
> hatte noch nie Probleme.
Dito. Deswegen hat es mich ja überrascht. Bis vor kurzem dachte ich,
dass Bit sei optional und nur dazu da, den externen Ausgang des
Oszillators zu deaktivieren.
> RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;> Wenn es dann funktioniert durch den Code steppen
Es ist seit
Beitrag "Re: STM32L073RZ läuft auf HSE nur halb so schnell wie erwartet" klar,
dass es am HSEBYP Bit scheiterte. Hast du nicht gelesen?
So ein Oszillator muss dafür sorgen, dass der Quarz sicher anschwingt.
Aber anschliessend soll die Amplitude möglichst weit reduziert werden um
den Quarz nicht zu überlasten und um Strom zu sparen - gerade bei den L
Typen.
Also stellt er mit dem externen 3.3 V Rechteck die minimale Verstärkung
ein, die ist aber zu klein, also dreht er wieder auf...
Nur meine 2 Cent Theorie...
Hans W. schrieb:> Habe ich doch, mit Cube MX generiert. Damit tritt der gleiche Fehler> auf, wenn ich das HSEBYP Bit falsch (nicht) setze. Und mit Arduino> ebenso. Und auch ohne Framework.> Es ist seit> Beitrag "Re: STM32L073RZ läuft auf HSE nur halb so schnell wie erwartet" klar,> dass es am HSEBYP Bit scheiterte. Hast du nicht gelesen?
Bei mir hat CUBE MX das HSEBYP noch nie falsch gesetzt ;-)
Was mir Heute Morgen noch aufgefallen ist ...
Du setzt den Bypass und den HSE gleichzeitig.
SET_BIT(RCC->CR, RCC_CR_HSEON + RCC_CR_HSEBYP);
Im RM steht HSEBTYP kann(soll) nur gesetzt werden wenn HSE off.
Vielleicht gibt es an der Stelle ein überschneiden das den Oszillator
hochlaufen lässt und den externen Takt dazu koppelt. Schalte mal erst
den HSEBYP und dann den HSE ein. Evtl. noch ein paar Takte warten
dazwischen.
Alexander schrieb:> Im Datenblatt steht etwas von einer 4 MHz Quelle
Auf der Suche nach dieser Quelle fand ich ein Bildnis wunderschön ;)
Hans-Georg L. schrieb:> Du setzt den Bypass und den HSE gleichzeitig.> SET_BIT(RCC->CR, RCC_CR_HSEON + RCC_CR_HSEBYP);> Im RM steht HSEBTYP kann(soll) nur gesetzt werden wenn HSE off.
Du bist Rechtsanwalt, gib's zu ;)
Bauform B. schrieb:> Hans-Georg L. schrieb:>> Du setzt den Bypass und den HSE gleichzeitig.>> SET_BIT(RCC->CR, RCC_CR_HSEON + RCC_CR_HSEBYP);>> Im RM steht HSEBTYP kann(soll) nur gesetzt werden wenn HSE off.>> Du bist Rechtsanwalt, gib's zu ;)
Nö, ich bin Rentner;-)
Bauform B. schrieb:> Auf der Suche nach dieser Quelle fand ich ein Bildnis wunderschön ;)
Pierce-Oszillator mit CMOS-Inverter ohne Hysterese und abschaltbaren
Rückkopplungswiderstand?
https://de.wikipedia.org/wiki/TranskonduktanzverstärkerHans-Georg L. schrieb:> Vielleicht gibt es an der Stelle ein überschneiden das den Oszillator> hochlaufen lässt und den externen Takt dazu koppelt.
Könnte man mit einem 4 MHz Takt einen 8 MHz Quarz anschwingen?
Es gibt noch einen Widerspruch. Die Messung an PF0 und PF1 passt gut zu
dem Bild
https://www.mikrocontroller.net/attachment/697915/STM32L073-oscillator.png
und das Signal am PF1 würde auch den halben CPU-Takt erklären. Im Bild
ist "fHSE to core" aber am Eingang des Inverters angeschlossen. Wenn das
stimmt, müsste die CPU mit dem vollen Takt laufen.
Den halben Takt gibt es nur am Ausgang des Inverters. Instinktiv hätte
ich den Chip auch so verdrahtet. Am Ausgang gibt es ein geregeltes
niederohmiges Signal, am Eingang ist das Signal klein und hochohmig und
man verstimmt unnötig den Quarz.
Hans-Georg L. schrieb:> Was mir Heute Morgen noch aufgefallen ist ...> Du setzt den Bypass und den HSE gleichzeitig.> SET_BIT(RCC->CR, RCC_CR_HSEON + RCC_CR_HSEBYP);> Im RM steht HSEBTYP kann(soll) nur gesetzt werden wenn HSE off.
Schau dir die Doku des Registers an und den Quelltext der HAL, dann
siehst du, dass ich es richtig gemacht habt.
> Schalte mal erst den HSEBYP und dann den HSE ein.
Schau dir die Doku des Registers an, dann siehst du ...
HSEBYP kann man nicht einschalten, wenn HSE bereits eingeschaltet ist.
Hans W. schrieb:> Schau dir die Doku des Registers an,
Sorry Hans-Georg, ich habe dich missverstanden. Mir scheint gerade zu
viel Sonne auf Dach.
Ich denke, ich könnte wirklich zuerst HSEBYP=1 setzen und danach
HSEON=1. Aber wozu? Es funktioniert ja auch so.
===========================
Was ich eigentlich schreiben wollte:
Da hier einige Leute offenbar den Knackpunkt verpasst haben, fasse ich
die Situation nochmal zusammen.
Ich war es gewohnt, dass man wahlweise einen Quarz oder eine externe
Taktquelle anschließen konnte, wenn HSEBYP=0 ist. Am vergangenen
Wochenende klappte das plötzlich nicht mehr, obwohl Board und Quelltext
beide alt und erprobt waren.
Symptom: Der Systemtakt ist nur 4 MHz, obwohl die Taktquelle 8 MHz
liefert. Das zweite Oszillogramm vom Pin PF1/OSC_OUT bestätigt die
Fehlfunktion des fremd getriebenen Oszillators.
Es stellte sich heraus, dass das Problem verschwindet, wenn man das
HSEBYP Bit passend zur Schaltung auf 1 setzt. Es ist also doch wichtig.
Bitte hört auf, meine Registerzugriffe zu hinterfragen. Ja, ich hatte
anfangs darum gebeten, aber inzwischen ist 100% klar, dass es nur an
diesem einem HSEBYP Bit hängt. Und wie man es richtig setzt ist auch
klar, dazu brauche ich keine Hilfe.
Wir haben KEIN Softwareproblem mehr.
Die einzige Frage, die man hier noch sinnvoll weiter diskutieren kann,
ist: Warum verhält sich der Oszillator so? Was könnte Elektrotechnisch
dahinter stecken?
Hans W. schrieb:> Die einzige Frage, die man hier noch sinnvoll weiter diskutieren kann,> ist:
.... ob man beim Setzen eines Registers die Tokens der einzelnen
Bits addiert oder ver-odert. Ich sage: nein, addieren von Bits
tut man nicht tuten, denn es könnten mal ein paar Bits übereinander
liegen und das ergibt dann einen falschen Registerwert und man sucht
sich ggf. dumm und dämlich.
Hans W. schrieb:>
snip .....
> Was ich eigentlich schreiben wollte:> Da hier einige Leute offenbar den Knackpunkt verpasst haben, fasse ich> die Situation nochmal zusammen.>
Super !!!
> Ich war es gewohnt, dass man wahlweise einen Quarz oder eine externe> Taktquelle anschließen konnte, wenn HSEBYP=0 ist. Am vergangenen> Wochenende klappte das plötzlich nicht mehr, obwohl Board und Quelltext> beide alt und erprobt waren.>> Symptom: Der Systemtakt ist nur 4 MHz, obwohl die Taktquelle 8 MHz> liefert. Das zweite Oszillogramm vom Pin PF1/OSC_OUT bestätigt die> Fehlfunktion des fremd getriebenen Oszillators.>> Es stellte sich heraus, dass das Problem verschwindet, wenn man das> HSEBYP Bit passend zur Schaltung auf 1 setzt. Es ist also doch wichtig.>> Bitte hört auf, meine Registerzugriffe zu hinterfragen. Ja, ich hatte> anfangs darum gebeten, aber inzwischen ist 100% klar, dass es nur an> diesem einem HSEBYP Bit hängt. Und wie man es richtig setzt ist auch> klar, dazu brauche ich keine Hilfe.>> Wir haben KEIN Softwareproblem mehr.>
Ihr habt kein Softwareproblem mehr schön für euch !
Denke aber bitte mal daran, das dies ein öffentliches Forum ist und
Suchmaschinen den Thread finden. Wenn irgenwann mal jemand hier, mit dem
gleichen Problem, vorbei kommt, findet er dann die Lösung oder ist er
noch mehr verwirrt ?. Deshalb habe ich nachgefragt, und kommentiert,
nicht um dich zu ärgern.
Mit dem gleichzeitigen setzen der beiden bits sehe ich noch Probleme.
Weil der HSE Zeit braucht um hoch zu laufen, deshalb gibt es die while
Schleife zum warten bis das Bit HSE läuft gesetzt ist und ich nehme sehr
stark an das dieses Bit zum Sperren des HSEBYP benutzt wird. Was
passiert dann bei gleichzeitigen setzen ? Deshalb würde ich es nicht
empfehlen. Ok du hast keine Zeit für Versuche zu machen. Vielleicht
probiere ich das mal, ich habe hier noch ein Nucleo L476.
> Die einzige Frage, die man hier noch sinnvoll weiter diskutieren kann,> ist: Warum verhält sich der Oszillator so? Was könnte Elektrotechnisch> dahinter stecken?
Das habe ich mir auch überlegt ...
Der 8MHz Takt liegt am Eingang an und regt gleichzeitig die
Oszillatorschaltung an, die wiederum über den Rf Widerstand eingekoppelt
wird. Aber dann müsste sie doch mit 8MHz schwingen. Woher kommen die
4MHz ?
Meine Theorie ist, es verhält sich wie "Injection-locked oscillators".
Damit kann man mit 2 Oszillatoren gleicher Frequenz ganzzahlig
dividieren.
Das ist reine Spekulation von mir, aber eine andere Lösung ist mir nicht
eingefallen. Vielleicht kennt sich da ja Jemand besser aus ...
https://www.hajim.rochester.edu/ece/sites/laics/ilo_fd_m/
Bau den Oszillator doch mal simuliert auf, vielleicht in was besserem
als Falstad, und dann fahre die Spannung mal langsam hoch und
übersteuere den CMOS Inverter bis das Signal so verzerrt wird wie auf
_MAP002.bmp