📄 usb_framework.h
字号:
#ifndef USBFRAMEWORK_H
#define USBFRAMEWORK_H
/** \addtogroup module_usb_framework USB Framework (usbfw)
* \brief This module contains USB status information, functions for initialization, USB device reset
* handling, and most importantly, the framework for transfers on endpoint 0, FIFO access, and endpoint
* control.
*
* \section section_init Framework Initialization
* The framework and the USB peripheral unit can be initialized once the 48 MHz crystal oscillator is
* running. This is done by \ref usbfwInit(), which:
* \li Initializes framework variables
* \li Enables the USB peripheral unit by setting the \c SLEEP.USB_EN bit
* \li Enables the pull-up resistor via a GPIO pin
*
* When completing the last step, the host will be recognize the USB device, and start the enumeration
* process. To reply to the shortly incoming standard requests, the call to \ref usbfwInit() must be
* followed immediately by USB Interrupt \ref section_usbirq_initialization.
*
* \section section_endpoint_0_transfers Endpoint 0 Transfers
* The USB interface uses endpoint 0 to perform setup requests of the standard, vendor and class types.
* Such transfers consist of three phases:
* - A setup phase, where an 8-byte \ref USB_SETUP_HEADER is transferred to the device.
* - An IN/OUT data phase, if the length field of the \ref USB_SETUP_HEADER structure is non-zero.
* - A handshake phase, where the application can stall the endpoint to indicate error conditions.
*
* The setup handler, \ref usbfwSetupHandler(), takes care of the low-level parts of these transfers,
* including the IN/OUT buffering during the data phase (when there is one). The transfers fall into two
* categories:
* - Most standard requests can be processed internally, with little or no intervention form the user
* application. This is done internally by the \ref module_usb_standard_requests module.
* - Vendor and class requests are application specific and must always be processed by the application.
* Whenever such a request is received, the following hooks will be called between the phases:
* - <tt>void usbcrHookProcessOut(void)</tt>: Class requests with OUT data phase
* - <tt>void usbcrHookProcessIn(void)</tt>: Class requests with IN data phase
* - <tt>void usbvrHookProcessOut(void)</tt>: Vendor requests with OUT data phase
* - <tt>void usbvrHookProcessIn(void)</tt>: Vendor requests with IN data phase
*
* \section section_setup_handler_usage Setup Handler Usage
* This section describes what is required to make the vendor and class request hooks work. This
* information also applies to the standard requests that needs application processing
* (\ref usbsrHookSetDescriptor(), \ref usbsrHookSynchFrame(), and some cases of
* \ref usbsrHookSetFeature() and \ref usbsrHookClearFeature()).
*
* The transactions are made using a clean and efficient interface, consisting of two data structures and
* the endpoint 0 status byte:
* - The endpoint status is initially \ref EP_IDLE, which basically means that the setup handler is ready
* for a new setup phase (a new request). Upon an incoming request, the processing hook is called, and
* the \ref usbSetupHeader structure contains the 8 bytes received during the setup phase. At this
* point there are four different outcomes:
* - If the request is unknown or contains errors, the endpoint should be stalled. This is done by
* setting the endpoint status to \ref EP_STALL.
* - If there is no data phase (the length field is zero), the endpoint status should just remain in
* it's current state, \ref EP_IDLE.
* - If the request has an IN data phase, the \ref usbSetupData structure must be prepared. This
* includes setting a pointer to where IN data should be taken from, and the number of bytes to be
* transferred (usually the same number as indicated by the length field, but it can also be a
* lower number). The endpoint state is then changed to \ref EP_TX.
* - If the request has an OUT data phase, the \ref usbSetupData structure must be prepared. This
* includes setting a pointer to where OUT data should be stored, and the number of bytes to be
* transferred (always the same number as indicated by the length field). The endpoint state is
* then changed to \ref EP_RX.
* - When the data phase is complete, the processing hook will be called a second time to notify the
* application. Under normal conditions the endpoint status will be either \ref EP_TX or \ref EP_RX,
* and does not need to be changed any further (as this is done automatically upon return). If the
* endpoint status is \ref EP_CANCEL, it means that the USB host cancelled the setup transfer.
*
* The following code examples illustrate practical usage (more code is available in the application
* example projects):
*
* \par Example 1: Endpoint 0 Requests With OUT Data phase
*
* \code
* BYTE pLcdBuffer[358];
*
* void usbvrHookProcessOut(void) {
*
* // When this vendor request is received, we should either update a part of pLcdBuffer[] or leave
* // it as it is, and then refresh the LCD display. The index field of the setup header contains the
* // index of the first character to be updated, and the length field how many characters to update.
* if (usbSetupHeader.request == VR_LCD_UPDATE) {
*
* // First the endpoint status is EP_IDLE...
* if (usbfwData.ep0Status == EP_IDLE) {
*
* // There is no new data -> Just refresh the display
* if (usbSetupHeader.length == 0) {
* lcdRefresh();
* // There is no change to the endpoint status in this case
*
* // The PC wants to send data that will be stored outside pLcdBuffer -> stall the endpoint!
* } else if ((usbSetupHeader.length > sizeof(pTextBuffer) ||
* (usbSetupHeader.index >= sizeof(pTextBuffer) ||
* ((usbSetupHeader.index + usbSetupHeader.length) > sizeof(pTextBuffer)) {
* usbfwData.ep0Status = EP_STALL;
*
* // Setup the buffer
* } else {
* usbSetupData.pBuffer = &pLcdBuffer[usbSetupHeader.index];
* usbSetupData.bytesLeft = usbSetupHeader.length;
* usbfwData.ep0Status = EP_RX;
* }
*
* // Then the endpoint status is EP_RX (remember: we did that here when setting up the buffer)
* } else if (usbfwData.ep0Status == EP_RX) {
* // usbfwSetupHandler() has now updated pLcdBuffer, so all we need to do is refresh the LCD
* lcdRefresh();
* // usbfwData.ep0Status is automatically reset to EP_IDLE when returning to usbfwSetupHandler()
* }
*
* // Unknown request?
* } else {
* usbfwData.ep0Status = EP_STALL;
* }
* }
* \endcode
*
* \par Example 2: Endpoint 0 Requests With IN Data phase
*
* \code
* UINT8 keyBufferPos;
* BOOL blockKeyboard;
* char pKeyBuffer[150];
*
* void usbvrProcessIn(void) {
*
* // When this vendor request is received, we should send all registered key-strokes, and reset the
* // position counter. New keystrokes are blocked during the transfer to avoid overwriting the buffer
* // before it has been sent to the host.
* if (usbSetupHeader.request == VR_GET_KEYS) {
*
* // First the endpoint status is EP_IDLE...
* if (usbfwData.ep0Status == EP_IDLE) {
*
* // Make sure that we do not send more than the PC asked for
* if (usbSetupHeader.length < keyBufferPos) {
* usbfwData.ep0Status = EP_STALL;
*
* // Otherwise... , and reset the position counter
* } else {
* // Block for new keystrokes
* blockKeyboard = TRUE;
*
* // Setup the buffer
* usbSetupData.pBuffer = pKeyBuffer;
* usbSetupData.bytesLeft = keyBufferPos;
* usbfwData.ep0Status = EP_TX;
*
* // Reset the position counter
* keyBufferPos = 0;
* }
*
* // Then the endpoint status is EP_TX (remember: we did that here when setting up the buffer)
* } else if (usbfwData.ep0Status == EP_TX) {
*
* // pKeyBuffer has now been sent to the host, so new keystrokes can safely be registered
* blockKeyboard = FALSE;
*
* // usbfwData.ep0Status is automatically reset to EP_IDLE when returning to usbfwSetupHandler()
* }
*
* // Unknown request?
* } else {
* usbfwData.ep0Status = EP_STALL;
* }
* }
* \endcode
*
* If automated data transfer is not desired, the application should set \c USBFW_DATA.ep0Status to
* either \ref EP_MANUAL_RX or \ref EP_MANUAL_TX instead of \ref EP_RX or \ref EP_TX, respectively. Until
* the transfer is completed, the processing function (e.g. \ref usbvrHookProcessIn()) will be called at
* every endpoint 0 interrupt.
* @{
*/
#include "cc2511_usb_library_headers.h"
#ifdef EXTERN
#undef EXTERN
#endif
#ifdef USBFRAMEWORK_C
#define EXTERN
#else
#define EXTERN extern
#endif
//-------------------------------------------------------------------------------------------------------
/// \name Bus Pull-Up Control
//@{
///Enable pull-up on D+
#define USB_ENABLE_PULLUP() do { P1_0 = 1; P1DIR |= 0x01; } while (0)
///Disable pull-up on D+
#define USB_DISABLE_PULLUP() do { P1DIR &= ~0x01; } while (0)
//@}
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -