w5100 über soft-spi an atmega2560 RX-Pufferproblem

Philsen

Neues Mitglied
18. Sep. 2009
9
0
0
Sprachen
Hallo,

ich verusche verzweifelt meinem wiznet w5100 über soft-spi an atmega2560
etwas per tcp zu empfangen...

w5100 = server und Pc = client


das klapp soweit eigentlich auch ganz gut... doch leert der den
RX-Puffer anscheinend nicht. Wenn ich einen datenpacket an der w5100 und
ihn mir dann zurückgeben lasse kommt er fehlerlos, doch holt er beim
abfragen des RX-Puffers immer wieder die selben daten. Wenn ich dann
noch ein Datenpacket auf die Reise schicke gibt es Datensalat.

das DSCON Flag wird nach jedem empfang gesetzt...

Wie kann ich den Puffer meines w5100 leeren?



Code:
Sub receive
   Local I As Word                                          'word = 2 byte variable
   Local Top As Word                                        'word = 2 byte variable
   Local Bytes_rcv As Word                                  'word = 2 byte variable

   'Check for new incomming data
   Call Wiz5100_readvalue(&H4 , &H26)                        'hole 0x0426(receivesize register) MSB
   Bytes_rcv = Wert                                         'schreibe geholten wert in bytes_rcv
   Shift , Bytes_rcv , Left , 8                             'LSB -> MSB
   Call Wiz5100_readvalue(&H4 , &H27)                       'hole 0x0427(receivesize register) LSB
   Bytes_rcv = Bytes_rcv + Wert                             'schreibe geholten wert in bytes_rcv

   If Bytes_rcv > 0 Then                                    'wenn bytes vorhanden
      Bytes_rcv = Bytes_rcv - 1                             'offset-1 : um die offset adresse zu bekommen

      For I = 0 To Bytes_rcv                                'hier werden die einzelnen Bytes in buffer geschrieben....
         Top = I + &H6000                                   'RX base adresse 0x6000     chipbase ist 0x00
         Msb = High(top)                                    'msb lesen
         Lsb = Low(top)                                     'lsb lesen
         Call Wiz5100_readvalue(msb , Lsb)                  'hole wert von adresse
         If Bytes_rcv < 200 Then                            '200 bytes empfangen
            Buffer = Buffer + Chr(wert)                     'schreibe geholten wert zu buffer
         End If
      Next
   Elseif Bytes_rcv > 700 Then
      Call Wiz5100_writevalue(&H4 , &H1 , &H40)             'Set RECV flag


   Call Wiz5100_writevalue(&H4 , &H1 , &H40)                'Set RECV flag
   End If

End Sub



mfg Philipp
 
Hallo Philsen,
Du musst den Read Pointer auch um Deine abgeholten Bytes weiter setzen.
Das macht der W5100 nicht selber.
Dabei natürlich ein Wrap nicht vergessen.

Gruß
miparo
 
Hallo,

nur mal so aus Interesse ...
Du musst den Read Pointer auch um Deine abgeholten Bytes weiter setzen.
Das macht der W5100 nicht selber.
Dabei natürlich ein Wrap nicht vergessen.
hört sich nach einem Ring-Buffer an wo der Eingangsdatenstrom in den Buffer
geschrieben wird und den Write-Pointer weiterschiebt und der AVR aus dem
Ringbuffer liest und seinerseits den Read-Pointer weiterschiebt. Und wenn der
Write-Pointer den Read-Pointer überholt gibts nen Daten-Crash :D Bin ich da
auf dem richtigen Weg ? Geht mir dabei jetzt nur um den Buffer ...

Den Rest kann ich mir schon vorstellen ... Ethernet-Controller mit SPI zum
AVR und nem selbstgebauten IP-Stack ... aber im Moment noch nicht von
Interesse für mich.

EDIT : Ich hab mir mal das Datenblatt gezogen ... recht interessantes
Silizium-Klötzchen ;) Aber 0,4mm Pin-Raster ist schon eine Herausforderung :D

Gruß
Dino
 
Hi,
da wirst Du auch festgestellt haben , das der W5100 getrenntes RAM hat , für RX und TX.

So ein Wrap passiert, wenn der Read Ptr 30 Byte vor dem Ringbuffer Ende steht, das empfangene Paket aber 32 byte groß ist.
Also erst 30 Byte lesen. Ptr wieder zum Anfang und den Rest lesen.

Den kannste noch mit dem Dachrinnen Kolben löten :)

Gruß
miparo
 
danke für die schnelle antwort...

doch leider ist das glaub ich nicht die lösung meines problems.

ich bin gerade nochmal jeden punkt durch gegangen und finde einfach keinen fehler... :((

hab jetzt noch die zeile hinzufügt:

Msb = High(bytes_rcv)
Call Wiz5100_writevalue(&H4 , &H28 , Msb)

Lsb = Low(bytes_rcv)
Call Wiz5100_writevalue(&H4 , &H29 , Lsb)


leider ohne erfolg
 
er geht komischerweise immer von den den vorher geholten bytes + die aktuell angekommenen bytes aus....

muss ich danach irgendwie ein disconnect oder ähnliches ausführen?
macht er nach dem setzen des DSCON flags nicht den speicher leer?
 
ok... fakt ist: der pointer wird nicht weitergesetzt. Das ist jetzt schonmal sicher...

wie setzt man den Pointer denn weiter - ich dachte ich mache das schon - wie in der Wiznet Doku...


Bitte um Hilfe!!!
 
Hi,
bei mir sieht das so aus:
Code:
Procedure wz5CopyRD(s : tSocket; Data : Pointer; len : Word);
var
  ptr, s2        : Word;
begin
  s2:= Sn_RX_RD0(s);  // =  s * $100 + $0028
  wz5ChipRD(s2, @ptr, 2);  
  ptr:= Swap(ptr);
  read_Data(s, @ptr, @Data, len); // read data
  Inc(ptr, len);
  ptr:= Swap(ptr);
  wz5ChipWR(s2, @ptr, 2);  // update RX read ptr
end;


// Receive data (TCP)
function SocketReceiveTCP(SocketPtr : tSocketHandle) : Word;
var
  sp[@SocketPtr] : tptrSocket;
  ret, len       : Word;
begin
  ret:= 0;
  len:= GetSn_RX_RSR(sp^.SocketNr);   // Rx receive count bytes


  if  len > 0  then
    if (len > sp^.PacketRecInfo.BufferLen) then
      len := sp^.PacketRecInfo.BufferLen;
    endif;
    wz5ChipRD(Sn_DPORT0(SocketPtr^.SocketNr), @SocketPtr^.PacketRecInfo.PeerPort, 2);
    wz5ChipRD(Sn_DIPR0(SocketPtr^.SocketNr), @SocketPtr^.PacketRecInfo.PeerIP, 4);

    wz5CopyRD(sp^.SocketNr, sp^.PacketRecInfo.BufferPtr, len);
    wz5ChipRegWR(Sn_CR(sp^.SocketNr), Sn_CR_RECV);

    Repeat
    until  wz5ChipRegRD(Sn_CR(sp^.SocketNr)) = 0;
  endif;
  Return (len);
end;

Kann nur in Pascal mit dienen.


"das DSCON Flag wird nach jedem empfang gesetzt..."
WARUM ?

Gruß
miparo
 
hi!

das hatte ich mal testweise gesetzt, weil mir ist aufgefallen wenn ich mit meinem PC-client disconnecte dann macht er mir schön den puffer leer...

jetzt suche ich eigentlich nach einer möglichkeit den ringpuffer des w5100 mit einem befehl zu leeren, dann wäre für mich die welt in ordnung ...


mfg
 
Hi,
das ist aber nicht die Lösung :confused:

Ein Disconnect brauchst Du nur bei Http, sonst wartet sich der Browser tot.

Stellt doch nochmal die ganze Routine ein.

Gruß
miparo
 
Wieso willst Du denn den Puffer leeren? Was soll es bringen? Mach das Handling vom Ein- und Ausgangspointer richtig und schon passt es ohne zu leeren.

Grüsse
Heinrich
 
Code:
Sub Wiz5100_init

  'Register reset
  Call Wiz5100_writevalue(&H0 , &H0 , &H80)

  'Set gateway IP adress
  Call Wiz5100_writevalue(&H0 , &H1 , Gw[1])
  Call Wiz5100_writevalue(&H0 , &H2 , Gw[2])
  Call Wiz5100_writevalue(&H0 , &H3 , Gw[3])
  Call Wiz5100_writevalue(&H0 , &H4 , Gw[4])

  'Set Subnetmask
  Call Wiz5100_writevalue(&H0 , &H5 , Sn[1])
  Call Wiz5100_writevalue(&H0 , &H6 , Sn[2])
  Call Wiz5100_writevalue(&H0 , &H7 , Sn[3])
  Call Wiz5100_writevalue(&H0 , &H8 , Sn[4])

  'Set MAC
  Call Wiz5100_writevalue(&H0 , &H9 , Mac[1])
  Call Wiz5100_writevalue(&H0 , &HA , Mac[2])
  Call Wiz5100_writevalue(&H0 , &HB , Mac[3])
  Call Wiz5100_writevalue(&H0 , &HC , Mac[4])
  Call Wiz5100_writevalue(&H0 , &HD , Mac[5])
  Call Wiz5100_writevalue(&H0 , &HE , Mac[6])

  'Set own IP adress
  Call Wiz5100_writevalue(&H0 , &HF , Ip[1])
  Call Wiz5100_writevalue(&H0 , &H10 , Ip[2])
  Call Wiz5100_writevalue(&H0 , &H11 , Ip[3])
  Call Wiz5100_writevalue(&H0 , &H12 , Ip[4])

  'Initialize socket 0 with TCP
  Call Wiz5100_writevalue(&H4 , &H0 , &H1 )                 'TCP
  Call Wiz5100_writevalue(&H4 , &H4 , &HA )                 'Port 2730
  Call Wiz5100_writevalue(&H4 , &H5 , &HAA )                'Port 2730


  'Call Wiz5100_writevalue(&H4 , &H26 , &H0)                 'receive size register auf 200
  'Call Wiz5100_writevalue(&H4 , &H27 , &HC8)                'receive size register auf 200

  Call Wiz5100_disconnect()

End Sub



Sub Wiz5100_writevalue(byval Msb As Byte , Byval Lsb As Byte , Byval Value As Byte)
   Reset Wiz5100_cs
   A = Wiz5100_opcode_write
   Spiout A , 1
   A = Msb
   Spiout A , 1
   A = Lsb
   Spiout A , 1
   Spiout Value , 1
   Set Wiz5100_cs
End Sub

Sub Wiz5100_readvalue(byval Msb As Byte , Byval Lsb As Byte)
   Reset Wiz5100_cs
   A = Wiz5100_opcode_read
   Spiout A , 1
   A = Msb
   Spiout A , 1
   A = Lsb
   Spiout A , 1
   Spiin Wert , 1
   A = 0
   Set Wiz5100_cs
End Sub


Sub Wiz5100_reset
   Wiz5100_res = 0
   Waitus 30                                                'Minimum 20 µs
   Wiz5100_res = 1
End Sub


'Send subroutine
Sub Wiz5100_send(byval Daten As String)

   Local Sendsize As Integer , Pos_tx As Word , Freesize As Word , Offset As Word , Tx_wr As Word
   Local Startadress As Word , Offsend As Word , Uppersize As Word , Glaenge As Word , Startpos As Word

   Buffer = Daten

   Sendsize = Len(buffer)

   Freesize:
   Call Wiz5100_readvalue(&H4 , &H20)
   Freesize = Wert
   Shift , Freesize , Left , 8
   Call Wiz5100_readvalue(&H4 , &H21)
   Freesize = Freesize + Wert

   If Freesize < Sendsize Then
   Goto Freesize
   End If

   Call Wiz5100_readvalue(&H4 , &H24)
   Tx_wr = Wert
   Shift , Tx_wr , Left , 8
   Call Wiz5100_readvalue(&H4 , &H25)
   Tx_wr = Tx_wr + Wert

   Startpos = Tx_wr
   Offset = Tx_wr And &H7FF
   Startadress = &H4000 + Offset
   Offsend = Offset + Sendsize
   Pointer = Startadress

   If Offsend > &H800 Then
      Uppersize = &H800 - Offset
      For X = 1 To Uppersize
         Msb = High(pointer)
         Lsb = Low(pointer)
         Tmp_str = Mid(buffer , X , 1)
         Tmp_value = Asc(tmp_str)
         Call Wiz5100_writevalue(msb , Lsb , Tmp_value)
         Incr Pointer
      Next X
      Pointer = &H4000
      Incr Uppersize
         For X = Uppersize To Sendsize
         Msb = High(pointer)
         Lsb = Low(pointer)
         Tmp_str = Mid(buffer , X , 1)
         Tmp_value = Asc(tmp_str)
         Call Wiz5100_writevalue(msb , Lsb , Tmp_value)
         Incr Pointer
      Next X
   Else
      For X = 1 To Sendsize
         Msb = High(pointer)
         Lsb = Low(pointer)
         Tmp_str = Mid(buffer , X , 1)
         Tmp_value = Asc(tmp_str)
         Call Wiz5100_writevalue(msb , Lsb , Tmp_value)
         Incr Pointer
      Next X
   End If

   Call Wiz5100_readvalue(&H4 , &H24)
   Startpos = Wert
   Shift , Startpos , Left , 8
   Call Wiz5100_readvalue(&H4 , &H25)
   Startpos = Startpos + Wert

   Glaenge = Startpos + Sendsize

   'Send Site
   Msb = High(glaenge)
   Call Wiz5100_writevalue(&H4 , &H24 , Msb)

   Lsb = Low(glaenge)
   Call Wiz5100_writevalue(&H4 , &H25 , Lsb)

   'Set SEND flag
   Call Wiz5100_writevalue(&H4 , &H1 , &H20)

   Buffer = ""
   Daten = ""
   Msb = 0
   Lsb = 0
   Tmp_str = ""
   Tmp_value = ""
   Glaenge = 0



   'Set SENDKEEP
   'Call Wiz5100_writevalue(&H4 , &H1 , &H22)

   'Set DISCON flag
   'Call Wiz5100_writevalue(&H4 , &H1 , &H8)

End Sub



Sub Wiz5100_receive
   Local I As Word                                          'word = 2 byte variable
   Local Top As Word                                        'word = 2 byte variable
   Local Bytes_rcv As Word                                  'word = 2 byte variable
   Local Temp As String * 10


   Buffer = ""

   'Check For New Incomming Data
   Call Wiz5100_readvalue(&H4 , &H26)                       'hole 0x0426(receivesize register) MSB
   Bytes_rcv = Wert                                         'schreibe geholten wert in bytes_rcv
   Shift , Getsize , Left , 8                               'LSB -> MSB
   Call Wiz5100_readvalue(&H4 , &H27)                       'hole 0x0427(receivesize register) LSB
   Bytes_rcv = Bytes_rcv + Wert                             'schreibe geholten wert in bytes_rcv



   If Bytes_rcv > 0 Then                                    'wenn bytes vorhanden
      Bytes_rcv = Bytes_rcv - 1                             'offset-1 : um die offset adresse zu bekommen


      For I = 0 To Bytes_rcv                                'hier werden die einzelnen Bytes in buffer geschrieben....
         Top = I + &H6000                                   'RX base adresse 0x6000     chipbase ist 0x00
         Msb = High(top)                                    'msb lesen
         Lsb = Low(top)                                     'lsb lesen
         Call Wiz5100_readvalue(msb , Lsb)                  'hole wert von adresse
         If Getsize < 500 Then                              '200 bytes empfangen
            Buffer = Buffer + Chr(wert)                     'schreibe geholten wert zu buffer
            End If
      Next

   Elseif Bytes_rcv > 500 Then
      Call Wiz5100_writevalue(&H4 , &H1 , &H40)             'Set RECV flag

   End If

   Call Wiz5100_writevalue(&H4 , &H1 , &H40)                'Set RECV flag

End Sub



'Disconnect connection: close socket, reopen socket and wait for new connection
Sub Wiz5100_disconnect
   Call Wiz5100_writevalue(&H4 , &H1 , &H0)                 'CLOSE
   Call Wiz5100_writevalue(&H4 , &H1 , &H1)                 'OPEN
   Call Wiz5100_writevalue(&H4 , &H1 , &H2)                 'LISTEN
End Sub
 
Das freut mich :)

Mit der Seite habe ich auch meine ersten Versuche gemacht.

Für den nächsten könntest Du den Fehler im obigen Code ja korrigieren.


Gruß
miparo
 
Code:
Sub Wiz5100_receive

   Buffer = ""

   'Pointerposition
   Call Wiz5100_readvalue(&H04 , &H28)                      'Hole die aktuelle position des RX pointers
   Pointerh = Wert
   Call Wiz5100_readvalue(&H04 , &H29)
   Pointerl = Wert

   'Socket 0 RX Received Size
   Call Wiz5100_readvalue(&H04 , &H26)                      'schaue, wieviel die empfangenen bytes sind
   Sizeh = Wert
   Call Wiz5100_readvalue(&H04 , &H27)
   Sizel = Wert

   Rxstartpos = Pointer
   Rxoffset = Rxstartpos And &H7FF
   Rxstartadress = &H6000 + Rxoffset
   Rxoffsend = Rxoffset + Size
   Bpointer = Rxstartadress


   If Rxoffsend > &H800 Then
      Rxuppersize = &H800 - Rxoffset

      For X = 1 To Rxuppersize
         Call Readvalue(bpointer)
         Buffer = Buffer + Chr(wert)
         Incr Bpointer
      Next X

      Bpointer = &H6000
      Incr Rxuppersize

      For X = Rxuppersize To Size
         Call Readvalue(bpointer)
         Buffer = Buffer + Chr(wert)
         Incr Bpointer
      Next X
   Else
      For X = 1 To Size

         Call Readvalue(bpointer)
         Buffer = Buffer + Chr(wert)
         Incr Bpointer
      Next X
   End If

   Pointer = Pointer + Size

   'update pointer
   Call Wiz5100_writevalue(&H04 , &H28 , Pointerh)
   Call Wiz5100_writevalue(&H04 , &H29 , Pointerl)

   Call Wiz5100_writevalue(&H04 , &H01 , &H40)              ' Update Rxbuf Pointer , Recv Data

   'reset interrupt
   Call Wiz5100_writevalue(&H04 , &H02 , &B100)

End Sub
 
OK, leider ist es jetzt so, dass ich nur maximal 46 bytes empfangen kann, wobei das letzte byte immer irgendein quatsch darstellt...


hat jemand eine idee??


mfg phil
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)