Hallo Leute Mein eigener Networking Stack mit eigener Ethernet, IPv4, TCP, HTTP, ICMP und ARP Implementation ist nun in einem Zustand, in dem er zumindest auf meinem Linux PC einigermassen gut funktioniert. Ich Kompiliere das Projekt immer auch noch für einen atmega16, um zu verhindern, dass sich Programmabhängige Dinge einschleichen. Zum Portieren auf eine andere Platform müssen nur ein Timer und die Funktionen zum Senden und Empfangen einer Ethernet-Frame implementiert werden. Das Programm benötigt nur einen C11 Komplianten Compiler mit Support für das GCC Section und Packed Attribut, welche aber mittlerweile so ziemlich jeder Compiler unterstützt. Das gesamte Projekt ist OpenSource und unter der MIT-Lizenz verfügbar: https://github.com/Daniel-Abrecht/DPA-UCS Nun will ich endlich testen, ob es auf einem Mikrocontroller Funktioniert. Dies ist mein erstes μC Projekt, ich habe zwar bereits eine Lötstation, und einige Bauteile wie Widerstände und Kondensatoren herumliegen, aber der gesamte Rest fehlt mir noch. Zunächst zum μC, ich denke auf einem AVR zu bleiben macht Sinn, aber der atmega16 scheint etwas wenig RAM zu haben, was würdet ihr mir hier Empfehlen? Dann brauche ich noch einen Programmer der zum μC passt, welche Technologie (ISP,JTAG, oder ein High Voltage Programmer?), und welche konkreten Programmer würdet Ihr empfehlen? Ein USB UART Adapter erscheint mir auch noch nützlich, damit ich mir Log-Meldungen ausgeben lassen kann. Und die Geräte müssen unter Linux funktionieren. Dann brauche ich noch einen PHY, oder? Dieser darf aber keinen eigenen TCP/IP Stack haben, weil ich meinen eigenen testen will. Bei LAN scheinen diese etwas einfacher zu finden zu sein, aber wenn ich einen mit W-Lan finden würde, dann wäre ich nicht durch ein Kabel eingeschränkt. Schliesslich fehlt noch die Projekt-Idee. Anfangs dachte ich an ein kleines Auto, aber ein LAN-Kabel wäre dort etwas unpraktisch. Danach dachte ich an ein Rotor Clock Display, aber das Timing wäre während dem Senden und Empfangen von Ethernet Paketen sicher Problematisch. Ein LCD Text Display wäre vermutlich relativ einfach umzusetzen, aber dort fehlt irgendwie das gewisse etwas. Hier könnte ich noch einige Ideen brauchen. Aufbauen würde ich das ganze am liebsten auf einer Lochraster Platine, zumindest erscheint mir dies am einfachsten. Es geht mir momentan hauptsächlich um Ideen und Empfehlungen, um eine bessere Idee davon zu bekommen, was ich überhaupt womit bauen will.
Wie wäre es damit, einfach einen festen HTTP-Request auf Tastendruck abzusetzen? Oder ein UDP Broadcast?
Torsten R. schrieb: > Wie wäre es damit, einfach einen festen HTTP-Request auf Tastendruck > abzusetzen? Oder ein UDP Broadcast? Der Networking Stack ist noch nicht wirklich fertig, ich habe momentan erst die Server-Seite des HTTP Protokolls implementiert, also das Beantworten von HTTP-Requests mit einer HTTP-Response. Ich bin auch noch nicht dazu gekommen, UDP zu implementieren. Ich könnte wohl zu Testzwecken eine LED per HTTP Request ein oder ausschalten, und das ganze erst später um komplexere Dinge erweitern. Ich muss mich aber so oder so zuerst noch entscheiden, was für einen uC, Programmer, PHY, etc. ich mir besorgen will.
Daniel A. schrieb: > Ich könnte wohl zu Testzwecken eine LED per HTTP Request ein oder > ausschalten, und das ganze erst später um komplexere Dinge erweitern. Ist doch auch cool, dann kann man mit curl eine LED an und aus schalten :-) > Ich muss mich aber so oder so zuerst noch entscheiden, was für einen uC, > Programmer, PHY, etc. ich mir besorgen will. Hast Du Dir mal die Unmengen von ARM Cortex M0/M3/M4 etc. eval boards angeguckt? (von ST, NXP, etc.) Die haben in der Regel immer irgend ein integrierten Debug-Adapter mit dabei, mit dem Du den Controller flashen und debuggen kannst. Vielleicht findet sich in der Menge der Controller, auch einer, der bereits passende Hardware onboard hat.
>Zunächst zum μC, ich denke auf einem AVR zu bleiben macht Sinn, aber der >atmega16 scheint etwas wenig RAM zu haben, was würdet ihr mir hier >Empfehlen? Ein AVR-NET-IO. Den ATMega32 gleich rausschmeissen und einen ATMega1284 einsetzen. Dann noch die diversen Verbesserungen für das NET-IO durchführen. Mit einem Cortex-M4 würdest du aber sicher glücklicher werden;) Gibt da nette Nucleo Boards mit Ethernet.
Ich kenn mich ja nur in der Arduino Frickelwelt aus, aber der Atmega 1284p hat jede Menge RAM und der ENC28J60 ist ein Ethernet IC ohne TCP Stack. Wie wäre es mit einem über IP steuerbaren Relais? Ob du ein Relais reinpackst oder mehrere und ob du dann damit eine LED ein- und ausschaltest oder einen Motor startest spielt dann keine Rolle.
Daniel A. schrieb: > Dies ist mein erstes μC Projekt, ich habe zwar bereits > eine Lötstation, und einige Bauteile wie Widerstände und Kondensatoren > Schliesslich fehlt noch die Projekt-Idee. Anfangs dachte ich an ein > kleines Auto, > Es geht mir momentan hauptsächlich um Ideen und Empfehlungen, um eine > bessere Idee davon zu bekommen, was ich überhaupt womit bauen will. Für ein erstes µC Projekt fängt man im Allgemeinen damit an, LEDs blinken zu lassen. Erstmal also ein Lauflicht fürs Auto a la Knight Rider ;-) Da fällt dann die Entscheidung, ob es am Stack oder am "nicht richtig funktionierenden" µC liegt, nicht so schwer. Also erst mal die HW in den Griff bekommen bevor man im SW-Projekt nach Fehlern suchen muß.
Daniel A. schrieb: > > Zunächst zum µC, ich denke auf einem AVR zu bleiben macht Sinn, aber der > atmega16 scheint etwas wenig RAM zu haben, was würdet ihr mir hier > Empfehlen? > Wieviel footprint dein Stack braucht, musst Du schon selber wissen, davon hängt auch u.A. die Ressourcendimensionierung ab, oder? I.d. Regel brauchst Du für einen Netzwerkstack mindestens je 2 Input-und Outputframes @ 1592 bytes sowie dynamischen Speicher für die Pakete zu den höheren Schichten. Dazu natürlich der Bedarf für RTOS und die Applikation. > > Dann brauche ich noch einen PHY, oder? Dieser darf aber keinen eigenen > TCP/IP Stack haben, weil ich meinen eigenen testen will. Bei LAN > scheinen diese etwas einfacher zu finden zu sein, aber wenn ich einen > mit W-Lan finden würde, dann wäre ich nicht durch ein Kabel > eingeschränkt. > Bei lwip gibt es für fast alle gängigen PHYs und uCs ports, da brauchst Du nur die Schnittstelle zur "Unterseite Stack" anzupassen. Ich sehe mir den Code bei Gelegenheit gerne mal an, würde mich aber i.W. für C++ Adaptionen interessieren (Netzwerkstacks in C gibt's in Hülle und Fülle). Good luck!
Ruediger A. schrieb: > Wieviel footprint dein Stack braucht, musst Du schon selber wissen, > davon hängt auch u.A. die Ressourcendimensionierung ab, oder? I.d. Regel > brauchst Du für einen Netzwerkstack mindestens je 2 Input-und > Outputframes @ 1592 bytes sowie dynamischen Speicher für die Pakete zu > den höheren Schichten. Dazu natürlich der Bedarf für RTOS und die > Applikation. Ja, ich habe gerade mal mit avr-size nachgesehen, mit den Log-Meldungen passt es nicht einmal in einen ATMega1284. Ohne die Log-Meldungen, und nachdem ich einige der Puffer und Caches verkleinert habe, komme ich wenn ich es für einen atmega1284 Kompiliere noch auf rund 11441 bytes benötigter RAM, also rund 69.8% des RAMs des ATMega1284, und ich könnte es um weitere 3KB reduzieren, wenn ich auf den Cache zum zwischenspeichern und defragmentieren von IP-Packeten verzichten würde. Vom flash würden etwa 29648 bytes, also 22.6% von dem was auf dem ATMega1284 verfügbar ist, benötigt. Wenn ich einen Treiber für einen PHY schreiben muss, werde ich vermutlich noch 1,5K für eine Inputframes benötigen, die 2te Output-frame kann ich vermutlich vermeiden. Vermutlich könnte ich an weiteren Stellen auch noch etwas einsparen, aber 13KB RAM für das ganze erscheint mir vorerst noch in Ordnung, dann hätte ich noch 3KB übrig für den Stack und einen weiteren Buffer für sonstiges. Ich verwende nirgends malloc, also muss ich mir um den dynamischen Speicher keine sorgen machen, höchstens der Stack, der könnte noch relativ gross werden. Ich habe nicht vor RTOS zu verwenden, die Applikation ist ohnehin nicht thread-safe. Notfalls kann ich ja immer noch einen grösseren Controller nehmen, dann müsste ich eben die Architektur wechseln. holger schrieb: > Ein AVR-NET-IO. Den ATMega32 gleich rausschmeissen und einen > ATMega1284 einsetzen. Dann noch die diversen Verbesserungen für > das NET-IO durchführen. Zum Testen ist das sicher ein guter Anfang. Ich muss mir das morgen noch einmal anschauen.
:
Bearbeitet durch User
Daniel A. schrieb: > atmega1284 Kompiliere noch auf rund 11441 bytes > benötigter RAM, also rund 69.8% des RAMs des ATMega1284, und ich könnte > es um weitere 3KB reduzieren Das ist für eine Neuentwicklung ein völlig falscher Ansatz. Wenn man schon BEVOR man eine Hardware hat weiß dass man an allen ecken und Enden sparen muss, und man noch sehr viel mehr dazu programmieren möchte, dann ist das schon im Vorfeld klar dass dieser µC die völlig falsche Auswahl ist. holger schrieb: > Mit einem Cortex-M4 würdest du aber sicher glücklicher werden;) > Gibt da nette Nucleo Boards mit Ethernet. Ich rate Dir ebenfalls dazu so wie holger, ein Cortex-M4, z.B. STM32F4xx, die haben bis zu 2MB Flash und 256KB RAM, da kannst Du genügend Buffer haben und auch alle Debug-Ausgaben nutzen, denn die sind ungemein wichtig bei Entwicklung.
Daniel A. schrieb: > Aufbauen würde ich das ganze am liebsten auf einer Lochraster Platine, Chip1768: https://elmicro.com/de/chip1768.html
Was ist denn das Ziel und Zweck des Ganzen? Soll es extrem stromsparend mit dem minimalsten Speicherverbrauch und der minimalsten Hardware laufen? Soll es eine Art IOT-Anwendung werden? Soll es auf vielen Prozessorarchitekturen laufen? Was sollen die Applikationen machen? Davon hängt die Controller-Empfehlung maßgeblich ab. Mit den AVRs würde ich heute eher nicht mehr anfangen, solange es keine speziellen Gründe dafür gibt.
Ich habe mich jetzt vorerst für den AVR-NET-IO und einen ATMega1284 entschieden. Mir gefällt daran, dass der ENC28J60 und der ATMega1284 in einem DIP-Gehäuse verfügbar sind. Der Chip1768 sieht auch spannend aus, eventuell besorge ich mir mal einen davon wenn eines meiner zukünftigen Projekte etwas grösser werden sollte. Markus schrieb: > Was ist denn das Ziel und Zweck des Ganzen? Es geht in erster Linie darum, dass ich meinen eigenen Netzwerk Stack auf einem uC Testen kann. > Soll es extrem stromsparend mit dem minimalsten Speicherverbrauch und > der minimalsten Hardware laufen? Ob es stromsparend ist ist mir nicht so wichtig. Am Anfang der Entwicklung, vor etwa 2 Jahren, war das Ziel einmal einen zuverlässigen Netzwerk Stack zu erstellen, der mit mehreren TCP Verbindungen gleichzeitig umgehen kann, aber trotzdem noch auf einen kleinen AVR passt. Es ist zwar etwas grösser geworden, aber auf einen atmega1284 müsste es ja immernoch passen. > Soll es eine Art IOT-Anwendung werden? Gibt es überhaupt uC-Projekte mit Netzwerkanbindung, die keine IOT-Anwendung sind? > Soll es auf vielen Prozessorarchitekturen laufen? Dass kann es theoretisch ja schon, ich konnte es aber erst auf einer Testen.
Daniel A. schrieb: > mit den Log-Meldungen > passt es nicht einmal in einen ATMega1284. Wieso belegen deine Log-Meldungen RAM? Verwendest du evtl. const ohne __flash, so dass konstante Strings unnötig im Flash und im RAM angelegt werden?
Andreas K. schrieb: > Verwendest du evtl. const ohne __flash, so dass konstante Strings > unnötig im Flash und im RAM angelegt werden? Ja, ich habe das heute behoben, und die Log-Meldungen wieder eingeschaltet. Dabei wurden sogar weitere 1246 Bytes RAM frei.
Hi Daniel, dein Projekt sieht interessant aus, und die Codekompaktheit klingt vielversprechend. Hätte einige Anwendungen dafür, die v.a. in Richtung industrieller Messdatenerfassung gehen. Kann dein Stack mit verketteten DMA-Buffern umgehen, hast du da schon Performance-Abschätzungen gemacht? Da macht nämlich lwip ne sehr schwache Nummer. Leider sind die C11-Konstrukte für meine Zielarchitektur etwas problematisch, da der GCC älter ist, und ein Update keine Option ist. Würdest du allenfalls eine ISO-C-Kompatibilität (dort wo's geht) in der Weiterentwicklung in Betracht ziehen?
Markus M. schrieb: > Das ist für eine Neuentwicklung ein völlig falscher Ansatz. Wenn man > schon BEVOR man eine Hardware hat weiß dass man an allen ecken und Enden > sparen muss, und man noch sehr viel mehr dazu programmieren möchte, dann > ist das schon im Vorfeld klar dass dieser µC die völlig falsche Auswahl > ist. Ich finde den Ansatz als Herausforderung nicht schlecht. So manch anderer Stack ist wegen seiner Resourcenverschwendung unbrauchbar. Hochskalieren kann man die CPUs schnell, nur den Code später in kompakter Variante noch mal faktisch neuschreiben zu müssen, bringt mehr Aufwand. Es gibt Leute, die lassen TCP stacks auf msp430 laufen...
Martin S. schrieb: > Kann dein Stack mit verketteten > DMA-Buffern umgehen, hast du da schon Performance-Abschätzungen gemacht? Das kommt darauf an, wofür man die DMA-Buffer verwenden will. Beim Senden der Daten kommt meine Stream-API zum Einsatz[1]. Diese nutzt 2 Ring-Buffer, der erste beinhaltet Einträge mit der Information woher die Daten kommen, wie viele Bytes an Daten vorhanden sind, wieviele Bytes bereits gelesen wurden, und ein void Pointer, der je nach Datenquelle für verschiedene Sachen verwendet wird. Im Moment kann man damit kleinere mengen an temporären Daten in den 2ten Ringbuffer Kopieren, auf ein Array im RAM, oder auf ein Array im Flash verweisen. Ich könnte beliebige Datenquellen hinzufügen. Man kann dann über die DPA_stream_read Funktion eine Beliebige Menge an Bytes, die über beliebige Datenquellen verteilt sind, in einen Puffer kopieren. Es gibt jedoch eine kleine Limitation: Die Daten müssen, wenn diese über TCP Gesendet werden, mehrfach unverändert ausgelesen werden können, nämlich zur Berechnung der TCP-Checksumme, dem Kopieren der Daten in den Puffer für die Ethernet-frame, und bei späterem erneutem Senden von Daten, dessen Empfang noch nicht bestätigt wurde. Besonders Performant ist das ganze aber vermutlich nicht. > Leider sind die C11-Konstrukte für meine Zielarchitektur etwas > problematisch, da der GCC älter ist, und ein Update keine Option ist. Ich könnte es auf C99 Portieren, das Hauptproblem sind jedoch die anonymen unions, die an vielen stellen verwendet werden. Der gcc kann den Code jedoch mit c99 oder gnu99 kompilieren, solange man die -pedantic Option nicht verwendet. 1) https://github.com/Daniel-Abrecht/DPA-UCS/blob/master/src/headers/DPA/utils/stream.h
Versende über deinen Stack einfach MQTT Daten :) . Allerdings muss man sich vor Augen führen das ein AVR nie in der Lage ist alle Pakete abzuhandeln. Ich hoffe nur das du die PHY die MAC Adressen filtern lässt sonst wird dein AVR sofort in die Knie gehen ... Außerdem muss dieser ja die PHY auch noch steuern und die Daten je nach Interface 4bit/8bit verarbeiten. ENC28J60 ist ja so gesehen kein Stack der interagierte nur mit einen AVR. Die ganzen Dienste ARP,PING usw. müssen vom AVR initiiert werden. Beim W5500 ist dies schon anders um den eigentlich IP Stack muss man sich nicht mehr kümmern. für AVRs etc. funktioniert der Chip gut. Die ganze Arbeit taugt nur um Ethernet zu verstehen mehr aber auch nicht. und gewöhne dich gleich daran den Code zu kommentieren ! Bei dem Umfang den das Projekt jetzt schon hat sieht kein Schwein mehr durch außer du.
:
Bearbeitet durch User
Marco H. schrieb: > > Die ganze Arbeit taugt nur um Ethernet zu verstehen mehr aber auch > nicht. > Das hat man bei lwip auch gesagt, und nu nutzt es jeder Hampel, obwohl lwip ne miese Architektur hat. > und gewöhne dich gleich daran den Code zu kommentieren ! Bei dem Umfang > den das Projekt jetzt schon hat sieht kein Schwein mehr durch außer du. Der Code ist doch genug kommentiert. Mehr wäre kontraproduktiv. Nur die Lesbarkeit und Konsistenz ist noch nicht so optimal, ich empfehle da jeweils den Linux Coding Style. Merke einfach: 'if ist keine Funktion', deswegen: if (cond), aber f(x).
Daniel A. schrieb: > Gibt es überhaupt uC-Projekte mit Netzwerkanbindung, die keine > IOT-Anwendung sind? Ja, alle Projekte, bevor das Buzz-unwort-des-Jahres IOT erfunden wurde :)
Ich habe jetzt fürs erste alles zusammen was ich brauche: ein AVR-NET-IO Board, einen USB-Serial Converter, einen USBasp, einen AVR-ISP-Stick von eHaJo, ISP Kabel, ein 6 zu 6 Pin und ein 10 zu 10 Pin ISP Kabel, und einige andere Kleinteile. Ich habe die Hardware aller Geräte bereits überprüft, diese funktioniert einwandfrei. Die Firmware des USBasp ist aber etwas veraltet, sobald das 6pin zu 10pin ISP Kabel da ist werde ich diesen updaten. Ich habe den AVR-ISP-Stick von eHaJo und ein Breadbord verwendet, um die Fuses des atmega1284p für das AVR-NET-IO Board passend einzustellen. Der AVR-ISP-Stick von eHaJo hat jedoch nicht die richtige Produkt und Vendor ID damit avrdude ihn als usbtiny erkennt, und im Internet habe ich nur Beiträge von Usern gefunden, die nicht wussten, wie Sie diesen unter Linux mit avrdude verwenden können, aber nicht wie man das Problem löst, falls jemand später das selbe Problem haben sollte, einfach folgendes zu /etc/avrdude.conf hinzufügen:
1 | |
2 | programmer |
3 | id = "ehajo-isp"; |
4 | desc = "eHaJo AVR-ISP-Stick"; |
5 | type = "usbtiny"; |
6 | connection_type = usb; |
7 | usbvid = 0x16d0; |
8 | usbpid = 0x0ba5; |
9 | ; |
Eventuell müssen usbvid und usbpid angepasst werden, je nachdem was lsusb dafür ausgibt. Danach kann man bei avrdude ehajo-isp statt usbtiny als Programmer an avrdude übergeben. Ich habe meinen Netzwerk-Stack mal zum testen mit dem USBasp und dem AVR-NET-IO auf den atmega1284p hochgeladen, ich konnte bereits die Log-Meldungen über uart ausgeben lassen, und mit minicom und meinem USB-Serial Adapter auf dem PC ausgeben lassen. Ich habe noch keinen Treiber für den ENC28J60 geschrieben, zuerst muss ich ein anderes Problem lösen. Bei meinem Programm gibt es diverse Interfaces, welche durch Strukturen mit Funktionspointen repräsentiert werden, und diverse Module welche diese Interfaces implementieren, indem diese eine Instanz der Struktur erstellen. Ich habe ein Macros, um eine solche Instanz je nach Interface in eine Section zu Packen, und eins um durch alle Elemente in der Section zu Iterieren. Dadurch kann ich z.B. Treiber für Netzwerkinterfaces hinzufügen, ohne Änderungen am Code machen zu müssen, indem ich den Treiber zum Programm dazulinke oder auch nicht. Ich wusste der Hack würde sich irgendwann rächen, denn auf dem AVR bekomme ich nicht das erhoffte verhalten. Ich muss nun die Macros anpassen und statt dem __attribute__((section)) das __attribute__((constructor)) verwenden, und statt Arrays Linked Lists verwenden, diese Änderungen werden eine weile dauern.
Ich habe nun einen Treiber für den ENC28J60 für meinem TCP/IP Stack erstellt, und es funktioniert bereits erstaunlich gut. Am längsten dauert das Ausgeben der Log-Meldungen, mit den Log-Meldungen dauert das Senden einer 186 Byte grossen Datei ungefähr 2 Sekunden, ohne die Log-Meldungen sind es nur durchschnittlich 17ms. Ein ping (ohne logs) dauert ungefähr 2ms, und selbst ein ping -f ist kein Problem. Die Benchmarks sind im Anhang zu finden. Hier noch 2 Videos, wo ich damit eine LED ein und ausschalte: https://dpa.li/dpaucs/demo-no-logs.mp4 https://dpa.li/dpaucs/with-logs-slow.mp4 Mein TCP/IP Stack ist aber noch lange nicht fertig, es gibt noch vieles, dass ich noch nicht implementiert habe, und es gibt auch noch ein paar Bugs, es kann z.B. passieren, dass nachdem man beim Abrufen einer nicht existierenden Seite über http andere existierende Seiten versucht abzurufen, man manchmal stattdessen die 404 Fehlerseite bekommt. Und mit der Dokumentation habe ich noch nicht einmal angefangen...
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.