Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

TSE or SGDMA related problem with concurrent tx and rx

Hi,

Premise: I don't know if this problem is actually related to tse or sgdma; maybe even to Nios tse driver, although I don't think so.

I'm sending and receiving Ethernet packets using the standard tse reference design with minimal modifications (only added another timer and a few pio for test purposes).

I don't have timing issues in the design and it has no evident problems with tcp stack and a software like simple_socket_server.

In my design I actually don't use tcp stack but I simply send and receive raw ethernet packets.

All works fine as long as I don't have both a rx and a tx packet in the same moment (at least this seems to be the issue): a rx packet is lost if it arrives when my board is transmitting.

Example: I have a test a device which loopbacks the tx packet; if I connect it directly to my dev board I usually don't receive the answer (although sometimes I do...); if I connect them through an Ethernet switch (so a small delay between tx and rx is introduced) it works.

The PHY is correctly set to 100Mbit full duplex (I checked with an Ethernet tester), so there shouldn't be problems with concurrent rx and tx packets.

Maybe there could be any problem with memory available for rx? I use the ref design standard settings.

Can anyone suggest me if the problem is related to tse or sgdma?

Regards

17 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Daixiwen,

    I agree it could be a cache problem. How do I flush the cache as you suggest?

    Here you find my code. As you can see, I tried to insert a couple of flush functions I found around (now commented), but they had no effect.

    Maybe this is not the correct location to place them. Do I need to place them inside pkt_send function?

    void ecat_send(char*data, int len)
    {
       PACKET outpkt;
    /*
         OS_ENTER_CRITICAL();
            alt_dcache_flush_all ();
            alt_icache_flush_all ();
         OS_EXIT_CRITICAL();
    */
       LOCK_NET_RESOURCE(FREEQ_RESID);
       outpkt = pk_alloc(len+20);
       UNLOCK_NET_RESOURCE(FREEQ_RESID);
       if (!outpkt) {
          printf("Error: pk_alloc() failed");
          dtrap();
          return;
        }
       outpkt->net = ecat_net;
       memcpy(outpkt->nb_buff + ETHHDR_BIAS, data, len+ETHHDR_SIZE);
       outpkt->nb_plen = ETHHDR_BIAS + len;
       
       /* if a packet oriented send exists, use it: */
       if (outpkt->net->pkt_send)   {
          outpkt->nb_prot = outpkt->nb_buff;
          outpkt->net->pkt_send(outpkt);
       }
       else  {
          outpkt->net->raw_send(ecat_net, outpkt->nb_buff, outpkt->nb_plen);
          LOCK_NET_RESOURCE(FREEQ_RESID);
          pk_free(outpkt);
          UNLOCK_NET_RESOURCE(FREEQ_RESID);
       }
       
    }
    

    Regards
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    In these cases it is better to use uncached buffers, through the alt_remap_uncached() function. Using the alt_dcache_flush_all() will flush all the data cache (as the name suggests) and it can also have bad side-effects if a DMA is writing to memory at the same time.

    That said, I see that you use the pk_alloc() function, that should already return you an uncached buffer, so you shouldn't need to do anything. To be sure, you could add a printf() to display the value of outpkt->nb_buff, in hexadecimal. It should have its bit 31 set.

    I see that you free the packet just after calling raw_send(). This will work properly only if you ensure that the packet has been sent before raw_send() returns. This could explain why you had to add this option with the Opencores driver, but AFAIK the TSE driver uses a synchronous write, so it doesn't explain why you have the same problem with the TSE.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you,

    I'll check the bit 31 in nb_buff address when I will test again the board.

    About freeing the packet:

    I derived my send function from arp_send() or similar ones. I have no knowledge of proper usage of those free and lock calls.

    In the Opencore driver the raw_send function is NULL when I don't define the sync mode, so pkt_send is used. In sync mode it's the opposite: pkt_send is defined as NULL and a raw_send is used.

    In all case I always had TSE driver using pkt_send.

    Clearly, the pkt_send functions differ from one driver to the other.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't remember how the interniche drivers are made, but basically the free and lock process are very simple:

    [list][*]whenever you touch to the packet queues or allocation/deallocation, you must lock the stack first[*]when sending in sync mode, the send function only returns once the packet has been sent. The packet therefore can (and must!) be deallocated after the send call

    [*]when sending in async mode, the send function returns once it has set up the DMA, and probably before the packet has actually been sent. In that case you musn't deallocate the packet, because if it is allocated again before it has been sent, it's contents could be overwritten. The deallocation must be done from the ISR that is triggered by the DMA after the transfer has been complete.[/list]

    I'm guessing that the difference between pkt_send and raw_send is that one is synchronous and the other isn't, but they really didn't choose descriptive names for them. As far as I know the TSE driver doesn't use interrupts on the transmit DMA and only does synchronous transfers.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hi,SEILASER ,Daixiwen::confused:

    I wanna using the RJ45 on NEEK,The hardware part have been built,now in software part,I meet some troubles:

    1: Tripple speed ethernet.pdf I cannot read it clearly

    2: In NIOSII sofware ,I wanna to use HAL ,not tcp/ip ,IWIP,Interniche ,because I donnt understand them at all.

    I wanna to begin with the realizing the simple funtion,that is loopback function or somthing,now I try the loopback funtion,but I dont know how to write MAC frame,what exactly I need to configure the MAC registers?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Read the MAC datasheet to learn everything about the registers. You'll need to set up the MAC right, detect the PHY, configure it correctly, detect if the cable is connected, what is the speed of the link, if it is half or full duplex, and configure the MAC accordingly. You can have a look at the Interniche driver to see how it is done.

    Then you write your Ethernet packet contents somewhere in memory and set up the SGDMA to read it and send it to the MAC.

    In my opinion it is easier to learn how to use the TCP/IP stack than try to send the packets yourself. Have a look at the simple sockets server example and modify it to suit your needs. Read some documentation about the BSD sockets API, it isn't that hard to use.