Hallo zusammen,
ich bin gerade dabei, meinen Microcontroller für die Ansteuerung über
Lan einzurichten. Dazu habe ich mir den TCP-IP Stack uIP 1.0 von Adam
Dunkel gedownloaded und die benötigten Dateien in das Avr Studio
geladen.
Ich benutze das Avr Studio 5.0. Mein Controller ist der ATmega32 und der
Ethernetcontroller ein ENC28J60.
Da der Schwerpunkt meines Projektes auf anderen Bereichen als der
TCP-Stack Programmierung liegen sollte habe ich mich entschieden, einen
fertigen Stack zu verwenden.
Leider treten beim Compilieren des Codes viele Fehler auf und ich weiß
nicht warum.
Trotz Lesens der Dokumentation bin ich mir nicht ganz sicher, welche
Dateien zwingend erforderlich sind und wie genau der Stack an meinen
Controller angepasst werden muss.
Hat jemand schon ein ähnliches Projekt durchgeführt und kann mir sagen
worauf ich bei der Benutzung des Stacks achten muss?
>Leider treten beim Compilieren des Codes viele Fehler auf und ich weiß>nicht warum.
Und wie soll dir da jetzt jemand helfen?
Ist es so schwer die Fehlermeldungen hier zu zeigen?
> Leider treten beim Compilieren des Codes viele Fehler> auf und ich weiß nicht warum.
'viele Fehler' ist paradoxerweise meistens ein gutes Zeichen. Denn oft
ist es so, dass kleine Ursachen eine regelrechte Flut von Fehlern nach
sich ziehen. Beseitigt man die Ursache verschwinden oft viele Fehler in
einem Rutsch.
Also: Lies die erste Fehlermeldung, finde raus was die Ursache ist und
beseitige sie. Erneut compilieren und wieder die erste Fehlermeldung
analysieren.
Nicht von der Flut der Fehlermeldungen verdriessen lassen. Meistens sind
es nur ein paar wenige Ursachen, die bereinigt werden müssen.
Danke schon mal für die Antworten!!
Da der uIP Stack 0.9 weniger Dateien enthält und etwas übersichtlicher
ist habe ich diesen nun benutzt.
Ich habe einige Fehler behoben, aber leider treten immen noch Fehler
auf, bei denen ich nicht weiß, wie ich diese beheben soll. In uipopt.h
habe ich die Funktion, die bei Events aufgerufen wird wie folgt
definiert:
1
#define UIP_APPCALL example1_app();
2
3
#define UIP_APPSTATE_SIZE 0;
Appstate habe ich 0 zugewiesen, weil ich ein Speichern des Status nicht
benötige.
In uip.h wird der Fehler "Error expected ']' before ';' token 798" und
"Warning no semicolon at end of struct or union 799" bei folgenden
Zeilen angezeigt:
nimm das Semikolon da hinten weg.
Makros werden praktisch immer ohne Semikolon geschrieben. Das steht an
der Stelle an der das Makro benutzt wird. Nach der Textersetzung des
Makros ist dann alles paletti.
u8_t appstate[UIP_APPSTATE_SIZE];
Na spiel Präprozessor und mach die Textersetzung laut
#define UIP_APPSTATE_SIZE 0;
dann kommt da raus
u8_t appstate[0;];
und spätestens jetzt sollte klar sein, was das Problem ist.
Makros sind einfach nur Vorschriften, welcher Text durch welchen anderen
Text zu ersetzen ist.
Danke!
Leider treten immer noch Fehler auf. An jeder Stelle in uip.c, an der
UIP_APPCALL() aufgerufen wird, wird mir der Fehler "Error undefined
reference to `example1_app' " angezeigt. Ich habe gerde schon danach
gegoogelt aber nichts Brauchbares gefunden. Könnt ihr mir nochmal
helfen?
Das ist ein Callback Mechanismus, mit dem der TCP Stack sich bei deiner
Anwendung meldet, wenn etwas im Stack passiert. D.h. diese Funktion muss
deine Anwendung bereitstellen.
Sind denn da keine Beispiele im Package dabei, mit denen man sich das
ganze mal ansehen kann?
Ja die Funktion habe ich definiert. Sie liegt bei mir in der
main-Funktion und ist zum Testen so aufgebaut wie das Beispiel in der
Dokumentation des Stacks. Das Beispiel sieht so aus:
1
voidexample1_init(void)
2
{
3
uip_listen(HTONS(1234));
4
}
5
voidexample1_app(void){
6
if(uip_newdata()||uip_rexmit())
7
{
8
uip_send("ok\n",3);
9
}
10
}
Ich habe noch die Funktion eingebaut, dass ein Port des Controllers
gesetzt wird, um es zu kontrollieren.
Vor dieser Funktion warte ich mit dem Hardwaretreiber darauf, dass ein
Paket eingeht.
Hallo,
den Error undefined reference habe ich in den Griff bekommen. Ich hatte
die Funktion an der falschen Stelle deklariert.
Allerdings kann ich den PC immer noch nicht mit dem AVR verbinden. Meine
main-Funktion sieht zur Zeit so aus:
1
while(uip_len==0)
2
{
3
uip_len=enc28j60PacketReceive(1200,uip_buf);
4
}
5
6
example1_init();
7
8
if(uip_len>0)
9
{
10
uip_input();
11
if(uip_len>0)
12
{
13
enc28j60PacketSend(uip_len,uip_buf);
14
}
15
}
Zuerst warte ich mit der Schleife darauf, dass ein Paket eingeht. Dieses
wird in uip_buf geschrieben und die Länge in uip_len. Danach wird mit
example1_init() der Listener für eine TCP-Anfrage erstellt. Wenn dann
auch wirklich ein Paket da ist (uip_len > 0), dann wird das angekommene
Paket mit uip_input() bearbeitet. Diese Funktion sollte dann eigentlich
ein Antwort-Paket erzeugen. Falls dann also ein Antwort Paket erzeugt
wurde (uip_len > 0), soll diese Antwort mit
enc28j60PacketSend(uip_len,uip_buf) zurückgesendet werden.
Hat jemand eine Idee, was ich falsch gemacht habe oder ob ich einen
Denkfehler im Programm habe?
Hallo nochmal,
hat keiner eine Idee?
Ich bin auch generell für Vorschläge offen. Zum Beispiel wie ihr die
main-Funktion aufgebaut habt oder was ihr alles am Stack verändert habt,
falls ihr euch schon mit dem Stack uIP beschäftigt habt.
ich bastel jetz ne weile mit rum und versuch mich in das thema IP
einzuarbeiten
an sich ist vieles selbsterklärend
einzig die sache mit den protothreads sollte man vorher verstehen
das war auch mein problem warum eigene applikationen nicht gleich
funktioniert haben.
bei DHCP wird der hostname und fqdn mit übertragen
usw ...
ich hab mitlerweile ne namensauflösung mit drin
also das man xxxx.yy eintippen kann anstelle der IP
für windows geht das , linux bräuchte theoretisch samba
das funktioniert aber auch wenn der router ein vernünftiges DNS kann
meiner weigert sich leider hostnamen zu merken und mal weiterzuleiten
NTP is grad in arbeit
meine main ist derzeit leer
habe das ganze auf interruptbetrieb umgestellt
ist aber vom ablauf her das selbe wie die original main
fdssd schrieb:> ich hab mitlerweile ne namensauflösung mit drin> also das man xxxx.yy eintippen kann anstelle der IP>> für windows geht das , linux bräuchte theoretisch samba
Das glaube ich nicht. Samba ist die Nachbildung des SMB/CIFS Protokolls
(Windows Filesharing) für unixoide Systeme. Diese Protokolle verwenden
die Netbios Namensauflösung, die (früher) ohne DNS auskam. Vergibst du
netbios hostnamen mit dhcp? Kommt mir sehr komisch vor...
Ein Router kann sich bei DHCP den hostnamen merken.
Im discover steht der host und der fqdn mit drin.
Nbns funktioniert auch aber getrennt von DHCP.
Mein android Telefon über macht namensauflosung nur über DNS.
Und der Ubuntu PC auch. Erst mit Samba kommt die nbns abfrage
Da aber vom PC die dnsrequest nur im Router landen sieht der cortex
keine Port 53 requests
Hallo,
hier mal mein kompletter main-Funktions-Quelltext. Wäre nett wenn da mal
jemand drüber gucken könnte. Ich habe schon vieles ausprobiert, bin aber
nicht zu einer Lösung gekommen.
//Mac Adresse setzen(stack.h, dort wird auch die Ip festgelegt)
26
nicSetMacAddress(mymac);
27
28
/* Leds konfigurieren
29
LEDA : Link status
30
LEDB : Receive activity
31
Led Settings : enc28j60 datasheet, page 11*/
32
33
enc28j60PhyWrite(0x14,0b0000010000100000);
34
unsignedlongzaehler;
35
unsignedshortzaehlerENC;
36
37
/* uIP TCP/IP stack initialisieren. */
38
uip_init();
39
40
example1_init();
41
u8_ti,arptimer;
42
43
arptimer=0;
44
DDRC=0xFF;
45
46
uip_arp_init();
47
48
example1_init();
49
50
51
// Timer 0 konfigurieren
52
TCCR0=(1<<CS02)|(1<<CS00);// Prescaler 1024
53
54
// Overflow Interrupt erlauben
55
TIMSK=(1<<TOIE0);
56
57
// Global Interrupts aktivieren
58
sei();
59
while(1){
60
61
PORTC|=(1<<0);
62
63
/* Der enc28j60 liest ein ip-paket ein. wenn dieses eine länge größer 0 besitzt, wird es verarbeitet. */
64
65
uip_len=enc28j60PacketReceive(1200,uip_buf);
66
if(uip_len==0)
67
{
68
PORTC|=(1<<1);
69
for(i=0;i<UIP_CONNS;i++)
70
{
71
uip_periodic(i);
72
/* Wenn Daten produziert wurden, die in das Netzwerk gesendet werden müssen, wird die globale Variable
73
uip_len > 0 gesetzt. */
74
if(uip_len>0)
75
{
76
uip_arp_out();
77
enc28j60PacketSend(uip_len,uip_buf);
78
}
79
}
80
81
#if UIP_UDP
82
for(i=0;i<UIP_UDP_CONNS;i++)
83
{
84
uip_udp_periodic(i);
85
86
if(uip_len>0)
87
{
88
uip_arp_out();
89
enc28j60PacketSend(uip_len,uip_buf)
90
}
91
}
92
#endif /* UIP_UDP */
93
94
/* ARP timer funktion alle 10 sek aufrufen. */
95
if(zaehler>=156250)//(++arptimer == 20)
96
{
97
uip_arp_timer();
98
//arptimer = 0;
99
zaehler=0;
100
}
101
102
}else
103
{
104
PORTC|=(1<<2);
105
if(BUF->type==HTONS(UIP_ETHTYPE_IP))
106
{
107
PORTC|=(1<<3);
108
uip_arp_ipin();
109
uip_input();
110
111
if(uip_len>0)
112
{
113
PORTC|=(1<<4);
114
uip_arp_out();
115
enc28j60PacketSend(uip_len,uip_buf);
116
}
117
}elseif(BUF->type==HTONS(UIP_ETHTYPE_ARP))
118
{
119
uip_arp_arpin();
120
PORTC|=(1<<5);
121
/* If the above function invocation resulted in data that
122
should be sent out on the network, the global variable
123
uip_len is set to a value > 0. */
124
if(uip_len>0)
125
{
126
enc28j60PacketSend(uip_len,uip_buf);
127
PORTC|=(1<<6);
128
}
129
}
130
}
131
132
}
133
return0;
134
}
135
136
137
voidexample1_app(void)
138
{
139
140
if(uip_newdata()||uip_rexmit())
141
{
142
143
uip_send("ok\n",3);
144
enc28j60PacketSend(uip_len,uip_buf);
145
}
146
}
147
148
voidexample1_init(void)
149
{
150
uip_listen(HTONS(3000));
151
}
152
ISR(TIMER0_OVF_vect)
153
{
154
zaehler++;
155
zaehlerENC++;
156
}
Das Programm läuft bis zu dem Punkt, an dem Pin 3 von Port C auf High
gesetzt wird. Es wird aber leider kein Rücksendepaket erstellt und
abgesendet.
Danke schon mal im Vorraus.