Forum: Mikrocontroller und Digitale Elektronik Anpassung TCP-IP Stack


von Manuel (Gast)


Lesenswert?

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?

von tt4u (Gast)


Lesenswert?

schau Dir mal ethersex an

von holger (Gast)


Lesenswert?

>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?

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Manuel (Gast)


Lesenswert?

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:
1
u8_t appstate[UIP_APPSTATE_SIZE]; 
2
};

Danke

von Karl H. (kbuchegg)


Lesenswert?

Manuel schrieb:

>
1
#define UIP_APPCALL example1_app();
2
> 
3
> #define UIP_APPSTATE_SIZE 0;

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.

von Manuel (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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?

von Manuel (Gast)


Lesenswert?

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
void example1_init(void) 
2
{
3
uip_listen(HTONS(1234));
4
}
5
void example1_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.

von Manuel (Gast)


Lesenswert?

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?

von Manuel (Gast)


Lesenswert?

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.

von fdssd (Gast)


Lesenswert?

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

von Tom M. (tomm) Benutzerseite


Lesenswert?

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...

von hhnnjbh (Gast)


Lesenswert?

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

von Manuel (Gast)


Lesenswert?

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.
1
#include "uip.h"
2
#include "uip_arp.h"
3
#include "Enc28j60.h"
4
#include <avr/io.h>
5
6
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
7
8
#ifndef NULL
9
#define NULL (void *)0
10
#endif /* NULL */
11
12
#ifndef F_CPU
13
#define F_CPU 16000000
14
#endif
15
16
volatile unsigned char mymac[6] = {0x00,0x22,0xf9,0x01,0x73,0xc6};
17
18
/*-----------------------------------------------------------------------------------*/
19
int
20
main(void)
21
{
22
  
23
    /*ENC Initialisieren*/
24
  enc28j60Init();
25
  //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
unsigned long zaehler;
35
unsigned short zaehlerENC;
36
37
  /* uIP TCP/IP stack initialisieren. */
38
  uip_init();
39
  
40
  example1_init();
41
  u8_t i, 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
      } else if(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
  return 0;
134
    }
135
136
137
  void example1_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
  void example1_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.

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
Noch kein Account? Hier anmelden.