Update the A2F SoftConsole project to match the current A2F IAR project.

pull/4/head
Richard Barry 14 years ago
parent 9b6bd9e419
commit 5831485bdf

@ -1,38 +1,44 @@
/* /*
FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd. FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.
FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:
Atollic AB - Atollic provides professional embedded systems development
tools for C/C++ development, code analysis and test automation.
See http://www.atollic.com
*************************************************************************** ***************************************************************************
* * * *
* If you are: * * FreeRTOS tutorial books are available in pdf and paperback. *
* * * Complete, revised, and edited pdf reference manuals are also *
* + New to FreeRTOS, * * available. *
* + Wanting to learn FreeRTOS or multitasking in general quickly * * *
* + Looking for basic training, * * Purchasing FreeRTOS documentation will not only help you, by *
* + Wanting to improve your FreeRTOS skills and productivity * * ensuring you get running as quickly as possible and with an *
* * * in-depth knowledge of how to use FreeRTOS, it will also help *
* then take a look at the FreeRTOS books - available as PDF or paperback * * the FreeRTOS project to continue with its mission of providing *
* * * professional grade, cross platform, de facto standard solutions *
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" * * for microcontrollers - completely free of charge! *
* http://www.FreeRTOS.org/Documentation * * *
* * * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
* A pdf reference manual is also available. Both are usually delivered * * *
* to your inbox within 20 minutes to two hours when purchased between 8am * * Thank you for using FreeRTOS, and thank you for your support! *
* and 8pm GMT (although please allow up to 24 hours in case of * * *
* exceptional circumstances). Thank you for your support! *
* *
*************************************************************************** ***************************************************************************
This file is part of the FreeRTOS distribution. This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception. Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
***NOTE*** The exception to the GPL is included to allow you to distribute >>>NOTE<<< The modification to the GPL is included to allow you to
a combined work that includes FreeRTOS without being obliged to provide the distribute a combined work that includes FreeRTOS without being obliged to
source code for proprietary components outside of the FreeRTOS kernel. provide the source code for proprietary components outside of the FreeRTOS
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT kernel. FreeRTOS is distributed in the hope that it will be useful, but
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 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 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 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 can be viewed here: http://www.freertos.org/a00114.html and also obtained
@ -57,12 +63,15 @@
* executed from within CCS4! Once it has been executed, re-open or refresh * executed from within CCS4! Once it has been executed, re-open or refresh
* the CCS4 project and remove the #error line below. * the CCS4 project and remove the #error line below.
*/ */
//#error Ensure CreateProjectDirectoryStructure.bat has been executed before building. See comment immediately above. #error Ensure CreateProjectDirectoryStructure.bat has been executed before building. See comment immediately above.
#ifndef FREERTOS_CONFIG_H #ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H
#include <stdint.h>
#include <stddef.h>
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Application specific definitions. * Application specific definitions.
* *
@ -75,21 +84,23 @@
* See http://www.freertos.org/a00110.html. * See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern uint32_t SystemFrequency;
#define configUSE_PREEMPTION 1 #define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1 #define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 0 #define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( 75000000UL ) #define configCPU_CLOCK_HZ ( SystemFrequency )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 90 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 40 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 ) #define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1 #define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1 #define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 0 #define configQUEUE_REGISTRY_SIZE 0
#define configGENERATE_RUN_TIME_STATS 0 #define configGENERATE_RUN_TIME_STATS 1
#define configCHECK_FOR_STACK_OVERFLOW 2 #define configCHECK_FOR_STACK_OVERFLOW 2
#define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 1 #define configUSE_MALLOC_FAILED_HOOK 1
@ -102,7 +113,7 @@
/* Software timer definitions. */ /* Software timer definitions. */
#define configUSE_TIMERS 1 #define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 3 ) #define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 10 #define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
@ -116,6 +127,11 @@ to exclude the API function. */
#define INCLUDE_vTaskDelayUntil 1 #define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1 #define INCLUDE_vTaskDelay 1
void vMainConfigureTimerForRunTimeStats( void );
unsigned long ulGetRunTimeCounterValue( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vMainConfigureTimerForRunTimeStats()
#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue()
/* Use the system definition, if there is one */ /* Use the system definition, if there is one */
#ifdef __NVIC_PRIO_BITS #ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS #define configPRIO_BITS __NVIC_PRIO_BITS

@ -7,6 +7,8 @@
* SVN $Revision: 2152 $ * SVN $Revision: 2152 $
* SVN $Date: 2010-02-11 14:44:11 +0000 (Thu, 11 Feb 2010) $ * SVN $Date: 2010-02-11 14:44:11 +0000 (Thu, 11 Feb 2010) $
*/ */
#include "i2c.h" #include "i2c.h"
#include "../../CMSIS/mss_assert.h" #include "../../CMSIS/mss_assert.h"
@ -145,6 +147,14 @@ void MSS_I2C_init
this_i2c->hw_reg_bit->CTRL_CR1 = (clock_speed >> 1) & 0x01; this_i2c->hw_reg_bit->CTRL_CR1 = (clock_speed >> 1) & 0x01;
this_i2c->hw_reg_bit->CTRL_CR0 = clock_speed & 0x01; this_i2c->hw_reg_bit->CTRL_CR0 = clock_speed & 0x01;
this_i2c->hw_reg->ADDR = this_i2c->ser_address; this_i2c->hw_reg->ADDR = this_i2c->ser_address;
/* The interrupt can cause a context switch, so ensure its priority is
between configKERNEL_INTERRUPT_PRIORITY and configMAX_SYSCALL_INTERRUPT_PRIORITY. */
NVIC_SetPriority( this_i2c->irqn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
vSemaphoreCreateBinary( ( this_i2c->xI2CCompleteSemaphore ) );
xSemaphoreTake( ( this_i2c->xI2CCompleteSemaphore ), 0 );
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -196,6 +206,7 @@ void MSS_I2C_write
uint32_t primask; uint32_t primask;
ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) ); ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) );
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
primask = disable_interrupts(); primask = disable_interrupts();
@ -431,11 +442,28 @@ mss_i2c_status_t MSS_I2C_wait_complete
{ {
ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) ); ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) );
#ifdef USE_OLD_I2C_POLLING_CODE
while ( this_i2c->status == MSS_I2C_IN_PROGRESS ) while ( this_i2c->status == MSS_I2C_IN_PROGRESS )
{ {
/* Wait for transaction to compltete.*/ /* Wait for transaction to compltete.*/
; ;
} }
#else
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
if( xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED )
{
while ( this_i2c->status == MSS_I2C_IN_PROGRESS )
{
/* Wait for transaction to compltete.*/
;
}
}
else
{
xSemaphoreTake( this_i2c->xI2CCompleteSemaphore, portMAX_DELAY );
}
#endif
return this_i2c->status; return this_i2c->status;
} }
@ -451,12 +479,14 @@ mss_i2c_status_t MSS_I2C_wait_complete
static void mss_i2c_isr static void mss_i2c_isr
( (
mss_i2c_instance_t * this_i2c mss_i2c_instance_t * this_i2c
) )
{ {
volatile uint8_t status; volatile uint8_t status;
uint8_t data; uint8_t data;
uint8_t hold_bus; uint8_t hold_bus;
uint8_t clear_irq = 1; uint8_t clear_irq = 1;
long lHigherPriorityTaskWoken = pdFALSE;
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) ); ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) );
@ -539,6 +569,7 @@ static void mss_i2c_isr
clear_irq = 0; clear_irq = 0;
} }
this_i2c->status = MSS_I2C_SUCCESS; this_i2c->status = MSS_I2C_SUCCESS;
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
} }
break; break;
@ -577,6 +608,7 @@ static void mss_i2c_isr
clear_irq = 0; clear_irq = 0;
} }
this_i2c->status = MSS_I2C_SUCCESS; this_i2c->status = MSS_I2C_SUCCESS;
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
} }
break; break;
@ -600,6 +632,7 @@ static void mss_i2c_isr
case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
this_i2c->hw_reg_bit->CTRL_STO = 0x01; this_i2c->hw_reg_bit->CTRL_STO = 0x01;
this_i2c->status = MSS_I2C_FAILED; this_i2c->status = MSS_I2C_FAILED;
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
break; break;
case ST_RX_DATA_ACK: /* Data byte received, ACK returned */ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
@ -630,6 +663,7 @@ static void mss_i2c_isr
} }
this_i2c->status = MSS_I2C_SUCCESS; this_i2c->status = MSS_I2C_SUCCESS;
// xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
break; break;
/******************** SLAVE RECEIVER **************************/ /******************** SLAVE RECEIVER **************************/
@ -696,6 +730,7 @@ static void mss_i2c_isr
} }
/* Mark any previous master write transaction as complete. */ /* Mark any previous master write transaction as complete. */
this_i2c->status = MSS_I2C_SUCCESS; this_i2c->status = MSS_I2C_SUCCESS;
// xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
break; break;
case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
@ -747,6 +782,8 @@ static void mss_i2c_isr
/* Read the status register to ensure the last I2C registers write took place /* Read the status register to ensure the last I2C registers write took place
* in a system built around a bus making use of posted writes. */ * in a system built around a bus making use of posted writes. */
status = this_i2c->hw_reg->STATUS; status = this_i2c->hw_reg->STATUS;
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
} }
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------

@ -194,6 +194,11 @@
#include "../../CMSIS/a2fxxxm3.h" #include "../../CMSIS/a2fxxxm3.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -324,7 +329,10 @@ typedef struct mss_i2c_instance
/* Slave data: */ /* Slave data: */
uint_fast8_t slave_mem_offset_length; uint_fast8_t slave_mem_offset_length;
mss_i2c_slave_wr_handler_t slave_write_handler; mss_i2c_slave_wr_handler_t slave_write_handler;
/* Used to get access to and wait for completion of an I2C transaction. */
xSemaphoreHandle xI2CCompleteSemaphore;
} mss_i2c_instance_t; } mss_i2c_instance_t;
/*-------------------------------------------------------------------------*//** /*-------------------------------------------------------------------------*//**

@ -9,9 +9,18 @@
* *
******************************************************************************/ ******************************************************************************/
/*
*
*
* NOTE: This driver has been modified specifically for use with the* uIP stack.
* It is no longer a generic driver.
*
*
*/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -29,7 +38,7 @@ extern "C" {
/**************************** INTERNAL DEFINES ********************************/ /**************************** INTERNAL DEFINES ********************************/
#define MAC_CHECK(CHECK,ERRNO) \ #define MAC_CHECK(CHECK,ERRNO) \
{if(!(CHECK)){g_mss_mac.last_error=(ERRNO); ASSERT((CHECK));}} {if(!(CHECK)){g_mss_mac.last_error=(ERRNO); configASSERT((CHECK));}}
/* /*
* Flags * Flags
@ -54,8 +63,8 @@ extern "C" {
/* Allocating this many buffers will always ensure there is one free as, even /* Allocating this many buffers will always ensure there is one free as, even
though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
to the same buffer. */ to the same buffer. */
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE #define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 1
#define macBUFFER_SIZE 1500 #define macBUFFER_SIZE 1488
/***************************************************************/ /***************************************************************/
MAC_instance_t g_mss_mac; MAC_instance_t g_mss_mac;
@ -78,15 +87,16 @@ static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
/* /*
* Null variables * Null variables
*/ */
static MAC_instance_t* NULL_instance;
static uint8_t* NULL_buffer; static uint8_t* NULL_buffer;
static MSS_MAC_callback_t NULL_callback; static MSS_MAC_callback_t NULL_callback;
/* Declare the uip_buf as a pointer, rather than the traditional array, as this
is a zero copy driver. uip_buf just gets set to whichever buffer is being
processed. */
unsigned char *uip_buf = NULL; unsigned char *uip_buf = NULL;
/**************************** INTERNAL FUNCTIONS ******************************/ /**************************** INTERNAL FUNCTIONS ******************************/
static int32_t MAC_test_instance( void );
static int32_t MAC_dismiss_bad_frames( void ); static int32_t MAC_dismiss_bad_frames( void );
static int32_t MAC_send_setup_frame( void ); static int32_t MAC_send_setup_frame( void );
@ -109,12 +119,17 @@ static void MAC_release_buffer( unsigned char *pcBufferToRelease );
#error This uIP Ethernet driver required TX_RING_SIZE to be set to 2 #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2
#endif #endif
/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */ /* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.
static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ]; The union is used for alignment only. */
static union xMAC_BUFFERS
{
unsigned long ulAlignmentVariable; /* For alignment only, not used anywhere. */
unsigned char ucBuffer[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
} xMACBuffers;
/* Each array position indicated whether or not the buffer of the same index /* Each array position indicates whether or not the buffer of the same index
is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */ is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */
static unsigned char ucMACBufferFree[ macNUM_BUFFERS ]; static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
/***************************************************************************//** /***************************************************************************//**
* Initializes the Ethernet Controller. * Initializes the Ethernet Controller.
@ -138,7 +153,7 @@ MSS_MAC_init
/* To start with all buffers are free. */ /* To start with all buffers are free. */
for( a = 0; a < macNUM_BUFFERS; a++ ) for( a = 0; a < macNUM_BUFFERS; a++ )
{ {
ucMACBufferFree[ a ] = pdTRUE; ucMACBufferInUse[ a ] = pdFALSE;
} }
/* Try to reset chip */ /* Try to reset chip */
@ -151,9 +166,9 @@ MSS_MAC_init
/* Check reset values of some registers to constrol /* Check reset values of some registers to constrol
* base address validity */ * base address validity */
ASSERT( MAC->CSR0 == 0xFE000000uL ); configASSERT( MAC->CSR0 == 0xFE000000uL );
ASSERT( MAC->CSR5 == 0xF0000000uL ); configASSERT( MAC->CSR5 == 0xF0000000uL );
ASSERT( MAC->CSR6 == 0x32000040uL ); configASSERT( MAC->CSR6 == 0x32000040uL );
/* Instance setup */ /* Instance setup */
MAC_memset_All( &g_mss_mac, 0u ); MAC_memset_All( &g_mss_mac, 0u );
@ -169,8 +184,8 @@ MSS_MAC_init
/* Allocate a buffer to the descriptor, then mark the buffer as in use /* Allocate a buffer to the descriptor, then mark the buffer as in use
(not free). */ (not free). */
g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] ); g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );
ucMACBufferFree[ a ] = pdFALSE; ucMACBufferInUse[ a ] = pdTRUE;
} }
g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER; g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
@ -189,8 +204,6 @@ MSS_MAC_init
MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME; MAC_BITBAND->CSR0_BAR = (uint32_t)BUS_ARBITRATION_SCHEME;
/* Fixed settings */ /* Fixed settings */
/* No automatic polling */
MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;
/* No space between descriptors */ /* No space between descriptors */
MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK; MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
/* General-purpose timer works in continuous mode */ /* General-purpose timer works in continuous mode */
@ -198,39 +211,41 @@ MSS_MAC_init
/* Start general-purpose */ /* Start general-purpose */
MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT); MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
/* Disable promiscuous mode */ /* Ensure promiscous mode is off (it should be by default anyway). */
MAC_BITBAND->CSR6_PR = 0u; MAC_BITBAND->CSR6_PR = 0;
/* Enable store and forward */ /* Perfect filter. */
MAC_BITBAND->CSR6_SF = 1u; MAC_BITBAND->CSR6_HP = 1;
/* Pass multcast. */
MAC_BITBAND->CSR6_PM = 1;
/* Set descriptors */ /* Set descriptors */
MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0); MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0); MAC->CSR4 = (uint32_t)&(g_mss_mac.tx_descriptors[0].descriptor_0);
/* enable normal interrupts */ /* enable normal interrupts */
MAC_BITBAND->CSR7_NIE = 1u; MAC_BITBAND->CSR7_NIE = 1u;
/* Set default MAC address and reset mac filters */
MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
MSS_MAC_set_mac_address((uint8_t *)mac_address);
/* Detect PHY */ /* Detect PHY */
if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX ) if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
{ {
PHY_probe(); PHY_probe();
ASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX ); configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
} }
/* Reset PHY */ /* Reset PHY */
PHY_reset(); PHY_reset();
/* Set flags */
g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;
/* Configure chip according to PHY status */ /* Configure chip according to PHY status */
MSS_MAC_auto_setup_link(); MSS_MAC_auto_setup_link();
/* Set default MAC address and reset mac filters */ /* Ensure uip_buf starts by pointing somewhere. */
MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u ); uip_buf = MAC_obtain_buffer();
MSS_MAC_set_mac_filters( 0u, NULL_buffer );
MAC_BITBAND->CSR6_RA = 1; /* Receive all. */
} }
@ -259,18 +274,16 @@ MSS_MAC_configure
{ {
int32_t ret; int32_t ret;
ASSERT( MAC_test_instance() == MAC_OK );
ret = MAC_stop_transmission(); ret = MAC_stop_transmission();
ASSERT( ret == MAC_OK ); configASSERT( ret == MAC_OK );
ret = MAC_stop_receiving(); ret = MAC_stop_receiving();
ASSERT( ret == MAC_OK ); configASSERT( ret == MAC_OK );
MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u ); MAC_BITBAND->CSR6_RA = (uint32_t)(((configuration & MSS_MAC_CFG_RECEIVE_ALL) != 0u) ? 1u : 0u );
MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u ); MAC_BITBAND->CSR6_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u ); MAC_BITBAND->CSR6_SF = (uint32_t)(((configuration & MSS_MAC_CFG_STORE_AND_FORWARD) != 0u) ? 1u : 0u );
switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) { switch( configuration & MSS_MAC_CFG_THRESHOLD_CONTROL_11 ) {
case MSS_MAC_CFG_THRESHOLD_CONTROL_00: case MSS_MAC_CFG_THRESHOLD_CONTROL_00:
MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK; MAC->CSR6 = MAC->CSR6 & ~CSR6_TR_MASK;
@ -322,8 +335,6 @@ MSS_MAC_get_configuration( void )
{ {
uint32_t configuration; uint32_t configuration;
ASSERT( MAC_test_instance() == MAC_OK );
configuration = 0u; configuration = 0u;
if( MAC_BITBAND->CSR6_RA != 0u ) { if( MAC_BITBAND->CSR6_RA != 0u ) {
configuration |= MSS_MAC_CFG_RECEIVE_ALL; configuration |= MSS_MAC_CFG_RECEIVE_ALL;
@ -370,7 +381,7 @@ MSS_MAC_get_configuration( void )
if( MAC_BITBAND->CSR6_HP != 0u ) { if( MAC_BITBAND->CSR6_HP != 0u ) {
configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE; configuration |= MSS_MAC_CFG_HASH_PERFECT_RECEIVE_FILTERING_MODE;
} }
return (int32_t)configuration; return (int32_t)configuration;
} }
@ -382,11 +393,11 @@ MSS_MAC_get_configuration( void )
the transmit FIFO and then activates the transmitter for this packet. If space the transmit FIFO and then activates the transmitter for this packet. If space
is available in the FIFO, the function will return once pac_len bytes of the is available in the FIFO, the function will return once pac_len bytes of the
packet have been placed into the FIFO and the transmitter has been started. packet have been placed into the FIFO and the transmitter has been started.
This function will not wait for the transmission to complete. This function will not wait for the transmission to complete.
@return @return
The function returns zero if a timeout occurs otherwise it returns size of the packet. The function returns zero if a timeout occurs otherwise it returns size of the packet.
@see MAC_rx_packet() @see MAC_rx_packet()
*/ */
@ -399,42 +410,42 @@ MSS_MAC_tx_packet
uint32_t desc; uint32_t desc;
unsigned long ulDescriptor; unsigned long ulDescriptor;
int32_t error = MAC_OK; int32_t error = MAC_OK;
extern unsigned char *uip_buf;
ASSERT( MAC_test_instance() == MAC_OK );
ASSERT( uip_buf != NULL_buffer ); configASSERT( uip_buf != NULL_buffer );
ASSERT( usLength >= 12 ); configASSERT( usLength >= 12 );
if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u ) if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )
{ {
ASSERT( usLength <= MSS_MAX_PACKET_SIZE ); configASSERT( usLength <= MSS_MAX_PACKET_SIZE );
} }
/* Check if second descriptor is free, if it is then the first must /* Check if second descriptor is free, if it is then the first must
also be free. */ also be free. */
if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )
{ {
error = MAC_BUFFER_IS_FULL; error = MAC_BUFFER_IS_FULL;
} }
if( error == MAC_OK ) {
/* Assumed TX_RING_SIZE == 2. */ if( error == MAC_OK )
{
/* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
case. */
for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ ) for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
{ {
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) { if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;
} }
/* Every buffer can hold a full frame so they are always first and last /* Every buffer can hold a full frame so they are always first and last
descriptor */ descriptor */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;
/* set data size */ /* set data size */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
/* reset end of ring */ /* reset end of ring */
g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER; g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
@ -445,10 +456,10 @@ MSS_MAC_tx_packet
} }
/* The data buffer is assigned to the Tx descriptor. */ /* The data buffer is assigned to the Tx descriptor. */
g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;
/* update counters */ /* update counters */
desc = g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0; desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;
if( (desc & TDES0_LO) != 0u ) { if( (desc & TDES0_LO) != 0u ) {
g_mss_mac.statistics.tx_loss_of_carrier++; g_mss_mac.statistics.tx_loss_of_carrier++;
} }
@ -468,26 +479,22 @@ MSS_MAC_tx_packet
(desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK; (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
/* Give ownership of descriptor to the MAC */ /* Give ownership of descriptor to the MAC */
g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = TDES0_OWN; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;
g_mss_mac.tx_desc_index = 0; g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
}
MAC_start_transmission();
MAC->CSR1 = 1u;
}
} }
/* Start transmission */
MAC_start_transmission();
/* transmit poll demand */
MAC->CSR1 = 1u;
if (error == MAC_OK) if (error == MAC_OK)
{ {
/* The buffer uip_buf was pointing to is now under the control of the
MAC (it is being transmitted). Set uip_buf to point to a free buffer. */
uip_buf = MAC_obtain_buffer();
error = (int32_t)usLength; error = (int32_t)usLength;
/* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
Find anothere free buffer for uip_buf. */
uip_buf = MAC_obtain_buffer();
} }
else else
{ {
@ -512,8 +519,6 @@ MSS_MAC_rx_pckt_size
) )
{ {
int32_t retval; int32_t retval;
ASSERT( MAC_test_instance() == MAC_OK );
MAC_dismiss_bad_frames(); MAC_dismiss_bad_frames();
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u ) if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
@ -535,7 +540,7 @@ MSS_MAC_rx_pckt_size
* Receives a packet from the Ethernet Controller into the uIP stack. * Receives a packet from the Ethernet Controller into the uIP stack.
* This function reads a packet from the receive FIFO of the controller and * This function reads a packet from the receive FIFO of the controller and
* places it into uip_buf. * places it into uip_buf.
* @return Size of packet if packet fits in uip_buf. * @return Size of packet if packet fits in uip_buf.
* 0 if there is no received packet. * 0 if there is no received packet.
* @see MAC_rx_pckt_size() * @see MAC_rx_pckt_size()
@ -549,8 +554,6 @@ MSS_MAC_rx_packet
{ {
uint16_t frame_length=0u; uint16_t frame_length=0u;
ASSERT( MAC_test_instance() == MAC_OK );
MAC_dismiss_bad_frames(); MAC_dismiss_bad_frames();
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u ) if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
@ -565,7 +568,7 @@ MSS_MAC_rx_packet
if( frame_length > macBUFFER_SIZE ) { if( frame_length > macBUFFER_SIZE ) {
return MAC_NOT_ENOUGH_SPACE; return MAC_NOT_ENOUGH_SPACE;
} }
/* uip_buf is about to point to the buffer that contains the received /* uip_buf is about to point to the buffer that contains the received
data, mark the buffer that uip_buf is currently pointing to as free data, mark the buffer that uip_buf is currently pointing to as free
again. */ again. */
@ -585,7 +588,7 @@ MSS_MAC_rx_packet
/***************************************************************************//** /***************************************************************************//**
* Receives a packet from the Ethernet Controller. * Receives a packet from the Ethernet Controller.
* This function reads a packet from the receive FIFO of the controller and * This function reads a packet from the receive FIFO of the controller and
* sets the address of pacData to the received data. * sets the address of pacData to the received data.
* If time_out parameter is zero the function will return * If time_out parameter is zero the function will return
* immediately (after the copy operation if data is available. Otherwise the function * immediately (after the copy operation if data is available. Otherwise the function
* will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
@ -614,9 +617,7 @@ MSS_MAC_rx_packet_ptrset
uint16_t frame_length = 0u; uint16_t frame_length = 0u;
int8_t exit = 0; int8_t exit = 0;
ASSERT( MAC_test_instance() == MAC_OK ); configASSERT( (time_out == MSS_MAC_BLOCKING) ||
ASSERT( (time_out == MSS_MAC_BLOCKING) ||
(time_out == MSS_MAC_NONBLOCKING) || (time_out == MSS_MAC_NONBLOCKING) ||
((time_out >= 1) && (time_out <= 0x01000000UL)) ); ((time_out >= 1) && (time_out <= 0x01000000UL)) );
@ -653,11 +654,11 @@ MSS_MAC_rx_packet_ptrset
/* Here we are setting the buffer 'pacData' address to the address /* Here we are setting the buffer 'pacData' address to the address
RX descriptor address. After this is called, the following function RX descriptor address. After this is called, the following function
must be called 'MAC_prepare_rx_descriptor' must be called 'MAC_prepare_rx_descriptor'
to prepare the current rx descriptor for receiving the next packet. to prepare the current rx descriptor for receiving the next packet.
*/ */
*pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ; *pacData = (uint8_t *)g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 ;
} }
return ((int32_t)frame_length); return ((int32_t)frame_length);
} }
@ -679,8 +680,6 @@ MSS_MAC_link_status
{ {
uint32_t link; uint32_t link;
ASSERT( MAC_test_instance() == MAC_OK );
link = PHY_link_status(); link = PHY_link_status();
if( link == MSS_MAC_LINK_STATUS_LINK ) { if( link == MSS_MAC_LINK_STATUS_LINK ) {
link |= PHY_link_type(); link |= PHY_link_type();
@ -706,7 +705,6 @@ MSS_MAC_auto_setup_link
) )
{ {
int32_t link; int32_t link;
ASSERT( MAC_test_instance() == MAC_OK );
PHY_auto_negotiate(); PHY_auto_negotiate();
@ -741,9 +739,8 @@ MSS_MAC_set_mac_address
const uint8_t *new_address const uint8_t *new_address
) )
{ {
ASSERT( MAC_test_instance() == MAC_OK );
/* Check if the new address is unicast */ /* Check if the new address is unicast */
ASSERT( (new_address[0]&1) == 0 ); configASSERT( (new_address[0]&1) == 0 );
MAC_memcpy( g_mss_mac.mac_address, new_address, 6u ); MAC_memcpy( g_mss_mac.mac_address, new_address, 6u );
@ -777,8 +774,6 @@ MSS_MAC_get_mac_address
uint8_t *address uint8_t *address
) )
{ {
ASSERT( MAC_test_instance() == MAC_OK );
MAC_memcpy( address, g_mss_mac.mac_address, 6u ); MAC_memcpy( address, g_mss_mac.mac_address, 6u );
} }
@ -796,13 +791,12 @@ MSS_MAC_set_mac_filters
const uint8_t *filters const uint8_t *filters
) )
{ {
ASSERT( MAC_test_instance() == MAC_OK ); configASSERT( (filter_count==0) || (filters != NULL_buffer) );
ASSERT( (filter_count==0) || (filters != NULL_buffer) );
/* Check if the mac addresses is multicast */ /* Check if the mac addresses is multicast */
{ {
int32_t a; int32_t a;
for( a = 0u; a < filter_count; a++ ) { for( a = 0u; a < filter_count; a++ ) {
ASSERT( (filters[a*6]&1) == 1 ); configASSERT( (filters[a*6]&1) == 1 );
} }
} }
@ -852,8 +846,6 @@ void EthernetMAC_IRQHandler( void )
uint32_t events; uint32_t events;
uint32_t intr_status; uint32_t intr_status;
ASSERT( MAC_test_instance() == MAC_OK );
events = 0u; events = 0u;
intr_status = MAC->CSR5; intr_status = MAC->CSR5;
@ -871,7 +863,7 @@ void EthernetMAC_IRQHandler( void )
/* Clear interrupts */ /* Clear interrupts */
MAC->CSR5 = CSR5_INT_BITS; MAC->CSR5 = CSR5_INT_BITS;
if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) { if( (events != 0u) && (g_mss_mac.listener != NULL_callback) ) {
g_mss_mac.listener( events ); g_mss_mac.listener( events );
} }
@ -896,12 +888,10 @@ MSS_MAC_set_callback
MSS_MAC_callback_t listener MSS_MAC_callback_t listener
) )
{ {
ASSERT( MAC_test_instance() == MAC_OK );
/* disable tx and rx interrupts */ /* disable tx and rx interrupts */
MAC_BITBAND->CSR7_RIE = 0u; MAC_BITBAND->CSR7_RIE = 0u;
MAC_BITBAND->CSR7_TIE = 0u; MAC_BITBAND->CSR7_TIE = 0u;
g_mss_mac.listener = listener; g_mss_mac.listener = listener;
if( listener != NULL_callback ) { if( listener != NULL_callback ) {
@ -929,8 +919,6 @@ MSS_MAC_last_error
{ {
int8_t error_msg_nb; int8_t error_msg_nb;
const int8_t* returnvalue; const int8_t* returnvalue;
ASSERT( MAC_test_instance() == MAC_OK );
error_msg_nb = -(g_mss_mac.last_error); error_msg_nb = -(g_mss_mac.last_error);
if( error_msg_nb >= ERROR_MESSAGE_COUNT ) { if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
@ -957,7 +945,6 @@ MSS_MAC_get_statistics
) )
{ {
uint32_t returnval = 0u; uint32_t returnval = 0u;
ASSERT( MAC_test_instance() == MAC_OK );
switch( stat_id ) { switch( stat_id ) {
case MSS_MAC_RX_INTERRUPTS: case MSS_MAC_RX_INTERRUPTS:
@ -1024,31 +1011,6 @@ MSS_MAC_get_statistics
/**************************** INTERNAL FUNCTIONS ******************************/ /**************************** INTERNAL FUNCTIONS ******************************/
/***************************************************************************//**
* Checks if instace is valid.
*/
static int32_t
MAC_test_instance
(
void
)
{
uint32_t val1;
uint32_t val2;
int32_t retval = MAC_WRONG_PARAMETER;
val1 = MAC->CSR3;
val2 = MAC->CSR4;
if( (&g_mss_mac != NULL_instance) &&
((g_mss_mac.flags & FLAG_MAC_INIT_DONE) != 0u) &&
( val1 == (uint32_t)g_mss_mac.rx_descriptors) &&
(val2 == (uint32_t)g_mss_mac.tx_descriptors ) )
{
retval = MAC_OK;
}
return retval;
}
/***************************************************************************//** /***************************************************************************//**
* Prepares current rx descriptor for receiving. * Prepares current rx descriptor for receiving.
@ -1087,7 +1049,7 @@ MSS_MAC_prepare_rx_descriptor
if( (desc & RDES0_CE) != 0u ) { if( (desc & RDES0_CE) != 0u ) {
g_mss_mac.statistics.rx_crc_error++; g_mss_mac.statistics.rx_crc_error++;
} }
desc = MAC->CSR8; desc = MAC->CSR8;
g_mss_mac.statistics.rx_fifo_overflow += g_mss_mac.statistics.rx_fifo_overflow +=
(desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT; (desc & (CSR8_OCO_MASK|CSR8_FOC_MASK)) >> CSR8_FOC_SHIFT;
@ -1166,22 +1128,22 @@ MAC_send_setup_frame
/* Stop transmission */ /* Stop transmission */
ret = MAC_stop_transmission(); ret = MAC_stop_transmission();
ASSERT( ret == MAC_OK ); configASSERT( ret == MAC_OK );
ret = MAC_stop_receiving(); ret = MAC_stop_receiving();
ASSERT( ret == MAC_OK ); configASSERT( ret == MAC_OK );
/* Set descriptor */ /* Set descriptor */
MAC->CSR4 = (uint32_t)&descriptor; MAC->CSR4 = (uint32_t)&descriptor;
/* Start transmission */ /* Start transmission */
MAC_start_transmission(); MAC_start_transmission();
/* Wait until transmission over */ /* Wait until transmission over */
ret = MAC_OK; ret = MAC_OK;
MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT ); MAC_set_time_out( (uint32_t)SETUP_FRAME_TIME_OUT );
while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) != while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
CSR5_TS_SUSPENDED) && (MAC_OK == ret) ) CSR5_TS_SUSPENDED) && (MAC_OK == ret) )
{ {
/* transmit poll demand */ /* transmit poll demand */
@ -1195,7 +1157,7 @@ MAC_send_setup_frame
/* Set tx descriptor */ /* Set tx descriptor */
MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors; MAC->CSR4 = (uint32_t)g_mss_mac.tx_descriptors;
/* Start receiving and transmission */ /* Start receiving and transmission */
MAC_start_receiving(); MAC_start_receiving();
MAC_start_transmission(); MAC_start_transmission();
@ -1219,7 +1181,7 @@ MAC_stop_transmission
{ {
int32_t retval = MAC_OK; int32_t retval = MAC_OK;
MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT ); MAC_set_time_out( (uint16_t)STATE_CHANGE_TIME_OUT );
while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) != while( (((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) !=
CSR5_TS_STOPPED) && (retval == MAC_OK) ) CSR5_TS_STOPPED) && (retval == MAC_OK) )
{ {
@ -1300,7 +1262,7 @@ MAC_dismiss_bad_frames
{ {
int32_t dc = 0; int32_t dc = 0;
int8_t cont = 1; int8_t cont = 1;
if( MAC_BITBAND->CSR6_PB != 0u ) { if( MAC_BITBAND->CSR6_PB != 0u ) {
/* User wants bad frames too, don't dismiss anything */ /* User wants bad frames too, don't dismiss anything */
cont = 0; cont = 0;
@ -1357,14 +1319,14 @@ MAC_get_time_out
{ {
uint32_t timer; uint32_t timer;
uint32_t time = 0u; uint32_t time = 0u;
timer = ( MAC->CSR11 & CSR11_TIM_MASK ); timer = ( MAC->CSR11 & CSR11_TIM_MASK );
if( timer > g_mss_mac.last_timer_value ) { if( timer > g_mss_mac.last_timer_value ) {
time = 0x0000ffffUL; time = 0x0000ffffUL;
} }
time += g_mss_mac.last_timer_value - timer; time += g_mss_mac.last_timer_value - timer;
if( MAC_BITBAND->CSR6_TTM == 0u ) { if( MAC_BITBAND->CSR6_TTM == 0u ) {
time *= 10u; time *= 10u;
} }
@ -1409,10 +1371,6 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
MAC_memset( s->mac_address, (uint8_t)c, 6u ); MAC_memset( s->mac_address, (uint8_t)c, 6u );
MAC_memset( s->mac_filter_data, (uint8_t)c, 90u ); MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
s->phy_address = (uint8_t)c; s->phy_address = (uint8_t)c;
// for(count = 0; count<RX_RING_SIZE ;count++)
// {
// MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
// }
s->rx_desc_index =c; s->rx_desc_index =c;
for(count = 0; count<RX_RING_SIZE ;count++) for(count = 0; count<RX_RING_SIZE ;count++)
{ {
@ -1440,10 +1398,6 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
s->statistics.tx_no_carrier = c; s->statistics.tx_no_carrier = c;
s->statistics.tx_underflow_error = c; s->statistics.tx_underflow_error = c;
s->time_out_value = c; s->time_out_value = c;
// for(count = 0; count < TX_RING_SIZE ;count++)
// {
// MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
// }
s->tx_desc_index = c; s->tx_desc_index = c;
for(count = 0; count < TX_RING_SIZE ;count++) for(count = 0; count < TX_RING_SIZE ;count++)
{ {
@ -1470,21 +1424,28 @@ static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
} }
} }
void MSS_MAC_TxBufferCompleted( void ) /***************************************************************************//**
* Tx has completed, mark the buffers that were assigned to the Tx descriptors
* as free again.
*
*/
void MSS_MAC_FreeTxBuffers( void )
{ {
unsigned char *pxTransmittedBuffer; if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )
/* Was it the second transmission that has completed? */
if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )
{ {
pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1; MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );
MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1 );
/* The buffer has been transmitted and is no longer in use. */
MAC_release_buffer( pxTransmittedBuffer );
} }
} }
static unsigned char *MAC_obtain_buffer( void ) /***************************************************************************//**
* Look through the array of buffers until one is found that is free for use -
* that is, not currently assigned to an Rx or a Tx descriptor. Mark the buffer
* as in use, then return its address.
*
* @return a pointer to a free buffer.
*/
unsigned char *MAC_obtain_buffer( void )
{ {
long lIndex; long lIndex;
unsigned char *pcReturn = NULL; unsigned char *pcReturn = NULL;
@ -1493,9 +1454,10 @@ unsigned char *pcReturn = NULL;
the buffer as now in use. */ the buffer as now in use. */
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ ) for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{ {
if( ucMACBufferFree[ lIndex ] == pdTRUE ) if( ucMACBufferInUse[ lIndex ] == pdFALSE )
{ {
pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] ); pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
ucMACBufferInUse[ lIndex ] = pdTRUE;
break; break;
} }
} }
@ -1504,6 +1466,10 @@ unsigned char *pcReturn = NULL;
return pcReturn; return pcReturn;
} }
/***************************************************************************//**
* Return a buffer to the list of free buffers, it was in use, but is not now.
*
*/
void MAC_release_buffer( unsigned char *pucBufferToRelease ) void MAC_release_buffer( unsigned char *pucBufferToRelease )
{ {
long lIndex; long lIndex;
@ -1512,13 +1478,15 @@ long lIndex;
it is currently pointing to is marked as being free again. */ it is currently pointing to is marked as being free again. */
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ ) for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{ {
if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) ) if( pucBufferToRelease == &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] ) )
{ {
/* This is the buffer in use, mark it as being free. */ /* This is the buffer in use, mark it as being free. */
ucMACBufferFree[ lIndex ] = pdTRUE; ucMACBufferInUse[ lIndex ] = pdFALSE;
break; break;
} }
} }
configASSERT( lIndex < macNUM_BUFFERS );
} }

@ -16,7 +16,7 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/******************************** DEFINES *************************************/ /******************************** DEFINES *************************************/
@ -160,7 +160,7 @@ extern "C" {
#define MSS_PHY_ADDRESS_AUTO_DETECT 255u #define MSS_PHY_ADDRESS_AUTO_DETECT 255u
/***************************************************************************//** /***************************************************************************//**
* Listener function type defines the function prototype that might be followed * Listener function type defines the function prototype that might be followed
* by MAC_isr which is triggered with each receive and transmit related interrupts. * by MAC_isr which is triggered with each receive and transmit related interrupts.
* Listener functions should follow the following prototype: * Listener functions should follow the following prototype:
* void MAC_Listener( uint32_t events ); * void MAC_Listener( uint32_t events );
@ -168,7 +168,7 @@ extern "C" {
* or events. Events input to the system are: * or events. Events input to the system are:
* #define MSS_MAC_EVENT_PACKET_SEND 1 * #define MSS_MAC_EVENT_PACKET_SEND 1
* #define MSS_MAC_EVENT_PACKET_RECEIVED 2 * #define MSS_MAC_EVENT_PACKET_RECEIVED 2
* Listener function should be defined by the application using this driver if * Listener function should be defined by the application using this driver if
* needed. This function may be assigned to the driver using MAC_set_callback * needed. This function may be assigned to the driver using MAC_set_callback
* routine and may be un assigned again by using the same routine with a NULL pointer * routine and may be un assigned again by using the same routine with a NULL pointer
* as the event listener function. It is recommended to use this property for interrupt * as the event listener function. It is recommended to use this property for interrupt
@ -177,7 +177,7 @@ extern "C" {
typedef void (*MSS_MAC_callback_t)(uint32_t events); typedef void (*MSS_MAC_callback_t)(uint32_t events);
/***************************************************************************//** /***************************************************************************//**
* Statistics counter identifiers are used with MAC_get_statistics routine to * Statistics counter identifiers are used with MAC_get_statistics routine to
* receive the count of the requested errors/interrupts occurrences. * receive the count of the requested errors/interrupts occurrences.
* *
* MSS_MAC_RX_INTERRUPTS * MSS_MAC_RX_INTERRUPTS
@ -270,7 +270,7 @@ typedef enum {
MSS_MAC_TX_EXCESSIVE_COLLISION, MSS_MAC_TX_EXCESSIVE_COLLISION,
MSS_MAC_TX_COLLISION_COUNT, MSS_MAC_TX_COLLISION_COUNT,
MSS_MAC_TX_UNDERFLOW_ERROR MSS_MAC_TX_UNDERFLOW_ERROR
} mss_mac_statistics_id_t; } mss_mac_statistics_id_t;
/******************************* FUNCTIONS ************************************/ /******************************* FUNCTIONS ************************************/
@ -317,7 +317,7 @@ MSS_MAC_configure
/***************************************************************************//** /***************************************************************************//**
* Returns the configuration of the Ethernet Controller. * Returns the configuration of the Ethernet Controller.
* After the MAC_init function has been called, this API function can be used to * After the MAC_init function has been called, this API function can be used to
* get the configuration of the Ethernet Controller. * get the configuration of the Ethernet Controller.
* *
* @return The logical OR of the following values: * @return The logical OR of the following values:
@ -366,7 +366,7 @@ MSS_MAC_tx_packet
* Returns available packet's size. * Returns available packet's size.
* *
* @return Size of packet, bigger than 0, if a packet is available, * @return Size of packet, bigger than 0, if a packet is available,
* if not, returns 0. * if not, returns 0.
* @see MAC_rx_packet() * @see MAC_rx_packet()
*/ */
int32_t int32_t
@ -416,26 +416,26 @@ MSS_MAC_rx_packet
used by the user application or copied to another buffer, the used by the user application or copied to another buffer, the
MSS_MAC_prepare_rx_descriptor() function must be called to free up the receive MSS_MAC_prepare_rx_descriptor() function must be called to free up the receive
memory buffer used by the MSS Ethernet MAC memory buffer used by the MSS Ethernet MAC
@param pacData @param pacData
The pacData parameter is a pointer to a memory buffer pointer. The uint8_t The pacData parameter is a pointer to a memory buffer pointer. The uint8_t
pointer pointed to by the pacData parameter will contain the address of the pointer pointed to by the pacData parameter will contain the address of the
memory buffer containing the received packet after this function returns. The memory buffer containing the received packet after this function returns. The
value of pacData is only valid if the return value is larger than zero, value of pacData is only valid if the return value is larger than zero,
indicating that a packet was received. indicating that a packet was received.
@param time_out @param time_out
The time_out parameter is the timeout value for the transmission in milliseconds. The time_out parameter is the timeout value for the transmission in milliseconds.
The time_out parameter value can be one of the following values: The time_out parameter value can be one of the following values:
Unsigned integer greater than 0 and less than 0x01000000 Unsigned integer greater than 0 and less than 0x01000000
MSS_MAC_BLOCKING there will be no timeout. MSS_MAC_BLOCKING there will be no timeout.
MSS_MAC_NONBLOCKING the function will return immediately if no packets MSS_MAC_NONBLOCKING the function will return immediately if no packets
have been received. have been received.
@return @return
The function returns the size of the packet if the packet fits in pacData. The function returns the size of the packet if the packet fits in pacData.
Returns zero if there is no received packet. Returns zero if there is no received packet.
@see MAC_rx_pckt_size() @see MAC_rx_pckt_size()
@see MAC_tx_packet() @see MAC_tx_packet()
*/ */
@ -537,10 +537,10 @@ MSS_MAC_set_callback
/***************************************************************************//** /***************************************************************************//**
* Returns description of latest error happened. * Returns description of latest error happened.
* *
* @return A string describing the error. This string must not be * @return A string describing the error. This string must not be
* modified by the application. * modified by the application.
*/ */
const int8_t* const int8_t*
MSS_MAC_last_error MSS_MAC_last_error
( (
void void
@ -549,7 +549,7 @@ MSS_MAC_last_error
/***************************************************************************//** /***************************************************************************//**
* Returns statistics counter of stat_id identifier. * Returns statistics counter of stat_id identifier.
* *
* @param stat_id Identifier of statistics counter. * @param stat_id Identifier of statistics counter.
* @return Statistics counter of stat_id identifier. * @return Statistics counter of stat_id identifier.
* On error returns 0. * On error returns 0.
@ -560,23 +560,11 @@ MSS_MAC_get_statistics
mss_mac_statistics_id_t stat_id mss_mac_statistics_id_t stat_id
); );
/*
* Ensure uip_buf is pointing to a valid and free buffer before any transmissions
* initiated by the uIP stack occur.
*/
unsigned char *MSS_MAC_GetTxDescriptor( void );
/*
* A buffer is no longer required by the application. Hand it back to the
* control of the MAC hardware.
*/
void MSS_MAC_ReleaseBuffer( unsigned char *pucBuffer );
/* /*
* The double Tx has completed. Hand back the Tx buffer to the control of * The double Tx has completed. Hand back the Tx buffer to the control of
* the MAC hardware. * the MAC hardware.
*/ */
void MSS_MAC_TxBufferCompleted( void ); void MSS_MAC_FreeTxBuffers( void );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -19,12 +19,12 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "../../CMSIS/a2fxxxm3.h" #include "../../CMSIS/a2fxxxm3.h"
#include "mss_ethernet_mac.h" #include "mss_ethernet_mac.h"
#include "mss_ethernet_mac_user_cfg.h" #include "mss_ethernet_mac_user_cfg.h"
typedef uint32_t addr_t; typedef uint32_t addr_t;
@ -42,78 +42,78 @@ typedef struct {
/***************************************************************************//** /***************************************************************************//**
* There should be one instance of this structure for each instance of * There should be one instance of this structure for each instance of
* the MAC in your system. MSS_MAC_init routine initializes this structure. * the MAC in your system. MSS_MAC_init routine initializes this structure.
* It is used to identify the various MACs in your system and an initilized * It is used to identify the various MACs in your system and an initilized
* MAC instance's structure should be passed as first parameter to MAC functions * MAC instance's structure should be passed as first parameter to MAC functions
* to identify which MAC should perform the requested operation. * to identify which MAC should perform the requested operation.
* Software using the MAC driver should only need to create one single * Software using the MAC driver should only need to create one single
* instance of this data structure for each MAC hardware instance in * instance of this data structure for each MAC hardware instance in
* the system. Using MAC_get_configuration routine, latest status of the driver * the system. Using MAC_get_configuration routine, latest status of the driver
* may be read by receiving its flags field, similarly MAC_configure routine lets * may be read by receiving its flags field, similarly MAC_configure routine lets
* you modify some of these flags. * you modify some of these flags.
*/ */
#include "net/pack_struct_start.h"
typedef struct { typedef struct {
addr_t base_address; /**< Register base address of the driver*/ addr_t base_address; /**< Register base address of the driver*/
uint8_t flags; /**< Configuration of the driver*/ uint8_t flags; /**< Configuration of the driver*/
int8_t last_error; /**< Index of last error happened inside the driver*/ int8_t last_error; /**< Index of last error happened inside the driver*/
uint8_t mac_address[6]; /**< MAC address of the drived instance*/ uint8_t mac_address[6]; /**< MAC address of the drived instance*/
uint8_t mac_filter_data[90]; /**< MAC filter data, 15 addresses to be used for uint8_t mac_filter_data[90]; /**< MAC filter data, 15 addresses to be used for
received data filtering*/ received data filtering*/
uint16_t last_timer_value; /**< Last read value of timer */ uint16_t last_timer_value; /**< Last read value of timer */
uint32_t time_out_value; /**< Time out value */ uint32_t time_out_value; /**< Time out value */
MSS_MAC_callback_t listener; /**< Pointer to the call-back function to be triggered MSS_MAC_callback_t listener; /**< Pointer to the call-back function to be triggered
when a package is received*/ when a package is received*/
/* transmit related info: */ /* transmit related info: */
uint32_t tx_desc_index; /**< index of the transmit descriptor getting used*/ uint32_t tx_desc_index; /**< index of the transmit descriptor getting used*/
// uint8_t tx_buffers[TX_RING_SIZE][MSS_TX_BUFF_SIZE];/**< array of transmit buffers*/
MAC_descriptor_t tx_descriptors[TX_RING_SIZE];/**< array of transmit descriptors*/ MAC_descriptor_t tx_descriptors[TX_RING_SIZE];/**< array of transmit descriptors*/
/* receive related info: */ /* receive related info: */
uint32_t rx_desc_index; /**< index of the receive descriptor getting used*/ uint32_t rx_desc_index; /**< index of the receive descriptor getting used*/
// uint8_t rx_buffers[RX_RING_SIZE][MSS_RX_BUFF_SIZE+4];/**< array of receive buffers*/
MAC_descriptor_t rx_descriptors[RX_RING_SIZE];/**< array of receive descriptors*/ MAC_descriptor_t rx_descriptors[RX_RING_SIZE];/**< array of receive descriptors*/
uint8_t phy_address; /**< MII address of the connected PHY*/ uint8_t phy_address; /**< MII address of the connected PHY*/
struct { struct {
uint32_t rx_interrupts; /**< Number of receive interrupts occurred.*/ uint32_t rx_interrupts; /**< Number of receive interrupts occurred.*/
uint32_t rx_filtering_fail; /**< Number of received frames which did not pass uint32_t rx_filtering_fail; /**< Number of received frames which did not pass
the address recognition process.*/ the address recognition process.*/
uint32_t rx_descriptor_error; /**< Number of occurrences of; no receive buffer was uint32_t rx_descriptor_error; /**< Number of occurrences of; no receive buffer was
available when trying to store the received data.*/ available when trying to store the received data.*/
uint32_t rx_runt_frame; /**< Number of occurrences of; the frame is damaged by uint32_t rx_runt_frame; /**< Number of occurrences of; the frame is damaged by
a collision or by a premature termination before a collision or by a premature termination before
the end of a collision window.*/ the end of a collision window.*/
uint32_t rx_not_first; /**< Number of occurrences of; start of the frame is uint32_t rx_not_first; /**< Number of occurrences of; start of the frame is
not the first descriptor of a frame.*/ not the first descriptor of a frame.*/
uint32_t rx_not_last; /**< Number of occurrences of; end of the frame is not uint32_t rx_not_last; /**< Number of occurrences of; end of the frame is not
the first descriptor of a frame.*/ the first descriptor of a frame.*/
uint32_t rx_frame_too_long; /**< Number of occurrences of; a current frame is uint32_t rx_frame_too_long; /**< Number of occurrences of; a current frame is
longer than maximum size of 1,518 bytes, as specified longer than maximum size of 1,518 bytes, as specified
by 802.3.*/ by 802.3.*/
uint32_t rx_collision_seen; /**< Number of occurrences of; a late collision was seen uint32_t rx_collision_seen; /**< Number of occurrences of; a late collision was seen
(collision after 64 bytes following SFD).*/ (collision after 64 bytes following SFD).*/
uint32_t rx_crc_error; /**< Number of occurrences of; a CRC error has occurred uint32_t rx_crc_error; /**< Number of occurrences of; a CRC error has occurred
in the received frame.*/ in the received frame.*/
uint32_t rx_fifo_overflow; /**< Number of frames not accepted due to the receive uint32_t rx_fifo_overflow; /**< Number of frames not accepted due to the receive
FIFO overflow.*/ FIFO overflow.*/
uint32_t rx_missed_frame; /**< Number of frames not accepted due to the uint32_t rx_missed_frame; /**< Number of frames not accepted due to the
unavailability of the receive descriptor.*/ unavailability of the receive descriptor.*/
uint32_t tx_interrupts; /**< Number of transmit interrupts occurred.*/ uint32_t tx_interrupts; /**< Number of transmit interrupts occurred.*/
uint32_t tx_loss_of_carrier; /**< Number of occurrences of; a loss of the carrier uint32_t tx_loss_of_carrier; /**< Number of occurrences of; a loss of the carrier
during a transmission.*/ during a transmission.*/
uint32_t tx_no_carrier; /**< Number of occurrences of; the carrier was not asserted uint32_t tx_no_carrier; /**< Number of occurrences of; the carrier was not asserted
by an external transceiver during the transmission.*/ by an external transceiver during the transmission.*/
uint32_t tx_late_collision; /**< Number of occurrences of; a collision was detected uint32_t tx_late_collision; /**< Number of occurrences of; a collision was detected
after transmitting 64 bytes.*/ after transmitting 64 bytes.*/
uint32_t tx_excessive_collision;/**< Number of occurrences of; the transmission was uint32_t tx_excessive_collision;/**< Number of occurrences of; the transmission was
aborted after 16 retries.*/ aborted after 16 retries.*/
uint32_t tx_collision_count; /**< Number of collisions occurred.*/ uint32_t tx_collision_count; /**< Number of collisions occurred.*/
uint32_t tx_underflow_error; /**< Number of occurrences of; the FIFO was empty during uint32_t tx_underflow_error; /**< Number of occurrences of; the FIFO was empty during
the frame transmission.*/ the frame transmission.*/
} statistics; } statistics;
} MAC_instance_t; } MAC_instance_t
#include "net/pack_struct_end.h"
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
@ -130,29 +130,29 @@ typedef struct
uint32_t CSR0_TAP[3]; uint32_t CSR0_TAP[3];
uint32_t CSR0_DBO; uint32_t CSR0_DBO;
uint32_t CSR0_RESERVED1[11]; uint32_t CSR0_RESERVED1[11];
uint32_t MAC_CSR_RESERVED0[32]; uint32_t MAC_CSR_RESERVED0[32];
uint32_t CSR1[32]; uint32_t CSR1[32];
uint32_t MAC_CSR_RESERVED1[32]; uint32_t MAC_CSR_RESERVED1[32];
uint32_t CSR2[32]; uint32_t CSR2[32];
uint32_t MAC_CSR_RESERVED2[32]; uint32_t MAC_CSR_RESERVED2[32];
uint32_t CSR3[32]; uint32_t CSR3[32];
uint32_t MAC_CSR_RESERVED3[32]; uint32_t MAC_CSR_RESERVED3[32];
uint32_t CSR4[32]; uint32_t CSR4[32];
uint32_t MAC_CSR_RESERVED4[32]; uint32_t MAC_CSR_RESERVED4[32];
uint32_t CSR5_TI; uint32_t CSR5_TI;
uint32_t CSR5_TPS; uint32_t CSR5_TPS;
uint32_t CSR5_TU; uint32_t CSR5_TU;
uint32_t CSR5_RESERVED0[2]; uint32_t CSR5_RESERVED0[2];
uint32_t CSR5_UNF; uint32_t CSR5_UNF;
uint32_t CSR5_RI; uint32_t CSR5_RI;
uint32_t CSR5_RU; uint32_t CSR5_RU;
@ -169,7 +169,7 @@ typedef struct
uint32_t CSR5_RESERVED3[9]; uint32_t CSR5_RESERVED3[9];
uint32_t MAC_CSR_RESERVED5[32]; uint32_t MAC_CSR_RESERVED5[32];
uint32_t CSR6_HP; uint32_t CSR6_HP;
uint32_t CSR6_SR; uint32_t CSR6_SR;
uint32_t CSR6_HO; uint32_t CSR6_HO;
@ -191,7 +191,7 @@ typedef struct
uint32_t CSR6_RESERVED5; uint32_t CSR6_RESERVED5;
uint32_t MAC_CSR_RESERVED6[32]; uint32_t MAC_CSR_RESERVED6[32];
uint32_t CSR7_TIE; uint32_t CSR7_TIE;
uint32_t CSR7_TSE; uint32_t CSR7_TSE;
uint32_t CSR7_TUE; uint32_t CSR7_TUE;
@ -210,11 +210,11 @@ typedef struct
uint32_t CSR7[15]; uint32_t CSR7[15];
uint32_t MAC_CSR_RESERVED7[32]; uint32_t MAC_CSR_RESERVED7[32];
uint32_t CSR8[32]; uint32_t CSR8[32];
uint32_t MAC_CSR_RESERVED8[32]; uint32_t MAC_CSR_RESERVED8[32];
uint32_t CSR9_SCS; uint32_t CSR9_SCS;
uint32_t CSR9_SCLK; uint32_t CSR9_SCLK;
uint32_t CSR9_SDI; uint32_t CSR9_SDI;
@ -227,11 +227,11 @@ typedef struct
uint32_t CSR9_RESERVED1[12]; uint32_t CSR9_RESERVED1[12];
uint32_t MAC_CSR_RESERVED9[32]; uint32_t MAC_CSR_RESERVED9[32];
uint32_t CSR10[32]; uint32_t CSR10[32];
uint32_t MAC_CSR_RESERVED10[32]; uint32_t MAC_CSR_RESERVED10[32];
uint32_t CSR11_TIM[16]; uint32_t CSR11_TIM[16];
uint32_t CSR11_CON; uint32_t CSR11_CON;
uint32_t CSR11_NRP[3]; uint32_t CSR11_NRP[3];
@ -559,19 +559,19 @@ typedef struct
#define CSR5_TS_SHIFT 20 #define CSR5_TS_SHIFT 20
/** 000 - Stopped; RESET or STOP TRANSMIT command issued. */ /** 000 - Stopped; RESET or STOP TRANSMIT command issued. */
#define CSR5_TS_STOPPED 0u #define CSR5_TS_STOPPED 0u
/** 001 - Running, fetching the transmit descriptor. */ /** 001 - Running, fetching the transmit descriptor. */
#define CSR5_TS_RUNNING_FD 1u #define CSR5_TS_RUNNING_FD 1u
/** 010 - Running, waiting for end of transmission. */ /** 010 - Running, waiting for end of transmission. */
#define CSR5_TS_RUNNING_WT 2u #define CSR5_TS_RUNNING_WT 2u
/** 011 - Running, transferring data buffer from host memory to FIFO. */ /** 011 - Running, transferring data buffer from host memory to FIFO. */
#define CSR5_TS_RUNNING_TD 3u #define CSR5_TS_RUNNING_TD 3u
/** 101 - Running, setup packet. */ /** 101 - Running, setup packet. */
#define CSR5_TS_RUNNING_SP 5u #define CSR5_TS_RUNNING_SP 5u
/** 110 - Suspended; FIFO underflow or unavailable descriptor. */ /** 110 - Suspended; FIFO underflow or unavailable descriptor. */
#define CSR5_TS_SUSPENDED 6u #define CSR5_TS_SUSPENDED 6u
/** 111 - Running, closing transmit descriptor. */ /** 111 - Running, closing transmit descriptor. */
#define CSR5_TS_RUNNING_CD 7u #define CSR5_TS_RUNNING_CD 7u
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* CSR5_RS: * CSR5_RS:
@ -584,19 +584,19 @@ typedef struct
#define CSR5_RS_SHIFT 17 #define CSR5_RS_SHIFT 17
/** 000 - Stopped; RESET or STOP RECEIVE command issued. */ /** 000 - Stopped; RESET or STOP RECEIVE command issued. */
#define CSR5_RS_STOPPED 0u #define CSR5_RS_STOPPED 0u
/** 001 - Running, fetching the receive descriptor. */ /** 001 - Running, fetching the receive descriptor. */
#define CSR5_RS_RUNNING_FD 1u #define CSR5_RS_RUNNING_FD 1u
/** 010 - Running, waiting for the end-of-receive packet before prefetch of the /** 010 - Running, waiting for the end-of-receive packet before prefetch of the
*next descriptor. */ *next descriptor. */
#define CSR5_RS_RUNNING_WR 2u #define CSR5_RS_RUNNING_WR 2u
/** 011 - Running, waiting for the receive packet. */ /** 011 - Running, waiting for the receive packet. */
#define CSR5_RS_RUNNING_RB 3u #define CSR5_RS_RUNNING_RB 3u
/** 100 - Suspended, unavailable receive buffer. */ /** 100 - Suspended, unavailable receive buffer. */
#define CSR5_RS_SUSPENDED 4u #define CSR5_RS_SUSPENDED 4u
/** 101 - Running, closing the receive descriptor. */ /** 101 - Running, closing the receive descriptor. */
#define CSR5_RS_RUNNING_CD 5u #define CSR5_RS_RUNNING_CD 5u
/** 111 - Running, transferring data from FIFO to host memory. */ /** 111 - Running, transferring data from FIFO to host memory. */
#define CSR5_RS_RUNNING_TD 7u #define CSR5_RS_RUNNING_TD 7u
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------

@ -172,6 +172,7 @@ long lReturn = pdFALSE;
lReturn = pdTRUE; lReturn = pdTRUE;
} }
} }
taskEXIT_CRITICAL();
} }
return lReturn; return lReturn;

@ -212,7 +212,7 @@ static unsigned short generate_io_state( void *arg )
( void ) arg; ( void ) arg;
/* Are the dynamically setable LEDs currently on or off? */ /* Are the dynamically setable LEDs currently on or off? */
if( lParTestGetLEDState( 8 ) ) if( lParTestGetLEDState( 3 ) )
{ {
pcStatus = "checked"; pcStatus = "checked";
} }
@ -229,26 +229,13 @@ static unsigned short generate_io_state( void *arg )
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
extern void vTaskGetRunTimeStats( signed char *pcWriteBuffer ); extern void vTaskGetRunTimeStats( signed char *pcWriteBuffer );
extern unsigned short usMaxJitter; extern unsigned short usMaxJitter;
static char cJitterBuffer[ 200 ];
static unsigned short generate_runtime_stats( void *arg ) static unsigned short generate_runtime_stats( void *arg )
{ {
( void ) arg; ( void ) arg;
lRefreshCount++; lRefreshCount++;
sprintf( cCountBuf, "<p><br>Refresh count = %d", ( int ) lRefreshCount ); sprintf( cCountBuf, "<p><br>Refresh count = %d", ( int ) lRefreshCount );
#ifdef INCLUDE_HIGH_FREQUENCY_TIMER_TEST vTaskGetRunTimeStats( uip_appdata );
{
sprintf( cJitterBuffer, "<p><br>Max high frequency timer jitter = %d peripheral clock periods.<p><br>", ( int ) usMaxJitter );
vTaskGetRunTimeStats( uip_appdata );
strcat( uip_appdata, cJitterBuffer );
}
#else
{
( void ) cJitterBuffer;
strcpy( uip_appdata, "<p>Run time stats are only available in the debug_with_optimisation build configuration.<p>" );
}
#endif
strcat( uip_appdata, cCountBuf ); strcat( uip_appdata, cCountBuf );
return strlen( uip_appdata ); return strlen( uip_appdata );

@ -71,11 +71,11 @@
* incorporates a Cortex-M3 microcontroller. * incorporates a Cortex-M3 microcontroller.
* *
* The main() Function: * The main() Function:
* main() creates three demo specific software timers, one demo specific queue, * main() creates two demo specific software timers, one demo specific queue,
* and two demo specific tasks. It then creates a whole host of 'standard demo' * and three demo specific tasks. It then creates a whole host of 'standard
* tasks/queues/semaphores, before starting the scheduler. The demo specific * demo' tasks/queues/semaphores, before starting the scheduler. The demo
* tasks and timers are described in the comments here. The standard demo * specific tasks and timers are described in the comments here. The standard
* tasks are described on the FreeRTOS.org web site. * demo tasks are described on the FreeRTOS.org web site.
* *
* The standard demo tasks provide no specific functionality. They are * The standard demo tasks provide no specific functionality. They are
* included to both test the FreeRTOS port, and provide examples of how the * included to both test the FreeRTOS port, and provide examples of how the
@ -102,6 +102,11 @@
* the Blocked state every 200 milliseconds, and therefore toggles the LED * the Blocked state every 200 milliseconds, and therefore toggles the LED
* every 200 milliseconds. * every 200 milliseconds.
* *
* The Demo Specific OLED Task:
* The OLED task is a very simple task that just scrolls a message across the
* OLED. Ideally this would be done in a timer, but the OLED driver accesses
* the I2C which is time consuming.
*
* The Demo Specific LED Software Timer and the Button Interrupt: * The Demo Specific LED Software Timer and the Button Interrupt:
* The user button SW1 is configured to generate an interrupt each time it is * The user button SW1 is configured to generate an interrupt each time it is
* pressed. The interrupt service routine switches an LED on, and resets the * pressed. The interrupt service routine switches an LED on, and resets the
@ -110,10 +115,6 @@
* Therefore, pressing the user button will turn the LED on, and the LED will * Therefore, pressing the user button will turn the LED on, and the LED will
* remain on until a full five seconds pass without the button being pressed. * remain on until a full five seconds pass without the button being pressed.
* *
* The Demo Specific OLED Software Timer:
* The OLED software timer is responsible for drawing a scrolling text message
* on the OLED.
*
* The Demo Specific "Check" Callback Function: * The Demo Specific "Check" Callback Function:
* This is called each time the 'check' timer expires. The check timer * This is called each time the 'check' timer expires. The check timer
* callback function inspects all the standard demo tasks to see if they are * callback function inspects all the standard demo tasks to see if they are
@ -122,7 +123,7 @@
* is ever discovered. The check timer callback toggles the LED defined by * is ever discovered. The check timer callback toggles the LED defined by
* the mainCHECK_LED definition each time it executes. Therefore, if LED * the mainCHECK_LED definition each time it executes. Therefore, if LED
* mainCHECK_LED is toggling every three seconds, then no error have been found. * mainCHECK_LED is toggling every three seconds, then no error have been found.
* If LED mainCHECK_LED is toggling every 500ms, then at least one error has * If LED mainCHECK_LED is toggling every 500ms, then at least one errors has
* been found. The task in which the error was discovered is displayed at the * been found. The task in which the error was discovered is displayed at the
* bottom of the "task stats" page that is served by the embedded web server. * bottom of the "task stats" page that is served by the embedded web server.
* *
@ -146,6 +147,7 @@
/* Microsemi drivers/libraries includes. */ /* Microsemi drivers/libraries includes. */
#include "mss_gpio.h" #include "mss_gpio.h"
#include "mss_watchdog.h" #include "mss_watchdog.h"
#include "mss_timer.h"
#include "oled.h" #include "oled.h"
/* Common demo includes. */ /* Common demo includes. */
@ -193,6 +195,7 @@ the queue empty. */
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainOLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
@ -202,15 +205,19 @@ stack than most of the other tasks. */
/* The period at which the check timer will expire, in ms, provided no errors /* The period at which the check timer will expire, in ms, provided no errors
have been reported by any of the standard demo tasks. */ have been reported by any of the standard demo tasks. */
#define mainCHECK_TIMER_PERIOD_ms ( 3000UL ) #define mainCHECK_TIMER_PERIOD_MS ( 3000UL / portTICK_RATE_MS )
/* The period at which the OLED timer will expire. Each time it expires, it's /* The period at which the OLED timer will expire. Each time it expires, it's
callback function updates the OLED text. */ callback function updates the OLED text. */
#define mainOLED_PERIOD_ms ( 75UL ) #define mainOLED_PERIOD_MS ( 75UL / portTICK_RATE_MS )
/* The period at which the check timer will expire, in ms, if an error has been /* The period at which the check timer will expire, in ms, if an error has been
reported in one of the standard demo tasks. */ reported in one of the standard demo tasks. */
#define mainERROR_CHECK_TIMER_PERIOD_ms ( 500UL ) #define mainERROR_CHECK_TIMER_PERIOD_MS ( 500UL / portTICK_RATE_MS )
/* The LED will remain on until the button has not been pushed for a full
5000ms. */
#define mainLED_TIMER_PERIOD_MS ( 5000UL / portTICK_RATE_MS )
/* A zero block time. */ /* A zero block time. */
#define mainDONT_BLOCK ( 0UL ) #define mainDONT_BLOCK ( 0UL )
@ -228,24 +235,19 @@ static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters ); static void prvQueueSendTask( void *pvParameters );
/* /*
* The LED timer callback function. This does nothing but switch the red LED * The LED timer callback function. This does nothing but switch the red LED
* off. * off.
*/ */
static void vLEDTimerCallback( xTimerHandle xTimer ); static void prvLEDTimerCallback( xTimerHandle xTimer );
/*
* The check timer callback function, as described at the top of this file.
*/
static void vCheckTimerCallback( xTimerHandle xTimer );
/* /*
* The OLED timer callback function, as described at the top of this file. * The check timer callback function, as described at the top of this file.
*/ */
static void vOLEDTimerCallback( xTimerHandle xHandle ); static void prvCheckTimerCallback( xTimerHandle xTimer );
/* /*
* This is not a 'standard' partest function, so the prototype is not in * This is not a 'standard' partest function, so the prototype is not in
* partest.h, and is instead included here. * partest.h, and is instead included here.
*/ */
void vParTestSetLEDFromISR( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ); void vParTestSetLEDFromISR( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue );
@ -254,22 +256,26 @@ void vParTestSetLEDFromISR( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE x
*/ */
extern void vuIP_Task( void *pvParameters ); extern void vuIP_Task( void *pvParameters );
/*
* A very simply task that does nothing but scroll the OLED display. Ideally
* this would be done within a timer, but it accesses the I2C port which is
* time consuming.
*/
static void prvOLEDTask( void * pvParameters);
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The queue used by both application specific demo tasks defined in this file. */ /* The queue used by both application specific demo tasks defined in this file. */
static xQueueHandle xQueue = NULL; static xQueueHandle xQueue = NULL;
/* The LED software timer. This uses vLEDTimerCallback() as it's callback /* The LED software timer. This uses prvLEDTimerCallback() as it's callback
function. */ function. */
static xTimerHandle xLEDTimer = NULL; static xTimerHandle xLEDTimer = NULL;
/* The check timer. This uses vCheckTimerCallback() as it's callback /* The check timer. This uses prvCheckTimerCallback() as it's callback
function. */ function. */
static xTimerHandle xCheckTimer = NULL; static xTimerHandle xCheckTimer = NULL;
/* The OLED software timer. Writes a moving text string to the OLED. */
static xTimerHandle xOLEDTimer = NULL;
/* The status message that is displayed at the bottom of the "task stats" web /* The status message that is displayed at the bottom of the "task stats" web
page, which is served by the uIP task. This will report any errors picked up page, which is served by the uIP task. This will report any errors picked up
by the check timer callback. */ by the check timer callback. */
@ -287,33 +293,31 @@ int main(void)
if( xQueue != NULL ) if( xQueue != NULL )
{ {
/* Start the two application specific demo tasks, as described in the /* Start the three application specific demo tasks, as described in the
comments at the top of this file. */ comments at the top of this file. */
xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL ); xTaskCreate( prvQueueReceiveTask, ( signed char * ) "Rx", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL ); xTaskCreate( prvQueueSendTask, ( signed char * ) "TX", configMINIMAL_STACK_SIZE, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
xTaskCreate( prvOLEDTask, ( signed char * ) "OLED", configMINIMAL_STACK_SIZE, NULL, mainOLED_TASK_PRIORITY, NULL );
/* Create the software timer that is responsible for turning off the LED /* Create the software timer that is responsible for turning off the LED
if the button is not pushed within 5000ms, as described at the top of if the button is not pushed within 5000ms, as described at the top of
this file. */ this file. */
xLEDTimer = xTimerCreate( ( const signed char * ) "LEDTimer", /* A text name, purely to help debugging. */ xLEDTimer = xTimerCreate( ( const signed char * ) "LEDTimer", /* A text name, purely to help debugging. */
( 5000 / portTICK_RATE_MS ), /* The timer period, in this case 5000ms (5s). */ ( mainLED_TIMER_PERIOD_MS ), /* The timer period, in this case 5000ms (5s). */
pdFALSE, /* This is a one shot timer, so xAutoReload is set to pdFALSE. */ pdFALSE, /* This is a one shot timer, so xAutoReload is set to pdFALSE. */
( void * ) 0, /* The ID is not used, so can be set to anything. */ ( void * ) 0, /* The ID is not used, so can be set to anything. */
vLEDTimerCallback /* The callback function that switches the LED off. */ prvLEDTimerCallback /* The callback function that switches the LED off. */
); );
/* Create the software timer that performs the 'check' functionality, /* Create the software timer that performs the 'check' functionality,
as described at the top of this file. */ as described at the top of this file. */
xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer", /* A text name, purely to help debugging. */ xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer",/* A text name, purely to help debugging. */
( mainCHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ),/* The timer period, in this case 3000ms (3s). */ ( mainCHECK_TIMER_PERIOD_MS ), /* The timer period, in this case 3000ms (3s). */
pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */ pdTRUE, /* This is an auto-reload timer, so xAutoReload is set to pdTRUE. */
( void * ) 0, /* The ID is not used, so can be set to anything. */ ( void * ) 0, /* The ID is not used, so can be set to anything. */
vCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */ prvCheckTimerCallback /* The callback function that inspects the status of all the other tasks. */
); );
/* Create the OLED timer as described at the top of this file. */
xOLEDTimer = xTimerCreate( ( const signed char * ) "OLEDTimer", ( mainOLED_PERIOD_ms / portTICK_RATE_MS ), pdTRUE, ( void * ) 0, vOLEDTimerCallback );
/* Create a lot of 'standard demo' tasks. */ /* Create a lot of 'standard demo' tasks. */
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
vCreateBlockTimeTasks(); vCreateBlockTimeTasks();
@ -325,7 +329,13 @@ int main(void)
vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
/* Create the web server task. */ /* Create the web server task. */
// xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL ); xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainuIP_STACK_SIZE, NULL, mainuIP_TASK_PRIORITY, NULL );
/* The suicide tasks must be created last, as they need to know how many
tasks were running prior to their creation in order to ascertain whether
or not the correct/expected number of tasks are running at any given
time. */
vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
/* Start the tasks and timer running. */ /* Start the tasks and timer running. */
vTaskStartScheduler(); vTaskStartScheduler();
@ -340,7 +350,7 @@ int main(void)
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vCheckTimerCallback( xTimerHandle xTimer ) static void prvCheckTimerCallback( xTimerHandle xTimer )
{ {
/* Check the standard demo tasks are running without error. Latch the /* Check the standard demo tasks are running without error. Latch the
latest reported error in the pcStatusMessage character pointer. */ latest reported error in the pcStatusMessage character pointer. */
@ -379,18 +389,18 @@ static void vCheckTimerCallback( xTimerHandle xTimer )
pcStatusMessage = "Error: RecMutex\r\n"; pcStatusMessage = "Error: RecMutex\r\n";
} }
if( xAreTimerDemoTasksStillRunning( ( mainCHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ) ) != pdTRUE ) if( xAreTimerDemoTasksStillRunning( ( mainCHECK_TIMER_PERIOD_MS ) ) != pdTRUE )
{ {
pcStatusMessage = "Error: TimerDemo"; pcStatusMessage = "Error: TimerDemo";
} }
/* Toggle the check LED to give an indication of the system status. If /* Toggle the check LED to give an indication of the system status. If
the LED toggles every mainCHECK_TIMER_PERIOD_ms milliseconds then the LED toggles every mainCHECK_TIMER_PERIOD_MS milliseconds then
everything is ok. A faster toggle indicates an error. */ everything is ok. A faster toggle indicates an error. */
vParTestToggleLED( mainCHECK_LED ); vParTestToggleLED( mainCHECK_LED );
/* Have any errors been latch in pcStatusMessage? If so, shorten the /* Have any errors been latch in pcStatusMessage? If so, shorten the
period of the check timer to mainERROR_CHECK_TIMER_PERIOD_ms milliseconds. period of the check timer to mainERROR_CHECK_TIMER_PERIOD_MS milliseconds.
This will result in an increase in the rate at which mainCHECK_LED This will result in an increase in the rate at which mainCHECK_LED
toggles. */ toggles. */
if( pcStatusMessage != NULL ) if( pcStatusMessage != NULL )
@ -398,12 +408,12 @@ static void vCheckTimerCallback( xTimerHandle xTimer )
/* This call to xTimerChangePeriod() uses a zero block time. Functions /* This call to xTimerChangePeriod() uses a zero block time. Functions
called from inside of a timer callback function must *never* attempt called from inside of a timer callback function must *never* attempt
to block. */ to block. */
xTimerChangePeriod( xCheckTimer, ( mainERROR_CHECK_TIMER_PERIOD_ms / portTICK_RATE_MS ), mainDONT_BLOCK ); xTimerChangePeriod( xCheckTimer, ( mainERROR_CHECK_TIMER_PERIOD_MS ), mainDONT_BLOCK );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vLEDTimerCallback( xTimerHandle xTimer ) static void prvLEDTimerCallback( xTimerHandle xTimer )
{ {
/* The timer has expired - so no button pushes have occurred in the last /* The timer has expired - so no button pushes have occurred in the last
five seconds - turn the LED off. */ five seconds - turn the LED off. */
@ -443,21 +453,13 @@ static void prvQueueSendTask( void *pvParameters )
portTickType xNextWakeTime; portTickType xNextWakeTime;
const unsigned long ulValueToSend = 100UL; const unsigned long ulValueToSend = 100UL;
/* The suicide tasks must be created last, as they need to know how many
tasks were running prior to their creation in order to ascertain whether
or not the correct/expected number of tasks are running at any given time.
Therefore the standard demo 'death' tasks are not created in main(), but
instead created here. */
vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY );
/* The timer command queue will have been filled when the timer test tasks /* The timer command queue will have been filled when the timer test tasks
were created in main() (this is part of the test they perform). Therefore, were created in main() (this is part of the test they perform). Therefore,
while the check and OLED timers can be created in main(), they cannot be while the check and OLED timers can be created in main(), they cannot be
started from main(). Once the scheduler has started, the timer service started from main(). Once the scheduler has started, the timer service
task will drain the command queue, and now the check and OLED timers can be task will drain the command queue, and now the check and OLED timers can be
started successfully. */ started successfully. */
xTimerStart( xCheckTimer, portMAX_DELAY ); xTimerStart( xCheckTimer, portMAX_DELAY );
xTimerStart( xOLEDTimer, portMAX_DELAY );
/* Initialise xNextWakeTime - this only needs to be done once. */ /* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount(); xNextWakeTime = xTaskGetTickCount();
@ -474,7 +476,7 @@ const unsigned long ulValueToSend = 100UL;
toggle an LED. 0 is used as the block time so the sending operation toggle an LED. 0 is used as the block time so the sending operation
will not block - it shouldn't need to block as the queue should always will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */ be empty at this point in the code. */
xQueueSend( xQueue, &ulValueToSend, 0 ); xQueueSend( xQueue, &ulValueToSend, mainDONT_BLOCK );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -500,33 +502,20 @@ unsigned long ulReceivedValue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vOLEDTimerCallback( xTimerHandle xHandle ) static void prvOLEDTask( void * pvParameters)
{ {
volatile size_t xFreeStackSpace;
static struct oled_data xOLEDData; static struct oled_data xOLEDData;
static unsigned char ucOffset1 = 0, ucOffset2 = 5; static unsigned char ucOffset1 = 0, ucOffset2 = 5;
static portTickType xLastScrollTime = 0UL;
/* This function is called on each cycle of the idle task. In this case it /* Initialise the display. */
does nothing useful, other than report the amount of FreeRTOS heap that OLED_init();
remains unallocated. */
xFreeStackSpace = xPortGetFreeHeapSize();
if( xFreeStackSpace > 100 )
{
/* By now, the kernel has allocated everything it is going to, so
if there is a lot of heap remaining unallocated then
the value of configTOTAL_HEAP_SIZE in FreeRTOSConfig.h can be
reduced accordingly. */
}
/* Initialise the parts of the oled_data structure that do not change. */
xOLEDData.line1 = FIRST_LINE; xOLEDData.line1 = FIRST_LINE;
xOLEDData.char_offset1 = ucOffset1++; xOLEDData.string1 = " www.FreeRTOS.org";
xOLEDData.string1 = "www.FreeRTOS.org";
xOLEDData.line2 = SECOND_LINE; xOLEDData.line2 = SECOND_LINE;
xOLEDData.char_offset2 = ucOffset2++; xOLEDData.string2 = " www.FreeRTOS.org";
xOLEDData.string2 = "www.FreeRTOS.org";
xOLEDData.contrast_val = OLED_CONTRAST_VAL; xOLEDData.contrast_val = OLED_CONTRAST_VAL;
xOLEDData.on_off = OLED_HORIZ_SCROLL_OFF; xOLEDData.on_off = OLED_HORIZ_SCROLL_OFF;
xOLEDData.column_scrool_per_step = OLED_HORIZ_SCROLL_STEP; xOLEDData.column_scrool_per_step = OLED_HORIZ_SCROLL_STEP;
@ -534,21 +523,35 @@ static unsigned char ucOffset1 = 0, ucOffset2 = 5;
xOLEDData.time_intrval_btw_scroll_step = OLED_HORIZ_SCROLL_TINVL; xOLEDData.time_intrval_btw_scroll_step = OLED_HORIZ_SCROLL_TINVL;
xOLEDData.end_page = OLED_END_PAGE; xOLEDData.end_page = OLED_END_PAGE;
OLED_write_data( &xOLEDData, BOTH_LINES );
/* Initialise the last scroll time. This only needs to be done once,
because from this point on it will get automatically updated in the
xTaskDelayUntil() API function. */
xLastScrollTime = xTaskGetTickCount();
for( ;; )
{
/* Wait until it is time to update the OLED again. */
vTaskDelayUntil( &xLastScrollTime, mainOLED_PERIOD_MS );
xOLEDData.char_offset1 = ucOffset1++;
xOLEDData.char_offset2 = ucOffset2++;
OLED_write_data( &xOLEDData, BOTH_LINES );
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupHardware( void ) static void prvSetupHardware( void )
{ {
SystemCoreClockUpdate();
/* Disable the Watch Dog Timer */ /* Disable the Watch Dog Timer */
MSS_WD_disable( ); MSS_WD_disable( );
/* Configure the GPIO for the LEDs. */ /* Configure the GPIO for the LEDs. */
vParTestInitialise(); vParTestInitialise();
/* Initialise the display. */
OLED_init();
/* Setup the GPIO and the NVIC for the switch used in this simple demo. */ /* Setup the GPIO and the NVIC for the switch used in this simple demo. */
NVIC_SetPriority( GPIO8_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); NVIC_SetPriority( GPIO8_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( GPIO8_IRQn ); NVIC_EnableIRQ( GPIO8_IRQn );
@ -561,7 +564,7 @@ void vApplicationMallocFailedHook( void )
{ {
/* Called if a call to pvPortMalloc() fails because there is insufficient /* Called if a call to pvPortMalloc() fails because there is insufficient
free memory available in the FreeRTOS heap. pvPortMalloc() is called free memory available in the FreeRTOS heap. pvPortMalloc() is called
internally by FreeRTOS API functions that create tasks, queues, software internally by FreeRTOS API functions that create tasks, queues, software
timers, and semaphores. The size of the FreeRTOS heap is set by the timers, and semaphores. The size of the FreeRTOS heap is set by the
configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */ configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */
for( ;; ); for( ;; );
@ -616,3 +619,33 @@ char *pcGetTaskStatusMessage( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vMainConfigureTimerForRunTimeStats( void )
{
const unsigned long ulMax32BitValue = 0xffffffffUL;
MSS_TIM64_init( MSS_TIMER_PERIODIC_MODE );
MSS_TIM64_load_immediate( ulMax32BitValue, ulMax32BitValue );
MSS_TIM64_start();
}
/*-----------------------------------------------------------*/
unsigned long ulGetRunTimeCounterValue( void )
{
unsigned long long ullCurrentValue;
const unsigned long long ulMax64BitValue = 0xffffffffffffffffULL;
unsigned long *pulHighWord, *pulLowWord;
pulHighWord = ( unsigned long * ) &ullCurrentValue;
pulLowWord = pulHighWord++;
MSS_TIM64_get_current_value( ( uint32_t * ) pulHighWord, ( uint32_t * ) pulLowWord );
/* Convert the down count into an upcount. */
ullCurrentValue = ulMax64BitValue - ullCurrentValue;
/* Scale to a 32bit number of suitable frequency. */
ullCurrentValue >>= 13;
/* Just return 32 bits. */
return ( unsigned long ) ullCurrentValue;
}

@ -74,27 +74,25 @@
#include "mss_ethernet_mac_regs.h" #include "mss_ethernet_mac_regs.h"
#include "mss_ethernet_mac.h" #include "mss_ethernet_mac.h"
/* The buffer used by the uIP stack to both receive and send. This points to /* The buffer used by the uIP stack to both receive and send. In this case,
one of the Ethernet buffers when its actually in use. */ because the Ethernet driver has been modified to be zero copy - the uip_buf
variable is just a pointer to an Ethernet buffer, and not a buffer in its own
right. */
extern unsigned char *uip_buf; extern unsigned char *uip_buf;
static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; /* The ARP timer and the periodic timer share a callback function, so the
respective timer IDs are used to determine which timer actually expired. These
constants are assigned to the timer IDs. */
#define uipARP_TIMER 0 #define uipARP_TIMER 0
#define uipPERIODIC_TIMER 1 #define uipPERIODIC_TIMER 1
/* The length of the queue used to send events from timers or the Ethernet
driver to the uIP stack. */
#define uipEVENT_QUEUE_LENGTH 10 #define uipEVENT_QUEUE_LENGTH 10
#define uipETHERNET_RX_EVENT 0x01UL /* A block time of zero simply means "don't block". */
#define uipETHERNET_TX_EVENT 0x02UL
#define uipARP_TIMER_EVENT 0x04UL
#define uipPERIODIC_TIMER_EVENT 0x08UL
#define uipAPPLICATION_SEND_EVENT 0x10UL
#define uipDONT_BLOCK 0UL #define uipDONT_BLOCK 0UL
/*-----------------------------------------------------------*/
/* How long to wait before attempting to connect the MAC again. */ /* How long to wait before attempting to connect the MAC again. */
#define uipINIT_WAIT ( 100 / portTICK_RATE_MS ) #define uipINIT_WAIT ( 100 / portTICK_RATE_MS )
@ -113,30 +111,36 @@ static void prvSetMACAddress( void );
/* /*
* Perform any uIP initialisation required to ready the stack for http * Perform any uIP initialisation required to ready the stack for http
* processing. * processing.
*/ */
static void prvInitialise_uIP( void ); static void prvInitialise_uIP( void );
/* /*
* Handles Ethernet interrupt events. * Handles Ethernet interrupt events.
*/ */
static void prvEMACEventListener( unsigned long ulISREvents ); static void prvEMACEventListener( unsigned long ulISREvents );
/*
* The callback function that is assigned to both the periodic timer and the
* ARP timer.
*/
static void prvUIPTimerCallback( xTimerHandle xTimer ); static void prvUIPTimerCallback( xTimerHandle xTimer );
/* /*
* Initialise the MAC hardware. * Initialise the MAC hardware.
*/ */
static void prvInitEmac( void ); static void prvInitEmac( void );
/*
* Write data to the Ethener. Note that this actually writes data twice for the
* to get around delayed ack issues when communicating with a non real-time
* peer (for example, a Windows machine).
*/
void vEMACWrite( void ); void vEMACWrite( void );
long lEMACWaitForLink( void );
/* /*
* Port functions required by the uIP stack. * Port functions required by the uIP stack.
*/ */
void clock_init( void );
clock_time_t clock_time( void ); clock_time_t clock_time( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -144,14 +148,6 @@ clock_time_t clock_time( void );
/* The queue used to send TCP/IP events to the uIP stack. */ /* The queue used to send TCP/IP events to the uIP stack. */
xQueueHandle xEMACEventQueue = NULL; xQueueHandle xEMACEventQueue = NULL;
static unsigned long ulUIP_Events = 0UL;
/*-----------------------------------------------------------*/
void clock_init(void)
{
/* This is done when the scheduler starts. */
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
clock_time_t clock_time( void ) clock_time_t clock_time( void )
@ -163,89 +159,92 @@ clock_time_t clock_time( void )
void vuIP_Task( void *pvParameters ) void vuIP_Task( void *pvParameters )
{ {
portBASE_TYPE i; portBASE_TYPE i;
unsigned long ulNewEvent; unsigned long ulNewEvent = 0UL;
unsigned long ulUIP_Events = 0UL;
/* Just to prevent compiler warnings about the unused parameter. */
( void ) pvParameters; ( void ) pvParameters;
/* Initialise the uIP stack, configuring for web server usage. */ /* Initialise the uIP stack, configuring for web server usage. */
prvInitialise_uIP(); prvInitialise_uIP();
/* Initialise the MAC. */ /* Initialise the MAC and PHY. */
prvInitEmac(); prvInitEmac();
for( ;; ) for( ;; )
{ {
if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL ) /* Is there received data ready to be processed? */
{ uip_len = MSS_MAC_rx_packet();
ulUIP_Events &= ~uipETHERNET_TX_EVENT;
MSS_MAC_TxBufferCompleted();
}
if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL ) /* Statements to be executed if data has been received on the Ethernet. */
if( ( uip_len > 0 ) && ( uip_buf != NULL ) )
{ {
ulUIP_Events &= ~uipETHERNET_RX_EVENT; /* Standard uIP loop taken from the uIP manual. */
if( xHeader->type == htons( UIP_ETHTYPE_IP ) )
/* Is there received data ready to be processed? */
uip_len = MSS_MAC_rx_packet();
if( ( uip_len > 0 ) && ( uip_buf != NULL ) )
{ {
/* Standard uIP loop taken from the uIP manual. */ uip_arp_ipin();
if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) uip_input();
{
uip_arp_ipin();
uip_input();
/* If the above function invocation resulted in data that /* If the above function invocation resulted in data that
should be sent out on the network, the global variable should be sent out on the network, the global variable
uip_len is set to a value > 0. */ uip_len is set to a value > 0. */
if( uip_len > 0 ) if( uip_len > 0 )
{
uip_arp_out();
vEMACWrite();
}
}
else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )
{ {
uip_arp_arpin(); uip_arp_out();
vEMACWrite();
}
}
else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )
{
uip_arp_arpin();
/* If the above function invocation resulted in data that /* If the above function invocation resulted in data that
should be sent out on the network, the global variable should be sent out on the network, the global variable
uip_len is set to a value > 0. */ uip_len is set to a value > 0. */
if( uip_len > 0 ) if( uip_len > 0 )
{ {
vEMACWrite(); vEMACWrite();
}
} }
} }
} }
else
{
/* Clear the RX event latched in ulUIP_Events - if one was latched. */
ulUIP_Events &= ~uipETHERNET_RX_EVENT;
}
/* Statements to be executed if the TCP/IP period timer has expired. */
if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL )
{ {
ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT; ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;
for( i = 0; i < UIP_CONNS; i++ ) if( uip_buf != NULL )
{ {
uip_periodic( i ); for( i = 0; i < UIP_CONNS; i++ )
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if( uip_len > 0 )
{ {
uip_arp_out(); uip_periodic( i );
vEMACWrite();
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if( uip_len > 0 )
{
uip_arp_out();
vEMACWrite();
}
} }
} }
} }
/* Call the ARP timer function every 10 seconds. */ /* Statements to be executed if the ARP timer has expired. */
if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )
{ {
ulUIP_Events &= ~uipARP_TIMER_EVENT; ulUIP_Events &= ~uipARP_TIMER_EVENT;
uip_arp_timer(); uip_arp_timer();
} }
/* If all latched events have been cleared - block until another event
occurs. */
if( ulUIP_Events == pdFALSE ) if( ulUIP_Events == pdFALSE )
{ {
xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY ); xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );
@ -270,49 +269,6 @@ struct uip_eth_addr xAddr;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationProcessFormInput( char *pcInputString )
{
char *c;
/* Only interested in processing form input if this is the IO page. */
c = strstr( pcInputString, "io.shtml" );
if( c )
{
/* Is there a command in the string? */
c = strstr( pcInputString, "?" );
if( c )
{
/* Turn the LED's on or off in accordance with the check box status. */
if( strstr( c, "LED0=1" ) != NULL )
{
/* Turn the LEDs on. */
vParTestSetLED( 7, 1 );
vParTestSetLED( 8, 1 );
vParTestSetLED( 9, 1 );
vParTestSetLED( 10, 1 );
}
else
{
/* Turn the LEDs off. */
vParTestSetLED( 7, 0 );
vParTestSetLED( 8, 0 );
vParTestSetLED( 9, 0 );
vParTestSetLED( 10, 0 );
}
}
else
{
/* Commands to turn LEDs off are not always explicit. */
vParTestSetLED( 7, 0 );
vParTestSetLED( 8, 0 );
vParTestSetLED( 9, 0 );
vParTestSetLED( 10, 0 );
}
}
}
/*-----------------------------------------------------------*/
static void prvInitialise_uIP( void ) static void prvInitialise_uIP( void )
{ {
uip_ipaddr_t xIPAddr; uip_ipaddr_t xIPAddr;
@ -331,22 +287,25 @@ xTimerHandle xARPTimer, xPeriodicTimer;
/* Create and start the uIP timers. */ /* Create and start the uIP timers. */
xARPTimer = xTimerCreate( ( const signed char * const ) "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */ xARPTimer = xTimerCreate( ( const signed char * const ) "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */
( 500 / portTICK_RATE_MS ), /* Timer period. */ ( 10000UL / portTICK_RATE_MS ), /* Timer period. */
pdTRUE, /* Autor-reload. */ pdTRUE, /* Autor-reload. */
( void * ) uipARP_TIMER, ( void * ) uipARP_TIMER,
prvUIPTimerCallback prvUIPTimerCallback
); );
xPeriodicTimer = xTimerCreate( ( const signed char * const ) "PeriodicTimer", xPeriodicTimer = xTimerCreate( ( const signed char * const ) "PeriodicTimer",
( 5000 / portTICK_RATE_MS ), ( 500UL / portTICK_RATE_MS ),
pdTRUE, /* Autor-reload. */ pdTRUE, /* Autor-reload. */
( void * ) uipPERIODIC_TIMER, ( void * ) uipPERIODIC_TIMER,
prvUIPTimerCallback prvUIPTimerCallback
); );
/* Sanity check that the timers were indeed created. */
configASSERT( xARPTimer ); configASSERT( xARPTimer );
configASSERT( xPeriodicTimer ); configASSERT( xPeriodicTimer );
/* These commands will block indefinitely until they succeed, so there is
no point in checking their return values. */
xTimerStart( xARPTimer, portMAX_DELAY ); xTimerStart( xARPTimer, portMAX_DELAY );
xTimerStart( xPeriodicTimer, portMAX_DELAY ); xTimerStart( xPeriodicTimer, portMAX_DELAY );
} }
@ -355,24 +314,21 @@ xTimerHandle xARPTimer, xPeriodicTimer;
static void prvEMACEventListener( unsigned long ulISREvents ) static void prvEMACEventListener( unsigned long ulISREvents )
{ {
long lHigherPriorityTaskWoken = pdFALSE; long lHigherPriorityTaskWoken = pdFALSE;
unsigned long ulUIPEvents = 0UL; const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
/* Sanity check that the event queue was indeed created. */
configASSERT( xEMACEventQueue ); configASSERT( xEMACEventQueue );
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL ) if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL )
{ {
ulUIP_Events |= uipETHERNET_TX_EVENT; /* An Ethernet Tx event has occurred. */
MSS_MAC_FreeTxBuffers();
} }
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL ) if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL )
{ {
/* Wake the uIP task as new data has arrived. */ /* An Ethernet Rx event has occurred. */
ulUIPEvents |= uipETHERNET_RX_EVENT; xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
}
if( ulUIPEvents != 0UL )
{
xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );
} }
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken ); portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
@ -383,9 +339,12 @@ static void prvInitEmac( void )
{ {
const unsigned char ucPHYAddress = 1; const unsigned char ucPHYAddress = 1;
/* Initialise the MAC and PHY hardware. */
MSS_MAC_init( ucPHYAddress ); MSS_MAC_init( ucPHYAddress );
MSS_MAC_set_callback( prvEMACEventListener ); /* Register the event listener. The Ethernet interrupt handler will call
this listener whenever an Rx or a Tx interrupt occurs. */
MSS_MAC_set_callback( ( MSS_MAC_callback_t ) prvEMACEventListener );
/* Setup the EMAC and the NVIC for MAC interrupts. */ /* Setup the EMAC and the NVIC for MAC interrupts. */
NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
@ -399,6 +358,10 @@ const long lMaxAttempts = 10;
long lAttempt; long lAttempt;
const portTickType xShortDelay = ( 10 / portTICK_RATE_MS ); const portTickType xShortDelay = ( 10 / portTICK_RATE_MS );
/* Try to send data to the Ethernet. Keep trying for a while if data cannot
be sent immediately. Note that this will actually cause the data to be sent
twice to get around delayed ACK problems when communicating with non real-
time TCP/IP stacks (such as a Windows machine). */
for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ ) for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ )
{ {
if( MSS_MAC_tx_packet( uip_len ) != 0 ) if( MSS_MAC_tx_packet( uip_len ) != 0 )
@ -413,28 +376,14 @@ const portTickType xShortDelay = ( 10 / portTICK_RATE_MS );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
long lEMACWaitForLink( void )
{
long lReturn = pdFAIL;
unsigned long ulStatus;
ulStatus = MSS_MAC_link_status();
if( ( ulStatus & ( unsigned long ) MSS_MAC_LINK_STATUS_LINK ) != 0UL )
{
lReturn = pdPASS;
}
return lReturn;
}
/*-----------------------------------------------------------*/
static void prvUIPTimerCallback( xTimerHandle xTimer ) static void prvUIPTimerCallback( xTimerHandle xTimer )
{ {
static const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT; static const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT;
static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT; static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT;
/* This is a time callback, so calls to xQueueSend() must not attempt to /* This is a time callback, so calls to xQueueSend() must not attempt to
block. */ block. As this callback is assigned to both the ARP and Periodic timers, the
first thing to do is ascertain which timer it was that actually expired. */
switch( ( int ) pvTimerGetTimerID( xTimer ) ) switch( ( int ) pvTimerGetTimerID( xTimer ) )
{ {
case uipARP_TIMER : xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK ); case uipARP_TIMER : xQueueSend( xEMACEventQueue, &ulARPTimerExpired, uipDONT_BLOCK );
@ -448,3 +397,40 @@ static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT;
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationProcessFormInput( char *pcInputString )
{
char *c;
/* Only interested in processing form input if this is the IO page. */
c = strstr( pcInputString, "io.shtml" );
if( c )
{
/* Is there a command in the string? */
c = strstr( pcInputString, "?" );
if( c )
{
/* Turn the LED's on or off in accordance with the check box status. */
if( strstr( c, "LED0=1" ) != NULL )
{
/* Turn the LEDs on. */
vParTestSetLED( 3, 1 );
vParTestSetLED( 4, 1 );
}
else
{
/* Turn the LEDs off. */
vParTestSetLED( 3, 0 );
vParTestSetLED( 4, 0 );
}
}
else
{
/* Commands to turn LEDs off are not always explicit. */
vParTestSetLED( 3, 0 );
vParTestSetLED( 4, 0 );
}
}
}
/*-----------------------------------------------------------*/

Loading…
Cancel
Save