You are here

To Toggle or Not To Toggle... | Cypress Semiconductor

To Toggle or Not To Toggle...

// Start USB for 5V operation and wait till enumeration is complete
USBFS_Start(0, USB_5V_OPERATION);
while(!USBFS_bGetConfiguration());

// Load the IN endpoint with data with no toggle
USBFS_LoadInEP(1, Data, 8, USB_NO_TOGGLE);

while(1)
{
   ...
   // Other code
   ...
   // Wait till EP1 becomes free
   while(!USBFS_bGetEPAckState(1));

   // Load EP1 with gamepad report
   USBFS_LoadInEP(1, Data, 8, USB_TOGGLE);
}

Above code shows the general program flow when using an USBFS user module to send data to the PC using an IN Endpoint.  If you notice, the USBFS_LoadInEP function call before the while loop uses “USB_NO_TOGGLE” and the call inside the while loop uses “USB_TOGGLE”.  What is this TOGGLE and NO_TOGGLE?  What is the significance of these constants?  I can understand from the above code that the first time I call the USBFS_LoadInEP function, I have to use NO_TOGGLE option and TOGGLE for further transactions.  Why is it so?  These are some of the questions a first time user of USB faces. 

In the USB bus, data is transferred from the Peripheral to Host and vice versa using Data Packets.

 

A data packet comprises of a DATA0 / DATA1 flag, the payload data and the CRC of the payload data.  The DATA0 / DATA1 flag is used to synchronize the data delivery.  Whenever a data packet is delivered, the receiver checks the DATA flag with its own internal flag.  The transaction is successful only if the flag matches.  At the time of enumeration, both the peripheral and the host set the Data flag to DATA0.  When the peripheral sends the first data packet, it sends it with DATA0 flag.  The host on receiving the packet verifies that the received packet has the DATA0 flag and its own flag is also DATA0.  So, the transaction is successful.  Immediately, the host toggles its internal flag to DATA1.  The peripheral when sending the next data packet should also toggle its own data flag and send the data packet with Data1 flag.  This toggling continues on all successive transactions.


In the PSoC, the constants USB_TOGGLE and USB_NO_TOGGLE tell the USBFS_LoadInEP function whether toggle the DATA flag before sending the data to the host.  When the USB is started and enumeration is complete, the USB hardware sets the DATA flag to DATA0.  As the very first data packet should go with DATA0, the DATA flag should not be toggled and hence the USB_NO_TOGGLE option should be used.  All further transactions will require the DATA flag to be toggled and should use the USB_TOGGLE option.

The sample code given in the beginning has one flaw.  If the data is not initialized at the time of calling the LoadInEP function outside the while loop, the host will receive this uninitialized data as the first packet.  This may be fine in certain applications like mouse where a data packet with zeroes does not affect the system. 

But in other systems where the peripheral responds with data to the host when host sends some commands, then this call to LoadInEP with dummy data may not be good.  The solution is to use a flag in the application and use NO_TOGGLE for the very first data packet and use TOGGLE for all further data transfers.  The code will now look like this.

BYTE FirstPacket;  // Flag to indicate first packet

// Start USB for 5V operation and wait till enumeration is complete
USBFS_Start(0, USB_5V_OPERATION);
while(!USBFS_bGetConfiguration());

FirstPacket = 1;

while(1)
{
   ...
   // Other code
   ...  

   // Wait till EP1 becomes free
   while(!USBFS_bGetEPAckState(1));
   if(FirstPacket)
   {
      // This is the first packet
      // Load the IN endpoint with data, and do not toggle the DATA flag
      USBFS_LoadInEP(1, Data, 8, USB_NO_TOGGLE);
      FirstPacket = 0;
    }
   else
   {
      // This is not the first packet
      // Load the IN endpoint with data, and toggle the DATA flag
   USBFS_LoadInEP(1, Data, 8, USB_TOGGLE);
   }
}

Comments

jordanss123 jordanss123's picture

fake Yeezy boost 350 80% Off www.yeezy350find.com

 

ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". CYPRESS SEMICONDUCTOR AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY CYPRESS SEMICONDUCTOR. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM CYPRESS SEMICONDUCTOR.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.