CCS+C6678LE開發記錄08:乙太網介面測試示例之程式碼研究
阿新 • • 發佈:2019-01-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任務獨自運行了
某次測試如下
本文原創,博文地址