Ethernet working in the Kinetis K60 demo.
parent
9d181af847
commit
326b6a2c95
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* File: enet.c
|
||||
* Purpose: Driver for the ENET controller
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "enet.h"
|
||||
#include "nbuf.h"
|
||||
#include "eth.h"
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/* Initialize the MIB counters
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*/
|
||||
void
|
||||
enet_mib_init(int ch)
|
||||
{
|
||||
//To do
|
||||
}
|
||||
/********************************************************************/
|
||||
/* Display the MIB counters
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*/
|
||||
void
|
||||
enet_mib_dump(int ch)
|
||||
{
|
||||
//To do
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Set the duplex on the selected FEC controller
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
* duplex enet_MII_FULL_DUPLEX or enet_MII_HALF_DUPLEX
|
||||
*/
|
||||
void
|
||||
enet_duplex (int ch, ENET_DUPLEX duplex)
|
||||
{
|
||||
switch (duplex)
|
||||
{
|
||||
case MII_HDX:
|
||||
ENET_RCR/*(ch)*/ |= ENET_RCR_DRT_MASK;
|
||||
ENET_TCR/*(ch)*/ &= (uint32_t)~ENET_TCR_FDEN_MASK;
|
||||
break;
|
||||
case MII_FDX:
|
||||
default:
|
||||
ENET_RCR/*(ch)*/ &= ~ENET_RCR_DRT_MASK;
|
||||
ENET_TCR/*(ch)*/ |= ENET_TCR_FDEN_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Generate the hash table settings for the given address
|
||||
*
|
||||
* Parameters:
|
||||
* addr 48-bit (6 byte) Address to generate the hash for
|
||||
*
|
||||
* Return Value:
|
||||
* The 6 most significant bits of the 32-bit CRC result
|
||||
*/
|
||||
uint8_t
|
||||
enet_hash_address(const uint8_t* addr)
|
||||
{
|
||||
uint32_t crc;
|
||||
uint8_t byte;
|
||||
int i, j;
|
||||
|
||||
crc = 0xFFFFFFFF;
|
||||
for(i=0; i<6; ++i)
|
||||
{
|
||||
byte = addr[i];
|
||||
for(j=0; j<8; ++j)
|
||||
{
|
||||
if((byte & 0x01)^(crc & 0x01))
|
||||
{
|
||||
crc >>= 1;
|
||||
crc = crc ^ 0xEDB88320;
|
||||
}
|
||||
else
|
||||
crc >>= 1;
|
||||
byte >>= 1;
|
||||
}
|
||||
}
|
||||
return (uint8_t)(crc >> 26);
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Set the Physical (Hardware) Address and the Individual Address
|
||||
* Hash in the selected FEC
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
* pa Physical (Hardware) Address for the selected FEC
|
||||
*/
|
||||
void
|
||||
enet_set_address (int ch, const uint8_t *pa)
|
||||
{
|
||||
uint8_t crc;
|
||||
|
||||
/*
|
||||
* Set the Physical Address
|
||||
*/
|
||||
ENET_PALR/*(ch)*/ = (uint32_t)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);
|
||||
ENET_PAUR/*(ch)*/ = (uint32_t)((pa[4]<<24) | (pa[5]<<16));
|
||||
|
||||
/*
|
||||
* Calculate and set the hash for given Physical Address
|
||||
* in the Individual Address Hash registers
|
||||
*/
|
||||
crc = enet_hash_address(pa);
|
||||
if(crc >= 32)
|
||||
ENET_IAUR/*(ch)*/ |= (uint32_t)(1 << (crc - 32));
|
||||
else
|
||||
ENET_IALR/*(ch)*/ |= (uint32_t)(1 << crc);
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Reset the selected FEC controller
|
||||
*
|
||||
* Parameters:
|
||||
* ch FEC channel
|
||||
*/
|
||||
void
|
||||
enet_reset (int ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Set the Reset bit and clear the Enable bit */
|
||||
ENET_ECR/*(ch)*/ = ENET_ECR_RESET_MASK;
|
||||
|
||||
/* Wait at least 8 clock cycles */
|
||||
for (i=0; i<10; ++i)
|
||||
asm( "NOP" );
|
||||
}
|
||||
/********************************************************************/
|
||||
/*
|
||||
* Initialize the selected FEC
|
||||
*
|
||||
* Parameters:
|
||||
* config: ENET parameters
|
||||
*
|
||||
*
|
||||
*/
|
||||
void
|
||||
enet_init (ENET_CONFIG *config)
|
||||
{
|
||||
/* Clear the Individual and Group Address Hash registers */
|
||||
ENET_IALR/*(ch)*/ = 0;
|
||||
ENET_IAUR/*(ch)*/ = 0;
|
||||
ENET_GALR/*(ch)*/ = 0;
|
||||
ENET_GAUR/*(ch)*/ = 0;
|
||||
|
||||
/* Set the Physical Address for the selected FEC */
|
||||
enet_set_address(config->ch, config->mac);
|
||||
|
||||
/* Mask all FEC interrupts */
|
||||
ENET_EIMR/*(ch)*/ = 0;//FSL:ENET_EIMR_MASK_ALL_MASK;
|
||||
|
||||
/* Clear all FEC interrupt events */
|
||||
ENET_EIR/*(ch)*/ = 0xFFFFFFFF;//FSL:ENET_EIR_CLEAR_ALL_MASK;
|
||||
|
||||
/* Initialize the Receive Control Register */
|
||||
ENET_RCR/*(ch)*/ = 0
|
||||
| ENET_RCR_MAX_FL(ETH_MAX_FRM)
|
||||
| ENET_RCR_MII_MODE_MASK /*always*/
|
||||
| ENET_RCR_CRCFWD_MASK; /*no CRC pad required*/
|
||||
|
||||
if ( config->interface == mac_rmii )
|
||||
{
|
||||
ENET_RCR/*(ch)*/ |= ENET_RCR_RMII_MODE_MASK;
|
||||
|
||||
/*only set speed in RMII mode*/
|
||||
if( config->speed == MII_10BASET )
|
||||
{
|
||||
ENET_RCR/*(ch)*/ |= ENET_RCR_RMII_10T_MASK;
|
||||
}
|
||||
}/*no need to configure MAC MII interface*/
|
||||
|
||||
ENET_TCR/*(ch)*/ = 0;
|
||||
|
||||
/* Set the duplex */
|
||||
enet_duplex(config->ch, config->duplex);
|
||||
|
||||
if (config->prom)
|
||||
{
|
||||
ENET_RCR/*(ch)*/ |= ENET_RCR_PROM_MASK;
|
||||
}
|
||||
|
||||
#ifdef ENHANCED_BD
|
||||
ENET_ECR/*(ch)*/ = ENET_ECR_EN1588_MASK;
|
||||
#else
|
||||
ENET_ECR/*(ch)*/ = 0;//clear register
|
||||
#endif
|
||||
|
||||
if(config->loopback == INTERNAL_LOOPBACK)
|
||||
{
|
||||
/*seems like RMII internal loopback works, even if it's not supported*/
|
||||
ENET_RCR/*(0)*/ |= ENET_RCR_LOOP_MASK;
|
||||
}
|
||||
}
|
||||
/********************************************************************/
|
||||
void
|
||||
enet_start (int ch)
|
||||
{
|
||||
// Enable FEC
|
||||
ENET_ECR/*(ch)*/ |= ENET_ECR_ETHEREN_MASK;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
int
|
||||
enet_wait_for_frame_receive(int ch, int timeout)
|
||||
{
|
||||
int i, return_val = 1;
|
||||
|
||||
for (i=0; i < timeout; i++)
|
||||
{
|
||||
if (ENET_EIR/*(ch)*/ & ENET_EIR_RXF_MASK)
|
||||
{
|
||||
ENET_EIR/*(ch)*/ = ENET_EIR_RXF_MASK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == timeout)
|
||||
{
|
||||
return_val = 0;
|
||||
}
|
||||
return return_val;
|
||||
}
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* File: enet.h
|
||||
* Purpose: Driver for the ENET controller
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
|
||||
#ifndef _ENET_H_
|
||||
#define _ENET_H_
|
||||
|
||||
#include "nbuf.h"
|
||||
|
||||
/********INTERFACE**********/
|
||||
typedef enum {
|
||||
mac_mii,
|
||||
mac_rmii,
|
||||
} ENET_INTERFACE;
|
||||
/********AUTONEG**********/
|
||||
typedef enum {
|
||||
autoneg_on,
|
||||
autoneg_off
|
||||
} ENET_AUTONEG;
|
||||
/********SPEED**********/
|
||||
typedef enum {
|
||||
MII_10BASET,
|
||||
MII_100BASET
|
||||
} ENET_SPEED;
|
||||
/********DUPLEX**********/
|
||||
/* MII Duplex Settings */
|
||||
typedef enum {
|
||||
MII_HDX, /*!< half-duplex */
|
||||
MII_FDX /*!< full-duplex */
|
||||
} ENET_DUPLEX;
|
||||
/********LOOPBACK**********/
|
||||
typedef enum {
|
||||
INTERNAL_LOOPBACK,
|
||||
EXTERNAL_LOOPBACK,
|
||||
NO_LOOPBACK
|
||||
} ENET_LOOPBACK;
|
||||
/********EXTERNAL**********/
|
||||
typedef enum {
|
||||
EXTERNAL_NONE,
|
||||
EXTERNAL_YES
|
||||
} ENET_EXTERNAL_CONN;
|
||||
|
||||
/*
|
||||
* FEC Configuration Parameters
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ch; /* FEC channel */
|
||||
ENET_INTERFACE interface; /* Transceiver mode */
|
||||
ENET_AUTONEG neg; /* FEC autoneg */
|
||||
ENET_SPEED speed; /* Ethernet Speed */
|
||||
ENET_DUPLEX duplex; /* Ethernet Duplex */
|
||||
ENET_LOOPBACK loopback; /* Loopback Mode */
|
||||
ENET_EXTERNAL_CONN external; /* outside test? */
|
||||
uint8_t prom; /* Promiscuous Mode? */
|
||||
uint8_t mac[6]; /* Ethernet Address */
|
||||
} ENET_CONFIG;
|
||||
|
||||
void
|
||||
enet_mib_init(int);
|
||||
|
||||
void
|
||||
enet_mib_dump(int);
|
||||
|
||||
void
|
||||
enet_reg_dump(int);
|
||||
|
||||
void
|
||||
enet_duplex (int, ENET_DUPLEX);
|
||||
|
||||
uint8_t
|
||||
enet_hash_address(const uint8_t*);
|
||||
|
||||
void
|
||||
enet_set_address (int, const uint8_t*);
|
||||
|
||||
void
|
||||
enet_reset (int);
|
||||
|
||||
void
|
||||
enet_init (ENET_CONFIG *config);
|
||||
|
||||
void
|
||||
enet_start (int ch);
|
||||
|
||||
int
|
||||
enet_wait_for_frame_receive(int,int);
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
#endif /* _ENET_H_ */
|
@ -0,0 +1,58 @@
|
||||
/*!
|
||||
* \file eth.h
|
||||
* \brief Definitinos for Ethernet Frames
|
||||
* \version $Revision: 1.1 $
|
||||
* \author Michael Norman
|
||||
*/
|
||||
|
||||
#ifndef _ETH_H
|
||||
#define _ETH_H
|
||||
|
||||
/*b06862*/
|
||||
#include "common.h"
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
/* Ethernet standard lengths in bytes*/
|
||||
#define ETH_ADDR_LEN (6)
|
||||
#define ETH_TYPE_LEN (2)
|
||||
#define ETH_CRC_LEN (4)
|
||||
#define ETH_MAX_DATA (1500)
|
||||
#define ETH_MIN_DATA (46)
|
||||
#define ETH_HDR_LEN (ETH_ADDR_LEN * 2 + ETH_TYPE_LEN)
|
||||
|
||||
/* Defined Ethernet Frame Types */
|
||||
#define ETH_FRM_IP (0x0800)
|
||||
#define ETH_FRM_ARP (0x0806)
|
||||
#define ETH_FRM_RARP (0x8035)
|
||||
#define ETH_FRM_TEST (0xA5A5)
|
||||
|
||||
/* Maximum and Minimum Ethernet Frame Sizes */
|
||||
#define ETH_MAX_FRM (ETH_HDR_LEN + ETH_MAX_DATA + ETH_CRC_LEN)
|
||||
#define ETH_MIN_FRM (ETH_HDR_LEN + ETH_MIN_DATA + ETH_CRC_LEN)
|
||||
#define ETH_MTU (ETH_HDR_LEN + ETH_MAX_DATA)
|
||||
|
||||
/* Ethernet Addresses */
|
||||
typedef uint8_t ETH_ADDR[ETH_ADDR_LEN];
|
||||
|
||||
/* 16-bit Ethernet Frame Type, ie. Protocol */
|
||||
typedef uint16_t ETH_FRM_TYPE;
|
||||
|
||||
/* Ethernet Frame Header definition */
|
||||
typedef struct
|
||||
{
|
||||
ETH_ADDR dest;
|
||||
ETH_ADDR src;
|
||||
ETH_FRM_TYPE type;
|
||||
} ETH_HDR;
|
||||
|
||||
/* Ethernet Frame definition */
|
||||
typedef struct
|
||||
{
|
||||
ETH_HDR head;
|
||||
uint8_t* data;
|
||||
} ETH_FRAME;
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#endif /* _ETH_H */
|
@ -0,0 +1,413 @@
|
||||
/*!
|
||||
* \file eth_phy.c
|
||||
* \brief Ethernet Physical Layer Interface Driver
|
||||
* \version $Revision: 1.3 $
|
||||
* \author Michael Norman
|
||||
*
|
||||
* This is a generic driver for all Ethernet PHYs with the basic MII registers
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "eth_phy.h"
|
||||
#include "mii.h"
|
||||
|
||||
/* Variable to save off auto-negotiate settings */
|
||||
int eth_phy_anar = 0
|
||||
| PHY_ANAR_100BTX_FDX
|
||||
| PHY_ANAR_100BTX
|
||||
| PHY_ANAR_10BT_FDX
|
||||
| PHY_ANAR_10BT;
|
||||
|
||||
int
|
||||
eth_phy_reset(int ch, int phy_addr)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings;
|
||||
|
||||
/* Reset the PHY */
|
||||
if (mii_write(ch, phy_addr, PHY_BMCR, PHY_BMCR_RESET))
|
||||
return 1;
|
||||
/* Wait for reset to complete */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_LINK_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
/* Read back the contents of the CTRL register and verify
|
||||
* that RESET is not set - this is a sanity check to ensure
|
||||
* that we are talking to the PHY correctly. RESET should
|
||||
* always be cleared. */
|
||||
if (!(mii_read(ch, phy_addr, PHY_BMCR, &settings)) && !(settings & PHY_BMCR_RESET))
|
||||
break;/*FSL: ready*/
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_LINK_TIMEOUT || (settings & PHY_BMCR_RESET))
|
||||
return 1;
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Enable the Ethernet PHY in auto-negotiate mode
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param speed Desired speed (MII_10BASE_T or MII_100BASE_TX)
|
||||
* \param duplex Desired duplex (MII_FDX or MII_HDX)
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_autoneg(int ch, int phy_addr, ENET_SPEED speed, ENET_DUPLEX duplex)
|
||||
{
|
||||
int timeout, settings;
|
||||
|
||||
/* Reset the PHY */
|
||||
eth_phy_reset(ch, phy_addr);
|
||||
|
||||
/* Set the Auto-Negotiation Advertisement Register */
|
||||
if (speed == MII_10BASET)
|
||||
{
|
||||
settings = (duplex == MII_FDX)
|
||||
? PHY_ANAR_10BT_FDX | PHY_ANAR_10BT
|
||||
: PHY_ANAR_10BT;
|
||||
}
|
||||
else /* (speed == MII_100BASET) */
|
||||
{
|
||||
settings = (duplex == MII_FDX)
|
||||
? PHY_ANAR_100BTX_FDX |
|
||||
PHY_ANAR_100BTX |
|
||||
PHY_ANAR_10BT_FDX |
|
||||
PHY_ANAR_10BT
|
||||
: PHY_ANAR_10BT_FDX |
|
||||
PHY_ANAR_10BT;
|
||||
}
|
||||
|
||||
/* Save off the settings we just advertised */
|
||||
eth_phy_anar = settings;
|
||||
|
||||
if (mii_write(ch, phy_addr, PHY_ANAR, settings))
|
||||
return 1;
|
||||
|
||||
/* Enable Auto-Negotiation */
|
||||
if (mii_write(ch, phy_addr, PHY_BMCR, PHY_BMCR_AN_ENABLE | PHY_BMCR_AN_RESTART))
|
||||
return 1;
|
||||
|
||||
/* Wait for auto-negotiation to complete */
|
||||
for (timeout = 0; timeout < MII_LINK_TIMEOUT; ++timeout)
|
||||
{
|
||||
if (mii_read(ch, phy_addr, PHY_BMSR, &settings))
|
||||
return 1;
|
||||
if (settings & PHY_BMSR_AN_COMPLETE)
|
||||
break;
|
||||
}
|
||||
/* Read the BMSR one last time */
|
||||
if (mii_read(ch, phy_addr, PHY_BMSR, &settings))
|
||||
return 1;
|
||||
if (timeout == MII_LINK_TIMEOUT || !(settings & PHY_BMSR_LINK))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Enable the Ethernet PHY in manual mode
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param speed Desired speed (MII_10BASE_T or MII_100BASE_TX)
|
||||
* \param duplex Desired duplex (MII_FDX or MII_HDX)
|
||||
* \param loop Put PHY in loopback mode?
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_manual(int ch, int phy_addr, ENET_SPEED speed, ENET_DUPLEX duplex, int loop)
|
||||
{
|
||||
int timeout;
|
||||
int settings = 0;
|
||||
|
||||
/* Reset the PHY */
|
||||
/* Reset the PHY */
|
||||
eth_phy_reset(ch, phy_addr);
|
||||
|
||||
if (loop)
|
||||
settings |= PHY_BMCR_LOOP;
|
||||
if (duplex == MII_FDX)
|
||||
settings |= PHY_BMCR_FDX;
|
||||
if (speed == MII_100BASET)
|
||||
settings |= PHY_BMCR_SPEED;
|
||||
|
||||
if (mii_write(ch, phy_addr, PHY_BMCR, settings))
|
||||
return 1;
|
||||
|
||||
/* Wait for link */
|
||||
for (timeout = 0; timeout < MII_LINK_TIMEOUT; ++timeout)
|
||||
{
|
||||
if (mii_read(ch, phy_addr, PHY_BMSR, &settings))
|
||||
return 1;
|
||||
if (settings & PHY_BMSR_LINK)
|
||||
break;
|
||||
}
|
||||
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_LINK_TIMEOUT || !(settings & PHY_BMSR_LINK))
|
||||
return 1;
|
||||
else
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Get the auto-negotiated speed
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param speed Pointer where speed data is stored
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_get_speed(int ch, int phy_addr, int *speed)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings = 0;
|
||||
|
||||
/* Get Link Partner settings */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
if (mii_read(ch, phy_addr, PHY_ANLPAR, &settings))
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
settings &= eth_phy_anar;
|
||||
if (settings & PHY_ANLPAR_100BT4 ||
|
||||
settings & PHY_ANLPAR_100BTX_FDX ||
|
||||
settings & PHY_ANLPAR_100BTX)
|
||||
*speed = MII_100BASET;
|
||||
else
|
||||
*speed = MII_10BASET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Get the auto-negotiated duplex
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param speed Pointer where speed data is stored
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_get_duplex(int ch, int phy_addr, int *speed)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings = 0;
|
||||
|
||||
/* Get Link Partner settings */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
if (mii_read(ch, phy_addr, PHY_ANLPAR, &settings))
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
settings &= eth_phy_anar;
|
||||
if (settings & PHY_ANLPAR_100BTX_FDX ||
|
||||
settings & PHY_ANLPAR_10BTX_FDX)
|
||||
*speed = MII_FDX;
|
||||
else
|
||||
*speed = MII_HDX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Get the manual speed
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param speed Pointer where speed data is stored
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_get_manual_speed(int ch, int phy_addr, int *speed)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings = 0;
|
||||
|
||||
/* Get Link Partner settings */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
#ifdef TWR_K60N512
|
||||
if (mii_read(ch, phy_addr, PHY_PHYCTRL2, &settings))//Micrel
|
||||
#else
|
||||
if (mii_read(ch, phy_addr, PHY_PHYSTS, &settings))//National Semiconductors
|
||||
#endif
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef TWR_K60N512
|
||||
/*FSL: obtain speed/duplex*/
|
||||
settings = (settings & PHY_PHYCTRL2_OP_MOD_MASK)>>PHY_PHYCTRL2_OP_MOD_SHIFT;
|
||||
|
||||
if (settings == PHY_PHYCTRL2_MODE_OP_MOD_10MBPS_HD ||
|
||||
settings == PHY_PHYCTRL2_MODE_OP_MOD_10MBPS_FD)
|
||||
*speed = MII_10BASET;
|
||||
else
|
||||
*speed = MII_100BASET;
|
||||
#else
|
||||
if (settings & PHY_PHYSTS_SPEEDSTATUS)
|
||||
*speed = MII_10BASET;
|
||||
else
|
||||
*speed = MII_100BASET;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Get the manual duplex
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param duplex Pointer where duplex data is stored
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_get_manual_duplex(int ch, int phy_addr, int *duplex)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings = 0;
|
||||
|
||||
/* Get Link Partner settings */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
#ifdef TWR_K60N512
|
||||
if (mii_read(ch, phy_addr, PHY_PHYCTRL2, &settings))//Micrel
|
||||
#else
|
||||
if (mii_read(ch, phy_addr, PHY_PHYSTS, &settings))//National Semiconductors
|
||||
#endif
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef TWR_K60N512
|
||||
/*FSL: obtain speed/duplex*/
|
||||
settings = (settings & PHY_PHYCTRL2_OP_MOD_MASK)>>PHY_PHYCTRL2_OP_MOD_SHIFT;
|
||||
|
||||
if (settings == PHY_PHYCTRL2_MODE_OP_MOD_10MBPS_HD ||
|
||||
settings == PHY_PHYCTRL2_MODE_OP_MOD_100MBPS_HD)
|
||||
*duplex = MII_HDX;
|
||||
else
|
||||
*duplex = MII_FDX;
|
||||
#else
|
||||
if (settings & PHY_PHYSTS_DUPLEXSTATUS)
|
||||
*duplex = MII_FDX;
|
||||
else
|
||||
*duplex = MII_HDX;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Get the manual speed
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param loop set if loopback is needed
|
||||
* \return 0 if successful; non-zero otherwise
|
||||
*/
|
||||
int
|
||||
eth_phy_set_remote_loopback(int ch, int phy_addr, int loop)
|
||||
{
|
||||
#if MII_CHECK_TIMEOUT
|
||||
int timeout;
|
||||
#endif
|
||||
int settings = 0;
|
||||
|
||||
/* Get Link Partner settings */
|
||||
#if MII_CHECK_TIMEOUT
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; ++timeout)
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
if (mii_read(ch, phy_addr, PHY_PHYCTRL1, &settings))
|
||||
return 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if MII_CHECK_TIMEOUT
|
||||
if (timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
#endif
|
||||
/*set remote loopback flag*/
|
||||
if(loop)
|
||||
settings |= PHY_PHYCTRL1_REMOTE_LOOP; /*set bit*/
|
||||
else
|
||||
settings &= ~PHY_PHYCTRL1_REMOTE_LOOP; /*clear bit*/
|
||||
|
||||
if (mii_write(ch, phy_addr, PHY_PHYCTRL1, settings))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Print all the MII registers (0x00-0x1F)
|
||||
* \param phy_addr Address of the PHY
|
||||
*/
|
||||
int
|
||||
eth_phy_reg_dump(int ch, int phy_addr)
|
||||
{
|
||||
int j, settings;
|
||||
|
||||
printf("\n MII Register Block\n");
|
||||
printf("--------------------------------");
|
||||
for (j = 0; j < 32; j++)
|
||||
{
|
||||
mii_read(ch, phy_addr, j, &settings);
|
||||
if (!(j % 4))
|
||||
printf("\n0x%02X-0x%02X : %04X ", j, j + 3, settings);
|
||||
else
|
||||
printf("%04X ", settings);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*!
|
||||
* \file eth.h
|
||||
* \brief Definitions for Ethernet Physical Layer Interface
|
||||
* \version $Revision: 1.3 $
|
||||
* \author Michael Norman
|
||||
* \modif b06862
|
||||
*/
|
||||
|
||||
#ifndef _ETH_PHY_H
|
||||
#define _ETH_PHY_H
|
||||
|
||||
|
||||
#include "enet.h"
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
int
|
||||
eth_phy_reset(int ch, int phy_addr);
|
||||
|
||||
int
|
||||
eth_phy_autoneg(int ch, int phy_addr, ENET_SPEED speed, ENET_DUPLEX duplex);
|
||||
|
||||
int
|
||||
eth_phy_manual(int ch, int phy_addr, ENET_SPEED speed, ENET_DUPLEX duplex, int loop);
|
||||
|
||||
int
|
||||
eth_phy_get_speed(int, int, int*);
|
||||
|
||||
int
|
||||
eth_phy_get_duplex(int, int, int*);
|
||||
|
||||
int
|
||||
eth_phy_get_manual_speed(int, int, int*);
|
||||
|
||||
int
|
||||
eth_phy_get_manual_duplex(int, int, int*);
|
||||
|
||||
int
|
||||
eth_phy_set_remote_loopback(int, int, int);
|
||||
|
||||
int
|
||||
eth_phy_reg_dump(int, int);
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
/* MII Register Addresses */
|
||||
#define PHY_BMCR (0x00)
|
||||
#define PHY_BMSR (0x01)
|
||||
#define PHY_PHYIDR1 (0x02)
|
||||
#define PHY_PHYIDR2 (0x03)
|
||||
#define PHY_ANAR (0x04)
|
||||
#define PHY_ANLPAR (0x05)
|
||||
#define PHY_ANLPARNP (0x05)
|
||||
#define PHY_ANER (0x06)
|
||||
#define PHY_ANNPTR (0x07)
|
||||
#define PHY_PHYSTS (0x10)
|
||||
#define PHY_MICR (0x11)
|
||||
#define PHY_MISR (0x12)
|
||||
#define PHY_PAGESEL (0x13)
|
||||
|
||||
/*TSI-EVB definition: National Semiconductor*/
|
||||
#define PHY_PHYCR2 (0x1C)
|
||||
|
||||
/*TWR definition: Micrel*/
|
||||
#define PHY_PHYCTRL1 (0x1E)
|
||||
#define PHY_PHYCTRL2 (0x1F)
|
||||
|
||||
/* Bit definitions and macros for PHY_BMCR */
|
||||
#define PHY_BMCR_RESET (0x8000)
|
||||
#define PHY_BMCR_LOOP (0x4000)
|
||||
#define PHY_BMCR_SPEED (0x2000)
|
||||
#define PHY_BMCR_AN_ENABLE (0x1000)
|
||||
#define PHY_BMCR_POWERDOWN (0x0800)
|
||||
#define PHY_BMCR_ISOLATE (0x0400)
|
||||
#define PHY_BMCR_AN_RESTART (0x0200)
|
||||
#define PHY_BMCR_FDX (0x0100)
|
||||
#define PHY_BMCR_COL_TEST (0x0080)
|
||||
|
||||
/* Bit definitions and macros for PHY_BMSR */
|
||||
#define PHY_BMSR_100BT4 (0x8000)
|
||||
#define PHY_BMSR_100BTX_FDX (0x4000)
|
||||
#define PHY_BMSR_100BTX (0x2000)
|
||||
#define PHY_BMSR_10BT_FDX (0x1000)
|
||||
#define PHY_BMSR_10BT (0x0800)
|
||||
#define PHY_BMSR_NO_PREAMBLE (0x0040)
|
||||
#define PHY_BMSR_AN_COMPLETE (0x0020)
|
||||
#define PHY_BMSR_REMOTE_FAULT (0x0010)
|
||||
#define PHY_BMSR_AN_ABILITY (0x0008)
|
||||
#define PHY_BMSR_LINK (0x0004)
|
||||
#define PHY_BMSR_JABBER (0x0002)
|
||||
#define PHY_BMSR_EXTENDED (0x0001)
|
||||
|
||||
/* Bit definitions and macros for PHY_ANAR */
|
||||
#define PHY_ANAR_NEXT_PAGE (0x8001)
|
||||
#define PHY_ANAR_REM_FAULT (0x2001)
|
||||
#define PHY_ANAR_PAUSE (0x0401)
|
||||
#define PHY_ANAR_100BT4 (0x0201)
|
||||
#define PHY_ANAR_100BTX_FDX (0x0101)
|
||||
#define PHY_ANAR_100BTX (0x0081)
|
||||
#define PHY_ANAR_10BT_FDX (0x0041)
|
||||
#define PHY_ANAR_10BT (0x0021)
|
||||
#define PHY_ANAR_802_3 (0x0001)
|
||||
|
||||
/* Bit definitions and macros for PHY_ANLPAR */
|
||||
#define PHY_ANLPAR_NEXT_PAGE (0x8000)
|
||||
#define PHY_ANLPAR_ACK (0x4000)
|
||||
#define PHY_ANLPAR_REM_FAULT (0x2000)
|
||||
#define PHY_ANLPAR_PAUSE (0x0400)
|
||||
#define PHY_ANLPAR_100BT4 (0x0200)
|
||||
#define PHY_ANLPAR_100BTX_FDX (0x0100)
|
||||
#define PHY_ANLPAR_100BTX (0x0080)
|
||||
#define PHY_ANLPAR_10BTX_FDX (0x0040)
|
||||
#define PHY_ANLPAR_10BT (0x0020)
|
||||
|
||||
|
||||
/* Bit definitions of PHY_PHYSTS: National */
|
||||
#define PHY_PHYSTS_MDIXMODE (0x4000)
|
||||
#define PHY_PHYSTS_RX_ERR_LATCH (0x2000)
|
||||
#define PHY_PHYSTS_POL_STATUS (0x1000)
|
||||
#define PHY_PHYSTS_FALSECARRSENSLAT (0x0800)
|
||||
#define PHY_PHYSTS_SIGNALDETECT (0x0400)
|
||||
#define PHY_PHYSTS_PAGERECEIVED (0x0100)
|
||||
#define PHY_PHYSTS_MIIINTERRUPT (0x0080)
|
||||
#define PHY_PHYSTS_REMOTEFAULT (0x0040)
|
||||
#define PHY_PHYSTS_JABBERDETECT (0x0020)
|
||||
#define PHY_PHYSTS_AUTONEGCOMPLETE (0x0010)
|
||||
#define PHY_PHYSTS_LOOPBACKSTATUS (0x0008)
|
||||
#define PHY_PHYSTS_DUPLEXSTATUS (0x0004)
|
||||
#define PHY_PHYSTS_SPEEDSTATUS (0x0002)
|
||||
#define PHY_PHYSTS_LINKSTATUS (0x0001)
|
||||
|
||||
|
||||
/* Bit definitions of PHY_PHYCR2 */
|
||||
#define PHY_PHYCR2_SYNC_ENET_EN (0x2000)
|
||||
#define PHY_PHYCR2_CLK_OUT_RXCLK (0x1000)
|
||||
#define PHY_PHYCR2_BC_WRITE (0x0800)
|
||||
#define PHY_PHYCR2_PHYTER_COMP (0x0400)
|
||||
#define PHY_PHYCR2_SOFT_RESET (0x0200)
|
||||
#define PHY_PHYCR2_CLK_OUT_DIS (0x0001)
|
||||
|
||||
/* Bit definition and macros for PHY_PHYCTRL1 */
|
||||
#define PHY_PHYCTRL1_LED_MASK (0xC000)
|
||||
#define PHY_PHYCTRL1_POLARITY (0x2000)
|
||||
#define PHY_PHYCTRL1_MDX_STATE (0x0800)
|
||||
#define PHY_PHYCTRL1_REMOTE_LOOP (0x0080)
|
||||
|
||||
/* Bit definition and macros for PHY_PHYCTRL2 */
|
||||
#define PHY_PHYCTRL2_HP_MDIX (0x8000)
|
||||
#define PHY_PHYCTRL2_MDIX_SELECT (0x4000)
|
||||
#define PHY_PHYCTRL2_PAIRSWAP_DIS (0x2000)
|
||||
#define PHY_PHYCTRL2_ENERGY_DET (0x1000)
|
||||
#define PHY_PHYCTRL2_FORCE_LINK (0x0800)
|
||||
#define PHY_PHYCTRL2_POWER_SAVING (0x0400)
|
||||
#define PHY_PHYCTRL2_INT_LEVEL (0x0200)
|
||||
#define PHY_PHYCTRL2_EN_JABBER (0x0100)
|
||||
#define PHY_PHYCTRL2_AUTONEG_CMPLT (0x0080)
|
||||
#define PHY_PHYCTRL2_ENABLE_PAUSE (0x0040)
|
||||
#define PHY_PHYCTRL2_PHY_ISOLATE (0x0020)
|
||||
#define PHY_PHYCTRL2_OP_MOD_MASK (0x001C)
|
||||
#define PHY_PHYCTRL2_EN_SQE_TEST (0x0002)
|
||||
#define PHY_PHYCTRL2_DATA_SCRAM_DIS (0x0001)
|
||||
|
||||
|
||||
/* Bit definitions of PHY_PHYCTRL2_OP_MOD_MASK */
|
||||
#define PHY_PHYCTRL2_OP_MOD_SHIFT 2
|
||||
#define PHY_PHYCTRL2_MODE_OP_MOD_STILL_NEG 0
|
||||
#define PHY_PHYCTRL2_MODE_OP_MOD_10MBPS_HD 1
|
||||
#define PHY_PHYCTRL2_MODE_OP_MOD_100MBPS_HD 2
|
||||
#define PHY_PHYCTRL2_MODE_OP_MOD_10MBPS_FD 5
|
||||
#define PHY_PHYCTRL2_MODE_OP_MOD_100MBPS_FD 6
|
||||
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#endif /* _ETH_PHY_H */
|
@ -0,0 +1,130 @@
|
||||
/*!
|
||||
* \file mii.c
|
||||
* \brief Media Independent Interface (MII) driver
|
||||
* \version $Revision: 1.2 $
|
||||
* \author Michael Norman
|
||||
*
|
||||
* \warning This driver assumes that FEC0 is used for all MII management
|
||||
* communications. For dual PHYs, etc. Insure that FEC0_MDC and
|
||||
* FEC0_MDIO are connected to the PHY's MDC and MDIO.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "mii.h"
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* \brief Initialize the MII interface controller
|
||||
* \param System Clock Frequency (in MHz)
|
||||
* \warning The system clock in this case is the clock that drives
|
||||
* the FEC logic. This may be different from the speed at which
|
||||
* the CPU is operating.
|
||||
*
|
||||
* Initialize the MII clock (EMDC) frequency. The desired MII clock is 2.5MHz:
|
||||
*
|
||||
* MII Speed Setting = System_Clock / (2.5MHz * 2)
|
||||
* (plus 1 to round up)
|
||||
*/
|
||||
void
|
||||
mii_init(int ch, int sys_clk_mhz)
|
||||
{
|
||||
ENET_MSCR/*(ch)*/ = 0
|
||||
#ifdef TSIEVB/*TSI EVB requires a longer hold time than default 10 ns*/
|
||||
| ENET_MSCR_HOLDTIME(2)
|
||||
#endif
|
||||
| ENET_MSCR_MII_SPEED((2*sys_clk_mhz/5)+1)
|
||||
;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Write a value to a PHY's MII register.
|
||||
*
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param reg_addr Address of the register in the PHY
|
||||
* \param data Data to be written to the PHY register
|
||||
* \return 0 if write is successful; 1 if write times out
|
||||
*
|
||||
* mii_write() polls for the FEC's MII interrupt event (which should
|
||||
* be masked from the interrupt handler) and clears it. If after a
|
||||
* suitable amount of time the event isn't triggered, a non-zero value
|
||||
* is returned.
|
||||
*/
|
||||
int
|
||||
mii_write(int ch, int phy_addr, int reg_addr, int data)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/* Clear the MII interrupt bit */
|
||||
ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK;
|
||||
|
||||
/* Initiatate the MII Management write */
|
||||
ENET_MMFR/*(ch)*/ = 0
|
||||
| ENET_MMFR_ST(0x01)
|
||||
| ENET_MMFR_OP(0x01)
|
||||
| ENET_MMFR_PA(phy_addr)
|
||||
| ENET_MMFR_RA(reg_addr)
|
||||
| ENET_MMFR_TA(0x02)
|
||||
| ENET_MMFR_DATA(data);
|
||||
|
||||
/* Poll for the MII interrupt (interrupt should be masked) */
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; timeout++)
|
||||
{
|
||||
if (ENET_EIR/*(ch)*/ & ENET_EIR_MII_MASK)
|
||||
break;
|
||||
}
|
||||
|
||||
if(timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
|
||||
/* Clear the MII interrupt bit */
|
||||
ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
||||
/*!
|
||||
* \brief Read a value from a PHY's MII register.
|
||||
* \param phy_addr Address of the PHY
|
||||
* \param reg_addr Address of the register in the PHY
|
||||
* \param data Pointer to location were read data will be stored
|
||||
* \return 0 if write is successful; 1 if write times out
|
||||
*
|
||||
* mii_read() polls for the FEC's MII interrupt event (which should
|
||||
* be masked from the interrupt handler) and clears it. If after a
|
||||
* suitable amount of time the event isn't triggered, a non-zero value
|
||||
* is returned.
|
||||
*/
|
||||
int
|
||||
mii_read(int ch, int phy_addr, int reg_addr, int *data)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/* Clear the MII interrupt bit */
|
||||
ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK;
|
||||
|
||||
/* Initiatate the MII Management read */
|
||||
ENET_MMFR/*(ch)*/ = 0
|
||||
| ENET_MMFR_ST(0x01)
|
||||
| ENET_MMFR_OP(0x2)
|
||||
| ENET_MMFR_PA(phy_addr)
|
||||
| ENET_MMFR_RA(reg_addr)
|
||||
| ENET_MMFR_TA(0x02);
|
||||
|
||||
/* Poll for the MII interrupt (interrupt should be masked) */
|
||||
for (timeout = 0; timeout < MII_TIMEOUT; timeout++)
|
||||
{
|
||||
if (ENET_EIR/*(ch)*/ & ENET_EIR_MII_MASK)
|
||||
break;
|
||||
}
|
||||
|
||||
if(timeout == MII_TIMEOUT)
|
||||
return 1;
|
||||
|
||||
/* Clear the MII interrupt bit */
|
||||
ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK;
|
||||
|
||||
*data = ENET_MMFR/*(ch)*/ & 0x0000FFFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/********************************************************************/
|
@ -0,0 +1,30 @@
|
||||
/*!
|
||||
* \file mii.h
|
||||
* \brief Media Independent Interface (MII) driver
|
||||
* \version $Revision: 1.2 $
|
||||
* \author Michael Norman
|
||||
*
|
||||
* \warning
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MII_H_
|
||||
#define _MII_H_
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#define MII_TIMEOUT 0x1FFFF
|
||||
#define MII_LINK_TIMEOUT 0x1FFFF
|
||||
|
||||
void
|
||||
mii_init(int, int);
|
||||
|
||||
int
|
||||
mii_write(int, int, int, int);
|
||||
|
||||
int
|
||||
mii_read(int, int, int, int*);
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
#endif /* _MII_H_ */
|
@ -0,0 +1,233 @@
|
||||
// ----------------------------------------------------------------------
|
||||
// File: nbuf.h
|
||||
// Purpose: Definitions for Network Buffer Allocation.
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#ifndef _NBUF_H_
|
||||
#define _NBUF_H_
|
||||
|
||||
// Define number of MACs
|
||||
#define NUM_CHANNELS 1/*b06862*/
|
||||
|
||||
// Choose Enhanced Buffer Descriptor or Legacy
|
||||
#define ENHANCED_BD
|
||||
|
||||
//b06862: define Endianess for Little Endian architectures like ARM.
|
||||
//Motorola/Freescale uses Big Endian or Register-Endianess
|
||||
#define NBUF_LITTLE_ENDIAN
|
||||
|
||||
// Transmit packet directly or copy to dedicated buffers. If packets
|
||||
// are not alligned dedicated Tx buffers can be used
|
||||
//#define USE_DEDICATED_TX_BUFFERS
|
||||
|
||||
// Buffer sizes in bytes (must be divisible by 16)
|
||||
#define RX_BUFFER_SIZE 256
|
||||
#define TX_BUFFER_SIZE 256
|
||||
|
||||
// Number of Receive and Transmit Buffers and Buffer Descriptors
|
||||
#define NUM_RXBDS 20//10
|
||||
#define NUM_TXBDS 20//10
|
||||
|
||||
// Buffer Descriptor Format
|
||||
#ifdef ENHANCED_BD
|
||||
typedef struct
|
||||
{
|
||||
uint16_t status; /* control and status */
|
||||
uint16_t length; /* transfer length */
|
||||
uint8_t *data; /* buffer address */
|
||||
uint32_t ebd_status;
|
||||
uint16_t length_proto_type;
|
||||
uint16_t payload_checksum;
|
||||
uint32_t bdu;
|
||||
uint32_t timestamp;
|
||||
uint32_t reserverd_word1;
|
||||
uint32_t reserverd_word2;
|
||||
} NBUF;
|
||||
#else
|
||||
typedef struct
|
||||
{
|
||||
uint16_t status; /* control and status */
|
||||
uint16_t length; /* transfer length */
|
||||
uint8_t *data; /* buffer address */
|
||||
} NBUF;
|
||||
#endif /* ENHANCED_BD */
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Function Declarations
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
nbuf_alloc(int ch);
|
||||
|
||||
void
|
||||
nbuf_init(int);
|
||||
|
||||
void
|
||||
nbuf_start_rx(int);
|
||||
|
||||
void
|
||||
nbuf_flush(int);
|
||||
|
||||
//NM - return value
|
||||
void
|
||||
enet_get_received_packet(int, NBUF *);
|
||||
|
||||
//NM - return value
|
||||
void
|
||||
enet_fill_txbds(int, NBUF *);
|
||||
|
||||
void
|
||||
enet_transmit_packet(int,NBUF *);
|
||||
|
||||
#ifdef NBUF_LITTLE_ENDIAN
|
||||
|
||||
//For Freescale ARM Architecture
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// TX Buffer Descriptor Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define TX_BD_R 0x0080
|
||||
#define TX_BD_TO1 0x0040
|
||||
#define TX_BD_W 0x0020
|
||||
#define TX_BD_TO2 0x0010
|
||||
#define TX_BD_L 0x0008
|
||||
#define TX_BD_TC 0x0004
|
||||
#define TX_BD_ABC 0x0002
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// TX Enhanced BD Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define TX_BD_INT 0x00000040
|
||||
#define TX_BD_TS 0x00000020
|
||||
#define TX_BD_PINS 0x00000010
|
||||
#define TX_BD_IINS 0x00000008
|
||||
#define TX_BD_TXE 0x00800000
|
||||
#define TX_BD_UE 0x00200000
|
||||
#define TX_BD_EE 0x00100000
|
||||
#define TX_BD_FE 0x00080000
|
||||
#define TX_BD_LCE 0x00040000
|
||||
#define TX_BD_OE 0x00020000
|
||||
#define TX_BD_TSE 0x00010000
|
||||
|
||||
#define TX_BD_BDU 0x00000080
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// RX Buffer Descriptor Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Offset 0 flags - status: Big Endian
|
||||
#define RX_BD_E 0x0080
|
||||
#define RX_BD_R01 0x0040
|
||||
#define RX_BD_W 0x0020
|
||||
#define RX_BD_R02 0x0010
|
||||
#define RX_BD_L 0x0008
|
||||
#define RX_BD_M 0x0001
|
||||
#define RX_BD_BC 0x8000
|
||||
#define RX_BD_MC 0x4000
|
||||
#define RX_BD_LG 0x2000
|
||||
#define RX_BD_NO 0x1000
|
||||
#define RX_BD_CR 0x0400
|
||||
#define RX_BD_OV 0x0200
|
||||
#define RX_BD_TR 0x0100
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// RX Enhanced BD Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define RX_BD_ME 0x00000080
|
||||
#define RX_BD_PE 0x00000004
|
||||
#define RX_BD_CE 0x00000002
|
||||
#define RX_BD_UC 0x00000001
|
||||
|
||||
#define RX_BD_INT 0x00008000
|
||||
|
||||
#define RX_BD_ICE 0x20000000
|
||||
#define RX_BD_PCR 0x10000000
|
||||
#define RX_BD_VLAN 0x04000000
|
||||
#define RX_BD_IPV6 0x02000000
|
||||
#define RX_BD_FRAG 0x01000000
|
||||
|
||||
#define RX_BD_BDU 0x00000080
|
||||
|
||||
#else
|
||||
|
||||
//For Freescale ColdFire Architecture
|
||||
// ----------------------------------------------------------------------
|
||||
// TX Buffer Descriptor Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define TX_BD_R 0x8000
|
||||
#define TX_BD_TO1 0x4000
|
||||
#define TX_BD_W 0x2000
|
||||
#define TX_BD_TO2 0x1000
|
||||
#define TX_BD_L 0x0800
|
||||
#define TX_BD_TC 0x0400
|
||||
#define TX_BD_ABC 0x0200
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// TX Enhanced BD Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define TX_BD_INT 0x40000000
|
||||
#define TX_BD_TS 0x20000000
|
||||
#define TX_BD_PINS 0x10000000
|
||||
#define TX_BD_IINS 0x08000000
|
||||
#define TX_BD_TXE 0x00008000
|
||||
#define TX_BD_UE 0x00002000
|
||||
#define TX_BD_EE 0x00001000
|
||||
#define TX_BD_FE 0x00000800
|
||||
#define TX_BD_LCE 0x00000400
|
||||
#define TX_BD_OE 0x00000200
|
||||
#define TX_BD_TSE 0x00000100
|
||||
|
||||
#define TX_BD_BDU 0x80000000
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// RX Buffer Descriptor Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Offset 0 flags - status
|
||||
#define RX_BD_E 0x8000
|
||||
#define RX_BD_R01 0x4000
|
||||
#define RX_BD_W 0x2000
|
||||
#define RX_BD_R02 0x1000
|
||||
#define RX_BD_L 0x0800
|
||||
#define RX_BD_M 0x0100
|
||||
#define RX_BD_BC 0x0080
|
||||
#define RX_BD_MC 0x0040
|
||||
#define RX_BD_LG 0x0020
|
||||
#define RX_BD_NO 0x0010
|
||||
#define RX_BD_CR 0x0004
|
||||
#define RX_BD_OV 0x0002
|
||||
#define RX_BD_TR 0x0001
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// RX Enhanced BD Bit Definitions
|
||||
// ----------------------------------------------------------------------
|
||||
#define RX_BD_ME 0x80000000
|
||||
#define RX_BD_PE 0x04000000
|
||||
#define RX_BD_CE 0x02000000
|
||||
#define RX_BD_UC 0x01000000
|
||||
#define RX_BD_INT 0x00800000
|
||||
#define RX_BD_ICE 0x00000020
|
||||
#define RX_BD_PCR 0x00000010
|
||||
#define RX_BD_VLAN 0x00000004
|
||||
#define RX_BD_IPV6 0x00000002
|
||||
#define RX_BD_FRAG 0x00000001
|
||||
|
||||
#define RX_BD_BDU 0x80000000
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Defines for word offsets of various fields of RX Enhanced BDs
|
||||
// ----------------------------------------------------------------------
|
||||
//#define RX_EBD_HEADER_LENGTH_OFFSET 12
|
||||
//#define RX_EBD_PROTOCOL_TYPE_OFFSET 12
|
||||
//#define RX_EBD_PAYLOAD_CHKSM_OFFSET 14
|
||||
//#define RX_EBD_BDU_OFFSET 16
|
||||
//#define RX_EBD_TIMESTAMP_MSB_OFFSET 20
|
||||
//#define RX_EBD_TIMESTAMP_LSB_OFFSET 22
|
||||
|
||||
|
||||
#endif /* _NBUF_H_ */
|
@ -0,0 +1,354 @@
|
||||
/*
|
||||
FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* 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! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* 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 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
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <string.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* uip includes. */
|
||||
#include "net/uip.h"
|
||||
#include "net/uip_arp.h"
|
||||
#include "apps/httpd/httpd.h"
|
||||
#include "sys/timer.h"
|
||||
#include "net/clock-arch.h"
|
||||
#include "emac.h"
|
||||
|
||||
/* Demo includes. */
|
||||
#include "ParTest.h"
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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 )
|
||||
|
||||
/* Shortcut to the header within the Rx buffer. */
|
||||
#define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ])
|
||||
|
||||
/* Standard constant. */
|
||||
#define uipTOTAL_FRAME_HEADER_SIZE 54
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the MAC address in the MAC itself, and in the uIP stack.
|
||||
*/
|
||||
static void prvSetMACAddress( void );
|
||||
|
||||
/*
|
||||
* Perform any uIP initialisation required to ready the stack for http
|
||||
* processing.
|
||||
*/
|
||||
static void prvInitialise_uIP( void );
|
||||
|
||||
/*
|
||||
* The callback function that is assigned to both the periodic timer and the
|
||||
* ARP timer.
|
||||
*/
|
||||
static void prvUIPTimerCallback( xTimerHandle xTimer );
|
||||
|
||||
/*
|
||||
* Port functions required by the uIP stack.
|
||||
*/
|
||||
clock_time_t clock_time( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The queue used to send TCP/IP events to the uIP stack. */
|
||||
xQueueHandle xEMACEventQueue = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
clock_time_t clock_time( void )
|
||||
{
|
||||
return xTaskGetTickCount();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vuIP_Task( void *pvParameters )
|
||||
{
|
||||
portBASE_TYPE i;
|
||||
unsigned long ulNewEvent = 0UL, ulUIP_Events = 0UL;
|
||||
unsigned short usPacketLength;
|
||||
|
||||
/* 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 and PHY. */
|
||||
vEMACInit();
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Is there received data ready to be processed? */
|
||||
usPacketLength = usEMACRead();
|
||||
|
||||
/* Statements to be executed if data has been received on the Ethernet. */
|
||||
if( ( usPacketLength > 0U ) && ( uip_buf != NULL ) )
|
||||
{
|
||||
uip_len = usPacketLength;
|
||||
|
||||
/* Standard uIP loop taken from the uIP manual. */
|
||||
if( xHeader->type == htons( UIP_ETHTYPE_IP ) )
|
||||
{
|
||||
uip_arp_ipin();
|
||||
uip_input();
|
||||
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )
|
||||
{
|
||||
uip_arp_arpin();
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;
|
||||
|
||||
if( uip_buf != NULL )
|
||||
{
|
||||
for( i = 0; i < UIP_CONNS; i++ )
|
||||
{
|
||||
uip_periodic( 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();
|
||||
vEMACWrite();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
ulUIP_Events |= ulNewEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetMACAddress( void )
|
||||
{
|
||||
struct uip_eth_addr xAddr;
|
||||
|
||||
/* Configure the MAC address in the uIP stack. */
|
||||
xAddr.addr[ 0 ] = configMAC_ADDR0;
|
||||
xAddr.addr[ 1 ] = configMAC_ADDR1;
|
||||
xAddr.addr[ 2 ] = configMAC_ADDR2;
|
||||
xAddr.addr[ 3 ] = configMAC_ADDR3;
|
||||
xAddr.addr[ 4 ] = configMAC_ADDR4;
|
||||
xAddr.addr[ 5 ] = configMAC_ADDR5;
|
||||
uip_setethaddr( xAddr );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialise_uIP( void )
|
||||
{
|
||||
uip_ipaddr_t xIPAddr;
|
||||
xTimerHandle xARPTimer, xPeriodicTimer;
|
||||
|
||||
uip_init();
|
||||
uip_ipaddr( &xIPAddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 );
|
||||
uip_sethostaddr( &xIPAddr );
|
||||
uip_ipaddr( &xIPAddr, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 );
|
||||
uip_setnetmask( &xIPAddr );
|
||||
prvSetMACAddress();
|
||||
httpd_init();
|
||||
|
||||
/* Create the queue used to sent TCP/IP events to the uIP stack. */
|
||||
xEMACEventQueue = xQueueCreate( uipEVENT_QUEUE_LENGTH, sizeof( unsigned long ) );
|
||||
|
||||
/* Create and start the uIP timers. */
|
||||
xARPTimer = xTimerCreate( ( signed char * ) "ARPTimer", /* Just a name that is helpful for debugging, not used by the kernel. */
|
||||
( 10000UL / portTICK_RATE_MS ), /* Timer period. */
|
||||
pdTRUE, /* Autor-reload. */
|
||||
( void * ) uipARP_TIMER,
|
||||
prvUIPTimerCallback
|
||||
);
|
||||
|
||||
xPeriodicTimer = xTimerCreate( ( signed char * ) "PeriodicTimer",
|
||||
( 500UL / portTICK_RATE_MS ),
|
||||
pdTRUE, /* Autor-reload. */
|
||||
( void * ) uipPERIODIC_TIMER,
|
||||
prvUIPTimerCallback
|
||||
);
|
||||
|
||||
/* Sanity check that the timers were indeed created. */
|
||||
configASSERT( xARPTimer );
|
||||
configASSERT( xPeriodicTimer );
|
||||
configASSERT( xEMACEventQueue );
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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. 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 );
|
||||
break;
|
||||
|
||||
case uipPERIODIC_TIMER : xQueueSend( xEMACEventQueue, &ulPeriodicTimerExpired, uipDONT_BLOCK );
|
||||
break;
|
||||
|
||||
default : /* Should not get here. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -0,0 +1,620 @@
|
||||
/*
|
||||
FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* 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! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* 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 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
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/* Freescale includes. */
|
||||
#include "common.h"
|
||||
#include "eth_phy.h"
|
||||
#include "enet.h"
|
||||
#include "mii.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* uIP includes. */
|
||||
#include "net/uip.h"
|
||||
|
||||
/* The time to wait between attempts to obtain a free buffer. */
|
||||
#define emacBUFFER_WAIT_DELAY_ms ( 3 / portTICK_RATE_MS )
|
||||
|
||||
/* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving
|
||||
up on attempting to obtain a free buffer all together. */
|
||||
#define emacBUFFER_WAIT_ATTEMPTS ( 30 )
|
||||
|
||||
/* The number of Rx descriptors. */
|
||||
#define emacNUM_RX_DESCRIPTORS 8
|
||||
|
||||
/* The number of Tx descriptors. When using uIP there is not point in having
|
||||
more than two. */
|
||||
#define emacNUM_TX_BUFFERS 2
|
||||
|
||||
/* The total number of EMAC buffers to allocate. */
|
||||
#define emacNUM_BUFFERS ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )
|
||||
|
||||
/* The time to wait for the Tx descriptor to become free. */
|
||||
#define emacTX_WAIT_DELAY_ms ( 10 / portTICK_RATE_MS )
|
||||
|
||||
/* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to
|
||||
become free. */
|
||||
#define emacTX_WAIT_ATTEMPTS ( 50 )
|
||||
|
||||
#define emacTX_INTERRUPT_NO ( 76 )
|
||||
#define emacRX_INTERRUPT_NO ( 77 )
|
||||
#define emacERROR_INTERRUPT_NO ( 78 )
|
||||
#define emacLINK_DELAY ( 500 / portTICK_RATE_MS )
|
||||
#define emacPHY_STATUS ( 0x1F )
|
||||
#define emacPHY_DUPLEX_STATUS ( 4 << 2 )
|
||||
#define emacPHY_SPEED_STATUS ( 1 << 2 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise both the Rx and Tx descriptors.
|
||||
*/
|
||||
static void prvInitialiseDescriptors( void );
|
||||
|
||||
/*
|
||||
* Return a pointer to a free buffer within xEthernetBuffers.
|
||||
*/
|
||||
static unsigned char *prvGetNextBuffer( void );
|
||||
|
||||
/*
|
||||
* Return a buffer to the list of free buffers.
|
||||
*/
|
||||
static void prvReturnBuffer( unsigned char *pucBuffer );
|
||||
|
||||
/*
|
||||
* Examine the status of the next Rx descriptor to see if it contains new data.
|
||||
*/
|
||||
static unsigned short prvCheckRxStatus( void );
|
||||
|
||||
/*
|
||||
* Something has gone wrong with the descriptor usage. Reset all the buffers
|
||||
* and descriptors.
|
||||
*/
|
||||
static void prvResetEverything( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The buffers and descriptors themselves. */
|
||||
#pragma data_alignment=16
|
||||
volatile NBUF xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];
|
||||
|
||||
#pragma data_alignment=16
|
||||
volatile NBUF xTxDescriptors[ emacNUM_TX_BUFFERS ];
|
||||
|
||||
#pragma data_alignment=16
|
||||
char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];
|
||||
|
||||
/* Used to indicate which buffers are free and which are in use. If an index
|
||||
contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise
|
||||
the buffer is in use or about to be used. */
|
||||
static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];
|
||||
|
||||
/* Points to the Rx descriptor currently in use. */
|
||||
static volatile NBUF *pxCurrentRxDesc = NULL;
|
||||
|
||||
/* pxCurrentRxDesc points to descriptor within the xRxDescriptors array that
|
||||
has an index defined by ulRxDescriptorIndex. */
|
||||
static unsigned long ulRxDescriptorIndex = 0UL;
|
||||
|
||||
/* 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. */
|
||||
unsigned char *uip_buf = NULL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
#define ENET_HARDWARE_CHECKSUM 0 //_RB_ for test only
|
||||
void vEMACInit( void )
|
||||
{
|
||||
int iData;
|
||||
extern int periph_clk_khz;
|
||||
const unsigned portCHAR ucMACAddress[] =
|
||||
{
|
||||
configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5
|
||||
};
|
||||
|
||||
/* Enable the ENET clock. */
|
||||
SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;
|
||||
|
||||
/* Allow concurrent access to MPU controller to avoid bus errors. */
|
||||
MPU_CESR = 0;
|
||||
|
||||
prvInitialiseDescriptors();
|
||||
|
||||
/* Reset and enable. */
|
||||
ENET_ECR = ENET_ECR_RESET_MASK;
|
||||
|
||||
/* Wait at least 8 clock cycles */
|
||||
vTaskDelay( 2 );
|
||||
|
||||
/* Start the MII interface*/
|
||||
mii_init( 0, periph_clk_khz / 1000L );
|
||||
|
||||
/* Configure the transmit interrupt. */
|
||||
set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
enable_irq( emacTX_INTERRUPT_NO );
|
||||
|
||||
/* Configure the receive interrupt. */
|
||||
set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
enable_irq( emacRX_INTERRUPT_NO );
|
||||
|
||||
/* Configure the error interrupt. */
|
||||
set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
enable_irq( emacERROR_INTERRUPT_NO );
|
||||
|
||||
/* Configure the pins to the PHY - RMII mode used. */
|
||||
PORTB_PCR0 = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */
|
||||
PORTB_PCR1 = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */
|
||||
PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */
|
||||
PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */
|
||||
PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */
|
||||
PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */
|
||||
PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */
|
||||
PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */
|
||||
|
||||
/* Is there communication with the PHY? */
|
||||
do
|
||||
{
|
||||
vTaskDelay( emacLINK_DELAY );
|
||||
iData = 0xFFFF;
|
||||
mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData );
|
||||
|
||||
} while( iData == 0xFFFF );
|
||||
|
||||
/* Start to auto negotiate. */
|
||||
mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
|
||||
|
||||
/* Wait for auto negotiate to complete. */
|
||||
do
|
||||
{
|
||||
vTaskDelay( emacLINK_DELAY );
|
||||
mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData );
|
||||
|
||||
} while( !( iData & PHY_BMSR_AN_COMPLETE ) );
|
||||
|
||||
/* A link has been established. What was negotiated? */
|
||||
iData = 0;
|
||||
mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData );
|
||||
|
||||
/* Clear the Individual and Group Address Hash registers */
|
||||
ENET_IALR = 0;
|
||||
ENET_IAUR = 0;
|
||||
ENET_GALR = 0;
|
||||
ENET_GAUR = 0;
|
||||
|
||||
/* Set the Physical Address for the selected ENET */
|
||||
enet_set_address( 0, ucMACAddress );
|
||||
|
||||
ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK;
|
||||
|
||||
/* Clear the control registers. */
|
||||
ENET_TCR = 0;
|
||||
|
||||
if( iData & emacPHY_DUPLEX_STATUS )
|
||||
{
|
||||
/* Full duplex */
|
||||
ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK;
|
||||
ENET_TCR |= ENET_TCR_FDEN_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Half duplex */
|
||||
ENET_RCR |= ENET_RCR_DRT_MASK;
|
||||
ENET_TCR &= (unsigned portLONG)~ENET_TCR_FDEN_MASK;
|
||||
}
|
||||
|
||||
if( iData & emacPHY_SPEED_STATUS )
|
||||
{
|
||||
/* 10Mbps */
|
||||
ENET_RCR |= ENET_RCR_RMII_10T_MASK;
|
||||
}
|
||||
|
||||
ENET_ECR = ENET_ECR_EN1588_MASK;
|
||||
|
||||
#if 0
|
||||
//_RB_
|
||||
// Enable Ethernet header alignment for rx
|
||||
ENET_RACC |= 0
|
||||
| ENET_RACC_SHIFT16_MASK
|
||||
;
|
||||
|
||||
// Enable Ethernet header alignment for tx
|
||||
ENET_TACC |= 0
|
||||
| ENET_TACC_SHIFT16_MASK
|
||||
;
|
||||
#endif
|
||||
|
||||
/* Store and forward checksum. */
|
||||
ENET_TFWR = ENET_TFWR_STRFWD_MASK;
|
||||
|
||||
/* Set Rx Buffer Size */
|
||||
ENET_MRBR = ( unsigned short ) UIP_BUFSIZE;
|
||||
|
||||
/* Point to the start of the circular Rx buffer descriptor queue */
|
||||
ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] );
|
||||
|
||||
/* Point to the start of the circular Tx buffer descriptor queue */
|
||||
ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] );
|
||||
|
||||
/* Clear all ENET interrupt events */
|
||||
ENET_EIR = ( unsigned long ) -1;
|
||||
|
||||
/* Enable interrupts. */
|
||||
ENET_EIMR = 0
|
||||
/*rx irqs*/
|
||||
| ENET_EIMR_RXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/
|
||||
/*xmit irqs*/
|
||||
| ENET_EIMR_TXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/
|
||||
/*enet irqs*/
|
||||
| ENET_EIMR_UN_MASK | ENET_EIMR_RL_MASK | ENET_EIMR_LC_MASK | ENET_EIMR_BABT_MASK | ENET_EIMR_BABR_MASK | ENET_EIMR_EBERR_MASK
|
||||
;
|
||||
|
||||
/* Enable the MAC itself. */
|
||||
ENET_ECR |= ENET_ECR_ETHEREN_MASK;
|
||||
|
||||
/* Indicate that there have been empty receive buffers produced */
|
||||
ENET_RDAR = ENET_RDAR_RDAR_MASK;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseDescriptors( void )
|
||||
{
|
||||
volatile NBUF *pxDescriptor;
|
||||
long x;
|
||||
|
||||
for( x = 0; x < emacNUM_BUFFERS; x++ )
|
||||
{
|
||||
/* Ensure none of the buffers are shown as in use at the start. */
|
||||
ucBufferInUse[ x ] = pdFALSE;
|
||||
}
|
||||
|
||||
/* Initialise the Rx descriptors. */
|
||||
for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )
|
||||
{
|
||||
pxDescriptor = &( xRxDescriptors[ x ] );
|
||||
pxDescriptor->data = ( uint8_t* ) &( xEthernetBuffers[ x ][ 0 ] );
|
||||
pxDescriptor->data = ( uint8_t* ) __REV( ( unsigned long ) pxDescriptor->data );
|
||||
pxDescriptor->length = 0;
|
||||
pxDescriptor->status = RX_BD_E;
|
||||
pxDescriptor->bdu = 0;
|
||||
pxDescriptor->ebd_status = RX_BD_INT;
|
||||
|
||||
/* Mark this buffer as in use. */
|
||||
ucBufferInUse[ x ] = pdTRUE;
|
||||
}
|
||||
|
||||
/* The last descriptor points back to the start. */
|
||||
pxDescriptor->status |= RX_BD_W;
|
||||
|
||||
/* Initialise the Tx descriptors. */
|
||||
for( x = 0; x < emacNUM_TX_BUFFERS; x++ )
|
||||
{
|
||||
pxDescriptor = &( xTxDescriptors[ x ] );
|
||||
|
||||
/* A buffer is not allocated to the Tx descriptor until a send is
|
||||
actually required. */
|
||||
pxDescriptor->data = NULL;
|
||||
pxDescriptor->length = 0;
|
||||
pxDescriptor->status = TX_BD_TC;
|
||||
pxDescriptor->ebd_status = TX_BD_INT;
|
||||
}
|
||||
|
||||
/* The last descriptor points back to the start. */
|
||||
pxDescriptor->status |= TX_BD_W;
|
||||
|
||||
/* Use the first Rx descriptor to start with. */
|
||||
ulRxDescriptorIndex = 0UL;
|
||||
pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMACWrite( void )
|
||||
{
|
||||
long x;
|
||||
|
||||
/* Wait until the second transmission of the last packet has completed. */
|
||||
for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )
|
||||
{
|
||||
if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )
|
||||
{
|
||||
/* Descriptor is still active. */
|
||||
vTaskDelay( emacTX_WAIT_DELAY_ms );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the descriptor free after waiting for it? */
|
||||
if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )
|
||||
{
|
||||
/* Something has gone wrong. */
|
||||
prvResetEverything();
|
||||
}
|
||||
|
||||
/* Setup both descriptors to transmit the frame. */
|
||||
xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );
|
||||
xTxDescriptors[ 0 ].length = __REVSH( uip_len );
|
||||
xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );
|
||||
xTxDescriptors[ 1 ].length = __REVSH( uip_len );
|
||||
|
||||
/* uip_buf is being sent by the Tx descriptor. Allocate a new buffer
|
||||
for use by the stack. */
|
||||
uip_buf = prvGetNextBuffer();
|
||||
|
||||
/* Clear previous settings and go. */
|
||||
xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L );
|
||||
xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L );
|
||||
|
||||
/* Start the Tx. */
|
||||
ENET_TDAR = ENET_TDAR_TDAR_MASK;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static unsigned char *prvGetNextBuffer( void )
|
||||
{
|
||||
long x;
|
||||
unsigned char *pucReturn = NULL;
|
||||
unsigned long ulAttempts = 0;
|
||||
|
||||
while( pucReturn == NULL )
|
||||
{
|
||||
/* Look through the buffers to find one that is not in use by
|
||||
anything else. */
|
||||
for( x = 0; x < emacNUM_BUFFERS; x++ )
|
||||
{
|
||||
if( ucBufferInUse[ x ] == pdFALSE )
|
||||
{
|
||||
ucBufferInUse[ x ] = pdTRUE;
|
||||
pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Was a buffer found? */
|
||||
if( pucReturn == NULL )
|
||||
{
|
||||
ulAttempts++;
|
||||
|
||||
if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait then look again. */
|
||||
vTaskDelay( emacBUFFER_WAIT_DELAY_ms );
|
||||
}
|
||||
}
|
||||
|
||||
return pucReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvResetEverything( void )
|
||||
{
|
||||
/* Temporary code just to see if this gets called. This function has not
|
||||
been implemented. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned short usEMACRead( void )
|
||||
{
|
||||
unsigned short usBytesReceived;
|
||||
|
||||
usBytesReceived = prvCheckRxStatus();
|
||||
usBytesReceived = __REVSH( usBytesReceived );
|
||||
|
||||
if( usBytesReceived > 0 )
|
||||
{
|
||||
/* Mark the pxDescriptor buffer as free as uip_buf is going to be set to
|
||||
the buffer that contains the received data. */
|
||||
prvReturnBuffer( uip_buf );
|
||||
|
||||
/* Point uip_buf to the data about to be processed. */
|
||||
uip_buf = ( void * ) pxCurrentRxDesc->data;
|
||||
uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf );
|
||||
|
||||
/* Allocate a new buffer to the descriptor, as uip_buf is now using it's
|
||||
old descriptor. */
|
||||
pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer();
|
||||
pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data );
|
||||
|
||||
/* Prepare the descriptor to go again. */
|
||||
pxCurrentRxDesc->status |= RX_BD_E;
|
||||
|
||||
/* Move onto the next buffer in the ring. */
|
||||
ulRxDescriptorIndex++;
|
||||
if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS )
|
||||
{
|
||||
ulRxDescriptorIndex = 0UL;
|
||||
}
|
||||
pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] );
|
||||
|
||||
/* Restart Ethernet if it has stopped */
|
||||
ENET_RDAR = ENET_RDAR_RDAR_MASK;
|
||||
}
|
||||
|
||||
return usBytesReceived;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReturnBuffer( unsigned char *pucBuffer )
|
||||
{
|
||||
unsigned long ul;
|
||||
|
||||
/* Return a buffer to the pool of free buffers. */
|
||||
for( ul = 0; ul < emacNUM_BUFFERS; ul++ )
|
||||
{
|
||||
if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )
|
||||
{
|
||||
ucBufferInUse[ ul ] = pdFALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static unsigned short prvCheckRxStatus( void )
|
||||
{
|
||||
unsigned long usReturn = 0;
|
||||
|
||||
if( ( pxCurrentRxDesc->status & RX_BD_E ) != 0 )
|
||||
{
|
||||
/* Current descriptor is still active. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The descriptor contains a frame. Because of the size of the buffers
|
||||
the frame should always be complete. */
|
||||
usReturn = pxCurrentRxDesc->length;
|
||||
}
|
||||
|
||||
return usReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMAC_TxISRHandler( void )
|
||||
{
|
||||
/* Check the buffers have not already been freed in the first of the
|
||||
two Tx interrupts - which could potentially happen if the second Tx completed
|
||||
during the interrupt for the first Tx. */
|
||||
if( xTxDescriptors[ 0 ].data != NULL )
|
||||
{
|
||||
if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )
|
||||
{
|
||||
configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );
|
||||
|
||||
xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );
|
||||
prvReturnBuffer( xTxDescriptors[ 0 ].data );
|
||||
|
||||
/* Just to mark the fact that the buffer has already been released. */
|
||||
xTxDescriptors[ 0 ].data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMAC_RxISRHandler( void )
|
||||
{
|
||||
const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
|
||||
long lHigherPriorityTaskWoken = pdFALSE;
|
||||
extern xQueueHandle xEMACEventQueue;
|
||||
|
||||
/* An Ethernet Rx event has occurred. */
|
||||
xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
|
||||
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMAC_ErrorISRHandler( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
volatile unsigned long ulEvent, ulMask;
|
||||
void vEMAC_ISRHandler( void )
|
||||
{
|
||||
//unsigned long ulEvent;
|
||||
long lHigherPriorityTaskWoken = pdFALSE;
|
||||
const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
|
||||
extern xQueueHandle xEMACEventQueue;
|
||||
|
||||
/* What caused the interrupt? */
|
||||
ulMask = ENET_EIMR;
|
||||
ulEvent = ENET_EIR;
|
||||
ulEvent &= ulMask;
|
||||
|
||||
ENET_EIR = ulEvent;
|
||||
|
||||
if( ( ulEvent & ENET_EIR_TXF_MASK ) != 0UL )
|
||||
{
|
||||
/* Transmit complete.
|
||||
Check the buffers have not already been freed in the first of the
|
||||
two Tx interrupts - which could potentially happen if the second Tx completed
|
||||
during the interrupt for the first Tx. */
|
||||
if( xTxDescriptors[ 0 ].data != NULL )
|
||||
{
|
||||
if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )
|
||||
{
|
||||
configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );
|
||||
|
||||
xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );
|
||||
prvReturnBuffer( xTxDescriptors[ 0 ].data );
|
||||
|
||||
/* Just to mark the fact that the buffer has already been released. */
|
||||
xTxDescriptors[ 0 ].data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( ( ulEvent & ENET_EIR_RXF_MASK ) != 0UL )
|
||||
{
|
||||
/* Packet Rxed. */
|
||||
xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
|
||||
portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
|
||||
}
|
||||
|
||||
if( ulEvent & ( ENET_EIR_UN_MASK | ENET_EIR_RL_MASK | ENET_EIR_LC_MASK | ENET_EIR_EBERR_MASK | ENET_EIR_BABT_MASK | ENET_EIR_BABR_MASK | ENET_EIR_EBERR_MASK ) )
|
||||
{
|
||||
/* Error. */
|
||||
prvInitialiseDescriptors();
|
||||
ENET_RDAR = ENET_RDAR_RDAR_MASK;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* 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! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* 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 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
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
#ifndef FR_EMAC_H
|
||||
#define FR_EMAC_H
|
||||
|
||||
/*
|
||||
* Configure all the ethernet components (MAC, DMA, PHY) ready for communication.
|
||||
*/
|
||||
void vEMACInit( void );
|
||||
|
||||
/*
|
||||
* Check the Rx status, and return the number of bytes received if any.
|
||||
*/
|
||||
unsigned short usEMACRead( void );
|
||||
|
||||
/*
|
||||
* Send uip_len bytes from uip_buf to the Tx descriptors and initiate a Tx.
|
||||
*/
|
||||
void vEMACWrite( void );
|
||||
|
||||
#endif /* FR_EMAC_H */
|
@ -0,0 +1,277 @@
|
||||
/**
|
||||
* \addtogroup httpd
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Web server script interface
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: httpd-cgi.c,v 1.2 2006/06/11 21:46:37 adam Exp $
|
||||
*
|
||||
*/
|
||||
#include "net/uip.h"
|
||||
#include "net/psock.h"
|
||||
#include "apps/httpd/httpd.h"
|
||||
#include "apps/httpd/httpd-cgi.h"
|
||||
#include "apps/httpd/httpd-fs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
HTTPD_CGI_CALL( file, "file-stats", file_stats );
|
||||
HTTPD_CGI_CALL( tcp, "tcp-connections", tcp_stats );
|
||||
HTTPD_CGI_CALL( net, "net-stats", net_stats );
|
||||
HTTPD_CGI_CALL( rtos, "rtos-stats", rtos_stats );
|
||||
HTTPD_CGI_CALL( run, "run-time", run_time );
|
||||
HTTPD_CGI_CALL( io, "led-io", led_io );
|
||||
|
||||
static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, &rtos, &run, &io, NULL };
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( nullfunction ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
httpd_cgifunction httpd_cgi( char *name )
|
||||
{
|
||||
const struct httpd_cgi_call **f;
|
||||
|
||||
/* Find the matching name in the table, return the function. */
|
||||
for( f = calls; *f != NULL; ++f )
|
||||
{
|
||||
if( strncmp((*f)->name, name, strlen((*f)->name)) == 0 )
|
||||
{
|
||||
return( *f )->function;
|
||||
}
|
||||
}
|
||||
|
||||
return nullfunction;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static unsigned short generate_file_stats( void *arg )
|
||||
{
|
||||
char *f = ( char * ) arg;
|
||||
return sprintf( ( char * ) uip_appdata, "%5u", httpd_fs_count(f) );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( file_stats ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
|
||||
( void ) PT_YIELD_FLAG;
|
||||
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_file_stats, strchr(ptr, ' ') + 1 );
|
||||
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static const char closed[] = /* "CLOSED",*/ { 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0 };
|
||||
static const char syn_rcvd[] = /* "SYN-RCVD",*/ { 0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, 0x44, 0 };
|
||||
static const char syn_sent[] = /* "SYN-SENT",*/ { 0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, 0x54, 0 };
|
||||
static const char established[] = /* "ESTABLISHED",*/ { 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0 };
|
||||
static const char fin_wait_1[] = /* "FIN-WAIT-1",*/ { 0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 0x54, 0x2d, 0x31, 0 };
|
||||
static const char fin_wait_2[] = /* "FIN-WAIT-2",*/ { 0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, 0x54, 0x2d, 0x32, 0 };
|
||||
static const char closing[] = /* "CLOSING",*/ { 0x43, 0x4c, 0x4f, 0x53, 0x49, 0x4e, 0x47, 0 };
|
||||
static const char time_wait[] = /* "TIME-WAIT,"*/ { 0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, 0x49, 0x54, 0 };
|
||||
static const char last_ack[] = /* "LAST-ACK"*/ { 0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, 0x4b, 0 };
|
||||
|
||||
static const char *states[] = { closed, syn_rcvd, syn_sent, established, fin_wait_1, fin_wait_2, closing, time_wait, last_ack };
|
||||
|
||||
static unsigned short generate_tcp_stats( void *arg )
|
||||
{
|
||||
struct uip_conn *conn;
|
||||
struct httpd_state *s = ( struct httpd_state * ) arg;
|
||||
|
||||
conn = &uip_conns[s->count];
|
||||
return sprintf( ( char * ) uip_appdata,
|
||||
"<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n", htons(conn->lport),
|
||||
htons(conn->ripaddr.u16[0]) >> 8, htons(conn->ripaddr.u16[0]) & 0xff, htons(conn->ripaddr.u16[1]) >> 8,
|
||||
htons(conn->ripaddr.u16[1]) & 0xff, htons(conn->rport), states[conn->tcpstateflags & UIP_TS_MASK], conn->nrtx, conn->timer,
|
||||
(uip_outstanding(conn)) ? '*' : ' ', (uip_stopped(conn)) ? '!' : ' ' );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( tcp_stats ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
for( s->count = 0; s->count < UIP_CONNS; ++s->count )
|
||||
{
|
||||
if( (uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED )
|
||||
{
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_tcp_stats, s );
|
||||
}
|
||||
}
|
||||
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static unsigned short generate_net_stats( void *arg )
|
||||
{
|
||||
struct httpd_state *s = ( struct httpd_state * ) arg;
|
||||
return sprintf( ( char * ) uip_appdata, "%5u\n", (( uip_stats_t * ) &uip_stat)[s->count] );
|
||||
}
|
||||
|
||||
static PT_THREAD( net_stats ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
#if UIP_STATISTICS
|
||||
for( s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); ++s->count )
|
||||
{
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_net_stats, s );
|
||||
}
|
||||
|
||||
#endif /* UIP_STATISTICS */
|
||||
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
extern void vTaskList( signed char *pcWriteBuffer );
|
||||
extern char *pcGetTaskStatusMessage( void );
|
||||
static char cCountBuf[128];
|
||||
long lRefreshCount = 0;
|
||||
static unsigned short generate_rtos_stats( void *arg )
|
||||
{
|
||||
( void ) arg;
|
||||
lRefreshCount++;
|
||||
sprintf( cCountBuf, "<p><br>Refresh count = %d<p><br>%s", ( int ) lRefreshCount, pcGetTaskStatusMessage() );
|
||||
vTaskList( uip_appdata );
|
||||
strcat( uip_appdata, cCountBuf );
|
||||
|
||||
return strlen( uip_appdata );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( rtos_stats ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_rtos_stats, NULL );
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *pcStatus;
|
||||
unsigned long ulString;
|
||||
|
||||
static unsigned short generate_io_state( void *arg )
|
||||
{
|
||||
extern long lParTestGetLEDState( unsigned long ulLED );
|
||||
( void ) arg;
|
||||
|
||||
/* Are the dynamically setable LEDs currently on or off? */
|
||||
if( lParTestGetLEDState( 8 ) )
|
||||
{
|
||||
pcStatus = "checked";
|
||||
}
|
||||
else
|
||||
{
|
||||
pcStatus = "";
|
||||
}
|
||||
|
||||
sprintf( uip_appdata, "<input type=\"checkbox\" name=\"LED0\" value=\"1\" %s>LED<p><p>", pcStatus );
|
||||
|
||||
return strlen( uip_appdata );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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 );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( run_time ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_runtime_stats, NULL );
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static PT_THREAD( led_io ( struct httpd_state *s, char *ptr ) )
|
||||
{
|
||||
PSOCK_BEGIN( &s->sout );
|
||||
( void ) ptr;
|
||||
( void ) PT_YIELD_FLAG;
|
||||
PSOCK_GENERATOR_SEND( &s->sout, generate_io_state, NULL );
|
||||
PSOCK_END( &s->sout );
|
||||
}
|
||||
|
||||
/** @} */
|
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<body bgcolor="white">
|
||||
<center>
|
||||
<h1>404 - file not found</h1>
|
||||
<h3>Go <a href="/">here</a> instead.</h3>
|
||||
</center>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY onLoad="window.setTimeout("location.href='index.shtml'",100)">
|
||||
<font face="arial">
|
||||
Loading index.shtml. Click <a href="index.shtml">here</a> if not automatically redirected.
|
||||
</font>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY onLoad="window.setTimeout("location.href='index.shtml'",2000)">
|
||||
<font face="arial">
|
||||
<a href="index.shtml">Task Stats</a> <b>|</b> <a href="runtime.shtml">Run Time Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">37K jpg</a>
|
||||
<br><p>
|
||||
<hr>
|
||||
<br><p>
|
||||
<h2>Task statistics</h2>
|
||||
Page will refresh every 2 seconds.<p>
|
||||
<font face="courier"><pre>Task State Priority Stack #<br>************************************************<br>
|
||||
%! rtos-stats
|
||||
</pre></font>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY>
|
||||
<font face="arial">
|
||||
<a href="index.shtml">Task Stats</a> <b>|</b> <a href="runtime.shtml">Run Time Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">37K jpg</a>
|
||||
<br><p>
|
||||
<hr>
|
||||
<b>LED and LCD IO</b><br>
|
||||
|
||||
<p>
|
||||
|
||||
Use the check box to turn on or off LED 4, then click "Update IO".
|
||||
|
||||
|
||||
<p>
|
||||
<form name="aForm" action="/io.shtml" method="get">
|
||||
%! led-io
|
||||
<p>
|
||||
<input type="submit" value="Update IO">
|
||||
</form>
|
||||
<br><p>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY onLoad="window.setTimeout("location.href='runtime.shtml'",2000)">
|
||||
<font face="arial">
|
||||
<a href="index.shtml">Task Stats</a> <b>|</b> <a href="runtime.shtml">Run Time Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">37K jpg</a>
|
||||
<br><p>
|
||||
<hr>
|
||||
<br><p>
|
||||
<h2>Run-time statistics</h2>
|
||||
Page will refresh every 2 seconds.<p>
|
||||
<font face="courier"><pre>Task Abs Time % Time<br>****************************************<br>
|
||||
%! run-time
|
||||
</pre></font>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY>
|
||||
<font face="arial">
|
||||
<a href="index.shtml">Task Stats</a> <b>|</b> <a href="runtime.shtml">Run Time Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">37K jpg</a>
|
||||
<br><p>
|
||||
<hr>
|
||||
<br><p>
|
||||
<h2>Network statistics</h2>
|
||||
<table width="300" border="0">
|
||||
<tr><td align="left"><font face="courier"><pre>
|
||||
IP Packets received
|
||||
Packets sent
|
||||
Forwaded
|
||||
Dropped
|
||||
IP errors IP version/header length
|
||||
IP length, high byte
|
||||
IP length, low byte
|
||||
IP fragments
|
||||
Header checksum
|
||||
Wrong protocol
|
||||
ICMP Packets received
|
||||
Packets sent
|
||||
Packets dropped
|
||||
Type errors
|
||||
Checksum errors
|
||||
TCP Packets received
|
||||
Packets sent
|
||||
Packets dropped
|
||||
Checksum errors
|
||||
Data packets without ACKs
|
||||
Resets
|
||||
Retransmissionsa
|
||||
Syn to closed port
|
||||
UDP Packets dropped
|
||||
Packets received
|
||||
Packets sent
|
||||
Packets chkerr
|
||||
No connection avaliable
|
||||
</pre></font></td><td><font face="courier"><pre>%! net-stats
|
||||
</pre></font></td></table>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FreeRTOS.org uIP WEB server demo</title>
|
||||
</head>
|
||||
<BODY>
|
||||
<font face="arial">
|
||||
<a href="index.shtml">Task Stats</a> <b>|</b> <a href="runtime.shtml">Run Time Stats</a> <b>|</b> <a href="stats.shtml">TCP Stats</a> <b>|</b> <a href="tcp.shtml">Connections</a> <b>|</b> <a href="http://www.freertos.org/">FreeRTOS Homepage</a> <b>|</b> <a href="io.shtml">IO</a> <b>|</b> <a href="logo.jpg">37K jpg</a>
|
||||
<br><p>
|
||||
<hr>
|
||||
<br>
|
||||
<h2>Network connections</h2>
|
||||
<p>
|
||||
<table>
|
||||
<tr><th>Local</th><th>Remote</th><th>State</th><th>Retransmissions</th><th>Timer</th><th>Flags</th></tr>
|
||||
%! tcp-connections
|
||||
</pre></font>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
open(OUTPUT, "> httpd-fsdata.c");
|
||||
|
||||
chdir("httpd-fs");
|
||||
|
||||
opendir(DIR, ".");
|
||||
@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
|
||||
closedir(DIR);
|
||||
|
||||
foreach $file (@files) {
|
||||
|
||||
if(-d $file && $file !~ /^\./) {
|
||||
print "Processing directory $file\n";
|
||||
opendir(DIR, $file);
|
||||
@newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
|
||||
closedir(DIR);
|
||||
printf "Adding files @newfiles\n";
|
||||
@files = (@files, map { $_ = "$file/$_" } @newfiles);
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
foreach $file (@files) {
|
||||
if(-f $file) {
|
||||
|
||||
print "Adding file $file\n";
|
||||
|
||||
open(FILE, $file) || die "Could not open file $file\n";
|
||||
binmode FILE;
|
||||
|
||||
$file =~ s-^-/-;
|
||||
$fvar = $file;
|
||||
$fvar =~ s-/-_-g;
|
||||
$fvar =~ s-\.-_-g;
|
||||
# for AVR, add PROGMEM here
|
||||
print(OUTPUT "static const char data".$fvar."[] = {\n");
|
||||
print(OUTPUT "\t/* $file */\n\t");
|
||||
for($j = 0; $j < length($file); $j++) {
|
||||
printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
|
||||
}
|
||||
printf(OUTPUT "0,\n");
|
||||
|
||||
|
||||
$i = 0;
|
||||
while(read(FILE, $data, 1)) {
|
||||
if($i == 0) {
|
||||
print(OUTPUT "\t");
|
||||
}
|
||||
printf(OUTPUT "%#02x, ", unpack("C", $data));
|
||||
$i++;
|
||||
if($i == 10) {
|
||||
print(OUTPUT "\n");
|
||||
$i = 0;
|
||||
}
|
||||
}
|
||||
print(OUTPUT "0};\n\n");
|
||||
close(FILE);
|
||||
push(@fvars, $fvar);
|
||||
push(@pfiles, $file);
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0; $i < @fvars; $i++) {
|
||||
$file = $pfiles[$i];
|
||||
$fvar = $fvars[$i];
|
||||
|
||||
if($i == 0) {
|
||||
$prevfile = "NULL";
|
||||
} else {
|
||||
$prevfile = "file" . $fvars[$i - 1];
|
||||
}
|
||||
print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
|
||||
print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
|
||||
print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
|
||||
}
|
||||
|
||||
print(OUTPUT "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n");
|
||||
print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n");
|
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* \addtogroup uipopt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \name Project-specific configuration options
|
||||
* @{
|
||||
*
|
||||
* uIP has a number of configuration options that can be overridden
|
||||
* for each project. These are kept in a project-specific uip-conf.h
|
||||
* file and all configuration names have the prefix UIP_CONF.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: uip-conf.h,v 1.6 2006/06/12 08:00:31 adam Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* An example uIP configuration file
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __UIP_CONF_H__
|
||||
#define __UIP_CONF_H__
|
||||
|
||||
#define UIP_CONF_EXTERNAL_BUFFER
|
||||
#define UIP_CONF_PROCESS_HTTPD_FORMS 1
|
||||
|
||||
/**
|
||||
* 8 bit datatype
|
||||
*
|
||||
* This typedef defines the 8-bit type used throughout uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef unsigned char u8_t;
|
||||
|
||||
/**
|
||||
* 16 bit datatype
|
||||
*
|
||||
* This typedef defines the 16-bit type used throughout uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef unsigned short u16_t;
|
||||
|
||||
typedef unsigned long u32_t;
|
||||
|
||||
/**
|
||||
* Statistics datatype
|
||||
*
|
||||
* This typedef defines the dataype used for keeping statistics in
|
||||
* uIP.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
/**
|
||||
* Maximum number of TCP connections.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_MAX_CONNECTIONS 40
|
||||
|
||||
/**
|
||||
* Maximum number of listening TCP ports.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_MAX_LISTENPORTS 40
|
||||
|
||||
/**
|
||||
* uIP buffer size.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_BUFFER_SIZE 1480
|
||||
|
||||
/**
|
||||
* CPU byte order.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#if __LITTLE_ENDIAN__ == 1
|
||||
#define UIP_CONF_BYTE_ORDER UIP_LITTLE_ENDIAN
|
||||
#else
|
||||
#define UIP_CONF_BYTE_ORDER UIP_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Logging on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_LOGGING 0
|
||||
|
||||
/**
|
||||
* UDP support on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_UDP 0
|
||||
|
||||
/**
|
||||
* UDP checksums on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_UDP_CHECKSUMS 1
|
||||
|
||||
/**
|
||||
* uIP statistics on or off
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define UIP_CONF_STATISTICS 1
|
||||
|
||||
/* Here we include the header file for the application(s) we use in
|
||||
our project. */
|
||||
/*#include "smtp.h"*/
|
||||
/*#include "hello-world.h"*/
|
||||
/*#include "telnetd.h"*/
|
||||
#include "webserver.h"
|
||||
/*#include "dhcpc.h"*/
|
||||
/*#include "resolv.h"*/
|
||||
/*#include "webclient.h"*/
|
||||
|
||||
#define CCIF
|
||||
#define CC_REGISTER_ARG
|
||||
|
||||
#endif /* __UIP_CONF_H__ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2002, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* $Id: webserver.h,v 1.2 2006/06/11 21:46:38 adam Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef __WEBSERVER_H__
|
||||
#define __WEBSERVER_H__
|
||||
|
||||
#include "apps/httpd/httpd.h"
|
||||
|
||||
typedef struct httpd_state uip_tcp_appstate_t;
|
||||
/* UIP_APPCALL: the name of the application function. This function
|
||||
must return void and take no arguments (i.e., C type "void
|
||||
appfunc(void)"). */
|
||||
#define UIP_APPCALL httpd_appcall
|
||||
|
||||
|
||||
#endif /* __WEBSERVER_H__ */
|
Loading…
Reference in New Issue