Add FreeRTOS-Plus directory.

This commit is contained in:
Richard Barry 2012-08-11 21:34:11 +00:00
parent 7bd5f21ad5
commit f508a5f653
6798 changed files with 134949 additions and 19 deletions

View file

@ -0,0 +1,48 @@
[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%ATMEL%
LayoutFile=layout.inf
DriverVer=10/15/1999,5.0.2153.1
[MANUFACTURER]
%FreeRTOS%=FreeRTOS
[FreeRTOS]
%FreeRTOS_CDC%=Reader,USB\VID_EB03&PID_0920
[Reader_Install.NTx86]
;Windows2000
[DestinationDirs]
DefaultDestDir=12
Reader.NT.Copy=12
[Reader.NT]
CopyFiles=Reader.NT.Copy
AddReg=Reader.NT.AddReg
[Reader.NT.Copy]
usbser.sys
[Reader.NT.AddReg]
HKR,,NTMPDriver,,*ntkern
HKR,,NTMPDriver,,usbser.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[Reader.NT.Services]
AddService = usbser, 0x00000002,Service_Inst
[Service_Inst]
DisplayName = %Serial.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary = %12%\usbser.sys
LoadOrderGroup = Base
[Strings]
FreeRTOS = "FreeRTOS"
FreeRTOS_CDC = "FreeRTOS CDC Demo"
Serial.SvcDesc = "USB Serial emulation driver"

View file

@ -0,0 +1,897 @@
/*
FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
/*
USB Communications Device Class driver.
Implements task vUSBCDCTask and provides an Abstract Control Model serial
interface. Control is through endpoint 0, device-to-host notification is
provided by interrupt-in endpoint 3, and raw data is transferred through
bulk endpoints 1 and 2.
- developed from original FreeRTOS HID example by Scott Miller
- modified to support 3.2 GCC by najay
*/
/* Standard includes. */
#include <string.h>
#include <stdio.h>
/* Demo board includes. */
#include "Board.h"
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* Demo app includes. */
#include "USB-CDC.h"
#include "descriptors.h"
#define usbNO_BLOCK ( ( portTickType ) 0 )
/* Reset all endpoints */
static void prvResetEndPoints( void );
/* Clear pull up resistor to detach device from host */
static void vDetachUSBInterface( void );
/* Set up interface and initialize variables */
static void vInitUSBInterface( void );
/* Handle control endpoint events. */
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage );
/* Handle standard device requests. */
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest );
/* Handle standard interface requests. */
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest );
/* Handle endpoint requests. */
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest );
/* Handle class interface requests. */
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest );
/* Prepare control data transfer. prvSendNextSegment starts transfer. */
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthLeftToSend, long lSendingDescriptor );
/* Send next segment of data for the control transfer */
static void prvSendNextSegment( void );
/* Send stall - used to respond to unsupported requests */
static void prvSendStall( void );
/* Send a zero-length (null) packet */
static void prvSendZLP( void );
/* Handle requests for standard interface descriptors */
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest );
/*------------------------------------------------------------*/
/* File scope static variables */
static unsigned char ucUSBConfig = ( unsigned char ) 0;
static unsigned long ulReceivedAddress = ( unsigned long ) 0;
static eDRIVER_STATE eDriverState = eNOTHING;
/* Incoming and outgoing control data structures */
static xCONTROL_MESSAGE pxControlTx;
static xCONTROL_MESSAGE pxControlRx;
/* Queue holding pointers to pending messages */
xQueueHandle xUSBInterruptQueue;
/* Queues used to hold received characters, and characters waiting to be
transmitted. Rx queue must be larger than FIFO size. */
static xQueueHandle xRxCDC;
static xQueueHandle xTxCDC;
/* Line coding - 115,200 baud, N-8-1 */
static const unsigned char pxLineCoding[] = { 0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08 };
/* Status variables. */
static unsigned char ucControlState;
static unsigned int uiCurrentBank;
/*------------------------------------------------------------*/
void vUSBCDCTask( void *pvParameters )
{
xISRStatus *pxMessage;
unsigned long ulStatus;
unsigned long ulRxBytes;
unsigned char ucByte;
portBASE_TYPE xByte;
( void ) pvParameters;
/* Disconnect USB device from hub. For debugging - causes host to register reset */
portENTER_CRITICAL();
vDetachUSBInterface();
portEXIT_CRITICAL();
vTaskDelay( portTICK_RATE_MS * 60 );
/* Init USB interface */
portENTER_CRITICAL();
vInitUSBInterface();
portEXIT_CRITICAL();
/* Main task loop. Process incoming endpoint 0 interrupts, handle data transfers. */
for( ;; )
{
/* Look for data coming from the ISR. */
if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORTEST_DELAY ) )
{
if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
{
/* All endpoint 0 interrupts are handled here. */
prvProcessEndPoint0Interrupt( pxMessage );
}
if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
{
/* End of bus reset - reset the endpoints and de-configure. */
prvResetEndPoints();
}
}
/* See if we're ready to send and receive data. */
if( eDriverState == eREADY_TO_SEND && ucControlState )
{
if( ( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] & AT91C_UDP_TXPKTRDY) ) && uxQueueMessagesWaiting( xTxCDC ) )
{
for( xByte = 0; xByte < 64; xByte++ )
{
if( !xQueueReceive( xTxCDC, &ucByte, 0 ) )
{
/* No data buffered to transmit. */
break;
}
/* Got a byte to transmit. */
AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_2 ] = ucByte;
}
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] |= AT91C_UDP_TXPKTRDY;
}
/* Check for incoming data (host-to-device) on endpoint 1. */
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) )
{
ulRxBytes = (AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] >> 16) & usbRX_COUNT_MASK;
/* Only process FIFO if there's room to store it in the queue */
if( ulRxBytes < ( USB_CDC_QUEUE_SIZE - uxQueueMessagesWaiting( xRxCDC ) ) )
{
while( ulRxBytes-- )
{
ucByte = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ];
xQueueSend( xRxCDC, &ucByte, 0 );
}
/* Release the FIFO */
portENTER_CRITICAL();
{
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
usbCSR_CLEAR_BIT( &ulStatus, uiCurrentBank );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
}
portEXIT_CRITICAL();
/* Re-enable endpoint 1's interrupts */
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
/* Update the current bank in use */
if( uiCurrentBank == AT91C_UDP_RX_DATA_BK0 )
{
uiCurrentBank = AT91C_UDP_RX_DATA_BK1;
}
else
{
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
}
}
else
{
break;
}
}
}
}
}
/*------------------------------------------------------------*/
void vUSBSendByte( char cByte )
{
/* Queue the byte to be sent. The USB task will send it. */
xQueueSend( xTxCDC, &cByte, usbNO_BLOCK );
}
/*------------------------------------------------------------*/
static void prvSendZLP( void )
{
unsigned long ulStatus;
/* Wait until the FIFO is free - even though we are not going to use it.
THERE IS NO TIMEOUT HERE! */
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
{
vTaskDelay( usbSHORTEST_DELAY );
}
portENTER_CRITICAL();
{
/* Cancel any further pending data */
pxControlTx.ulTotalDataLength = pxControlTx.ulNextCharIndex;
/* Set the TXPKTRDY bit to cause a transmission with no data. */
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
usbCSR_SET_BIT( &ulStatus, AT91C_UDP_TXPKTRDY );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
}
portEXIT_CRITICAL();
}
/*------------------------------------------------------------*/
static void prvSendStall( void )
{
unsigned long ulStatus;
portENTER_CRITICAL();
{
/* Force a stall by simply setting the FORCESTALL bit in the CSR. */
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
}
portEXIT_CRITICAL();
}
/*------------------------------------------------------------*/
static void prvResetEndPoints( void )
{
unsigned long ulTemp;
eDriverState = eJUST_RESET;
ucControlState = 0;
/* Reset all the end points. */
AT91C_BASE_UDP->UDP_RSTEP = usbEND_POINT_RESET_MASK;
AT91C_BASE_UDP->UDP_RSTEP = ( unsigned long ) 0x00;
/* Enable data to be sent and received. */
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
/* Repair the configuration end point. */
portENTER_CRITICAL();
{
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
usbCSR_SET_BIT( &ulTemp, ( ( unsigned long ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
}
portEXIT_CRITICAL();
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
}
/*------------------------------------------------------------*/
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
{
static xUSB_REQUEST xRequest;
unsigned long ulRxBytes;
/* Get number of bytes received, if any */
ulRxBytes = pxMessage->ulCSR0 >> 16;
ulRxBytes &= usbRX_COUNT_MASK;
if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
{
/* We received a TX complete interrupt. What we do depends on
what we sent to get this interrupt. */
if( eDriverState == eJUST_GOT_CONFIG )
{
/* We sent an acknowledgement of a SET_CONFIG request. We
are now at the end of the enumeration.
TODO: Config 0 sets unconfigured state, should enter Address state.
Request for unsupported config should stall. */
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
/* Set up endpoints */
portENTER_CRITICAL();
{
unsigned long ulTemp;
/* Set endpoint 1 to bulk-out */
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
/* Set endpoint 2 to bulk-in */
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ];
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] = ulTemp;
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT2;
/* Set endpoint 3 to interrupt-in, enable it, and enable interrupts */
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ];
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] = ulTemp;
/*AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT3 ); */
}
portEXIT_CRITICAL();
eDriverState = eREADY_TO_SEND;
}
else if( eDriverState == eJUST_GOT_ADDRESS )
{
/* We sent an acknowledgement of a SET_ADDRESS request. Move
to the addressed state. */
if( ulReceivedAddress != ( unsigned long ) 0 )
{
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
}
else
{
AT91C_BASE_UDP->UDP_GLBSTATE = 0;
}
AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );
eDriverState = eNOTHING;
}
else
{
/* The TXCOMP was not for any special type of transmission. See
if there is any more data to send. */
prvSendNextSegment();
}
}
if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
{
/* Received a control data packet. May be a 0-length ACK or a data stage. */
unsigned char ucBytesToGet;
/* Got data. Cancel any outgoing data. */
pxControlTx.ulNextCharIndex = pxControlTx.ulTotalDataLength;
/* Determine how many bytes we need to receive. */
ucBytesToGet = pxControlRx.ulTotalDataLength - pxControlRx.ulNextCharIndex;
if( ucBytesToGet > ulRxBytes )
{
ucBytesToGet = ulRxBytes;
}
/* If we're not expecting any data, it's an ack - just quit now. */
if( !ucBytesToGet )
{
return;
}
/* Get the required data and update the index. */
memcpy( pxControlRx.ucBuffer, pxMessage->ucFifoData, ucBytesToGet );
pxControlRx.ulNextCharIndex += ucBytesToGet;
}
if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
{
/* Received a SETUP packet. May be followed by data packets. */
if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
{
/* Create an xUSB_REQUEST variable from the raw bytes array. */
xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];
xRequest.usValue = pxMessage->ucFifoData[ usbVALUE_HIGH_BYTE ];
xRequest.usValue <<= 8;
xRequest.usValue |= pxMessage->ucFifoData[ usbVALUE_LOW_BYTE ];
xRequest.usIndex = pxMessage->ucFifoData[ usbINDEX_HIGH_BYTE ];
xRequest.usIndex <<= 8;
xRequest.usIndex |= pxMessage->ucFifoData[ usbINDEX_LOW_BYTE ];
xRequest.usLength = pxMessage->ucFifoData[ usbLENGTH_HIGH_BYTE ];
xRequest.usLength <<= 8;
xRequest.usLength |= pxMessage->ucFifoData[ usbLENGTH_LOW_BYTE ];
pxControlRx.ulNextCharIndex = 0;
if( ! (xRequest.ucReqType & 0x80) ) /* Host-to-Device transfer, may need to get data first */
{
if( xRequest.usLength > usbMAX_CONTROL_MESSAGE_SIZE )
{
/* Too big! No space for control data, stall and abort. */
prvSendStall();
return;
}
pxControlRx.ulTotalDataLength = xRequest.usLength;
}
else
{
/* We're sending the data, don't wait for any. */
pxControlRx.ulTotalDataLength = 0;
}
}
}
/* See if we've got a pending request and all its associated data ready */
if( ( pxMessage->ulCSR0 & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP ) )
&& ( pxControlRx.ulNextCharIndex >= pxControlRx.ulTotalDataLength ) )
{
unsigned char ucRequest;
/* Manipulate the ucRequestType and the ucRequest parameters to
generate a zero based request selection. This is just done to
break up the requests into subsections for clarity. The
alternative would be to have more huge switch statement that would
be difficult to optimise. */
ucRequest = ( ( xRequest.ucReqType & 0x60 ) >> 3 );
ucRequest |= ( xRequest.ucReqType & 0x03 );
switch( ucRequest )
{
case usbSTANDARD_DEVICE_REQUEST:
/* Standard Device request */
prvHandleStandardDeviceRequest( &xRequest );
break;
case usbSTANDARD_INTERFACE_REQUEST:
/* Standard Interface request */
prvHandleStandardInterfaceRequest( &xRequest );
break;
case usbSTANDARD_END_POINT_REQUEST:
/* Standard Endpoint request */
prvHandleStandardEndPointRequest( &xRequest );
break;
case usbCLASS_INTERFACE_REQUEST:
/* Class Interface request */
prvHandleClassInterfaceRequest( &xRequest );
break;
default: /* This is not something we want to respond to. */
prvSendStall();
}
}
}
/*------------------------------------------------------------*/
static void prvGetStandardDeviceDescriptor( xUSB_REQUEST *pxRequest )
{
/* The type is in the high byte. Return whatever has been requested. */
switch( ( pxRequest->usValue & 0xff00 ) >> 8 )
{
case usbDESCRIPTOR_TYPE_DEVICE:
prvSendControlData( ( unsigned char * ) &pxDeviceDescriptor, pxRequest->usLength, sizeof( pxDeviceDescriptor ), pdTRUE );
break;
case usbDESCRIPTOR_TYPE_CONFIGURATION:
prvSendControlData( ( unsigned char * ) &( pxConfigDescriptor ), pxRequest->usLength, sizeof( pxConfigDescriptor ), pdTRUE );
break;
case usbDESCRIPTOR_TYPE_STRING:
/* The index to the string descriptor is the lower byte. */
switch( pxRequest->usValue & 0xff )
{
case usbLANGUAGE_STRING:
prvSendControlData( ( unsigned char * ) &pxLanguageStringDescriptor, pxRequest->usLength, sizeof(pxLanguageStringDescriptor), pdTRUE );
break;
case usbMANUFACTURER_STRING:
prvSendControlData( ( unsigned char * ) &pxManufacturerStringDescriptor, pxRequest->usLength, sizeof( pxManufacturerStringDescriptor ), pdTRUE );
break;
case usbPRODUCT_STRING:
prvSendControlData( ( unsigned char * ) &pxProductStringDescriptor, pxRequest->usLength, sizeof( pxProductStringDescriptor ), pdTRUE );
break;
case usbCONFIGURATION_STRING:
prvSendControlData( ( unsigned char * ) &pxConfigurationStringDescriptor, pxRequest->usLength, sizeof( pxConfigurationStringDescriptor ), pdTRUE );
break;
case usbINTERFACE_STRING:
prvSendControlData( ( unsigned char * ) &pxInterfaceStringDescriptor, pxRequest->usLength, sizeof( pxInterfaceStringDescriptor ), pdTRUE );
break;
default:
prvSendStall();
break;
}
break;
default:
prvSendStall();
break;
}
}
/*------------------------------------------------------------*/
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest )
{
unsigned short usStatus = 0;
switch( pxRequest->ucRequest )
{
case usbGET_STATUS_REQUEST:
/* Just send two byte dummy status. */
prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
break;
case usbGET_DESCRIPTOR_REQUEST:
/* Send device descriptor */
prvGetStandardDeviceDescriptor( pxRequest );
break;
case usbGET_CONFIGURATION_REQUEST:
/* Send selected device configuration */
prvSendControlData( ( unsigned char * ) &ucUSBConfig, sizeof( ucUSBConfig ), sizeof( ucUSBConfig ), pdFALSE );
break;
case usbSET_FEATURE_REQUEST:
prvSendZLP();
break;
case usbSET_ADDRESS_REQUEST:
/* Get assigned address and send ack, but don't implement new address until we get a TXCOMP */
prvSendZLP();
eDriverState = eJUST_GOT_ADDRESS;
ulReceivedAddress = ( unsigned long ) pxRequest->usValue;
break;
case usbSET_CONFIGURATION_REQUEST:
/* Ack SET_CONFIGURATION request, but don't implement until TXCOMP */
ucUSBConfig = ( unsigned char ) ( pxRequest->usValue & 0xff );
eDriverState = eJUST_GOT_CONFIG;
prvSendZLP();
break;
default:
/* Any unsupported request results in a STALL response. */
prvSendStall();
break;
}
}
/*------------------------------------------------------------*/
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest )
{
switch( pxRequest->ucRequest )
{
case usbSEND_ENCAPSULATED_COMMAND:
prvSendStall();
break;
case usbGET_ENCAPSULATED_RESPONSE:
prvSendStall();
break;
case usbSET_LINE_CODING:
/* Set line coding - baud rate, data bits, parity, stop bits */
prvSendZLP();
memcpy( ( void * ) pxLineCoding, pxControlRx.ucBuffer, sizeof( pxLineCoding ) );
break;
case usbGET_LINE_CODING:
/* Get line coding */
prvSendControlData( (unsigned char *) &pxLineCoding, pxRequest->usLength, sizeof( pxLineCoding ), pdFALSE );
break;
case usbSET_CONTROL_LINE_STATE:
/* D0: 1=DTR, 0=No DTR, D1: 1=Activate Carrier, 0=Deactivate carrier (RTS, half-duplex) */
prvSendZLP();
ucControlState = pxRequest->usValue;
break;
default:
prvSendStall();
break;
}
}
/*------------------------------------------------------------*/
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest )
{
switch( ( pxRequest->usValue & ( unsigned short ) 0xff00 ) >> 8 )
{
default:
prvSendStall();
break;
}
}
/*-----------------------------------------------------------*/
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest )
{
unsigned short usStatus = 0;
switch( pxRequest->ucRequest )
{
case usbGET_STATUS_REQUEST:
/* Send dummy 2 bytes. */
prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
break;
case usbGET_DESCRIPTOR_REQUEST:
prvGetStandardInterfaceDescriptor( pxRequest );
break;
/* This minimal implementation does not respond to these. */
case usbGET_INTERFACE_REQUEST:
case usbSET_FEATURE_REQUEST:
case usbSET_INTERFACE_REQUEST:
default:
prvSendStall();
break;
}
}
/*-----------------------------------------------------------*/
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest )
{
switch( pxRequest->ucRequest )
{
/* This minimal implementation does not expect to respond to these. */
case usbGET_STATUS_REQUEST:
case usbCLEAR_FEATURE_REQUEST:
case usbSET_FEATURE_REQUEST:
default:
prvSendStall();
break;
}
}
/*-----------------------------------------------------------*/
static void vDetachUSBInterface( void)
{
/* Setup the PIO for the USB pull up resistor. */
AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
/* Disable pull up */
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
}
/*-----------------------------------------------------------*/
static void vInitUSBInterface( void )
{
extern void ( vUSB_ISR_Wrapper )( void );
/* Create the queue used to communicate between the USB ISR and task. */
xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
/* Create the queues used to hold Rx and Tx characters. */
xRxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE, ( unsigned char ) sizeof( signed char ) );
xTxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE + 1, ( unsigned char ) sizeof( signed char ) );
if( (!xUSBInterruptQueue) || (!xRxCDC) || (!xTxCDC) )
{
/* Not enough RAM to create queues!. */
return;
}
/* Initialise a few state variables. */
pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
pxControlRx.ulNextCharIndex = ( unsigned long ) 0;
ucUSBConfig = ( unsigned char ) 0;
eDriverState = eNOTHING;
ucControlState = 0;
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
/* HARDWARE SETUP */
/* Set the PLL USB Divider */
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
/* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
/* Setup the PIO for the USB pull up resistor. */
AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
/* Start without the pullup - this will get set at the end of this
function. */
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
/* When using the USB debugger the peripheral registers do not always get
set to the correct default values. To make sure set the relevant registers
manually here. */
AT91C_BASE_UDP->UDP_IDR = ( unsigned long ) 0xffffffff;
AT91C_BASE_UDP->UDP_ICR = ( unsigned long ) 0xffffffff;
AT91C_BASE_UDP->UDP_CSR[ 0 ] = ( unsigned long ) 0x00;
AT91C_BASE_UDP->UDP_CSR[ 1 ] = ( unsigned long ) 0x00;
AT91C_BASE_UDP->UDP_CSR[ 2 ] = ( unsigned long ) 0x00;
AT91C_BASE_UDP->UDP_CSR[ 3 ] = ( unsigned long ) 0x00;
AT91C_BASE_UDP->UDP_GLBSTATE = 0;
AT91C_BASE_UDP->UDP_FADDR = 0;
/* Enable the transceiver. */
AT91C_UDP_TRANSCEIVER_ENABLE = 0;
/* Enable the USB interrupts - other interrupts get enabled as the
enumeration process progresses. */
AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
/* Wait a short while before making our presence known. */
vTaskDelay( usbINIT_DELAY );
AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
}
/*-----------------------------------------------------------*/
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthToSend, long lSendingDescriptor )
{
if( ( ( unsigned long ) usRequestedLength < ulLengthToSend ) )
{
/* Cap the data length to that requested. */
ulLengthToSend = ( unsigned short ) usRequestedLength;
}
else if( ( ulLengthToSend < ( unsigned long ) usRequestedLength ) && lSendingDescriptor )
{
/* We are sending a descriptor. If the descriptor is an exact
multiple of the FIFO length then it will have to be terminated
with a NULL packet. Set the state to indicate this if
necessary. */
if( ( ulLengthToSend % usbFIFO_LENGTH ) == 0 )
{
eDriverState = eSENDING_EVEN_DESCRIPTOR;
}
}
/* Here we assume that the previous message has been sent. THERE IS NO
BUFFER OVERFLOW PROTECTION HERE.
Copy the data to send into the buffer as we cannot send it all at once
(if it is greater than 8 bytes in length). */
memcpy( pxControlTx.ucBuffer, pucData, ulLengthToSend );
/* Reinitialise the buffer index so we start sending from the start of
the data. */
pxControlTx.ulTotalDataLength = ulLengthToSend;
pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
/* Send the first 8 bytes now. The rest will get sent in response to
TXCOMP interrupts. */
prvSendNextSegment();
}
/*-----------------------------------------------------------*/
static void prvSendNextSegment( void )
{
volatile unsigned long ulNextLength, ulStatus, ulLengthLeftToSend;
/* Is there any data to send? */
if( pxControlTx.ulTotalDataLength > pxControlTx.ulNextCharIndex )
{
ulLengthLeftToSend = pxControlTx.ulTotalDataLength - pxControlTx.ulNextCharIndex;
/* We can only send 8 bytes to the fifo at a time. */
if( ulLengthLeftToSend > usbFIFO_LENGTH )
{
ulNextLength = usbFIFO_LENGTH;
}
else
{
ulNextLength = ulLengthLeftToSend;
}
/* Wait until we can place data in the fifo. THERE IS NO TIMEOUT
HERE! */
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
{
vTaskDelay( usbSHORTEST_DELAY );
}
/* Write the data to the FIFO. */
while( ulNextLength > ( unsigned long ) 0 )
{
AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ] = pxControlTx.ucBuffer[ pxControlTx.ulNextCharIndex ];
ulNextLength--;
pxControlTx.ulNextCharIndex++;
}
/* Start the transmission. */
portENTER_CRITICAL();
{
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
usbCSR_SET_BIT( &ulStatus, ( ( unsigned long ) 0x10 ) );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
}
portEXIT_CRITICAL();
}
else
{
/* There is no data to send. If we were sending a descriptor and the
descriptor was an exact multiple of the max packet size then we need
to send a null to terminate the transmission. */
if( eDriverState == eSENDING_EVEN_DESCRIPTOR )
{
prvSendZLP();
eDriverState = eNOTHING;
}
}
}

View file

@ -0,0 +1,120 @@
/*
FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
#ifndef USB_CDC_H
#define USB_CDC_H
#include "usb.h"
#define USB_CDC_QUEUE_SIZE 200
/* Structure used to take a snapshot of the USB status from within the ISR. */
typedef struct X_ISR_STATUS
{
unsigned long ulISR;
unsigned long ulCSR0;
unsigned char ucFifoData[ 8 ];
} xISRStatus;
/* Structure used to hold the received requests. */
typedef struct
{
unsigned char ucReqType;
unsigned char ucRequest;
unsigned short usValue;
unsigned short usIndex;
unsigned short usLength;
} xUSB_REQUEST;
typedef enum
{
eNOTHING,
eJUST_RESET,
eJUST_GOT_CONFIG,
eJUST_GOT_ADDRESS,
eSENDING_EVEN_DESCRIPTOR,
eREADY_TO_SEND
} eDRIVER_STATE;
/* Structure used to control the data being sent to the host. */
typedef struct
{
unsigned char ucBuffer[ usbMAX_CONTROL_MESSAGE_SIZE ];
unsigned long ulNextCharIndex;
unsigned long ulTotalDataLength;
} xCONTROL_MESSAGE;
/*-----------------------------------------------------------*/
void vUSBCDCTask( void *pvParameters );
/* Send cByte down the USB port. Characters are simply buffered and not
sent unless the port is connected. */
void vUSBSendByte( char cByte );
#endif

View file

@ -0,0 +1,211 @@
/*
FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
/*
BASIC INTERRUPT DRIVEN DRIVER FOR USB.
This file contains all the usb components that must be compiled
to ARM mode. The components that can be compiled to either ARM or THUMB
mode are contained in USB-CDC.c.
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* Demo application includes. */
#include "Board.h"
#include "usb.h"
#include "USB-CDC.h"
#define usbINT_CLEAR_MASK (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 )
/*-----------------------------------------------------------*/
/* Messages and queue used to communicate between the ISR and the USB task. */
static xISRStatus xISRMessages[ usbQUEUE_LENGTH + 1 ];
extern xQueueHandle xUSBInterruptQueue;
/*-----------------------------------------------------------*/
/* The ISR can cause a context switch so is declared naked. */
void vUSB_ISR_Wrapper( void ) __attribute__ ((naked));
/* The function that actually performs the ISR work. This must be separate
from the wrapper function to ensure the correct stack frame gets set up. */
void vUSB_ISR_Handler( void );
/*-----------------------------------------------------------*/
void vUSB_ISR_Handler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
static volatile unsigned long ulNextMessage = 0;
xISRStatus *pxMessage;
unsigned long ulRxBytes;
unsigned char ucFifoIndex;
/* Use the next message from the array. */
pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );
ulNextMessage++;
/* Save UDP ISR state for task-level processing. */
pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR;
pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
/* Clear interrupts from ICR. */
AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES;
/* Process incoming FIFO data. Must set DIR (if needed) and clear RXSETUP
before exit. */
/* Read CSR and get incoming byte count. */
ulRxBytes = ( pxMessage->ulCSR0 >> 16 ) & usbRX_COUNT_MASK;
/* Receive control transfers on endpoint 0. */
if( pxMessage->ulCSR0 & ( AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 ) )
{
/* Save FIFO data buffer for either a SETUP or DATA stage */
for( ucFifoIndex = 0; ucFifoIndex < ulRxBytes; ucFifoIndex++ )
{
pxMessage->ucFifoData[ ucFifoIndex ] = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ];
}
/* Set direction for data stage. Must be done before RXSETUP is
cleared. */
if( ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP ) )
{
if( ulRxBytes && ( pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ] & 0x80 ) )
{
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] |= AT91C_UDP_DIR;
/* Might not be wise in an ISR! */
while( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_DIR) );
}
/* Clear RXSETUP */
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RXSETUP;
/* Might not be wise in an ISR! */
while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP );
}
else
{
/* Clear RX_DATA_BK0 */
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RX_DATA_BK0;
/* Might not be wise in an ISR! */
while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RX_DATA_BK0 );
}
}
/* If we received data on endpoint 1, disable its interrupts until it is
processed in the main loop */
if( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 ) )
{
AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_EPINT1;
}
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT );
/* Clear interrupts for the other endpoints, retain data flags for endpoint
1. */
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP );
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] &= ~usbINT_CLEAR_MASK;
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] &= ~usbINT_CLEAR_MASK;
/* Post ISR data to queue for task-level processing */
xQueueSendFromISR( xUSBInterruptQueue, &pxMessage, &xHigherPriorityTaskWoken );
/* Clear AIC to complete ISR processing */
AT91C_BASE_AIC->AIC_EOICR = 0;
/* Do a task switch if needed */
if( xHigherPriorityTaskWoken )
{
/* This call will ensure that the unblocked task will be executed
immediately upon completion of the ISR if it has a priority higher
than the interrupted task. */
portYIELD_FROM_ISR();
}
}
/*-----------------------------------------------------------*/
void vUSB_ISR_Wrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler to do the work. This must be a separate
function to ensure the stack frame is set up correctly. */
vUSB_ISR_Handler();
/* Restore the context of whichever task will execute next. */
portRESTORE_CONTEXT();
}

View file

@ -0,0 +1,237 @@
/*
FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
/*
- DESCRIPTOR DEFINITIONS -
*/
/* String descriptors used during the enumeration process.
These take the form:
{
Length of descriptor,
Descriptor type,
Data
}
*/
const char pxLanguageStringDescriptor[] =
{
4,
usbDESCRIPTOR_TYPE_STRING,
0x09, 0x04
};
const char pxManufacturerStringDescriptor[] =
{
18,
usbDESCRIPTOR_TYPE_STRING,
'F', 0x00, 'r', 0x00, 'e', 0x00, 'e', 0x00, 'R', 0x00, 'T', 0x00, 'O', 0x00, 'S', 0x00
};
const char pxProductStringDescriptor[] =
{
36,
usbDESCRIPTOR_TYPE_STRING,
'F', 0x00, 'r', 0x00, 'e', 0x00, 'e', 0x00, 'R', 0x00, 'T', 0x00, 'O', 0x00, 'S', 0x00, ' ', 0x00, 'C', 0x00, 'D', 0x00,
'C', 0x00, ' ', 0x00, 'D', 0x00, 'E', 0x00, 'M', 0x00, 'O', 0x00
};
const char pxConfigurationStringDescriptor[] =
{
38,
usbDESCRIPTOR_TYPE_STRING,
'C', 0x00, 'o', 0x00, 'n', 0x00, 'f', 0x00, 'i', 0x00, 'g', 0x00, 'u', 0x00, 'r', 0x00, 'a', 0x00, 't', 0x00, 'i', 0x00,
'o', 0x00, 'n', 0x00, ' ', 0x00, 'N', 0x00, 'a', 0x00, 'm', 0x00, 'e', 0x00
};
const char pxInterfaceStringDescriptor[] =
{
30,
usbDESCRIPTOR_TYPE_STRING,
'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, ' ', 0x00, 'N', 0x00,
'a', 0x00, 'm', 0x00, 'e', 0x00
};
/* Device should properly be 0x134A:0x9001, using 0x05F9:0xFFFF for Linux testing */
const char pxDeviceDescriptor[] =
{
/* Device descriptor */
0x12, /* bLength */
0x01, /* bDescriptorType */
0x10, 0x01, /* bcdUSBL */
0x02, /* bDeviceClass: */
0x00, /* bDeviceSubclass: */
0x00, /* bDeviceProtocol: */
0x08, /* bMaxPacketSize0 */
0x03, 0xEB, /* idVendorL */
0x20, 0x09, /* idProductL */
0x10, 0x01, /* bcdDeviceL */
usbMANUFACTURER_STRING, /* iManufacturer */
usbPRODUCT_STRING, /* iProduct */
0x00, /* SerialNumber */
0x01 /* bNumConfigs */
};
const char pxConfigDescriptor[] = {
/* Configuration 1 descriptor
Here we define two interfaces (0 and 1) and a total of 3 endpoints.
Interface 0 is a CDC Abstract Control Model interface with one interrupt-in endpoint.
Interface 1 is a CDC Data Interface class, with a bulk-in and bulk-out endpoint.
Endpoint 0 gets used as the CDC management element.
*/
0x09, /* CbLength */
0x02, /* CbDescriptorType */
0x43, 0x00, /* CwTotalLength 2 EP + Control ? */
0x02, /* CbNumInterfaces */
0x01, /* CbConfigurationValue */
usbCONFIGURATION_STRING,/* CiConfiguration */
usbBUS_POWERED, /* CbmAttributes Bus powered + Remote Wakeup*/
0x32, /* CMaxPower: 100mA */
/* Communication Class Interface Descriptor Requirement */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndpoints */
0x02, /* bInterfaceClass: Comm Interface Class */
0x02, /* bInterfaceSubclass: Abstract Control Model*/
0x00, /* bInterfaceProtocol */
usbINTERFACE_STRING,/* iInterface */
/* Header Functional Descriptor */
0x05, /* bLength */
0x24, /* bDescriptor type: CS_INTERFACE */
0x00, /* bDescriptor subtype: Header Func Desc*/
0x10, 0x01, /* bcdCDC:1.1 */
/* ACM Functional Descriptor */
0x04, /* bFunctionLength */
0x24, /* bDescriptor type: CS_INTERFACE */
0x02, /* bDescriptor subtype: ACM Func Desc */
0x00, /* bmCapabilities: We don't support squat*/
/* Union Functional Descriptor */
0x05, /* bFunctionLength */
0x24, /* bDescriptor type: CS_INTERFACE */
0x06, /* bDescriptor subtype: Union Func Desc */
0x00, /* bMasterInterface: CDC Interface */
0x01, /* bSlaveInterface0: Data Class Interface*/
/* Call Management Functional Descriptor
0 in D1 and D0 indicates that device does not handle call management*/
0x05, /* bFunctionLength */
0x24, /* bDescriptor type: CS_INTERFACE */
0x01, /* bDescriptor subtype: Call Management Func*/
0x01, /* bmCapabilities: D1 + D0 */
0x01, /* bDataInterface: Data Class Interface 1*/
/* CDC Control - Endpoint 3 descriptor
This endpoint serves as a notification element. */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x83, /* bEndpointAddress, Endpoint 03 - IN */
0x03, /* bmAttributes INT */
0x08, 0x00, /* wMaxPacketSize: 8 bytes */
0xFF, /* bInterval */
/* Data Class Interface Descriptor Requirement */
0x09, /* bLength */
0x04, /* bDescriptorType */
0x01, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndPoints */
0x0A, /* bInterfaceClass */
0x00, /* bInterfaceSubclass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface */
/* CDC Data - Endpoint 1 descriptor */
0x07, /* bLenght */
0x05, /* bDescriptorType */
0x01, /* bEndPointAddress, Endpoint 01 - OUT */
0x02, /* bmAttributes BULK */
64, /* wMaxPacketSize */
0x00,
0x00, /* bInterval */
/* CDC Data - Endpoint 2 descriptor */
0x07, /* bLength */
0x05, /* bDescriptorType */
0x82, /* bEndPointAddress, Endpoint 02 - IN */
0x02, /* bmAttributes BULK */
64, /* wMaxPacketSize */
0x00,
0x00 /* bInterval */
};

View file

@ -0,0 +1,178 @@
/*
FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
***************************************************************************
* *
* FreeRTOS tutorial books are available in pdf and paperback. *
* Complete, revised, and edited pdf reference manuals are also *
* available. *
* *
* Purchasing FreeRTOS documentation will not only help you, by *
* ensuring you get running as quickly as possible and with an *
* in-depth knowledge of how to use FreeRTOS, it will also help *
* the FreeRTOS project to continue with its mission of providing *
* professional grade, cross platform, de facto standard solutions *
* for microcontrollers - completely free of charge! *
* *
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* *
* Thank you for using FreeRTOS, and thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
>>>NOTE<<< The modification to the GPL is included to allow you to
distribute a combined work that includes FreeRTOS without being obliged to
provide the source code for proprietary components outside of the FreeRTOS
kernel. FreeRTOS is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
***************************************************************************
* *
* Having a problem? Start by reading the FAQ "My application does *
* not run, what could be wrong? *
* *
* http://www.FreeRTOS.org/FAQHelp.html *
* *
***************************************************************************
http://www.FreeRTOS.org - Documentation, training, latest information,
license and contact details.
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
including FreeRTOS+Trace - an indispensable productivity tool.
Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
the code with commercial support, indemnification, and middleware, under
the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
provide a safety engineered and independently SIL3 certified version under
the SafeRTOS brand: http://www.SafeRTOS.com.
*/
/* Descriptor type definitions. */
#define usbDESCRIPTOR_TYPE_DEVICE ( 0x01 )
#define usbDESCRIPTOR_TYPE_CONFIGURATION ( 0x02 )
#define usbDESCRIPTOR_TYPE_STRING ( 0x03 )
/* USB request type definitions. */
#define usbGET_REPORT_REQUEST ( 0x01 )
#define usbGET_IDLE_REQUEST ( 0x02 )
#define usbGET_PROTOCOL_REQUEST ( 0x03 )
#define usbSET_REPORT_REQUEST ( 0x09 )
#define usbSET_IDLE_REQUEST ( 0x0A )
#define usbSET_PROTOCOL_REQUEST ( 0x0B )
#define usbGET_CONFIGURATION_REQUEST ( 0x08 )
#define usbGET_STATUS_REQUEST ( 0x00 )
#define usbCLEAR_FEATURE_REQUEST ( 0x01 )
#define usbSET_FEATURE_REQUEST ( 0x03 )
#define usbSET_ADDRESS_REQUEST ( 0x05 )
#define usbGET_DESCRIPTOR_REQUEST ( 0x06 )
#define usbSET_CONFIGURATION_REQUEST ( 0x09 )
#define usbGET_INTERFACE_REQUEST ( 0x0A )
#define usbSET_INTERFACE_REQUEST ( 0x0B )
/* ACM Requests */
#define usbSEND_ENCAPSULATED_COMMAND ( 0x00 )
#define usbGET_ENCAPSULATED_RESPONSE ( 0x01 )
#define usbSET_LINE_CODING ( 0x20 )
#define usbGET_LINE_CODING ( 0x21 )
#define usbSET_CONTROL_LINE_STATE ( 0x22 )
/* Misc USB definitions. */
#define usbDEVICE_CLASS_VENDOR_SPECIFIC ( 0xFF )
#define usbBUS_POWERED ( 0x80 )
#define usbHID_REPORT_DESCRIPTOR ( 0x22 )
#define AT91C_UDP_TRANSCEIVER_ENABLE ( *( ( unsigned long * ) 0xfffb0074 ) )
/* Index to the various string. */
#define usbLANGUAGE_STRING ( 0 )
#define usbMANUFACTURER_STRING ( 1 )
#define usbPRODUCT_STRING ( 2 )
#define usbCONFIGURATION_STRING ( 3 )
#define usbINTERFACE_STRING ( 4 )
/* Defines fields of standard SETUP request. Now in normal order. */
#define usbREQUEST_TYPE_INDEX ( 0 )
#define usbREQUEST_INDEX ( 1 )
#define usbVALUE_HIGH_BYTE ( 3 )
#define usbVALUE_LOW_BYTE ( 2 )
#define usbINDEX_HIGH_BYTE ( 5 )
#define usbINDEX_LOW_BYTE ( 4 )
#define usbLENGTH_HIGH_BYTE ( 7 )
#define usbLENGTH_LOW_BYTE ( 6 )
/* Misc application definitions. */
#define usbINTERRUPT_PRIORITY ( 3 )
#define usbQUEUE_LENGTH ( 0x3 ) /* Must have all bits set! */
#define usbFIFO_LENGTH ( ( unsigned long ) 8 )
#define usbEND_POINT_0 ( 0 )
#define usbEND_POINT_1 ( 1 )
#define usbEND_POINT_2 ( 2 )
#define usbEND_POINT_3 ( 3 )
#define usbMAX_CONTROL_MESSAGE_SIZE ( 128 )
#define usbRX_COUNT_MASK ( ( unsigned long ) 0x7ff )
#define AT91C_UDP_STALLSENT AT91C_UDP_ISOERROR
#define usbSHORTEST_DELAY ( ( portTickType ) 1 )
#define usbINIT_DELAY ( ( portTickType ) 1000 / portTICK_RATE_MS )
#define usbSHORT_DELAY ( ( portTickType ) 50 / portTICK_RATE_MS )
#define usbEND_POINT_RESET_MASK ( ( unsigned long ) 0x0f )
#define usbDATA_INC ( ( char ) 5 )
#define usbEXPECTED_NUMBER_OF_BYTES ( ( unsigned long ) 8 )
/* Control request types. */
#define usbSTANDARD_DEVICE_REQUEST ( 0 )
#define usbSTANDARD_INTERFACE_REQUEST ( 1 )
#define usbSTANDARD_END_POINT_REQUEST ( 2 )
#define usbCLASS_INTERFACE_REQUEST ( 5 )
/* Macros to manipulate the control and status registers. These registers
cannot be accessed using a direct read modify write operation outside of the
ISR as some bits are left unchanged by writing with a 0, and some are left
unchanged by writing with a 1. */
#define usbCSR_SET_BIT( pulValueNow, ulBit ) \
{ \
/* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
/* STALLSENT and RX_DATA_BK1 to 1 so the */ \
/* write has no effect. */ \
( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f; \
\
/* Clear the FORCE_STALL and TXPKTRDY bits */ \
/* so the write has no effect. */ \
( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf; \
\
/* Set whichever bit we want set. */ \
( * ( ( unsigned long * ) pulValueNow ) ) |= ( ulBit ); \
}
#define usbCSR_CLEAR_BIT( pulValueNow, ulBit ) \
{ \
/* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
/* STALLSENT and RX_DATA_BK1 to 1 so the */ \
/* write has no effect. */ \
( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f; \
\
/* Clear the FORCE_STALL and TXPKTRDY bits */ \
/* so the write has no effect. */ \
( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf; \
\
/* Clear whichever bit we want clear. */ \
( * ( ( unsigned long * ) pulValueNow ) ) &= ( ~ulBit ); \
}