Spru 523 K
Spru 523 K
Spru 523 K
User's Guide
Preface ........................................................................................................................................ 5
1 Overview ............................................................................................................................. 7
1.1 Introduction ................................................................................................................... 8
1.2 Rebuilding NDK Libraries ................................................................................................... 9
1.3 NDK Stack Library Design .................................................................................................. 9
1.3.1 Design Philosophy .................................................................................................. 9
1.3.2 Control Flow ....................................................................................................... 10
1.3.3 Library Directory Structure ....................................................................................... 10
1.3.4 The STACK Library ............................................................................................... 11
1.3.5 NETTOOL Libraries ............................................................................................... 12
1.3.6 OS Library .......................................................................................................... 12
1.3.7 HAL Libraries ...................................................................................................... 12
1.3.8 NETCTRL Libraries ............................................................................................... 12
1.4 NDK Programming APIs................................................................................................... 14
1.4.1 Operating System Abstraction ................................................................................... 14
1.4.2 Sockets and Stream IO API...................................................................................... 14
1.4.3 NETTOOL Services and Support Functions ................................................................... 14
1.4.4 Internal Stack API ................................................................................................. 14
1.4.5 Hardware Adaptation Layer API ................................................................................. 14
1.5 NDK Software Directory Structure ....................................................................................... 15
1.5.1 NDK Include File Directory ....................................................................................... 15
1.5.2 Tool Programs ..................................................................................................... 16
1.5.3 Windows and Linux Test Utilities ................................................................................ 16
1.5.4 Example Programs ................................................................................................ 16
1.6 Configuring NDK Modules ................................................................................................ 16
2 Network Application Development ........................................................................................ 17
2.1 Configuring the NDK with C Code ....................................................................................... 18
2.1.1 Required RTOS Objects.......................................................................................... 18
2.1.2 Include Files ....................................................................................................... 18
2.1.3 Library Files ........................................................................................................ 18
2.1.4 System Configuration ............................................................................................ 18
2.1.5 NDK Initialization .................................................................................................. 26
2.1.6 Adding NDK Hooks Using ACD Support ....................................................................... 29
2.2 Configuring the NDK with XGCONF ..................................................................................... 31
2.2.1 Opening the XGCONF Configuration Editor ................................................................... 33
2.2.2 Adding a Module to Your Configuration ........................................................................ 35
2.2.3 Setting Properties for a Module ................................................................................. 35
2.2.4 Adding an Instance for a Module ................................................................................ 36
2.2.5 Saving Changes to the Configuration .......................................................................... 36
2.2.6 Linked Libraries Configuration ................................................................................... 37
2.2.7 Global Scheduling Configuration ................................................................................ 37
2.2.8 Global Buffer Configuration ...................................................................................... 39
2.2.9 Global Hook Configuration ....................................................................................... 39
2.2.10 Global Debug Configuration .................................................................................... 40
2.2.11 Advanced Global Configuration ................................................................................ 41
List of Figures
1-1. Components of a NDK-Enabled Application ............................................................................. 8
1-2. Stack Control Flow ......................................................................................................... 10
2-1. C/C++ Perspective Icon .................................................................................................. 33
2-2. NDK Modules in Available Products List ................................................................................ 34
2-3. Adding a Module to the Configuration ................................................................................... 35
2-4. Module Properties .......................................................................................................... 35
2-5. DHCP Server Instance .................................................................................................... 36
2-6. Configuring the IP Module ................................................................................................ 42
List of Tables
A-1. Document Revision History ............................................................................................... 64
Notational Conventions
This document uses the following conventions:
• Program listings, program examples, and interactive displays are shown in a special typeface.
• In syntax descriptions, the function or macro appears in a bold typeface and the parameters appear in
plainface within parentheses. Portions of a syntax that are in bold should be entered as shown;
portions of a syntax that are within parentheses describe the type of information that should be
entered.
• Macro names are written in uppercase text; function names are written in lowercase.
NOTE: The location of NDK files referenced in this document will vary depending on the type of
installation your performed to obtain the NDK component. If you installed a SimpleLink™
SDK, the files are likely to be located in your <SDK_INSTALL_DIR>/sources/ti/ndk
directory. If you installed some other type of SDK, the files are likely to be located in your
<NDK_INSTALL_DIR>/packages/ti/ndk directory. For simplicity, this document refers to
the directories beginning at the /ti/ndk level, which is common to all installations.
Information about the TI-RTOS Kernel, which may be used with NDK applications, can be found in the TI-
RTOS Kernel (SYS/BIOS) User's Guide (SPRUEX3) and the SYS/BIOS main page of the TI Embedded
Processors Wiki.
The following documents describe Cortex™-A8 and ARM9 devices and related support tools. Many of
these documents can be found on the Internet at http://www.ti.com.
SPNU151— ARM Optimizing C/C++ Compiler User's Guide
SPNU118— ARM Assembly Language Tools User's Guide
SPRUH73— AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual
Cortex-A8 wiki page— on the TI Embedded Processors Wiki
ARM9 wiki page— on TI's Embedded Processors Wiki
Sitara ARM Microprocessors forum— in TI's E2E Community
Trademarks
SimpleLink, Cortex are trademarks of Texas Instruments.
ARM is a registered trademark of Texas Instruments.
Windows is a registered trademark of Microsoft.
Overview
This chapter introduces the Network Developer's Kit (NDK) by providing a brief overview of the purpose
and construction of the NDK, along with hardware and software environment specifics in the context of
NDK deployment. This Network Developer's Kit (NDK) Software User's Guide serves as an introduction to
both the NDK and to developing network applications.
1.1 Introduction
The Network Developer's Kit (NDK) is a platform for development and demonstration of network enabled
applications on TI embedded processors. The code included in this NDK release is generic C code which
runs on a variety of TI devices.
Within the SimpleLink SDK, the Network Services SlNetSock module configures the NDK as the network
stack for wired Ethernet communications.
The NDK stack serves as a rapid prototyping platform for the development of network and packet
processing applications. It can be used to add network connectivity to existing applications for
communications, configuration, and control. Using the components provided in the NDK, developers can
quickly move from development concepts to working implementations attached to the network.
In Figure 1-1, the user application can make calls using the standard BSD sockets APIs, or it can directly
call into the SlNetSock layer to communicate with a network connection. The SlNetSock layer is a stack-
independent layer between the user application and the service-specific stacks.
Within the SimpleLink SDK, the Network Services SlNetSock module configures the NDK as the network
stack for wired Ethernet communications. The "SlNetIfNDK" is the implementation of the SlNetSock
interface for the NDK.
The NDK stack's settings may be configured at run time by making calls to the NDK's Cfg*() functions.
The NDK is designed to provide a platform-independent, device-independent, and RTOS-independent API
interface for use by the application. Many of the API modules described in this document and in the TI
Network Developer's Kit (NDK) API Reference Guide (SPRU524) are rarely used by applications. Instead
they are available to those who are writing device drivers and network stacks.
A user application typically uses the following APIs provided by the NDK:
• Cfg*() functions add settings to the configuration database that determine which network services will
be available to the application. For details, see the TI Network Developer's Kit (NDK) API Reference
Guide (SPRU524).
• NC_*() functions cause the network services system to be initialized, started, and stopped. For
details, see the TI Network Developer's Kit (NDK) API Reference Guide (SPRU524).
• TaskCreate() or pthread*() functions to handle application threading using POSIX. Internally, POSIX
can use any RTOS supported for the target device by the SimpleLink SDK. For most targets, this
includes TI-RTOS Kernel and FreeRTOS. For details, see Section 2.3.
• NDK socket APIs to perform socket actions such as accept, send, and receive. For a pure NDK
application, these are the BSD-like NDK_*() functions. For SimpleLink SDK applications, you can use
the standard BSD APIs provided via SlNetSock. For details, see the TI Network Developer's Kit (NDK)
API Reference Guide (SPRU524).
NOTE: With the exception of calling TaskCreate() to create a new sockets thread, NDK applications
should no longer make calls to the Task*() functions that directly access the Task threads
provided by the TI-RTOS Kernel. This is because the NDK itself uses POSIX pthread calls.
While internally the POSIX threading APIs may be using TI-RTOS Kernel, calls to pthread
are not compatible with calls to the TI-RTOS Kernel's Task module.
NOTE: The location of NDK files referenced in this document will vary depending on the type of
installation your performed to obtain the NDK component. If you installed a SimpleLink SDK,
the files are likely to be located in your <SDK_INSTALL_DIR>/sources/ti/ndk directory.
If you installed some other type of SDK, the files are likely to be located in your
<NDK_INSTALL_DIR>/packages/ti/ndk directory. For simplicity, this document refers to
the directories beginning at the /ti/ndk level, which is common to all installations.
Pre-built linkable libraries and source code are provided for each of the libraries that make up the NDK in
the /ti/ndk directory tree. The pre-built libraries are in a lib subdirectory of the directory for each library.
See Section 1.5 for more about the directory tree.
• Both IPv4 and IPv6 libraries are provided. Filenames that do not include "ipv4" are compiled for IPv6.
However, in the /ti/ndk/stack/lib directory, filenames that do not include "6" are compiled for IPv4.
• The NETCTRL library comes in "min", regular, and "full" versions. For example, netctrl_min, netctrl,
and netctrl_full. See Section 1.3.8 for details.
• The OS library comes in TI-RTOS Kernel ("os" and "os_sem") and FreeRTOS ("os_freertos" and
"os_sem_freertos") versions.
• Libraries with Jumbo Frame support (for packet sizes larger than 1500 bytes) are not included in the
NDK installation. If you want NDK libraries with Jumbo Frame support enabled, you will need to
#define the _INCLUDE_JUMBOFRAME_SUPPORT pre-processor definition and rebuild the libraries
as described in the Rebuilding the NDK Core topic in the TI Embedded Processors Wiki.
The file extensions for pre-built libraries provided with the NDK include the following:
.aa8fg For Cortex-A8 targets (ELF format, little endian, GNU compiler)
.aa9fg For Cortex-A9 targets (ELF format, little endian, GNU compiler)
.aa15fg For Cortex-A15 targets (ELF format, little endian, GNU compiler)
.ae9 For ARM9 targets (ELF format, little endian, TI compiler)
.ae66 For C66x targets (ELF format, little endian, TI compiler)
.ae674 For C674x targets (ELF format, little endian, TI compiler)
.aea8f For Cortex-A8 targets (ELF format, little endian, TI compiler, does not use hardware-based
floating point support, for legacy application support)
.aea8fnv For Cortex-A8 targets (ELF format, little endian, TI compiler, uses hardware-based vector
floating point support, recommended over .aea8f)
.aem3 For Cortex-M3 targets (ELF format, little endian, TI compiler)
.am3g For Cortex-M3 targets (ELF format, little endian, GNU compiler)
.arm3 For Cortex-M3 targets (ELF format, little endian, IAR compiler)
.aem4 For Cortex-M4 targets (ELF format, little endian, TI compiler)
.am4g For Cortex-M4 targets (ELF format, little endian, GNU compiler)
.arm4 For Cortex-M4 targets (ELF format, little endian, IAR compiler)
.aem4f For Cortex-M4F floating point targets (ELF format, little endian, TI compiler)
.am4fg For Cortex-M4F floating point targets (ELF format, little endian, GNU compiler)
.arm4f For Cortex-M4F floating point targets (ELF format, little endian, IAR compiler)
The libraries provided with the NDK are platform independent. That is, versions of these libraries are
provided for all platforms. Any hardware-dependent libraries that exist only for certain platforms are
distributed in the appropriate NDK Support Package (NSP), which you download separately from the NDK.
The NDK installation includes all source files and full support for rebuilding its libraries. In order to rebuild
the NDK libraries, please see the instructions in the Rebuilding the NDK Core topic in the TI Embedded
Processors Wiki.
stk_ppp, stk6_ppp Stack with PPP, NIMU, VLAN, and Raw Ethernet Socket support.
Variants support IPv4 or IPv6. No support for NAT, PPPoE and LL
architectures.
stk_ppp_pppoe, Stack with PPP, PPPoE, NIMU, VLAN, and Raw Ethernet Socket
stk6_ppp_pppoe support. Variants support IPv4 or IPv6. No support for NAT and LL
architectures.
1.3.6 OS Library
These libraries form a thin adaptation layer that maps some abstracted OS function calls to POSIX and
DPL function calls. This includes Task thread management, memory allocation, packet buffer
management, printing, logging, critical sectioning, and jumbo packet buffer management.
The OS libraries are provided in the /ti/ndk/os/lib directory. The "os" library is the OS Adaptation Layer
library with priority exclusion. The "os_sem" library uses semaphore exclusion, instead. See Section 1.4.1
for more information.
Library Description
eth_stub/lib/hal_eth_stub Ethernet Stub Driver
ser_stub/lib/hal_ser_stub Serial Stub Driver
timer_bios/lib/hal_timer Timer Driver Using SYS/BIOS Timer object
userled_stub/lib/hal_userled_stub User LED Stub Driver
See Section 1.4.5 for information about the HAL APIs. The HAL is also discussed in the TI Network
Developer's Kit (NDK) API Reference Guide (SPRU524) and the NDK Support Package Ethernet Driver
Design Guide (SPRUFP2).
registered with the NIMU core. Initialize the VLAN module in the NDK core stack.
• De-initialize the NIMU core during stack shutdown, which in turn cycles through all the registered
device drivers and shuts them down.
• Poll all the registered devices periodically so as to allow them to perform any routine maintenance
activity, such as link management. Also, checks for any events, like packet reception, from any of the
registered devices.
• Initialize the IPv6 Stack if built in during stack bring up.
The NETCTRL library is designed to support "potential" stack features that the user may desire within their
application (e.g. DHCP server). However, the drawback of this is that the code for such features will be
included in the executable even if the application never uses the features. This results in a larger footprint
than is usually necessary.
To minimize this problem, the following different versions of the NETCTRL library are available in the
/ti/ndk/netctrl/lib directory:
• netctrl_min. This minimal library enables only the DHCP client. It should be used when a minimal
footprint is desired.
• netctrl. This "standard" version of the NETCTRL library enables the following features and has a
medium footprint:
– Telnet server
– HTTP server
– DHCP client
• netctrl_full. This "full" library enables all supported NETCTRL features, which include:
– Telnet server
– HTTP server
– NAT server
– DHCP client
– DHCP server
– DNS server
All versions of NETCTRL support NIMU, VLAN, and Raw Ethernet Socket. Each of these NETCTRL
library versions is built for both pure IPv4 as well as IPv6.
If you configure the NDK in Code Composer Studio (CCS) with the XGCONF configuration tool, the
appropriate NETCTRL library is automatically selected based on the modules you enable.
You can rebuild the NETCTRL library to include only features you want to use. To do this, edit the
package.bld file in the/ti/ndk/netctrl directory, and redefine any of the following options. For information
about rebuilding the NDK libraries, see the Rebuilding the NDK Core topic in the TI Embedded Processors
Wiki.
• NETSRV_ENABLE_TELNET
• NETSRV_ENABLE_HTTP
• NETSRV_ENABLE_NAT
• NETSRV_ENABLE_DHCPCLIENT
• NETSRV_ENABLE_DHCPSERVER
• NETSRV_ENABLE_DNSSERVER
Directory Description
config Used internally. Contains packages for all the modules configured by XGCONF and
used by application code.
docs Contains Doxygen documentation for NDK internals (for advanced users only).
hal Contains NDK driver libraries and source code. See Section 1.3.7.
inc NDK include file directory. See Section 1.5.1.
netctrl Contains libraries and source code for network startup and shutdown, including
special versions for various subsets of network functionality. See Section 1.3.8
nettools Contains libraries and source code for network tools, such as DHCP, DNS, and
HTTP. See Section 1.4.3.
os Contains libraries and source code for the OS Adaptation Layer. See Section 1.3.6.
stack Contains libraries and source code for the network stack. See Section 1.3.4.
tools Contains libraries and source code for several network tools. See Section 1.5.2.
winapps Contains client test applications for Windows® and Linux command-prompt use. Both
source code and executables are provided. See Section 1.5.3.
Filename Description
netmain.h Master include file for applications (stacksys.h, _nettool.h, _netctrl.h)
stacksys.h Main include file (minus the end-application oriented include files) (usertype.h,
serrno.h, socket.h, osif.h, hal.h)
_netctrl.h Includes references for the NETCTRL scheduler library
_nettool.h Includes references for all the services in the NETTOOL library
_oskern.h Includes kernel level OS functions declarations
_stack.h Includes all low level STACK interface functions
serrno.h Standard error values
socket.h Prototypes for all file descriptor based functions
stkmain.h Include file used by low-level modules (not for use by applications)
usertype.h Standard types used by the stack
Additional include files are provided in the subdirectories for the HAL, NETCTRL, NETTOOLS, OS,
STACK, and TOOLS libraries.
NOTE: You should not mix configuration methods. If a project uses both methods, there will be
conflicts between the two configurations.
This chapter describes how to begin developing network applications. It discusses the issues and
guidelines involved in the development of network applications using the NDK libraries.
NOTE: Do not mix configuration methods. If a project uses both methods, there will be conflicts
between the two configurations.
rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
if (rc) {
DbgPrintf(DBG_ERROR, "NC_SystemOpen Failed (%d)\n");
}
main_exit:
NC_SystemClose();
Note that the CLIENT example program in the example applications uses a form of this code. Now, when
a DHCP client is used, it clears and resets the contents of the part of the configuration it controls. This
includes the DNS server addresses. Therefore, if the above code was added to an application that used
DHCP, the entry would be cleared whenever DHCP executed a status update.
To share this configuration space with DHCP (or to read the results of a DHCP configuration), the DHCP
status callback report codes must be used. The status callback function was introduced in Section 2.1.5.5.
When DHCP reports a status change, the application knows that the DHCP portion of the system
configuration has been reset.
The following code also appears in the CLIENT example program. This code manually adds a DNS server
address when the DHCP client is in use. Note that this code is part of the standard service callback
function that is supplied to the configuration when the DHCP client service is specified.
//
// Service Status Reports
//
static char *TaskName[] = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };
static char *ReportStr[] = { "","Running","Updated","Complete","Fault" };
static char *StatusStr[] = { "Disabled","Waiting","IPTerm", "Failed","Enabled" };
static void ServiceReport( uint32_t Item, uint32_t Status, uint32_t Report, void *h )
{
printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",
TaskName[Item-1], StatusStr[Status], ReportStr[Report/256], Report&0xFF );
if( IPTmp )
CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,
0, sizeof(IPTmp), (unsigned char *)&IPTmp, 0 );
}
}
2.1.4.3 Shutdown
There are two ways the stack can be shut down. The first is a manual shutdown that occurs when an
application calls NC_NetStop(). Here, the calling argument to the function is returned to the NETCTRL
thread as the return value from NC_NetStart(). Therefore, for the example code, calling NC_NetStop(1)
reboots the network stack, while calling NC_NetStop(0) shuts down the network stack.
The second way the stack can be shut down is when the stack code detects a fatal error. A fatal error is
an error above the fatal threshold set in the configuration. This type of error generally indicates that it is
not safe for the stack to continue. When this occurs, the stack code calls NC_NetStop(-1). It is then up to
you to determine what should be done next. The way the NC_NetStart() loop is coded determines if the
system will shut down (as in the example), or simply reboot.
Note that the critical threshold to shut down can also be disabled. The following code can be added to the
configuration to disable error-related shutdowns:
// We do not want the stack to abort on any error
uint32_t rc = DBG_NONE;
//
// THIS MUST BE THE ABSOLUTE 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(;;);
}
//
// First load the linear memory block holding the configuration
//
if( !hCfg )
{
printf("Unable to create configuration\n");
free( pBuf );
goto main_exit;
}
mmFree( pBuf );
//
// Boot the system using this configuration
//
// We keep booting until the function returns less than 1. This allows
// us to have a "reboot" command.
//
do
{
rc = NC_NetStart( hCfg, NetworkStart, NetworkStop, NetworkIPAddr );
} while( rc > 0 );
// Delete Configuration
CfgFree( hCfg );
// Close the OS
main_exit:
NC_SystemClose();
return(0);
}
2.1.5.2 Pre-Initialization
If you use Cfg*() API calls for configuration, your application must call the primary initialization function
NC_SystemOpen() before calling any other stack API functions. This initializes the stack and the memory
environment used by all the stack components. Two calling arguments, Priority and OpMode, indicate how
the scheduler should execute. For example, the example applications included in the NSP contain the
following code:
rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );
if( rc )
{
printf("NC_SystemOpen Failed (%d)\n",rc);
for(;;);
}
//
// NetworkStart
//
// This function is called after the configuration has booted
//
The above code launches a self-contained application that needs no further monitoring, but the application
must be shut down when the system shuts down. This is done via the NetworkStop() callback function.
Therefore, the NetworkStop() function must undo what was done in NetworkStart().
//
// NetworkStop
//
// This function is called when the network is shutting down
//
static void NetworkStop()
{
// Close our SMTP server Task
SMTP_close( hSMTP );
}
The above example assumes that the network scheduler Task can be launched whether or not the stack
has a local IP address. This is true for servers that listen on a wildcard address of 0.0.0.0. In some rare
cases, an IP address may be required for Task initialization, or perhaps an IP address on a certain device
type is required. In these circumstances, the NetworkIPAddr() callback function signals the application that
it is safe to start.
The following example illustrates the calling parameters to the NetworkIPAddr() callback. Note that the
IFIndexGetHandle() and IFGetType() functions can be called to get the type of device (HTYPE_ETH or
HTYPE_PPP) on which the new IP address is being added or removed. This example just prints a
message. The most common use of this callback function is to synchronize network Tasks that require a
local IP address to be installed before executing.
//
// NetworkIPAddr
// This function is called whenever an IP address binding is
// added or removed from the system.
//
static void NetworkIPAddr( IPN IPAddr, uint32_t IfIdx, uint32_t fAdd )
{
IPN IPTmp;
if( fAdd )
printf("Network Added: ");
else
printf("Network Removed: ");
// Print a message
IPTmp = ntohl( IPAddr );
static void ServiceReport( uint32_t Item, uint32_t Status, uint32_t Report, void *h )
{
printf( "Service Status: %-9s: %-9s: %-9s: %03d\n",
TaskName[Item-1], StatusStr[Status], ReportStr[Report/256], Report&0xFF );
}
Note that the names of the individual services are listed in the TaskName[] array. This order is specified
by the definition of the service items in the configuration system and is constant. See the file
INC/NETTOOLS/NETCFG.H for the physical declarations.
Note that the strings defining the master report code are listed in the ReportStr[] array. This order is
specified by the NETTOOLS standard reporting mechanism and is constant. See the file
INC/NETTOOLS/NETTOOLS.H for the physical declarations.
Note that the strings defining the Task state are defined in the StatusStr[] array. This order is specified
by the definition of the standard service structure in the configuration system. See the file
INC/NETTOOLS/NETCFG.H for the physical declarations.
The last value this callback function prints is the least significant 8 bits of the value passed in Report. This
value is specific to the service in question. For most services this value is redundant. Usually, if the
service succeeds, it reports Complete, and if the service fails, it reports Fault. For services that never
complete (for example, a DHCP client that continues to run while the IP lease is active), the upper byte of
Report signifies Running and the service specific lower byte must be used to determine the current state.
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
These DHCP client specific report codes are defined in INC/NETTOOLS/INC/DHCPIF.H. In most cases,
you do not have to examine state report codes down to this level of detail, except in the following case.
When using the DHCP client to configure the stack, the DHCP client controls the first 256 entries of the
CFGTAG_SYSINFO tag space. These entries correspond to the 256 DHCP option tags. An application
may check for DHCPCODE_IPADD or DHCPCODE_IPRENEW return codes so that it can read or alter
information obtained by DHCP client. This is discussed further in Section 2.1.4.1.2.
The IP layer then calls the validation function "fxn" (if it is not NULL) before binding a potential IP address.
If the validation function returns success, then the stack binds the IP address. If not, the binding fails.
The NS_setAddrHook() API must be called in the appropriate place, early in the stack initialization code.
In particular, it should be called in the startup code before the call to NC_NetStart(). In order to make this
call during stack initialization, it is necessary to modify the code of the NDK stack thread to add the call.
rc = NC_SystemOpen(NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT);
if (rc) {
System_abort("NC_SystemOpen Failed (%d)\n");
}
/* ... */
do {
rc = NC_NetStart(hCfg, ti_ndk_config_Global_NetworkOpen,
ti_ndk_config_Global_NetworkClose,
ti_ndk_config_Global_NetworkIPAddr);
} while (rc > 0 || rc == UAT_LINKDOWN);
The ARP layer will then call your validation function "fxn" (if it is not NULL) for ARP packets received by
the stack.
The steps to call the LLI_setARPHook() function are similar to those found in Section 2.1.6.2.
When you create a project using a TI-RTOS Kernel template, the project will contain a configuration file
(*.cfg) that can be edited with the XGCONF graphical editor in CCStudio. If you checked the boxes to
enable use of the NDK and NSP when you created the project, you can configure your application's use of
the NDK modules. The configuration file is processed during the build to generate code that configures
your application.
You can configure the NDK modules through the XGCONF configuration editor. (Internally, the same
configuration database is updated when the *.cfg file is built.)
NOTE: You must choose one method or the other to configure your application. You should not mix
configuration methods. If you have NDK applications that use the C-based configuration
method, you should either continue to use that method or convert the configuration entirely to
an *.cfg file configuration. If a project uses both methods, there will be unpredictable conflicts
between the two configurations.
1. To open XGCONF, simply double-click the *.cfg file in your application's project. See the steps in
Section 1.6 for how to use XGCONF with the NDK. For more details, see Chapter 2 of the TI-RTOS
Kernel (SYS/BIOS) User's Guide (SPRUEX3).
2. When XGCONF opens, you see the Welcome sheet for TI-RTOS Kernel. You should see categories
for the NDK Core Stack and your NSP in the Available Products area. If you do not, your CCStudio
Project does not have NDK support enabled. See to correct this problem. (If the configuration is shown
in a text editor instead of XGCONF, right-click on the .cfg file in the Project Explorer and choose Open
With > XGCONF.)
3. Click the Global item in either the Available Products view (under the NDK Core Stack category) or
in the Outline view
4. You see the Welcome sheet for NDK configuration. This sheet provides an overview of the NDK,
configuration information, and documentation for the NDK.
5. Click the System Overview button to see a handy diagram of the NDK modules you can configure. If
you are editing the configuration of one of the NSP examples, notice the green checkmarks next to
some modules. These checkmarks indicate that support for the modules have been enabled in the
configuration.
The XGCONF configuration automatically performs the following actions for you:
• Generates C code to create and populate a configuration database.
• Generates C code to act as the network scheduling function and to perform network activity.
The following C functions are generated as a result of using the NDK Global module for configuration. You
should take care not to write application functions with these names.
• ti_ndk_config_Global_stackThread(): The NDK stack thread function.
• NetworkOpen(): function that is called automatically by NC_NetStart().
• NetworkClose(): function that is called automatically by NC_NetStart().
• NetworkIPAddr(): function that is called automatically by NC_NetStart().
• ti_ndk_config_Global_serviceReport(): Service report callback function.
2. Double-click on the *.cfg configuration file in the Project Explorer tree. While XGCONF is opening, the
CCStudio status bar shows that the configuration is being processed and validated.
3. When XGCONF opens, you see the Welcome sheet for the TI-RTOS Kernel. You should see
categories for the NDK Core Stack and your NSP in the Available Products area. If you do not, your
CCStudio Project does not have NDK support enabled. See to correct this problem. (If the
configuration is shown in a text editor instead of XGCONF, right-click on the .cfg file in the Project
Explorer and choose Open With > XGCONF.)
4. Click the Global item in either the Available Products view (under the NDK Core Stack category) or
in the Outline view
4. You will see the Welcome sheet for NDK configuration. This sheet provides an overview of the NDK,
configuration information, and documentation for the NDK.
5. Click the System Overview button to see a handy diagram of the NDK modules you can configure. If
you are editing the configuration of one of the NSP examples, notice the green checkmarks next to
some modules. These checkmarks indicate that support for the modules have been enabled in the
configuration.
3. Notice that the module you added to the configuration is now listed in the Outline view.
For details about properties, right-click and choose Help from the context menu. This opens the CDOC
online reference system for the NDK. The properties names listed in this online help are the names used
in the configuration source file. You can click the Source tab at the bottom of the XGCONF editor window
to see the actual source statements.
5. Notice that the instance you created is also listed in the Outline view.
If you specify a hook function in the configuration, but do not define the function in your C code, a linker
error will result.
For example, the following function could be called as the Stack Thread Initialization hook function to
open an SMTP server application:
//
// SmtpStart
// This function is called after the configuration has been loaded
//
static void SmtpStart( )
{
// Create an SMTP server Task
hSMTP = SMTP_open( );
}
The above code launches a self-contained application that needs no further monitoring, but the application
must be shut down when the system shuts down. This is done via the Stack Thread Delete callback
function.
//
// SmtpStop
// This function is called when the network is shutting down
//
static void SmtpStop()
{
// Close SMTP server Task
SMTP_close( hSMTP );
}
The above code assumes that the network scheduler Task can be launched whether or not the stack has
a local IP address. This is true for servers that listen on a wildcard address of 0.0.0.0. In some rare cases,
an IP address may be required for Task initialization, or perhaps an IP address on a certain device type is
required. In these circumstances, the NetworkIPAddr() callback function signals the application that it
is safe to start.
If you are using XGCONF for configuration, saving and reloading configurations via the CfgSave() and
CfgLoad() functions is not automatically supported by XGCONF. However, internally, the same
configuration database used by the Cfg*() C functions is populated when the *.cfg file is built. You may
want to use the example functions in Section 2.1.4.4 as hook functions to save the configuration created
with XGCONF and reload if from non-volatile memory on startup.
5. If you want information about a property, point to the field with your mouse cursor. Right-click on any
field to get reference help for all the configurable IP module properties.
6. In addition to the properties listed on the General Settings page, a number of additional properties can
be set if you click the Advanced button.
The following example uses pthread APIs to create Tasks for use by the NDK. The thread has a normal
priority level and a stack size of 2048.
#include <pthread.h>
#include <ti/ndk/inc/netmain.h>
void mySocketThreadFxn()
{
fdOpenSession((void *)pthread_self());
/* do socket calls */
fdCloseSession((void *)pthread_self());
}
void createNdkThread()
{
int status;
pthread_attr_t pthreadAttrs;
struct sched_param schedParams;
pthread_t task;
pthread_attr_init(&pthreadAttrs);
schedParams.sched_priority = OS_TASKPRINORM;
status = pthread_attr_setschedparam(&pthreadAttrs, &schedParams);
if (status != 0) {
/* error */
}
pthread_attr_destroy(&pthreadAttrs);
if (status != 0) {
/* error */
}
}
/* do socket calls */
fdCloseSession((void *)pthread_self());
return (NULL);
}
// configure NDK
CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_IPREASMMAXSIZE,
CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (unsigned char*) &tmp, 0);
CfgAddEntry(hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,
CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (unsigned char*) &tmp, 0);
– Increase the Memory Manager Buffer Page Size in the Buffers tab of the Global configuration.
– If you use Cfg*() API calls for configuration, you can edit the MMALLOC_MAXSIZE definition in the
pbm.c file and RAW_PAGE_SIZE definition in the mem.c file. Then rebuild the appropriate OS
Adaptation Layer library in /ti/ndk/os/lib.
Timestamping UDP Datagram Payloads
The NDK allows the application to update the payload of UDP datagrams. The typical usage of this is
to update the timestamp information of the datagram. This way, transmitting and receiving ends can
more accurately adjust delivery delays depending on changing run-time characteristic of the system.
On the transmitting end:
• The application can register a call-out function per socket basis by using the NDK_setsockopt()
function.
• The call-out function is called by the stack before inserting the datagram into driver's transmit queue.
• It is the call-out function's responsibility to update the UDP checksum information in the header.
• The following code section is a sample of how to control it:
void myTxTimestampFxn(unsigned char *pIpHdr) {
...
}
In General
• Do not try to tune the Timer function frequency. Make sure it calls llTimerTick() every 100 ms.
• Watch for out of memory conditions. These can be detected by the return from some functions, but will
also print out warning messages when the messages are enabled. These messages contain the
acronym OOM for out of memory. (Out of memory conditions can be caused by many things, but the
most common cause in the NDK is when TCP sockets are created and closed very quickly without
using the SO_LINGER socket option. This puts many sockets in the TCP timewait state, exhausting
scratchpad memory. The solution is to use the SO_LINGER socket option.)
By default, all debug messages are printed, and messages with a level of DBG_ERROR causes a stack
shutdown. This behavior can be modified in the configuration as described in Section 2.2.10. Or, you can
modify it through the system configuration as described in Section 2.1.4.2 and Section 2.1.4.3. Also see
the TI Network Developer's Kit (NDK) API Reference Guide (SPRU524).
To check to see if corruption is being caused by a NULL pointer, change the cache mode to use less
cache. When there is some internal memory available, reads or writes to address 0x0 do not cause cache
corruption (the application still may not work, but the error messages should stop).
Another way to track down any kind of cache corruption is to break on CPU reads or writes to the entire
cache range. Code Composer Studio has the ability to trap reads or writes to a range of memory, but both
cannot be checked simultaneously. Therefore, a couple of trials may be necessary.
Of course, it is possible that the memory corruption has nothing to do with the stack. It could be a wild
pointer. However, since corrupting the cache can corrupt memory throughout the system, the cache is the
first place to start.
if (pTempBuf != NULL)
{
myFun( pTempBuf );
Memory_free( NULL, pTempBuf, 2000 );
}
}
If calling a memory allocation function is too much of a speed overhead, consider using an external buffer.
This is just an example, with a little forethought you can eliminate all possible stack overflow conditions,
and eliminate the possibility of program lockups from this condition.
Here, the entry 18:96 (56%) means that at most, 18 blocks were allocated in the 96 byte bucket. The page
size on the memory manager is 3072, so 56% of a page was used. The entry 21504/46080 means that at
most 21,504 bytes were allocated, with a total of 46,080 bytes available.
The entry mmAlloc: 61347036/0/61346947 means that 61,347,036 calls were made to mmAlloc(), of which
0 failed, and 61,346,947 calls were made to mmFree(). Note that at any time, the call to mmAlloc plus the
failures must equal the calls to mmFree plus any outstanding allocations. Therefore, on a final report
where the report is mmAlloc: n1/n2/n3, n1+n2 should equal n3. If not, there is a memory leak.
There are several methods to obtain a memory report when using the telnet console program included
with most of the example applications. The console 'mem' command prints out a current report, but more
importantly, the console 'shutdown' command shuts down the stack and prints out a final report. If all
network applications are created and destroyed according to the specifications in this document, there
should be no memory leaks detected in the final report. The function called to obtain a memory report is
defined below.
Parameters
Description Prints out a memory report to the printf() compatible function pointed to by pPrn. The
type of report printed is determined by the value of CallMode. The reporting function has
the option of printing out memory block IDs. This means that the first uint32_t sized field
in the memory block of each allocated block is printed in the report. This is a useful
option when the first field of allocated memory stores an object handle type, or some
other unique identifier.
Call Mode
Returns None
3.1.1 History
The NETCTRL module was originally a recommended initialization and scheduling method to execute the
NDK. Although mostly simple, this code became standard. Eventually, it was separated out into the
NETCTRL library.
The NETCTRL module is the center of the NDK because it connects the HAL and the OS Adaptation
Layer to the NDK. It controls both initialization and how events are scheduled for execution within the
stack. Understanding how the NETCTRL module works helps you tune your DSP or ARM networking
application for ideal performance.
There are two include files associated with NETCTRL in the /INC/NETCTRL directory:
CreateConfigurationBootThread() ;
NetScheduler();
CloseConfiguration();
CloseDevices();
}
Out of the functional stages for NC_NetStart() listed above, the two that are of the most concern are the
creation of the boot thread, and the implementation of the network event scheduler.
The boot thread is handled by a second C module in the NETCTRL library named NETSRV.C. This name
is an abbreviation for Network Service Manager. The NETSRV module hooks into the configuration
system as a configuration service provider. The configuration system module is just an active database. In
contrast, the network service module turns configuration entries into actual NDK objects. The service
module can be altered to fit a particular need. This likely involves the creation of custom configuration tags
for the configuration system. However, a full understanding of the code in NETSRV requires a basic
understanding of nearly all the API functions discussed in the TI Network Developer's Kit (NDK) API
Reference Guide (SPRU524).
You should be most concerned about the NetScheduler() function because this scheduler runs the NDK. It
looks for events that need to be processed by the NDK, and it performs the work necessary to start
processing.
while( !NetHaltFlag )
{
WaitOrPollForEvents();
ServiceDeviceDrivers();
The sections that follow address each of the highlighted functions in turn. Note that the code continues to
run until the NetHaltFlag is set. This flag is set when an application calls the NC_NetStop() function.
Mode 3 is the most Unix-like environment. Here, the network scheduler Task runs at a higher priority than
any other networking Task in the system. The stack runs whenever new network related events are
detected, pre-empting other Tasks from potentially using the stack. This is the best method for keeping the
networking environment up to date without placing restrictions on how network applications are written.
Setting priority and polling or interrupt driven scheduling is done when the application first calls
NC_SystemOpen(). This is discussed further in Section 2.1.5.2 and in the NDK Programmer’s Reference
Guide.
This code changes the priority of the Task thread that calls into NC_NetStart(), so that there is a single
control point to set the scheduler priority. The priority used is that which was passed to the
NC_SystemOpen() function. This is discussed further in Section 2.1.5.2 and in the NDK Programmer’s
Reference Guide.
The scheduler priority (relative to network application thread priority) affects how network applications can
be programmed. For example, when running the scheduler in low priority, a network application cannot
poll for data by continuously calling NDK_recv() in a non-blocking fashion. This is because if the
application thread never blocks, the network scheduler thread never runs, and incoming packets are never
processed by the NDK.
#define STKEVENT_NUMEVENTS 5
#define STKEVENT_TIMER 0
#define STKEVENT_ETHERNET 1
#define STKEVENT_SERIAL 2
#define STKEVENT_LINKUP 3
#define STKEVENT_LINKDOWN 4
There are two parts to the structure, a Semaphore handle and an array of events. Each driver signals an
event by setting a flag in the EventCode[ ] array for its event type, and then optionally signaling the event
semaphore. The semaphore is only signaled when the driver detects an interrupt condition. If the event is
detected during driver polling (either periodic polling or constant in the case of a polling only driver), the
event is set, but the semaphore is not signaled.
You can provide a hook function to run when a driver signals a STKEVENT_LINKUP or
STKEVENT_LINKDOWN event, meaning that the link has come up or gone down. Note that such a hook
function will only be called if the driver has code to call STKEVENT_signal({STKEVENT_LINKUP}) and
STKEVENT_signal({STKEVENT_LINKDOWN}).
The hook function should accept a single int status parameter. If the function receives 0, the link is now
down (for example, because a cable was disconnected). If the function receives a 1, the link is now up. To
register your hook function, call NC_setLinkHook() as follows:
NC_setLinkHook( void (*LinkHook)(int) );
The NETCTRL module creates a private instance of the STKEVENT structure that it passes to device
drivers as a handle of type STKEVENT_Handle. The private instance that is operated on directly by
NETCTRL is declared as:
// Static Event Object
static STKEVENT stkEvent;
In the full source to NetScheduler() that follows, the STKEVENT structure is referred to by its instance
stkEvent.
/* Poll only once every timer event for ISR based drivers, */
/* and continuously for polling drivers. Note that "fEvents" */
/* can only be set to FLAG_EVENT_TIMER at this point. */
if( fEvents || !stkEvent.hSemEvent )
{
NIMUPacketServiceCheck (fEvents);
Each of these NETCTRL library versions is built for both pure IPv4 as well as IPv6.
If you configure the NDK in CCStudio with the XGCONF configuration tool, the appropriate NETCTRL
library is automatically selected based on the modules you enable.
If you need even more control over which features are available in the NETCTRL library used by your
application, you can #define the following constants in /ti/ndk/inc/netctrl/netsrv.h, which control
the features brought into the NETCTRL library if "_NDK_EXTERN_CONFIG" is not defined.
#define NETSRV_ENABLE_TELNET 1
#define NETSRV_ENABLE_HTTP 1
#define NETSRV_ENABLE_NAT 0
#define NETSRV_ENABLE_DHCPCLIENT 1
#define NETSRV_ENABLE_DHCPSERVER 1
#define NETSRV_ENABLE_DNSSERVER 1
By setting any of the above to 0 and rebuilding the appropriate NETCTRL library, individual services can
be purged from the executable.
OS Adaptation Layer
The OS adaptation layer controls how the NDK uses RTOS resources. This includes its use of tasks,
semaphores, and memory. In most cases, the only API described in this chapter that your NDK application
will call is TaskCreate().
NOTE: In previous releases, the NDK did not require this configuration setting. If this configuration
setting is not made, Task clean-up will not occur, and out of memory errors may occur
because the task stacks and objects will not be freed when TaskExit() and/or TaskDestroy()
is called.
Note that when the memory is declared, it is placed on a cache aligned boundary. Also, each packet
buffer must be an even number of cache lines in size so that it can be reliably flushed without the risk of
conflicting with other buffers.
As noted in the source code to PBM.C, the function RtDeRef() can only be called from kernel mode.
However, instead of defining two versions of the PBM_free() function, the PBM module relies on the fact
that device drivers are never given packet buffers containing routes. Therefore, any call to PBM_free()
where the buffer contains a route, must have been called from within kernel mode. It is, therefore, safe to
call RtDeRef().
When a packet buffer is copied with PBM_copy(), all the information about the packet is also copied. This
information may include a referenced route handle. If the handle to a route is copied in the process of
copying the packet buffer, then a reference to that handle must also be added by calling the RtRef()
function. The PBM module does not need to worry about kernel mode for the same reason as it did not
with PBM_free().
The allocation functions for the small memory blocks (mmAlloc() and mmFree()) should not be altered.
These functions are used by the NDK to allocate and free scratchpad type memory. They can be called at
interrupt time and are not allowed to block. The memory is currently allocated out of a static array.
The memory manipulation functions mmZeroInit() and mmCopy() are both coded in C. A system
programmer may recode these functions in assembly, or to use an EDMA channel to move memory.
The allocation functions for the large memory blocks (mmBulkAlloc() and mmBulkFree()) are currently
defined to use malloc() and free(). These functions can be altered to use any memory allocation system of
choice. They are not called at interrupt time and are allowed to block.
Revision History
Texas Instruments Incorporated (‘TI”) technical, application or other design advice, services or information, including, but not limited to,
reference designs and materials relating to evaluation modules, (collectively, “TI Resources”) are intended to assist designers who are
developing applications that incorporate TI products; by downloading, accessing or using any particular TI Resource in any way, you
(individually or, if you are acting on behalf of a company, your company) agree to use it solely for this purpose and subject to the terms of
this Notice.
TI’s provision of TI Resources does not expand or otherwise alter TI’s applicable published warranties or warranty disclaimers for TI
products, and no additional obligations or liabilities arise from TI providing such TI Resources. TI reserves the right to make corrections,
enhancements, improvements and other changes to its TI Resources.
You understand and agree that you remain responsible for using your independent analysis, evaluation and judgment in designing your
applications and that you have full and exclusive responsibility to assure the safety of your applications and compliance of your applications
(and of all TI products used in or for your applications) with all applicable regulations, laws and other applicable requirements. You
represent that, with respect to your applications, you have all the necessary expertise to create and implement safeguards that (1)
anticipate dangerous consequences of failures, (2) monitor failures and their consequences, and (3) lessen the likelihood of failures that
might cause harm and take appropriate actions. You agree that prior to using or distributing any applications that include TI products, you
will thoroughly test such applications and the functionality of such TI products as used in such applications. TI has not conducted any
testing other than that specifically described in the published documentation for a particular TI Resource.
You are authorized to use, copy and modify any individual TI Resource only in connection with the development of applications that include
the TI product(s) identified in such TI Resource. NO OTHER LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE TO
ANY OTHER TI INTELLECTUAL PROPERTY RIGHT, AND NO LICENSE TO ANY TECHNOLOGY OR INTELLECTUAL PROPERTY
RIGHT OF TI OR ANY THIRD PARTY IS GRANTED HEREIN, including but not limited to any patent right, copyright, mask work right, or
other intellectual property right relating to any combination, machine, or process in which TI products or services are used. Information
regarding or referencing third-party products or services does not constitute a license to use such products or services, or a warranty or
endorsement thereof. Use of TI Resources may require a license from a third party under the patents or other intellectual property of the
third party, or a license from TI under the patents or other intellectual property of TI.
TI RESOURCES ARE PROVIDED “AS IS” AND WITH ALL FAULTS. TI DISCLAIMS ALL OTHER WARRANTIES OR
REPRESENTATIONS, EXPRESS OR IMPLIED, REGARDING TI RESOURCES OR USE THEREOF, INCLUDING BUT NOT LIMITED TO
ACCURACY OR COMPLETENESS, TITLE, ANY EPIDEMIC FAILURE WARRANTY AND ANY IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL
PROPERTY RIGHTS.
TI SHALL NOT BE LIABLE FOR AND SHALL NOT DEFEND OR INDEMNIFY YOU AGAINST ANY CLAIM, INCLUDING BUT NOT
LIMITED TO ANY INFRINGEMENT CLAIM THAT RELATES TO OR IS BASED ON ANY COMBINATION OF PRODUCTS EVEN IF
DESCRIBED IN TI RESOURCES OR OTHERWISE. IN NO EVENT SHALL TI BE LIABLE FOR ANY ACTUAL, DIRECT, SPECIAL,
COLLATERAL, INDIRECT, PUNITIVE, INCIDENTAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES IN CONNECTION WITH OR
ARISING OUT OF TI RESOURCES OR USE THEREOF, AND REGARDLESS OF WHETHER TI HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
You agree to fully indemnify TI and its representatives against any damages, costs, losses, and/or liabilities arising out of your non-
compliance with the terms and provisions of this Notice.
This Notice applies to TI Resources. Additional terms apply to the use and purchase of certain types of materials, TI products and services.
These include; without limitation, TI’s standard terms for semiconductor products http://www.ti.com/sc/docs/stdterms.htm), evaluation
modules, and samples (http://www.ti.com/sc/docs/sampterms.htm).
Mailing Address: Texas Instruments, Post Office Box 655303, Dallas, Texas 75265
Copyright © 2018, Texas Instruments Incorporated