Demo: qemu mps2 echo client cleanup (#833)

This commit is contained in:
alfred gedeon 2022-08-03 00:05:14 +02:00 committed by GitHub
parent 9058c39aed
commit 4242c47a8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 386 additions and 399 deletions

View file

@ -47,10 +47,6 @@ SOURCE_FILES += ${FREERTOS_TCP}/portable/NetworkInterface/MPS2_AN385/NetworkInte
SOURCE_FILES += TCPEchoClient_SingleTasks.c SOURCE_FILES += TCPEchoClient_SingleTasks.c
SOURCE_FILES += ${FREERTOS_TCP}/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c SOURCE_FILES += ${FREERTOS_TCP}/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c
# networking specific cflags
CFLAGS := -DmainCREATE_NETWORKING_DEMO_ONLY=1
CFLAGS += -DmainCREATE_TCP_ECHO_TASKS_SINGLE=1
DEFINES := -DprojCOVERAGE_TEST -DQEMU_SOC_MPS2 -DHEAP3 DEFINES := -DprojCOVERAGE_TEST -DQEMU_SOC_MPS2 -DHEAP3
LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon LDFLAGS = -T ./scripts/mps2_m3.ld -specs=nano.specs --specs=rdimon.specs -lc -lrdimon

View file

@ -54,22 +54,22 @@
#if ( ipconfigUSE_TCP == 1 ) #if ( ipconfigUSE_TCP == 1 )
/* The echo tasks create a socket, send out a number of echo requests, listen /* The echo tasks create a socket, send out a number of echo requests, listen
for the echo reply, then close the socket again before starting over. This * for the echo reply, then close the socket again before starting over. This
delay is used between each iteration to ensure the network does not get too * delay is used between each iteration to ensure the network does not get too
congested. */ * congested. */
#define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS ) #define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS )
/* The echo server is assumed to be on port 7, which is the standard echo /* The echo server is assumed to be on port 7, which is the standard echo
protocol port. */ * protocol port. */
#define echoECHO_PORT ( 7 ) #define echoECHO_PORT ( 7 )
/* The size of the buffers is a multiple of the MSS - the length of the data /* The size of the buffers is a multiple of the MSS - the length of the data
sent is a pseudo random size between 20 and echoBUFFER_SIZES. */ * sent is a pseudo random size between 20 and echoBUFFER_SIZES. */
#define echoBUFFER_SIZE_MULTIPLIER ( 1 ) #define echoBUFFER_SIZE_MULTIPLIER ( 1 )
#define echoBUFFER_SIZES ( ipconfigTCP_MSS * echoBUFFER_SIZE_MULTIPLIER ) #define echoBUFFER_SIZES ( ipconfigTCP_MSS * echoBUFFER_SIZE_MULTIPLIER )
/* The number of instances of the echo client task to create. */ /* The number of instances of the echo client task to create. */
#define echoNUM_ECHO_CLIENTS ( 1 ) #define echoNUM_ECHO_CLIENTS ( 1 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -77,302 +77,303 @@ sent is a pseudo random size between 20 and echoBUFFER_SIZES. */
* Uses a socket to send data to, then receive data from, the standard echo * Uses a socket to send data to, then receive data from, the standard echo
* port number 7. * port number 7.
*/ */
static void prvEchoClientTask( void *pvParameters ); static void prvEchoClientTask( void * pvParameters );
/* /*
* Creates a pseudo random sized buffer of data to send to the echo server. * Creates a pseudo random sized buffer of data to send to the echo server.
*/ */
static BaseType_t prvCreateTxData( char *ucBuffer, static BaseType_t prvCreateTxData( char * ucBuffer,
uint32_t ulBufferLength ); uint32_t ulBufferLength );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Rx and Tx time outs are used to ensure the sockets do not wait too long for /* Rx and Tx time outs are used to ensure the sockets do not wait too long for
missing data. */ * missing data. */
static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 ); static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 );
static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 ); static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 );
/* Counters for each created task - for inspection only. */ /* Counters for each created task - for inspection only. */
static uint32_t ulTxRxCycles[ echoNUM_ECHO_CLIENTS ] = { 0 }, static uint32_t ulTxRxCycles[ echoNUM_ECHO_CLIENTS ] = { 0 },
ulTxRxFailures[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulTxRxFailures[ echoNUM_ECHO_CLIENTS ] = { 0 },
ulConnections[ echoNUM_ECHO_CLIENTS ] = { 0 }; ulConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
/* Rx and Tx buffers for each created task. */ /* Rx and Tx buffers for each created task. */
static char cTxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ], static char cTxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ],
cRxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ]; cRxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ];
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority ) UBaseType_t uxTaskPriority )
{ {
BaseType_t x; BaseType_t x;
/* Create the echo client tasks. */ /* Create the echo client tasks. */
for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ ) for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
{ {
xTaskCreate( prvEchoClientTask, /* The function that implements the task. */ xTaskCreate( prvEchoClientTask, /* The function that implements the task. */
"Echo0", /* Just a text name for the task to aid debugging. */ "Echo0", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
( void * ) x, /* The task parameter, not used in this case. */ ( void * ) x, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL ); /* The task handle is not used. */ NULL ); /* The task handle is not used. */
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvEchoClientTask( void *pvParameters ) static void prvEchoClientTask( void * pvParameters )
{ {
Socket_t xSocket; Socket_t xSocket;
struct freertos_sockaddr xEchoServerAddress; struct freertos_sockaddr xEchoServerAddress;
int32_t lLoopCount = 0UL; int32_t lLoopCount = 0UL;
const int32_t lMaxLoopCount = 1; const int32_t lMaxLoopCount = 1;
volatile uint32_t ulTxCount = 0UL; volatile uint32_t ulTxCount = 0UL;
BaseType_t xReceivedBytes, xReturned, xInstance; BaseType_t xReceivedBytes, xReturned, xInstance;
BaseType_t lTransmitted, lStringLength; BaseType_t lTransmitted, lStringLength;
char *pcTransmittedString, *pcReceivedString; char * pcTransmittedString, * pcReceivedString;
WinProperties_t xWinProps; WinProperties_t xWinProps;
TickType_t xTimeOnEntering; TickType_t xTimeOnEntering;
BaseType_t ret; BaseType_t ret;
/* Fill in the buffer and window sizes that will be used by the socket. */ /* Fill in the buffer and window sizes that will be used by the socket. */
xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS;
xWinProps.lTxWinSize = 3; xWinProps.lTxWinSize = 3;
xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS; xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS;
xWinProps.lRxWinSize = 3; xWinProps.lRxWinSize = 3;
/* This task can be created a number of times. Each instance is numbered /* This task can be created a number of times. Each instance is numbered
to enable each instance to use a different Rx and Tx buffer. The number is * to enable each instance to use a different Rx and Tx buffer. The number is
passed in as the task's parameter. */ * passed in as the task's parameter. */
xInstance = ( BaseType_t ) pvParameters; xInstance = ( BaseType_t ) pvParameters;
/* Point to the buffers to be used by this instance of this task. */ /* Point to the buffers to be used by this instance of this task. */
pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] ); pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] );
pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] ); pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] );
/* Echo requests are sent to the echo server. The address of the echo /* Echo requests are sent to the echo server. The address of the echo
server is configured by the constants configECHO_SERVER_ADDR0 to * server is configured by the constants configECHO_SERVER_ADDR0 to
configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ * configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 ); configECHO_SERVER_ADDR3 );
for( ; ; ) for( ; ; )
{ {
/* Create a TCP socket. */ /* Create a TCP socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP ); xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
/* Set a time out so a missing reply does not cause the task to block /* Set a time out so a missing reply does not cause the task to block
indefinitely. */ * indefinitely. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
/* Set the window and buffer sizes. */ /* Set the window and buffer sizes. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
/* Connect to the echo server. */ /* Connect to the echo server. */
printf( "connecting to echo server....\n" ); printf( "connecting to echo server....\n" );
ret = FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ); ret = FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) );
if( ret == 0 ) if( ret == 0 )
{ {
printf( "Connected to server.. \n" ); printf( "Connected to server.. \n" );
ulConnections[ xInstance ]++; ulConnections[ xInstance ]++;
/* Send a number of echo requests. */ /* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{ {
/* Create the string that is sent to the echo server. */ /* Create the string that is sent to the echo server. */
lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES ); lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES );
/* Add in some unique text at the front of the string. */ /* Add in some unique text at the front of the string. */
sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount ); sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount );
ulTxCount++; ulTxCount++;
printf( "sending data to the echo server size %d original %d\n", printf( "sending data to the echo server size %d original %d\n",
lStringLength, lStringLength,
echoBUFFER_SIZES); echoBUFFER_SIZES );
/* Send the string to the socket. */ /* Send the string to the socket. */
lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */ lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */
( void * ) pcTransmittedString, /* The data being sent. */ ( void * ) pcTransmittedString, /* The data being sent. */
lStringLength, /* The length of the data being sent. */ lStringLength, /* The length of the data being sent. */
0 ); /* No flags. */ 0 ); /* No flags. */
printf("FreeRTOS_send returned...transmitted %d\n", printf( "FreeRTOS_send returned...transmitted %d\n",
lTransmitted); lTransmitted );
if( lTransmitted < 0 ) if( lTransmitted < 0 )
{ {
/* Error? */ /* Error? */
break; break;
} }
printf("data send receiving data... \n");
/* Clear the buffer into which the echoed string will be printf( "data send receiving data... \n" );
placed. */
memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );
xReceivedBytes = 0;
/* Receive data echoed back to the socket. */ /* Clear the buffer into which the echoed string will be
while( xReceivedBytes < lTransmitted ) * placed. */
{ memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );
xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ xReceivedBytes = 0;
&( pcReceivedString[ xReceivedBytes ] ), /* The buffer into which the received data will be written. */
lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */
0 ); /* No flags. */
if( xReturned < 0 ) /* Receive data echoed back to the socket. */
{ while( xReceivedBytes < lTransmitted )
/* Error occurred. Latch it so it can be detected {
below. */ xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
xReceivedBytes = xReturned; &( pcReceivedString[ xReceivedBytes ] ), /* The buffer into which the received data will be written. */
break; lStringLength - xReceivedBytes, /* The size of the buffer provided to receive the data. */
} 0 ); /* No flags. */
else if( xReturned == 0 )
{
/* Timed out. */
break;
}
else
{
/* Keep a count of the bytes received so far. */
xReceivedBytes += xReturned;
}
}
/* If an error occurred it will be latched in xReceivedBytes, if( xReturned < 0 )
otherwise xReceived bytes will be just that - the number of {
bytes received from the echo server. */ /* Error occurred. Latch it so it can be detected
if( xReceivedBytes > 0 ) * below. */
{ xReceivedBytes = xReturned;
/* Compare the transmitted string to the received string. */ break;
configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ); }
else if( xReturned == 0 )
{
/* Timed out. */
break;
}
else
{
/* Keep a count of the bytes received so far. */
xReceivedBytes += xReturned;
}
}
if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 ) /* If an error occurred it will be latched in xReceivedBytes,
{ * otherwise xReceived bytes will be just that - the number of
/* The echo reply was received without error. */ * bytes received from the echo server. */
ulTxRxCycles[ xInstance ]++; if( xReceivedBytes > 0 )
} {
else /* Compare the transmitted string to the received string. */
{ configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 );
/* The received string did not match the transmitted
string. */
ulTxRxFailures[ xInstance ]++;
break;
}
}
else if( xReceivedBytes < 0 )
{
/* FreeRTOS_recv() returned an error. */
break;
}
else
{
/* Timed out without receiving anything? */
break;
}
}
/* Finished using the connected socket, initiate a graceful close: if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 )
FIN, FIN+ACK, ACK. */ {
FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR ); /* The echo reply was received without error. */
ulTxRxCycles[ xInstance ]++;
}
else
{
/* The received string did not match the transmitted
* string. */
ulTxRxFailures[ xInstance ]++;
break;
}
}
else if( xReceivedBytes < 0 )
{
/* FreeRTOS_recv() returned an error. */
break;
}
else
{
/* Timed out without receiving anything? */
break;
}
}
/* Expect FreeRTOS_recv() to return an error once the shutdown is /* Finished using the connected socket, initiate a graceful close:
complete. */ * FIN, FIN+ACK, ACK. */
xTimeOnEntering = xTaskGetTickCount(); FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
do /* Expect FreeRTOS_recv() to return an error once the shutdown is
{ * complete. */
xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ xTimeOnEntering = xTaskGetTickCount();
&( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */
echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */
0 );
if( xReturned < 0 ) do
{ {
break; xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */
} &( pcReceivedString[ 0 ] ), /* The buffer into which the received data will be written. */
} while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut ); echoBUFFER_SIZES, /* The size of the buffer provided to receive the data. */
} 0 );
else
{
printf( "Could not connect to server %ld\n", ret );
}
/* Close this socket before looping back to create another. */ if( xReturned < 0 )
FreeRTOS_closesocket( xSocket ); {
break;
}
} while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );
}
else
{
printf( "Could not connect to server %ld\n", ret );
}
/* Pause for a short while to ensure the network is not too /* Close this socket before looping back to create another. */
congested. */ FreeRTOS_closesocket( xSocket );
vTaskDelay( echoLOOP_DELAY );
} /* Pause for a short while to ensure the network is not too
} * congested. */
vTaskDelay( echoLOOP_DELAY );
}
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvCreateTxData( char *cBuffer, static BaseType_t prvCreateTxData( char * cBuffer,
uint32_t ulBufferLength ) uint32_t ulBufferLength )
{ {
BaseType_t lCharactersToAdd, lCharacter; BaseType_t lCharactersToAdd, lCharacter;
char cChar = '0'; char cChar = '0';
const BaseType_t lMinimumLength = 60; const BaseType_t lMinimumLength = 60;
uint32_t ulRandomNumber; uint32_t ulRandomNumber;
/* Randomise the number of characters that will be sent in the echo /* Randomise the number of characters that will be sent in the echo
request. */ * request. */
do do
{ {
( void ) xApplicationGetRandomNumber( &ulRandomNumber ); ( void ) xApplicationGetRandomNumber( &ulRandomNumber );
lCharactersToAdd = ulRandomNumber % ( ulBufferLength - 20UL ); lCharactersToAdd = ulRandomNumber % ( ulBufferLength - 20UL );
} while( ( lCharactersToAdd == 0 ) || ( lCharactersToAdd < lMinimumLength ) ); /* Must be at least enough to add the unique text to the start of the string later. */ } while( ( lCharactersToAdd == 0 ) || ( lCharactersToAdd < lMinimumLength ) ); /* Must be at least enough to add the unique text to the start of the string later. */
/* Fill the buffer. */ /* Fill the buffer. */
for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ ) for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )
{ {
cBuffer[ lCharacter ] = cChar; cBuffer[ lCharacter ] = cChar;
cChar++; cChar++;
if( cChar > '~' ) if( cChar > '~' )
{ {
cChar = '0'; cChar = '0';
} }
} }
return lCharactersToAdd; return lCharactersToAdd;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void ) BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void )
{ {
static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 }; static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };
BaseType_t xReturn = pdPASS, x; BaseType_t xReturn = pdPASS, x;
/* Return fail is the number of cycles does not increment between /* Return fail is the number of cycles does not increment between
consecutive calls. */ * consecutive calls. */
for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ ) for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )
{ {
if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] ) if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] )
{ {
xReturn = pdFAIL; xReturn = pdFAIL;
} }
else else
{ {
ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ]; ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ];
} }
if( ulConnections[ x ] == ulLastConnections[ x ] ) if( ulConnections[ x ] == ulLastConnections[ x ] )
{ {
xReturn = pdFAIL; xReturn = pdFAIL;
} }
else else
{ {
ulConnections[ x ] = ulLastConnections[ x ]; ulConnections[ x ] = ulLastConnections[ x ];
} }
} }
return xReturn; return xReturn;
} }
#endif /* ipconfigUSE_TCP */ #endif /* ipconfigUSE_TCP */

View file

@ -37,48 +37,50 @@ extern void xPortSysTickHandler( void );
extern void uart_init(); extern void uart_init();
extern int main(); extern int main();
void __attribute__((weak)) EthernetISR (void); void __attribute__( ( weak ) ) EthernetISR( void );
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
/* Prevent optimization so gcc does not replace code with memcpy */ /* Prevent optimization so gcc does not replace code with memcpy */
__attribute__((optimize("O0"))) __attribute__( ( optimize( "O0" ) ) )
__attribute__((naked)) __attribute__( ( naked ) )
void Reset_Handler(void) void Reset_Handler( void )
{ {
// set stack pointer /* set stack pointer */
__asm volatile ("ldr r0, =_estack"); __asm volatile ( "ldr r0, =_estack" );
__asm volatile ("mov sp, r0"); __asm volatile ( "mov sp, r0" );
// copy .data section from flash to RAM
for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) /* copy .data section from flash to RAM */
for( uint32_t * src = &_sidata, * dest = &_sdata; dest < &_edata; )
{ {
*dest++ = *src++; *dest++ = *src++;
} }
// zero out .bss section /* zero out .bss section */
for (uint32_t *dest = &_sbss; dest < &_ebss;) for( uint32_t * dest = &_sbss; dest < &_ebss; )
{ {
*dest++ = 0; *dest++ = 0;
} }
// jump to board initialisation
void _start(void); /* jump to board initialisation */
void _start( void );
_start(); _start();
} }
void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress ) void prvGetRegistersFromStack( uint32_t * pulFaultStackAddress )
{ {
/* These are volatile to try and prevent the compiler/linker optimising them /* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used. If the debugger won't show the * away as the variables never actually get used. If the debugger won't show the
values of the variables, make them global my moving their declaration outside * values of the variables, make them global my moving their declaration outside
of this function. */ * of this function. */
volatile uint32_t r0; volatile uint32_t r0;
volatile uint32_t r1; volatile uint32_t r1;
volatile uint32_t r2; volatile uint32_t r2;
volatile uint32_t r3; volatile uint32_t r3;
volatile uint32_t r12; volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */ volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */ volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */ volatile uint32_t psr; /* Program status register. */
r0 = pulFaultStackAddress[ 0 ]; r0 = pulFaultStackAddress[ 0 ];
r1 = pulFaultStackAddress[ 1 ]; r1 = pulFaultStackAddress[ 1 ];
@ -91,11 +93,13 @@ of this function. */
psr = pulFaultStackAddress[ 7 ]; psr = pulFaultStackAddress[ 7 ];
/* When the following line is hit, the variables contain the register values. */ /* When the following line is hit, the variables contain the register values. */
for( ;; ); for( ; ; )
{
}
} }
static void Default_Handler( void ) __attribute__( ( naked ) ); static void Default_Handler( void ) __attribute__( ( naked ) );
void Default_Handler(void) void Default_Handler( void )
{ {
__asm volatile __asm volatile
( (
@ -111,9 +115,8 @@ void Default_Handler(void)
); );
} }
static void HardFault_Handler( void ) __attribute__( ( naked ) ); static void HardFault_Handler( void ) __attribute__( ( naked ) );
void Default_Handler2(void) void Default_Handler2( void )
{ {
__asm volatile __asm volatile
( (
" tst lr, #4 \n" " tst lr, #4 \n"
@ -127,79 +130,86 @@ void Default_Handler2(void)
); );
} }
void Default_Handler3(void) void Default_Handler3( void )
{ {
for (;;) { } for( ; ; )
{
}
} }
void Default_Handler4(void) void Default_Handler4( void )
{ {
for (;;) { } for( ; ; )
{
}
} }
void Default_Handler5(void) void Default_Handler5( void )
{ {
for (;;) { } for( ; ; )
{
}
} }
void Default_Handler6(void) void Default_Handler6( void )
{ {
for (;;) { } for( ; ; )
{
}
} }
const uint32_t* isr_vector[] __attribute__((section(".isr_vector"))) = const uint32_t * isr_vector[] __attribute__( ( section( ".isr_vector" ) ) ) =
{ {
(uint32_t*)&_estack, ( uint32_t * ) &_estack,
(uint32_t*)&Reset_Handler, // Reset -15 ( uint32_t * ) &Reset_Handler, /* Reset -15 */
(uint32_t*)&Default_Handler, // NMI_Handler -14 ( uint32_t * ) &Default_Handler, /* NMI_Handler -14 */
(uint32_t*)&Default_Handler2, // HardFault_Handler -13 ( uint32_t * ) &Default_Handler2, /* HardFault_Handler -13 */
(uint32_t*)&Default_Handler3, // MemManage_Handler -12 ( uint32_t * ) &Default_Handler3, /* MemManage_Handler -12 */
(uint32_t*)&Default_Handler4, // BusFault_Handler -11 ( uint32_t * ) &Default_Handler4, /* BusFault_Handler -11 */
(uint32_t*)&Default_Handler5, // UsageFault_Handler -10 ( uint32_t * ) &Default_Handler5, /* UsageFault_Handler -10 */
0, // reserved 0, /* reserved */
0, // reserved 0, /* reserved */
0, // reserved 0, /* reserved */
0, // reserved -6 0, /* reserved -6 */
(uint32_t*)&vPortSVCHandler, // SVC_Handler -5 ( uint32_t * ) &vPortSVCHandler, /* SVC_Handler -5 */
(uint32_t*)&Default_Handler6, // DebugMon_Handler -4 ( uint32_t * ) &Default_Handler6, /* DebugMon_Handler -4 */
0, // reserved 0, /* reserved */
(uint32_t*)&xPortPendSVHandler, // PendSV handler -2 ( uint32_t * ) &xPortPendSVHandler, /* PendSV handler -2 */
(uint32_t*)&xPortSysTickHandler, // SysTick_Handler -1 ( uint32_t * ) &xPortSysTickHandler, /* SysTick_Handler -1 */
0, // uart0 receive 0 0, /* uart0 receive 0 */
0, // uart0 transmit 0, /* uart0 transmit */
0, // uart1 receive 0, /* uart1 receive */
0, // uart1 transmit 0, /* uart1 transmit */
0, // uart 2 receive 0, /* uart 2 receive */
0, // uart 2 transmit 0, /* uart 2 transmit */
0, // GPIO 0 combined interrupt 0, /* GPIO 0 combined interrupt */
0, // GPIO 2 combined interrupt 0, /* GPIO 2 combined interrupt */
0, // Timer 0 0, /* Timer 0 */
0, // Timer 1 0, /* Timer 1 */
0, // Dial Timer 0, /* Dial Timer */
0, // SPI0 SPI1 0, /* SPI0 SPI1 */
0, // uart overflow 1 2,3 12 0, /* uart overflow 1 2,3 12 */
(uint32_t*)&EthernetISR, // Ethernet 13 ( uint32_t * ) &EthernetISR, /* Ethernet 13 */
}; };
void _start(void) void _start( void )
{ {
uart_init(); uart_init();
main(0, 0); main( 0, 0 );
exit(0); exit( 0 );
} }
__attribute__((naked)) void exit(int status) __attribute__( ( naked ) ) void exit( int status )
{ {
// Force qemu to exit using ARM Semihosting /* Force qemu to exit using ARM Semihosting */
__asm volatile ( __asm volatile (
"mov r1, r0\n" "mov r1, r0\n"
"cmp r1, #0\n" "cmp r1, #0\n"
"bne .notclean\n" "bne .notclean\n"
"ldr r1, =0x20026\n" // ADP_Stopped_ApplicationExit, a clean exit "ldr r1, =0x20026\n" /* ADP_Stopped_ApplicationExit, a clean exit */
".notclean:\n" ".notclean:\n"
"movs r0, #0x18\n" // SYS_EXIT "movs r0, #0x18\n" /* SYS_EXIT */
"bkpt 0xab\n" "bkpt 0xab\n"
"end: b end\n" "end: b end\n"
); );
} }

View file

@ -43,16 +43,7 @@ extern void initialise_monitor_handles(void);
int main () int main ()
{ {
#if ( mainCREATE_NETWORKING_DEMO_ONLY == 1 ) main_tcp_echo_client_tasks();
{
main_tcp_echo_client_tasks();
}
#else
{
#error "Invalid Selection..." \
"\nPlease Select a Demo application from the main command"
}
#endif
return 0; return 0;
} }

View file

@ -26,8 +26,7 @@
/* /*
* This project is a cut down version of the project described on the following * This project is a cut down version of the project described on the following
* link. Only the simple UDP client and server and the TCP echo clients are * link. Only the TCP echo clients is included in the build:
* included in the build:
* https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html * https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
*/ */
@ -44,26 +43,15 @@
/* Demo application includes. */ /* Demo application includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
/*#include "SimpleUDPClientAndServer.h" */
/*#include "SimpleTCPEchoServer.h" */
/*#include "logging.h" */
#include "TCPEchoClient_SingleTasks.h" #include "TCPEchoClient_SingleTasks.h"
/* Simple UDP client and server task parameters. */ /* Echo client task parameters */
#define mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainECHO_CLIENT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* Not used in the linux port. */
#define mainSIMPLE_UDP_CLIENT_SERVER_PORT ( 5005UL ) #define mainECHO_CLIENT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Echo client task parameters - used for both TCP and UDP echo clients. */
#define mainECHO_CLIENT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* Not used in the linux port. */
#define mainECHO_CLIENT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Echo server task parameters. */
#define mainECHO_SERVER_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) /* Not used in the linux port. */
#define mainECHO_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
/* Define a name that will be used for LLMNR and NBNS searches. */ /* Define a name that will be used for LLMNR and NBNS searches. */
#define mainHOST_NAME "RTOSDemo" #define mainHOST_NAME "RTOSDemo"
#define mainDEVICE_NICK_NAME "qemu_demo" #define mainDEVICE_NICK_NAME "qemu_demo"
/* Set the following constants to 1 or 0 to define which tasks to include and /* Set the following constants to 1 or 0 to define which tasks to include and
* exclude: * exclude:
@ -94,43 +82,43 @@ static void prvMiscInitialisation( void );
* defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is * defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is
* 1 but a DHCP server could not be contacted. See the online documentation for * 1 but a DHCP server could not be contacted. See the online documentation for
* more information. */ * more information. */
static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, static const uint8_t ucIPAddress[ 4 ] =
configIP_ADDR1, {
configIP_ADDR2, configIP_ADDR0,
configIP_ADDR3 configIP_ADDR1,
}; configIP_ADDR2,
static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configIP_ADDR3
configNET_MASK1, };
configNET_MASK2, static const uint8_t ucNetMask[ 4 ] =
configNET_MASK3 {
}; configNET_MASK0,
static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configNET_MASK1,
configGATEWAY_ADDR1, configNET_MASK2,
configGATEWAY_ADDR2, configNET_MASK3
configGATEWAY_ADDR3 };
}; static const uint8_t ucGatewayAddress[ 4 ] =
static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, {
configDNS_SERVER_ADDR1, configGATEWAY_ADDR0,
configDNS_SERVER_ADDR2, configGATEWAY_ADDR1,
configDNS_SERVER_ADDR3 configGATEWAY_ADDR2,
}; configGATEWAY_ADDR3
const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, };
configMAC_ADDR1, static const uint8_t ucDNSServerAddress[ 4 ] =
configMAC_ADDR2, {
configMAC_ADDR3, configDNS_SERVER_ADDR0,
configMAC_ADDR4, configDNS_SERVER_ADDR1,
configMAC_ADDR5 configDNS_SERVER_ADDR2,
}; configDNS_SERVER_ADDR3
};
/* Set the following constant to pdTRUE to log using the method indicated by the const uint8_t ucMACAddress[ 6 ] =
* name of the constant, or pdFALSE to not log using the method indicated by the {
* name of the constant. Options include to standard out (xLogToStdout), to a disk configMAC_ADDR0,
* file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE configMAC_ADDR1,
* then UDP messages are sent to the IP address configured as the echo server configMAC_ADDR2,
* address (see the configECHO_SERVER_ADDR0 definitions in FreeRTOSConfig.h) and configMAC_ADDR3,
* the port number set by configPRINT_PORT in FreeRTOSConfig.h. */ configMAC_ADDR4,
//const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE; configMAC_ADDR5
};
/* Use by the pseudo random number generator. */ /* Use by the pseudo random number generator. */
static UBaseType_t ulNextRand; static UBaseType_t ulNextRand;
@ -182,7 +170,8 @@ void main_tcp_echo_client_tasks( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xTasksAlreadyCreated = pdFALSE; BaseType_t xTasksAlreadyCreated = pdFALSE;
/* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect /* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect
* events are only received if implemented in the MAC driver. */ * events are only received if implemented in the MAC driver. */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
@ -205,10 +194,10 @@ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
* demo tasks. */ * demo tasks. */
#if ( mainCREATE_TCP_ECHO_TASKS_SINGLE == 1 ) #if ( mainCREATE_TCP_ECHO_TASKS_SINGLE == 1 )
{ {
vStartTCPEchoClientTasks_SingleTasks( mainECHO_CLIENT_TASK_STACK_SIZE, vStartTCPEchoClientTasks_SingleTasks( mainECHO_CLIENT_TASK_STACK_SIZE,
mainECHO_CLIENT_TASK_PRIORITY ); mainECHO_CLIENT_TASK_PRIORITY );
} }
#endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */ #endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */
xTasksAlreadyCreated = pdTRUE; xTasksAlreadyCreated = pdTRUE;
@ -231,7 +220,7 @@ void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
} }
else else
{ {
FreeRTOS_printf( ("Application idle hook network down\n") ); FreeRTOS_printf( ( "Application idle hook network down\n" ) );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/