• AVR Freaks

Using isochronous endpoint with packet size >=256 and usb_device.c limitation

Author
xiaofan
Super Member
  • Total Posts : 6247
  • Reward points : 0
  • Joined: 2005/04/14 07:05:25
  • Location: Singapore
  • Status: offline
2010/06/27 01:55:34 (permalink)
0

Using isochronous endpoint with packet size >=256 and usb_device.c limitation

The following code is in usb_hal_pic24.h


// BDT Entry Layout
typedef union __BDT
{
    union
    {
        struct
        {
            BYTE CNT         __attribute__ ((packed));
            BD_STAT     STAT __attribute__ ((packed));
        };
        struct
        {
            WORD        count:10;   //test
            BYTE        :6;
            WORD        ADR; //Buffer Address
        };
    };
    DWORD           Val;
    WORD            v[2];
} BDT_ENTRY;


The following is in usb_hal_pic18.h.


// BDT Entry Layout
typedef union __BDT
{
    struct
    {
        BD_STAT STAT;
        BYTE CNT;
        BYTE ADRL;                      //Buffer Address Low
        BYTE ADRH;                      //Buffer Address High
    };
    struct
    {
        unsigned :8;
        unsigned :8;
        WORD     ADR;                      //Buffer Address
    };
    DWORD Val;
    BYTE v[4];
} BDT_ENTRY;


The stack code, as of now (v2.7), does not support transmit packet size bigger than 255 (256 is not okay).


/********************************************************************
 * Function:        USB_HANDLE USBTransferOnePacket(
 *                      BYTE ep,
 *                      BYTE dir,
 *                      BYTE* data,
 *                      BYTE len)
 *
 * PreCondition:    The pBDTEntryIn[] or pBDTEntryOut[] pointer to
 *                    the endpoint that will be used must have been
 *                    initialized, prior to calling USBTransferOnePacket().
 *                    Therefore, the application firmware should not call
 *                    USBTransferOnePacket() until after the USB stack has been
                     initialized (by USBDeviceInit()), and the host has sent a
 *                    set configuration request.  This can be checked by
 *                    verifying that the USBGetDeviceState() == CONFIGURED_STATE,
 *                    prior to calling USBTransferOnePacket().
 *                   
 *                    Note: If calling the USBTransferOnePacket()
 *                    function from within the USBCBInitEP() callback function,
 *                    the set configuration is still being processed and the
 *                    USBDeviceState may not be == CONFIGURED_STATE yet.  In this
 *                    special case, the USBTransferOnePacket() may still be
 *                    called, but make sure that the endpoint has been enabled
 *                    and initialized by the USBEnableEndpoint() function first.
 *
 * Input:
 *   BYTE ep - the endpoint number that the data will be transmitted or
 *                received on
 *   BYTE dir - the direction of the transfer
 *              This value is either OUT_FROM_HOST or IN_TO_HOST
 *   BYTE* data - For IN transactions: pointer to the RAM buffer containing
 *                  the data to be sent to the host.
 *                  For OUT transactions: pointer to the RAM buffer that the
 *                  received data should get written to.
 *   BYTE len - length of the data needing to be sent (for IN transactions).
 *                For OUT transactions, the len parameter should normally be set
 *                to the endpoint size specified in the endpoint descriptor.
 *
 * Output:         
 *   USB_HANDLE - handle to the transfer.  The handle is a pointer to
 *                    the BDT entry associated with this transaction.  The
 *                    status of the transaction (ex: if it is complete or still
 *                    pending) can be checked using the USBHandleBusy() macro
 *                    and supplying the USB_HANDLE provided by
 *                    USBTransferOnePacket().
 *
 *
 * Side Effects:    None
 *
 * Overview:        The USBTransferOnePacket() function prepares a USB endpoint
 *                    so that it may send data to the host (an IN transaction),
 *                    or receive data from the host (an OUT transaction).  The
 *                    USBTransferOnePacket() function can be used both to receive
 *                    and send data to the host.  The USBTransferOnePacket()
 *                    function is the primary API function provided by the USB
 *                    stack firmware for sending or receiving application data
 *                    over the USB port.  The USBTransferOnePacket() is intended
 *                    for use with all application endpoints.  It is not used for
 *                    sending or receiving applicaiton data through endpoint 0
 *                    by using control transfers.  Separate API functions,
 *                    such as USBEP0Receive(), USBEP0SendRAMPtr(), and
 *                    USBEP0SendROMPtr() are provided for this purpose.
 *                   
 *                    The    USBTransferOnePacket() writes to the Buffer Descriptor
 *                    Table (BDT) entry associated with an endpoint buffer, and
 *                    sets the UOWN bit, which prepares the USB hardware to
 *                    allow the transaction to complete.  The application firmware
 *                    can use the USBHandleBusy() macro to check the status of the
 *                    transaction, to see if the data has been successfully
 *                    transmitted yet.
 *
 * Note:            None
 *******************************************************************/
USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,BYTE len)
{
    volatile BDT_ENTRY* handle;

    //If the direction is IN
    if(dir != 0)
    {
        //point to the IN BDT of the specified endpoint
        handle = pBDTEntryIn[ep];
    }
    else
    {
        //else point to the OUT BDT of the specified endpoint
        handle = pBDTEntryOut[ep];
    }
   
    //Error checking code.  Make sure the handle (pBDTEntryIn[ep] or
    //pBDTEntryOut[ep]) is initialized before using it.
    if(handle == 0)
    {
        return 0;
    }

    //Toggle the DTS bit if required
    #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG)
        handle->STAT.Val ^= _DTSMASK;
    #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY)
        if(ep != 0)
        {
            handle->STAT.Val ^= _DTSMASK;
        }
    #endif

    //Set the data pointer, data length, and enable the endpoint
    handle->ADR = ConvertToPhysicalAddress(data);
    handle->CNT = len;
    handle->STAT.Val &= _DTSMASK;
    handle->STAT.Val |= _USIE | _DTSEN;

    //Point to the next buffer for ping pong purposes.
    if(dir != 0)
    {
        //toggle over the to the next buffer for an IN endpoint
        ((BYTE_VAL*)&pBDTEntryIn[ep])->Val ^= USB_NEXT_PING_PONG;
    }
    else
    {
        //toggle over the to the next buffer for an OUT endpoint
        ((BYTE_VAL*)&pBDTEntryOut[ep])->Val ^= USB_NEXT_PING_PONG;
    }
    return (USB_HANDLE)handle;
}


The above code does not consider isochronous endpoint which can have packet size bigger than 255 (up to 1023 for full speed isochronous endpoint. Maybe this is a design flaw. The PIC24 code seems to go in the right direction with 10 bit WORD count defintion (0...1023) but there is no corresponding codes  in usb_device.c.

Anyone looking at this?


  USB_Links and libusb
#1

9 Replies Related Threads

    newfound
    Super Member
    • Total Posts : 1846
    • Reward points : 0
    • Joined: 2003/11/07 12:35:49
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2010/06/27 11:16:25 (permalink)
    0
    The funny thing is that if you look at USBCtrlTrftxService it is capable of > 255 byte transfers and it holds this up as a demo of how you would handle isochronous transfers even though a control transfer packet cannot be > 64 bytes.

    I'm sure it would not be difficult to modify the USBTransferOnePacket code to work with packets > 255 bytes. 
    #2
    Howard Long
    Super Member
    • Total Posts : 706
    • Reward points : 0
    • Joined: 2005/04/04 08:50:32
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2010/06/28 16:04:54 (permalink)
    0
    How incredibly weird! Coincidentally, I just hit exactly the same problem a few minutes ago trying to make a 192kHz 16 bit stereo soundcard interface work. Works fine up to 48kHz, then at 96kHz the buffer needs 384 bytes (96 samples every millisecond) and I started getting compiler warnings and the macro described thus:
     
    USB_HANDLE USBTxOnePacket(
        BYTE ep,
        BYTE* data,
        WORD len
    );

     
    is merely defined...
     
    #define USBTxOnePacket(ep,data,len)     USBTransferOnePacket(ep,IN_TO_HOST,data,len)

    with USBTransferOnePacket defined as...
     
    USB_HANDLE USBTransferOnePacket(
        BYTE ep,
        BYTE dir,
        BYTE* data,
        BYTE len
    );

     
    Uh-oh.
     
    While we can of course hack the library routines, it's not exactly a great solution for maintenance purposes!
     
    Cheers, Howard
    #3
    Howard Long
    Super Member
    • Total Posts : 706
    • Reward points : 0
    • Joined: 2005/04/04 08:50:32
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2010/06/28 17:00:30 (permalink)
    0
    Furthermore, it appears that the changes are pretty trivial:
     
    usb_device.h, line 674, change function prototype:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,WORD len);

    usb_device.c, line 648, change function prototype:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, WORD len);

    usb_device.c, line 2566, change function declaration:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,WORD len)

    usb_device.c, lines 2601 - 2603 change:
    #ifdef __C32__
        handle->CNT = len;
        handle->STAT.Val &= _DTSMASK;
        handle->STAT.Val |= _USIE | _DTSEN;
    #else
        handle->CNT = (BYTE)len;
        handle->STAT.Val &= _DTSMASK;
        handle->STAT.Val |= _USIE | _DTSEN | ((len>>8) & 3);
    #endif

    I now have 192kHz 16 bit stereo audio sampling rate.
     
    I have tested this in a PIC32 USB Starter board and a PIC24F Starter Kit 1.  I tried a test on a PICDEM FS USB but unsurprisingly I ran out of RAM in my test, but it still worked on the lower sample rates.
     
    Cheers, Howard
    post edited by Howard Long - 2010/06/28 17:48:44
    #4
    xiaofan
    Super Member
    • Total Posts : 6247
    • Reward points : 0
    • Joined: 2005/04/14 07:05:25
    • Location: Singapore
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2010/07/23 19:51:31 (permalink)
    0
    Another possible solution is to ditch the USBTransferOnePacket altogether. Travis Robinson has released the version of Benchmark firmware which has a faster implementation. You might want to give it  a try. It can be configured as single or dual interface, each interface can be configured as loopback bulk or isochronous transfer. And the isochronous transfer endpoint max packet size can higher than 256 (I tested 384).

    http://sourceforge.net/projects/libusbdotnet/
    Download the LibUsbDotNet_Src.2.2.6.zip file to try it out.

      USB_Links and libusb
    #5
    ivan.mercier
    New Member
    • Total Posts : 2
    • Reward points : 0
    • Joined: 2011/07/06 09:18:27
    • Location: 0
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2011/07/13 08:06:47 (permalink)
    0

    I try to modify USB stack as described here but usb enumeration doesn't  work anymore...any suggestion?
    thank you

    lsusb log:
    unable to read config index 0 descriptor/all
    can't read configurationd,error -32
    unable to enumerate USB device

    #6
    Antipodean
    Super Member
    • Total Posts : 1752
    • Reward points : 0
    • Joined: 2008/12/09 10:19:08
    • Location: Didcot, United Kingdom
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2011/07/13 09:38:52 (permalink)
    0
    Howard Long

    Furthermore, it appears that the changes are pretty trivial:
     
    usb_device.h, line 674, change function prototype:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,WORD len);

    usb_device.c, line 648, change function prototype:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, WORD len);

    usb_device.c, line 2566, change function declaration:
     
    USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,WORD len)



    If you dig around in the archives of the USB section of this forum, you will find I have mentioned this in the past (using ver 2.5 IIRC), and needing to do these mods for >255 byte transfer, in my case using CDC device. I beleive the reason it is set to 255 is so that the buffer stays within one bank of an 18F, but of course this is not a problem for the 16bit devices which have unbanked RAM. It seems that no-one who does the maintenance has put in the conditional code for the larger PICs to allow larger transfers.
     
     
     

    Do not use my alias in your message body when replying, your message will disappear ...

    Alan
    #7
    emarx
    Super Member
    • Total Posts : 100
    • Reward points : 0
    • Joined: 2009/05/04 21:53:32
    • Location: 0
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2011/07/13 09:48:12 (permalink)
    0
    Ivan - The USB enumeration uses endpoint 0 so there is no need for 256 data. You may want to just try using the original USBTransferOnePacket  for endpoint 0 and a modified version with a different name like USBTransferOnePacketWord for the endpoint requiring more than 256 data.
    post edited by emarx - 2011/07/13 09:49:39
    #8
    ajs410
    Junior Member
    • Total Posts : 97
    • Reward points : 0
    • Joined: 2011/05/19 13:08:46
    • Location: 0
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2011/07/14 09:25:15 (permalink)
    0
    Shouldn't you use USBEP0SendRAMPtr() for sending data over EP0?  The framework pumps the data over EP0 on its own when USBDeviceTasks() calls USBCtrlEPService().

    Also, Howard Long in post #4 uses an #ifdef __C32__.  I don't think that's defined for a PIC24 project.  Wouldn't this still work for a PIC24 though?
    #9
    emarx
    Super Member
    • Total Posts : 100
    • Reward points : 0
    • Joined: 2009/05/04 21:53:32
    • Location: 0
    • Status: offline
    Re:Using isochronous endpoint with packet size >=256 and usb_device.c limitation 2011/07/16 02:09:20 (permalink)
    0
    Hello ajs410, sorry I do coding in assembly so hopefully someone else who uses the Microchip C library could help you with this.

    Elliot
    #10
    Jump to:
    © 2019 APG vNext Commercial Version 4.5