Forum Discussion

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

TSE and scatter-gather dma problem

hi, everyone

I am recently trying to connect nios II to computor through ethernet , I separately connected a memory to stream scatter gather DMA to TSE's transmit and a stream to memory scatter gather DMA to TSE's receive . But when I sent a packet through scatter gather DMA, the output of TSE was nothing , also ,when I send packet from computor to NIOS, the receiving DMA got nothing.

I had tried connect the memory to stream DMA to stream to memory DMA, it worked OK.

Please give me some advice ,thanks.

https://www.alteraforum.com/forum/attachment.php?attachmentid=5665

when I runned the code below , I checked ouput signals of TSE through signaltap II,but nothing happened

# include "sys/alt_stdio.h"# include "altera_avalon_sgdma_regs.h"# include "altera_avalon_sgdma.h"# include "altera_avalon_sgdma_descriptor.h"
/* These will gate the data checking near the end of main */
volatile alt_u8 tx_done = 0;
volatile alt_u8 rx_done = 0;
void tx_callback_function(void * context)
{
    tx_done++;  /* main will be polling for this value being 1 */
}
void rx_callback_function(void * context)
{
    rx_done++;  /* main will be polling for this value being 1 */
}
unsigned int * mac_rev = (unsigned int *)TRIPLE_SPEED_ETHERNET_BASE;
unsigned int * mac_phy_addr = (unsigned int *)(TRIPLE_SPEED_ETHERNET_BASE+0x3C);
unsigned int * mac_phy_reg_addr_base = (unsigned int *)(TRIPLE_SPEED_ETHERNET_BASE+0x200);
unsigned int * mac_phy_reg_17 = (unsigned int *)(TRIPLE_SPEED_ETHERNET_BASE+0x200+ 17*4);
char rx_buf;
char tx_buf;
int i;  
void init_phy()
{
    * mac_phy_addr = 1;
    * mac_phy_reg_addr_base = * mac_phy_reg_addr_base | 0x8000; 
    //*mac_phy_reg_addr_base = *mac_phy_reg_addr_base | 0x1000;
}
int main()
{
    init_phy();
    alt_printf("control register is %x\n", *mac_phy_reg_17);
    alt_sgdma_dev * pSink = alt_avalon_sgdma_open(HITIC_SINK_NAME);
    if(pSink  == NULL)
    {
        alt_putstr("open sink error!\n");
    }
    alt_sgdma_dev * pSource = alt_avalon_sgdma_open(HITIC_SOURCE_NAME);
    if(pSource == NULL)
    {
        alt_putstr("open source error!\n");
    }
    
    /**************************************************************
     * Register the ISRs that will get called when each (full)  *
     * transfer completes                                       *
     ************************************************************/ 
    alt_avalon_sgdma_register_callback(pSource, &tx_callback_function,
                                       (ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK),
                                       NULL);
    alt_avalon_sgdma_register_callback(pSink, &rx_callback_function,
                                       (ALTERA_AVALON_SGDMA_CONTROL_IE_GLOBAL_MSK | ALTERA_AVALON_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK),
                                       NULL);
    /**************************************************************/
    alt_sgdma_descriptor sinkDesc, sourceDesc;
    alt_sgdma_descriptor nextSinkDesc, nextSourceDesc;
    nextSinkDesc.control = 0;
    nextSinkDesc.control = 0;
    alt_avalon_sgdma_construct_stream_to_mem_desc(&sinkDesc, &nextSinkDesc,
                                                    (alt_u32 *)rx_buf, 100, 0);
    alt_avalon_sgdma_construct_mem_to_stream_desc(&sourceDesc, &nextSourceDesc,
                                                    (alt_u32 *)tx_buf, 100, 0, 0, 0, 0);
    for(i = 0; i < 6; i ++) 
    {
        tx_buf=0xff;
    }  
    for(i = 6; i < 12; i ++) 
    {
        tx_buf=0x11;
    }                  
    tx_buf = 0;
    tx_buf = 100;                           
//    while(1)
//    {
//        alt_avalon_sgdma_do_async_transfer(pSource, &sourceDesc);
//        while(tx_done == 0) {}
//        alt_putstr("The transmit SGDMA has completed\n");
//        tx_done = 0;
//        for(i = 0; i < 10000000; i++);
//    }
    while(1)
    {
        alt_avalon_sgdma_do_async_transfer(pSink, &sinkDesc);
        while(rx_done == 0) {}
        alt_putstr("The receive SGDMA has completed\n");
        rx_done = 0;
    }

16 Replies

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

    Hello, Daixiwen.

    Thank you so much for clarifications.

    I tried to use uncached pointers (with 31 bit set). Now after TSE and PHY initialization complete, I read PHY mode status register, and bits "Auto-Negotiation Complete" and "Link Status" are both 1. So, PHY is configurated correctly and evidently must work.

    However, I can't see any data on TSE output, and code never comes to 'tx_done = 1'.

    I think that sgdma in my project is not configurated properly, or some changes are needed in software functions where I try to send data...

    Is there any other simple way to test TSE sending/receiving without sgdma?

    Actually I need to receive raw ethernet frames in my project, but first of all I try to send data as I think it should be easier to make it work.

    I looked through some threads in altera forums, but unfortunately didn't find any thread about how to receive ethernet frames with TSE and NOT using interNiche stack and OS.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Some data was transmitted via ethernet now: as I said in previous post, sgdma was initialized incorrectly.

    But while catching the packets with Wireshark, I see that packets content isn't correct.

    Besides that the packet was transmitted only twice (instead of infinite sending), after 2 transmissions code never comes to tx_done++, so it is looped in while(tx_done == 0);

    I have attached zip-code of source files.

    The only correct information is the source mac (00-11-22-33-44-55)

    All other bytes should be 0xA5 (as initialized), but in fact I see such packet:

    CC CC A5 A5 CC CC 00 11 22 33 44 55 CC CC A5 A5 CC CC A5 A5 CC CC A5 A5 CC CC

    and so on...

    Total length is also correct (128 bytes).

    I have no ideas, what happens...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Some data was transmitted via ethernet now: as I said in previous post, sgdma was initialized incorrectly.

    But while catching the packets with Wireshark, I see that packets content isn't correct.

    Besides that the packet was transmitted only twice (instead of infinite sending), after 2 transmissions code never comes to tx_done++, so it is looped in while(tx_done == 0);

    I have attached zip-code of source files.

    The only correct information is the source mac (00-11-22-33-44-55)

    All other bytes should be 0xA5 (as initialized), but in fact I see such packet:

    CC CC A5 A5 CC CC 00 11 22 33 44 55 CC CC A5 A5 CC CC A5 A5 CC CC A5 A5 CC CC

    and so on...

    Total length is also correct (128 bytes).

    I have no ideas, what happens...

    --- Quote End ---

    One of the problem is that sgdma descriptor should be constructed before every cycle of transmitting.

    So, now I achieved stable tramsmitting of packets by TSE ( in while(1) loop ). The only issue is that packet content is incorrect (only MAC of source is OK )...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It could be a problem with the data cache again, although it is rather odd that it would only get the high (or low) 16 bits of every 32-bit word correctly.

    I'd suggest to use signaltap to monitor what the SGDMA is doing, on both the TX fifo (as dsl suggests) and the Avalon master mread interface, to check what address the DMA is using and what it is reading there.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The issue was very simple:

    alt_avalon_sgdma_construct_mem_to_stream_desc(

    &sourceDesc[0], // descriptor I want to work with

    &nextSourceDesc[0], // pointer to "next"

    (alt_u32 *)ActualData, // starting read address

    (length), //# bytes

    0, // don't read from constant address

    1, // generate sop

    1, // generate endofpacket signal

    0);

    Parameter 5 should be 0 (zero) - don't read from constant address. Now all eth packets are transmitted correctly.

    So, thanks, everyone, for clarifications and suggestions.

    As actually I need to receive raw ethernet frames, I'll try to modificate the project for such a purpose.