本文是针对《CCS+C6678LE开发记录06:以太网接口测试》的后续研究。
在已经通过测试之后我想研究一下测试用例的实现原理,至少应该明白大致原理。
为了方便贴代码,我将原始实例的代码做了精简;
为了探索其原理,我修改/添加了少量代码。
主要代码如下
-
#include <stdio.h>
-
#include <ti/ndk/inc/netmain.h>
-
#include <ti/sysbios/BIOS.h>
-
#include <ti/sysbios/knl/Task.h>
-
#include <xdc/runtime/Error.h>
-
#include <xdc/runtime/System.h>
-
#include "ti/platform/platform.h"
-
#include "ti/platform/resource_mgr.h"
-
-
static
int counter=
0;
-
static HANDLE hHello=
0;
-
char *HostName =
"TMS320C6678";
-
char *LocalIPAddr =
"169.254.11.119";
// My PC Local IP
-
char *LocalIPMask =
"255.255.255.0";
// Not used when using DHCP
-
char *GatewayIP =
"192.168.2.101";
// Not used when using DHCP
-
char *DomainName =
"demo.net";
// Not used when using DHCP
-
char *DNSServer =
"0.0.0.0";
// Used when set to anything but zero
-
Uint8 clientMACAddress[
6] = {
0x01,
0x02,
0x03,
0x04,
0x0C,
0xEF};
/* MAC Addr */
-
-
-
static void NetworkOpen();
-
static void NetworkClose();
-
static void NetworkIPAddr(IPN IPAddr, uint IfIdx, uint fAdd);
-
extern int dtask_udp_hello();
-
-
void EVM_init()
-
{
-
printf(
"\nEVM_Init()\n");
-
platform_init_flags sFlags;
-
platform_init_config sConfig;
-
memset( (
void *) &sFlags,
0,
sizeof(platform_init_flags));
-
memset( (
void *) &sConfig,
0,
sizeof(platform_init_config));
-
sFlags.pll =
0;
/* PLLs for clocking */
-
sFlags.ddr =
0;
/* External memory */
-
sFlags.tcsl =
1;
/* Time stamp counter */
-
sFlags.phy =
1;
/* Ethernet */
-
sFlags.ecc =
0;
/* Memory ECC */
-
sConfig.pllm =
0;
/* Use libraries default clock divisor */
-
platform_init(&sFlags, &sConfig);
-
}
-
-
Void Hello(UArg arg0, UArg arg1)
-
{
-
while(
1)
-
{
-
printf(
"Hello\n");
-
Task_sleep(
2000);
-
if(counter>=
3)
break;
-
}
-
}
-
-
Void Test(UArg arg0,UArg arg1);
-
-
int main()
-
{
-
Task_Handle task1 = Task_create(Test,
NULL,
NULL);
-
Task_Handle task2 = Task_create(Hello,
NULL,
NULL);
-
if (task1==
NULL || task2==
NULL)
-
{
-
printf(
"Task_create() failed!\n");
-
BIOS_exit(
0);
-
}
-
BIOS_start();
-
}
-
-
Void Test(UArg arg0,UArg arg1)
-
{
-
QMSS_CFG_T qmss_cfg;
-
CPPI_CFG_T cppi_cfg;
-
-
uint32_t coreID = platform_get_coreid();
-
uint32_t master=(coreID==
0)?
1:
0;
-
-
qmss_cfg.master_core = master;
-
qmss_cfg.max_num_desc = MAX_NUM_DESC;
-
qmss_cfg.desc_size = MAX_DESC_SIZE;
-
qmss_cfg.mem_region = Qmss_MemRegion_MEMORY_REGION0;
-
-
cppi_cfg.master_core = master;
-
cppi_cfg.dma_num = Cppi_CpDma_PASS_CPDMA;
-
cppi_cfg.num_tx_queues = NUM_PA_TX_QUEUES;
-
cppi_cfg.num_rx_channels = NUM_PA_RX_CHANNELS;
-
-
res_mgr_init_qmss(&qmss_cfg);
-
res_mgr_init_cppi(&cppi_cfg);
-
res_mgr_init_pass();
-
-
-
int rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
-
if( rc!=
0 )
-
{
-
NC_SystemClose();
-
return;
-
}
-
-
HANDLE hCfg = CfgNew();
-
if( !hCfg )
-
{
-
NC_SystemClose();
-
return;
-
}
-
CfgAddEntry( hCfg,CFGTAG_SYSINFO,CFGITEM_DHCP_HOSTNAME,
0,
strlen(HostName),(UINT8*)HostName,
0);
-
-
CI_IPNET NA;
-
bzero( &NA,
sizeof(NA) );
-
NA.IPAddr = inet_addr(LocalIPAddr);
-
NA.IPMask = inet_addr(LocalIPMask);
-
strcpy( NA.Domain, DomainName );
-
NA.NetType =
0;
-
CfgAddEntry( hCfg, CFGTAG_IPNET,
1,
0,
sizeof(CI_IPNET), (UINT8 *)&NA,
0 );
-
-
CI_ROUTE RT;
-
bzero( &RT,
sizeof(RT) );
-
RT.IPDestAddr =
0;
-
RT.IPDestMask =
0;
-
RT.IPGateAddr = inet_addr(GatewayIP);
-
CfgAddEntry( hCfg, CFGTAG_ROUTE,
0,
0,
sizeof(CI_ROUTE), (UINT8 *)&RT,
0 );
-
-
IPN IPTmp = inet_addr(DNSServer);
-
if( IPTmp )
-
{
-
CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
0,
sizeof(IPTmp), (UINT8 *)&IPTmp,
0 );
-
}
-
-
rc = DBG_WARN;
-
CfgAddEntry(hCfg,CFGTAG_OS,CFGITEM_OS_DBGPRINTLEVEL,CFG_ADDMODE_UNIQUE,
sizeof(uint),(UINT8 *)&rc,
0);
-
-
rc =
8192;
-
CfgAddEntry(hCfg,CFGTAG_IP,CFGITEM_IP_SOCKUDPRXLIMIT,CFG_ADDMODE_UNIQUE,
sizeof(uint),(UINT8 *)&rc,
0);
-
-
do
-
{
-
rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );
-
}
while( rc >
0 );
-
-
CfgFree( hCfg );
-
-
NC_SystemClose();
-
}
-
-
static void NetworkOpen()
-
{
-
hHello = DaemonNew( SOCK_DGRAM,
0,
7,dtask_udp_hello,OS_TASKPRINORM,OS_TASKSTKNORM,
0,
1);
-
}
-
-
static void NetworkClose()
-
{
-
DaemonFree( hHello );
-
}
-
-
static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
-
{
-
IPN IPTmp;
-
if( fAdd )
printf(
"Network Added: ");
-
else
printf(
"Network Removed: ");
-
IPTmp = ntohl( IPAddr );
-
printf(
"If-%d:%d.%d.%d.%d\n", IfIdx,
-
(UINT8)(IPTmp>>
24)&
0xFF,(UINT8)(IPTmp>>
16)&
0xFF,
-
(UINT8)(IPTmp>>
8)&
0xFF, (UINT8)IPTmp&
0xFF );
-
}
-
-
int dtask_udp_hello( SOCKET s, UINT32 unused )
-
{
-
printf(
"TASK execution %d\n",++counter);
-
-
(
void)unused;
-
-
struct timeval tv;
-
tv.tv_sec =
3;
-
tv.tv_usec =
0;
-
setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,&tv,
sizeof(tv));
-
setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,&tv,
sizeof(tv));
-
-
struct sockaddr_in sin1;
-
int sz=
sizeof(sin1);
-
int recvSize;
-
HANDLE hBuffer;
-
unsigned
char* pBuf;
-
while(
1)
-
{
-
recvSize=recvncfrom( s, (
void**)&pBuf,
0, (PSA)&sin1, &sz, &hBuffer );
-
if(recvSize<=
0)
break;
-
sendto( s, pBuf, recvSize,
0, (PSA)&sin1, sz );
-
recvncfree( hBuffer );
-
}
-
-
// Since the socket is still open, return "1"
-
// (we need to leave UDP sockets open)
-
return
1;
-
}
其中EVM_init()函数被设置为在main()函数之前执行,具体设置在一个*.cfg文件中,
部分内容如下
-
var Memory = xdc.useModule(
'xdc.runtime.Memory');
-
var BIOS = xdc.useModule(
'ti.sysbios.BIOS');
-
var Task = xdc.useModule(
'ti.sysbios.knl.Task');
-
var HeapBuf = xdc.useModule(
'ti.sysbios.heaps.HeapBuf');
-
var Log = xdc.useModule(
'xdc.runtime.Log');
-
//...省略...
-
Program.sectMap[
"sharedL2"] =
"DDR3";
-
Program.sectMap[
"systemHeap"] =
"DDR3";
-
Program.sectMap[
".sysmem"] =
"DDR3";
-
Program.sectMap[
".args"] =
"DDR3";
-
Program.sectMap[
".cio"] =
"DDR3";
-
Program.sectMap[
".far"] =
"DDR3";
-
Program.sectMap[
".rodata"] =
"DDR3";
-
Program.sectMap[
".neardata"] =
"DDR3";
-
//...省略...
-
Startup.lastFxns.$add(
'&EVM_init');
-
BIOS.taskEnabled =
true;
-
-
Ecm.eventGroupHwiNum[
0] =
7;
-
Ecm.eventGroupHwiNum[
1] =
8;
-
Ecm.eventGroupHwiNum[
2] =
9;
-
Ecm.eventGroupHwiNum[
3] =
10;
-
Global.IPv6 =
true;
注意其中的
Startup.lastFxns.$add('&EVM_init');
在主函数中执行BIOS_start()会完成一些主动操作
(似乎是因为main函数在DSP中的地位和在PC上不一样)
总之,在执行完EVM_init()完成基本的初始化后,创建我们的主要任务:
Task_Handle task1 = Task_create(Test, NULL, NULL);
Task_Handle task2 = Task_create(Hello, NULL, NULL);
而Test任务则执行了QMSS、CPPI、PA等等的初始化,完成了基本网络配置
启动Network服务后,关联了dtask_udp_hello任务,等待以太网接口的连接
另一边使用PC执行测试,发送字符串进行交互。
因为我们的程序中设置了一个计数器counter
每次发送一个字符串,dtask_udp_hello()就执行一次,counter++
在Hello任务中,一旦发现条件counter>=3满足了就会退出while()循环,它的使命也就终结了
(注意并不是真的终结,因为没有执行KillTask这样的命令,只是Hello任务不再执行任何操作罢了)
这样只剩下Test任务独自运行了
某次测试如下