
- •Preface
- •About this book
- •Intended audience
- •Using this book
- •Typographical conventions
- •Further reading
- •Feedback
- •Feedback on ARM TCP/IP
- •Feedback on this book
- •Introduction
- •1.1 A typical embedded networking stack
- •1.2 What is PPP?
- •1.3 ARM TCP/IP requirements
- •1.3.1 Memory requirements
- •1.3.2 CPU requirements
- •1.3.3 Operating system requirements
- •1.4 ARM PPP requirements
- •1.4.1 Line management functions
- •1.4.2 Static memory
- •1.4.3 Dynamic memory
- •1.4.4 Periodic clock tick
- •1.5 Example package directories
- •1.6 Sample programs
- •TCP/IP Porting
- •2.1 Porting procedure
- •2.2 Portable and nonportable files
- •2.2.1 Portable files
- •2.2.2 Nonportable files
- •2.3 Creating the IP port file
- •2.3.1 Standard macros and definitions
- •2.3.2 CPU architecture
- •2.3.4 Debugging aids
- •2.3.5 Timers and multitasking
- •2.3.6 Stack features and options
- •2.4 Coding the glue layer
- •2.4.1 Task control
- •2.5 Specifying IP addresses
- •2.5.1 Porting programmer IP issues
- •2.5.2 End user IP issues
- •2.6 Testing the TCP/IP port
- •PPP Porting
- •3.1 Porting procedure
- •3.2 Porting PPP
- •3.2.1 Source files
- •3.2.2 Compiling PPP
- •3.2.3 Entry points and support calls
- •3.3 Testing PPP
- •3.3.1 Loopback
- •3.3.2 Client connection
- •3.3.3 Server connection
- •3.3.4 Abrupt disconnect
- •3.3.5 Multilink test
- •TCP/IP API Functions
- •4.2.1 cksum()
- •4.2.2 dprintf() and initmsg()
- •4.2.3 dtrap()
- •4.2.4 ENTER_CRIT_SECTION() and EXIT_CRIT_SECTION()
- •4.2.5 LOCK_NET_RESOURCE() and UNLOCK_NET_RESOURCE()
- •4.2.6 npalloc()
- •4.2.7 npfree()
- •4.2.8 panic()
- •4.2.9 prep_ifaces()
- •4.2.10 tcp_sleep()
- •4.2.11 tcp_wakeup()
- •4.3 Network interfaces
- •4.3.1 The NET structure
- •4.3.2 n_close()
- •4.3.3 n_init()
- •4.3.4 n_reg_type()
- •4.3.5 n_stats()
- •4.3.6 pkt_send()
- •4.3.7 raw_send()
- •PPP API Functions
- •5.2.1 _ALLOC() functions
- •5.2.2 ConPrintf()
- •5.2.3 _FREE() functions
- •5.2.4 get_secret()
- •5.2.5 ppp_port_init()
- •5.3 Serial line drivers
- •5.3.1 ln_connect()
- •5.3.2 ln_getc()
- •5.3.3 ln_hangup()
- •5.3.4 ln_putc()
- •5.3.5 ln_speed()
- •5.3.6 ln_state()
- •5.3.7 ln_write()
- •5.4 PPP entry points
- •5.4.1 lcp_lowerdown()
- •5.4.2 lcp_lowerup()
- •5.4.3 ppp_input()
- •5.4.4 ppp_timeisup()
- •5.4.5 prep_ppp()
- •Modem Functions
- •6.1 dialer.c
- •6.1.1 dial()
- •6.1.2 dial_check()
- •6.1.3 dialer_status()
- •6.1.4 modem_cmd()
- •6.1.5 modem_connect()
- •6.1.6 modem_getc()
- •6.1.7 modem_gets()
- •6.1.8 modem_hangup()
- •6.1.9 modem_init()
- •6.1.10 modem_lstate()
- •6.1.11 modem_putc()
- •6.1.12 modem_reset()
- •6.1.13 modem_speed()
- •6.1.14 modem_state()
- •6.1.15 modem_write()
- •6.2 login.c
- •6.2.1 do_script()
- •6.2.2 login()
- •6.2.3 log_input()
- •6.2.4 log_output()
- •6.2.5 logserver()
- •6.3 mdmport.c
- •6.3.1 dial_delay()
- •6.3.2 hangup()
- •6.3.3 modem_clr_dtr() and modem_set_dtr()
- •6.3.4 modem_DCD()
- •6.3.5 modem_portstat()
- •DHCP Client Functions
- •7.1 DHCP client functions
- •7.1.1 dhc_init()
- •7.1.2 dhc_discover()
- •7.1.3 dhc_set_callback()
- •7.1.4 dhc_halt()
- •7.1.5 dhc_second()
- •Low-overhead UDP Functions
- •8.1 UDP functions
- •8.1.1 udp_alloc()
- •8.1.2 udp_close()
- •8.1.3 udp_open()
- •8.1.4 udp_send()
- •8.1.5 udp_socket()
- •Sockets
- •9.1 ARM implementation of sockets
- •9.2 Socket API reference
- •9.2.1 t_accept()
- •9.2.2 t_bind()
- •9.2.3 t_connect()
- •9.2.4 t_errno()
- •9.2.5 t_getpeername()
- •9.2.6 t_getsockname()
- •9.2.7 t_getsockopt()
- •9.2.8 t_listen()
- •9.2.9 t_recv() and t_recvfrom()
- •9.2.10 t_select()
- •9.2.11 t_send() and t_sendto()
- •9.2.12 t_setsockopt()
- •9.2.13 t_shutdown()
- •9.2.14 t_socket()
- •9.2.15 t_socketclose()
- •ARM-specific Functions
- •10.1 ARM directories
- •10.1.1 armthumb
- •10.2 cksum.s
- •10.3 clock.c
- •10.3.1 clock_init()
- •10.3.2 clock_c()
- •10.4 delay.s
- •10.5 dtrap.s
- •10.6 except.s
- •10.7.1 ENTER_CRIT_SECTION() and EXIT_CRIT_SECTION()
- •10.7.2 irqDispatch()
- •10.7.3 irq_Enable() and irq_Disable()
- •10.7.4 irqInit()
- •10.8 lswap.s
- •10.10 olicom.c
- •10.11 pcmcia.c
- •10.12 stack.s
- •10.13 uart.c description
- •10.14 uart.c ring buffer management functions
- •10.14.1 ring_add()
- •10.14.2 ring_avail()
- •10.14.3 ring_new()
- •10.14.4 ring_remove()
- •10.14.5 ring_space()
- •10.15 uart.c interface functions
- •10.15.1 uart_getc()
- •10.15.2 uart_DCD()
- •10.15.3 uart_delay()
- •10.15.4 uart_do_irq()
- •10.15.5 uart_init()
- •10.15.6 uart_irq()
- •10.15.7 uart_putc()
- •10.15.8 uart_ready()
- •10.15.9 uart_reset()
- •10.15.10 uart_setup()
- •10.15.11 uart_stats()
- •10.16 uart.c debug TTY interface functions
- •10.16.1 dputchar()
- •10.16.2 getch()
- •10.16.3 kbhit()
- •Miscellaneous Library Functions
- •11.1 app_ping.c
- •11.2 in_utils.c
- •11.2.1 con_page()
- •11.2.2 hexdump()
- •11.2.3 nextarg()
- •11.2.4 ns_printf()
- •11.2.5 panic()
- •11.2.6 print_eth()
- •11.2.7 print_ipad()
- •11.2.8 print_uptime()
- •11.2.11 sysuptime()
- •11.2.12 uslash()
- •11.3 memman.c
- •11.4 menus.c, menulib.c, and nrmenus.c
- •11.5 nextcarg.c
- •11.5.1 nextcarg()
- •11.6 nvfsio.c
- •11.6.1 Overview
- •11.6.2 nv_fclose()
- •11.6.3 nv_fgets()
- •11.6.4 nv_fopen()
- •11.6.5 nv_fprintf()
- •11.6.6 nv_fwrite()
- •11.6.7 nv_initialize()
- •11.6.8 nv_writeflash()
- •11.7 nvparms.c
- •11.8 parseip.c
- •11.8.1 parseip()
- •11.9 reshost.c
- •11.9.1 in_reshost()
- •11.10 strilib.c
- •11.11 strlib.c
- •11.12 tcp_echo.c
- •11.13 ttyio.c
- •11.14 udp_echo.c
- •11.15 userpass.c
- •11.15.1 add_user()
- •11.15.2 check_permit()
- •Example Applications
- •12.1 Overview of the examples
- •12.1.1 Requirements
- •12.1.2 Building projects
- •12.1.3 Running the examples
- •12.2 Example descriptions
- •12.2.1 chargen
- •12.2.2 loopback
- •12.2.3 maildemo
- •12.2.4 menus
- •Error Codes
- •A.1 ENP_ error codes
- •A.2 Socket error codes

TCP/IP Porting
2.3Creating the IP port file
You must create a version of the IP port file before you compile the portable TCP/IP stack files. The ipport.h file contains the IP layer’s port-dependent definitions and the architectural definitions for all the IP-related code.
The ipport.h file also controls CPU architectures (big-endian or little-endian), compiler options, and optional features (DHCP, multiple interfaces, and IP routing support).
You must #include the ipport.h file in every C file of every module throughout the TCP/IP software.
Caution
A mistake in this file (such as using big-endian in place of little-endian) can create severe problems, so it is important to set this file up correctly.
2.3.1Standard macros and definitions
The ARM TCP/IP stack expects TRUE, FALSE, and NULL to be defined in ipport.h. Typically, the best way to do this is to include the standard C library file stdio.h in ipport.h. If stdio.h is impractical to use or not available on your system, the following example works in most environments:
#ifndef TRUE #define TRUE -1 #define FALSE 0 #endif
#ifndef NULL
#define NULL (void*)0; #endif
2-4 |
Copyright © 1998 and 1999 ARM Limited. All rights reserved. |
ARM DUI 0079B |

TCP/IP Porting
2.3.2CPU architecture
Four common macros from Berkeley UNIX are used for doing byte order conversions between different CPU architecture types:
•htons()
•htonl()
•ntohs()
•ntohl().
These functions can be used as either macros or functions. They accept 16-bit and 32-bit quantities as shown and convert them from network format (big-endian) to the format supported by the local system.
If your system is using the ARM processor in big-endian mode, these macros can return the variable passed, for example:
#define htonl(l) (l) #define htons(s) (s) #define ntohl(l) (l) #define ntohs(s) (s)
If your system is using the ARM processor in little-endian mode, the byte order must be swapped. For htonl() and ntohl(), use the lswap() function provided in the \armthumb directory (see Example package directories on page 1-16). For htons() and ntohs(), use a byte-swapping macro, as shown below:
#define htonl(l) |
lswap(l) |
|
#define htons(s) |
((u_short)(((u_short)(s) >> 8) | |
|
|
|
((u_short)(s) << 8))) |
#define |
ntohl(l) |
lswap(l) |
#define |
ntohs(s) |
htons(s) |
ARM DUI 0079B |
Copyright © 1998 and 1999 ARM Limited. All rights reserved. |
2-5 |

TCP/IP Porting
2.3.3Pre-emption and protection
You must define primitives in order to protect sections of code that must not be interrupted or pre-empted (see Implementing pre-emption and protection on page 2-12).
The critical section protection scheme is typically used on embedded systems that lack a multitasking capability:
void |
ENTER_CRIT_SECTION(); |
/* |
enter critical section */ |
void |
EXIT_CRIT_SECTION(); |
/* |
exit critical section */ |
Those systems are described in detail in ENTER_CRIT_SECTION() and
EXIT_CRIT_SECTION() on page 4-7.
The lock net resource macros are typically used on realtime kernels, such as VRTX and VxWorks:
void LOCK_NET_RESOURCE(); |
/* start re-entrance protection */ |
void UNLOCK_NET_RESOURCE(); /* end re-entrance protection */
2.3.4Debugging aids
You should include the following macros in your functions to provide support while you are debugging your code:
•dtrap
•initmsg() and dprintf() on page 2-7
•NPDEBUG on page 2-7.
dtrap
This macro is called by the stack code when it detects a situation that should not be occurring. The intention is for the dtrap() macro to invoke whatever debugger may be in use by the programmer. In this way, it acts like an embedded breakpoint. The stack code can continue executing after a dtrap(), but the dtrap() typically indicates that something is wrong with the port.
Note
Products based on this code should not be shipped until all calls to dtrap() have been removed from the code. You can redefine dtrap() to a null macro to slightly reduce code size.
As shipped, dtrap() does not cause a break into the ARM Debugger for Windows or armsd. To cause dtrap() to break into either of these debuggers, you must enter the command break @dtrap at the debugger command prompt.
2-6 |
Copyright © 1998 and 1999 ARM Limited. All rights reserved. |
ARM DUI 0079B |

TCP/IP Porting
initmsg() and dprintf()
The initmsg() and dprintf() macros have the same function and syntax as printf(). They have different names so their output can be redirected to different locations, or so they can be disabled.
The initmsg() macro is called by various stack functions to print function status messages during initialization. These messages are for information and are not warnings.
The dprintf() macro is used throughout the stack code to print warning messages when something seems to be wrong.
In most ports, these can both be mapped to printf() while the product is under development.
Note
Mapping initmsg() and dprintf() to printf() works with the ARM Software Development Toolkit 2.50, but performance of the stack is severely affected by the time taken to transfer debugging information across the RDI link to the ARM debugger.
A more efficient alternative is to use low-level functions to replace putchar() and printf() and to write output to a UART or other console device. The file \misclib\ttyio.c contains an example dprintf() function that can be used in conjunction with \pid7tdm\uart.c for this purpose.
#define initmsg printf /* Same parms as printf. Called at */ /* boot time */
#define dprintf printf /* Same parms as printf. Called */ /* during run time */
For some products, it may be desirable to define these to a null macro before releasing.
#define |
initmsg |
/* |
define |
to |
nothing |
*/ |
#define |
dprintf |
/* |
define |
to |
nothing |
*/ |
NPDEBUG
Defining the NPDEBUG macro causes the debug code to be compiled into the application. The debug code performs tasks, such as checking for valid parameters and sensible configurations during runtime. The debug code invokes dtrap() or dprintf() to inform the programmer of detected problems. To make use of this feature, make sure NPDEBUG is defined during development.
#define NPDEBUG 1 /* enable debug checks */
ARM DUI 0079B |
Copyright © 1998 and 1999 ARM Limited. All rights reserved. |
2-7 |