TI的TCP/IP协议栈--NDK
这是之前用TI的DM642做视频编码器用到的网络协议栈,源码TI官网上有的下载。维基网上也有关于NDK的一些技术文档,都是英文的,看了费劲。
看这个之前我对TCP/IP协议几乎不了解,拿到这个就开始看英文文档,天昏地暗的,边看边整理些东西,没基础真的痛苦,硬着头皮看吧。下面都是我边看边整理的,怕丢了,放到这,以后还有用。
一、NDK中创建任务的方法:
1、用标准的DSP/BIOS API
- struct TSK_Attrs ta;
- ta = TSK_ATTRS;
- ta.priority = OS_TASKPRINORM;
- ta.stack = 0;
- ta.stacksize = stacksize;
- ta.stackseg = 0;
- ta.environ = 0;
- ta.name = "TaskName";
- ta.exitflag = 0;
- hMyTask = TSK_create( (Fxn)entrypoint, &ta, arg1, arg2, arg3 );
复制代码
2、用NDK的任务抽象API
- hMyTask = TaskCreate( entrypoint, "TaskName", OS_TASKPRINORM, stacksize, arg1, arg2, arg3 );
- In both cases, hMyTask is a handle to a DSP/BIOS TSK task thread.
复制代码
二、内存分配
应用程序在分配内存时最好使用标准的malloc()/free()函数,或者使用DSP/BIOS来分配。
三、NDK初始化和配置
1、必须包含NETCTRL.LIB,NETCTRL模块是协议栈初始化、配置和事件调度的核心。
2、由DSP/BIOS创建的线程是程序的入口点,并且最终成为NETCTRL调度线程。这个控制线程直到协议栈关闭才返回给调用者。
3、在调用其他任何协议栈API之前必须先调用NC_SystemOpen()函数。它初始化协议栈及其所需内存环境。它的两个参数Priority和OpMode分别决定调度任务的优先级和调度器何时开始执行。
Priority包括NC_PRIORITY_LOW 和 NC_PRIORITY_HIGH两种,
OpMode包括NC_OPMODE_POLLING 和 NC_OPMODE_INTERRUPT两种,大部分情况使用interrupt模式,而polling模式会持续运行,当使用polling模式时,优先级必须设为低(NC_PRIORITY_LOW)。
4、使用实例:
- //
- // THIS IS THE FIRST THING DONE IN AN APPLICATION!!
- //
- rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
- if( rc )
- {
- printf("NC_SystemOpen Failed (%d)/n",rc);
- for(;;);
- }
复制代码
5、系统配置,包括以下参数:
- · Network Hostname
- · IP Address and Subnet Mask
- · IP Address of Default Routes
- · Services to be Executed (DHCP, DNS, HTTP, etc.)
- · IP Address of name servers
- · Stack Properties (IP routing, socket buffer size, ARP timeouts, etc.)
复制代码
系统配置开始时调用CfgNew()来创建配置句柄。
配置好之后调用NC_NetStart()函数,该函数有4个参数,配置句柄,指向开始回调函数的指针,指向结束函数的指针,指向IP地址事件的函数。开始和结束函数都只被调用一次。开始函数在初始化结束准备执行网络应用程序时调用,结束函数在系统完全关闭时调用,意味着协议栈将不能执行网路应用。IP地址事件函数能够多次被调用。
NC_NetStart()到系统关闭才返回一个关闭代码。
- //
- // Boot the system using our configuration
- //
- // We keep booting until the function returns 0. This allows
- // us to have a "reboot" command.
- //
- do
- {
- rc = NC_NetStart( hCfg, NetworkStart, NetworkStop, NetworkIPAddr );
- } while( rc > 0 );
- As an example of a network start callback, the NetworkStart() function below opens a user SMTP server
- application by calling an open function to create the main application thread.
- //
- // NetworkStart
- //
- // This function is called after the configuration has booted
- //
- static SMTP_Handle hSMTP;
- static void NetworkStart( )
- {
- // Create an SMTP server
- task hSMTP = SMTP_open( );
- }
- //
- // NetworkStop
- //
- // This function is called when the network is shutting down
- //
- static void NetworkStop()
- {
- // Close our SMTP server task
- SMTP_close( hSMTP );
- }
复制代码
NetworkIPAddr()函数通常用来同步网络任务,该网络任务需要在执行前设置一个本地IP地址。
- void NetIPCb( IPN IPAddr, uint IfIndex, uint fAdd );
- IPAddr 增加或者移除的IP地址
- IfIndex 外设接口获取或者移除IP地址的标识
- fAdd 增加一个IP地址时设为1,移除IP地址时设为0
- //
- // NetworkIPAddr
- //
- // This function is called whenever an IP address binding is
- // added or removed from the system.
- //
- static void NetworkIPAddr( IPN IPAddr, uint IfIdx, uint fAdd )
- {
- IPN IPTmp;
- if( fAdd )
- printf("Network Added: ");
- else
- printf("Network Removed: ");
- // Print a message
- 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 );
- }
复制代码
6、关闭协议栈的方法:
①手动关闭,NC_NetStop(1)重启网络栈,NC_NetStop(0)关闭网络栈。
②当检测到致命错误时关闭,NC_NetStop(-1)。
- // We do not want the stack to abort on any error禁止错误引起的关闭
- uint rc = DBG_NONE;
- CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGABORTLEVEL,
- CFG_ADDMODE_UNIQUE, sizeof(uint), (UINT8 *)&rc, 0 );
复制代码
7、追踪服务状态
当使用NETTOOLS库时,NETTOOLS状态回调函数被引入,这个回调函数追踪被配置使能的服务的状态。状态回调函数有两级,第一个回调由NETTOOLS服务生成,当服务状态改变时它调用配置服务提供者。然后配置服务提供者增加它自己的状态到报告中,并且调用应用程序回调函数。当应用程序增加服务到系统配置中时,一个指向应用程序回调的指针被提供。
- void StatusCallback( uint Item, uint Status, uint Code, HANDLE hCfgEntry )
- Item Item value of entry changed被更改的入口的项目值
- Status New status新状态
- Code Report code (if any)报告代码
- hCfgEntry Non-Referenced HANDLE to entry with status change不引用
复制代码
实例:
- //
- // Service Status Reports
- //
- static char *TaskName[] = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" }; //不能改变,在netcfg.h中定义
- static char *ReportStr[] = { "","Running","Updated","Complete","Fault" }; //不能改变,在nettools.h中定义
- static char *StatusStr[] = { "Disabled", "Waiting", "IPTerm", "Failed", "Enabled" }
- static void ServiceReport( uint Item, uint Status, uint Report, HANDLE h )
- {
- printf( "Service Status: %-9s: %-9s: %-9s: %03d/n",
- TaskName[Item-1], StatusStr[Status],
- ReportStr[Report/256], Report&0xFF );
- }
复制代码
以上函数打印的最后一个值是答应通过Report传递的低8位的值,这个值是固定的,大部分情况下这个值不需要。通常,如果服务成功,它报告Complete,失败,他报告Fault。对于那些不会结束的服务(例如,当IP分配启动时,DHCP客户端会持续运行),Report的高位字节意味着Running,而服务特定的低字节必须被用来指定当前状态。
For example, the status codes returned in the 8 least significant bits of Report when using the DHCP client service are:
- DHCPCODE_IPADD Client has added an IP address
- DHCPCODE_IPREMOVE IP address removed and CFG erased
- DHCPCODE_IPRENEW IP renewed, DHCP config space reset
复制代码
大部分情况下不必去核对这些状态报告代码,除非以下情况:
当使用DHCP客户端来配置协议栈,DHCP客户端控制CFGTAG_SYSINFO标签空间的前256个入口。这些入口与这256个DHCP操作标签通信。应用程序可以检查DHCPCODE_IPADD或者DHCPCODE_IPRENEW返回代码以便它能够读或者改变通过DHCP客户端获得的信息。
8、不使用DHCP client时,手动配置DNS的IP地址方法如下:
- IPN IPTmp;
- // Manually add the DNS server "128.114.12.2"
- IPTmp = inet_addr("128.114.12.2");
- CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
- 0, sizeof(IPTmp), (UINT8 *)&IPTmp, 0 );
复制代码
如果以上代码被加到使用DHCP的应用程序中,当DHCP执行状态更新时这个入口将会被清除。
[color=rgb(51, 102, 153) !important]
|