Hallo, ich arbeite mich gerade in die HAL Bibliothek ein und habe Probleme mit dem I2C. Der CubeMX generiert ja die ganze Hardware-Initialisierungen und man muss dann nur noch die Transmit-Funktion aufrufen: HAL_I2C_Master_Transmit(h_i2c, (slave_address << 1), p_data, length, 100); Dummerweise funktioniert das nicht - das BUSY Bit wird gesetzt und nicht mehr gelöscht. Dies ist offenbar auch ein bekannter Bug für den es sogar einen/mehrere Workarounds gibt. Diese funktionieren aber bei mir nicht, und da ich schon den halben Tag damit rummache, habe ich jetzt auch die Schnautze voll. Die Hardware ist soweit in Ordnung, da ein Treiber mit der Standard Perpheral Library und diesem Setup läuft. Meine Frage ist nun, ob jemand vielleicht etwas lauffähigen Code mit dem CubeMX und dem HAL für einen STM32F103C8 hat? Gruß und Danke Peter
Für den SSD1306 mit oder ohne DMA hat das prima funktioniert. Welcher I2C Baustein macht denn Probleme? Hast du eine Möglichkeit die Signale anzusehen?
pegel schrieb: > Für den SSD1306 mit oder ohne DMA hat das prima funktioniert. as kann ich bestätigen. Häng doch mal die vom CubeMX generierte PDF und deine main.c an!
Peter schrieb: > Meine Frage ist nun, ob jemand vielleicht etwas lauffähigen Code > mit dem CubeMX und dem HAL für einen STM32F103C8 hat? Ich habe lauffähigen Code ohne Cube HAL, aber auf Basis der CMSIS Core Library, die in allen HAL Projekten als Unterbau enthalten ist. Das ist nicht ganz das, wonach du suchst, aber zur Not hilft es vielleicht trotzdem. http://stefanfrings.de/stm32/index.html#i2c
https://www.st.com/content/ccc/resource/technical/document/errata_sheet/7d/02/75/64/17/fc/4d/fd/CD00190234.pdf/files/CD00190234.pdf/jcr:content/translations/en.CD00190234.pdf Seite 26 Alternativ gibt es das Problem, dass eventuell noch was anderes am selben Pin hängt und danach initialisiert wird. Schau dir ganz genau an wo die Pins initialisiert werden, wo das peripheral und wo die clocks
Ich kann mich dunkel an ein Problem mit Datentypen dabei erinnern. Danach habe ich mir angewöhnt die Typen anzugeben, seit dem gab es keine Probleme mehr. Z.B. in der Art:
1 | HAL_I2C_Master_Transmit(&hi2c1,(uint16_t)OLED_I2C_ADDR,(uint8_t*)init_sequence,sizeof(init_sequence),100); |
Peter schrieb: > ich arbeite mich gerade in die HAL Bibliothek ein und habe Probleme mit > dem I2C. > > Der CubeMX generiert ja die ganze Hardware-Initialisierungen und man > muss dann nur noch die Transmit-Funktion aufrufen: [...] > Dummerweise funktioniert das nicht - das BUSY Bit wird gesetzt und nicht > mehr gelöscht. Dies ist offenbar auch ein bekannter Bug für den es sogar > einen/mehrere Workarounds gibt. Diese funktionieren aber bei mir nicht, > und da ich schon den halben Tag damit rummache, habe ich jetzt auch die > Schnautze voll. Jetzt ist der Zeitpunkt gekommen einen Schritt zurückzutreten, die Zusammenhänge zu betrachten, seine Schlüsse zu ziehen und den bisherigen Weg in Frage zu stellen: Warum nimmst Du CubeMX? Was bringt es Dir? Was würde Dir ohne es fehlen? Bringt es im Endeffekt mehr Nutzen oder kostet das Zusammensuchen der Bezeichner und Funktionen, das Verstehen der Funktionen, der Workaround um Bugs evtl. mehr als es nutzt? Versuch auch mal alternative Wege: - libopencm3 - die Register alle selbst ansprechen - ChibiOS HAL Such hier mal im Forum ein bischen nach für und wider zum Cube, da findest Du noch mehr Berichte und Argumente. Mein Fazit für mich ist, daß ich um das Cube einen weiten Bogen mache.
Falls Dir mein I²C Code Beispiel ziemlich komplex vorkommt: Auf AVR wäre der Quelltext sehr viel kürzer. Aber ich habe mir das nicht so ausgedacht, ich habe lediglich die Hinweise aus der entsprechenden Application Note und dem Errata umgesetzt. > Mein Fazit für mich ist, dass ich um das Cube einen weiten Bogen mache. Meins auch, aus den selben Gründen, die du genannt hast. Leider ist die I²C Schnittstelle gerade kein gutes Beispiel, um die Einfachheit der Programmierung "zu Fuß" zu demonstrieren.
Wieso endet die Diskussion wenn jemand CubeMX einsetzt eigentlich immer gleich? Lasst doch jeden machen wie er will. Nur weil ein kleines Problem auftritt muss man nicht gleich alles verteufeln. Und nun: Feuer!
Ach ja, in den Beispielen von ST wird es auch mit Datentyp Angabe gemacht. Aus der I2C/I2C_TwoBoards_ComPolling/Src/main.c :
1 | while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 10000)!= HAL_OK) |
pegel schrieb: > Wieso endet die Diskussion wenn jemand CubeMX einsetzt eigentlich immer > gleich? > Lasst doch jeden machen wie er will. > > Nur weil ein kleines Problem auftritt muss man nicht gleich alles > verteufeln. Wo habe ich verteufelt? Wo habe ich ihn nicht machen lassen wie er will? ST empfiehlt das Cube halt an jeder Ecke, das ist ja der Hersteller und die werden es schon wissen etc. Viele Neueinsteiger wissen daher gar nicht daß es Alternativen gibt und denken das wäre halt so wie es ist. Jeder muss seine Entscheidung für sich treffen. Doch dafür muss er erst mal wissen daß er überhaupt eine Wahl hat und was die Alternativen sind. Darauf wollte ich hinwesen, mehr nicht.
Hallo, danke für die vielen Antworten. Dummerweise hatte ich hier gerade ein ganz anderes Problem. Beitrag "OpenOCD startet plötzlich nicht mehr, Boards defekt" Es ist inzwischen (teilweise) gelöst, aber ich bin immer noch etwas skeptich, was denCubeMX betrifft. Trotzdem werde ich es weiterhin versuchen den I2C zum laufen zu bringen. Bei meinem Test-Projekt, welches die im anderen Thread genannten Probleme hervor brachte, hatte ich übrigens keinerlei weitere Hardware an dem Testboard hängen - also auch keine weiteren Signal-Pegel (mit ausnahme des JTAG). Gruß Peter
Da ich weder die HAL noch die alte SPL-Libs verwende, habe ich mir die I2C-Routinen selbst lowlevel auf Registerbasis geschrieben. Ich hänge die hier mal mit an, eventuell kann das ja mal wer gebrauchen. Benutzt werden kann es so um die ersten 7 Byte aus einer DS1307 rtc zu lesen:
1 | #include <i2c.h> |
2 | |
3 | |
4 | I2C aI2C(1); // I2C1 benutzen 2 fürI2C2 |
5 | |
6 | ...
|
7 | int rc=0; |
8 | // init I2C, no portremap, use PB6 and PB7
|
9 | rc=aI2C1.Init(I2C_FAST, false); |
10 | if (rc==0) |
11 | {
|
12 | uint8_t wdata[]={0}; |
13 | uint8_t rdata[7]; |
14 | |
15 | // 0x68 is the address for DS1307
|
16 | // write 1 byte (0) to set the addr in DS1307 to 0
|
17 | // read 7 byte from addr 0 in DS1307
|
18 | int rc=aI2C.WriteAndRead(0x68,wdata,1,rdata,7); |
19 | if (rc!=7) |
20 | return false; |
21 | }
|
22 | ...
|
(Das kurze Beispiel ist jetzt nicht getestet)
pegel schrieb: > Welcher I2C Baustein macht denn Probleme? > Hast du eine Möglichkeit die Signale anzusehen? Das ist so ein LCD Modul: https://funduino.de/nr-19-i%C2%B2c-display SCL und SDA sind beide auf high, und es ist kein einziger Wackler zu sehen. Harry L. schrieb: > Häng doch mal die vom CubeMX generierte PDF und deine main.c an! Das PDF hängt an, die main.c auch. Stefanus F. schrieb: > Ich habe lauffähigen Code ohne Cube HAL, aber temp schrieb: > Da ich weder die HAL noch die alte SPL-Libs verwende, habe ich mir die > I2C-Routinen selbst lowlevel auf Registerbasis geschrieben. Es geht mir nur um den CubeMX, aber danke. Der Witz ist, dass das Senden über I2C (nach der Initialisierung durch den Cube) nur aus einer einzigen Funktion HAL_I2C_Master_Transmit() besteht - aber es geht trotzdem nicht. Gerd E. schrieb: > Warum nimmst Du CubeMX? Die StdPeriphLib wird nicht mehr weiter entwickelt. Wenn ich also up-to-date bleiben will, dann muss ich wechseln. pegel schrieb: > Ach ja, in den Beispielen von ST wird es auch mit Datentyp Angabe Das halte ich für überzogen, aber nun gut. Gruß Peter
Beim kurzen Überfliegen habe ich nichts gefunden wo du die Gpio-Pins für I2C und Opendrain konfigurierst.
temp schrieb: > Beim kurzen Überfliegen habe ich nichts gefunden wo du die Gpio-Pins für > I2C und Opendrain konfigurierst. Das wird alles in den als 'weak' definierten Funktionen der stm32f1xx_hal_msp.c Datei erledigt (hier HAL_I2C_MspInit()). Diese Funktionen wiederum werden durch die HAL-Treiber eingebunden. In Falle des I2C durch HAL_I2C_Init() (siehe Anhang). Vorab wird die komplette Datei durch den CubeMX projekt-spezifisch erstellt (ich sag ja: Der Cube ist was für Faule).
Peter schrieb: > Das halte ich für überzogen, aber nun gut. Wie jetzt? Warum machst du nicht einfach mal aus deinem: HAL_I2C_Master_Transmit(&hi2c1, (0x27 << 1), &value, 1, 100); ein: HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)(0x27 << 1), (uint8_t*)value, 1, 100); ?
pegel schrieb: > Warum machst du nicht einfach mal aus deinem: > > HAL_I2C_Master_Transmit(&hi2c1, (0x27 << 1), &value, 1, 100); > > ein: > > HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)(0x27 << 1), (uint8_t*)value, > 1, 100); > > ? Weil das meiner Meinung nach keinen Unterschied macht wenn 'value' als uint8_t definiert ist. Und (0x27 << 1) passt auch immer noch in einen 8 Bit Wert rein - in einen 16 Bit Wert also allemal.
pegel schrieb: > Nur weil ein kleines Problem auftritt muss man nicht gleich alles > verteufeln. > > Und nun: Feuer! Nein. Eher den Löschwagen. So wie ich das sehe, machen all diese Hersteller-Helferlein zwei Dinge: Erstens halten sie den Benutzer soweit von der eigentlichen Hardware ab, daß er meint, sie nicht verstehen zu müssen, womit er auf eben diese Hersteller-Programme und folglich auf den Hersteller angewiesen wird/bereits ist. Ist eben die Hersteller-Bindung. Man sieh das hier in diesem forum häufig, daß Leute zwar Arm-Cortex meinen, aber dazu "Stm32" sagen. Ist wie Hoover für Staubsauger zu sagen. Zweitens bauschen sie all die Hardware-Dinge gewaltig auf, mit Unmengen zusätzlicher Bezeichner, die man sich nie und nimmer wirklich merken kann. Peter schrieb: > ich arbeite mich gerade in die HAL Bibliothek ein und habe Probleme.. Und deshalb würde ich dir eher dazu raten, derartige herstellerspezifische Helferlein besser nicht verwenden zu wollen und stattdessen deinen eigenen Weg zu gehen und dir deine eigenen Lowlevel-Treiber zu schreiben. Allerdings sind mMn die I2C-Cores der meisten heutigen µC eher krötig gemacht. Frühere Cores waren primitiv und haben den Benutzer mit Unmengen von Interrupts zu jedem blöden Zustandswechsel am I2C belästigt. Heutige I2C-hardware ist hingegen teilweise völlig überzüchtet, so daß sie irgendwelche Transfers ganz allein erledigen will, was jedoch andere Probleme macht, insbesondere dann, wenn man beim Öffnen einer Verbindung noch nicht weiß, wieviel Bytes beim Transfer tatsächlich zu erwarten sind - was ja eigentlich die Regel ist. Nicht umsonst gibt es ACK/NAK. In Problemfällen neige ich dazu, den I2C schlichtweg mal per Software zu benutzen, um Zickigkeiten des I2C-Cores auszuschließen. Dies zusammen mit dem Oszilloskop hilft sehr. Mir sind bei solchen Gelegenheiten auch Chips aufgefallen, die extrem zickig sind bei den Low-Pegeln, weswegen man dort schon beim Adressieren kein ACK kriegt. W.S.
W.S. schrieb: > Und deshalb würde ich dir eher dazu raten, derartige > herstellerspezifische Helferlein besser nicht verwenden zu wollen und > stattdessen deinen eigenen Weg zu gehen und dir deine eigenen > Lowlevel-Treiber zu schreiben. Ich habe ja schon gesagt, dass die StdPeriphLib eingestellt wird. Deshalb will ich wechseln.
pegel schrieb: > Ich geb es auf. > Dann mach mal. Dann erklär mir mal bitte was der entscheidende Unterschied ist? Übrigens, wenn ich das so mache wie Du vorschlägst, dann bekomme ich eine Warnung: warning: cast to pointer from integer of different size Sollte es vielleicht nicht vielmehr so lauten? HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)(0x27 << 1), (uint8_t*)&value, 1, 100);
Die Funktion HAL_I2C_Master_Transmit erwartet eine 16bit Adresse. Du gibst ihr 8bit und weißt nicht was in den anderen 8bit steht. Das & hängt natürlich davon ab, wie value definiert ist. Meine Funktion sieht so aus:
1 | void oled_on(){ |
2 | const uint8_t disp_on [] = { |
3 | 0x00, |
4 | 0xAF, |
5 | };
|
6 | HAL_I2C_Master_Transmit(&hi2c1,(uint16_t)OLED_I2C_ADDR,uint8_t*)disp_on,sizeof(disp_on),100); |
7 | }
|
W.S. schrieb: > In Problemfällen neige ich dazu, den I2C schlichtweg mal per Software zu > benutzen, um Zickigkeiten des I2C-Cores auszuschließen. ... oder wenn es einfach nur funktionieren soll ;-) Peter schrieb: > Ich habe ja schon gesagt, dass die StdPeriphLib eingestellt wird. Das ist doch kein sonderliches Problem. Für GPIO oder ... kannst Du doch ruhig die SPL weiter verwenden, wenn Du magst. Die sind doch zum größten Teil bei allen STM32 gleich. Lediglich bei RCC und einigen anderen Einheiten können mehr Bits dazugekommen sein. Das steht dann im Referenz-Handbuch. Haupsache ist, daß die "stm32fxxx.h" verfügbar ist. Dort sind alle vorhandenen Register und Definitionen aufgeführt.
Ich sehe gerade vor uint8_t ist eine Klammer verloren gegangen.
pegel schrieb: > Die Funktion HAL_I2C_Master_Transmit erwartet eine 16bit Adresse. > Du gibst ihr 8bit und weißt nicht was in den anderen 8bit steht. Danke für den Hinweis. Ich hätte gedacht, das wird automatisch mit Nullen vorbelegt.
Ich habe den Fehler gefunden. temp schrieb: > Beim kurzen Überfliegen habe ich nichts gefunden wo du die Gpio-Pins für > I2C und Opendrain konfigurierst. Das hat mich auf die richtige Fährte gebracht. Denn diese Konfigurationen werden zwar alle durch den CubeMX automatisch erstellt und aufgerufen. Aber im Fall des I2C hat der CubeMX eben nicht gemacht, was er für GPIO, DMA und UART tat. Auch wenn die MX_I2C1_Init() Funktion zwar automatisch generiert wurde, wurde sie nicht in die Start-Sequenz eingefügt:
1 | ...
|
2 | |
3 | /* USER CODE END SysInit */
|
4 | |
5 | /* Initialize all configured peripherals */
|
6 | MX_GPIO_Init(); |
7 | MX_DMA_Init(); |
8 | MX_USART1_UART_Init(); |
9 | |
10 | /* USER CODE BEGIN 2 */
|
11 | x_user_init(&hi2c1, &huart1); |
12 | |
13 | ...
|
Wie man oben sieht hat der CubeMX die Initialisierungen für DMA, GPIO und USART automatisch eingefügt, aber die für I2C nicht. Nach händischem Einfügen von MX_I2C1_Init() läuft jetzt alles. Gruß Peter
Nachtrag: Das witzige ist, wenn ich den Code im CubeMX erneut generiere, dann ist der Eintrag für I2C wieder verschwunden. Die für GPIO, UART und DMA sind noch da. Das kann nur ein Bug sein - nicht der Einzige.
Sowas:
1 | for (uint32_t i = 0; i < 100000; i++) |
2 | asm("NOP"); |
wird dir um die Ohren fliegen, da der Compiler das gerne weg-optimiert. Dafür gibt es HAL_Delay(), Und wenn dir diese Wartezeit genommen wird, führt das genau zu dem von dir beschriebenen Verhalten.
Für mich gibt's nur einen Grund, die HAL zu verwenden: USB. Aber diesen Wind haben mir Niklas Gürtler und W.S. aus den Segeln genommen.
Stefanus F. schrieb: > Für mich gibt's nur einen Grund, die HAL zu verwenden: USB. > > Aber diesen Wind haben mir Niklas Gürtler und W.S. aus den Segeln > genommen. Und wen interessiert das? Der TO hat explizit nach HAL und nicht nach Alternativen dazu gefragt.
Stefanus F. schrieb: > Harry L. schrieb: >> Und wen interessiert das? > > Mich. Ich darf auch mal nachtreten. Dann mach doch deinen eigenen "ich hasse HAL"-Thread auf. Solche "Meinungen" sind hier nicht zielführend, bringen den TO kein Stück weiter und stören nur.
:
Bearbeitet durch User
mit asm volatile("NOP"); ist dann wieder alles in Ordnung und der Gammel HAL muss nicht genutzt werden. Stefanus F. schrieb: > Für mich gibt's nur einen Grund, die HAL zu verwenden: USB. > > Aber diesen Wind haben mir Niklas Gürtler und W.S. aus den Segeln > genommen. Der USB Host Code ist der einzige HAL Code den ich in meinen Projekten nutze und der hat BUGS BUGS BUGS. In Verbindung mit nem RTOS jedenfalls. So Scherze wie: der IRQ handler spielt an der Statemachine des Threads rum ud sendet DANN ein Event. Der Thread kennt aber noch den alten Zustand. Das führt dann dazu, dass ein eingesteckter USB Stick nicht immer erkannt wird und der USB Host dann in einem undefinierten Zustand verweilt. Nach 2-3mal stecken gehts dann... Die haben es zudem doch glatt vergessen in der "USBH_LL_Init". Den LOCK State des Initstructs auf 0 zu setzen. Wodurch der HAL mit "locked" gestartet wurde und er somit nix machte. Das funktioniert nur beim ersten Mal, da ist das struct noch durch bss genullt.
Mw E. schrieb: > und der hat BUGS BUGS BUGS. Und die SW die du schreibst ist auf Anhieb fehlerfrei? Respekt!
Peter schrieb: > Das kann nur ein Bug sein - nicht der Einzige. So etwas sollte dir doch eigentlich zu denken geben, oder? Ich meine, wenn einem schon die Bugs so dicht um die Ohren fliegen, dann sollte das doch ausreichend Anlaß sein, ein gewisses Maß an Skepsis aufkommen zu lassen. Und eben auch den Gedanken, sich besser von so etwas zu verabschieden und den eigenen Kram zu pflegen. W.S.
Harry L. schrieb: > Dann mach doch deinen eigenen "ich hasse HAL"-Thread auf. Es sind wohl deine Beiträge, die hier alles andere als zielführend sind. Ich sag's mal so (zum wiederholten Male): Wenn unsereiner jemanden sieht, wie der verzweifelt mit dem Kopf gegen die Wand rennt, weil er durch selbige durchkommen will, sich aber dabei nur eine Beule nach der anderen holt,... DANN: ist es meiner Meinung nach wirklich der beste Ratschlag, ihm zu sagen: "Hör auf, gegen die Wand zu springen. Besinne dich lieber, tritt dann einen Schritt zur Seite und gehe durch die dort vorhandene Tür". Genau das hat Stefanus getan und genau DAS ist auch ein guter und zum Thema passender Ratschlag. W.S.
@jojos, Hab ich nicht gesagt. Nur drücke ich niemanden meine SW so auf wie ST es mit dem CubeMX+HAL tut. Das wird ja überall von ST wie warme Semmeln angeboten und als das nonplusultra. Sobald mans mal nutzt stehen einem die Haare zu berge. Vor allem wenns so offensichtliche Dinge sind die bei Tests auffallen müssten. (Haben die keine QC Abteilung für den HAL?) Bei meinem Registergeclimper hatte ich mich mal vertippt und der HSE wurde nicht für die PLL genommen, sondern der HSI. Fällt erst auf wenn man mal 8MHz statt 16MHz verbaut und man sich über den zickenden UART wundert ;)
Mitmachen, mitgewinnen :) Fehler bei STM melden und hoffen das die auch beseitigt werden. Immerhin wird das alles kostenlos angeboten und die Community hat da sicher schon einiges mitverbessert.
Najaa :/ Wenn man nach so diesen HAL Bugs sucht findet man imemr wieder, dass die schon reported wurden und nicht viel passiert ist. Das USB Host Problem wird sich nur durch viel umschreiben der Statemachine. Bis jtzt muss ich mir mit nem Workaround helfen: USb Host komplett beenden wenn der Stick gezogen wird und neuinit des Host.
W.S. schrieb: > Ich sag's mal so (zum wiederholten Male): > > Wenn unsereiner jemanden sieht, wie der verzweifelt mit dem Kopf gegen > die Wand rennt, weil er durch selbige durchkommen will, sich aber dabei > nur eine Beule nach der anderen holt,... Komm mal langsam wieder runter von deinem hohen Ross! Ich bin zumindest auf die ursprüngliche Frage des TO eingegangen - du betreibst -wie üblich- nur dein "HAL-Bashing" Ich hab keine Probleme mit HAL, und alles, was ich hier von den "HAL-Kritikern" lese ist fast ausnahmslos Blabla, weil die sich gar nicht erst die Mühe gemacht haben, das überhaupt "verstehen zu wollen", und sowieso alles viel besser können, als die Leute von ST. Dein Code, den du nicht müde wirst, an allen erdenklichen Stellen anzupreisen ist ganz sicher auch nicht fehlerfrei und auch nicht der Weisheit letzter Schluß. Das mag ja für dich das Optimale sein - für Andere muß das noch lange nicht zutreffen.
Harry L. schrieb: > Alles, was ich hier von den > "HAL-Kritikern" lese ist fast ausnahmslos Blabla, weil die sich gar > nicht erst die Mühe gemacht haben, das überhaupt "verstehen zu wollen" Das schätzt du aber ganz falsch ein. Ich kann Dir mit Sicherheit sagen, dass ich die HAL ernsthaft verwenden wollte. Mit ganz viel Doku lesen, denn da es nur mein Hobby ist (der Weg ist das Ziel) hatte ich auch die Zeit dazu. Und ich bin sicher, dass dies auch W.S. gilt. Der Mann ist nicht blöd. Nur, wenn schon der allererste Usecase (Clock Initialisierung mit Default Settings!) den µC zum aufhängen bringt, weil die == mit != verwechselt haben, damm bei zweiten Usecase Bits im falschen Register gesetzt werden und beim dritten Usecase auffällt, dass sie nicht einmal ihre eigenen Empfehlungen aus dem Errata umgesetzt haben, dann verliert man die Lust an der HAL. Ich habe keinen Bock, mich nach dieser Erfahrung auf so viel fremden Code zu verlassen. Wirklich leicht zu lesen ist er ja auch nicht gerade. Bevor ich diesen Rotz umfangreich analysiert und kontrolliere, schreibe ich es lieber selbst. Dann weiß ich auch, was ich da mache. Beruflich entwickle ich Java Enterprise Anwendungen. Glaube mir, ich bin es absolut gewohnt, massenweise fremde Libraries und Sourcen einzubinden. Auch dort muss ich zwischen Rotz und guten Libraries unterscheiden - und zwar ernsthaft, denn da können Fehler das Aus der Firma bedeuten. Verglichen mit den Java Libraries, ist die HAL ein großer Haufen schlecht dokumentierter und schlecht gepflegter Rotz. Noch wesentlich schlechter als die kurzlebige SPL. Da ist mir sogar Arduino noch lieber, und das soll schon was bedeuten.
Stefanus F. schrieb: > Ich habe keinen Bock, mich nach dieser Erfahrung auf so viel fremden > Code zu verlassen. Wirklich leicht zu lesen ist er ja auch nicht gerade. > Bevor ich diesen Rotz umfangreich analysiert und kontrolliere, schreibe > ich es lieber selbst. Dann weiß ich auch, was ich da mache. Ging mir genauso ... Erstes STM32-Projekt mit HAL versucht und festgestellt, dass es nicht nur buggy ist sondern auch erstaunlich viel Performance frisst, da sehr viel Overhead. Mühsam damals das Projekt dann von HAL wieder weg-migriert und seitdem läuft alles wunderbar und ich fasse HAL nicht mehr an. CubeMX finde ich allerdings super, um die Pins zu konfigurieren ... Code lasse ich mir da aber nicht generieren.
Stefanus F. schrieb: > ist die HAL ein großer Haufen > schlecht dokumentierter und schlecht gepflegter Rotz. Noch wesentlich > schlechter als die kurzlebige SPL. Da ist mir sogar Arduino noch lieber, > und das soll schon was bedeuten. Volle Zustimmung auch von mir. Auch zu der Aussage bezüglich Arduino. Der Code den die Arduino-Leute schreiben ist jedenfalls deutlich besser als der von dem STM-Praktikanten. Wer weiß schon ob die HAL nicht auch nur so ein kurzes Leben hat. Die Register bleiben. Und die gesamte Doku ist in einem einzigen pdf. Was will man mehr.
temp schrieb: > Und die gesamte Doku ist in einem einzigen pdf. Was will man mehr. Nicht untertreiben, es sind drei: - Reference Manual - Datasheet - Errata Für die Assembler Programmierer kommt noch das dazu: - STM32 Cortex Mx Programming Manual
Hallo, ohne alles gelesen zu haben, kann ich Dir sagen, dass die I2C prime Cell Bugs hat! Da habe ich mich auch schon dran tot gesucht, dass die Statemachine sich aufhängt. Habe aber lauffähigen StdPeriph Code für den M3. Mit kompletter Fehlerabfrage aller Events.
Ich verwende HAL ja ich finde auch hier bugs. Aber es ist ja auch meine Entscheidung... Gerade der USB Host mit RTOS funktioniert wirklich nicht sauber. Da sollte man nochmal drüberwischen Aber ansonst habe ich bisher bei sehr wenigen stellen Probleme gehabt. Gerade die seriellen Verbindungen funktionieren recht gut. Und sehr oft saß das Problem VOR dem Rechner!! Und so viel Overhead frisst das auch nicht , es sei denn man nutzt nur O0 Optimierung.
fsdf schrieb: > ja ich finde auch hier bugs. > Aber es ist ja auch meine Entscheidung... Ich meine damit Bugs in der Hardware! Bei mir lief die Anwendung ein paar Stunden, bis dann ein Event Flag nicht mehr kam, was aber kommen musste. Und O0 benutze ich bei allen Hardware Zugriffen, damit das was da steht auch genauso ausgeführt wird. Ist bei uns in der Firma übrigens auch Codierungs Richtlinie geworden für den GCC.
Chris J. schrieb: > -O0 ist bei uns in der Firma übrigens auch > Codierungs Richtlinie geworden für den GCC. Habt Ihr mit dem Optimizer schlechte Erfahrung gemacht? Wenn ja, würde mich interessieren, was vorgefallen ist. Oder geht es darum, nachträglich einen Debugger anstöpseln zu können.
Chris J. schrieb: > Und O0 benutze ich bei allen Hardware Zugriffen, damit das was da steht > auch genauso ausgeführt wird. Ist bei uns in der Firma übrigens auch > Codierungs Richtlinie geworden für den GCC. Besser du machst für deine Firma keine Werbung.
Stefanus F. schrieb: > Aber diesen Wind haben mir Niklas Gürtler und W.S. aus den Segeln > genommen. Na da danke ich... ;-) Chris J. schrieb: > Und O0 benutze ich bei allen Hardware Zugriffen, damit das was da steht > auch genauso ausgeführt wird. Ist bei uns in der Firma übrigens auch > Codierungs Richtlinie geworden für den GCC. Hast du dir den vom GCC generierten Code bei -O0 mal angeschaut? Der ist nicht nur einfach ineffizient, da ist jede Menge komplett unnötiges Zeug drin. So Dinge wie:
1 | 80004284: e50b100c str r1, [r11, #-12] |
2 | 80004288: e51b000c ldr r0, [r11, #-12] |
kommen da in Mengen vor. Ich finde den optimierten Code (-O2) sogar deutlich besser lesbar. Funktionen welche zur Laufzeit nichts machen und nur Referenzen casten (insb. std::forward) werden zu längeren Prozeduren - für jeden Typ einzeln!
1 | 80004250 <Foo& std::forward<Foo&>(std::remove_reference<Foo&>::type&)>: |
2 | 80004250: e52db004 push {r11} ; (str r11, [sp, #-4]!) |
3 | 80004254: e28db000 add r11, sp, #0 |
4 | 80004258: e24dd00c sub sp, sp, #12 |
5 | 8000425c: e50b0008 str r0, [r11, #-8] |
6 | 80004260: e51b3008 ldr r3, [r11, #-8] |
7 | 80004264: e1a00003 mov r0, r3 |
8 | 80004268: e28bd000 add sp, r11, #0 |
9 | 8000426c: e49db004 pop {r11} ; (ldr r11, [sp], #4) |
10 | 80004270: e12fff1e bx lr |
Diese Funktion macht absolut nichts. Die könnte man zu einem schlichten "bx lr" vereinfachen. Bei eingeschaltetem Optimizer passiert das auch, wird inlined. Den unoptimierten Code möchte man gar nicht auf den armen Controller spielen... Ohne Optimizer ist wie mit angezogener Handbremse zu fahren. Ich hatte es bisher nur sehr selten, dass wirklich etwas kaputt optimiert wurde, und das passiert auch nur bei fehlerhaftem Code. Ich konnte die Optimierung immer recht problemlos bei Hardware-Zugriffen nutzen. Nur Styp-by-Step-Debugging ist lästiger. Stefanus F. schrieb: > Nicht untertreiben, es sind drei: Das ARMv7-M Architecture Reference Manual ist auch enorm hilfreich... Stefanus F. schrieb: > Nur, wenn schon der allererste Usecase Wie neu war denn der Controller? Wenn das etwas reift, sollte es doch stabiler werden... Ich arbeite auch selten mit CubeMX, aber habe z.B. mal eine einfache DC-Motorregelung gebastelt: Im CubeMX den PWM-Input-Capture, PWM-Output und GPIO zusammen geklickt, ein paar Zeilen Füllcode und den eigentlichen Regler in C geschrieben, und hat sofort funktioniert. So war das schon ganz nett.
:
Bearbeitet durch User
Stefanus F. schrieb: > Habt Ihr mit dem Optimizer schlechte Erfahrung gemacht? Wenn ja, würde > mich interessieren, was vorgefallen ist. Inzwischen hat auch der Keil Compiler Einzug gehalten. Es geht einfach darum, dass wenn Du SIL 3 Produkte herstellst der Notified Body, in dem Fall der TÜV oder die PTB nachvollziehen können will ob der Code die Richtlinien einhält. Die gehen durch den Asm durch. Und das geht nicht, wenn der Compiler etwas erzeugt, was keiner mehr nachvollziehen kann. Auf O0 erzeugt jede Zeile einen Abschnitt, stur durch. Keine Var wird weg optiomiert. Man denke nur an globale Variablen, die weg optimiert werden könnten. Ebensfalls verboten sind alle Arten von Zeiger Funktionen und Rekursionen. Als ich noch Gutachter der KTA 3503 war gingen wir auch jeden einzelnen Asm Befehl durch in Steuerungen an denen lebenswichtige Funktionen eines Kraftwerkes hängen. Versuche einen Compiler als "bewährte Technik" durch zu kriegen laufen seit 2014 mit IAR, die ihren zertifizieren lassen wollen. Bei 180 Mhz und 1MB Flash juckt es keinen ob da mehr oder weniger Code drin ist.
> Stefanus F. schrieb: >> Nur, wenn schon der allererste Usecase Niklas G. schrieb: > Wie neu war denn der Controller? STM32F103RBT6, also eher ein Opa, aber noch nicht tot. > Wenn das etwas reift, sollte es doch stabiler werden... Aber dass man die PLL erst nutzen kann NACHDEM sie Ready ist, sollte jedem Entwickler bei ST klar sein - auch den Praktikanten. Die haben es aber anders herum programmiert: Erst auf die PLL umschalten, dann warten, dass sie Ready wird. Solch grobe Fehler erwartet man nicht in diesem Framework.
Stefanus F. schrieb: > Erst auf die PLL umschalten, dann > warten, dass sie Ready wird. Vielleicht ist die Hardware ja clever genug, erst dann umzuschalten, wenn die PLL ready ist. So erschlägt man dann 2 Klappen mit einer Warteschleife. Ich meine, solchen Code hier irgendwo auch schon ohne HAL gesehen zu haben... War er sogar von W.S.? Chris J. schrieb: > Bei 180 Mhz und 1MB Flash juckt es keinen ob da mehr oder weniger Code > drin ist. Wie ist das mit Leistungsaufnahme, Akku-Lebensdauer und Stückpreis des Controllers?
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.