Ethernet TCP/IP Source Code Driver Project
Section 02. Adding The Driver To Your Project

02. Adding The Driver To Your Project

a) Notes About Our Source Code Files

How We Organise Our Project Files

There are many different ways to organise your source code and many different opinions on the best method! We have chosen the following as a very good approach that is widely used, well suited to both small and large projects and simple to follow.

Each .c source code file has a matching .h header file. All function and memory definitions are made in the header file. The .c source code file only contains functions. The header file is separated into distinct sections to make it easy to find things you are looking for. The function and data memory definition sections are split up to allow the defining of local (this source code file only) and global (all source code files that include this header file) functions and variables. To use a function or variable from another .c source code file simply include the .h header file.

Variable types BYTE, WORD, SIGNED_WORD, DWORD, SIGNED_DWORD are used to allow easy compatibility with other compilers. A WORD is 16 bits and a DWORD is 32 bits. Our projects include a ‘main.h’ global header file which is included in every .c source code file. This file contains the typedef statements mapping these variable types to the compiler specific types. You may prefer to use an alternative method in which case you should modify as required. Our main.h header file also includes any project wide global defines.

This is much easier to see in use than to try and explain and a quick look through any of the included sample projects will show you by example.

Please also refer to the resources section of the embedded-code.com web site for additional documentation which may be useful to you.

Modifying Our Project Files

We may issue new versions of our source code files from time to time due to improved functionality, bug fixes, additional device / compiler support, etc. Where possible you should try not to modify our source codes files and instead call the driver functions from other files in your application. Where you need to alter the source code it is a good idea to consider marking areas you have changed with some form of comment marker so that if you need to use an upgraded driver file it is as easy as possible to upgrade and still include all of the additions and changes that you have made.

b) Step By Step Instructions

Move The Main Driver Files To Your Project Directory

The following files are the main driver files which you need to copy to your main project directory:

eth-main.c – TCP/IP Stack main functions

eth-main.h

eth-arp.c – Address resolution protocol functions

eth-arp.h

eth-ip.c – IP functions

eth-ip.h

eth-nic.c – Network Interface IC functions. Select the pair of files for the nic

eth-nic.h device being used.

Move The Generic Global Defines File To You Project Directory

The generic global file is located in each driver sample project directory. Select the most suitable sample project based on the compiler being used and copy the following file to your main project directory:

main.h – The embedded-code.com generic global file

Check Driver Definitions

Check the definitions in each of the following files to see if any need to be adjusted for the microcontroller / processor you are using, and your hardware connections:-

eth-main.h

eth-nic.h

Timers

You will need to provide some form of timer for the driver. Typically this can be done in your applications general heartbeat timer if you have one. These timers do not have to be interrupt based.

Do the following every 1mS (if DHCP is being used):-


	//----- NIC DHCP TIMER -----
	if (eth_dhcp_1ms_timer)
		eth_dhcp_1ms_timer--;

Do the following every 10mS:-


	//----- ETHERNET GENERAL TIMER -----
	ethernet_10ms_clock_timer_working++;

Do the following every 1 Second (if DHCP is being used):-


	//----- NIC DHCP TIMERS -----
	if (eth_dhcp_1sec_renewal_timer)
		eth_dhcp_1sec_renewal_timer--;
	if (eth_dhcp_1sec_lease_timer)
		eth_dhcp_1sec_lease_timer--;

Application Requirements

In each .c file of your application that will use the driver functions include the following file

eth-main.h

If your application will use manually configured IP settings it needs to do the following function as part of its power-up initialisation:


	//----- CONFIGURE ETHERNET -----
	eth_dhcp_using_manual_settings = 1;
	our_ip_address.v[0] = 192;		//MSB
	our_ip_address.v[1] = 168;

	our_ip_address.v[2] = 0;

	our_ip_address.v[3] = 51;		//LSB
	our_subnet_mask.v[0] = 255;		//MSB
	our_subnet_mask.v[1] = 255;

	our_subnet_mask.v[2] = 255;

	our_subnet_mask.v[3] = 0;		//LSB
	our_gateway_ip_address.v[0] = 192;
	our_gateway_ip_address.v[1] = 168;
	our_gateway_ip_address.v[2] = 0;
	our_gateway_ip_address.v[3] = 1;

	//----- SET OUR ETHENET UNIQUE MAC ADDRESS -----
	our_mac_address.v[0] = 0x00;	//MSB	(This is a generic address - replace
	our_mac_address.v[1] = 0x50;	//with your own globally unique MAC 	our_mac_address.v[2] = 0xC2;	//address for release products)
	our_mac_address.v[3] = 0x50;
	our_mac_address.v[4] = 0x10;
	our_mac_address.v[5] = 0x32;	//LSB

	//----- INITIALISE ETHERNET -----
	tcp_ip_initialise();

Or if your application will use DHCP (Dynamic Host Configuration Protocol) to obtain IP settings from a network DHCP server it instead needs to do the following function as part of its power-up initialisation:


//----- CONFIGURE ETHERNET -----
	eth_dhcp_using_manual_settings = 0;

	//----- SET OUR ETHENET UNIQUE MAC ADDRESS -----
	our_mac_address.v[0] = 0x00;	//MSB	(This is a generic address - replace
	our_mac_address.v[1] = 0x50;	//with your own globally unique MAC 	our_mac_address.v[2] = 0xC2;	//address for release products)
	our_mac_address.v[3] = 0x50;
	our_mac_address.v[4] = 0x10;
	our_mac_address.v[5] = 0x32;	//LSB

	//----- INITIALISE ETHERNET -----
	tcp_ip_initialise();

Your application needs to periodically call the drivers background processing function. Typically this should be done as part of your applications main loop. This function deals with all the background TCP/IP stack processing tasks. Add the following call:-


	//----- PROCESS ETHERNET STACK -----
	tcp_ip_process_stack();

MAC Address

Every Ethernet device requires a globally unique MAC (Media Access Control) address. This is the lowest level adaptor address which is used at the level below IP addresses. Blocks of MAC addresses may be officially purchased from the IEEE.

When you purchase a network interface card for say a PC the card will contain a unique MAC address that will have been assigned to it by the manufacturer. However when you use a nic (network interface controller) IC you typically need to tell it what MAC address to use as part of its power up initialisation sequence. Therefore, unless the nic you are using incorporates its own MAC address, or you are using eeprom memory connected to the nic that has been pre-programmed with a unique MAC address, your application will need to provide the means to be assigned a MAC address at manufacture, which is unique to each device manufactured, so that it can pass it to the nic every time it is powered up.

The following MAC addresses are assigned to us and may be used for development purposes:-

00:50:c2:50:10:32

00:50:c2:50:10:33

00:50:c2:50:10:34

00:50:c2:50:10:35

00:50:c2:50:10:36

IPAddress

The Internet Assigned Numbers Authority (IANA) manages the global IP address space. IPv4 addresses are becoming a precious resource these days, but the use of routers has put off the predicted crises that had been forecast of IP addresses running out. As embedded devices will typically sit behind a router of some sort before any connection to the internet (if they are connected to the internet at all) it is typically the case that IP addresses from the unassigned general use blocks will be used. IP addresses must be unique to every device on a local network, but they do not need to be globally unique as when a router passes packets on to a higher level network (for instance the internet or a corporate network) it will replace the packets sender address with its own IP address and remember which device any response will need to be directed to on the local network, should a response be received. This is called Network Address Translation (NAT) and its why routers are so good at providing a firewall – if an unsolicited packet arrives from the higher level network they have no knowledge of where to sent it on the local network so have to discard it.

The following are IANA reserved private network ranges that you may use on a local network:

Size, Start of range, End of range,  Total addresses

24-bit Block 10.0.0.0, 10.255.255.255, 16,777,216

20-bit Block 172.16.0.0 172.31.255.255, 1,048,576

16-bit Block 192.168.0.0, 192.168.255.255, 65,536

c) Individual Stack Components

Adding UDP Functionality

For fast non-managed data transfer. Client and server functionality provided by the driver.

Required for some other stack components.

Copy the following files to your main project directory:

eth-udp.c

eth-udp.h

In each .c file of your application that will use the UDP functions include the following file:

eth-udp.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-udp.h

UDP Checksum Header File Option

UDP checksum field transmission and received packet checking of checksums checksum can be turned off if desired to improve performance. If you application will only communicate over a local network then its safe to turn off the UDP checksum functions as the Ethernet packet CRC (generated by the nic) provides error detection. However if your UDP packets may travel over the internet or some other link, or if you don’t care about the extra bit of processing time required, then you should turn the UDP checksum functions on (using the UDP_CHECKSUMS_ENABLED define in eth-udp.h) as there is no guarantee that all the links between source and destination will provide overall packet error checking. Bear in mind that although UDP provides checksum error checking, a packet that contains an error will simply be discarded by the TCP/IP stack and never reach the socket it was intended for (there is no automatic re-try).

Adding TCP Functionality

For fast connection based managed data transfers, but with a significant overhead. Client and server functionality provided by the driver.

Required for some other stack components.

Copy the following files to your main project directory:

eth-tcp.c

eth-tcp.h

In each .c file of your application that will use the TCP functions include the following file:

eth-tcp.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-tcp.h

Adding HTTP Server Functionality

To provide web server functionality.

Requires TCP to be included.

Copy the following files to your main project directory:

eth-http.c

eth-http.h

In each .c file of your application that will use the HTTP functions include the following file:

eth-http.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-http.h

Adding HTTP Client Functionality

To provide the ability for the driver to connect to a remote http server and download files.  A really useful way of allowing embedded products to access updated information which can be created using normal web publishing tools.

Requires TCP to be included.  The HTTP server does not need to be included.

Copy the following files to your main project directory:

eth-http-client.c

eth-http-client.h

In each .c file of your application that will use the HTTP client functions include the following file:

eth-http-client.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-http-client.h

Adding DHCP Functionality

Not required if you will manually configure the IP address and subnet mask (and gateway address for some stack components). Include DHCP to allow your device to automatically request these settings from a network DHCP server on power-up and periodically when they need to be renewed (if there is no dedicated server on your network typically DSL routers include a DHCP server for simple home or small office networks).

Requires UDP to be included.

Copy the following files to your main project directory:

eth-dhcp.c

eth-dhcp.h

In each .c file of your application that will use the DHCP functions include the following file:

eth-dhcp.h

See the timers section earlier in this manual for details of the timers your application needs to implement for DHCP.

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-dhcp.h

Adding NetBIOS Functionality

Allows you to find your device using a text based name rather than IP address when trying to connect to it via a local network (not via a router). This can be very useful when using DHCP as you may not know what IP address has been assigned by a DHCP server, but with a NetBIOS name set you can use this to connect to it.

Requires UDP to be included.

Copy the following files to your main project directory:

eth-netbios.c

eth-netbios.h

In each .c file of your application that will use the NetBIOS functions include the following file:

eth-netbios.h

Adding DNS Functionality

Allows your embedded device to use text URL’s to connect to remote devices, such as mail servers or your own remote servers. An important feature to protect against changes in a remote servers IP address effectively stopping your device from connecting to it.

Requires UDP to be included.

Copy the following files to your main project directory:

eth-dns.c

eth-dns.h

In each .c file of your application that will use the DNS functions include the following file:

eth-dns.h

Adding POP3 Functionality

Automatically check for and download emails from a standard POP3 mailbox. Apart from obvious uses POP3 is a great way to work around strict network administrators in this security conscious world. If your embedded devices will be behind routers or firewalls you can use POP3 to allow your device to retreive messages via the internet, avoiding the need to configure routers or firewalls to allow an incoming connection.

Requires DNS and TCP to be included.

Copy the following files to your main project directory:

eth-pop3.c

eth-pop3.h

In each .c file of your application that will use the POP3 functions include the following file:

eth-pop3.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-pop3.h

Adding SMTP Functionality

Automatically send anyone emails in response to events or at fixed intervals. A file attachment may also be included with each outgoing email using the built in MIME BASE64 encoding.

Requires DNS and TCP to be included.

Copy the following files to your main project directory:

eth-smtp.c

eth-smtp.h

In each .c file of your application that will use the SMTP functions include the following file:

eth-smtp.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-smtp.h

Adding ICMP Functionality

An automatic component that responds to ping requests. Not a requirement but typically included in a TCP/IP Stack.

Copy the following files to your main project directory:

eth-icmp.c

eth-icmp.h

In each .c file of your application that will use the ICMP functions include the following file:

eth-icmp.h

Adding SNTP Functionality

Allows your embedded device to request the current time (in seconds since a reference date) from public NTP time servers.

Requires UDP to be included.

Copy the following files to your main project directory:

eth-sntp.c

eth-sntp.h

In each .c file of your application that will use the SNTP functions include the following file:

eth-sntp.h

Check the definitions in the following file to see if any need to be adjusted for your application:

eth-sntp.h

d) Important Hardware Design Notes

When using a nic good PCB layout is important. Apart from the usual reasons associated with high speed digital designs, reading and writing data to and from a nic is often achieved using fast DMA transfers or clocked serial busses such as SPI. These require clean signals on the Read and Write or Clock pins to the nic, as should noise be present false peeks can either cause the nic pointer to increment to the next memory location, causing additional bytes / words written to the nic or missed bytes / words read from the nic, or SPI transfers to be corrupted.

Please see the:

Signal Noise Issues With MMC & SD Memory Cards (& Clocked Devices In General)

page in the resources area of our web site for details of a common problem that may be experienced when using clocked devices of this type to ensure that you are aware of the potential problem and can make sure you avoid it in your hardware design.