Source changes to allow simultaneous WiFi and dataflash

Postings related to the second version of the WiShield

Re: Source changes to allow simultaneous WiFi and dataflash

Postby spidermonkey04 » Sun Sep 26, 2010 11:43 pm

Whoops, forgot to check back on this thread.

Your 2nd packet is garbage because the IP and TCP headers need to be rebuilt also. This problem is unique to SPI interfaces, and one can't expect the authors of uIP to anticipate every type of network interface. Plus I think the uip-split stuff is a hack anyway. It's because of the way an SPI transfer works. Now, pardon my rough explanation.

When you spi_transfer() a byte it is actually writing AND reading a byte, and since the wifi chip isn't returning anything, the the byte you send is essentially being erased afterwards. So we can just rebuild the headers and it'll work.

Here's a function that works in MY modified code, but I think you can figure out the important stuff. Sorry, I don't feel like going back to make this work with the stock code when I'll never use it that way. I'm around to help though, PM's never hurt anybody :)

Code: Select all
void UIP::split_output(void)
{
  u16_t tcplen, len1, len2;
 
  // We only try to split maximum sized TCP segments.
  if(BUF->proto == UIP_PROTO_TCP &&
  // MSS can change each time, so we might have a max sized segment BUT it doens't fill up buffer so won't split
     //uip_len == UIP_BUFSIZE - UIP_LLH_LEN) {
     uip_len >= uip_conn->mss-71){ // >= just to be safe
        //Serial.println("Splitn");
        tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN;
        // Split the segment in two. If the original packet length was odd, we make
        //    the second packet one byte larger.
        len1 = len2 = tcplen / 2;
        if(len1 + len2 < tcplen) {
          ++len2;
        }
   
        // Create the first packet. This is done by altering the length
        //   field of the IP header and updating the checksums.
        uip_len = len1 + UIP_TCPIP_HLEN;
       
    #if UIP_CONF_IPV6
        BUF->vtc = 0x60;
        // For IPv6, the IP length field does not include IPv6 IP header length.
        BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
        BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
    #else
        BUF->len[0] = uip_len >> 8;
        BUF->len[1] = uip_len & 0xff;
    #endif
         
        uip_len += UIP_LLH_LEN;
   
        // Recalculate the TCP checksum.
        BUF->tcpchksum = 0;
        BUF->tcpchksum = ~(tcpchksum());
   
    #if !UIP_CONF_IPV6
        // Recalculate the IP checksum.
        BUF->ipchksum = 0;
        BUF->ipchksum = ~(ipchksum());
    #endif
   
        // Transmit the first packet immediately
        Zg.zg_send();
   
        /* Now, create the second packet. To do this, it is not enough to
           just alter the length field, but we must also update the TCP
           sequence number and point the uip_appdata to a new place in
           memory. This place is detemined by the length of the first
           packet (len1). */
        uip_len = len2 + UIP_TCPIP_HLEN;
        //Serial.println(uip_len, DEC);
       
        /*    uip_appdata += len1;*/
        memcpy((u8*)&uip_buf[54], (u8*)uip_appdata + len1, len2);
       
        // For 2nd packet, IP and TCP headers need to be rebuilt since they were
        // erased when SPI_transfering the first packet.
        BUF->proto = UIP_PROTO_TCP;
        BUF->vhl = 0x45;
        BUF->flags = TCP_PSH | TCP_ACK;
        BUF->tcpoffset = 5 << 4;
        BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
        BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
        ++ipid;
        BUF->ipid[0] = ipid >> 8;
        BUF->ipid[1] = ipid & 0xff;
        BUF->ttl = UIP_TTL;

        BUF->srcport  = uip_conn->lport;
        BUF->destport = uip_conn->rport;

        uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
        uip_ipaddr_copy(BUF->destipaddr, uip_conn->ripaddr);
       
       
    #if UIP_CONF_IPV6
        // For IPv6, the IP length field does not include IPv6 IP header length.
        BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
        BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
    #else
        BUF->len[0] = uip_len >> 8;
        BUF->len[1] = uip_len & 0xff;
    #endif
       
        add32(uip_conn->snd_nxt, len1);
        BUF->seqno[0] = uip_acc32[0];
        BUF->seqno[1] = uip_acc32[1];
        BUF->seqno[2] = uip_acc32[2];
        BUF->seqno[3] = uip_acc32[3];
       
        BUF->ackno[0] = uip_conn->rcv_nxt[0];
        BUF->ackno[1] = uip_conn->rcv_nxt[1];
        BUF->ackno[2] = uip_conn->rcv_nxt[2];
        BUF->ackno[3] = uip_conn->rcv_nxt[3];
   
        // Recalculate the TCP checksum.
        BUF->tcpchksum = 0;
        BUF->tcpchksum = ~(tcpchksum());
   
    #if !UIP_CONF_IPV6
        // Recalculate the IP checksum.
        BUF->ipchksum = 0;
        BUF->ipchksum = ~(ipchksum());
    #endif
   
        // Let stack.cpp transmit the second packet.
      Arp.arpout();
  }
 
}

( hints: uip_add32(), uip_tcpchksum(), uip_arpout. zg_send might be problems )

---Jared
spidermonkey04
 
Posts: 66
Joined: Thu Oct 29, 2009 6:45 pm

Re: Source changes to allow simultaneous WiFi and dataflash

Postby CapnBry » Tue Sep 28, 2010 12:54 pm

Oh well there's the thing I overlooked. I didn't even bother to check the actual transfer of data in spi_transfer(). I didn't realize that overwrote the buffer with reads as it wrote. Thanks for your code, certainly makes it easy to drop into place!
CapnBry
 
Posts: 10
Joined: Wed Aug 18, 2010 11:21 am

Previous

Return to WiShield 2.0

Who is online

Users browsing this forum: No registered users and 1 guest