Hallo Forum,
ich versuche seit Tagen, nachdem mein JTAG-Problem endlich erledigt ist,
mein Systemtakt zum fliegen zu bekommen, doch es klappt iwie nicht.
Der Controller ist ein STM32F446ret6. Mit einem generierten Cube-Code
funktioniert alles bestens nur mein selbst geschriebener Code läuft
einfach nicht und ich verstehe nicht warum. Hier mein Code:
functions.c
1
voidRCC_config(void)
2
{
3
/* GPIOA, GPIOB und GPIOC aktiv */
4
RCC->AHB1ENR|=0x00000007;
5
6
/* [16]: HSE ON, [24]: PLLM */
7
RCC->CR|=0x01010001;
8
9
/*
10
[1:0]: 01 PLL_P, [3:2] PLL, -> hier müsste der System Source Mux sein
11
[12:10]: 100 APB1 div2
12
[22:21]: 11 MCO1 aktiv, PLL */
13
RCC->CFGR|=0x0060100A;
14
15
/*
16
[5:0]: 00 1111 PLLM= div15
17
[14:6]: 0110 0000 PLLN= *96 */
18
RCC->PLLCFGR|=0x0000180F;
19
}
20
21
/*GPIO-Konfigurationen*/
22
voidGPIO_config(void)
23
{
24
/*Konfiguration GPIOA */
25
GPIOA->MODER|=0x01020000;/*PA.08 als AF, PA.12 als Ausgang */
26
}
27
28
voidstartUp(void)
29
{
30
SystemInit();
31
SystemCoreClockUpdate();
32
SysTick_Config(SystemCoreClock/1000);
33
RCC_config();
34
GPIO_config();
35
}
main.c
1
intmain()
2
{
3
startUp();
4
5
while(1)
6
{
7
/*hier kommt noch Code herein*/
8
}
9
}
Auf MCO1 kommt kein Taktsignal an, was heißt, das irgendwo eine
Unterbrechung ist, bloß wo? Wechsel ich auf den internen HSI, zeigt er
mir 16 MHz an und bei HSE die 25 MHz.
Vielen Dank Euch im Voraus!
Gruß
Daniel
>Mit einem generierten Cube-Code>funktioniert alles bestens nur mein selbst geschriebener Code läuft>einfach nicht
Dann vergleiche mit dem generierten Code. Wo ist das Problem?
holger schrieb:>>Mit einem generierten Cube-Code>>funktioniert alles bestens nur mein selbst geschriebener Code läuft>>einfach nicht>> Dann vergleiche mit dem generierten Code. Wo ist das Problem?
Das ist es ja, ich finde den Fehler einfach nicht :(
Der einzige Unterschied zwischen meinem und dem Cube ist der aktivierte
HSI. Das habe ich auch schon ausprobiert, es kommt dennoch kein
Taktsignal an. Eine LED kann ich im Debugmode jedoch ein- und
ausschalten.
Gruß
Daniel
>Das ist es ja, ich finde den Fehler einfach nicht :(
Dann schau im Debugger nach was mit dem generierten Code
in den Registern landet.
> RCC->CFGR |= 0x0060100A;
Wer sowas macht, der frisst auch kleine Kinder.
Komplett unwartbarer Code.
holger schrieb:> Wer sowas macht, der frisst auch kleine Kinder.> Komplett unwartbarer Code.
Sehe ich ein bisschen anders.Ich habe mir eine entsprechende
Exceltabelle gebaut, der mir aus Bits die Hex berechnet (und umgekehrt)
und dann gehe ich Schritt für Schritt ins Datenblatt und setze das
jeweilige Bit.
Die Registerwerte sind im Debugmodus etwas anders, da Cube eine andere
Grundkonfiguration vornimmt.
Gruß
Daniel
>Die Registerwerte sind im Debugmodus etwas anders, da Cube eine andere>Grundkonfiguration vornimmt.
Und es gibt dir nicht zu denken das die von Cube erzeugte
etwas andere Grundkonfiguration läuft? Schätze dich glücklich
dass du die Registerwerte für eine funktionierende Konfiguration
von Cube zum vergleichen hast. Jetzt nimmst du jedes abweichende
Bit zu deiner Konfiguration und schaust im Datenblatt nach
was da noch so eingestellt wird von Cube. Und nochmal:
Wo ist das Problem? Es wird sich vermutlich niemand hinsetzen
und deine Hexzahlen im Datenblatt für dich nachvollziehen.
Daniel V. schrieb:> Sehe ich ein bisschen anders.Ich habe mir eine entsprechende> Exceltabelle gebaut
Das ist schön, aber anscheinend ja nicht lauffähig. Da die ganze Chose
nur einmal abgearbeitet wird, ist es auch gar nicht notwendig, hier
unbedingt ein paar Takte zu sparen. Ich vermisse ausserdem die
obligatorische Warterei auf eine stabile PLL, du machst einfach weiter,
als würde es schon gutgehen...
Daniel V. schrieb:> Ich stehe gerade auf den Schlauch...
Ich zitiere mal einige Zeilen aus cmsis_boot/stm32f4xx.c, betreffend der
Konfiguration der PLL:
Der normale Ablauf geht so, wobei ich die Fehlerbehandlung für nicht
funktionierenden HSE jetzt mal unterschlage:
- HSI und HSE anwerfen
- auf HSI warten
- CFGR resetten und auf HSI setzen
- warten, daß das System auf HSI läuft
- PLL abschalten
- warten, bis PLL down ist
- warten, daß HSE hochgelaufen ist (timeout!)
- power regulator enable
- voltage scaling passend zur Zielfrequenz einstellen
- warten, bis voltage regulator läuft
- PLL konfigurieren, mit den Faktoren und der Quelle
- PLL anwerfen
- warten, bis PLL läuft
- ABP-Vorteiler einstellen
- Flash-Einstellungen (waitstates usw.) machen
- System auf die PLL als Taktgeber aufschalten
- warten, bis die PLL das System befeuert (timeout!)
Wenn man das gründlich machen will, wertet man den Timeout beim Anwerfen
des HSE aus und schaltet die PLL im Fehlerfall stattdesen auf den HSI
auf, dann mit entsprechend etwas anderen Skalierungsfaktoren.
Nop schrieb:> Der normale Ablauf geht so
Genau, die meisten Sachen, die SetSysClk macht, hast du schön
beschrieben, die habe ich oben nur rausgenommen, um den TE nicht noch
mehr zu verwirren :-P
Ehrlich gesagt verstehe ich auch nicht, warum man das Rad unbedingt neu
erfinden muss und dafür komplett unlesbaren Code erstellt - der dann
auch nicht klappt.
Ob man HAL oder CMSIS benutzt, ist sicher Geschmackssache, aber dieses
Bitgemurkse des TE muss bei solch grundlegenden Sachen wirklich nicht
sein.
Matthias S. schrieb:> Genau, die meisten Sachen, die SetSysClk macht, hast du schön> beschrieben, die habe ich oben nur rausgenommen, um den TE nicht noch> mehr zu verwirren :-P
hrhr^^ naja was die SetSysClk zum Beispiel nicht so gut macht, ist, den
HSI überhaupt erstmal anzustellen. Den schalte ich nämlich am Ende auch
noch ab, wenn das System auf HSE und PLL läuft, spart halt etwas Strom.
Wenn man dann aber im Betrieb die Taktung dynamisch umstellt, muß man
den HSI ja auch wieder anwerfen.
SetSysClk hat außerdem keine Fehlerbehandlung für einen versagenden HSE,
das muß man selber imlementieren. Kann ja beim Bestücken mal
runtergefallen und kaputtgegangen sein.
Sowas logt man dann im POST und dem Systemfehlerspeicher, aber auch auf
HSI hat man bei Raumtemperatur dann noch eine Timinggenauigkeit von 1%.
Also 30 Sekunden Ungenauigkeit pro Stunde.
> Ehrlich gesagt verstehe ich auch nicht, warum man das Rad unbedingt neu> erfinden muss
Ich nutze auch weder HAL noch SPL noch CMSIS, aber logischerweise ein
Headerfile mit Bitdefinitionen, deren Benamung nach Datenblatt geht.
Dann finde ich das im Datenblatt auch sofort wieder.
das geht dann zum Beispiel als:
#define RCC_CR_PLLON ((uint32_t)(1ul << 24))
> Ob man HAL oder CMSIS benutzt, ist sicher Geschmackssache, aber dieses> Bitgemurkse des TE muss bei solch grundlegenden Sachen wirklich nicht> sein.
Jep. Und mit einer Exceltabelle, übler geht's kaum. Wird unlustig, wenn
man so ein Projekt in ein paar Jahren anfassen will und auf dem Rechner
kein Excel ist oder Excel in der dann vorhandenen Version mal wieder
irgendwelche Funktionen umbenannt hat, so daß das Tool dann nicht mehr
geht.
Ich bin leider kein Super-ARM Profi, aber neben den anderen
tollen Hinweisen, fand ich den vom Kinderfresser noch mit
am wichtigsten:
Du setzt per ODER ("|=") die Bits in den Config-Registern,
ohne zu beachten, dass dort ja durchaus schon andere Bits
gesetzt sein können.
Anschließend werden dort Bitkombinationen zu finden sein,
die Du so vermutlich gar nicht gewollt hast.
... was jetzt allerdings nicht heißt, dass die anderen Tipps
anschließend nicht genauso umgesetzt werden müssten.
Wenn ich selbst die Clocks unbedingt auf die "harte" Tour von
Hand einstellen möchte, so nehme ich eines der Beispiele aus
der Peripheral Library und editiere dann kräftig in
"system_stm32f4xx.c" herum (selbstverständlich geht's auch
eleganter ..) - dort kannst Du die Parameter aus dem Excel-File
von Hand einstellen. Klappt wunderbar.
Viele Grüße
Igel1
Daniel V. schrieb:> Auf MCO1 kommt kein Taktsignal an, was heißt, das irgendwo eine> Unterbrechung ist, bloß wo?
Soll das ein Clockausgang sein? Dann würde ich die Ausgabe darauf
erstmal aktivieren.
PS. Und du meinst dich in einem anderen Thread über OS X als
Entwicklungsbetriebssystem für embedded lustig zu machen? Verwendest
aber gleichzeitig ein beschissenes Excel-Sheet um unwartbaren
Schrottcode zu erzeugen? Dass ich nicht lache...
Hall Leute,
erstmal vielen Dank an Euch. Der hardwarenahe Programmierstil hatte ich
mir angewöhnt um erstens einen Geschwindigkeitsvorteil zu schaffen und,
so meine Erfahrung bei dem STMF0, hat dies sehr gut geklappt. Allerdings
hatte ich den HSI-Clock benutzt.
Aber, ihr habt ja recht, wartbar ist der Code nicht wirklich, besonders
wenn ein Fremder diesen Code warten muss. Völlig richtig.
Andreas S. schrieb:> Du setzt per ODER ("|=") die Bits in den Config-Registern,> ohne zu beachten, dass dort ja durchaus schon andere Bits> gesetzt sein können.
Völlig richtig.
Horst schrieb:> Und du meinst dich in einem anderen Thread über OS X als> Entwicklungsbetriebssystem für embedded lustig zu machen? Verwendest> aber gleichzeitig ein beschissenes Excel-Sheet um unwartbaren> Schrottcode zu erzeugen? Dass ich nicht lache...
Lustig nicht, sondern hinterfragt. Das Excelsheet kennst Du ja nicht.
Das habe ich mir selber geschrieben.
Ich werde heute Abend mich nochmal melden. Vielen Dank an nop und
Andreas an dieser Stelle.
Gruß
Daniel
Daniel V. schrieb:> Ich werde heute Abend mich nochmal melden. Vielen Dank an nop und> Andreas an dieser Stelle.
Oh nein - dieser Dank gebührt nicht mir, sondern holger (Gast),
der Dich in diesem Beitrag oben auf die Gefahren der Veroderung
ohne vorige Variablen-Initialisierung hinwies:
Beitrag "Re: STM32F4: Taktprobleme"
Er hatte daraus sogar eine Einschätzung Deiner kulinarischen
Vorlieben abgeleitet.
Ich habe an seinen (Wink mit dem) Zaunpfahl lediglich noch etwas
Lametta drangehängt, damit Du den Wink bzw. den Pfahl besser
kommen siehst :-)
Viele Grüße & viel Erfolg beim Fixing
Igel1
Andreas S. schrieb:> Oh nein - dieser Dank gebührt nicht mir, sondern holger (Gast),> der Dich in diesem Beitrag oben auf die Gefahren der Veroderung> ohne vorige Variablen-Initialisierung hinwies:> Beitrag "Re: STM32F4: Taktprobleme"
Den hatte ich jetzt schickt unterm Tisch fallen lassen ;)
Andreas S. schrieb:> Er hatte daraus sogar eine Einschätzung Deiner kulinarischen> Vorlieben abgeleitet.
Igitt...
Also, diese Art zu coden (Peripherie->Register = HEXWERT) ist gar nicht
so unüblich (ist mir auch hier im Forum schon desöfteren begegnet), da
ich auch beruflich viel so in dieser Art coden muss. Nur weil es dem
Holger (Gast) nicht gefällt muss das nicht schlecht sein. Klar, bei der
Fehlersuche kann das echt mies sein und auch die Unwartbarkeit ist nicht
gegeben (außer für mich), da gebe ich Euch im vollen Umfang recht ;)
Andreas S. schrieb:> Viele Grüße & viel Erfolg beim Fixing
Danke Dir. Ich habe auch eine Idee. Werde den Fix auch dann hier
bekanntgeben.
Gruß
Daniel
Daniel V. schrieb:> lso, diese Art zu coden (Peripherie->Register = HEXWERT) ist gar nicht> so unüblich (ist mir auch hier im Forum schon desöfteren begegnet), da> ich auch beruflich viel so in dieser Art coden muss.
Niemand "muß" so coden, denn defines kann jeder C-Compiler. Hardwarenah
bedeutet nicht programmiererischen Pfusch. "Magic numbers" sind ein
bekanntes Antipattern in der Programmierung.
Wenn Dir das beruflich viel begegnet, dann zeigt es nicht, daß es üblich
ist, sondern daß Deine Firma programmiertechnsich zum unteren Drittel
gehört. Entweder, die haben noch nie etwas von Codereviews gehört, oder
sie sind nicht in der Lage, die angemessen durchzuführen.
> Nur weil es dem> Holger (Gast) nicht gefällt muss das nicht schlecht sein
Stimmt. Es ist aber schlecht, weil es Holger aus genau den zutreffenden
Gründen nicht gefällt: Fehlersuche kannste vergessen, Wartbarkeit
ebenfalls.
> auch die Unwartbarkeit ist nicht gegeben (außer für mich),
Du schreibst Code so, daß ihn jeder warten kann, außer Dir? (;
Nop schrieb:> Wenn Dir das beruflich viel begegnet, dann zeigt es nicht, daß es üblich> ist, sondern daß Deine Firma programmiertechnsich zum unteren Drittel> gehört. Entweder, die haben noch nie etwas von Codereviews gehört, oder> sie sind nicht in der Lage, die angemessen durchzuführen.
Du glaubst gar nicht,was wir für einen Dokumentenkrieg wir haben.
Nop schrieb:> Du schreibst Code so, daß ihn jeder warten kann, außer Dir? (;
Blöd formuliert. Im diesen Falle warte ich den Code selber.
Aber, hey, ich habe es geschafft. Der Controller taktet nun mit 80 MHz.
Ich habe die PLL in der system_stm32f4xx.c angepasst.
Danke an Euch allen
Daniel
Pete K. schrieb:> Du zeigst uns nicht alles. Salamitaktik?
Zumindest zeigt er uns seinen persönlichen Ersatz für
SystemClock_Config.
Und nee, er will das alles mit eigener Bitschieberei machen, anstatt HAL
oder CMSIS zu benutzen. Da das nicht so richtig funktioniert hat, hat er
hier den Thread gemacht.
Aber der TE ist ziemlich lernresistent und schaut sich auch nicht an,
wie es die Jungs von ST machen, und ja, das halte ich für ziemlich dumm.
Es wäre ja nicht wirklich schwierig, sich mal stm32F4xx.c anzuschauen...
Ich warte jetzt darauf, das der TE externen SDRAM oder den Flash
konfiguriert.
holger schrieb:> Wer sowas macht, der frisst auch kleine Kinder.> Komplett unwartbarer Code.
Man könnte mit W.C. Fields sagen 'Wer Tiere und kleine Kinder hasst,
kann kein ganz schlechter Mensch sein', aber irgendwann ist Schluss -
vor allem wenn man die Grundregeln von C nicht kennt, aber eine 32-Bit
ARM Kiste zu Fuss programmieren will.
Bist Du jetzt fertig? Es gibt keine stm32f4xx.c sondern eine
system_stm32f4xx.c. Und wenn Du das hier gelesen hast:
Daniel V. schrieb:> aber, hey, ich habe es geschafft. Der Controller taktet nun mit 80 MHz.> Ich habe die PLL in der system_stm32f4xx.c angepasst.
wirst Du erkennen, dass ich sehr wohl mich mit den ST-Dateien
beschäftige. Und ja, ich habe mich verrannt das gebe ich gerne zu. Wie
hat mal mein Werkstoffkundeprof einmal gesagt? "Erfahrung ist die Summe
aller Fehler"
Aber Du bist anscheinend fehlerlos und der
superdupermikrocontrollercassemblerking...
Das Thema ist aber nun erledigt.
Nein, das Thema ist eigentlich noch lange nicht erledigt. Auch wenn du
inzwischen beleidigt reagierst.
Daniel V. schrieb:> ich versuche seit Tagen, nachdem mein JTAG-Problem endlich erledigt ist,> mein Systemtakt zum fliegen zu bekommen, doch es klappt iwie nicht.Daniel V. schrieb:> {>> RCC_OscInitTypeDef RCC_OscInitStruct;> RCC_ClkInitTypeDef RCC_ClkInitStruct;>> __HAL_RCC_PWR_CLK_ENABLE();
Warum ich das hier zitiere?
Nun, du bist wie der Friseur an den µC herangegangen. Anders gesagt, du
hast ein bissel an der Oberfläche von Cube und ST-Lib herumgetingelt und
herumgekratzt, aber den Chip verstanden hast du nicht. Aber genau das
wäre es, was dich wirklich weitergebracht hätte.
jaja, es ist ja so bequem, sich Initialisierungen und sonstiges Zeugs
per Fremdanbieter (egal ob Cube oder CMSIS oser St-Lib oder sonstwas)
machen zu lassen, aberes ist eben auch ein ganz erhebliches Stück
Unselbständigkeit und Unkenntnis, die das ausmacht. Jetzt hast du es mal
gemerkt, wie sehr man durch schiere Unkenntnis auf die Nase fallen und
in den Wald rennen kann, aber anstatt dich zu besinnen und die Nase ins
RefManual zu stecken um wissender zu werden, reagierst du beleidigt. Ist
nicht gut, sowas.
Nochwas zum Stil:
1
// RCC_CFGR fertig setzen bis auf PLL-Auswahl
2
RCC_CFGR=(1<<16)|// Quarz-Oszi als Input für PLL
3
(4<<11)|// APB2 Vorteiler auf :2 (72-->36 MHz)
4
(4<<8)|// APB1 Vorteiler auf :2 (72-->36 MHz)
5
(0<<17)|// Quarz nicht :2 teilen vor der PLL
6
(4<<18)|// PLL Teiler: 4--> x6, also 12MHz*6-->72MHz
7
(7<<24)|// 7 = PLL:2 an MCO = PA.8 zur Beobachtung
8
(1<<22)|// USBPRES, vermutlich 72MHz/1.5-->48MHz
9
0;
wie du siehst, braucht man kein Excel, um aus Bits Hex-Zahlen zu machen.
Es geht auch lesbarer. Gelle?
W.S.
Hier einmal ein paar Gedanken, die mir bei der Lektüre dieses Threads
durch den Kopf gehen:
- Muss ich wirklich andere Menschen, die meiner Meinung nach
(und vielleicht auch gemäß "best practice"-Regeln)
nicht perfekt coden, derartig zurechtweisen?
- Wart Ihr wirklich schon immer so perfekt? Oder habt Ihr nicht auch
aus Fehlern gelernt - sowohl aus den eigenen, als auch aus denen
anderer Menschen?
- Und wart Ihr dann dankbar, wenn Euch die Dinge in freundlicher,
höflicher Art und Weise erklärt wurden? Oder habt Ihr harsche
Zurechtweisungen und Rechthaberei geschätzt?
- Und selbst wenn es 1000 Gründe gibt, etwas rechtsherum zu tun,
beansprucht Ihr nicht auch für Euch das Recht, es trotzdem
linksherum machen zu dürfen? (warum auch immer!)
- Und ist es nicht genau dieser letzte Punkt, den man Toleranz nennt?
Viele Grüße
Igel1