Add branch for the conversion of demos to use standard C header files for configuration, rather than makefile defined macros.

This commit is contained in:
Dean Camera 2012-05-10 19:24:58 +00:00
parent e8570c4a37
commit 359fbfe14d
395 changed files with 9912 additions and 2756 deletions

View file

@ -92,10 +92,12 @@
*/
#define USB_DEVICE_OPT_LOWSPEED (1 << 0)
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
* USB interface should be initialized in full speed (12Mb/s) mode.
*/
#define USB_DEVICE_OPT_FULLSPEED (0 << 0)
#if (F_USB > 6000000)
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
* USB interface should be initialized in full speed (12Mb/s) mode.
*/
#define USB_DEVICE_OPT_FULLSPEED (0 << 0)
#endif
//@}
#if (!defined(NO_INTERNAL_SERIAL) || defined(__DOXYGEN__))
@ -157,7 +159,7 @@
static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint16_t USB_Device_GetFrameNumber(void)
{
return USB_EndpointTable.FrameNum;
return ((USB_EndpointTable_t*)USB.EPPTR)->FrameNum;
}
#if !defined(NO_SOF_EVENTS)

View file

@ -48,20 +48,36 @@ volatile uint8_t USB_Endpoint_SelectedEndpoint;
volatile USB_EP_t* USB_Endpoint_SelectedHandle;
volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number,
const uint8_t Direction,
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
const uint8_t Entries)
{
for (uint8_t i = 0; i < Entries; i++)
{
if (!(Table[i].Address))
continue;
if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
{
return false;
}
}
return true;
}
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
const uint8_t Config,
const uint8_t Size)
{
Endpoint_SelectEndpoint(Number | Direction);
Endpoint_SelectEndpoint(Address);
USB_Endpoint_SelectedHandle->CTRL = 0;
USB_Endpoint_SelectedHandle->STATUS = (Direction == ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
USB_Endpoint_SelectedHandle->STATUS = (Address & ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
USB_Endpoint_SelectedHandle->CTRL = Config;
USB_Endpoint_SelectedHandle->CNT = 0;
USB_Endpoint_SelectedHandle->DATAPTR = (intptr_t)USB_Endpoint_SelectedFIFO->Data;
USB_Endpoint_SelectedFIFO->Length = (Direction == ENDPOINT_DIR_IN) ? Size : 0;
USB_Endpoint_SelectedFIFO->Length = (Address & ENDPOINT_DIR_IN) ? Size : 0;
USB_Endpoint_SelectedFIFO->Position = 0;
return true;
@ -71,8 +87,8 @@ void Endpoint_ClearEndpoints(void)
{
for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
{
USB_EndpointTable.Endpoints[EPNum].IN.CTRL = 0;
USB_EndpointTable.Endpoints[EPNum].OUT.CTRL = 0;
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].IN.CTRL = 0;
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].OUT.CTRL = 0;
}
}

View file

@ -88,14 +88,20 @@
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
/** Total number of endpoints (including the default control endpoint at address 0) which may
* be used in the device. Different USB AVR models support different amounts of endpoints,
* this value reflects the maximum number of endpoints for the currently selected AVR model.
*/
#define ENDPOINT_TOTAL_ENDPOINTS 16
#else
#define ENDPOINT_TOTAL_ENDPOINTS 1
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define _ENDPOINT_GET_MAXSIZE(EPIndex) 1023
#define _ENDPOINT_GET_BANKS(EPIndex) 2
#define ENDPOINT_DETAILS_MAXEP 16
/* Type Defines: */
typedef struct
{
@ -112,7 +118,7 @@
} Endpoint_FIFOPair_t;
/* External Variables: */
extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_DETAILS_MAXEP];
extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
extern volatile uint8_t USB_Endpoint_SelectedEndpoint;
extern volatile USB_EP_t* USB_Endpoint_SelectedHandle;
extern volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
@ -135,8 +141,7 @@
}
/* Function Prototypes: */
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number,
const uint8_t Direction,
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
const uint8_t Config,
const uint8_t Size);
void Endpoint_ClearEndpoints(void);
@ -144,23 +149,6 @@
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name Endpoint Bank Mode Masks */
//@{
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
* that the endpoint should have one single bank, which requires less USB FIFO memory but results
* in slower transfers as only one USB device (the AVR or the host) can access the endpoint's
* bank at the one time.
*/
#define ENDPOINT_BANK_SINGLE 0
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
* that the endpoint should have two banks, which requires more USB FIFO memory but results
* in faster transfers as one USB device (the AVR or the host) can access one bank while the other
* accesses the second bank.
*/
#define ENDPOINT_BANK_DOUBLE USB_EP_PINGPONG_bm
//@}
#if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
/** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
* value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
@ -168,34 +156,6 @@
#define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
#endif
/** Retrieves the maximum bank size in bytes of a given endpoint.
*
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
* defined by the preprocessor.
*
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
*/
#define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex)
/** Retrieves the total number of banks supported by the given endpoint.
*
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
* defined by the preprocessor.
*
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
*/
#define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex)
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
/** Total number of endpoints (including the default control endpoint at address 0) which may
* be used in the device. Different USB AVR models support different amounts of endpoints,
* this value reflects the maximum number of endpoints for the currently selected AVR model.
*/
#define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP
#else
#define ENDPOINT_TOTAL_ENDPOINTS 1
#endif
/* Enums: */
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
*
@ -221,54 +181,47 @@
};
/* Inline Functions: */
/** Selects the given endpoint number. If the address from the device descriptors is used, the
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
* number (and discarding the endpoint direction bit).
/** Selects the given endpoint address.
*
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
* Any endpoint operations which do not require the endpoint address to be indicated will operate on
* the currently selected endpoint.
*
* \param[in] EndpointNumber Endpoint number to select.
* \param[in] Address Endpoint address to select.
*/
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber);
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
static inline void Endpoint_SelectEndpoint(const uint8_t Address);
static inline void Endpoint_SelectEndpoint(const uint8_t Address)
{
USB_Endpoint_SelectedEndpoint = EndpointNumber;
uint8_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
if (EndpointNumber & ENDPOINT_DIR_IN)
USB_Endpoint_SelectedEndpoint = Address;
if (Address & ENDPOINT_DIR_IN)
{
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN;
USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].IN;
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].IN;
USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].IN;
}
else
{
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT;
USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT;
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].OUT;
USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].OUT;
}
}
/** Configures the specified endpoint number with the given endpoint type, direction, bank size
/** Configures the specified endpoint address with the given endpoint type, direction, bank size
* and banking mode. Once configured, the endpoint may be read from or written to, depending
* on its direction.
*
* \param[in] Number Endpoint number to configure. This must be more than 0 and less than
* \ref ENDPOINT_TOTAL_ENDPOINTS.
* \param[in] Address Endpoint address to configure.
*
* \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
* are available on Low Speed USB devices - refer to the USB 2.0 specification.
*
* \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN.
* All endpoints (except Control type) are unidirectional - data may only be read
* from or written to the endpoint bank based on its direction, not both.
*
* \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
* to the USB host, or after they have been received from the USB host (depending on
* the endpoint's data direction). The bank size must indicate the maximum packet size
* that the endpoint can handle.
*
* \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask.
* More banks uses more USB DPRAM, but offers better performance. Isochronous type
* endpoints <b>must</b> have at least two banks.
* \param[in] Banks Number of hardware banks to use for the endpoint being configured.
*
* \note The default control endpoint should not be manually configured by the user application, as
* it is automatically configured by the library internally.
@ -278,21 +231,19 @@
*
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
*/
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
const uint8_t Type,
const uint8_t Direction,
const uint16_t Size,
const uint8_t Banks) ATTR_ALWAYS_INLINE;
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
const uint8_t Type,
const uint8_t Direction,
const uint16_t Size,
const uint8_t Banks)
{
uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | Banks | Endpoint_BytesToEPSizeMask(Size));
uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | ((Banks > 1) ? USB_EP_PINGPONG_bm : 0) | Endpoint_BytesToEPSizeMask(Size));
// TODO - Fix once limitations are lifted
if ((Banks != ENDPOINT_BANK_SINGLE) || (Size > 64))
if ((Banks > 1) || (Size > 64))
return false;
switch (Type)
@ -309,9 +260,9 @@
}
if (Type == EP_TYPE_CONTROL)
Endpoint_ConfigureEndpoint_PRV(Number, (Direction ^ ENDPOINT_DIR_IN), EPConfigMask, Size);
Endpoint_ConfigureEndpoint_PRV(Address ^ ENDPOINT_DIR_IN, EPConfigMask, Size);
return Endpoint_ConfigureEndpoint_PRV(Number, Direction, EPConfigMask, Size);
return Endpoint_ConfigureEndpoint_PRV(Address, EPConfigMask, Size);
}
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
@ -327,8 +278,8 @@
}
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
* the currently selected endpoint number so that it can be restored after another endpoint has
* been manipulated.
* the currently selected endpoint so that it can be restored after another endpoint has been
* manipulated.
*
* \return Index of the currently selected endpoint.
*/
@ -341,15 +292,15 @@
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
* data In and Out pointers to the bank's contents.
*
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
* \param[in] Address Endpoint address whose FIFO buffers are to be reset.
*/
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber)
static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetEndpoint(const uint8_t Address)
{
if (EndpointNumber & ENDPOINT_DIR_IN)
USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN.Position = 0;
if (Address & ENDPOINT_DIR_IN)
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].IN.Position = 0;
else
USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
}
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
@ -388,10 +339,7 @@
static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsReadWriteAllowed(void)
{
if (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN)
return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
else
return (USB_Endpoint_SelectedFIFO->Position > 0);
return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
}
/** Determines if the currently selected endpoint is configured.
@ -404,32 +352,6 @@
return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) ? true : false);
}
/** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
* interrupt duration has elapsed. Which endpoints have interrupted can be determined by
* masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
*
* \return Mask whose bits indicate which endpoints have interrupted.
*/
static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointInterrupts(void)
{
return 0; // TODO
}
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints).
*
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
*
* \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
*/
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
{
(void)EndpointNumber;
return 0; // TODO
}
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
*
* \ingroup Group_EndpointPacketManagement_XMEGA
@ -800,6 +722,20 @@
#endif
/* Function Prototypes: */
/** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
* endpoints at the same time.
*
* \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
* control endpoint.
*
* \param[in] Table Pointer to a table of endpoint descriptions.
* \param[in] Entries Number of entries in the endpoint table to configure.
*
* \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
*/
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
const uint8_t Entries);
/** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
* with respect to the data direction. This is a convenience function which can be used to
* simplify user control request handling.

View file

@ -43,7 +43,8 @@ volatile uint8_t USB_CurrentMode = USB_MODE_None;
volatile uint8_t USB_Options;
#endif
USB_EndpointTable_t USB_EndpointTable ATTR_ALIGNED(4);
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */
uint8_t USB_EndpointTable[sizeof(USB_EndpointTable_t) + 1];
void USB_Init(
#if defined(USB_CAN_BE_BOTH)
@ -75,8 +76,9 @@ void USB_Init(
USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
NVM.CMD = 0;
USB.EPPTR = (intptr_t)&USB_EndpointTable;
USB.CTRLA = (USB_STFRNUM_bm | USB_MAXEP_gm);
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */
USB.EPPTR = ((intptr_t)&USB_EndpointTable[1] & ~(1 << 0));
USB.CTRLA = (USB_STFRNUM_bm | ((ENDPOINT_TOTAL_ENDPOINTS - 1) << USB_MAXEP_gp));
if ((USB_Options & USB_OPT_BUSEVENT_PRIHIGH) == USB_OPT_BUSEVENT_PRIHIGH)
USB.INTCTRLA = (3 << USB_INTLVL_gp);
@ -103,13 +105,17 @@ void USB_Disable(void)
void USB_ResetInterface(void)
{
#if defined(USB_DEVICE_OPT_FULLSPEED)
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp);
else
CLK.USBCTRL = (((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp);
#else
CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp);
#endif
if (USB_Options & USB_OPT_PLLCLKSRC)
CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
else
CLK.USBCTRL |= (CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
@ -172,8 +178,7 @@ static void USB_Init_Device(void)
USB_Device_SetFullSpeed();
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
ENDPOINT_BANK_SINGLE);
USB_Device_ControlEndpointSize, 1);
USB_INT_Enable(USB_INT_BUSEVENTI);

View file

@ -69,7 +69,7 @@
} ATTR_PACKED USB_EndpointTable_t;
/* External Variables: */
extern USB_EndpointTable_t USB_EndpointTable;
extern uint8_t USB_EndpointTable[];
#endif
@ -95,7 +95,7 @@
#error F_USB is not defined. You must define F_USB to the frequency of the unprescaled USB controller clock in your project makefile.
#endif
#if (F_USB % 6000000)
#if ((F_USB % 6000000) || (F_USB < 6000000))
#error Invalid F_USB specified. F_USB must be a multiple of 6MHz for USB Low Speed operation, and a multiple of 48MHz for Full Speed operation.
#endif

View file

@ -97,8 +97,7 @@ ISR(USB_BUSEVENT_vect)
Endpoint_ClearEndpoints();
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
ENDPOINT_BANK_SINGLE);
USB_Device_ControlEndpointSize, 1);
EVENT_USB_Device_Reset();
}