Forum Discussion
Guys,
Comments: First, pbuf payload is guaranteed aligned. I use custom version of this driver (more optimized and improves on SGDMA and PHY handling plus some bug fixes in the Altera code) and took out the alignment check and added an assertion and it never asserts. If user code sets payload (a bad practice) than it's not guaranteed, but pbuf_alloc aligns payload. An application that uses UDP for high data rates is probably using a custom client in which case the payload size could be enforced. I use a zero-copy UDP high speed reliable protocol (the hardware writes in the UDP payload and checksum) and in this case the payload is large and always aligned. You only need to unwind if pkt->next isn't NULL. An unchained pbuf can never have a payload size less then 4 because of the IP header. I'd put back the pkt->next != NULL test before the for loop. Minor:
// Unwind pbuf chains
if (pkt->tot_len > sizeof(buf2)) { // no space for unwinding; drop the packet
return ERR_OK; }
Can't occur. lwIP will never chain more than the MTU. It can't because 802.11 cannot support it. This bug in the SGDMA (it's a bug if you can't sent 1-x bytes) maybe why InterNiche is so slow and full of copies. It's too bad it cripples lwIP which otherwise is much more efficient. I wonder if we can write the small payload bytes right to the MAC. I.e. don't use SGDMA but use a for loop to write 1 to 3 bytes to the MAC buffer (same place the SGDMA writes to)? Does either of you or anyone know if this could be done? I think I'll put in a service request for this as a SGDMA bug. Great discussion - thanks! Bill- Msg064842 years ago
New Contributor
Hi, I downloaded the latest LWIP. It somewhat works in that I have to start two cmd shells and send ping requests from both so that the second will "unbuffer" the first. I tried replacing the err_t tse_mac_raw_send(struct netif *netif, struct pbuf *pkt) with yours above, but the compiler complains that
ALT_LINK_ERROR("alt_remap_uncached() is not available because Nios II Gen2 cores with data caches don't support mixing cacheable and uncacheable data on the same line.");
From alt_remap_uncached.c
I tried putting it back to use
ActualData = (void*)(((alt_u32)data)); which does compile but does not actually reply to the ping.
below is the tse_mac_raw_send() found in the latest lwip lwip_tse_mac.c
I am not sure if this is causing the issue, it seems like the packet is coming in and getting buffered until the next packet arrives that is why having 2 ping running makes everything appear to work.
Does this make sense? I may be completely wrong, any help is appreciated.
err_t tse_mac_raw_send_orig (struct netif *netif, struct pbuf *pkt){int tx_length;unsigned len;struct pbuf *p;alt_u32 *data;tse_mac_trans_info *mi;lwip_tse_info *tse_ptr;struct ethernetif *ethernetif;alt_u32 *ActualData;/* Intermediate buffers used for temporary copy of frames that cannot be directrly DMA'ed*/char buf2[1560];ethernetif = netif->state;tse_ptr = ethernetif->tse_info;mi = &tse_ptr->mi;for(p = pkt; p != NULL; p = p->next){data = p->payload;len = p->len;// just in case we have an unaligned buffer, this should never occurif(((unsigned long)data & 0x03) != 0){/** Copy data to temporary buffer <buf2>. This is done because of alignment* issues. The SGDMA cannot copy the data directly from (data + ETH_PAD_SIZE)* because it needs a 32-bit aligned address space.*/memcpy(buf2,data,len);data = (alt_u32 *)buf2;}// uncache the ethernet frameActualData = (void*)(((alt_u32)data));/* Write data to Tx FIFO using the DMA */alt_avalon_sgdma_construct_mem_to_stream_desc((alt_sgdma_descriptor *) &tse_ptr->desc[ALTERA_TSE_FIRST_TX_SGDMA_DESC_OFST], // descriptor I want to work with(alt_sgdma_descriptor *) &tse_ptr->desc[ALTERA_TSE_SECOND_TX_SGDMA_DESC_OFST],// pointer to "next"(alt_u32*)ActualData, // starting read address(len), // # bytes0, // don't read from constant addressp == pkt, // generate sopp->next == NULL, // generate endofpacket signal0); // atlantic channel (don't know/don't care: set to 0)tx_length = tse_mac_sTxWrite(mi,&tse_ptr->desc[ALTERA_TSE_FIRST_TX_SGDMA_DESC_OFST]);if (tx_length != p->len)dprintf(("failed to send all bytes, send %d out of %d\r\n", tx_length, p->len));ethernetif->bytes_sent += tx_length;}LINK_STATS_INC(link.xmit);return ERR_OK;}