MityDSP Documentation Index
Initializing the MityDSP Network Interface

The MityDSP system allows flexible configuration of hardware and software. Since the hardware in the FPGA can be modified for your particular application, you may also need access to different Ethernet device drivers. The MityDSP net library allows this by using a C++ class derived from a generic Ethernet driver base class. Inside the net module all driver calls are made to a tcNetDrvr base class type object. You specify the actual driver type by creating a driver object from a class derived from tcNetDrvr, then you pass a pointer to the derived driver object to the netif_add function.

Most MityDSP applications can use the stock MAC network driver and FPGA core, which is the tcNetDrvr_B() class, and the example code provided below should be appropriate for initialization of the network/stack API.

For the MityDSP-Pro, applications may use the tcNetDrvr_B() class for use with the legacy MAC FPGA core, or they may use the tcNetDrvr_645x() class which provides an lwIP compatible driver for the on-chip DSP EMAC engine, or both.

Two key parameters that require attention are the tcpip_priority field and the nacb_func field of the tsDSPNetStackInit structure. The tcpip_priority field sets the priority of the network stack, which must be higher than all other threads utilizing the stack. In order to gaurantee known prioritization, this value should be defined by the application. The nacb_func callback function is used by the lwIP stack to notify the user of critical failures associated with using the network. This function should always be assigned so that developers are appropriately notified of network issues, as in general the errors raised are user errors (e.g., registering a thread at a priority higher than the stack, registering more threads than allowed by the stack, not registering a thread on the stack, etc.).

See also:
tcNetDrvr_B, DSPNetStackInit, tcNetDrvr_645x

Initializing the MityDSP Network Interface

The following simple example will setup a derived Ethernet driver object designed for the standard MityDSP boards.

#include <std.h>
#include <clk.h>
#include <string_extras.h>
#include <core/DspFirmware.h>
#include <core/DspConfig.h>
#include <core/DspError.h>
#include <core/DspSpi.h>
#include <core/DspTimer.h>
#include <net/DSPNetStack.h>
#include <net/net_iface.h>
using namespace MityDSP;
#define READ_CONFIG_FROM_FLASH 1
// ethernet default init
#define IP_ADDR_INIT { 192, 168, 0, 192 }
#define SUBNET_INIT { 255, 255, 255, 0 }
#define GATEWAY_INIT { 192, 168, 0, 1 }
#define MAC_INIT { 0, 4, 0, 4, 0, 5 }
const int gnNET_TCP_PRIORITY = (TSK_MINPRI + 10);
unsigned int mnTicksPerMsec = CLK_countspms() / CLK_getprd();
tcNetDrvr_B *mpNetDrvr = NULL;
void lwipAssertReport(const char *apMsg)
{
tcDspError::report(<strong>FILE</strong>, <strong>LINE</strong>, error, "LWIP ASSERT: %s", apMsg);
}
void lwipStackInit(unsigned int anEnetBase, tcDspSpi <em>apSpi)
{
bool success;
unsigned char g_ip_addr[4] = IP_ADDR_INIT;
unsigned char g_subnet[4] = SUBNET_INIT;
unsigned char g_gw_addr[4] = GATEWAY_INIT;
tcDspNetIFConfigUtil</em> configutil;
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gateway;
tsNetPhyStatus phyStatus;
teNetPhyType phyType;
static struct netif netif;
static tsNetIface NetIface;
#ifdef READ_CONFIG_FROM_FLASH
// Get stored data from FLASH. This class will generate DHCP enabled defaults if
// no valid FLASH configuration has been stored. Assumes location is at base of
// application data area. Change this per requirements.
configutil = new tcDspNetIFConfigUtil(mpFlash, tcDspConfig::GetInstance(mpFlash),
tcDspConfig::GetInstance(mpFlash)->GetAppDataOffset());
configutil->GetConfig(&netconfig);
#else
netconfig.mnUseDHCP = true; // set to true to obtain IP addr via DHCP
if (useDHCP)
{
IP4_ADDR(&netconfig.msIpAddr, 0, 0, 0, 0);
IP4_ADDR(&netconfig.msNetmask, 0, 0, 0, 0);
IP4_ADDR(&netconfig.msGateway, 0, 0, 0, 0);
}
else
{
IP4_ADDR(&netconfig.msIpAddr, g_ip_addr[0], g_ip_addr[1], g_ip_addr[2], g_ip_addr[3]);
IP4_ADDR(&netconfig.msNetmask, g_subnet[0], g_subnet[1], g_subnet[2], g_subnet[3]);
IP4_ADDR(&netconfig.msGateway, g_gw_addr[0], g_gw_addr[1], g_gw_addr[2], g_gw_addr[3]);
}
// placeholder, you must launch WINS manually using DspWins.lib
sprintf(netconfig.maNetBIOSName,"My BIOS Name");
netconfig.mnUseWINS = false;
sprintf(netconfig.maPolledName,"My Locator Name");
sprintf(netconfig.maDescription,"My Locator Description");
tcDspConfig::GetInstance(mpFlash)->GetMACAddress((unsigned char*)netconfig.maMACAddress);
configutil = new tcDspNetIFConfigUtil(tcDspConfig::GetInstance(mpFlash),&netconfig);
#endif
// Do low level stack initialization...
si.tcpip_priority = gnNET_TCP_PRIORITY; // default priority=5, must be higher than
// all stack users
si.nacb_func = lwipAssertReport; // set LWIP assert notification so errors
// are displayed while debugging
#ifdef USE_645X_EMAC
// instantiate the network driver for the C645x on-chip EMAC on HWI vector 8
mpNetDrvr = new tcNetDrvr_645x(g_mac_addr, 8);
#else
// instantiate the network driver (default: use RX and TX DMA, DMA thread prio=14)
mpNetDrvr = new tcNetDrvr_B(g_mac_addr, (void *)anEnetBase);
#endif
// set default values for NetIface (prio=5, stack=4K, mbox=10 entries)
net_iface_set_defaults(&NetIface, (tcNetDrvr *)mpNetDrvr);
NetIface.mnRxThreadPriority = si.tcpip_priority + 1; // must be higher than stack
memset(&netif, 0, sizeof(netif));
netif_add(&netif, &netconfig.msIpAddr, &netconfig.msNetmask, &netconfig.msGateway,
&NetIface, net_iface_init, tcpip_input);
netif_set_default(&netif);
// some PHY-specific set-up...
phyType = mpNetDrvr->GetPhyType();
// for DP83848, make sure auto-MDIX is enabled
if (phyType == eeNationalDP83848)
{
mpNetDrvr->SetMIIRegister(0x19, (mpNetDrvr->GetMIIRegister(0x19) | 0x8000));
}
// for BCM5221, put LEDs in the proper mode
if (phyType == eeBroadcomBCM5221)
{
mpNetDrvr->SetMIIRegister(0x1A, (mpNetDrvr->GetMIIRegister(0x1A) & ~0xC000));
}
// If PHY is KS8995, try using the SPI to enable a built-in managed Ethernet switch...
if (phyType == eeMicrelKS8995)
{
tcDspSpi::tuFifoData FifoData;
FifoData.mnLword = 0x00020101; // 02=write register, 01=register #1, 01=value to write
if (apSpi) apSpi->WriteData(&FifoData, 1);
}
if (netconfig.mnUseDHCP)
{
if (dhcp_start(&netif) == ERR_OK)
{
tcDspError::report(<strong>FILE</strong>, <strong>LINE</strong>, status ,
"DHCP Initialized");
}
else
{
tcDspError::report(<strong>FILE</strong>, <strong>LINE</strong>, warning,
"DHCP Initialization Failed");
}
// Don't allow any more network activity until DHCP completes...
// NOTE: This will block the thread indefinitely. Depending on the
// nature of the application, it may be necessary to provide
// a timeout, or check for completion at the time the stack is
// to be used. At any rate, do <em>not</em> attempt to use an
// interface while its IP address is still 0.0.0.0.
int count=0;
while (netif_is_up(&netif) == false)
{
TSK_sleep(1000 * mnTicksPerMsec);
// Timeout DHCP and assign default IP address
if (++count > 20)
{
dhcp_stop(&netif);
IP4_ADDR(&netconfig.msIpAddr,
g_ip_addr[0], g_ip_addr[1], g_ip_addr[2], g_ip_addr[3]);
IP4_ADDR(&netconfig.msNetmask,
g_subnet[0], g_subnet[1], g_subnet[2], g_subnet[3]);
IP4_ADDR(&netconfig.msGateway,
g_gw_addr[0], g_gw_addr[1], g_gw_addr[2], g_gw_addr[3]);
netif_set_addr(&netif, netconfig.msIpAddr, &netconfig.msNetmask,
&netconfig.msGateway);
netif_set_up(&netif);
break;
}
}
}
else
{
netif_set_up(&netif);
}
// report network settings
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"Network Address = %d.%d.%d.%d",
netif.ip_addr.addr&0xFF,
(netif.ip_addr.addr&0xFF00) >> 8,
(netif.ip_addr.addr&0xFF0000) >> 16,
(netif.ip_addr.addr&0xFF000000) >> 24);
// ...and some basic status
success = mpNetDrvr->GetPhyStatus(phyStatus);
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"PHY type is %s",
((phyStatus.meType == eeNationalDP83848) ? "National DP83848":
((phyStatus.meType == eeCrystalLanCS8952) ? "Crystal LAN CS8952":
((phyStatus.meType == eeBroadcomBCM5221) ? "Broadcom BCM5221":
((phyStatus.meType == eeMicrelKS8995) ? "Micrel KS8995":
"Unknown")))));
if (success)
{
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"Link is %s, %s Mbps, %s Duplex, MDI %s",
(phyStatus.mbLinkUp ? "Up" : "Down"),
((phyStatus.meSpeed == eeSpeed10Mbps) ? "10":
((phyStatus.meSpeed == eeSpeed100Mbps) ? "100":
((phyStatus.meSpeed == eeSpeed1Gbps) ? "1000": "???"))),
(phyStatus.mbFullDuplex ? "Full" : "Half"),
(phyStatus.mbMdiSwapped ? "Swapped" : "Normal"));
}
// get KS8995 status for all 4 ports via SPI
else if (phyType == eeMicrelKS8995)
{
tcDspSpi::tuFifoData FifoData;
// report status for 4 external ports
for (int port=0; port<4; port++)
{
FifoData.mnLword = 0x00031E00 + (port * 0x00001000);
if (apSpi) apSpi->ReadData(&FifoData, 1);
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"Port %1d: Link is %s, %s Mbps, %s Duplex, MDI %s", port+1,
((FifoData.ms8Bit.mnFifoData & 0x00000020) ? "Up" : "Down"),
((FifoData.ms8Bit.mnFifoData & 0x0000000C) ? "100": "10"),
((FifoData.ms8Bit.mnFifoData & 0x0000000A) ? "Full" : "Half"),
((FifoData.ms8Bit.mnFifoData & 0x00000080) ? "Normal" : "Swapped"));
}
}
// optional, run MityDSPLocator query server
mpNetIFConfigUtil->RunQueryServer(&msNetIf);
// this would be a good place to launch the WINS server if desired as well...
return;
}

  
Generated on Mon Apr 22 2013 11:33:33 for MityDSP Net by  Doxygen Version 1.8.1.1
Copyright © 2009, Critical Link LLC, All rights reserved.