求助:
TMS320C6678 有两个网口, 我在core0 中调用NDK 的API初始化网络,其中有一句cfgAddEntry(hcfg, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (UNIT *)& NA, 0),应该表示配置端口1,配置完成,程序可以正常使用网络资源。如果把上一句改为cfgAddEntry(hcfg, CFGTAG_IPNET, 0, 0, sizeof(CI_IPNET), (UNIT *)& NA, 0), 也可以正常使用。但是如果core0 调用NDK 的API初始化网络,使用cfgAddEntry(hcfg, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (UNIT *)& NA, 0), 而 同时core 1 调用NDK 的API初始化网络,使用cfgAddEntry(hcfg, CFGTAG_IPNET, 0, 0, sizeof(CI_IPNET), (UNIT *)& NA, 0), 在core0先启动,core1后启动时,core1 会报错:配置MAC address error.而且EMAC channel 的 id也是一样的,是什么原因啊?
c6678的两个网口是如何同时使用的, 能不能多个cpu core 同时使用同一个网口, 请赐教。
weifeng guo:
回复 Andy Yin:
您好,
首先非常感谢您的回答。我所碰到的问题是MAC address 出错,是不是因为两个核的NDK所使用的EMAC channel 相同造成的呢?另外,我在NDK USER'S GUIDE 和 NDK software programmer's reference guide 两篇文档中好像没发现有设置EMAC channel 的API 呀。我把我的代码和错误信息贴在下面,还想麻烦您看一下,指出问题所在。
使用的核为 CORE_0 和 CORE_1 ,两个核单独启动 即: Ipc.procSync = Ipc.ProcSync_NONE; // in file.cfg
错误信息如下:
[C66xx_0] EVM in StaticIP mode at 192.168.0.218[C66xx_0] QMSS successfully initialized [C66xx_0] CPPI successfully initialized [C66xx_0] PASS successfully initialized [C66xx_0] Ethernet subsystem successfully initialized [C66xx_0] eventId : 48 and vectId : 7 [C66xx_0] Registration of the EMAC Successful, waiting for link up ..[C66xx_0] run in daemon [C66xx_0] receive : [C66xx_1] QMSS successfully initialized [C66xx_1] CPPI successfully initialized [C66xx_1] PASS successfully initialized [C66xx_1] Ethernet subsystem successfully initialized [C66xx_1] eventId : 48 and vectId : 7 [C66xx_1] Timeout waiting for reply from PA to Pa_addMac command[C66xx_1] Add_MACAddress failed [C66xx_1] Error: Unable to register the EMAC
CORE_0 网络配置代码:
int RunUDP_sever()
{
HANDLE hCfg;
CI_IPNET NA;
IPN IPTmp;
int nStatus, nRecv;
char *HostName = "UDP_SEVER_0";
char *DomainName = "demo0.net"; /* Not used when using DHCP */
char *DNSServer = "0.0.0.0"; /* Used when set to anything but zero */
nStatus = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
if(nStatus != NC_OPEN_SUCCESS)
{
#ifdef UDP_SEVER_DEBUG
printf("NC_SystemOpen Failed (%d)\n",nStatus);
#endif
goto close_n_exit;
}
hCfg = CfgNew();
if( !hCfg )
{
#ifdef UDP_SEVER_DEBUG
printf("Unable to create configuration\n");
#endif
goto close_n_exit;
}
/* Validate the length of the supplied names */
if( strlen( DomainName ) >= CFG_DOMAIN_MAX ||
strlen( HostName ) >= CFG_HOSTNAME_MAX )
{
#ifdef UDP_SEVER_DEBUG
printf("Domain or Host Name too long\n");
#endif
goto close_n_exit;
}
/* Add our global hostname to hCfg (to be claimed in all connected domains) */
CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0, strlen(HostName), (UINT8 *)HostName, 0 );
/* Setup an IP address to this EVM */
bzero( &NA, sizeof(NA) );
NA.IPAddr = inet_addr("192.168.0.218");
NA.IPMask = inet_addr("255.255.255.0");
strcpy( NA.Domain, DomainName );
/* Add the address to interface 1 */
CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (UINT8 *)&NA, 0 );
/* Manually add the DNS server when specified */
IPTmp = inet_addr(DNSServer);
if( IPTmp )
CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER, 0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
/* Set debug message level */
nStatus = DBG_WARN;
CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL, CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&nStatus, 0 );
// UDP Receive limit
nRecv = 8192;
CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,
CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&nRecv, 0 );
do
{
nStatus = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );
} while( nStatus > 0 );
#ifdef UDP_SEVER_DEBUG
platform_write ("Shutting things down\n");
#endif
close_n_exit:
CfgFree( hCfg );
NC_SystemClose();
return 0;
}
static HANDLE hDaemon=0;
static void NetworkOpen()
{
hDaemon = DaemonNew( SOCK_DGRAM, 0, 1062, RecvImg, OS_TASKPRIHIGH, OS_TASKSTKNORM, 0, 1 );//7//OS_TASKPRINORM
}
CORE_1网络配置代码:
int UDP_Sever(){
HANDLE hCfg; CI_IPNET NA; IPN IPTmp; int nStatus, nRecv; char *HostName = "UDP_SEVER"; char *DomainName = "demo.net"; /* Not used when using DHCP */ char *DNSServer = "0.0.0.0"; /* Used when set to anything but zero */
nStatus = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT ); if(nStatus != NC_OPEN_SUCCESS) {#ifdef UDP_SEVER_DEBUG printf("NC_SystemOpen Failed (%d)\n",nStatus);#endif goto close_n_exit; }
hCfg = CfgNew(); if( !hCfg ) { #ifdef UDP_SEVER_DEBUG printf("Unable to create configuration\n");#endif goto close_n_exit; }
/* Validate the length of the supplied names */ if( strlen( DomainName ) >= CFG_DOMAIN_MAX || strlen( HostName ) >= CFG_HOSTNAME_MAX ) {#ifdef UDP_SEVER_DEBUG printf("Domain or Host Name too long\n");#endif goto close_n_exit; }
/* Add our global hostname to hCfg (to be claimed in all connected domains) */ CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0, strlen(HostName), (UINT8 *)HostName, 0 );
/* Setup an IP address to this EVM */ bzero( &NA, sizeof(NA) ); NA.IPAddr = inet_addr("192.168.0.217"); NA.IPMask = inet_addr("255.255.255.0"); strcpy( NA.Domain, DomainName );
/* Add the address to interface 1 */ CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0, sizeof(CI_IPNET), (UINT8 *)&NA, 0 );
/* Manually add the DNS server when specified */ IPTmp = inet_addr(DNSServer); if( IPTmp ) CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER, 0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
/* Set debug message level */ nStatus = DBG_WARN; CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL, CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&nStatus, 0 );
// UDP Receive limit nRecv = 8192; CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT, CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&nRecv, 0 );
do { nStatus = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr ); } while( nStatus > 0 );
#ifdef UDP_SEVER_DEBUG platform_write ("Shutting things down\n");#endif
close_n_exit: CfgFree( hCfg ); NC_SystemClose(); return 0;}
static HANDLE hDaemon=0;static void NetworkOpen(){ // Create our local server hHello = DaemonNew( SOCK_DGRAM, 0, 7, dtask_udp_hello, OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 ); }
Thomas Yang1:
回复 weifeng guo:
您好
请单步跟踪nimu_eth.c中
Add_MACAddress函数和paReturn_t Pa_addMac函数 获取具体失败的信息
比如Queue资源不够 等等
谢谢!
Andy Yin:
回复 Thomas Yang1:
weifeng guo您好,
请问该问题解决了么,能否写一下你是如何解决的,非常感谢!
weifeng guo:
回复 Andy Yin:
非常感谢 Andy Yin 的关注:
这个问题还没解决,Thomas Yang 提的方案我会尝试一下, 解决的话我我会及时回复,分享的。
顺便问一下,如果CORE_0 使用网络端口0, CORE_1使用网络端口1,那么在调用NDK的API 配置网络时,有没有哪个参数是用来指定使用的端口号的?
再次感谢!
Andy Yin:
回复 weifeng guo:
您好,
在使用不同的port发送包时,在应用层要做的是配置switch及ALE entry,使携带不同目的地址的包经过匹配后发往不同的port,而不是直接通过操作switch port。
weifeng guo:
回复 Marvin Liang:
Marvin Liang,
非常感谢您的回答和建议。我的初衷是6678中的一个核专注于接收数据,另一个核专注于发送数据。当前的应用需求是:两个工业相机通过网络采用UDP协议向一个TMS320C6678传送图像数据(总带宽要求达到 60MB/s),而 C6678在对图像完成处理后,将结果图像通过网络采用TCP协议传给PC机。 由于一幅图像的大小为1.5MB,若接收缓冲区为6幅图像,那么就需要9MB的存储空间,很显然,接收缓冲区要放到外存。那么CPU在接收网络数据时,应该是忙于将数据传到外存(目前我还不清楚在使用NDK编程时,能否使用EDMA实现该数据的传输功能),所以希望由另一个核将结果图像发送出去,以免干扰图像数据的接收。至于多个核如何协作处理以太网数据包,要根据具体的处理算法来定。
NDK的文档中确实没有提到其在多核的应用,但也没明确说不能应用于多核,而我又接触多核DSP时间不长,所以有许多困惑,而您回答让我对6678网络这块又有了更好的了解,再次真诚的感谢!
Marvin Liang:
回复 weifeng guo:
weifeng guo,
根据你的应用场景,数据量较大60MBps=480Mbps,。传输图像,相信是大包为主,但480Mbps的流量对于NDK整个协议栈来说开销不会小,所以这是你为什么选择多核跑NDK的原因?
因为NDK提供了较为完整的TCP/IP协议栈,所以协议栈本身对内核MIPS有消耗。你的应用似乎只需要UDP和TCP?如果你们要求的网络协议比较单一,可否不用NDK,自己实现简单的UDP/TCP 封装/剥离 功能?
如果这样,你们可以实现如下比较高效的收发路径:
RX: SGMII/CPSW/NETCP–(PKTDMA)->SL2–(EDMA)->DDR
TX: DDR–(PKTDMA)–>NETCP/CPSW/SGMII
当然,你可以继续移植NDK到多核,只是效率相对较低,但不用自己开发代码来处理协议。因为我不清楚你们多个核如何协作处理以太网数据包,所以不能给你更多建议。