#include "semphr.h"\r
#include "task.h"\r
\r
-/* Demo includes. */\r
+/* Hardware includes. */\r
#include "fecbd.h"\r
#include "mii.h"\r
#include "eth_phy.h"\r
#include "uip.h"\r
#include "uip_arp.h"\r
\r
-#define MCF_FEC_MSCR_MII_SPEED(x) (((x)&0x3F)<<0x1)\r
-#define MCF_FEC_RCR_MAX_FL(x) (((x)&0x7FF)<<0x10)\r
-\r
/* Delay between polling the PHY to see if a link has been established. */\r
#define fecLINK_DELAY ( 500 / portTICK_RATE_MS )\r
\r
#define fecMII_DELAY ( 10 / portTICK_RATE_MS )\r
#define fecMAX_POLLS ( 20 )\r
\r
-/* Delay between looking for incoming packets. In ideal world this would be\r
-infinite. */\r
-#define netifBLOCK_TIME_WAITING_FOR_INPUT fecLINK_DELAY\r
-\r
/* Constants used to delay while waiting for a tx descriptor to be free. */\r
-#define fecTX_BUFFER_WAIT ( 200 / portTICK_RATE_MS )\r
+#define fecMAX_WAIT_FOR_TX_BUFFER ( 200 / portTICK_RATE_MS )\r
\r
-/* We only use a single Tx descriptor - the duplicate send silicon errata\r
-actually assists in this case. */\r
+/* We only use a single Tx descriptor which can lead to Txed packets being sent\r
+twice (due to a bug in the FEC silicon). However, in this case the bug is used\r
+to our advantage in that it means the uip-split mechanism is not required. */\r
#define fecNUM_FEC_TX_BUFFERS ( 1 )\r
#define fecTX_BUFFER_TO_USE ( 0 )\r
/*-----------------------------------------------------------*/\r
xSemaphoreHandle xFECSemaphore = NULL, xTxSemaphore = NULL;\r
\r
/* The buffer used by the uIP stack. In this case the pointer is used to\r
-point to one of the Rx buffers. */\r
+point to one of the Rx buffers to effect a zero copy policy. */\r
unsigned portCHAR *uip_buf;\r
\r
/* The DMA descriptors. This is a char array to allow us to align it correctly. */\r
static FECBD *xFECTxDescriptors;\r
static FECBD *xFECRxDescriptors;\r
\r
-/* The DMA buffers. These are char arrays to allow them to be alligned correctly. */\r
+/* The DMA buffers. These are char arrays to allow them to be aligned correctly. */\r
static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxIndexToBufferOwner = 0;\r
\r
/*-----------------------------------------------------------*/\r
\r
+/* \r
+ * Enable all the required interrupts in the FEC and in the interrupt controller. \r
+ */\r
static void prvEnableFECInterrupts( void );\r
+\r
+/*\r
+ * Reset the FEC if we get into an unrecoverable state.\r
+ */\r
static void prvResetFEC( portBASE_TYPE xCalledFromISR );\r
\r
/********************************************************************/\r
+\r
/*\r
+ * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE\r
+ * \r
* Write a value to a PHY's MII register.\r
*\r
* Parameters:\r
\r
/********************************************************************/\r
/*\r
+ * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE\r
+ *\r
* Read a value from a PHY's MII register.\r
*\r
* Parameters:\r
\r
/********************************************************************/\r
/*\r
+ * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE\r
+ *\r
* Generate the hash table settings for the given address\r
*\r
* Parameters:\r
\r
/********************************************************************/\r
/*\r
+ * FUNCTION ADAPTED FROM FREESCALE SUPPLIED SOURCE\r
+ *\r
* Set the Physical (Hardware) Address and the Individual Address\r
* Hash in the selected FEC\r
*\r
unsigned portBASE_TYPE ux;\r
unsigned portCHAR *pcBufPointer;\r
\r
+ /* Correctly align the Tx descriptor pointer. */\r
pcBufPointer = &( xFECTxDescriptors_unaligned[ 0 ] );\r
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
{\r
\r
xFECTxDescriptors = ( FECBD * ) pcBufPointer;\r
\r
+ /* Likewise the Rx descriptor pointer. */\r
pcBufPointer = &( xFECRxDescriptors_unaligned[ 0 ] );\r
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
{\r
xFECRxDescriptors = ( FECBD * ) pcBufPointer;\r
\r
\r
- /* Setup the buffers and descriptors. The data member does not point\r
- anywhere yet as there is not yet anything to send and a zero copy policy\r
- is used. */
+ /* Setup the Tx buffers and descriptors. There is no separate Tx buffer\r
+ to point to (the Rx buffers are actually used) so the data member is\r
+ set to NULL for now. */
for( ux = 0; ux < fecNUM_FEC_TX_BUFFERS; ux++ )\r
{\r
xFECTxDescriptors[ ux ].status = TX_BD_TC;\r
xFECTxDescriptors[ ux ].length = 0;\r
}\r
\r
+ /* Setup the Rx buffers and descriptors, having first ensured correct\r
+ alignment. */\r
pcBufPointer = &( ucFECRxBuffers[ 0 ] );\r
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )\r
{\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vInitFEC( void )\r
+void vFECInit( void )\r
{\r
unsigned portSHORT usData;\r
struct uip_eth_addr xAddr;\r
+\r
+/* The MAC address is set at the foot of FreeRTOSConfig.h. */\r
const unsigned portCHAR ucMACAddress[6] =\r
{\r
configMAC_0, configMAC_1,configMAC_2, configMAC_3, configMAC_4, configMAC_5\r
\r
/* Create the semaphore used by the ISR to wake the uIP task. */\r
vSemaphoreCreateBinary( xFECSemaphore );\r
+\r
+ /* Create the semaphore used to unblock any tasks that might be waiting\r
+ for a Tx descriptor. */\r
vSemaphoreCreateBinary( xTxSemaphore );\r
\r
+ /* Initialise all the buffers and descriptors used by the DMA. */\r
prvInitialiseFECBuffers();\r
\r
for( usData = 0; usData < 6; usData++ )\r
\r
prvEnableFECInterrupts();\r
\r
+ /* Finally... enable. */\r
MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;\r
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
}\r
#error configFEC_INTERRUPT_PRIORITY must be less than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY\r
#endif\r
\r
+ /* Set the priority of each of the FEC interrupts. */\r
for( ux = uxFirstFECVector; ux <= uxLastFECVector; ux++ )\r
{\r
MCF_INTC0_ICR( ux ) = MCF_INTC_ICR_IL( configFEC_INTERRUPT_PRIORITY );\r
{\r
portBASE_TYPE x;\r
\r
+ /* A critical section is used unless this function is being called from\r
+ an ISR. */\r
if( xCalledFromISR == pdFALSE )\r
{\r
taskENTER_CRITICAL();\r
}\r
\r
{\r
+ /* Reset all buffers and descriptors. */\r
prvInitialiseFECBuffers();\r
\r
/* Set the Reset bit and clear the Enable bit */\r
asm( "NOP" );\r
}\r
\r
+ /* Re-enable. */\r
MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;\r
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
-unsigned short usGetFECRxData( void )\r
+unsigned short usFECGetRxedData( void )\r
{\r
unsigned portSHORT usLen;\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vDiscardRxData( void )\r
+void vFECRxProcessingCompleted( void )\r
{\r
/* Free the descriptor as the buffer it points to is no longer in use. */\r
xFECRxDescriptors[ uxNextRxBuffer ].status |= RX_BD_E;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vSendBufferToFEC( void )\r
+void vFECSendData( void )\r
{\r
/* Ensure no Tx frames are outstanding. */\r
- if( xSemaphoreTake( xTxSemaphore, fecTX_BUFFER_WAIT ) == pdPASS )\r
+ if( xSemaphoreTake( xTxSemaphore, fecMAX_WAIT_FOR_TX_BUFFER ) == pdPASS )\r
{\r
/* Get a DMA buffer into which we can write the data to send. */\r
if( xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status & TX_BD_R )\r
else\r
{\r
/* Setup the buffer descriptor for transmission. The data being\r
- sent is actually stored in one of the Rx descripter buffers,\r
+ sent is actually stored in one of the Rx descriptor buffers,\r
pointed to by uip_buf. */\r
xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].length = uip_len;\r
xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status |= ( TX_BD_R | TX_BD_L );\r
}\r
else\r
{\r
- vDiscardRxData();\r
+ /* Gave up waiting. Free the buffer back to the DMA. */\r
+ vFECRxProcessingCompleted();\r
}\r
}\r
/*-----------------------------------------------------------*/\r
unsigned portLONG ulEvent;\r
portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;\r
\r
+ /* This handler is called in response to any of the many separate FEC\r
+ interrupt. */\r
+\r
+ /* Find the cause of the interrupt, then clear the interrupt. */\r
ulEvent = MCF_FEC_EIR & MCF_FEC_EIMR;\r
MCF_FEC_EIR = ulEvent;\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
+/* Install the many different interrupt vectors, all of which call the same\r
+handler function. */\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_87( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }\r
port sections of the online documentation.\r
***************************************************************************\r
*/\r
+\r
+\r
+/* Task that controls the uIP TCP/IP stack. */\r
+\r
+\r
/* Standard includes. */\r
#include <string.h>\r
\r
#include "FEC.h"\r
#include "partest.h"\r
\r
-//struct timer {\r
-// clock_time_t start;\r
-// clock_time_t interval;\r
-//};\r
-\r
\r
/*-----------------------------------------------------------*/\r
\r
-/* How long to wait before attempting to connect the MAC again. */\r
-#define uipINIT_WAIT 100\r
-\r
/* Shortcut to the header within the Rx buffer. */\r
#define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])\r
\r
-/* Standard constant. */\r
-#define uipTOTAL_FRAME_HEADER_SIZE 54\r
-\r
/*-----------------------------------------------------------*/\r
\r
/*\r
*/\r
void clock_init( void );\r
clock_time_t clock_time( void );\r
+extern void timer_set(struct timer *t, clock_time_t interval);\r
+extern int timer_expired(struct timer *t);\r
+extern void timer_reset(struct timer *t);\r
\r
/*-----------------------------------------------------------*/\r
\r
{\r
return xTaskGetTickCount();\r
}\r
-extern void timer_set(struct timer *t, clock_time_t interval);\r
-extern int timer_expired(struct timer *t);\r
-extern void timer_reset(struct timer *t);\r
-\r
-\r
-\r
+/*-----------------------------------------------------------*/\r
\r
void vuIP_Task( void *pvParameters )\r
{\r
portBASE_TYPE i;\r
uip_ipaddr_t xIPAddr;\r
struct timer periodic_timer, arp_timer;\r
-extern void ( vEMAC_ISR )( void );\r
\r
/* To prevent compiler warnings. */\r
( void ) pvParameters;\r
uip_init();\r
uip_ipaddr( xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );\r
uip_sethostaddr( xIPAddr );\r
+\r
+ /* Initialise the WEB server. */\r
httpd_init();\r
\r
- vInitFEC();\r
+ /* Initialise the Ethernet controller peripheral. */\r
+ vFECInit();\r
\r
for( ;; )\r
{\r
/* Is there received data ready to be processed? */\r
- uip_len = usGetFECRxData();\r
+ uip_len = usFECGetRxedData();\r
\r
if( uip_len > 0 )\r
{\r
if( uip_len > 0 )\r
{\r
uip_arp_out();\r
- vSendBufferToFEC();\r
+ vFECSendData();\r
}\r
else\r
{\r
- vDiscardRxData();\r
+ /* If we are not sending data then let the FEC driver know\r
+ the buffer is no longer required. */\r
+ vFECRxProcessingCompleted();\r
}\r
}\r
else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
uip_len is set to a value > 0. */\r
if( uip_len > 0 )\r
{\r
- vSendBufferToFEC();\r
+ vFECSendData();\r
}\r
else\r
{\r
- vDiscardRxData();\r
+ /* If we are not sending data then let the FEC driver know\r
+ the buffer is no longer required. */\r
+ vFECRxProcessingCompleted();\r
}\r
}\r
else\r
{\r
- vDiscardRxData();\r
+ /* If we are not sending data then let the FEC driver know\r
+ the buffer is no longer required. */\r
+ vFECRxProcessingCompleted();\r
}\r
}\r
else\r
if( uip_len > 0 )\r
{\r
uip_arp_out();\r
- vSendBufferToFEC();\r
+ vFECSendData();\r
}\r
}\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vApplicationProcessFormInput( portCHAR *pcInputString )\r
-{\r
-char *c = pcInputString;\r
-\r
- /* Process the form input sent by the IO page of the served HTML. */\r
- while( ( *c != '?' ) && ( *c != 0x00 ) )\r
- {\r
- c++;\r
- }\r
-\r
- if( *c == '?' )\r
- {\r
- c++;\r
- if( strcmp( c, "LED0=1" ) == 0 )\r
- {\r
- vParTestSetLED( 3, 1 );\r
- }\r
- else\r
- {\r
- vParTestSetLED( 3, 0 );\r
- }\r
- }\r
-}\r
-\r
\r
\r