mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-05-10 23:29:02 -04:00
Update the A2F SoftConsole project to match the current A2F IAR project.
This commit is contained in:
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 *
|
||||
* available. *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* then take a look at the FreeRTOS books - available as PDF or paperback *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). Thank you for your support! *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
||||
a combined work that includes FreeRTOS without being obliged to provide the
|
||||
source code for proprietary components outside of the FreeRTOS kernel.
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
|
@ -57,12 +63,15 @@
|
|||
* executed from within CCS4! Once it has been executed, re-open or refresh
|
||||
* 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
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
|
@ -75,21 +84,23 @@
|
|||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern uint32_t SystemFrequency;
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( 75000000UL )
|
||||
#define configCPU_CLOCK_HZ ( SystemFrequency )
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 40 * 1024 ) )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 90 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 10 )
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configQUEUE_REGISTRY_SIZE 0
|
||||
#define configGENERATE_RUN_TIME_STATS 0
|
||||
#define configGENERATE_RUN_TIME_STATS 1
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_MALLOC_FAILED_HOOK 1
|
||||
|
@ -102,7 +113,7 @@
|
|||
|
||||
/* Software timer definitions. */
|
||||
#define configUSE_TIMERS 1
|
||||
#define configTIMER_TASK_PRIORITY ( 3 )
|
||||
#define configTIMER_TASK_PRIORITY ( 2 )
|
||||
#define configTIMER_QUEUE_LENGTH 10
|
||||
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )
|
||||
|
||||
|
@ -116,6 +127,11 @@ to exclude the API function. */
|
|||
#define INCLUDE_vTaskDelayUntil 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 */
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
#define configPRIO_BITS __NVIC_PRIO_BITS
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* SVN $Revision: 2152 $
|
||||
* SVN $Date: 2010-02-11 14:44:11 +0000 (Thu, 11 Feb 2010) $
|
||||
*/
|
||||
|
||||
|
||||
#include "i2c.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_CR0 = clock_speed & 0x01;
|
||||
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;
|
||||
|
||||
ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) );
|
||||
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
|
||||
|
||||
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) );
|
||||
|
||||
#ifdef USE_OLD_I2C_POLLING_CODE
|
||||
while ( this_i2c->status == MSS_I2C_IN_PROGRESS )
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -451,12 +479,14 @@ mss_i2c_status_t MSS_I2C_wait_complete
|
|||
static void mss_i2c_isr
|
||||
(
|
||||
mss_i2c_instance_t * this_i2c
|
||||
)
|
||||
)
|
||||
{
|
||||
volatile uint8_t status;
|
||||
uint8_t data;
|
||||
uint8_t hold_bus;
|
||||
uint8_t clear_irq = 1;
|
||||
long lHigherPriorityTaskWoken = pdFALSE;
|
||||
configASSERT( ( this_i2c->xI2CCompleteSemaphore ) );
|
||||
|
||||
ASSERT( (this_i2c == &g_mss_i2c0) || (this_i2c == &g_mss_i2c1) );
|
||||
|
||||
|
@ -539,6 +569,7 @@ static void mss_i2c_isr
|
|||
clear_irq = 0;
|
||||
}
|
||||
this_i2c->status = MSS_I2C_SUCCESS;
|
||||
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -577,6 +608,7 @@ static void mss_i2c_isr
|
|||
clear_irq = 0;
|
||||
}
|
||||
this_i2c->status = MSS_I2C_SUCCESS;
|
||||
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
|
||||
}
|
||||
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) */
|
||||
this_i2c->hw_reg_bit->CTRL_STO = 0x01;
|
||||
this_i2c->status = MSS_I2C_FAILED;
|
||||
xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
|
||||
break;
|
||||
|
||||
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;
|
||||
// xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
|
||||
break;
|
||||
|
||||
/******************** SLAVE RECEIVER **************************/
|
||||
|
@ -696,6 +730,7 @@ static void mss_i2c_isr
|
|||
}
|
||||
/* Mark any previous master write transaction as complete. */
|
||||
this_i2c->status = MSS_I2C_SUCCESS;
|
||||
// xSemaphoreGiveFromISR( this_i2c->xI2CCompleteSemaphore, &lHigherPriorityTaskWoken );
|
||||
break;
|
||||
|
||||
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
|
||||
* in a system built around a bus making use of posted writes. */
|
||||
status = this_i2c->hw_reg->STATUS;
|
||||
|
||||
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
|
|
@ -194,6 +194,11 @@
|
|||
|
||||
#include "../../CMSIS/a2fxxxm3.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -325,6 +330,9 @@ typedef struct mss_i2c_instance
|
|||
uint_fast8_t slave_mem_offset_length;
|
||||
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;
|
||||
|
||||
/*-------------------------------------------------------------------------*//**
|
||||
|
|
|
@ -9,6 +9,15 @@
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* NOTE: This driver has been modified specifically for use with the* uIP stack.
|
||||
* It is no longer a generic driver.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -29,7 +38,7 @@ extern "C" {
|
|||
/**************************** INTERNAL DEFINES ********************************/
|
||||
|
||||
#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
|
||||
|
@ -54,8 +63,8 @@ extern "C" {
|
|||
/* 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
|
||||
to the same buffer. */
|
||||
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE
|
||||
#define macBUFFER_SIZE 1500
|
||||
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 1
|
||||
#define macBUFFER_SIZE 1488
|
||||
|
||||
/***************************************************************/
|
||||
MAC_instance_t g_mss_mac;
|
||||
|
@ -78,15 +87,16 @@ static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = {
|
|||
/*
|
||||
* Null variables
|
||||
*/
|
||||
static MAC_instance_t* NULL_instance;
|
||||
static uint8_t* NULL_buffer;
|
||||
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;
|
||||
|
||||
/**************************** INTERNAL FUNCTIONS ******************************/
|
||||
|
||||
static int32_t MAC_test_instance( void );
|
||||
|
||||
static int32_t MAC_dismiss_bad_frames( 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
|
||||
#endif
|
||||
|
||||
/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */
|
||||
static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ];
|
||||
/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors.
|
||||
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
|
||||
is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */
|
||||
static unsigned char ucMACBufferFree[ macNUM_BUFFERS ];
|
||||
/* Each array position indicates whether or not the buffer of the same index
|
||||
is currently allocated to a descriptor (pdTRUE) or is free for use (pdFALSE). */
|
||||
static unsigned char ucMACBufferInUse[ macNUM_BUFFERS ] = { 0 };
|
||||
|
||||
/***************************************************************************//**
|
||||
* Initializes the Ethernet Controller.
|
||||
|
@ -138,7 +153,7 @@ MSS_MAC_init
|
|||
/* To start with all buffers are free. */
|
||||
for( a = 0; a < macNUM_BUFFERS; a++ )
|
||||
{
|
||||
ucMACBufferFree[ a ] = pdTRUE;
|
||||
ucMACBufferInUse[ a ] = pdFALSE;
|
||||
}
|
||||
|
||||
/* Try to reset chip */
|
||||
|
@ -151,9 +166,9 @@ MSS_MAC_init
|
|||
|
||||
/* Check reset values of some registers to constrol
|
||||
* base address validity */
|
||||
ASSERT( MAC->CSR0 == 0xFE000000uL );
|
||||
ASSERT( MAC->CSR5 == 0xF0000000uL );
|
||||
ASSERT( MAC->CSR6 == 0x32000040uL );
|
||||
configASSERT( MAC->CSR0 == 0xFE000000uL );
|
||||
configASSERT( MAC->CSR5 == 0xF0000000uL );
|
||||
configASSERT( MAC->CSR6 == 0x32000040uL );
|
||||
|
||||
/* Instance setup */
|
||||
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
|
||||
(not free). */
|
||||
g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] );
|
||||
ucMACBufferFree[ a ] = pdFALSE;
|
||||
g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( xMACBuffers.ucBuffer[ a ][ 0 ] );
|
||||
ucMACBufferInUse[ a ] = pdTRUE;
|
||||
}
|
||||
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;
|
||||
|
||||
/* Fixed settings */
|
||||
/* No automatic polling */
|
||||
MAC->CSR0 = MAC->CSR0 &~ CSR0_TAP_MASK;
|
||||
/* No space between descriptors */
|
||||
MAC->CSR0 = MAC->CSR0 &~ CSR0_DSL_MASK;
|
||||
/* General-purpose timer works in continuous mode */
|
||||
|
@ -198,11 +211,14 @@ MSS_MAC_init
|
|||
/* Start general-purpose */
|
||||
MAC->CSR11 = (MAC->CSR11 & ~CSR11_TIM_MASK) | (0x0000FFFFuL << CSR11_TIM_SHIFT);
|
||||
|
||||
/* Disable promiscuous mode */
|
||||
MAC_BITBAND->CSR6_PR = 0u;
|
||||
/* Ensure promiscous mode is off (it should be by default anyway). */
|
||||
MAC_BITBAND->CSR6_PR = 0;
|
||||
|
||||
/* Enable store and forward */
|
||||
MAC_BITBAND->CSR6_SF = 1u;
|
||||
/* Perfect filter. */
|
||||
MAC_BITBAND->CSR6_HP = 1;
|
||||
|
||||
/* Pass multcast. */
|
||||
MAC_BITBAND->CSR6_PM = 1;
|
||||
|
||||
/* Set descriptors */
|
||||
MAC->CSR3 = (uint32_t)&(g_mss_mac.rx_descriptors[0].descriptor_0);
|
||||
|
@ -211,26 +227,25 @@ MSS_MAC_init
|
|||
/* enable normal interrupts */
|
||||
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 */
|
||||
if( g_mss_mac.phy_address > MSS_PHY_ADDRESS_MAX )
|
||||
{
|
||||
PHY_probe();
|
||||
ASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
|
||||
configASSERT( g_mss_mac.phy_address <= MSS_PHY_ADDRESS_MAX );
|
||||
}
|
||||
|
||||
/* Reset PHY */
|
||||
PHY_reset();
|
||||
|
||||
/* Set flags */
|
||||
g_mss_mac.flags = FLAG_MAC_INIT_DONE | FLAG_PERFECT_FILTERING;
|
||||
|
||||
/* Configure chip according to PHY status */
|
||||
MSS_MAC_auto_setup_link();
|
||||
|
||||
/* Set default MAC address and reset mac filters */
|
||||
MAC_memcpy( g_mss_mac.mac_address, mac_address, 6u );
|
||||
MSS_MAC_set_mac_filters( 0u, NULL_buffer );
|
||||
MAC_BITBAND->CSR6_RA = 1; /* Receive all. */
|
||||
/* Ensure uip_buf starts by pointing somewhere. */
|
||||
uip_buf = MAC_obtain_buffer();
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,13 +274,11 @@ MSS_MAC_configure
|
|||
{
|
||||
int32_t ret;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
ret = MAC_stop_transmission();
|
||||
ASSERT( ret == MAC_OK );
|
||||
configASSERT( ret == MAC_OK );
|
||||
|
||||
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_TTM = (((configuration & MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE) != 0u) ? 1u : 0u );
|
||||
|
@ -322,8 +335,6 @@ MSS_MAC_get_configuration( void )
|
|||
{
|
||||
uint32_t configuration;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
configuration = 0u;
|
||||
if( MAC_BITBAND->CSR6_RA != 0u ) {
|
||||
configuration |= MSS_MAC_CFG_RECEIVE_ALL;
|
||||
|
@ -399,42 +410,42 @@ MSS_MAC_tx_packet
|
|||
uint32_t desc;
|
||||
unsigned long ulDescriptor;
|
||||
int32_t error = MAC_OK;
|
||||
extern unsigned char *uip_buf;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
configASSERT( uip_buf != NULL_buffer );
|
||||
|
||||
ASSERT( uip_buf != NULL_buffer );
|
||||
|
||||
ASSERT( usLength >= 12 );
|
||||
configASSERT( usLength >= 12 );
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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++ )
|
||||
{
|
||||
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 ) {
|
||||
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
|
||||
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 */
|
||||
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 */
|
||||
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. */
|
||||
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 */
|
||||
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 ) {
|
||||
g_mss_mac.statistics.tx_loss_of_carrier++;
|
||||
}
|
||||
|
@ -468,26 +479,22 @@ MSS_MAC_tx_packet
|
|||
(desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Start transmission */
|
||||
MAC_start_transmission();
|
||||
|
||||
/* transmit poll demand */
|
||||
MAC->CSR1 = 1u;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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
|
||||
{
|
||||
|
@ -512,8 +519,6 @@ MSS_MAC_rx_pckt_size
|
|||
)
|
||||
{
|
||||
int32_t retval;
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
MAC_dismiss_bad_frames();
|
||||
|
||||
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) != 0u )
|
||||
|
@ -549,8 +554,6 @@ MSS_MAC_rx_packet
|
|||
{
|
||||
uint16_t frame_length=0u;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
MAC_dismiss_bad_frames();
|
||||
|
||||
if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
|
||||
|
@ -614,9 +617,7 @@ MSS_MAC_rx_packet_ptrset
|
|||
uint16_t frame_length = 0u;
|
||||
int8_t exit = 0;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
ASSERT( (time_out == MSS_MAC_BLOCKING) ||
|
||||
configASSERT( (time_out == MSS_MAC_BLOCKING) ||
|
||||
(time_out == MSS_MAC_NONBLOCKING) ||
|
||||
((time_out >= 1) && (time_out <= 0x01000000UL)) );
|
||||
|
||||
|
@ -679,8 +680,6 @@ MSS_MAC_link_status
|
|||
{
|
||||
uint32_t link;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
link = PHY_link_status();
|
||||
if( link == MSS_MAC_LINK_STATUS_LINK ) {
|
||||
link |= PHY_link_type();
|
||||
|
@ -706,7 +705,6 @@ MSS_MAC_auto_setup_link
|
|||
)
|
||||
{
|
||||
int32_t link;
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
PHY_auto_negotiate();
|
||||
|
||||
|
@ -741,9 +739,8 @@ MSS_MAC_set_mac_address
|
|||
const uint8_t *new_address
|
||||
)
|
||||
{
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
/* 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 );
|
||||
|
||||
|
@ -777,8 +774,6 @@ MSS_MAC_get_mac_address
|
|||
uint8_t *address
|
||||
)
|
||||
{
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
MAC_memcpy( address, g_mss_mac.mac_address, 6u );
|
||||
}
|
||||
|
||||
|
@ -796,13 +791,12 @@ MSS_MAC_set_mac_filters
|
|||
const uint8_t *filters
|
||||
)
|
||||
{
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
ASSERT( (filter_count==0) || (filters != NULL_buffer) );
|
||||
configASSERT( (filter_count==0) || (filters != NULL_buffer) );
|
||||
/* Check if the mac addresses is multicast */
|
||||
{
|
||||
int32_t 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 intr_status;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
events = 0u;
|
||||
intr_status = MAC->CSR5;
|
||||
|
||||
|
@ -896,8 +888,6 @@ MSS_MAC_set_callback
|
|||
MSS_MAC_callback_t listener
|
||||
)
|
||||
{
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
/* disable tx and rx interrupts */
|
||||
MAC_BITBAND->CSR7_RIE = 0u;
|
||||
MAC_BITBAND->CSR7_TIE = 0u;
|
||||
|
@ -930,8 +920,6 @@ MSS_MAC_last_error
|
|||
int8_t error_msg_nb;
|
||||
const int8_t* returnvalue;
|
||||
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
error_msg_nb = -(g_mss_mac.last_error);
|
||||
if( error_msg_nb >= ERROR_MESSAGE_COUNT ) {
|
||||
returnvalue = unknown_error;
|
||||
|
@ -957,7 +945,6 @@ MSS_MAC_get_statistics
|
|||
)
|
||||
{
|
||||
uint32_t returnval = 0u;
|
||||
ASSERT( MAC_test_instance() == MAC_OK );
|
||||
|
||||
switch( stat_id ) {
|
||||
case MSS_MAC_RX_INTERRUPTS:
|
||||
|
@ -1024,31 +1011,6 @@ MSS_MAC_get_statistics
|
|||
|
||||
/**************************** 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.
|
||||
|
@ -1166,10 +1128,10 @@ MAC_send_setup_frame
|
|||
|
||||
/* Stop transmission */
|
||||
ret = MAC_stop_transmission();
|
||||
ASSERT( ret == MAC_OK );
|
||||
configASSERT( ret == MAC_OK );
|
||||
|
||||
ret = MAC_stop_receiving();
|
||||
ASSERT( ret == MAC_OK );
|
||||
configASSERT( ret == MAC_OK );
|
||||
|
||||
/* Set descriptor */
|
||||
MAC->CSR4 = (uint32_t)&descriptor;
|
||||
|
@ -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_filter_data, (uint8_t)c, 90u );
|
||||
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;
|
||||
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_underflow_error = 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;
|
||||
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;
|
||||
|
||||
/* Was it the second transmission that has completed? */
|
||||
if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )
|
||||
if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )
|
||||
{
|
||||
pxTransmittedBuffer = ( 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 );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned char *pcReturn = NULL;
|
||||
|
@ -1493,9 +1454,10 @@ unsigned char *pcReturn = NULL;
|
|||
the buffer as now in use. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1504,6 +1466,10 @@ unsigned char *pcReturn = NULL;
|
|||
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 )
|
||||
{
|
||||
long lIndex;
|
||||
|
@ -1512,13 +1478,15 @@ long lIndex;
|
|||
it is currently pointing to is marked as being free again. */
|
||||
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. */
|
||||
ucMACBufferFree[ lIndex ] = pdTRUE;
|
||||
ucMACBufferInUse[ lIndex ] = pdFALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
configASSERT( lIndex < macNUM_BUFFERS );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -560,23 +560,11 @@ MSS_MAC_get_statistics
|
|||
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 MAC hardware.
|
||||
*/
|
||||
void MSS_MAC_TxBufferCompleted( void );
|
||||
void MSS_MAC_FreeTxBuffers( void );
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef struct {
|
|||
* may be read by receiving its flags field, similarly MAC_configure routine lets
|
||||
* you modify some of these flags.
|
||||
*/
|
||||
#include "net/pack_struct_start.h"
|
||||
typedef struct {
|
||||
addr_t base_address; /**< Register base address of the driver*/
|
||||
uint8_t flags; /**< Configuration of the driver*/
|
||||
|
@ -65,12 +66,10 @@ typedef struct {
|
|||
|
||||
/* transmit related info: */
|
||||
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*/
|
||||
|
||||
/* receive related info: */
|
||||
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*/
|
||||
|
||||
uint8_t phy_address; /**< MII address of the connected PHY*/
|
||||
|
@ -113,7 +112,8 @@ typedef struct {
|
|||
uint32_t tx_underflow_error; /**< Number of occurrences of; the FIFO was empty during
|
||||
the frame transmission.*/
|
||||
} statistics;
|
||||
} MAC_instance_t;
|
||||
} MAC_instance_t
|
||||
#include "net/pack_struct_end.h"
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
|
|
@ -172,6 +172,7 @@ long lReturn = pdFALSE;
|
|||
lReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
return lReturn;
|
||||
|
|
|
@ -212,7 +212,7 @@ static unsigned short generate_io_state( void *arg )
|
|||
( void ) arg;
|
||||
|
||||
/* Are the dynamically setable LEDs currently on or off? */
|
||||
if( lParTestGetLEDState( 8 ) )
|
||||
if( lParTestGetLEDState( 3 ) )
|
||||
{
|
||||
pcStatus = "checked";
|
||||
}
|
||||
|
@ -229,26 +229,13 @@ static unsigned short generate_io_state( void *arg )
|
|||
/*---------------------------------------------------------------------------*/
|
||||
extern void vTaskGetRunTimeStats( signed char *pcWriteBuffer );
|
||||
extern unsigned short usMaxJitter;
|
||||
static char cJitterBuffer[ 200 ];
|
||||
static unsigned short generate_runtime_stats( void *arg )
|
||||
{
|
||||
( void ) arg;
|
||||
lRefreshCount++;
|
||||
sprintf( cCountBuf, "<p><br>Refresh count = %d", ( int ) lRefreshCount );
|
||||
|
||||
#ifdef INCLUDE_HIGH_FREQUENCY_TIMER_TEST
|
||||
{
|
||||
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 );
|
||||
|
||||
return strlen( uip_appdata );
|
||||
|
|
|
@ -71,11 +71,11 @@
|
|||
* incorporates a Cortex-M3 microcontroller.
|
||||
*
|
||||
* The main() Function:
|
||||
* main() creates three demo specific software timers, one demo specific queue,
|
||||
* and two demo specific tasks. It then creates a whole host of 'standard demo'
|
||||
* tasks/queues/semaphores, before starting the scheduler. The demo specific
|
||||
* tasks and timers are described in the comments here. The standard demo
|
||||
* tasks are described on the FreeRTOS.org web site.
|
||||
* main() creates two demo specific software timers, one demo specific queue,
|
||||
* and three demo specific tasks. It then creates a whole host of 'standard
|
||||
* demo' tasks/queues/semaphores, before starting the scheduler. The demo
|
||||
* specific tasks and timers are described in the comments here. The standard
|
||||
* demo tasks are described on the FreeRTOS.org web site.
|
||||
*
|
||||
* The standard demo tasks provide no specific functionality. They are
|
||||
* 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
|
||||
* 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 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
|
||||
|
@ -110,10 +115,6 @@
|
|||
* 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.
|
||||
*
|
||||
* 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:
|
||||
* 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
|
||||
|
@ -122,7 +123,7 @@
|
|||
* is ever discovered. The check timer callback toggles the LED defined by
|
||||
* the mainCHECK_LED definition each time it executes. Therefore, if LED
|
||||
* 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
|
||||
* bottom of the "task stats" page that is served by the embedded web server.
|
||||
*
|
||||
|
@ -146,6 +147,7 @@
|
|||
/* Microsemi drivers/libraries includes. */
|
||||
#include "mss_gpio.h"
|
||||
#include "mss_watchdog.h"
|
||||
#include "mss_timer.h"
|
||||
#include "oled.h"
|
||||
|
||||
/* Common demo includes. */
|
||||
|
@ -193,6 +195,7 @@ the queue empty. */
|
|||
#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
|
||||
#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||
#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
#define mainOLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
|
||||
#define mainINTEGER_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
|
||||
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
|
||||
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
|
||||
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. */
|
||||
#define mainDONT_BLOCK ( 0UL )
|
||||
|
@ -231,17 +238,12 @@ static void prvQueueSendTask( void *pvParameters );
|
|||
* The LED timer callback function. This does nothing but switch the red LED
|
||||
* 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.
|
||||
*/
|
||||
static void vOLEDTimerCallback( xTimerHandle xHandle );
|
||||
static void prvCheckTimerCallback( xTimerHandle xTimer );
|
||||
|
||||
/*
|
||||
* This is not a 'standard' partest function, so the prototype is not in
|
||||
|
@ -254,22 +256,26 @@ void vParTestSetLEDFromISR( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE x
|
|||
*/
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
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
|
||||
page, which is served by the uIP task. This will report any errors picked up
|
||||
by the check timer callback. */
|
||||
|
@ -287,33 +293,31 @@ int main(void)
|
|||
|
||||
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. */
|
||||
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( prvOLEDTask, ( signed char * ) "OLED", configMINIMAL_STACK_SIZE, NULL, mainOLED_TASK_PRIORITY, NULL );
|
||||
|
||||
/* 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
|
||||
this file. */
|
||||
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. */
|
||||
( 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,
|
||||
as described at the top of this file. */
|
||||
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). */
|
||||
xCheckTimer = xTimerCreate( ( const signed char * ) "CheckTimer",/* A text name, purely to help debugging. */
|
||||
( 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. */
|
||||
( 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. */
|
||||
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
|
||||
vCreateBlockTimeTasks();
|
||||
|
@ -325,7 +329,13 @@ int main(void)
|
|||
vStartTimerDemoTask( mainTIMER_TEST_PERIOD );
|
||||
|
||||
/* 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. */
|
||||
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
|
||||
latest reported error in the pcStatusMessage character pointer. */
|
||||
|
@ -379,18 +389,18 @@ static void vCheckTimerCallback( xTimerHandle xTimer )
|
|||
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";
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
vParTestToggleLED( mainCHECK_LED );
|
||||
|
||||
/* 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
|
||||
toggles. */
|
||||
if( pcStatusMessage != NULL )
|
||||
|
@ -398,12 +408,12 @@ static void vCheckTimerCallback( xTimerHandle xTimer )
|
|||
/* This call to xTimerChangePeriod() uses a zero block time. Functions
|
||||
called from inside of a timer callback function must *never* attempt
|
||||
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
|
||||
five seconds - turn the LED off. */
|
||||
|
@ -443,13 +453,6 @@ static void prvQueueSendTask( void *pvParameters )
|
|||
portTickType xNextWakeTime;
|
||||
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
|
||||
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
|
||||
|
@ -457,7 +460,6 @@ const unsigned long ulValueToSend = 100UL;
|
|||
task will drain the command queue, and now the check and OLED timers can be
|
||||
started successfully. */
|
||||
xTimerStart( xCheckTimer, portMAX_DELAY );
|
||||
xTimerStart( xOLEDTimer, portMAX_DELAY );
|
||||
|
||||
/* Initialise xNextWakeTime - this only needs to be done once. */
|
||||
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
|
||||
will not block - it shouldn't need to block as the queue should always
|
||||
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 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
|
||||
does nothing useful, other than report the amount of FreeRTOS heap that
|
||||
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 display. */
|
||||
OLED_init();
|
||||
|
||||
/* Initialise the parts of the oled_data structure that do not change. */
|
||||
xOLEDData.line1 = FIRST_LINE;
|
||||
xOLEDData.char_offset1 = ucOffset1++;
|
||||
xOLEDData.string1 = "www.FreeRTOS.org";
|
||||
|
||||
xOLEDData.string1 = " www.FreeRTOS.org";
|
||||
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.on_off = OLED_HORIZ_SCROLL_OFF;
|
||||
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.end_page = OLED_END_PAGE;
|
||||
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
SystemCoreClockUpdate();
|
||||
|
||||
/* Disable the Watch Dog Timer */
|
||||
MSS_WD_disable( );
|
||||
|
||||
/* Configure the GPIO for the LEDs. */
|
||||
vParTestInitialise();
|
||||
|
||||
/* Initialise the display. */
|
||||
OLED_init();
|
||||
|
||||
/* Setup the GPIO and the NVIC for the switch used in this simple demo. */
|
||||
NVIC_SetPriority( GPIO8_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
NVIC_EnableIRQ( GPIO8_IRQn );
|
||||
|
@ -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.h"
|
||||
|
||||
/* The buffer used by the uIP stack to both receive and send. This points to
|
||||
one of the Ethernet buffers when its actually in use. */
|
||||
/* The buffer used by the uIP stack to both receive and send. In this case,
|
||||
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;
|
||||
|
||||
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 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 uipETHERNET_RX_EVENT 0x01UL
|
||||
#define uipETHERNET_TX_EVENT 0x02UL
|
||||
#define uipARP_TIMER_EVENT 0x04UL
|
||||
#define uipPERIODIC_TIMER_EVENT 0x08UL
|
||||
#define uipAPPLICATION_SEND_EVENT 0x10UL
|
||||
|
||||
/* A block time of zero simply means "don't block". */
|
||||
#define uipDONT_BLOCK 0UL
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* How long to wait before attempting to connect the MAC again. */
|
||||
#define uipINIT_WAIT ( 100 / portTICK_RATE_MS )
|
||||
|
||||
|
@ -122,6 +120,10 @@ static void prvInitialise_uIP( void );
|
|||
*/
|
||||
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 );
|
||||
|
||||
/*
|
||||
|
@ -129,14 +131,16 @@ static void prvUIPTimerCallback( xTimerHandle xTimer );
|
|||
*/
|
||||
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 );
|
||||
|
||||
long lEMACWaitForLink( void );
|
||||
|
||||
/*
|
||||
* Port functions required by the uIP stack.
|
||||
*/
|
||||
void clock_init( 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. */
|
||||
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 )
|
||||
|
@ -163,31 +159,24 @@ clock_time_t clock_time( void )
|
|||
void vuIP_Task( void *pvParameters )
|
||||
{
|
||||
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;
|
||||
|
||||
/* Initialise the uIP stack, configuring for web server usage. */
|
||||
prvInitialise_uIP();
|
||||
|
||||
/* Initialise the MAC. */
|
||||
/* Initialise the MAC and PHY. */
|
||||
prvInitEmac();
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL )
|
||||
{
|
||||
ulUIP_Events &= ~uipETHERNET_TX_EVENT;
|
||||
MSS_MAC_TxBufferCompleted();
|
||||
}
|
||||
|
||||
if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL )
|
||||
{
|
||||
ulUIP_Events &= ~uipETHERNET_RX_EVENT;
|
||||
|
||||
/* Is there received data ready to be processed? */
|
||||
uip_len = MSS_MAC_rx_packet();
|
||||
|
||||
/* Statements to be executed if data has been received on the Ethernet. */
|
||||
if( ( uip_len > 0 ) && ( uip_buf != NULL ) )
|
||||
{
|
||||
/* Standard uIP loop taken from the uIP manual. */
|
||||
|
@ -218,12 +207,19 @@ unsigned long ulNewEvent;
|
|||
}
|
||||
}
|
||||
}
|
||||
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 )
|
||||
{
|
||||
ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;
|
||||
|
||||
if( uip_buf != NULL )
|
||||
{
|
||||
for( i = 0; i < UIP_CONNS; i++ )
|
||||
{
|
||||
uip_periodic( i );
|
||||
|
@ -238,14 +234,17 @@ unsigned long ulNewEvent;
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
ulUIP_Events &= ~uipARP_TIMER_EVENT;
|
||||
uip_arp_timer();
|
||||
}
|
||||
|
||||
/* If all latched events have been cleared - block until another event
|
||||
occurs. */
|
||||
if( ulUIP_Events == pdFALSE )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
uip_ipaddr_t xIPAddr;
|
||||
|
@ -331,22 +287,25 @@ xTimerHandle xARPTimer, xPeriodicTimer;
|
|||
|
||||
/* 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. */
|
||||
( 500 / portTICK_RATE_MS ), /* Timer period. */
|
||||
( 10000UL / portTICK_RATE_MS ), /* Timer period. */
|
||||
pdTRUE, /* Autor-reload. */
|
||||
( void * ) uipARP_TIMER,
|
||||
prvUIPTimerCallback
|
||||
);
|
||||
|
||||
xPeriodicTimer = xTimerCreate( ( const signed char * const ) "PeriodicTimer",
|
||||
( 5000 / portTICK_RATE_MS ),
|
||||
( 500UL / portTICK_RATE_MS ),
|
||||
pdTRUE, /* Autor-reload. */
|
||||
( void * ) uipPERIODIC_TIMER,
|
||||
prvUIPTimerCallback
|
||||
);
|
||||
|
||||
/* Sanity check that the timers were indeed created. */
|
||||
configASSERT( xARPTimer );
|
||||
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( xPeriodicTimer, portMAX_DELAY );
|
||||
}
|
||||
|
@ -355,24 +314,21 @@ xTimerHandle xARPTimer, xPeriodicTimer;
|
|||
static void prvEMACEventListener( unsigned long ulISREvents )
|
||||
{
|
||||
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 );
|
||||
|
||||
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 )
|
||||
{
|
||||
/* Wake the uIP task as new data has arrived. */
|
||||
ulUIPEvents |= uipETHERNET_RX_EVENT;
|
||||
}
|
||||
|
||||
if( ulUIPEvents != 0UL )
|
||||
{
|
||||
xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );
|
||||
/* An Ethernet Rx event has occurred. */
|
||||
xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
|
||||
|
@ -383,9 +339,12 @@ static void prvInitEmac( void )
|
|||
{
|
||||
const unsigned char ucPHYAddress = 1;
|
||||
|
||||
/* Initialise the MAC and PHY hardware. */
|
||||
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. */
|
||||
NVIC_SetPriority( EthernetMAC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
@ -399,6 +358,10 @@ const long lMaxAttempts = 10;
|
|||
long lAttempt;
|
||||
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++ )
|
||||
{
|
||||
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 const unsigned long ulARPTimerExpired = uipARP_TIMER_EVENT;
|
||||
static const unsigned long ulPeriodicTimerExpired = uipPERIODIC_TIMER_EVENT;
|
||||
|
||||
/* 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 ) )
|
||||
{
|
||||
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…
Reference in a new issue