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