Mahlzeit allerseits
Ich hätte da mal eine Frage:
Gibt es irgendwo so etwas wie eine Dokumentation zur LL? Das, was sich
im CubeMX Firmwarepackage unter Documentation verbirgt kommt mir eher
wie ein schlechter Witz vor.
Es ist ja eigentlich nett und idiotensicher von ST gelöst, die
Registerzugriffe hinter Funktionen zu verstecken. Wenn die Funktionen
vernünftig benannt sind, kommt da gut lesbarer Code raus, finde ich. Das
gefällt mir, auch besser als direkte Registerzugriffe mit logischen
Verknüpfungen.
Aber wie finde ich z.B. die Funktion, mit der ich einen Timer loslaufen
lassen oder wieder anhalten kann? Sich im Eclipseverschnitt durch die
Autocodevervollständigung durchzuhangeln finde ich jetzt weniger gut,
allzumal das teilweise etwas uneindeutig ist.
Und sich ein Beispielprojekt zu suchen in der Hoffnung, daß dieses die
Hardware verwendet die man auch benutzen will...das ist eine nette
Demonstration, aber keine Doku.
Und duckduckgo findet leider auch nichts außer Werbeflyer.
Ich suche eigentlich so etwas wie eine Funktionsübersicht oder so. Gibt
es da irgendetwas hilfreiches?
Vielen Dank.
die einzelnen files sind nicht so riesig. Ich bin bisher immer damit
zurechtgekommen, einfach mal durch zu lesen, was es da so gibt. Da neben
das ref manual, damit man versteht, was die Register tun.
Machmal ist es auch hilfreich, mit dem STM32CubeMX ein Projekt
aufzusetzen und in den generierten Code zu schauen, wie z.B. die
Initialisierung aussieht.
Und aus der Erfahrung raus: Es ist sehr viel angenehmer, die
LL-funktionen zu verwenden, als selbst in den Registern rum zu stochern.
Viele Grüße,
Hermann
Die einzige gute Doku von ST sind die in CubeMX mitgelieferten
Beispielprojekte. Ansonsten hilft der griff zur Reference Manual, da die
LL-Treiber in der Regel eh nur einzelne Registerzugriffe abstrahieren.
Low-Level-Programmierer schrieb:> Es ist ja eigentlich nett und idiotensicher von ST gelöst, die> Registerzugriffe hinter Funktionen zu verstecken. Wenn die Funktionen> vernünftig benannt sind, kommt da gut lesbarer Code raus, finde ich. Das> gefällt mir, auch besser als direkte Registerzugriffe mit logischen> Verknüpfungen.>> Aber wie finde ich z.B. die Funktion, mit der ich einen Timer loslaufen> lassen oder wieder anhalten kann?
Also was hast du eigentlich davon, wenn du für jeden HW-Registerzugriff
anstelle des eigentlichen Zugriffs eine Funktion aufrufst? Willst du
bloß Taktzyklen verbraten?
Ich glaube auch nicht, daß da ein guter Code herauskommt. Daß so etwas
schön lesbar sein kann, glaube ich dir sofort - aber ist so etwas auch
gut verstehbar? Oder kommt da gar ein guter Algorithmus bei heraus?
Nein, eben nicht.
Lowlevel-treiber sollten die Dinge abstrahieren, also nicht so:
void SetzePin(int port, int bit, bool hi_lo);
sondern so:
void SchalteLampeEin(void);
Ich denke, du merkst den Unterschied: Das SetzePin abstrahiert überhaupt
nichts, sondern verallgemeinert bloß. Noch mehr verallgemeinert wäre
das:
void SetzeBit(int variable, int bit, bool hi_lo);
Aber wer braucht so etwas denn?
Zweck der Abstrahierung ist, daß man sich in den höheren
Programmschichten eben NICHT mehr um die niederen Details zu kümmern
braucht. Also nicht darum, wie denn nun die Lampe eingeschaltet wird.
Aber so etwas bietet ST eben nicht an, sondern alles bleibt immerzu sehr
ST-spezifisch.
Kann man verstehen, muß man aber nicht gut heißen.
Für dein Beispiel zum starten und stoppen des Timers würde auch gehören,
ihn aufzusetzen, also Taktquelle, Flanke, intern/extern, Vorteiler und
so weiter. Und das alles mit separaten Funktionen, wo doch viele
Einstellungen im selben Einstell-Register vorzunehmen sind? Nein, hier
ist der direkte HW-Zugriff gefragt - und dieser möglichst in einem
separaten Lowlevel-Treiber, der ein hardwareunabhängiges Interface hat.
Etwa sowas:
long MissZeitdifferenz(long TakteBisTimeout);
W.S.
W.S. schrieb:> Also was hast du eigentlich davon, wenn du für jeden HW-Registerzugriff> anstelle des eigentlichen Zugriffs eine Funktion aufrufst? Willst du> bloß Taktzyklen verbraten?
nachdem viele der ST-Funktionen inline definiert sind, hält sich der
Overhead vermutlich in Grenzen. Und selbst wenn: Optimierung sollte
immer der letzte Schritt sein, wenn die Software an sich funktioniert.
Und das meiste holt man sicherlich nicht bei einer handgestrickten
Initialisierung der Peripherie raus...
> Ich glaube auch nicht, daß da ein guter Code herauskommt. Daß so etwas> schön lesbar sein kann, glaube ich dir sofort - aber ist so etwas auch> gut verstehbar? Oder kommt da gar ein guter Algorithmus bei heraus?> Nein, eben nicht.
Abstraktion hat erstmal nichts mit der Funktionalität an sich zu tun,
eher etwas mit Wiederverwendbarkeit und Portabilität.
> Lowlevel-treiber sollten die Dinge abstrahieren, also nicht so:>> void SetzePin(int port, int bit, bool hi_lo);>> sondern so:>> void SchalteLampeEin(void);
Sinnvolle Abstraktion besteht aus mehreren Schichten. Sonst schreibt man
die Software für jedes Projekt neu. In Deinem Beispiel also eher nicht:
void SchalteLampeEin(void);
sondern:
void SetzePin(LampenPin);
wenn das für die Applikation sinnvoll ist, kann man darüber ja noch was
spezifischeres setzen:
dann habe ich ein Lampenmodul, das z.B. nicht nur anbietet:
Lampe_einschalten(Lampe1) sonder auch z.B.
Lampe_aktiviereBlinken(Lampe1), oder Lampe_einschaltenMitTimeout(timeout
in ms)
Auch ST bietet ja zwei Schichten an:
einmal die LL, die die Registerzugriffe abstrahiert und verständlicher
macht. Um die selbst sinnvoll zu nutzen, sollte man durchaus wissen, wie
die Register aussehen und die jeweilige Einheit aufgebaut ist.
die nächste Schicht bei ST ist dann die HAL, die die HW weiter
abstrahiert und erweiterte Features wie Ringpuffer für den Usart, usw
anbietet.
Die finde ich persönlich allerdings auch etwas überladen, weshalb wir
uns auf Basis der LL eine eigene HAL gebaut haben.
Die Verwendung der LL hat dabei den Vorteil, das wir ohne größere
Umbaumaßnahmen innerhalb einer Controllerfamile (STM32G0, STM32F1,
STM32L0, usw) wechseln können.
Die darüberliegende Schicht ermöglich dann z.B. die "gleiche"
Applikation auf einem STM32 oder auf einem STM8 o.ä. laufen zu lassen.
Ein bisschen Anpassung ist im Zweifel schon nötig, aber kein Vergleich
als wenn man alles mit direkten Registerzugriffen geschrieben hätte.
Viele Grüße,
Hermann
errdzg schrieb:> In Deinem Beispiel also eher nicht:> void SchalteLampeEin(void);> sondern:> void SetzePin(LampenPin);
Nein, dein Beispiel ist schlecht, denn es setzt ja voraus, daß man die
Lampe über ein Pin einschaltet. Das definiert man dann in einer .h und
hat das dann in den Algorithmus eingeschleust, wo es nicht hin gehört.
Denn verschiedene Plattformen haben auch verschiedene Port-Definitionen
und verschiedene Ansteuerung für Portpins und damit hat man dann den
ganzen Kruscht mitten in den Programmteilen, wo eigentlich nur der
Algorithmus hingehört, aber nicht die Einzelheiten der aktuellen
Peripherie.
Das SchalteLampeEin() hingegen ist genau richtig, denn da kann die Lampe
auch per I2C-Expander oder sonstiger Peripherie oder zum Beispiel auch
per LAN bei den Antipoden angeordnet sein, OHNE daß es den Algorithmus
betrifft, der die Lampe benutzen muß. Der Einzige, der wissen muß, wie
die Lampe angeht, ist der Lowlevel-Treiber. Aber der ist sehr
überschaubar, denn er hat ja nur diese eine Aufgabe.
So soll es sein: daß der Algorithmus so plattformunabhängig wie möglich
sein soll. Die Umsetzung auf irgend eine spezielle Plattform macht dann
ein recht einfach gehaltener Lowlevel-Treiber, der dann das EInzige ist,
was man ändern muß, wenn man das Ganze woanders hin portieren will.
Du hast hingegen unbewußt eine unnötige Einschränkung vorgenommen.
Extrapoliert man das, dann landet man unweigerlich wieder bei den
plattform- und herstellerabhängigen Libs.
W.S.
W.S. schrieb:> Lowlevel-treiber sollten die Dinge abstrahieren, also nicht so:>> void SetzePin(int port, int bit, bool hi_lo);>> sondern so:>> void SchalteLampeEin(void);
Mal wieder W.S. geblubber.
Beide sind nicht das gelbe vom Ei.
Erstens steht hier STM32 im Titel, daher hat son Pin noch mehr config:
Pullupdown, speed, alternate function, usw.
Das packt man alles schön in const struct und übergibt den Pointer davon
einer SetzeIrgendwas(const struct *pin);
Diese Funktion "SchalteLampeEin(void)" hat was von deinem Lernbetty
Kopierpastencode ala:
Uart1_Init();
Uart2_Init();
Uart3_Init();
Also Code sinnfrei duplizieren wo eine Hauptfunktion reicht mit einem
Pointer zu nem Pin.
Sei es init, set, clear oder sonstwas.
Diese Pointer kann man dann als Config struct einem Treiber reinwerfen
statt auf hardcalls setzen zu müssen.
W.S. schrieb:> Also was hast du eigentlich davon, wenn du für jeden HW-Registerzugriff> anstelle des eigentlichen Zugriffs eine Funktion aufrufst? Willst du> bloß Taktzyklen verbraten?
Mal wieder keine Ahnung von nichts!
Die LL Funktionen sind inline, da wird im Gegensatz zum HAL wirklich
nichts verbraten.
Fang doch bitte erst an was zu tippen wenn du mal reingesehen hast, so
machst du dich nur noch lächerlicher als du schon bist.
W.S. schrieb:> Also was hast du eigentlich davon, wenn du für jeden HW-Registerzugriff> anstelle des eigentlichen Zugriffs eine Funktion aufrufst? Willst du> bloß Taktzyklen verbraten?
Was ich davon (Gebrauch von CubeMX) habe? Eine Kontrolle darüber, daß
keine Parameter miteinander kollidieren, Hardwareressourcen doppelt
belegt werden, ich muß mich um die Initialisierung nicht mehr kümmern,
graphische Übersicht über die Takteinstellungen, ...
Auch wenn ich mit STM32 relativ unerfahren bin:
Zunächst einmal würde ich mich nicht darauf verlassen, daß der Compiler
aus einem Funktionsaufruf in C auch tatsächlich einen Sprung im
Maschinencode macht. Im Gegenteil, wenn in der Funktion nur eine
einzelne Anweisung steht würde ich von einem halbwegs anständigen
Compiler erwarten, den Aufruf wegzuoptimieren. Und andere schrieben ja
schon 'Inline'.
Überhaupt halte ich es für reichlich sinnlos, in Hochsprachen (da zähle
ich C dazu, auch wenn ich die Beschreibung von C als "Assembler mit
syntaktischem Zucker" durchaus treffend finde) sehr viel Wert auf
Performance zu legen. Sperrige Konstrukte wie überflüssige
Arrayiterationen mal aussen vor gelassen.
Irgendwo geisterte hier mal ein Thread über so eine Fragestellung herum.
Ich glaube, es war die Frage, wie man in einer for-Schleife die
Abbruchbedingung am effizientesten prüft. Nachdem die Helden bestimmt
über 50 Beiträge lang gestritten haben was denn nun besser ist, hat mal
jemand das Compilat der zwei konkurrierenden Abbruchvarianten
hochgeladen: Aus beiden Codestücken hat der Compiler denselben ASM-Code
gestrickt.
Und Code, der besser lesbar ist, ist auch definitiv besser verstehbar.
Low-Level-Programmierer schrieb:> Eine Kontrolle darüber, daß> keine Parameter miteinander kollidieren, Hardwareressourcen doppelt> belegt werden, ich muß mich um die Initialisierung nicht mehr kümmern,> graphische Übersicht über die Takteinstellungen, ...
Ich habe CubeMx dreimal versucht, und jedes mal ist genau das passiert.
Es beschützt dich eben nicht vor solchen Fehler, es sieht nur so aus.
Das Programm ist voller Bugs, die mich ohne Erfahrung mit dem Framework
total überfordert haben.
Die Programmierung anhand des Referenzhandbuchs macht mir hingegen keine
Sorgen.
Low-Level-Programmierer schrieb:> Überhaupt halte ich es für reichlich sinnlos, in Hochsprachen ... sehr> viel Wert auf Performance zu legen.
Hmm.. da hast du eine eigentümliche Einstellung.
Aber ich schätze, du hast mich durchweg nicht verstanden. Was ist zum
Beispiel, wenn du dein Programm mal von einem STM32 auf einen PIC32
portieren willst? Oder (um es einfacher zu machen) auf einen LPC oder
einen NUC120? Wenn du in deinen Algorithmen keine plattformspezifischen
Dinge machst, dann kannst du die ohne Probleme woanders auch benutzen.
Wenn du hingegen dort jede Menge Zeugs wie von Cube usw. drin hast, dann
ist es mit dem Portieren weitaus miserabler.
W.S.
Alex schrieb:> Welche Bugs?
79596 [MX-RCC] Wrong exported RCC configuration with LL drivers.
78859 [MX-G0][I2C] No SDA signal.
73371 [MX-MP][USART] Hardware flow control (RS485) not available.
70790 [MX-Code Generation] Incorrect OPAMP number assigned.
66665 [MX-MP][PINOUT] Pinout changes not updated.
52366 STM32F412 FSMC PB7 functionality: STM32CubeMX vs. datasheet
discrepancy.
68063 [MX-L4][TIM2-GPIO] Line missed in code generation.
69542 [MX-USB]: USB pins set wrongly as alternate functions.
70459 [MX-F4][ADC] Cannot enable “DMA Continuous Requests”.
70965 [MX-L4][CLOCK] Wrong minimum frequency for ADC.
65919 [MX-F7][USB]: Speed setting for USB_OTG_HS Device missed.
66183 [MX-F7][QSPI]: Add disabled mode to dual-Flash parameter.
66502 [MX-L4+][SYSTICK] [LL]: SysTick is disabled after calling
SystemClock_Config().
66652 [MX-F3][ADC-LL]: Wrong code gen in the configuration for ADC LL.
57986 Bug in STM32CubeMX / STM32F0 LL Library internal ADC channel.
62446 [MX-F7][SAI] Internal synchronization does not work.
63768 [MX-SPI] Cannot configure CRC poly.
Brauchste noch mehr?
Das sind nur die gefixten von v5.2 nach v5.6 und dann nur eine Auswahl
meinerseits.
Bei sowas biste dann erstmal am suchen in der HAL.
Daher die LL direkt nutzen (wies der TE vorhat) oder nach Refman selber
coden,
W.S. schrieb:> Hmm.. da hast du eine eigentümliche Einstellung.
Wie oft willste eigentlich immer über dich reden?
W.S. schrieb:> Aber ich schätze, du hast mich durchweg nicht verstanden.
Dein Geschwurbel ist auch unverständlich und voller "dont dos" ;)
W.S. schrieb:> Aber ich schätze, du hast mich durchweg nicht verstanden. Was ist zum> Beispiel, wenn du dein Programm mal von einem STM32 auf einen PIC32> portieren willst? Oder (um es einfacher zu machen) auf einen LPC oder> einen NUC120?
Hätten mir direkte Registerzugriffe denn in diesem Fall was gebracht?
Hat der PIC32 einen High Resolution Timer? Ist die Taktkonfiguration
hinreichend bei beiden Controllern hinreichend identisch?
W.S. schrieb:> Wenn du in deinen Algorithmen keine plattformspezifischen> Dinge machst, dann kannst du die ohne Probleme woanders auch benutzen.
Eben, dafür gibt es Hochsprachen wie C. Dann lagert man
plattformUNspezifische Dinge halt in eine Funktion aus, und übergibt
alle notwendigen Daten in plattformUNspezifischen Datentypen. Oder liege
ich da so falsch?
Wie gesagt, ich habe von STM32 leider nur wenig Ahnung (ändert sich
demnächst hoffentlich), aber mit AVR-Assembler und mit C allgemein kann
ich durchaus umgehen. Auch wenn ich den mit großem Abstand meisten Code
bisher in Java geschrieben habe. Und eigentlich kein Programmierer bin.
Eine Frage hätte ich mal noch an Mw E:
Wo hast du die Fehlerliste ausgegraben? Ich glaube ich seh da schon
etwas, das mir auf die Füße fallen könnte...
Ich hätte mal noch eine Frage:
Es gibt ja von ST allerhand Debug- und Profilerkram für
Motorsteuerungen.
Gibt es auch ein Debug-Werkzeug, das z.B. ADC-Werte mitloggt und
anzeigt?
Kann ich nicht direkt beantworten, aber ST hat viel Doku und Application
Notes, da sollte sich was finden lassen. Und wenn über eine
Schnittstelle Momentanwerte abgefragt werden können, dann können die
auch geloggt werden.
Ich hätte mal noch eine Frage zum ADC des F334:
Ich will jetzt zwei Kanäle auf einem ADC benutzen. Sehe ich das richtig,
daß ich anhand der Flags nur sehen kann, daß:
1. ein neuer Wert konvertiert wurde und
2. ob der ADC mit einer Sequenz fertig ist?
Oder habe ich da noch etwas übersehen? Ein Register, welcher Kanal
gerade selektiert war/ist, gibt es nicht?
Low-Level-Programmierer schrieb:> Eine Frage hätte ich mal noch an Mw E:> Wo hast du die Fehlerliste ausgegraben? Ich glaube ich seh da schon> etwas, das mir auf die Füße fallen könnte...
Man suche nach "cubemx changelog pdf".
Dann kommt sowas:
https://www.st.com/content/ccc/resource/technical/document/release_note/b2/02/4b/e3/81/32/49/c4/DM00107607.pdf/files/DM00107607.pdf/jcr:content/translations/en.DM00107607.pdf
Da einfach mal durchstöbern.
Low-Level-Programmierer schrieb:> Ich hätte mal noch eine Frage:> Es gibt ja von ST allerhand Debug- und Profilerkram für> Motorsteuerungen.>> Gibt es auch ein Debug-Werkzeug, das z.B. ADC-Werte mitloggt und> anzeigt?
Mit dem ST-Link fällt mir da jetzt kein Weg ein.
Aber mit meinem J-Link Edu und J-Scope geht das.
https://www.segger.com/products/debug-probes/j-link/tools/j-scope/
Einen originalen ST-Link von ST kann man auf einen J-Link mini
umflashen:
https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/
Ob dann J-Scope damit funzt kann ich dir leider nicht sagen, da musste
experimentieren.
Low-Level-Programmierer schrieb:> Ich hätte mal noch eine Frage zum ADC des F334:>> Ich will jetzt zwei Kanäle auf einem ADC benutzen. Sehe ich das richtig,> daß ich anhand der Flags nur sehen kann, daß:> 1. ein neuer Wert konvertiert wurde und> 2. ob der ADC mit einer Sequenz fertig ist?>> Oder habe ich da noch etwas übersehen? Ein Register, welcher Kanal> gerade selektiert war/ist, gibt es nicht?
Ich hab mal kurz ins F334 Refman gesehen, der ADC sieht ziemlich gleich
aus mit dem vom F2/F4/L4, daher sage ich:
Nein, gibt es nicht.
Aber dafür gibts den DMA!
Du stellst den DMA auf Ringbuffer ein mit so vielen Elementen wie du ADC
Kanäle samplen willst.
Dann hast du in einem Array immer den neusten ADC Wert.
Der ADC kann eh so schnell samplen, dass ein IRQ manchmal zu langsam
abgehandelt wird.
Wenn dir das erstmal zu kompliziert ist:
Der F334 hat 2 ADC Instanzen und du willst erstmal nur 2 Kanäle.
Dann nimm doch einen ADC pro Kanal, so weiste immer was du ließt.
---
Ansonsten empfehle ich dir dich nicht weiter mit W.S.
auseinanderzusetzen.
Er hat hier schon mehrmals im Forum gezeigt, dass er keine Ahnung hat.
Sein Magic Number Code der Lernbetty (ein Projekt, dass niemanden hier
im Forum interessiert), bietet er auch bei jeder Gelegenheit als besten
Code der Welt an.
Sein lustigster Klogriff letztens ist die Verteufelung von memcpy.
Da weis man echt nicht mehr was man dazu sagen soll ;)
Ansonsten evrteufelt er noch Debugger, denn Leute die sowas nutzen könne
ja nicht programmieren! (schreibt er).
DMA mag er auch nicht, weil er nicht versteht was das ist und faselt
dann imemr was von "das nimmt der CPU keine Rechenleistung ab" = keine
AHnung was DMA ist aber gegen hetzen.
Außerdem siehst du ja, dass er nur mit Allgemeinplätzchen kommt, bei mir
wirds konkret.
Mw E. schrieb:> Er hat hier schon mehrmals im Forum gezeigt, dass er keine Ahnung hat.
Und du zeigst hier immer wieder, dass du kein Benehmen hast. Deine
permanente Stänkerei gegen W.S. nervt.
Wir waren zwar auch mal jung, haben uns aber nicht im Ton vergriffen.
Halt einfach mal den Mund!
Keine Sorge Leute, den W.S. kenn ich doch. Ich bin ja öfter hier,
allerdings verirre ich mich selten in diesen Teil des µC-Boards. :)
Den DMA wollte ich erstmal vermeiden aber wie es aussieht ist es wohl
doch sinnvoller, sich auch gleich damit zu befassen.
Vielen Dank bis hierher. :)
Low-Level-Programmierer schrieb:> Den DMA wollte ich erstmal vermeiden aber wie es aussieht ist es wohl> doch sinnvoller, sich auch gleich damit zu befassen.
Ich klickma auf Thread beobachten mit ich die Fragen nicht verpasse.
So schwer ist der DMA nu aber auch wieder nicht, stells dir wie ein
memcopy in Hardware vor.
Wenn ich in der LL etwas nicht finde habe ich eigentlich nur im
Referenzmanual nachgeschaut um welchen Register es sich hauptsächlich
dreht. Zum Beispiel um zu prüfen welcher PIN den Interrupt getriggert
hat suche ich nach dem EXTI_PR Register einfach in der entsprechenden
smt32fxxx_ll_exti.h nach dem Register und finde dann meist schnell die
passende Funktion. Zur Not schaue ich auch tatsächlich mal in die HAL
Funktionen was für Schritte dort passieren...
So liebe Leute, ich hätte mal wieder eine Frage:
Ich habe jetzt hier für das Wochenende ein Discovery Board mit dem F3
und will damit etwas spielen.
Jetzt frag ich mich: Wie lege ich in CubeIDE eine neue Bibliothek für
das Projekt an?
Ich hab im Ordner Projektpfad\Core\libraries\ledcircle zwei Ordner:
einer heißt "inc", dieser beinhaltet eine Datei "ledcircle.h" und der
andere "src", dieser beinhaltet eine Datei "ledcircle.c".
Rechtsklick auf Projekt > Properties > C/C++Build > Settings > Tab
Toolsettings > MCU GCC Compiler > Include paths und dort habe ich
(aktuell) für [All configurations] den Pfad
"${ProjDirPath}Core/libraries/ledcircle/inc/" hinzugefügt.
Jetzt meckert der Linker aber andauernd, das er keine Datei ledcircle.h
finden kann.
Kann mir mal jemand erklären, ob ich da einen offensichtlichen Fehler
gemacht habe? Oder kann erklären, wie das funktoniert?
Ich lege die *.h Dateien immer in das gleiche Verzeichnis, wie die
zugehörigen *.c Dateien. Ist einfacher so.
Zu einer eigentlichen Frage: Unterhalb von "MCU GCC Compiler" gibt es
noch einen Abschnitt für den Linker, da musst du den Pfad auch
einstellen.
Sicher, dass der Linker meckert?
Dem sind .h eigentlich eher egal oder haste da inline Code drinne?
Ansonsten fehlen eher Include Pfade im Makefile.
Die erkennt man durch "-I<Pfad>"
errdzg schrieb:> Abstraktion hat erstmal nichts mit der Funktionalität an sich zu tun,> eher etwas mit Wiederverwendbarkeit und Portabilität.
So SOLLTE es sein.
Tatsächlich ist es aber eher so, dass diese ganzen unnützen
HAL-Abstraktionen so geschreiben sind, dass sie vor allem genau eins
tuen: deren Verwender möglichst weitgehend auf genau den einen
Hersteller festzunageln.
Das gilt natürlich herstellerübergreifend für alle gleichermaßen.
Wer das nicht kapiert, ist ein Vollidiot. Ende der Ansage.
Stefan ⛄ F. schrieb:> Diese IDE arbeitet standardmäßig ohne Makefile.
Dann muss man den passenden Tab für die Includepfade suchen.
Wo die bei der CubeIDE sind kann ich aber nicht sagen.
Mw E. schrieb:> Dann muss man den passenden Tab für die Includepfade suchen.> Wo die bei der CubeIDE sind kann ich aber nicht sagen.
Habe ich doch schon erklärt.
Low-Level-Programmierer schrieb:> Eben, dafür gibt es Hochsprachen wie C. Dann lagert man> plattformUNspezifische Dinge halt in eine Funktion aus, und übergibt> alle notwendigen Daten in plattformUNspezifischen Datentypen. Oder liege> ich da so falsch?
Da liegst du falsch. Man lagert die plattformspezifischen Dinge in
Lowlevel-Treiber aus. Und nicht umgekehrt.
Ich gebe dir mal ein Beispiel:
Da hatte vor Zeiten mal einer einen Treiber für irgend ein Display
geschrieben, was per I2C anzusteuern war. Er hatte also all die
Spezifika des I2C-Anschlusses seines µC in diesen Treiber gepackt und
damit war sein Treiber überhaupt nicht portabel, sondern NUR auf eben
dieser HW zu benutzen.
Ist uneffektiv, weil schon beim nächsten Projekt alles wieder von vorn
neu geschreiben werden muß.
Ich hab sowas ja auch schon gemacht, aber gänzlich anders:
- zuerst ein LL-Treiber für den I2C, der nach oben hin völlig
plattformunabhängig ist. Im Prinzip braucht man dazu ja nur 5
Funktionen:
I2C_Init(void);
I2C_Start(byte adresse, bool rw);
I2C_Write(byte was);
byte I2C_Read(void);
I2C_Stop (void);
Das reicht, und was im Inneren des Treibers abgeht, interessiert die
Welt oberhalb überhaupt nicht. Dieses Interface ist plattformunabhängig.
So, und dann den Treiber für das Display oben drauf. Er greift natürlich
NICHT auf irgend eine Hardware zu, sondern benutzt den I2C-Treiber.
Damit ist er ebenfalls plattformunabhängig.
Um also so ein Display auf irgend einem anderen µC zu benutzen, muß man
lediglich den I2C-Treiber anpassen, nicht jedoch den Treiber des
Displays.
Du siehst, daß das alles nicht durch C oder plattformunabhängige
Datentypen zu machen ist, sondern nur durch Zerteilen des
Gesamtproblems in sinnvolle Schichten.
Und wenn man es gut gemacht hat, dann ist auch das Interface des
Displaytreibers so gehalten, daß man mit dem gleichen Interface auch den
Treiber für ein anderes Display schreiben kann. Dann braucht sich die
darüberliegende Schicht, also das GDI, nicht um die niederen Dinge der
Displayansteuerung zu kümmern, sondern braucht nur die Dinge der
GDI-Schicht zu erledigen, also Linien zeichnen, Blöcke füllen,
Schriftzeichen in verschiedenen Fonts an die Stelle X,Y zeichnen und so
weiter.
Natürlich ist auch das GDI nicht zum Selbstzweck da, sondern es dient
der darüberliegenden Schicht, die dir z.B. anzeigen will, welchen Sender
du am Radio gerade eingestellt hast oder wieviel Benzin du grad getankt
hast und wieviel das kostet.
Ich habe nicht umsonst ein so simples Beispiel wie
"void SchalteLampeEin(void);"
gewählt. Dieses Beispiel mag dir auf den ersten Blick primitiv vorkommen
(und ist es ja auch), aber es steht für all die Lowlevel-Treiber, die
das Bindeglied zwischen der Hardware ganz unten und den Algorithmen ganz
oben darstellen. Und eine jede Schicht soll das Darunterliegende
abstrahieren. Wer den I2C benutzen will, muß sich mit dem I2C auskennen
- aber ihn interessiert eigentlich nicht, wie das im Detail bei dem
gerade gewählten µC gelöst ist. Viel mehr interessiert ihn, daß seine
Quelle, die auf den I2C zugreift, auch auf anderer HW so funktioniert
wie sie soll. Und wenn man seine Kringel auf einem 12864 malen will,
möchte man sich auch nicht an die Details des einen oder anderen
Produkts festnageln, sondern das soll mit allen 12864 und auf allen µC
funktionieren.
So, ist das jetzt etwas klarer?
W.S.
W.S. schrieb:> I2C_Init(void);> I2C_Start(byte adresse, bool rw);> I2C_Write(byte was);> byte I2C_Read(void);> I2C_Stop (void);> Das reicht, und was im Inneren des Treibers abgeht, interessiert die> Welt oberhalb überhaupt nicht. Dieses Interface ist plattformunabhängig.
Ich verstehe woraus du hinaus willst und stimme grundsätzlich zu.
Dein Beispiel ist allerdings unglücklich, weil es schon auf einem
STM32F1 unmöglich funktionieren kann. Da muss man nämlich die beiden
letzten empfangenen Bytes anders behandeln. Da bräuchtest du drei
verschiedene read-Funktionen oder zusätzliche Parameter.
Low-Level-Programmierer schrieb:> Wie gesagt, ich habe von STM32 leider nur wenig Ahnung (ändert sich> demnächst hoffentlich), aber mit AVR-Assembler und mit C allgemein kann> ich durchaus umgehen. Auch wenn ich den mit großem Abstand meisten Code> bisher in Java geschrieben habe. Und eigentlich kein Programmierer bin.
Nun gut, wenn du ansonsten hauptsächlich Java geschrieben hast, dann
liegen deine Schwerpunkte eben ganz woanders. Geht mir zwar ähnlich,
dennoch waren und sind bei mir NEC 78K4, Fujitsu FR, ARM klassisch (NXP
und Atmel), ARM Cortex (NXP, Nuvoton, ST), MicroChip PIC16 in Mode. Und
das sind alles z.T. recht unterschiedliche Architekturen. FR ist z.B.
bigendian - und das schlägt sich auf die Gestaltung von einigen Quellen
nieder, vor allem Fonts.
Noch ein Rat meineseits: Klebe nicht zu fest an ST. Benutze wenigstens
auch die LPC's von NXP - einfach um nicht Scheuklappen zu kriegen. ST
ist da ziemlich scharf drauf, dir welche zu verpassen.
W.S.
Stefan ⛄ F. schrieb:> Habe ich doch schon erklärt.
Es kommt mir eben noch etwas komisch vor, dass der Linker bei einer
Headerdatei meckert.
Daher noch die Nachfrage ob wirklich der Linker meckert.
Wenns wirklich der Linker ist, dann hast du schon die Lösung gepostet.
Wenn nicht, dann müssen wir nochmal ran.
W.S. schrieb:> I2C_Init(void);> I2C_Start(byte adresse, bool rw);> I2C_Write(byte was);> byte I2C_Read(void);> I2C_Stop (void);
Das ist nicht portabel.
Ein STM32L431 hat zb einen I2C mit Autostart und Autostop.
Der muss vorher die Byteanzahl wissen und möchte die nicht kleckerweise
haben.
Außerdem fehlt dort eine übergabe ob I2C 1, 2 oder 3 oder mehr.
Also mal wieder setzen 6 an W.S. !
Außerdem machen deine Funktionen genau das was Low-Level-Programmierer
geschrrieben hat, du hast nur mal wieder kein Leseverständnis.
Stefan ⛄ F. schrieb:> Dein Beispiel ist allerdings unglücklich,
1. Diese Kalamität bei diesen STM kenne ich.
2. Nicht das Beispiel ist unglücklich, sondern die Oberschlauheit von ST
ist unglücklich. So herum. Ärgerlich ist es dennoch.
3. I2C war und ist bei sehr vielen µC einfach beschissen gemacht. Die
einzigen, wo es recht gut gelöst war, ist NEC 78K4 gewesen. Aber NEC ist
tot.
W.S.
W.S. schrieb:> 2. Nicht das Beispiel ist unglücklich, sondern die Oberschlauheit von ST> ist unglücklich. So herum. Ärgerlich ist es dennoch.
Achsoo W.S. macht sich die Welt mal wieder wie sie ihm gefällt!
Du kennst nur die alten I2C ohne automatismem und willst nichts anderes
wissen.
Bei den ATSAM gibts auch nette I2C mit schönen Extras.
Also: Ich habe dem Linker noch den Pfad mitgeteilt, jetzt sind es schon
ein paar Fehlermeldungen weniger. Prima. :)
Welche Datei muß ich eigentlich einbinden, damit er die
Low-Level-Funktionen wie LL_GPIO_SetPin() findet? Shift+Klick dirigiert
mich zu einer Datei namens stm32f3xx_ll_gpio.h, aber diese einzubinden
behebt den Fehler nicht.
@W.S.:
W.S. schrieb:> Low-Level-Programmierer schrieb:>> [..] plattformUNspezifische Dinge [..]>> Da liegst du falsch. Man lagert die plattformspezifischen Dinge in> Lowlevel-Treiber aus. Und nicht umgekehrt.
...ich hab es doch extra groß geschrieben... :)
W.S. schrieb:> Noch ein Rat meineseits: Klebe nicht zu fest an ST. Benutze wenigstens> auch die LPC's von NXP - einfach um nicht Scheuklappen zu kriegen. ST> ist da ziemlich scharf drauf, dir welche zu verpassen.
Ja, da hast du sicher recht. Welcher Chiphersteller wäre das nicht? :)
oder man nimmt ein OS das NXP, STM, Nuvoton, Nordic, Freescale
unterstützt und ein spi.write() funktioniert einfach ungeachtet der
Hardware Kalamitäten.
Mw E. schrieb:> Du kennst nur die alten I2C ohne automatismem
Nur eine Art von Automatismen ist akzeptabel: diejenigen, die eine
"switch off"-Option haben...
Denn nix ist schlimmer als ein Automatismus, der bekanntermaßen unter
bestimmten Umständen Scheiße baut, aber nicht abschaltbar ist, selbst
wenn man schon weiss, dass genau diese Umstände eingetreten sind (bzw.
eintreten werden)...
c-hater schrieb:> Nur eine Art von Automatismen ist akzeptabel: diejenigen, die eine> "switch off"-Option haben...>> Denn nix ist schlimmer als ein Automatismus, der bekanntermaßen unter> bestimmten Umständen Scheiße baut, aber nicht abschaltbar ist, selbst> wenn man schon weiss, dass genau diese Umstände eingetreten sind (bzw.> eintreten werden)...
Bei I2C ist es durchaus mal eine erfrischende Ausnahme.
Register setzen, DMA scharfstellen, go!
Die I2C Frames der ganzen Slaves sind ja ziemlich fest, das geht nach
Schema X.
(Exoten bestätigen die Ausnahme)
Low-Level-Programmierer schrieb:> Welche Datei muß ich eigentlich einbinden, damit er die> Low-Level-Funktionen wie LL_GPIO_SetPin() findet?
hast du das define USE_FULL_LL_DRIVER gesetzt? Da in der Nähe wo auch
die Includepfade sind, da sollten die defines rein. Dann berücksichtigt
der Indexer die auch und zeigt den Quelltext aktiv/inaktiv an.
das ist kein Haken, das ist in dem Dialog wo auch der Includepfad
gesetzt wird, Symbols müsste es heissen. Schon lange kein Eclipse mehr
benutzt.
oder Preprocessor.
Ah...ja, ich hab was gefunden, du meintest das hier? Preprozessor?
https://community.st.com/s/question/0D50X0000BsQvhYSQS/cubemx-ll-build-failure
Hab Ich drin, aber er meckert immer noch über ein "unresolved inclusion"
bei besagter Datei stm32f3xx_ll_rcc.h.
In der main ist sie auch eingebunden, und da meckert er genauso.
Könnte sagt er, wurde das .elf oder .bin was er bauen sollte vielleicht
trotzdem erzeugt? Mit dem Parallelen kompilieren hatte Eclipse auch
seine Probleme.
Johannes S. schrieb:> Puh. Nimm Mbed und eine LED blinkt in 10 Minuten.> Aber dann musst du deinen Nick ändern:)
Mbed hat natürlich auch den Vorteil, dass sich die Kompilierzeit auf
eine Minute verlängert und der Binärcode sich auf das 100-fache
aufbläht.
Also zur Vollständigkeit halber: Das hat auch Konsequenzen und nicht nur
Vorteile so ein "Komplett"-OS zu benutzen.
Oder war das als Scherz gemeint?:)
Jedzia D. schrieb:> Also zur Vollständigkeit halber: Das hat auch Konsequenzen und nicht nur> Vorteile so ein "Komplett"-OS zu benutzen.
Gähn. Wurde hier schon x-mal diskutiert. Vor 15 Jahren wäre das ein
Thema, wo 32 kB Flash noch viel war und 64 kB gar gigantisch. Vom RAM
ganz zu schweigen.
Wer die die Zwänge hat damit auskommen zu müssen, mein Beileid.
Wer Angst hat das ein Blinky damit nicht mehr in einen F3 passt, der
sollte auch die Finger davon lassen. Wenn das in einer Minute bei build
all kompiliert, dann hast du einen superschnellen Rechner, da bin ich
neidisch.
Aber ehrlich, das juckt mich nicht wenn ich die ganzen Probleme hier
lese wie man ein SPI oder I2C ans Laufen bekommt. Ich will das Rad nicht
mehr erfinden.
Grafikdisplays die nicht in TTY Geschwindigkeit Klötzchengrafik
aktualisieren (mal touchGFX oder lvgl gesehen?), Ethernet nutzen, einen
schnellen HTTP Server zu haben, eine aktuelle Stdlib nutzen zu können,
ein C++ API mit dem Basiskram in Klassen vorliegen zu haben, Filesysteme
zu nutzen auf Basis von SPIF, QSPIF, internem Flash, SD karten, das ist
der Level den ich haben möchte ohne erstmal einen Codegenerator
anstossen zu wollen. Da will ich hin bzw. habe es in weiten Teilen
erreicht.
Scheiss auf 1 Minute kompilieren und 100 fachen Code für eine blinkende
LED, das ist eben nicht nur Luft.
Und mit Eclipse rumärgern, nein da will ich jetzt gar nicht mehr mit
anfangen. Schonmal versucht zu ergründen wie das automagische make
arbeitet und versucht es zu beeinflussen?
Eine gar nicht so schlechte Übersicht/Dokumentation lässt sich übrigens
mit doxygen erstellen.
eine default config (-g) mit z.B.:
1
INPUT = Drivers/STM32F3xx_HAL_Driver
2
...
3
FILE_PATTERNS = *_ll_*.c \
4
...
5
*_ll_*.h \
um nur die ll files mit einzubeziehen.
Johannes: Ich hatte nicht erwartet deine persönliche Leidensgeschichte
zu hören. Ich meinte was ich schrieb nicht anekdotenhaft. Eine
ordentlich auf die Problemstellung angepasste Lösung ist meist schlanker
und performanter als eine auf höherer Abstraktionsebene und Generische.
Das wird natürlich mit Zeit zum einarbeiten oder zur Softwarepflege
bezahlt. Trotz das wir uns in einem Beitrag mit "Low Level" darin
tummeln war mein Kommentar nicht als Seitenhieb gemeint. Es gibt halt
auch Menschen, die zeitlich kurze Kompilate schätzen;)
Johannes S. schrieb:> Könnte sagt er, wurde das .elf oder .bin was er bauen sollte vielleicht> trotzdem erzeugt? Mit dem Parallelen kompilieren hatte Eclipse auch> seine Probleme.
Also, eine .elf- oder .bin-Datei habe ich nicht gefunden.
Wenn es ein Problem mit parallelem Kompilieren gibt: kann man das nicht
auf seriell umstellen? (Und wenn ja: wie?)
Wegen etwas Kompilierzeit mache ich mir jetzt nicht ins Hemd, das wäre
für mich aktuell ein Luxusproblem.
Johannes S. schrieb:> Jedzia D. schrieb:>> Es gibt halt auch Menschen, die zeitlich kurze Kompilate schätzen;)>> Und das ist der Hauptgrund einen F3 zu benutzen?
Falls sich das auf mich bezieht, was ich wegen des Zitats annehme:
"Drivers/STM32F3xx_HAL_Driver" ist Beispielhaft gemeint und doxygen
weiss nichts von irgendwelcher Hardware. Das ist komplett aus dem
Kontext gerissen, wie auch andere deiner Annahmen über mich und
Makefiles, etc. ... falls sich das auf mich beziehen sollte. Auf diese
Idee würde ich allerdings nur im Traum kommen, da ich mich nicht
angesprochen fühle, bzw. deinen merkwürdigen anekdotischen
Gedankengängen nicht folgen kann.
worum ging es nochmal?
Low-Level-Programmierer schrieb:> Also, eine .elf- oder .bin-Datei habe ich nicht gefunden.
Die parallel Option ist in dem Project properties Dialog versteckt, am
Besten über die Suche links oben finden. Das ist aber nur ein kleiner
Strohhalm, ich kenne das bisher nur als kosmetisches Problem das nur die
Ausgaben durcheinandergewürfelt sind. Habe Eclipse aber auch schon
länger nicht mehr benutzt.
Der Screenshot ist aus MCUXpresso, aber an der Stelle sollten die
Eclipse Varianten gleich sein, trotzdem ohne Gewähr.
Hat das den vor den LL Änderungen schon funktioniert oder von Anfang an
nicht? Hast du CubeMX zum Start benutzt?
Letzteres wäre der einfache Weg. Starten, mit 'Start my Project from
STBoard' anfangen. Dann das vorhandene Board auswählen, damit werden die
HW Voreinstellungen wie Clock und belegte Pins ausgewählt. Weitere Pins
und Middleware nach belieben hinzufügen, Projekt speichern und dann
'generate Code' drücken. Die CubeIDE auswählen und links auf die
Advanced Options.
Da ist dann versteckt rechts oben die Auswahl ob HAL oder LL.
Hi
Also, die Parallel Jobs Settings hab ich auch, aber das hat nichts
gebracht. Mist.
Ansonsten: Ich habe das Projekt in CubeIDE aufgezogen, und gleich als LL
angelegt. Über die CubeMX-View, allerdings war ganz am Anfang noch etwas
HAL
-Zeug drin weil ich USB nicht deaktiviert habe.
Und ich habe das Projekt anfangs über den Boardselektor zum passenden
Discoveryboard ausgewählt, also im Prinzip alles so wie du geschrieben
hast.
Aber mal sehen, vielleicht werd ich es mal als richtiges HAL-Projekt
bauen, mal sehen obs dann wird.
Umstellung auf HAL hat nix gebracht, außer 168 Fehler (in generiertem
Code). Und ich habe definitiv keine Lust, die alle zu beheben.
Dafür hatte ich danach den Spaß, alle include-Pfade wieder einzubauen,
Eclipse hat die zwischendurch gelöscht. Nach einigen Ratespielchen (wars
jetzt "${ProjDirPath}/Core/libraries/ledcircle/" oder doch
"${ProjDirPath}Core/libraries/ledcircle/" bin ich zumindest wieder an
der Ausgangssituation mit dem Fehler, daß er nicht bauen will.
Ach, ist das frustrierend...
Ok..ich hab es jetzt. Im Supportforum wurde mir geraten, die Option -L
einzuschalten (was immer die auch tut, ich hab keine Ahnung) und dabei
fiel mir auf, daß "External Builder" aktiviert war. Nach Umstellung auf
"Internal Builder" baut er jetzt brav das Projekt.
Falls irgendwer bei seiner verzweifelten Googlesuche auf diesen Thread
stößt, im Anhang steht was ich umgestellt habe.
Mal sehen wie ich es jetzt aus der IDE auf den F3 bekomme...
Low-Level-Programmierer schrieb:> Nach Umstellung auf> "Internal Builder" baut er jetzt brav das Projekt.
ja, das ist das automagische make das ich schon erwähnte von dem man
nicht genau weiss was es macht. Eclipse kann schon eine Menge, man muss
es nur finden und wissen was die vielen Knöppe bewirken...
Low-Level-Programmierer schrieb:> Mal sehen wie ich es jetzt aus der IDE auf den F3 bekomme...
oben sollten Launch oder Debug Buttons sein, den STLink wird ST schon
vorkonfiguriert haben. Wenn das Board einen aktuellen STLink drauf hat
(evtl. Update mit STLink Utility durchführen), dann kann man auch das
.bin in das USB MSD vom Nucleo kopieren.
Zu der IDE müsste es auch ein mitgeliefertes Tutorial geben. oder das:
https://www.digikey.com/en/maker/projects/getting-started-with-stm32-introduction-to-stm32cubeide/6a6c60a670c447abb90fd0fd78008697
Den STLink auf dem Board hab ich schon auf die neuste Version
aktualisiert (V2J34S0), und Verbinden mit dem STLink-Utillity ist auch
kein Problem.
In der IDE macht er aber nix wenn ich auf Debug (F11) klicke. Eigentlich
sollte da eine zweite Leiste mit den Debugger-Knöpfen aufgehen, macht er
aber nicht. Das Projekt kompiliert er lediglich neu.
aus dem verlinkten getting started:
click Run > Debug As > STM32 MCU C/C++ Application.
Man muss eine Launch config erstellen, das macht ein STM Plugin.
Johannes S. schrieb:> click Run > Debug As > STM32 MCU C/C++ Application.
Wenn du mehrere Projekte offen hast, kommt er dabei oft durcheinander.
Ich klicke mit der rechten Maustaste auf den Projektnamen und dann auf
Debug. Dann verwendet er immer die richtige Konfiguration.
Johooo...es scheint endlich geklappt zu haben. Ich mußte einen Suchpfad
wieder entfernen (auch wenn in der Konsole "Build finished" steht, so
versteckte sich da noch eine Meldung daß er eine Bibliothek nicht
gefunden hat), CubeIDE wollte den ST-Link nochmal updaten, und noch
allerlei anderes Zeug...jetzt gehts.
Bzw. heißt das: Jetzt geht gerade gar nix mehr, das Standardprogramm ist
jedenfalls weg und vermutlich habe ich in meinem eigenen Programm
vergessen, den Timer anzuwerfen.
Weiß vielleicht noch jemand, wie der Funktionsaufruf dazu heißt? Ich
hätte so etwas wie LL_TIM_Enable() erwartet, aber so etwas gibts nicht.
Nur ein Haufen Funktionen, die div. Features enablen.
Low-Level-Programmierer schrieb:> das Standardprogramm ist> jedenfalls weg und vermutlich habe ich in meinem eigenen Programm> vergessen, den Timer anzuwerfen.
Ich empfehle Dir, ein Source Repository wie Mercurial oder GIT zu
verwenden und dann Zwischenstände von deinem Programm zu sichern. Damit
kannst du später alle Änderungen nachvollziehen. Also GUI dazu dann
TortoiseHG oder TortoiseGit.
Naja, das was ich jetzt hier habe ist ja nur ne Spielerei, um mit der
Technik etwas warm zu werden. Und den Quellcode von dem Programm, mit
dem das Discovery ausgeliefert wird, hab ich nicht. :)
Für ernsthafte Sachen verwende ich SVN oder GIT.
egal was das Programm macht, mit einem Breakpoint im main sollte das da
auch anhalten. Bei Cube gab es noch die Falle das man SWD da in der
Pinconfig auch auswählen muss.
Git Unterstützung ist in doch im Eclipse schon länger mit drin? Früher
musste man dafür ein Plugin installieren.
Eclipse wird ganz sicher GIT von sich aus unterstützen. Ich hab mir aber
abgewöhnt, die internen Versionskontrollsystem zu benutzen, ich mach das
lieber mit etwas externem.
Mit dem ARR Register auf 0 läuft der Timer nicht los.
edit:
wenn LL_TIM_DisableARRPreload das ARR deaktiviert, dann ist es das
nicht.
Aber im Timer gibts noch Maskierungsbits damit der IRQ den Timer auch
verlässt und das wurd da nicht gesetzt.
Ein Event ist kein IRQ.
Mit einem Event kannste IRQ los einen ADC sample anstoßen zb.
Low-Level-Programmierer schrieb:> So, doch noch ein paar Fragen.
Ich hätte auch eine: warum beachtest du nicht die Regeln beim
Posten von Beiträgen? Gelten die für dich nicht oder sind sie
unleserlich oder unverständlich geschrieben?
Oh man...stimmt, ohne AutoReload funktioniert das nicht.
Ich habe da jetzt mal den Wert 1000 eingetragen, da sollte ich jetzt
(mit Vorteiler 72, der Takt läuft mit 72MHz mit) alle ms einen Interrupt
bekommen.
Wie gesagt: sollte. Ist aber leider nicht.
Aber er bleibt in der while-Schleife in der main-Funktion.
Codebeispiele haben mich da auch noch nicht weitergebracht.
Hast du vielleicht noch eine Idee?
Ist jetzt <Low-Level-Programmierer> plötzlich <Wühlhase>?
Wie auch immer, <Wühlhase> darf sich auch an die vorher erwähnten
und immer lesbaren Regeln halten.
Und direkt in die Falle getappt zu nur ein Name pro Thread ;)
Ich hatte doch noch geschrieben, dass ein IRQ Mask Bit im Timer nicht
gesetzt ist.
Willste denn nen IRQ beim Overflow oder wenn das Timerregister ein
Compareregisterwert gleichkommt?
Du hast nämlich nur Events eingeschaltet und das sind keine IRQs.
Fragesteller schrieb:> Ist jetzt <Low-Level-Programmierer> plötzlich <Wühlhase>?>> Wie auch immer, <Wühlhase> darf sich auch an die vorher erwähnten> und immer lesbaren Regeln halten.
Jap...passiert mal, ich hoffe es nimmt mir niemand übel. Wenn man sich
darauf verläßt daß normalerweise der Standardnick schon vom Browser im
Feld eingetragen ist und dann schreibt man mal eben im Platinenforum
oder so...
Mea culpa.
Aber ich denke, Low-Level-Programmierer passt, zumindest was STM32
angeht, auch in mehrfacher Hinsicht besser. Daher bleib ich mal dabei.
:)
Mw E. schrieb:> Ich hatte doch noch geschrieben, dass ein IRQ Mask Bit im Timer nicht> gesetzt ist.
Ja, das hast du. Ich hab allerdings nicht kapiert was du damit meintest
und zu allem Überfluß auch noch vergessen, danach zu fragen. Gefunden
habe ich den Funktionsaufruf dann doch noch im Beispielcode von ST.
Wenn es interessiert: mit der Low-Level-Library muß das so aussehen:
LL_TIM_EnableIT_UPDATE(TIM6); //<- Diesen Aufruf vergessen
12
LL_TIM_Init(TIM6, &TIM_InitStruct);
13
LL_TIM_DisableARRPreload(TIM6);
14
LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET);
15
LL_TIM_DisableMasterSlaveMode(TIM6);
16
17
}
Ich hätte erwartet das CubeMX diese eine Zeile mit einbaut (ich hab das
jetzt händisch eingefügt), werde jetzt aber mal noch etwas
herumexperimentieren ob ich da auch was falsch eingestellt habe.
Jedenfalls vielen Dank für eure Hilfe bisher. Vielleicht komme ich heute
abend noch dazu, CubeMonitor auszuprobieren.
PS:
@Mw E.:
Einen netten Basteltisch hast du da. Gefällt mir.
Low-Level-Programmierer schrieb:> Einen netten Basteltisch hast du da. Gefällt mir.
Danke ;)
Low-Level-Programmierer schrieb:> Ich hätte erwartet das CubeMX diese eine Zeile mit einbaut
IRQs muss man da noch extra Asuwählen,
Aber ich nutze den MX eh nur zum Pinbelegung auswürfeln.
Low-Level-Programmierer schrieb:> Jedenfalls vielen Dank für eure Hilfe bisher. Vielleicht komme ich heute> abend noch dazu, CubeMonitor auszuprobieren.
Nicht links, nicht rechts schauen, und immer schön die Scheuklappen
anbehalten!
Fragesteller schrieb:> Ich hätte auch eine: warum beachtest du nicht die Regeln beim> Posten von Beiträgen? Gelten die für dich nicht oder sind sie> unleserlich oder unverständlich geschrieben?
Low-Level-Programmierer schrieb:> Den STLink auf dem Board hab ich schon auf die neuste Version> aktualisiert (V2J34S0), und Verbinden mit dem STLink-Utillity ist auch> kein Problem.
Obwohl bestimmt die Welt davon nicht untergeht, aber V2J37S7 ist aktuell
und deine Version ist aus dem März 2019!
... "Contains the application in its "historical" form: executable
dedicated to Windows + dll. With all most recent firmwares (V1J13S3 for
ST-Link/V1 boards, V2J37S7 for ST-Link/V2 boards, V2J37M26 for
ST-Link/V2-1 boards, V3J7M2 for STLINK-V3 boards)
ST-LINK, ST-LINK/V2, ST-LINK/V2-1, STLINK-V3 boards firmware upgrade:
https://www.st.com/en/development-tools/stsw-link007.html
" ...
P.S: An GNU-make ist nichts selbst-magisch. Es ist vollkommen
deterministisch, nachvollziehbar ->
http://git.savannah.gnu.org/cgit/make.git und dabei ein großartiges Tool
auf das man sich verlassen kann
(https://savannah.gnu.org/bugs/?group=make).
Jedzia D. schrieb:> Low-Level-Programmierer schrieb:>> Den STLink auf dem Board hab ich schon auf die neuste Version>> aktualisiert (V2J34S0), und Verbinden mit dem STLink-Utillity ist auch>> kein Problem.>> Obwohl bestimmt die Welt davon nicht untergeht, aber V2J37S7 ist aktuell> und deine Version ist aus dem März 2019!
In der Tat hast du da Recht. Ich habe erst ein Update mit
STLink-Utillity gefahren, das hat mir diese Version als neuste
vorgeschlagen. Und danach hab ich meinen Post verfasst.
Irgendwann hat CubeIDE aber auch noch einmal vorgeschlagen, den STLink
zu aktualisieren und kam dann mit einer höheren Versionsnummer (welche
weiß ich nicht mehr, wahrscheinlich die die du genannt hast).
Keine Ahnung warum das so ist...
Übrigens:
Ich habe gerade CubeMonitor erfolgreich zum Laufen gebracht und tracke
damit jetzt eine Countervariable, mit der ich jeweils eine LED im Kreis
leuchten lasse.
Wer es mal ausprobiern will: hier ist ein Video wie es benutzt wird:
https://www.youtube.com/watch?v=sTVds5rxM3w
Möglicherweise wird mir das Tool demnächst einiges einfacher machen. :)
Ich finde lästig, dass ich immer wieder meine ST-Links updaten soll.
Irgendwann geht das mal schief, und dann habe ich einen toten ST-Link.
Normalerweise update ich Firmware nur, wenn ich einen guten Grund dazu
haben, das Update also für irgend etwas bestimmtes brauche. Aber die
neue Cube Software lässt mir diese Wahl nicht mehr. Die verlangt immer
nach nach einer sehr aktuellen Version.
Ja, Stefan. Wir haben gerne alles unter Kontrolle und den Überblick:)
Ich hatte bei meiner Anmerkung auf den Softwarestand
Low-Level-Programmierer's Absicht den "Cube-Monitor" auszuprobieren im
Auge. Da diese Software neu heruntergeladen wurde kann es schon etwas
ausmachen welche Versionen hier zusammenspielen und ich dachte, das
erspart ihm Kopfschmerzen. Genau sagen kann ich das allerdings nicht.
Hier ist die Einsicht wegen fehlender Quellen, bzw. der Komplexität der
ganzen Infrastruktur natürlich sehr hoch. Der Wunsch nach Durchblick ist
(bei mir) schon vorhanden, aber die Zeit, die man da investieren müsste
überschreitet meine Hemmschwelle. Da muss ich eben mein Vertrauen
entgegen bringen. Das ist genau so wie mit allen anderen komplexen
Systemen, wie OpenSSL oder Firefox, etc. Da kann ich alleine nicht nach
dem Rechten sehen und das Überschaubar halten.
Soll keine Kritik an deinen Einwänden sein, ich hab die auch, aber
vielleicht solltest du deine Einstellung gegenüber Update-Prozessen
dahingehend ändern, dass der Grundwert auf "Positive Sache" eingepegelt
ist und nur Dinge, die wir sehr suspekt finden oder Erfahrung damit
haben in einer (berechtigten?) "Update-Faulheit" münden. Es gibt Tage an
denen funktioniert nach einem Update nichts mehr, aber auch das
Gegenteil: Stundenlanges debuggen... Danach stellt sich die Krux als
Nebenkriegsschauplatz dar und man fragt sich warum man so blöd war nicht
upzudaten und all die Zeit verschwendet hat.
Entschuldigung, das ist ein weites und kontroverses Thema für sich
allein genommen und hinterher ist frau immer schlauer! :)))
Jedzia D. schrieb:> und man fragt sich warum man so blöd war nicht> upzudaten und all die Zeit verschwendet hat.
Glaube mir, natürlich habe ich schon hunderte Male Sachen auf gut Glück
oder Neugier aktualisiert. Geholfen hat es aber noch nie bei irgendeinem
akuten Problem.
Die wenigen male, wo Updates geholfen haben, passiert das ganz gezielt.
Vorgestern z.B. konnte eine Kollegin eine Datenbank-Anwendung nicht mehr
re-starten. Das Programm behauptete steif und fest, dass einige Tabellen
nicht existieren würden - sie waren aber da und hatten passende
Zugriffsrechte. Auslöser war, dass Cheffe vor zwei Wochen bei einigen
Konfigurationstabellen "Versioning" aktivierte (ist ein neues Feature
bei MariaDB). Danach habe ich dann gegoogelt, einen Bug Report gefunden
und die Erkenntnis, dass ein neuer neuen MariaDB Connector das Problem
behebt.
Wenn ich schon auf gut Glück jedes Updates herunter laden soll, dass mir
angeboten wird, dann doch bitte wenigstens mit aussagekräftigen Release
Notes. Aber nein, die muss ich mir mühsam selber suchen. Und da finde
ich dann aktuell als einzige Erklärung diese:
"Improvements including the support of drag-and-drop programming of .hex
files for ST-LINK/V2-1 and STLINK-V3 boards"
Auch so, und inwiefern soll das jetzt für die IDE relevant sein?
Das meine ich mit unnötigen Updates! Jedes Firmwareupgrade bringt das
Risiko mit sich, das Gerät für immer unbrauchbar zu machen. Ich will
dieses Risiko nicht für solche Pillepalle Änderungen an Features
eingehen, die ich nicht einmal nutze.
Ärgerlich finde ich auch, dass ich die Release Notes zu älteren
Versionen nicht finden konnte.
Hallo allerseits, da bin ich wieder.
Ich habe bis jetzt halbwegs erfolgreich mit Timerinterrupts
herumgespielt, letztes Wochenede mit ADC/DMA angefangen, und stehe jetzt
vor einem Problem:
Wenn ich ein neues Programm in den F3 übertragen will, kommt die Meldung
"Error in final launch sequence: Failed to start GDB server."
Hat jemand eine Idee, was da das Problem sein könnte?
Noch etwas, was ich gefunden habe:
Im Debuggertab links, wo auch der Projektexplorer ist (öffnet man mit
Klick auf die Wanze ganz rechts oben) steht eine Baumstruktur, die da
sagt:
<terminated>SandkastenF3 (so heißt mein Projekt)
-<terminated, exit value: 0> C:/sehr/langer/Dateipfad
-<terminated, exit value: -1> ST-LINK (ST-LINK Gdb Server)
Außerdem gibt es noch einen Debuggertab unten, in dem steht außer
Lizenzhinweisen aber nichts, was hilfreich aussieht.
Hat jemand eine Idee, wie ich das reparieren kann? Die IDE hab ich
zwischenzeitlich schon neu installiert.
Low-Level-Programmierer schrieb:> Hm, also ein Target Connect mit dem ST-Link Utility ist erfolgreich.
Und Speicher auslesen geht auch?
Wenn ja, hast du wohl ein Problem mit GDB oder mit dessen Konfiguration.
Die IDE legt für jede Debug-Konfiguration eine Datei im Hauptverzeichnis
des Projektes an. Lösche die mal, und klicke dann mit der rechten
Maustaste auf den Projektnamen und dann "Debug As...", dann auf "STM32
Cortex-M C/C++ Application". Die IDE legt dann eine neue
Konfigurationsdatei an.
Low-Level-Programmierer schrieb:> Hm, du meinst die .cfg-Datei?
Ja, die meinte ich
> Die hab ich gelöscht, aber das Problem besteht weiterhin.> Und CubeIDE hat die Datei auch nicht wiederhergestellt.
Dann würde ich mal suchen, wo die IDE entsprechende Logfiles hin
schreibt oder wie man das Logging einschaltet.
Ich habe hier mal den Inhalt des Logfiles, falls das weiterhilft:
Ganz unten steht zwar, daß er externen Speicher nicht initialisieren
kann, aber mit dem Auslesen hatte ST-Link Utility zumindest bis gerade
eben kein Problem.
Das ist jetzt seit gerade eben merkwürdigerweise anders. Vorher hat
ST-Link Utility den Speicherinhalt beim Verbinden angezeigt, jetzt zeigt
es nichts mehr an.
Low-Level-Programmierer schrieb:> Please check power and cabling to target.
Genau das hätte ich jetzt auch ohne diese Meldung empfohlen.
Hast du Dupont Kabel oder Steckbretter im Aufbau? Die haben oft
Wackelkontakte bzw. unsichtbare Kabelbrüche.
Probiere mal ein anderes USB Kabel, ein möglichst dickes kurzes.
Dazu fällt mir gerade noch ein dass die USB Port beliebten Polyfuses
dazu neigen, nach der ersten Auslösung (z.B. durch Kurzschluss) deutlich
hochohmiger zu werden, als in neuem Zustand. Danach Funktionen an
solchen Ports oft keine Festplatten mehr, Mäuse und Tastaturen gehen
aber.
Hm...das ist merkwürdig.
Ich habe mit dem ST-Link Utility auf eine ältere Version "geupdated".
Frag mich nicht warum, aber das ST-Link Utility kennt keine neuere.
Jetzt hat CubeIDE nach einem erneuten Update verlangt (auf die alte,
höhere Version) und nun geht es wieder.
So...jetzt, wo es wieder läuft, hätte ich mal wieder eine Frage. Ich
will den ADC in Verbindung mit dem DMA nutzen.
Ich will den ADC im Continious Mode betreiben. Jetzt habe ich alles
konfiguriert, teils mit CubeMX, teils hab ich mir die Beispielprojekte
von ST angesehen/abkopiert, selbstverständlich auch das Reference Manual
dabei.
Ich würde jetzt erwarten das die DMA-IRQHandler-Funktion angesprungen
wird. Aber das passiert nicht. Sieht jemand vielleicht, was ich nicht
sehe?
ADC-Konfiguration:
Mahlzeit allerseits
Das mit dem ADC und dem DMA ist erledigt - ich habs hinbekommen.
Jetzt wartet hier das nächste auf mich: Ein Nucleoboard mit einem F446
mit MEMS Erweiterungsboard. Zunächst will ich diesen IC darauf über I²C
ansprechen und die Temperatur auslesen:
https://www.st.com/resource/en/datasheet/hts221.pdf
ST stellt zwar ein Softwarepackage bereit, aber ich will mich da auch
nicht zu sehr auf ST-Produkte festnageln lassen, und etwas lernen will
ich ja auch.
Ich meine zwar verstanden zu haben wie I²C funktioniert, aber es hapert
noch etwas an der Umsetzung. Entweder hänge ich in meinen Warteschleifen
fest, oder ich lese lediglich das aus was ich als letztes gesendet habe.
Ich weiß das, wenn man den HTS221 ernsthaft nutzen will, erst noch die
Kalibrierbits ausgewertet werden müssen, aber bevor ich die
versehentlich überschreibe will ich zur Sicherheit lieber erstmal etwas
auslesen, was ich nicht versehentlich überschreiben kann.
Low-Level-Programmierer schrieb:> ST stellt zwar ein Softwarepackage bereit, aber ich will mich da auch> nicht zu sehr auf ST-Produkte festnageln lassen
Warum benutzt du dann trotzdem die Bibliothek von ST? Das passt doch
nicht zusammen. Ich meine: Ich will sie dir jetzt nicht unbedingt
ausreden, aber entweder stehst du dazu, oder nicht.
Naja, die Bibliotheken sind halt nicht nur auf die Mikrocontroller von
ST, sondern auch auf die Sensoren abgestimmt - jedenfalls, soweit wie
ich das verstanden habe.
Und das ist für mich schon ein Unterschied.
Und wie gesagt - es geht mir auch um das selber machen. Einfach nur eine
Funktion getTemperature() aufrufen...damit ist man schnell fertig, hat
hinterher aber nicht mehr Ahnung als vorher.
Du darfst auch nicht sofort ins DR schreiben nach dem Set Startbit.
Du musst warten bis die Periph auch das Startbit gesendet hat:
"Setting the START bit causes the interface to generate a Start
condition and to switch toMaster mode (MSL bit set) when the BUSY bit is
cleared.
Then the master waits for a read of the SR1 register followed by a write
in the DR register with the Slave address"
Wer weis was die Hardware macht wenn man sofort ins DR reinbrüllt.
Hast du eigentlich nen Oszi um zu gucken was am I2C rauskommt?
Sonst ist das ne Suche im Nebel.
Warum du nach dem Stop noch was schreibst erschließt sich mir jetzt auch
nicht.
Im Refman stehen schöne Schritt für Schritt Anleitungen an den man sich
langhangelt.
Ansonsten noch Kleinigkeiten:
Erst den I2C aktivieren, dann die Pins einstellen.
Das kann sonst Glitches auf dme IO geben und das mögen die I2C SLaves
eher nicht.
Ansonsten müssen die I2C Oins auf ALternate Function Open Drain gestellt
werden.
Die COnfig kannste also auch mal hier reinhängen.
Low-Level-Programmierer schrieb:> Naja, die Bibliotheken sind halt nicht nur auf die Mikrocontroller von> ST, sondern auch auf die Sensoren abgestimmt - jedenfalls, soweit wie> ich das verstanden habe.
Wer mir neu, dass da was abgestimmt wäre.
Ich weiß jetzt nicht, wie verbuggt die I²C Schnittstelle beim F4 ist,
aber beim F1 bekommt man sie ohne die zahlreichen Hinweise vom Errata
Dokument kaum ans Laufen.
@Mw E.:
Nach dem Stopp schiebe ich das, was ich gelesen habe, über die USART am
ST-Link raus und schau mir das mit hterm an.
Dann werd ich mal nochmal das Errata Sheet ansehen, und die
Konfiguration ändern...
Low-Level-Programmierer schrieb:> Nach dem Stopp schiebe ich das, was ich gelesen habe, über die USART am> ST-Link raus und schau mir das mit hterm an.
Hmm, freudscher verleser?
Das USART hab ich gekonnt überlsen, da ich nur I2C Funktionen erwartet
habe :>