Ich habe einen LPC2368 mit einem Micrel PHY KSZ8721BLI und würde das
gerne mit uIP betreiben.
Ich habe hier noch ein paar Verständnissprobleme bezüglich der
Kommunikation untereinander.
Also, es gibt den Netzwerkstecker, den stecke ich ein, dann ist der PHY
mit Netzwerk verbunden.
Zuvor habe ich den PHY initialisiert.
Jetzt ist mir nicht ganz klar was passiert, bzw. passieren soll.
Im PHY ISR Register sehe ich, dass ein Datenpaket angekommen ist, aber
der LPC registriert das irgendwie nicht und die Daten werden auch nicht
über das RMII Interface übertragen.
Wie sage ich dem Netzwerk dass mein Controller die IP Adresse
192.168.1.10 haben soll, bzw wenn ich vom PC aus dort hin ein Datenpaket
schicke, dass mein PHY es empfängt und meiner CPU überträgt?
Kann mir bitte jemad die Augen öffnen wie das gehen soll?
Das geht doch sicher in wenigen Sätzen, ohne dass ich gleich die
Paketstruktur von TCP/IP & Co kennen muss.
Ich bin neuling auf dem Ethernet gebiet und es ist auch möglich dass in
meinen Quellen noch ein Fehler drin ist. Ich habe die emac.c vom Code
Bundle aus www.standardics.nxp.com geladen.
Dein MAC (im LPC2368) hat ne MAC Adresse (ich bin mir nich sicher, ob da
schon fest eine vorgegeben ist oder ob du die selber einprogrammieren
musst). Um dann eine Zuordnung von MAC- zu IP-Adressen vorzunehmen, muss
du das ARP (Address Resolution Protocol) implementieren, siehe
Wikipedia.
Wenn z.B. dein PC an die IP 192.168.1.1 ein Paket senden will, dann
generiert er erst mal ein ARP-Paket, das er an den Router versendet. Der
Router löst dann die IP auf und gibt deinem PC die MAC-Adresse zurück.
Dein PC generiert erst dann das eigentliche Datenpaket, wo er dann die
MAC-Adresse reinpackt, die der Router ihm verraten hat.
Damit kannst du aber noch nicht so viel anfangen; Damit du wirklich mit
deinem Controller kommunizieren kannst musst du noch ICMP (ping)
implementieren (z.B.) oder TCP/IP oder UDP. Sonst lässt sich nicht viel
sinnvolles damit anfangen...
ich wrote:
> Das geht doch sicher in wenigen Sätzen, ohne dass ich gleich die> Paketstruktur von TCP/IP & Co kennen muss.
Ganz ehrlich? Nein geht es nicht. Nicht mit uIP/lwIP. Auf einem PC mit
genügend Abstraktion zwischen den Netzwerksachen und der tatsächlichen
Programmierung geht es vielleicht noch. Aber hier hast du keine Chance.
Lies dir ein paar Grundlagen zu TCP/IP, Ethernet und ARP an, versuche zu
verstehen wie die Kommunikation von statten gehen und welche Protokolle
für genau welchen Zweck zuständig sind.
Alles andere kann sehr schnell in Frust und Frickelei ausarten ;)
Also, muss mein LPC2368 erst mal ein Paket generieren, das dem Switch
sagt:
Hallo, ich habe Macadresse x.x.x.x.x.x und die IP x.x.x.x
Und das als ARP Paket verpackt?
Also dem Switch mitteilen dass an diesem Port mein LPC hängt?
ich wrote:
> Also, muss mein LPC2368 erst mal ein Paket generieren, das dem Switch> sagt:>> Hallo, ich habe Macadresse x.x.x.x.x.x und die IP x.x.x.x>> Und das als ARP Paket verpackt?> Also dem Switch mitteilen dass an diesem Port mein LPC hängt?
Nein, das macht uIP/lwIP.
@Simon:
Also aus dem FreeRTOS Demo, da ist es ganz einfach:
uIP_Init()
uIP_SetAddr(...)
httpd_init()
EMAC_Init()
Und dann in einer Schleife die Daten abholen und schicken.
Das Senden und Empfangen mit der HW ist in der emac.c drin.
Das sieht doch enorm einfach aus?
Natürlich muss mann sich erst richtig einarbeiten, wenn man jedes Bytes
eines TCP/IP Stackst und den anderen wissen möchte, mich interessiert
aber nur das Ergebnis. Ähnlich wie bei USB, die ganze Header bits macht
halt hier die Hardware, so dachte ich mir, das macht bei TCP/IP uIP.
@Simon, die Texte überschneiden sich...
Dann fehlt mir der Teil, wo dieser automatismus von uIP auch auf den
EMAC/LPC überträgt? Also Irgend eine Routine wird noch von uIP
aufgerufen, die ich noch nicht programmiert habe?
ich wrote:
> @Simon, die Texte überschneiden sich...>> Dann fehlt mir der Teil, wo dieser automatismus von uIP auch auf den> EMAC/LPC überträgt? Also Irgend eine Routine wird noch von uIP> aufgerufen, die ich noch nicht programmiert habe?
Beim uIP/lwIP sind auch Beispiele, sowie Dokumentationen dabei. Du musst
dich nur um das Empfangen und das Senden der Pakete kümmern. Diese
liegen dabei immer in einem globalen Puffer (im Falle von uIP).
ich wrote:
> @Simon:> Also aus dem FreeRTOS Demo, da ist es ganz einfach:> uIP_Init()> uIP_SetAddr(...)> httpd_init()>> EMAC_Init()>> Und dann in einer Schleife die Daten abholen und schicken.> Das Senden und Empfangen mit der HW ist in der emac.c drin.>> Das sieht doch enorm einfach aus?
Okay, ich kenne mich mit den Mikroprozessoren von NXP nicht aus. Scheint
als gäbe es da schon vorhandenen Quellcode.
> Natürlich muss mann sich erst richtig einarbeiten, wenn man jedes Bytes> eines TCP/IP Stackst und den anderen wissen möchte, mich interessiert> aber nur das Ergebnis. Ähnlich wie bei USB, die ganze Header bits macht> halt hier die Hardware, so dachte ich mir, das macht bei TCP/IP uIP.
Ja, die Headersachen macht prinzipiell jemand anders für dich (uIP).
Aber wenn du auch selber Applikationen für den Stack schreiben möchtest
(und nicht nur den mitgelieferten HTTP-Dienst benutzen willst, fängt die
Sache schon gut an ;)).
Bei uIP müsste er doch alle Nase lang die Funktion "UIP_APPCALL()"
aufrufen, oder nicht?
bzw. wenn uip_periodic() aufgerugen wird, dann sollte auch eine uip_len
mit einer Zahl zurück kommen, die die Anzahl der zu sendenden Bytes
zurück gibt?
ich wrote:
> Bei uIP müsste er doch alle Nase lang die Funktion "UIP_APPCALL()"> aufrufen, oder nicht?
Nein, diese Funktion darf nur der Stack aufrufen.
> bzw. wenn uip_periodic() aufgerugen wird, dann sollte auch eine uip_len> mit einer Zahl zurück kommen, die die Anzahl der zu sendenden Bytes> zurück gibt?
Je nachdem, ob neue Daten gesendet werden müssen oder nicht.
Ich habe mich falsch ausgedrücht, sorry:
> Nein, diese Funktion darf nur der Stack aufrufen.
Ich meinte, der Stack müsste diese funktion alle Nase lang aufrufen...
Also mal ganz von vorne...
- Die Initialisierung:
1
EMACInit();
2
EMAC_RxEnable();
3
EMAC_TxEnable();
4
uip_init();// Initialisierung
5
uip_setethaddr(xAddr);// MAC-Adresse
6
uip_sethostaddr(ipaddr);// 192.168.1.10
7
uip_arp_init();
8
uip_listen(HTONS(80));
- Die Endlosschleife:
1
uip_len=EMACReceive((void*)uip_buf);
2
if(uip_len>0)
3
{
4
uip_input();
5
uip_arp_ipin();
6
if(uip_len>0)
7
{
8
uip_arp_out();
9
EMACSend((void*)uip_buf,uip_len);
10
}
11
}else{
12
// Zyklischer Aufruf
13
if(TimerPuls1Sekunde)
14
{
15
for(i=0;i<UIP_CONNS;i++)
16
{
17
uip_periodic(i);
18
if(uip_len>0)
19
{
20
uip_arp_out();
21
EMACSend((void*)uip_buf,uip_len);
22
}
23
}
24
}
25
}
Hier fehlt doch noch was, also ich meine die Initialisierung müsste doch
ein Paket generieren, das ich schicken müsste?
Das ganze ist wie ein Puzzle...
Im Anhang ist meine uIP_Task.c wo alles nochmal genauer drin steht, hier
nur der Auszug (kurzform). Der Task wird bei mir bei jedem Main-Loop
aufgerufen.
ich wrote:
> Ich habe mich falsch ausgedrücht, sorry:>> Nein, diese Funktion darf nur der Stack aufrufen.> Ich meinte, der Stack müsste diese funktion alle Nase lang aufrufen...
Der Stack ruft die Funktion auch periodisch auf, das ist richtig.
> Hier fehlt doch noch was, also ich meine die Initialisierung müsste doch> ein Paket generieren, das ich schicken müsste?> Das ganze ist wie ein Puzzle...
Nein die Initialisierung muss kein Paket generieren. Wenn du den kleinen
einmal ans Netz hängst, wird erst mal niemand wissen, dass er da ist.
Sobald jemand eine ARP-Anfrage (mit der Ziel-IP des Mikrocontrollers)
ins Netz stellt, muss dieser aber antworten.
> Im Anhang ist meine uIP_Task.c wo alles nochmal genauer drin steht, hier> nur der Auszug (kurzform). Der Task wird bei mir bei jedem Main-Loop> aufgerufen.
So wie es in dem Sourcecode ist, wird deine Applikation ständig
aufgerufen, das ist richtig. Du hast nämlich die Zeitbasis im Moment
nicht im Code eingebaut. Normalerweise reicht es wenn uip_periodic (und
somit die Applikation für jede Verbindung) alle 100ms aufgerufen wird.
uip_periodic() wird jede Sekunde aufgerufen, ich habe hier eine Ausgabe
auf den COM Port, das ist es so. In meinem Quellcode heist es im
Original "tPuls1s", diese Variable wird durch den Timer-Task für genau
einen Main-Loop Zyklus jede Sekunde gesetzt.
Wenn ich Sie richtig verstanden habe, passiert erstmal gar nichts.
Erst wenn ich z.B. über meinen IE auf 192.168.1.10 los gehe, dann sucht
der Explorer nach der Broad-Cast Methode (Port 80) ob da jemand
antwortet (dabei blinkt auch die grüne LED an meinem LPC2368-Board,
angesteuert vom PHY).
Und dann müsste das Paket doch irgendwie in mein LPC2368 gelangen, ich
habe auf der LCD Anzeige das Interrupt-Register des PHYs angezeigt, es
kommt aber nichts.
Wie sollte es denn sein?