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.).
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>
using namespace MityDSP;
#define READ_CONFIG_FROM_FLASH 1
#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();
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;
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gateway;
static struct netif netif;
#ifdef READ_CONFIG_FROM_FLASH
tcDspConfig::GetInstance(mpFlash)->GetAppDataOffset());
configutil->GetConfig(&netconfig);
#else
if (useDHCP)
{
IP4_ADDR(&netconfig.
msIpAddr, 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]);
}
tcDspConfig::GetInstance(mpFlash)->GetMACAddress((
unsigned char*)netconfig.
maMACAddress);
#endif
si.tcpip_priority = gnNET_TCP_PRIORITY;
si.nacb_func = lwipAssertReport;
#ifdef USE_645X_EMAC
#else
mpNetDrvr =
new tcNetDrvr_B(g_mac_addr, (
void *)anEnetBase);
#endif
NetIface.mnRxThreadPriority = si.tcpip_priority + 1;
memset(&netif, 0, sizeof(netif));
netif_set_default(&netif);
phyType = mpNetDrvr->GetPhyType();
{
mpNetDrvr->SetMIIRegister(0x19, (mpNetDrvr->GetMIIRegister(0x19) | 0x8000));
}
{
mpNetDrvr->SetMIIRegister(0x1A, (mpNetDrvr->GetMIIRegister(0x1A) & ~0xC000));
}
{
tcDspSpi::tuFifoData FifoData;
FifoData.mnLword = 0x00020101;
if (apSpi) apSpi->WriteData(&FifoData, 1);
}
{
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");
}
int count=0;
while (netif_is_up(&netif) == false)
{
TSK_sleep(1000 * mnTicksPerMsec);
if (++count > 20)
{
dhcp_stop(&netif);
g_ip_addr[0], g_ip_addr[1], g_ip_addr[2], g_ip_addr[3]);
g_subnet[0], g_subnet[1], g_subnet[2], g_subnet[3]);
g_gw_addr[0], g_gw_addr[1], g_gw_addr[2], g_gw_addr[3]);
netif_set_up(&netif);
break;
}
}
}
else
{
netif_set_up(&netif);
}
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);
success = mpNetDrvr->GetPhyStatus(phyStatus);
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"PHY type is %s",
"Unknown")))));
if (success)
{
tcDspError::report(<strong>FILE</strong>,<strong>LINE</strong>, status,
"Link is %s, %s Mbps, %s Duplex, MDI %s",
(phyStatus.mbFullDuplex ? "Full" : "Half"),
(phyStatus.mbMdiSwapped ? "Swapped" : "Normal"));
}
{
tcDspSpi::tuFifoData FifoData;
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"));
}
}
mpNetIFConfigUtil->RunQueryServer(&msNetIf);
return;
}