Internet Connectivity: The Time is Right and the Technology is Ready For You
by Olaf Pfieffer, Embedded Systems Academy, Inc. and John Rodrigues, CMX Systems, Inc.
Introduction
Embedded Networking and Internetworking implementations are on the rise. However, anecdotal evidence from engineers gathered at trade shows and seminars across the country indicates that the embedded industry is still in the exploration stage: everybody knows that they eventually need to have some type of Internet connectivity on their embedded devices, but it's really not a priority. And yet, decisions to add Internetworking capability now may eliminate the need for costly redesign in the near future.
If an embedded system already has access to a PC of some sort (either directly connected to one or maybe using an embedded PC within), providing Internet access is not really a challenge. Commercially available software and protocol stacks can greatly help to reduce development time and speed integration of the involved network technology, even for tiny 8-bit devices. The greatest hurdle for Embedded Internetworking today is not the technology itself but predicting its usage in the future.
This article will explore some of the variables involved in adding Internet connectivity to an 8-bit device, discuss current developments in the field of Embedded Internetworking, and offer an application example to provide a closer look into one possible route for Internet enabling embedded devices based on the implementation of a TCP/IP to CANopen (Controller Area Network) gateway.
Internet Connectivity Parameters
Due to a lack of standards regarding "remote access" implementation for embedded systems*, the number of technical variations is great. For example, which physical media should one assume? Ethernet? If the answer is yes, is there a DHCP server to assign an IP address or will a static IP address need to be assigned? Alternately, if the choice is to dial-up via a modem, which phone number and ISP will be chosen, which protocols and services will be needed for support (Email, Web Server, and/or FTP Server), and what about reliability and security issues?
Perhaps the biggest challenge in determining a design route is the "gateway question." Do we allow our embedded device to directly communicate with the Internet - or will all communication be funneled through a gateway? And if a gateway is used, where does that come from? Is it an external product? Or is it part of the embedded system - potentially running on one of many controllers within the application?
The preceding question highlights a trend in the embedded industry in which embedded systems often consist of several microcontrollers communicating with each other. This is especially true for any machinery with multiple sensors and/or actuators. If a local network already exists (something like a proprietary serial bus, CAN/CANopen, DeviceNet, LON or USB - just to name a few), the logical approach is to try to implement a gateway between the local network and the Internet, thereby providing "remote access" to all local nodes.
*To address the standardization of the methods and protocols used to access embedded devices, the authors of this article currently work with several companies and universities on an Internet Draft that eventually might become an RFC (Request For Comments) published with the RFC-Editor (www.rfc-editor.org). For further information on Embedded Internetworking and to read the latest about the Internet Draft on "Embedded Internetworking with Remote Access", please go to www.embeddedinternetworking.com
Case Study: Implementing TCP/IP to CANopen gateway on an 8-bit Processor
When Embedded Systems Academy was approached by NXP Semiconductors to prove that such Embedded Internetworking gateway applications could be implemented on a regular 8051 microcontroller, we accepted the challenge - and designed and built a prototype of a gateway between the Internet and a CAN/CANopen network. See figure 1 for an illustration of the components.
The choice for using CAN and CANopen was made due to its increasing popularity in embedded machine control applications. Since CAN interfaces are available directly on-chip with a wide selection of 8-bit and 16-bit microcontrollers from many semiconductor manufacturers, developers can most likely find a derivative of their favorite microcontroller that has a CAN interface on-chip. Besides a transceiver and the connector, no additional hardware is required to connect such a microcontroller to a CAN bus that just requires a twisted pair as physical media.
As usual with embedded projects today, time-to-market is an issue, even in a "proof of concept" project. Due to customer requirements, the prototype based on the Philips 8xC591 Rapid Development Starter Kits from Phytec had to be completed in less than three weeks.
This implementation of a network protocol stack is a perfect example of how to shorten time-to-market by selecting off-the-shelf software products. Instead of re-inventing the wheel and writing the network protocol stacks for TCP/IP and CANopen ourselves, we chose commercial, off-the-shelf implementations specifically optimized for 8-bit and 16-bit microcontrollers, and which included all source files.
Adapting the Software
Once the hardware components and development tools were in place, implementation was straightforward. Using #define statements, the source code was configured to enable/disable certain protocols and features. We enabled modem and PPP support, as the serial channel of the 8051 was connected to an external modem and we wanted to allow users to dial-up the system. Furthermore we selected TCP (vs. UDP) as the main transport protocol and enabled the HTTP Web server.
After making the local adjustments to the timers (required to select a baud rate and to implement a timeout based on multiples of milliseconds) and assigning some fixed IP addresses to both the local server and the dial-up host, we quickly finished the microcontroller specific adaptations.
Before activating the Web server, we needed to have some Web pages in place. Fortunately, they can be written in standard HTML. We used a conversion utility to convert any DOS/Windows file (no matter if HTML, GIF or other) into a pair of .h and .c files. These were directly included into the project and easily added to the minimized virtual file system implemented within the TCP/IP software stack.
We were then ready for the first test: Our computer's internal modem was connected via a telephone line to the external modem that was connected to the serial port of the 8051. Using an in-circuit emulator we loaded the code to the application and hit "GO." On the computer side we had to specify a new dial-up connection using the fixed, assigned IP number we specified earlier in the code.
Using the login name and password specified in the code, we had a successful dial-up. We started the Web browser and in the URL field we typed in the IP address of the 8051 board. As this is a closed system with no domain name server, the 32-bit IPv4 addresses have to be used to directly identify the connected computers.
Our two Web pages were displayed as static files with a small graphic served by an 8051 running at 12 MHz.
However, the excitement cooled off pretty quickly. We were only serving up plain, static Web pages with no application specific data. So, the next step was to implement Web pages that are dynamically updated by the server and display data from the application.
Dynamic Web Pages
To create dynamic Web pages, we used a method similar to one used by many "full-grown" Web servers to transmit dynamic pages: SSI - Server Side Includes.
Using some special HTML tags to indicate SSI, an HTML page can be marked up to insert dynamic data in the place of the tags. The SSI tag itself indicates the name of a function that the Web server needs to call locally to get access to the dynamic data. So for each SSI tag used, a function must be implemented within the application that will be called from the server. The syntax for these SSI tags is:
- <!--#exec cgi="FunctionName"-->
The implementation works as follows: During the initialization phase, the TCP/IP software builds up a list of all the applications SSI functions.
The entire process of requesting dynamic Web pages involves the following steps:
- When a Web page is requested, the server copies the page from its ROM location into a RAM output buffer.
- While copying, the server scans for SSI tags.
- If an SSI tag is found, the matching function within the application is called. The parameter passed on to the function is a char pointer to the current location in the output buffer.
- The SSI function can now directly insert ASCII characters into the output buffer. This could be as simple as converting a local variable that should be displayed into an ASCII string right into the output buffer.
- After the SSI function returns, the server updates the pointers used to ensure that continuous copying will not overwrite any of the data just copied into the output buffer by the SSI function.
- Steps 2. through 4. are repeated until the end-of-file is reached
- The server can now transmit the contents of the output buffer to the requesting host / Web browser.
Listing 1 shows the implementation of the SSI function getDIPVal that reads current settings of DIP switches and generates an appropriate ASCII representation. In this hardware environment, reading from the address 0xFF80 tells us the current DIP switch settings. A fixed value of 8 is returned for the length of the inserted ASCII text, as we will always process 8 bits. The output is "0" for switch is off and "1" for switch is on.
- #define DIP_ADDR 0xFF80
- // passed is a pointer to the web page buffer
- // returned is the number of characters inserted
- // into the web page buffer by the function
- word16 getDIPVal(byte *str) cmx_reentrant
- {
- char xdata *dPTR;
- byte DIP, c;
- // initialize a pointer to the DIP switches dPTR = DIP_ADDR;
- // read DIP switches DIP = *dPTR; c = 0x80;
- // step through bits in read value
- while (c > 0)
- {
- // if bit is set then insert '1' otherwise
- // insert '0' into the web page
- if ((DIP & c) > 0)
- *str++ = '1';
- else
- *str++ = '0';
- c = c >> 1;
- }
- // return size of data inserted into the web page
- return (8);
- }
To use this SSI function in a Web page and get an array of 8 digits representing the settings of the DIP switches, we just have to insert something like the following into the HTML code:
- ...
- <p>
- Current settings of the DIP switches: <b><!--#exec cgi="getDIPVal"--></b>
- </p>
- ...
Feedback With Forms
So far, we had the option of getting data from the application transmitted to the browser of the user - what we still needed was a way to get commands from the user back to the application.
This functionality can be implemented using standard HTML forms. Much as with the SSI functions, the Web page needs to contain the tags to build a FORM and indicate the name of the POST function to be executed within the Web server.
Let's assume we have a form with a text field for user input and maybe a pull-down menu with a few items. Once the user hits the "Send" or "Submit" button, a POST request is sent to the HTTP server with all variable settings squeezed into a single ASCII line. The format of this line is the same as used when passing variables in URLs:
- variable1=value1&variable2=value2&variable3=value3...
In case spaces are used in string variables, they have to be replaced by "%20".
Once the HTTP server receives such a POST message, it locates the application function matching the post request and executes it. The TCP/IP software eases the search for a specific variable in this ASCII line by providing search functions that allow the application function for that FORM to easily detect the variables and their current settings and respond accordingly.
Our example in listing 2 shows a function that is called by the HTTP server when a certain POST request is detected. In this case the variables named "d1" and "d2" are detected and used to switch on/off 2 LEDs.
- // passed is a pointer to the socket being used for
- // the web server end of the connection that just
- // received a POST command
- void mypostfunction(PSOCKET_INFO socket_ptr)
- {
- // buffer to receive values of posted variables
- byte buf[2];
- // turn d1 on or off depending on whether a variable
- // called d1 was posted or not
- if (mn_http_find_value(BODYptr, (byte *)"d1", buf))
- *LEDs = *LEDs | 0x10; // led d1 on
- else
- *LEDs = *LEDs & 0xEF; // led d1 off
- // turn d2 on or off depending on whether a variable
- // called d2 was posted or not
- if (mn_http_find_value(BODYptr, (byte *)"d2", buf))
- *LEDs = *LEDs | 0x20; // led d2 on
- else
- *LEDs = *LEDs & 0xDF; // led d2 off
- // return HTTP code 204 which means "no content" in the
- // response, however anything could be returned including
- // a new web page or a redirect command
- socket_ptr->send_ptr = (byte *)HTTPStatus204;
- socket_ptr->send_len = STATUS_204_LEN;
- }
Continuous Refresh
By now, the user can view dynamic data from the embedded device and send data to it. However, all communication is user-driven in that the user needs to initiate every request. Wouldn't it be nice to see a window constantly updating / refreshing itself with the dynamic data from the embedded device without the need of user intervention?
If one refresh every few seconds is sufficient, the HTML REFRESH tag can be used to make the browser refresh the display automatically every few seconds by re-requesting the Web page. However, this causes overhead issues as the entire Web page gets transferred every time (also the static part) and it does not allow faster updates.
A faster, more efficient window refresh cycles can be achieved using Java. A Java applet can establish an additional TCP/IP channel between the host computer and the embedded Web server. As the implementation of this TCP/IP channel is customized on both ends of the communication, it can be highly optimized to transfer only the required data.
In this application, we used it to transfer all the data from the CAN/CANopen network in the embedded device and the Java applet implements a basic CAN monitor that constantly displays all the CAN/CANopen messages in the Web browser.
Security
One point not yet addressed is security. In this example, we implemented a PPP dial-up server and thus disconnected the application physically from the Internet. To get access, a user must know the telephone number to dial and know the PPP login name and password.
On the downside, the system in this application is never connected to the Internet. We always just have a point-to-point connection between the server and the host computer dialing in creating a mini-Intranet.
Putting the system onto the "real" Internet would require implementing some additional security functionality either directly into the system or into an external firewall type device. (Putting the system on the 'real internet' can be done without any changes to the commercial TCP/IP stack. Only the security aspects of the design require changes to the code.)
Summary
While Embedded Internetworking has tremendous growth potential, because there are so many diverse industries involved in the development of Embedded Internetworking solutions, it is unlikely that we will see a dominant standard for Embedded Internetworking solutions any time soon. As a result, it is difficult to predict what the technology's usage will be in the future, but implementing commercially available software and protocol stacks now, will not only help to reduce development time and speed integration of the involved network technology now, but also can provide designers with added flexibility to grow and change dynamically as the technology evolves.