Forum Discussion

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

IORD_ALTERA_AVALON_PIO_DATA to slow?

Hi,

I'm trying to capture samples from an A/D Converter and streaming them onto a PC via an ethernet connection. I've extended the triple speed ethernet design example from the Nios II v9.1 installation directory.

I'm using a PIO component in my SOPC System where the ADC data is written on the data register of the component. From there I'm reading it in a while loop in my Nios software using:

while(tx_wr_pos < &tx_buf[SSS_TX_BUF_SIZE-8])

{

tx_wr_pos += sprintf(tx_wr_pos,"%d\n\r", IORD_ALTERA_AVALON_PIO_DATA(AD_DATA_BASE));

}

send(conn.fd, tx_buf, tx_wr_pos - tx_buf, 0);

However, there seems to be aliasing occuring whenever the ADC signal gets faster then a few 100Hz.

How many clock cycles does the IORD function need?

My Nios II system is set to the maximum 100 ticks/s.

Is my software to slow for just reading the PIO in a while loop?

27 Replies

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

    Yes, well it all sounds nice but I kind of have trouble putting the Ideas into practice. As I said, I'm still new to this kind of hardware development.

    @Cris72: using my SGDMA seems like an effective way of transfering data from the PIO address to the TSE. I've constructed descriptors (although the instructions in the embedded peripheral IP user guide are not really clear) and I'm telling it to transfer 1518 Bytes to the Avalon-ST sink of the TSE. (1518 being the amount of payload bytes for one MAC-Frame).

    How can I execute a transmit operation with the TSE??

    So far I've used the send() function with my socket which sends a buffer of data. I have to get access to any place the DMA writes data to if I wanted to use the send() function.

    @spaugh: never used a circular buffer before and no I idea how to dump data to the PC. Well there has to be some kind of conventional way to pass data to the PC from an ADC. How else would you do it?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    1518 being the amount of payload bytes for one MAC-Frame.

    How can I execute a transmit operation with the TSE??

    So far I've used the send() function with my socket which sends a buffer of data. I have to get access to any place the DMA writes data to if I wanted to use the send() function.

    --- Quote End ---

    The payload depends on the protocol you will use.

    1518 is the max length of a raw Ethernet frame, but your payload is generally at least 14 bytes shorter because of Ethernet II header (6 bytes for destination MAC, 6 for source MAC and 2 for eth type). Morteover, if you use IP, UDP or TCP you have extra protocol header bytes and your payload shrinks.

    Since you talk about sockets and a send() function, I believe you intend to use UDP or TCP for data transport. With UDP the total protocol bytes are 42, so you spare 1476 for your data payload.

    Regarding the dma buffer, you can pass the same pointer to the send function. You can't transfer directly with dma to tse if your communication involves some higher layer protocol (at least, I don't think this is an easy task).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Ok, so I'm using a DMA core now (not a SGDMA). I want to use the DMA configuration "peripheral to memory", so I implement the receive channel with the API functions:

    
    static volatile int dma_done = 0;
    /*
    * Callback function that obtains notification that the data 
    * is received. 
    */
    static void done (void* handle, void* data)
    {
        dma_done = 1;
    }
    ...
    INT8U tx_buf;
    INT32U rc;
    alt_dma_rxchan rxchan;
    INT8U * rx_data = (INT8U *)IOADDR_ALTERA_AVALON_PIO_DATA(DMA_READ_MASTER_AD_DATA_BASE);  /* pointer to data to send */
       
    /* Create the receive channel */
    if ((rxchan = alt_dma_rxchan_open(DMA_NAME)) == NULL)
    {
         printf ("Failed to open receive channel\n");
    }
    alt_dma_rxchan_ioctl(rxchan, ALT_DMA_RX_ONLY_ON, rx_data);      // continuously read from fixed address rx_data
    ...
    // The rest will execute in a loop:
    /* Post the receive request */
    if ((rc = alt_dma_rxchan_prepare (rxchan, tx_buf, SSS_TX_BUF_SIZE, done, NULL)) < 0)
    {
          printf ("Failed to post read request, reason = %d\n", rc);
     }                
     /* wait for transfer to complete */
     while (!dma_done);
     dma_done = 0;
     printf ("Transfer successful!\n");
     send(conn.fd, tx_buf, SSS_TX_BUF_SIZE, 0);   // creates the MAC frames ect. and send tx_buf content to the PC
    ...
    

    This is all happening in a thread. The functions are not garantied to be thread safe. When I debug it, the while loop never stops! Why? I'm also not quite sure about my rx_data. In the example 6-13 on page 156 of the Nios Software Developers Handbook (http://www.altera.com/literature/hb/nios2/n2sw_nii5v2.pdf) it doesn't show where the data is read from. Is the data automatically read from the avalon slave address connected to the read master of the DMA ?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have a simple question. While reading data from PIO, we just need to mention the base address of the signal. Whereas, the PIOs can be of different widths (1bit to 32 bit)... so by just mentioning the base address, the system automatically reads the complete value???

    BIU_status_x = IORD_ALTERA_AVALON_PIO_DATA(BIU_STATUS_REG_BASE);

    In this case, the BIU_STATUS_REG is a 5 bit PIO. Will I get the same 5 bit value in BIU_status_x????
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have read this document. I have already successfully configured my hardware design. Now the issue is with programming. This is my first time working on NIOS system design. I am just confused about how to read data from an multi-bit input line. I hope my question is clear now.

    By the way, in this particular case the system.h file defines the data width of BIU_STATUS_REG as 5 bits

    #define biu_status_reg_data_width 5

    My question is, if I simply give the base address of the input line, will I still be able to read all the 5 bits???
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The pio data register access is always 32 bits. If your PIO is 5 bits wide, then the 27 most significant bits will be 0 when you read and ignored when you write. Just use the low 5 bits.