Xmega USB - buffer management?

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello again!  I recently got a CDC USB interface working on an A3BU.  I'm implementing a serial interface and was surprised by something - it looked like the micro would stop responding if I dumped a lot of data from the PC.  So I went to investigate using the code below just to implement a simple echo.

 

void main_cdc_rx_notify(void) // my UDI_CDC_RX_NOTIFY callback
{
    this_state = ECHO; // I want to do nothing but alert main loop that data is ready for echo
}

...

int main(void)
{
...
    while(true)
    {
        switch(this_state)
    ...
        case ECHO:
            while(!udi_cdc_is_rx_ready());
                rx_char = udi_cdc_getc();
            while(!udi_cdc_is_tx_ready());
                udi_cdc_putc(rx_char);
            this_state = IDLE;
    ...
    }
}

What I found is that if I type very quickly, the echo stops.  It's like the RX interrupt is being stopped...

 

For added background, I was using the udi_cdc read & write_buf funcs when I first noticed this, like so:

...
    num_bytes_rxd = udi_cdc_get_nb_received_data();
    udi_cdc_read_buf((char*)rx_buf, num_bytes_rxd);
...

...
    udi_cdc_write_buf(out_buf, BUF_SIZE);  // BUF_SIZE was 64 chars
...

after making the simple echo, I noticed that I can type at a regular rate and everything echos as I expect.  If I hammer a couple keys quickly, it hangs.  I added a timer ovf tick-tock that toggles an LED, and it keeps going after the USB stops, for whatever that's worth.

 

It looks to me like I'm not checking something correctly / am reading or writing at the wrong time.  I'm waiting for udi_cdc_is_rx/tx_ready before reading or writing, which is similar to how I used to read/write on Megas.  I guess I've missed something...

 

help?  I've dug through the ASF documentation and couldn't find a solution.

 

Last Edited: Thu. Jul 12, 2018 - 01:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well - for what it's worth, I think I've  fixed it.

 

I tried this out and it seems to prevent anything hosing up the interrupt:

int main (void)
{
    ...
    case ECHO:
        num_bytes_rxd = udi_cdc_get_nb...
        //while(!udi_cdc_is_rx_ready()){nop();}
        // -- this rx wait seemed unnecessary
        // ​I'd expect collisions in the buffer to be prevented by the API (I haven't verified that)
        // removing it seemed to have no impact
        udi_cdc_read_buf((char*)rx_buf, num_bytes_rxd)
        while(!udi_cdc_is_tx_ready()){nop();}
        udi_cdc_write_buf(rx_buf,num_bytes_rxd);
    ...
}

void main_cdc_rx_notify() // the callback
{
    this_state = ECHO;
}

This seems burdensome though - I'd expect this processor to be able to echo character by character without the rx interrupt getting clobbered.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have a read of how the USB peripheral in the XMEGA works. It can do stuff like double buffering, but really you need to make your own circular buffer somewhere. If you then look at the ASF code you should see some callbacks you can implement that will let you transfer incoming bytes to your circular buffer in the RX interrupt.