Continue work on MCF52233 demo.

This commit is contained in:
Richard Barry 2008-11-16 17:10:27 +00:00
parent 31606543da
commit 18f84c805f
32 changed files with 3949 additions and 438 deletions

View file

@ -60,31 +60,35 @@ infinite. */
#define netifBLOCK_TIME_WAITING_FOR_INPUT fecLINK_DELAY
/* Constants used to delay while waiting for a tx descriptor to be free. */
#define fecMAX_TX_WAIT_ATTEMPTS 4
#define fecTX_BUFFER_WAIT ( 10 / portTICK_RATE_MS )
#define fecTX_BUFFER_WAIT ( 200 / portTICK_RATE_MS )
/* We only use a single Tx descriptor - the duplicate send silicon errata
actually assists in this case. */
#define fecNUM_FEC_TX_BUFFERS ( 1 )
#define fecTX_BUFFER_TO_USE ( 0 )
/*-----------------------------------------------------------*/
/* The semaphore used to wake the uIP task when data arrives. */
xSemaphoreHandle xFECSemaphore = NULL;
xSemaphoreHandle xFECSemaphore = NULL, xTxSemaphore = NULL;
/* The buffer used by the uIP stack. In this case the pointer is used to
point to one of the Rx buffers. */
unsigned portCHAR *uip_buf;
/* The DMA descriptors. This is a char array to allow us to align it correctly. */
static unsigned portCHAR xFECTxDescriptors_unaligned[ ( configNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];
static unsigned portCHAR xFECTxDescriptors_unaligned[ ( fecNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];
static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];
static FECBD *xFECTxDescriptors;
static FECBD *xFECRxDescriptors;
/* The DMA buffers. These are char arrays to allow them to be alligned correctly. */
static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];
static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxNextTxBuffer = 0, uxIndexToBufferOwner = 0;
static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxIndexToBufferOwner = 0;
/*-----------------------------------------------------------*/
static void prvEnableFECInterrupts( void );
static void prvResetFEC( portBASE_TYPE xCalledFromISR );
/********************************************************************/
/*
@ -319,7 +323,7 @@ unsigned portCHAR *pcBufPointer;
/* Setup the buffers and descriptors. The data member does not point
anywhere yet as there is not yet anything to send and a zero copy policy
is used. */
for( ux = 0; ux < configNUM_FEC_TX_BUFFERS; ux++ )
for( ux = 0; ux < fecNUM_FEC_TX_BUFFERS; ux++ )
{
xFECTxDescriptors[ ux ].status = TX_BD_TC;
xFECTxDescriptors[ ux ].data = NULL;
@ -341,11 +345,10 @@ unsigned portCHAR *pcBufPointer;
}
/* Set the wrap bit in the last descriptors to form a ring. */
xFECTxDescriptors[ configNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;
xFECTxDescriptors[ fecNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;
xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;
uxNextRxBuffer = 0;
uxNextTxBuffer = 0;
}
/*-----------------------------------------------------------*/
@ -360,6 +363,7 @@ const unsigned portCHAR ucMACAddress[6] =
/* Create the semaphore used by the ISR to wake the uIP task. */
vSemaphoreCreateBinary( xFECSemaphore );
vSemaphoreCreateBinary( xTxSemaphore );
prvInitialiseFECBuffers();
@ -517,7 +521,8 @@ unsigned portBASE_TYPE ux;
MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );
MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27
| MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30
| MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL );
| MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24
| MCF_INTC_IMRL_MASKALL );
/* Clear any pending FEC interrupt events */
MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;
@ -527,6 +532,38 @@ unsigned portBASE_TYPE ux;
}
/*-----------------------------------------------------------*/
static void prvResetFEC( portBASE_TYPE xCalledFromISR )
{
portBASE_TYPE x;
if( xCalledFromISR == pdFALSE )
{
taskENTER_CRITICAL();
}
{
prvInitialiseFECBuffers();
/* Set the Reset bit and clear the Enable bit */
MCF_FEC_ECR = MCF_FEC_ECR_RESET;
/* Wait at least 8 clock cycles */
for( x = 0; x < 10; x++ )
{
asm( "NOP" );
}
MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
}
if( xCalledFromISR == pdFALSE )
{
taskEXIT_CRITICAL();
}
}
/*-----------------------------------------------------------*/
unsigned short usGetFECRxData( void )
{
unsigned portSHORT usLen;
@ -562,37 +599,31 @@ void vDiscardRxData( void )
void vSendBufferToFEC( void )
{
portLONG l;
/* Get a DMA buffer into which we can write the data to send. */
for( l = 0; l < fecMAX_TX_WAIT_ATTEMPTS; l++ )
/* Ensure no Tx frames are outstanding. */
if( xSemaphoreTake( xTxSemaphore, fecTX_BUFFER_WAIT ) == pdPASS )
{
if( xFECTxDescriptors[ uxNextTxBuffer ].status & TX_BD_R )
/* Get a DMA buffer into which we can write the data to send. */
if( xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status & TX_BD_R )
{
/* Wait for the buffer to become available. */
vTaskDelay( fecTX_BUFFER_WAIT );
/*** ERROR didn't expect this. Sledge hammer error handling. ***/
prvResetFEC( pdFALSE );
/* Make sure we leave the semaphore in the expected state as nothing
is being transmitted this will not happen in the Tx ISR. */
xSemaphoreGive( xTxSemaphore );
}
else
{
/* Setup the buffer descriptor for transmission. The data being
sent is actually stored in one of the Rx descripter buffers,
pointed to by uip_buf. */
xFECTxDescriptors[ uxNextTxBuffer ].length = uip_len;
xFECTxDescriptors[ uxNextTxBuffer ].status |= (TX_BD_R | TX_BD_L);
xFECTxDescriptors[ uxNextTxBuffer ].data = uip_buf;
/* Continue the Tx DMA (in case it was waiting for a new TxBD) */
MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].length = uip_len;
xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status |= ( TX_BD_R | TX_BD_L );
xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].data = uip_buf;
/* Remember which Rx descriptor owns the buffer we are sending. */
uxIndexToBufferOwner = uxNextRxBuffer;
uxNextTxBuffer++;
if( uxNextTxBuffer >= configNUM_FEC_TX_BUFFERS )
{
uxNextTxBuffer = 0;
}
/* We have finished with this Rx descriptor now. */
uxNextRxBuffer++;
if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )
@ -600,9 +631,14 @@ portLONG l;
uxNextRxBuffer = 0;
}
break;
/* Continue the Tx DMA (in case it was waiting for a new TxBD) */
MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;
}
}
else
{
vDiscardRxData();
}
}
/*-----------------------------------------------------------*/
@ -623,8 +659,7 @@ portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
if( ulEvent & ( MCF_FEC_EIR_UN | MCF_FEC_EIR_RL | MCF_FEC_EIR_LC | MCF_FEC_EIR_EBERR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_BABR | MCF_FEC_EIR_HBERR ) )
{
/* Sledge hammer error handling. */
prvInitialiseFECBuffers();
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
prvResetFEC( pdTRUE );
}
if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )
@ -633,12 +668,14 @@ portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
buffer has been sent we can mark the Rx descriptor as free again. */
xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;
xSemaphoreGiveFromISR( xTxSemaphore, &xHighPriorityTaskWoken );
}
portEND_SWITCHING_ISR( xHighPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
void __attribute__ ((interrupt)) __cs3_isr_interrupt_87( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }
@ -651,5 +688,5 @@ void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }
void __attribute__ ((interrupt)) __cs3_isr_interrupt_100( void ) { vFEC_ISR(); }

View file

@ -54,10 +54,14 @@
#include <stdio.h>
#include <string.h>
HTTPD_CGI_CALL(file, "file-stats", file_stats);
HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats);
HTTPD_CGI_CALL(net, "net-stats", net_stats);
HTTPD_CGI_CALL(rtos, "rtos-stats", rtos_stats );
HTTPD_CGI_CALL(io, "led-io", led_io );
static const struct httpd_cgi_call *calls[] = { &rtos, NULL };
static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, &rtos, &io, NULL };
/*---------------------------------------------------------------------------*/
static
@ -82,6 +86,23 @@ httpd_cgi(char *name)
return nullfunction;
}
/*---------------------------------------------------------------------------*/
static unsigned short
generate_file_stats(void *arg)
{
char *f = (char *)arg;
return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f));
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
{
PSOCK_BEGIN(&s->sout);
PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1);
PSOCK_END(&s->sout);
}
/*---------------------------------------------------------------------------*/
static const char closed[] = /* "CLOSED",*/
{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
static const char syn_rcvd[] = /* "SYN-RCVD",*/
@ -109,20 +130,92 @@ static const char last_ack[] = /* "LAST-ACK"*/
{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43,
0x4b, 0};
static const char *states[] = {
closed,
syn_rcvd,
syn_sent,
established,
fin_wait_1,
fin_wait_2,
closing,
time_wait,
last_ack};
static unsigned short
generate_tcp_stats(void *arg)
{
struct uip_conn *conn;
struct httpd_state *s = (struct httpd_state *)arg;
conn = &uip_conns[s->count];
return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
"<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n",
htons(conn->lport),
htons(conn->ripaddr[0]) >> 8,
htons(conn->ripaddr[0]) & 0xff,
htons(conn->ripaddr[1]) >> 8,
htons(conn->ripaddr[1]) & 0xff,
htons(conn->rport),
states[conn->tcpstateflags & UIP_TS_MASK],
conn->nrtx,
conn->timer,
(uip_outstanding(conn))? '*':' ',
(uip_stopped(conn))? '!':' ');
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
{
PSOCK_BEGIN(&s->sout);
( void ) ptr;
for(s->count = 0; s->count < UIP_CONNS; ++s->count) {
if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
PSOCK_GENERATOR_SEND(&s->sout, generate_tcp_stats, s);
}
}
PSOCK_END(&s->sout);
}
/*---------------------------------------------------------------------------*/
static unsigned short
generate_net_stats(void *arg)
{
struct httpd_state *s = (struct httpd_state *)arg;
return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
"%5u\n", ((uip_stats_t *)&uip_stat)[s->count]);
}
static
PT_THREAD(net_stats(struct httpd_state *s, char *ptr))
{
PSOCK_BEGIN(&s->sout);
( void ) ptr;
#if UIP_STATISTICS
for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t);
++s->count) {
PSOCK_GENERATOR_SEND(&s->sout, generate_net_stats, s);
}
#endif /* UIP_STATISTICS */
PSOCK_END(&s->sout);
}
/*---------------------------------------------------------------------------*/
extern void vTaskList( signed char *pcWriteBuffer );
extern unsigned long ulGetErrorCode( void );
static char cCountBuf[ 32 ];
long lRefreshCount = 0;
static unsigned short
generate_rtos_stats(void *arg)
{
( void ) arg;
lRefreshCount++;
sprintf( cCountBuf, "<p><br>Refresh count = %d", (int) lRefreshCount );
sprintf( cCountBuf, "<p><br>Refresh count = %d, Error code = %d (0 = no errors)", (int)lRefreshCount, (int)ulGetErrorCode() );
vTaskList( uip_appdata );
strcat( uip_appdata, cCountBuf );
@ -141,6 +234,37 @@ PT_THREAD(rtos_stats(struct httpd_state *s, char *ptr))
}
/*---------------------------------------------------------------------------*/
char *pcStatus;
extern unsigned long uxParTestGetLED( unsigned long uxLED );
static unsigned short generate_io_state( void *arg )
{
( void ) arg;
if( uxParTestGetLED( 3 ) )
{
pcStatus = "checked";
}
else
{
pcStatus = "";
}
sprintf( uip_appdata,
"<input type=\"checkbox\" name=\"LED0\" value=\"1\" %s>LED",
pcStatus );
return strlen( uip_appdata );
}
/*---------------------------------------------------------------------------*/
static PT_THREAD(led_io(struct httpd_state *s, char *ptr))
{
PSOCK_BEGIN(&s->sout);
( void ) ptr;
PSOCK_GENERATOR_SEND(&s->sout, generate_io_state, NULL);
PSOCK_END(&s->sout);
}
/** @} */

View file

@ -35,7 +35,7 @@
#ifndef __HTTPD_FS_H__
#define __HTTPD_FS_H__
#define HTTPD_FS_STATISTICS 0
#define HTTPD_FS_STATISTICS 1
struct httpd_fs_file {
char *data;

View file

@ -5,6 +5,9 @@
</head>
<BODY onLoad="window.setTimeout(&quot;location.href='index.shtml'&quot;,2000)"bgcolor="#CCCCff">
<font face="arial">
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">30K JPG</a>
<br><p>
<hr>
<br><p>
<h2>Task statistics</h2>
Page will refresh every 2 seconds.<p>

View file

@ -5,14 +5,14 @@
</head>
<BODY bgcolor="#CCCCff">
<font face="arial">
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a>
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">30K JPG</a>
<br><p>
<hr>
<b>LED and LCD IO</b><br>
<b>LED IO</b><br>
<p>
Use the check box to turn on or off the LED, enter text to display on the OLED display, then click "Update IO".
Use the check box to turn on or off the LED, then click "Update IO".
<p>

View file

@ -5,7 +5,7 @@
</head>
<BODY bgcolor="#CCCCff">
<font face="arial">
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a>
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">30K JPG</a>
<br><p>
<hr>
<br><p>

View file

@ -5,7 +5,7 @@
</head>
<BODY bgcolor="#CCCCff">
<font face="arial">
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a>
<a href="index.shtml">RTOS Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS.org Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">30K JPG</a>
<br><p>
<hr>
<br>

View file

@ -268,6 +268,12 @@ PT_THREAD(handle_input(struct httpd_state *s))
s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
/* Process any form input being sent to the server. */
{
extern void vApplicationProcessFormInput( char *pcInputString, long xInputLength );
vApplicationProcessFormInput( s->inputbuf, PSOCK_DATALEN(&s->sin) );
}
strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
}

View file

@ -208,23 +208,27 @@ extern void ( vEMAC_ISR )( void );
void vApplicationProcessFormInput( portCHAR *pcInputString )
{
char *c;
char *c = pcInputString;
/* Process the form input sent by the IO page of the served HTML. */
while( ( *c != '?' ) && ( *c != 0x00 ) )
{
c++;
}
c = strstr( pcInputString, "?" );
if( c )
if( *c == '?' )
{
/* Turn LED's on or off in accordance with the check box status. */
if( strstr( c, "LED0=1" ) != NULL )
c++;
if( strcmp( c, "LED0=1" ) == 0 )
{
vParTestSetLED( 0, 1 );
vParTestSetLED( 3, 1 );
}
else
{
vParTestSetLED( 0, 0 );
vParTestSetLED( 3, 0 );
}
}
}