Forum Discussion

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

data loopback problem

I have a custom Cyclone board with a USB interface chip (Cypress). All software i/o operations are via IORD and IOWR macros. I am using the small non-cached niosII processor.

I have written a test program which loops back received USB data from on endpoint to another endpoint, i.e., echoing data to/from USB. The basic loop consists of reading a small buffer (8 – 64 bytes) data from an external USB chip

and writing the same buffer back to USB chip.

There seems to be a “magic” printf statement between the read/write operations. If I print the loop count of the buffer size, the writeback operation is successful; however, if I comment out the simple printf statement, the writeback fails. I have substituted a usleep function call with the same delay as the printf but the writeback still fails. It seems as if the printf causes a transfer of updating of a variable.

I've tried various delays with no success. I've reduced the printf to a single character and it still works. I've tried various methods of declaring, “volatile”ing, etc. the data buffer or loop count without any success.

Any ideas?

As a change of approach, I tried a cached version of the Nios processor. At that point the Nios processor seemed to completely ignore the DATAREADY handshake line of the USB device, wrote when the device was not ready for data and was unable to even initialize the part or enumerate.

Any ideas why working code would fail by switching processor builds? I rebuilt the syslib each time I changed the processor. The IORD is supposed to bypass the data cache according to the manual.

Thanks

steve

3 Replies

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

    How are you determining that you have data available (polling or interrupt-driven)?

    Have you considered using a DMA to process this? It seems like it would make sense to do so..... or design the DMA/streaming capability into your USB peripheral(s) itself. In this way, you'd just use the processor to configure your endpoints and then wait for interrupts from them (or your DMA).

    Cheers,

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

    Slacker,

    Thanks for the reply. This forum is refreshing in that the people are helpful and actually respond. The Cypress forum has such little traffic that most threads are orphaned, i.e., zero or one replies. Not much to be learned from. Anyways, regarding your suggestions.....

    --- Quote Start ---

    originally posted by slacker@Jul 18 2006, 09:48 PM

    how are you determining that you have data available (polling or interrupt-driven)?

    --- Quote End ---

    At this point there's an interrupt from the USB chip, CY68c0001?, saying data is available. The ISR sets a data available flag. In the main program, the flag is noted and the endpoint FIFO is read into a buffer until the FIFO is empty noting the number of words read. The buffer is then written using that word count. As absurd as this sounds, the printf statement seems to affect the word count.

    <div class='quotetop'>QUOTE </div>

    --- Quote Start ---

    Have you considered using a DMA to process this? It seems like it would make sense to do so..... or design the DMA/streaming capability into your USB peripheral(s) itself. In this way, you&#39;d just use the processor to configure your endpoints and then wait for interrupts from them (or your DMA).

    Cheers,

    - slacker

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=16999)

    --- Quote End ---

    [/b]

    --- Quote End ---

    That&#39;s a possibility to try. At this point, this loopback feature is simply a test to learn the ins and outs of the USB chip and to exercise Windows to see its limitations. Since this is a learning exercise, I may try the DMA just to see what happens. However, I&#39;d still like to understand what&#39;s going on with these other problems.

    When I get into my office, I&#39;ll post a few lines of code here to see if anyone sees anything obvious is wrong. Our programmer at the lab didn&#39;t see anything.

    thanks.

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

    update:

    I have had little luck on this front. I have now tried all three Nios core options, i.e., non-cached, instruction-cached, and data&instruction-cached. I was not able to find any combination of C-code which would successfully run with either of the cached processors. I used various types of declarations, "volatile"s, and looping structures. It is curious that semi-working code (using previously mentioned "magic" printf) would become completely inoperable code by switching cores and yes, I rebuilt the project (the code and associated libraries). Notably, the cached cores seemed to fail while talking to the USB chip by ignoring the BUSY line. Simple while loops were in place to monitor the busy flag and write only when the chip was not busy. See code below:

    while ((IORD_ALTERA_AVALON_PIO_DATA(USB_STATUS_PIO_BASE)&0x01) != 0x01); //wait until not busy

    IOWR(USB_SX2_BASE, 0x04, (0x0030 | 0x0080)); //Write request, bit7 = 1, bit6 = 0

    This worked in the non-cached but not either of the cached versions. hmmmm.

    end run:

    I decided to try the DMA approach. I added a DMA controller to the Nios processor connecting the DMA ports to the peripheral and the on-chip data memory. While the resulting compilation ended up with additional timing errors, none of the timing violations were associated with logic used for the USB interface. I used C-code which was working immediately prior to adding the DMA controller and no longer ran. I changed the DMA port connections to Nios components not associated with the USB peripheral and regenerated/compiled. The program executed without problems. It seems that the DMA controller is affecting timing of the internal busses.

    punt

    At this point I need to stop my development on USB and focus on other functions of the board. This USB portion has consumed too much of my developing time budget and must move forward on other avenues. I will hopefully return to this problem within a couple months but frankly, I&#39;m not sure where to go with it. Perhaps this break will allow me to think of new approaches to the problem.

    My suspicions are timing issues. I just haven&#39;t found what needs to be tighter constrained. I have had previous erratic behavior on this board while developing code for another off-chip peripheral and "solved" the problem by changing timing constraints. Another alternative which is not very pleasant to think about, is a possible layout issue. This board is a six layer board: L1 - GND plane with some escape routing, L2 - signal w/ GND fill, L3 - split plane for core power, PLL power, L4 - +3.3V plane, L5 - signal w/ GND fill, L6 - GND plane. There are multiple 0.01/0.001uf SMD caps located at each corner of the 400-pin BGA. I don&#39;t see where I missed something but ???

    Here&#39;s some of the working code, as promised. Below the first excerpt is a different looping structure which was less succesful although it was possible to eventually get it to work. Curiously, on the second version, removal of the "j=0" line would keep the code from executing properly although the variable J has absolutely nothing to do with the loop.

    Not sure where to go from here. Thanks for your input.

    steve

    Working code:

    void USB_data_loopback(void)

    {

    volatile alt_u8 i,j,flag_statusOUT,flag_statusIN;

    alt_u16 data[128];

    no_activity = 1;// clear flag

    if (got_out_data) //The FLAGS int tells us we have out data

    {

    got_out_data = 0;

    if (IORD_ALTERA_AVALON_PIO_DATA(USB_STATUS_PIO_BASE)&0x02)

    {

    j = 0;

    while(IORD_ALTERA_AVALON_PIO_DATA(USB_STATUS_PIO_BASE)&0x02)

    {

    data[j] = IORD(USB_SX2_BASE, 0x00);

    j++;

    }

    printf ("0/2 %x \n",j); //magic printf

    for (i = 0; i < j; i++)

    {

    IOWR(USB_SX2_BASE, 0x02,data[i]);

    }

    }

    ..

    ..

    ..

    ..

    Other structure:

    void USB_data_loopback(void)

    {

    volatile alt_u8 i,j,flag_statusOUT,flag_statusIN;

    alt_u16 data;

    no_activity = 1;// clear flag

    if (got_out_data) //The FLAGS int tells us we have out data

    {

    got_out_data = 0;

    if (IORD_ALTERA_AVALON_PIO_DATA(USB_STATUS_PIO_BASE)&0x02)

    j = 0;

    while(IORD_ALTERA_AVALON_PIO_DATA(USB_STATUS_PIO_BASE)&0x02)

    {

    data = IORD(USB_SX2_BASE, 0x00);

    IOWR(USB_SX2_BASE, 0x02,data);

    }

    ..

    ..

    ..

    ..