Hallo Leuts, ich habe gerade mein LPC2478 Experimentierboard fertiggestellt und bastle jetzt ein bisschen Software. Im Moment befasse ich mich mit dem Ethernet-MAC, welche ich mittlerweile auch zum Laufen gebracht habe. Ich kann erfolgreich Pakete senden und empfangen, es funktioniert bestens! Die ganze Geschichte initialisiert sich von selber via einen Interrupt, sobald ein LAN-Kabel eingesteckt wird und Geschwindigkeit sowie Duplex und das ganze Gerümpel wird erkannt und der MAC dementsprechend konfiguriert. Soweit so gut. Nun brauche ich ja, um sinnvolle Daten zu senden und zu empfangen, einen IP-Stack. Zwar wäre es wohl möglich, den von Grund auf selber zu bauen, aber mir erscheint dies reichlich fehleranfällig und schwierig. Also nimmt man am besten wohl was fertiges. Könnt ihr eine bestimmte Software empfehlen? von lwIP liest man immer wieder, aber es gibt ja auch noch diverse andere Stacks. Welcher ist am einfachsten an die Zielhardware anzupassen? Was das Teil auf jeden Fall können sollte: - DHCP - (S)NTP - UDP - IPv4 - evtl. TCP. Der Rest ist nice to have, aber im Moment nicht notwendig. Hat wer Tipps?
Ein Problem ist mir noch gerade aufgefallen: Mein Compiler (ich verwende eine Testversion von IAR EWARM) scheint mir manchmal meine Variablen zu zerschiessen. Mein Testprogramm macht folgendes: in einer Endlosschleife wird ein Paket gesendet, welches neben der Ziel- und der Quell-MAC-Adresse nur den Text "Hallo Welt, diese Nachricht wurde vom LPC2478 gesendet" enthält. In Wireshark wird zu ca. 60% der richtige Text empfangen. In allen anderen Fällen lautet der empfangene Text "Hallo Welt, diese N.cropw urde vom LPC2478 gesendet". Wo der Fehler wohl liegt? Ich konnte es auch nach mehrstündigem Debugging nicht herausfinden. Der Stack läuft nie über, auch irgendwelche spurious Interrupts kann ich ausschliessen. Ich habe dann einen Daten-Breakpoint auf meine Variable, welche diesen Test-Text enthält, gesetzt. Und siehe da: mein eigener Programmcode, vom Compiler übersetzt, scheint diesen Text manuell zu verändern! Dabei besteht der Code nur aus zwei Stellen, wo diese Variable verwendet wird: 1. Definition: char test[] = "Hallo Welt, diese Nachricht wurde vom LPC2478 gesendet" 2. Zugriff fSendPacket(test, sizeof(test)), wobei die Funktion fSendPacket folgendes macht: while(packet_size) { *dest_buffer = *src_buffer; dest_buffer++; src_buffer++; packet_size--; } es wird auf die Quelle (in dem Fall die Variable test) nur lesend zugegriffen, und die Variable wird an KEINER EINZIGEN anderen Stelle im Code erwähnt. Aber WARUM ändert sie sich, und WARUM kommt mein Text falsch an? Solange ich den Debugger im Einzelschrittmode laufen lasse, funktioniert alles wie gewünscht. Sobald ich aber auf "Run" klicke, schlägt sofort mein Daten-Breakpoint zu, und die Variable verändert sich scheinbar willkürlich. Kann mir wer weiterhelfen?
Hat keiner was zu sagen? Ich habe mir mal lwIP runtergeladen und versuche grade, den compiliert zu bekommen. Ich bin mir aber überhaupt nicht sicher, welche files ich alle brauche. Was ist die absolute Minimalkonfiguration? Und eine Doku vermisse ich auch beim lwIP. Grundsätzlich möchte ich einen Stack, der alle wichtigen, gängigen Protokolle beherrscht. Notfalls implementiere ich sowas halt selber, aber im Moment fehlt mir ein kluger Ansatz.
Ich habe lwIP erfolgreich mit einem AT32UC3B zum laufen bekommen. lwIP ist sehr vielseitig, und funktioniert bei mir bestens. Man sollte allerdings so ca. 15 - 20 kB SRAM entbehren können. Das ist aber auch von der Datenrate abhängig. Gut möglich, dass man bei Datenraten im RS232-Bereich auch mit wesentlich weniger hinkommt.
Ich vergaß zu erwähnen, dass dabei der Netzwerkzugang via WLAN aufgebaut wurde. Als Chipsatz diente hier der HDG104 von H&D Wireless.
Tobias Plüss schrieb: > wobei die Funktion fSendPacket folgendes macht: > > while(packet_size) > { > *dest_buffer = *src_buffer; Wie groß ist der Buffer, den Du mittels dest_buffer füllst? > es wird auf die Quelle (in dem Fall die Variable test) nur lesend > zugegriffen, und die Variable wird an KEINER EINZIGEN anderen Stelle im > Code erwähnt. Aber WARUM ändert sie sich, und WARUM kommt mein Text > falsch an? Ist die Definition von char test[] global oder lokal? Durch Überschreiten von Buffergrenzen können sich Inhalte von Strings durchaus ändern, das liegt daran, wie die Variablen im RAM (globale Variable) oder auf dem Stack (lokale Variable) hintereinanderliegen. Es muss auch nicht an der Funktion fSendPacket() selbst liegen, das Überschreiben kann an ganz anderer Stelle im Code vorkommen. Merkwürdig ist allerdings, dass die Änderung mitten im String stattfindet. Normalerweise wird sie durch eine Bufferüberschreitung eher von vorn "aufgerollt". Noch merkwürdiger ist, dass sich die Nachricht durch diese Änderung verkürzt! Das Fragment "achricht " (9-Zeichen) wurde durch ".crop" (5 Zeichen) ersetzt, ist das wirklich korrekt? Schau Dir besser einen Hexdump an - auch im Wireshark. Wahrscheinlich sind da noch 4 nicht-druckbare Zeichen "versteckt". Ein kompletter Code wäre da hilfreicher als ein Code-Schnippsel. Ich bin mir ziemlich sicher dass die Ursache des Problems nicht in den gezeigten Codezeilen zu finden ist. Checke bitte auch sämtliche Buffergrößen auf Überschreiten ab.
Hallo, ich bin jetzt dabei, selber einmal eine kleine Implementation eines Stacks zu beginnen. Die Ethernet-Frames werden jetzt schon mal empfangen und in einem Empfangsbuffer abgelegt. Danach wird ermittelt, um welches Protokoll es sich handelt (IP, ARP usw.). Und anschliessend wird die jeweilige Funktion aufgerufen, welche das Paket weiter verarbeitet. Es funktioniert schon mal so halbwegs, aber ich habe immer noch das Problem, dass mir manchmal gewisse Variablen-Inhalte zerschossen werden, und ich weiss nicht wieso. Da die Übertragung der Daten vom Phy zum LPC2468 via DMA läuft, habe ich so langsam das Gefühl, dass da was nicht richtig läuft. Ich habe jetzt ein neues Testprojekt angelegt. Ich habe die Interrupts zwar eingeschaltet, da sie benötigt werden fürs Ethernet. Aber ich habe ausser meines MAC-Moduls keine weiteren Interruptfunktionen am Laufen. Des weiteren ist die Stack-Grösse auf 0x8000 Bytes festgelegt, was _reichlich_ langen sollte. Trotzdem werden manchmal Variablen überschrieben. Was auch interessant ist: Ich habe ein Testprogramm gebastelt, das in einer Endlosschleife auf den Empfang eines neuen Pakets wartet. Kommt dieses an, dann wird der Pakettyp geprüft. Ist es ein UDP-Paket, schalte ich eine rote LED ein, ist es ein ICMP-Paket wird die grüne LED eingeschaltet, und bei einem TCP-Paket werden alle LEDs wieder ausgeschaltet. Nun lasse ich auf meinem Notebook ein Programm zum generieren von Paketen laufen (Colasoft PacketBuilder). Das generiert mir in einer Endlosschleife diese 3 Pakete und versendet sie an mein Board. Dann sehe ich die LEDs schön blinken, es scheint also zu funktionieren. ABER! nach einigen tausend Paketen resettet sich das Board einfach und der LPC2468 hängt im prefetch_abort oder data_abort fest.
Anbei findet ihr noch meinen Code zur Initialisierung des MAC. Ich hoffe, wenns einen Fehler hat, steckt der da drin. Ich sehe wohl mittlerweile den Wald vor lauter Bäumen nicht mehr...
Hallo, so ich habe nun mal den MAC usw. zum Laufen bekommen. Ein Register war nicht richtig gesetzt, deshalb hat der Datentransfer manchmal funktioniert und manchmal nicht. Ich habe mich jetzt mal daran gemacht, selber ein bisschen mit den Ethernet-Paketen rumzuexperimentieren. Ich habe im main folgenden Code:
1 | char buffer[1500]; |
2 | |
3 | while(1) |
4 | {
|
5 | process_packets(); |
6 | }
|
7 | |
8 | void process_packets(void) |
9 | {
|
10 | int size = MAC_fReceivePacket(buffer); |
11 | struct ethernetheader *header; |
12 | if(size) |
13 | {
|
14 | header = (struct ethernetheader*)buffer; |
15 | switch(header->type) |
16 | {
|
17 | case TYPE_IP: |
18 | process_ip_packet(buffer, size); |
19 | case TYPE_ARP: |
20 | process_arp_packet(buffer, size); |
21 | }
|
22 | }
|
23 | }
|
das funktioniert auch ganz ordentlich, ich habe bereits mal ARP vollständig implementiert inclusive eines ARP-Cache. ICMP ist auch implementiert. Ich kann nun bereits ARP Requests an mein Board senden, und die werden dann auch korrekt beantwortet. Wenn ich es anpinge, kommt auch eine Antwort zurück. Soweit schon mal gut. Es funktioniert also Problemlos, Pakete zu beantworten. Jetzt möchte ich aber gern DHCP implementieren. Dazu muss ich ja erst die DHCPDISCOVER-Nachricht verschicken und dann auf eine Antwort warten - wenn möglich mit einem Timeout. Doch wie kann ich das hier realisieren? Wie ihr seht, werden die Pakete nur im Mainloop abgearbeitet, nachdem der MAC gepollt wurde, ob überhaupt Pakete vorhanden sind. Wenn ich jetzt aber eine DHCPO-funktion schreiben möchte, die auf die Antwort vom Router wartet - wie gehe ich das am besten an? Die Funktion muss ja irgendwo her wissen, ob der MAC Daten erhalten hat. Und das kann sie nur wissen, wenn vorher die Funktion process_packets aufgerufen worden ist, welche die Pakete der Reihe nach durch die Stacks durch reicht. Wie macht man das richtig? Es würde sicherlich funktionieren, die Abarbeitung der Pakete in einem Interrupt zu machen, aber das gefällt mir ganz und gar nicht, denn die Bearbeitungszeit dieser Pakete ist undefiniert und dauert möglicherweise zu lange. Irgendwie stehe ich grade auf dem Schlauch. Kann mir wer weiterhelfen?
es gibt auch noch den uIP-Stack. Ist bekannter als lwIP. Es gibt auch noch einen Stack von Microchip. Den kann ich sehr empfehlen, da er sehr gut dokumentiert und sauber geschrieben ist, und weil du deinen Stack ja jetzt selber schreibst, und eine gute Vorlage wäre von Vorteil. Wenn du hier im Forum das Stichwort "Webserver" eingibst, wirst du auf eine Menge anderer nützlicher Projekte stoßen.
Tobias Plüss schrieb: > Wenn ich jetzt aber eine > DHCPO-funktion schreiben möchte, die auf die Antwort vom Router wartet - > wie gehe ich das am besten an? Die Funktion muss ja irgendwo her wissen, > ob der MAC Daten erhalten hat. ??Warum?? - trenne die Anforderung und die Auswertung aus Main sendest du den DHCPDISCOVER, dann beendet sich diese Funktion. Die Antwort wertest du mit dem Stack aus, der dann die benötigten Daten aus dem Packet zieht. Wenn du in der Main wissen willst ob es funktioniert hat setze ein Flag, für einen Timeout nimm einen Timer oder einen per Timer gesteuerten Counter. Sascha
Sascha, ja das war jetzt ein einfaches Beispiel. In der Tat könnte man das Problem so lösen. Anders gestaltet es sich aber, wenn ich z.B. von meinem Board aus einem Rechner ein IP-Paket schicken möchte, von dem ich im Moment nur die IP-Adrese kenne. Ich weiss, dass der Zielrechner die IP 192.168.1.13 hat. Um ein Ethernet-Paket zu generieren, muss ich aber erst die MAC-Adresse rausfinden - sprich, ich muss erst einen ARP-Request senden, auf die ARP-Antwort mit einem Timeout warten, und erst dann kann ich fortfahren, das IP-Paket zu erstellen und zu senden.
ist auch kein Problem, hier mal ein Lösungsansatz: nehmen wir mal an ... von MAIN wird jede Sekunde eine Funktion data_send aufgerufen __________ zum Zeitpunkt X willst du eine Verbindung zu einem externen Rechner aufbauen also speicherst du IP_Adresse, Port usw. in entsprechenden Variablen. Dann wird sendstatus=1 __________ data_send: ? sendstatus=0 wenn JA =>return ;nix zu tun ? sendstatus<10 wenn JA ? schauen ob zur IP-Addr schon eine MAC im APR-Cache liegt wenn JA => sendstatus=11 wenn NEIN ? sendstatus=1 wenn JA => ARP-Request senden sendstatus++ ? sendstatus=10 wenn JA => sendstatus=0 ;ARP-Timeout ? sendstatus<20 wenn JA ? TCP-Verbindung schon aufgebaut (im Stack Eintrag suchen) wenn JA => sendstatus=21 wenn NEIN ? sendstatus=11 wenn JA => TCP-Verbindungsaufbau anstossen sendstatus++ ? sendstatus=20 wenn JA => sendstatus=0 ;TCP-Timeout, Verbindung nicht aufgebaut usw. Sascha
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.