Added new USB_Device_GetFrameNumber() and USB_Host_GetFrameNumber() functions to retrieve the current USB frame number.

Added new USB_Host_EnableSOFEvents(), USB_Host_DisableSOFEvents() and EVENT_USB_Host_StartOfFrame() for the user application handling of USB Start of Frame events while in USB Host mode.

Changed over all demos, drivers and internal functions to use the current frame number over the Start of Frame flag where possible to free up the Start of Frame flag for interrupt use in the user application.
pull/1469/head
Dean Camera 14 years ago
parent 0174d8ea70
commit 18cbd31605

@ -111,6 +111,7 @@ static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* const SCSICommandBlo
static uint8_t MassStore_WaitForDataReceived(void) static uint8_t MassStore_WaitForDataReceived(void)
{ {
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
/* Select the IN data pipe for data reception */ /* Select the IN data pipe for data reception */
Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);
@ -119,11 +120,13 @@ static uint8_t MassStore_WaitForDataReceived(void)
/* Wait until data received in the IN pipe */ /* Wait until data received in the IN pipe */
while (!(Pipe_IsINReceived())) while (!(Pipe_IsINReceived()))
{ {
uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
/* Check to see if a new frame has been issued (1ms elapsed) */ /* Check to see if a new frame has been issued (1ms elapsed) */
if (USB_INT_HasOccurred(USB_INT_HSOFI)) if (CurrentFrameNumber != PreviousFrameNumber)
{ {
/* Clear the flag and decrement the timeout period counter */ /* Save the new frame number and decrement the timeout period */
USB_INT_Clear(USB_INT_HSOFI); PreviousFrameNumber = CurrentFrameNumber;
TimeoutMSRem--; TimeoutMSRem--;
/* Check to see if the timeout period for the command has elapsed */ /* Check to see if the timeout period for the command has elapsed */

@ -109,28 +109,28 @@ uint8_t SImage_ReceiveEventHeader(void)
uint8_t SImage_ReceiveBlockHeader(void) uint8_t SImage_ReceiveBlockHeader(void)
{ {
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
/* Unfreeze the data IN pipe */ /* Unfreeze the data IN pipe */
Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE); Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);
Pipe_Unfreeze(); Pipe_Unfreeze();
/* Wait until data received on the IN pipe */ /* Wait until data received on the IN pipe */
while (!(Pipe_IsReadWriteAllowed())) while (!(Pipe_IsINReceived()))
{ {
uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
/* Check to see if a new frame has been issued (1ms elapsed) */ /* Check to see if a new frame has been issued (1ms elapsed) */
if (USB_INT_HasOccurred(USB_INT_HSOFI)) if (CurrentFrameNumber != PreviousFrameNumber)
{ {
/* Clear the flag and decrement the timeout period counter */ /* Save the new frame number and decrement the timeout period */
USB_INT_Clear(USB_INT_HSOFI); PreviousFrameNumber = CurrentFrameNumber;
TimeoutMSRem--; TimeoutMSRem--;
/* Check to see if the timeout period for the command has elapsed */ /* Check to see if the timeout period for the command has elapsed */
if (!(TimeoutMSRem)) if (!(TimeoutMSRem))
{
/* Return error code */
return PIPE_RWSTREAM_Timeout; return PIPE_RWSTREAM_Timeout;
} }
}
Pipe_Freeze(); Pipe_Freeze();
Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE); Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);

@ -167,18 +167,20 @@ static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInf
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
{ {
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber); Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipeNumber);
Pipe_Unfreeze(); Pipe_Unfreeze();
while (!(Pipe_IsINReceived())) while (!(Pipe_IsINReceived()))
{ {
if (USB_INT_HasOccurred(USB_INT_HSOFI)) uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{ {
USB_INT_Clear(USB_INT_HSOFI); PreviousFrameNumber = CurrentFrameNumber;
TimeoutMSRem--;
if (!(TimeoutMSRem)) if (!(TimeoutMSRem--))
return PIPE_RWSTREAM_Timeout; return PIPE_RWSTREAM_Timeout;
} }

@ -180,6 +180,7 @@ uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfac
SI_PIMA_Container_t* const PIMAHeader) SI_PIMA_Container_t* const PIMAHeader)
{ {
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS; uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive)) if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
return PIPE_RWSTREAM_DeviceDisconnected; return PIPE_RWSTREAM_DeviceDisconnected;
@ -187,18 +188,17 @@ uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfac
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber); Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
Pipe_Unfreeze(); Pipe_Unfreeze();
while (!(Pipe_IsReadWriteAllowed())) while (!(Pipe_IsINReceived()))
{ {
if (USB_INT_HasOccurred(USB_INT_HSOFI)) uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
{
USB_INT_Clear(USB_INT_HSOFI);
TimeoutMSRem--;
if (!(TimeoutMSRem)) if (CurrentFrameNumber != PreviousFrameNumber)
{ {
PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--))
return PIPE_RWSTREAM_Timeout; return PIPE_RWSTREAM_Timeout;
} }
}
Pipe_Freeze(); Pipe_Freeze();
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber); Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);

@ -180,6 +180,23 @@
*/ */
void EVENT_USB_Host_DeviceEnumerationComplete(void); void EVENT_USB_Host_DeviceEnumerationComplete(void);
/** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
* frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate
* millisecond timer source when the USB bus is not suspended while in host mode.
*
* This event is time-critical; it is run once per millisecond and thus long handlers will significantly
* degrade device performance. This event should only be enabled when needed to reduce device wake-ups.
*
* \note This event is not normally active - it must be manually enabled and disabled via the
* \ref USB_Host_EnableSOFEvents() and \ref USB_Host_DisableSOFEvents() commands after enumeration of
* a USB device.
* \n\n
*
* \note This event does not exist if the USB_DEVICE_ONLY token is supplied to the compiler (see
* \ref Group_USBManagement documentation).
*/
void EVENT_USB_Host_StartOfFrame(void);
/** Event for USB device connection. This event fires when the AVR in device mode and the device is connected /** Event for USB device connection. This event fires when the AVR in device mode and the device is connected
* to a host, beginning the enumeration process, measured by a rising level on the AVR's VBUS pin. * to a host, beginning the enumeration process, measured by a rising level on the AVR's VBUS pin.
* *
@ -339,6 +356,7 @@
void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
const uint8_t SubErrorCode) const uint8_t SubErrorCode)
ATTR_WEAK ATTR_ALIAS(USB_Event_Stub); ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
void EVENT_USB_Host_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
#endif #endif
#if defined(USB_CAN_BE_DEVICE) #if defined(USB_CAN_BE_DEVICE)

@ -140,6 +140,14 @@
}; };
/* Inline Functions: */ /* Inline Functions: */
/** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host)
* the frame number is incremented by one.
*/
static inline uint16_t USB_Device_GetFrameNumber(void)
{
return UDFNUM;
}
/** Enables the device mode Start Of Frame events. When enabled, this causes the /** Enables the device mode Start Of Frame events. When enabled, this causes the
* \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus, * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
* at the start of each USB frame when enumerated in device mode. * at the start of each USB frame when enumerated in device mode.

@ -142,6 +142,8 @@ uint8_t Endpoint_WaitUntilReady(void)
uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#endif #endif
uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
for (;;) for (;;)
{ {
if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN) if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
@ -162,9 +164,11 @@ uint8_t Endpoint_WaitUntilReady(void)
else if (Endpoint_IsStalled()) else if (Endpoint_IsStalled())
return ENDPOINT_READYWAIT_EndpointStalled; return ENDPOINT_READYWAIT_EndpointStalled;
if (USB_INT_HasOccurred(USB_INT_SOFI)) uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{ {
USB_INT_Clear(USB_INT_SOFI); PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--)) if (!(TimeoutMSRem--))
return ENDPOINT_READYWAIT_Timeout; return ENDPOINT_READYWAIT_Timeout;

@ -196,14 +196,17 @@ uint8_t USB_Host_WaitMS(uint8_t MS)
{ {
bool BusSuspended = USB_Host_IsBusSuspended(); bool BusSuspended = USB_Host_IsBusSuspended();
uint8_t ErrorCode = HOST_WAITERROR_Successful; uint8_t ErrorCode = HOST_WAITERROR_Successful;
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
USB_Host_ResumeBus(); USB_Host_ResumeBus();
while (MS) while (MS)
{ {
if (USB_INT_HasOccurred(USB_INT_HSOFI)) uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{ {
USB_INT_Clear(USB_INT_HSOFI); PreviousFrameNumber = CurrentFrameNumber;
MS--; MS--;
} }
@ -245,9 +248,11 @@ static void USB_Host_ResetDevice(void)
USB_Host_ResetBus(); USB_Host_ResetBus();
while (!(USB_Host_IsBusResetComplete())); while (!(USB_Host_IsBusResetComplete()));
USB_Host_ResumeBus(); USB_Host_ResumeBus();
bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
USB_INT_Disable(USB_INT_HSOFI);
USB_INT_Clear(USB_INT_HSOFI); USB_INT_Clear(USB_INT_HSOFI);
for (uint8_t MSRem = 10; MSRem != 0; MSRem--) for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
@ -267,6 +272,9 @@ static void USB_Host_ResetDevice(void)
_delay_ms(1); _delay_ms(1);
} }
if (HSOFIEnabled)
USB_INT_Enable(USB_INT_HSOFI);
if (BusSuspended) if (BusSuspended)
USB_Host_SuspendBus(); USB_Host_SuspendBus();

@ -245,6 +245,33 @@
}; };
/* Inline Functions: */ /* Inline Functions: */
/** Returns the current USB frame number, when in host mode. Every millisecond the USB bus is active (i.e. not suspended)
* the frame number is incremented by one.
*/
static inline uint16_t USB_Host_GetFrameNumber(void)
{
return UHFNUM;
}
/** Enables the host mode Start Of Frame events. When enabled, this causes the
* \ref EVENT_USB_Host_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
* at the start of each USB frame when a device is enumerated while in host mode.
*/
static inline void USB_Host_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_EnableSOFEvents(void)
{
USB_INT_Enable(USB_INT_HSOFI);
}
/** Disables the host mode Start Of Frame events. When disabled, this stops the firing of the
* \ref EVENT_USB_Host_StartOfFrame() event when enumerated in host mode.
*/
static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_DisableSOFEvents(void)
{
USB_INT_Disable(USB_INT_HSOFI);
}
/** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host. /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
* USB bus resets leave the default control pipe configured (if already configured). * USB bus resets leave the default control pipe configured (if already configured).
* *

@ -134,6 +134,8 @@ uint8_t Pipe_WaitUntilReady(void)
uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS; uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
#endif #endif
uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
for (;;) for (;;)
{ {
if (Pipe_GetPipeToken() == PIPE_TOKEN_IN) if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
@ -152,9 +154,11 @@ uint8_t Pipe_WaitUntilReady(void)
else if (USB_HostState == HOST_STATE_Unattached) else if (USB_HostState == HOST_STATE_Unattached)
return PIPE_READYWAIT_DeviceDisconnected; return PIPE_READYWAIT_DeviceDisconnected;
if (USB_INT_HasOccurred(USB_INT_HSOFI)) uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
if (CurrentFrameNumber != PreviousFrameNumber)
{ {
USB_INT_Clear(USB_INT_HSOFI); PreviousFrameNumber = CurrentFrameNumber;
if (!(TimeoutMSRem--)) if (!(TimeoutMSRem--))
return PIPE_READYWAIT_Timeout; return PIPE_READYWAIT_Timeout;

@ -209,6 +209,13 @@ ISR(USB_GEN_vect, ISR_BLOCK)
USB_ResetInterface(); USB_ResetInterface();
} }
if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))
{
USB_INT_Clear(USB_INT_HSOFI);
EVENT_USB_Host_StartOfFrame();
}
#endif #endif
#if defined(USB_CAN_BE_BOTH) #if defined(USB_CAN_BE_BOTH)

@ -13,6 +13,9 @@
* - Moved the Pipe and Endpoint stream related code to two new USB library core source files EndpointStream.c and PipeStream.c * - Moved the Pipe and Endpoint stream related code to two new USB library core source files EndpointStream.c and PipeStream.c
* - Added board hardware driver support for the Olimex AVR-USB-162 development board (thanks to Steve Fawcett) * - Added board hardware driver support for the Olimex AVR-USB-162 development board (thanks to Steve Fawcett)
* - Added board hardware driver support for the USBFOO development board * - Added board hardware driver support for the USBFOO development board
* - Added new USB_Device_GetFrameNumber() and USB_Host_GetFrameNumber() functions to retrieve the current USB frame number
* - Added new USB_Host_EnableSOFEvents(), USB_Host_DisableSOFEvents() and EVENT_USB_Host_StartOfFrame() for the user application
* handling of USB Start of Frame events while in USB Host mode
* *
* <b>Changed:</b> * <b>Changed:</b>
* - Removed complicated logic for the Endpoint_ConfigureEndpoint() function to use inlined or function called versions * - Removed complicated logic for the Endpoint_ConfigureEndpoint() function to use inlined or function called versions
@ -29,6 +32,8 @@
* - Changed the signature of the CALLBACK_USB_GetDescriptor() callback function so that the descriptor pointer is const, to remove * - Changed the signature of the CALLBACK_USB_GetDescriptor() callback function so that the descriptor pointer is const, to remove
* the need for extra casting inside the callback (thanks to Jonathan Kollasch) * the need for extra casting inside the callback (thanks to Jonathan Kollasch)
* - Reduced HOST_DEVICE_SETTLE_DELAY_MS to 1000ms down from 1500ms to improve device compatibility while in USB Host mode * - Reduced HOST_DEVICE_SETTLE_DELAY_MS to 1000ms down from 1500ms to improve device compatibility while in USB Host mode
* - Changed over all demos, drivers and internal functions to use the current frame number over the Start of Frame flag where possible
* to free up the Start of Frame flag for interrupt use in the user application
* *
* <b>Fixed:</b> * <b>Fixed:</b>
* - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist * - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist

Loading…
Cancel
Save