Introduction
SW high-level design
The whole mechanism is built out of several components (software modules) designed to perform a designated role.
Not all of these modules were written by us, most are porting of open source code.
Components:
- SD Server : based on the httpd web server application example from uIP.
This module is responsible for HTTP serving of files over TCP/IP.
The file system is abstracted by the FServ component. - DHCPC : porting of the dhcpc application example from uIP. This module has one time role during system boot to acquire an IP address for the server.
- uIP : Porting of uIP 1.0 TCP/IP stack. Written by Adam Dunkels.
- Ethernet Driver : Porting of a standard enc28j60 MicroChip ethernet controller with SPI interface.
- FServ : Simplified file system interface and uniform access to directory list and file elements. This layer works on top of the FatFS file system module and is also responsible for html document generation in case of directory browsing.
- FatFS : Porting of FatFS embedded file system module. Written by ChaN.
- I/O Device Driver : Simple FatFS interface device driver for accessing the SD cards.
- SD/MMC Driver : Partial implementation of the SD/MMC protocol. Porting of an example for implementation from NXP.
- SPI {0,1} : Both Ethernet and SD/MMC use SPI as a bus. Separated as two distinct drivers to exploit the two SPI bus controllers available on board.

How It Works
Initialization
When the board starts it initializes all components in the following order:It starts uart first so it will be possible to see debug messages and then the lcd to print the IP to the LCD.
fopen("uart0", "w");
lcdInit();
It then initializes the clock:
clock_init();
The clock is used by uIP in order to set timers in the TCP/IP implemetation and also in the main loop for the 'periodic' and 'arp' timers.Next we initialize the the filesystem module:
fsInit();
This is really a lazy data structure initialization because the SD card init (mmc_init()) and fs mount (auto_mount()) happen automatically when a file is accessed using the fs API (f_open, f_stat etc.)Next, the network is initialized.
network_init();
This code initializes the ethernet enc28j60 extension.
We then initialize uip, set the mac address to a static address we chose randomly. Finally, we start the HTTP server and the DHCP client.
uip_init();
...
uip_setethaddr(macaddr);
...
network_set_mac((uint8_t *)&(macaddr.addr));
...
httpd_init();
...
dhcpc_init(macaddr.addr, sizeof(macaddr.addr));
Getting an IP
The project implements a DHCP Client in order to obtain an IP dynamically at boot time when connected to a router.Basically there are three steps to obtain the IP :
1. The client broadcasts a DHCP_DISCOVER packet.
2. The router responds with a DHCP_OFFER packet including a free valid IP address.
3. The device sends a DHCP_REQUEST packet with his requested IP address.
4. Router sends DHCP_REQUEST_ACK packet if completed successfully.
DHCP client sequence is coded as following:
handle_dhcp() { ... send_discover(); ... if (uip_newdata() && parse_msg() == DHCPOFFER) { do { ... send_request(); ... if(uip_newdata() && parse_msg() == DHCPACK) { s.state = STATE_CONFIG_RECEIVED; break; } ... } while (s.state != STATE_CONFIG_RECEIVED); dhcpc_configured(&s); } }Then the dhcpc_configure() routine is responsible for setting the host addr and default gateway.
This function also shows LCD output for the configured IP address.
dhcpc_configure(const struct dhcpc_state *s) { uip_sethostaddr(s->ipaddr); uip_setdraddr(s->default_router); uip_setnetmask(s->netmask); ... lcdPrintString(ipmsg); }
Serving requests
The HTTP implementation supports only HTTP GET. When the server receives a GET request it parses it and builds a path for the FServ module. The FServ module check whether the given path is a directory or a file. If it is a directory it builds a directory listing and returns it to the caller. Otherwise, the file is read and returned to the caller. Both dir listings and file data are sent in chunks according to the uip_mss. FServ uses the FatFS driver in order to get filesystem data. FatFS uses the underlaying SD driver to perform raw data reads from the SD card.Download
To get the latest revision:
svn checkout http://tauembedded.googlecode.com/svn/trunk/project/src/trunk lpc2148-nas
Screenshots

Shot taken after a successful IP configuration with router.

FAQ
What do I need in order to run this code ?
You will need the following:
- Embedded Artists LPC2148 Education Board (v2 or v3)
- 10M Ethernet Expansion Board or Experiment Expansion Board
- The GNU ARM Toolchain
Under which license is your code released ?
The code is release under GPLv3
Does your code have any known issues ?
You can look at our GoogleCode issue list
We will also appreciate it if you tell us about bugs or problems you find in our code.
How do the jumpers on board need to be set for your code to work ?
You should set ethernet to work with spi0 and sd to work with spi1.
On the Ethernet extension: SO,SI and SCK pins should be set to SPI0 as drawn on the board itself
On LPC2148 you should set the SD card to work with SPI1.
The following images describe the correct jumper setting:
For LPC2148 (v2):
For the ethernet extension:
Future Work
- Upload files : One important feature that this projects lacks is the ability to upload files to the board.
This can be achieved by implementing an ftp server on the board or by extending the http server implemntation in order to support HTTP PUT or HTTP POST which gives the abillity to upload files. - Server side scripting : there is some basic scripting code available in the httpd
web server example from uIP,
however we did not use it and it could be a nice future extension to use such scripting combined with user interaction to create an interface to the board features.
(e.g. turn the rotor, display messages to the LCD or blink leds). - Server configurability : There is no supported configurations, the server has only one hard coded configurations and it could be nice to add the ability to configure the server either at compile or even better at run time.
- USB interface : Simple interface could be used (with terminal or a driver) to convey commands to the
web server such as server configuration.
It could be interleaved with a USB mass storage driver to edit the card content.
Testing & Performance
SD cards of two sizes were used: 1GB and 32MB. Both of which presented similar performance.
Most tests were performed when the board was connected to a switch which was connected to a router and to other PCs.
No real performance, stress testing & benchmarking was done, however the maximum speed we achieved using our setup was 5KB/s download.
About & Contact
This project was done by Michael Gendelman and Eyal Widder as part of the course "Advanced Computer Systems: Embedded Systems" at the Tel-Aviv University.
Our emails:
Michael: genged at gmail dot com
Eyal: wieyal at gmail dot com