This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

USB throughput for nRF52840

I have developed USB firmware for the 840 based on the USBD example so that we can use WINUSB (WCID) for the host.  The design is for USB 2.0 full speed with EPIN1 for device to host transfers and EPOUT1 for host to device transfers The firmware passes test for 60, 64 and 192 byte tests when they are manually triggered from a Windows test tool we wrote.  I just moved onto loop testing to validate throughput and the device seems unable to work at speed with more than 64 bytes in a transfer (tested at 1 , 10 and 100 MS rates).  I've examined the descriptor file (usbd_desc.c) and the USB code (usbd.c) but can't find an issue.  I am suspicious of how I handle receive packet for NRF_DR_USBD_EPOUT2 in the event handler but it does work with the manually triggered testing.  attached is a zip of my project (I am using the template example as a base).g4_boost_snapshot_041320_0912AM_start of day.zip

  • update:  I was able to get the USBD code to hook up to WINUSB and it is currently running about 200 KB/s using nrfx_usbd_ep_transfer() with the event handler.  I would increase throughput by implementing handled transactions but was unable to get that working.  After calling nrfx_usbd_ep_handled_transfer() for EPIN1 I can follow execution into the callback function but the endpoint never seems to send the data.  I can't find anything wrong with the functions involved but have included them below.  Any ideas?

    //  *****************************************************************
    //  function: usbd_start_tx
    //  purpose:  start a handled TX transaction.  This code starts up
    //            the TX using a handled transaction that automatically
    //            will pull data from the TX FIFO until it is emptied
    //            using a call back function.
    //  passed:   nothing
    //  returns:  nothing
    //  notes:    none
    //  *****************************************************************
    inline void usbd_start_tx(void)
    {
     
      if(nrf_drv_usbd_ep_is_busy(NRFX_USBD_EPIN1)==false)
      {
        if(fifo_empty(TX_FIFO)==false)
        {
          //data available so start a handled transaction
          tx_flag=true;
          nrfx_err_t err_code=nrfx_usbd_ep_handled_transfer(NRFX_USBD_EPIN1,&usbd_tx_handler);
    /*
    //non-handled transactions
          uint32_t size=fifo_rd_tx_fifo((uint8_t*)usb_tx_buff,64);
          if (size>0)
          {
              
            //push next packet into stack
            usb_tx_xfer.size=size;
            tx_flag=true;
            nrfx_usbd_ep_transfer(NRFX_USBD_EPIN1,&usb_tx_xfer);
           }

    */


        }
      }

      return;

    }//end function

    //  *****************************************************************
    //  function: usbd_tx_feeder
    //  purpose:  push data into the USB stack for TX based on calls from
    //            the stack itself.  This should increase TX throughput
    //            by avoiding using SW events for TX processing.
    //  passed:   p_next  transfer structure
    //            p_context   pointer to context
    //            ep_size     endpoint size
    //  returns:  true        more data for xfer
    //            false       no more data
    //  notes:    this function is part of a "handled" TX transfer and
    //            is a callback for TX transfers once they have been
    //            started
    //
    //            cannot transfer data from flash - RAM ONLY!
    //
    //            we return false with ep_size=0 for no data this can occur
    //            if the FIFO is loaded with only 64 bytes
    ////  *****************************************************************
    bool usbd_tx_feeder(nrfx_usbd_ep_transfer_t *p_next, void*p_context,size_t ep_size)
    {
      //get a 64 byte temporary buffer
      uint8_t *buff;

      //pop data off the TX fifo  into the temp buffer
      buff=nrfx_usbd_feeder_buffer_get();  

      //get some data
      ep_size=fifo_rd_tx_fifo((uint8_t*)usb_tx_buff,64);
     
      //update parameters
      usb_tx_xfer.p_data.tx=(uint8_t*)usb_tx_buff;
      usb_tx_xfer.size=ep_size;
      p_next=&usb_tx_xfer;
    //  p_context=NULL;

      //is there any more data in TX FIFO?
      if(fifo_empty(TX_FIFO))
      {
         //flag feeder needs priming
         tx_flag=false;
         return(false);
      }
      else
      {
        return(true);
      }
    }//end function

  • Hi Henry,

    Seems like you are using your own USB stack? I think you should try app_usbd and see if it works
  • I'm using the NORDIC USB stack; built my code on the USBD example which uses the USBD driver.  There is no example that implements WINUSB (WCID) which was a requirement for the implementation.

  • Do I have to use app_usbd for handled transactions to work? 

  • well it is not the matter of "have to". It is just that using app_usbd for handled trasactions would make the behavior more predictable and easier for us

Related