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 */
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.
Du hast die Hardwarekonfiguration geändert, nur das Programm selbst weiß
noch nichts davon. Funktionen wie delay() beruhen auf der Definition vom
CPU Takt.
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.
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?
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;
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.
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.
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.
Ich bin einfach mal von einem Pierce-Oszillator ausgegangen. Die Rückkopplung erfolgt über den Widerstand von Ausgang zu Eingang des Operationsverstärkers.
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.
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.
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.
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.
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
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...
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.
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.
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 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.
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.
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.
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?
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.
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 ...
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