manufacturer of I/O-rich SBCs, operator interfaces, handheld instruments, and development tools for embedded control low cost single board computers, embedded controllers, and operator interfaces for scientific instruments & industrial control development tools for embedded control order our low cost I/O-rich embedded control products embedded controller manufacturer profile single board computers & embedded controllers development tools & starter kits for your embedded design operator interfaces with touchscreens and graphical user interface plug-in expansion modules for digital & analog I/O C language & Forth language integrated development tools, IDE single board and embedded computer accessories embedded controller enclosures, bezels, environmental gaskets

The EtherSmart Wildcard User Guide

Table of Contents

Introduction

Internet Protocol Support

Summary of EtherSmart Capabilities

Hardware

Connecting To the Wildcard Bus

Selecting the Wildcard Address

Terminology Overview

Browser Notes

The EtherSmart Software Driver Routines

EtherSmart Driver Data Structures

The Demo Program

EtherSmart Initialization, Configuration and Diagnostics

Initialization Functions

Configuring the XPort Device

Assigning an IP Address

Reporting Routines

Using "Ping" for Diagnostics

Initializing Multiple EtherSmart Wildcards

Code Downloads and Interactive Communications via Ethernet

Serial Tunneling

A Serial Tunneling Example

Serial Tunneling Buffer Management Functions

Serial Tunneling Data Transmission and Reception Functions

Serial Tunneling Connection Functions

Serial Tunneling Inter-Task Service Management Functions

Sending Email

Introduction to the Dynamic Webserver

Using the Dynamic Webserver

HTTP Buffer Management

HTTP Header Generation

HTTP Data Transfer Functions

Web Form Processing

An Example of a Dynamic Web Page with a Remote Image Reference

Serving Out a Stand-Alone Image

Implementing a "Remote Front Panel" Using the Webserver

Appendix A: Installing the Software

Generating the EtherSmart Kernel Extension Library

Creating Web Page and Image Resources with the Image Converter

Loading the Software onto the Controller

Using the EtherSmart Driver with C

Using the Driver Code with Forth

Appendix B: C Demo Program

Appendix C: C Remote Front Panel Demo Program

Appendix D: Forth Demo Program

Appendix E: Forth Remote Front Panel Demo Program

Appendix F: Browser Configuration

Using Opera Is Highly Recommended

Reconfiguring the Internet Explorer Browser

Firefox and Mozilla

Appendix G: Hardware Schematic (pdf)

<< Previous | Next>>

Using the Dynamic Webserver

A comprehensive suite of pre-coded driver functions is available to simplify the implementation of an embedded webserver by your application program.  Most of these functions begin with the HTTP_ prefix to indicate that they are part of the web service suite.  These can be classified as buffer management, HTTP header generation, data transfer, form processing, handler posting, and inter-task service management functions.  Each of these is discussed in turn in the context of the constituent functions that implement the Web_Demo function (callable as main in C) from the demo program.

HTTP Buffer Management

Table 1‑9  lists the web service buffer functions.  The web service input and output buffers are called HTTP_Inbuf and HTTP_Outbuf. These can be used in any web handler function. The Ether_Connection_Manager routine that is running in the Ethernet task automatically stores the linefeed-delimited first line into the HTTP_Inbuf counted buffer, and examines the line to see if it starts with "GET ". If the first line starts with GET (which is the request keyword issued by a web browser), the connection manager invokes the web server. 

Table 1‑9      Web Service Buffer Management Functions.

Cat

HTTP_Outbuf_Cat

HTTP_Inbuf

HTTP_Outbufsize

HTTP_Inbufsize

HTTP_OUTBUFSIZE_DEFAULT

HTTP_INBUFSIZE_DEFAULT

HTTP_Set_Inbuf

HTTP_Outbuf

HTTP_Set_Outbuf

Web connections are typically handled "in the background" without the need for intervention by the application program.  This is very convenient, but it implies that dedicated HTTP buffers must be used for web service.  Hard to diagnose multitasking errors can result if the HTTP buffers are used to implement other services (such as tunneling or email), or if the Ether_Inbuf or Ether_Outbuf buffers are used to implement web handlers as well as tunneling or email services.  In other words, use separate buffers for web service as opposed to other Ethernet services.

Each of the buffers HTTP_Inbuf and HTTP_Outbuf has a default maximum size that is set at initialization time. In this context, the "size" is the maximum number of data bytes (not including the count stored in the first 2 bytes of the buffer) that can fit in the buffer.  The default sizes of the HTTP_Inbuf and HTTP_Outbuf are given by the constants HTTP_INBUFSIZE_DEFAULT (254 bytes) and HTTP_OUTBUFSIZE_DEFAULT (1022 bytes) respectively.  HTTP_Inbuf can be smaller because it only needs to hold one input line at a time, while HTTP_Outbuf should be able to accommodate multi-line strings to serve out web page content.  The functions HTTP_Inbufsize and HTTP_Outbufsize return the sizes of the HTTP_Inbuf and HTTP_Outbuf, respectively.  The Cat and HTTP_Outbuf_Cat functions that write to the buffers accept the maximum buffer size as an input parameter, and ensure that they never write beyond the allowed buffer size.

If you need specify a new buffer base xaddress or size that is different from the values set at initialization time, use the functions HTTP_Set_Inbuf and HTTP_Set_Outbuf.

HTTP Header Generation

The HTTP standard specifies that a webserver should respond to a GET request with a properly formatted HTTP header followed by a single blank line followed by the content.  This HTTP header should not be confused with the HTML <head> tag that specifies special content within an HTML page.  The HTTP header tells the browser about the nature of the content that is about to be served by the embedded webserver.  Table 1‑10 lists the EtherSmart functions that make it easy to serve a valid HTTP header.

Table 1‑10    HTTP Header Generation Functions.

HTTP_BINARY_DATA_CONTENT

HTTP_Put_Content_Type

HTTP_IMAGE_BITMAP_CONTENT

HTTP_Put_Header

HTTP_IMAGE_GIF_CONTENT

HTTP_TEXT_HTML_CONTENT

HTTP_IMAGE_JPEG_CONTENT

HTTP_TEXT_PLAIN_CONTENT

HTTP_IMAGE_PNG_CONTENT

 

The HTTP header specifies the content type (text/html, image/bitmap, etc.) and whether the referenced page can be "cached" by the browser for fast display after the initial loading.  "Static" web pages can be safely cached, as they do not change over time.  "Dynamic" web pages, on the other hand, should not be cached because they contain dynamic data that changes with time under the control of the application program. 

In the demo program, the Opera_Config_Page shown in Listing 1‑8 serves out an unchanging HTML web page.  The Home_Page function discussed below, on the other hand, serves HTML text plus the elapsed time between system initialization and the time the web page is served. Thus the static Opera_Config_Page handler should have a header that tells the browser that it is allowed to cache the page and restore it from memory if it is re-requested.  The Home_Page function, on the other hand, must have a header that tells the browser not to cache the contents, as this would render the time report inaccurate.

The Opera_Config_Page source code in Listing 1‑8 provides an example of how to serve out a simple static web page whose text is defined in a *.html resource file. Note that all web handler functions must accept a single input parameter (the modulenum) and return no parameters

In this code excerpt, we first initialize some variables that are passed as parameters to Ether_Get_Line. One of the rules of calling operating system or kernel extension functions is that no function nesting is allowed: it is illegal to invoke one of these functions within the parameter list of another.  By capturing the results returned by the HTTP_Outbuf and HTTP_Outbufsize functions into variables, we avoid the nesting prohibition when calling the EtherSmart driver functions invoked inside Opera_Config_Page.

Listing 18     A Handler Function from the Demo Program that Serves Static HTTP Header and HTML Text.

void Opera_Config_Page( int modulenum )

// this is the handler function for the /opera_configuration.html URL.

// sends the http header with static text/html content type,

// followed by opera_config.html text

{  xaddr http_outbuf_base = HTTP_Outbuf(modulenum);

   uint http_outbuf_size =  HTTP_Outbufsize(modulenum);

   HTTP_Put_Header(http_outbuf_base, http_outbuf_size);  // http header->outbuf

   HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size,0,

HTTP_TEXT_HTML_CONTENT);

                  // params: xlbuf,maxbufsize,dynamic?,content_type

                  // static text/html content ->outbuf;header is done

   HTTP_Send_LBuffer(http_outbuf_base, modulenum);

// send out header, ignore #bytes_sent

   HTTP_Send_Buffer(OPERA_CONFIG_HTML_XADDR, OPERA_CONFIG_HTML_SIZE, modulenum);

}                 // send opera_config.html, ignore #bytes_sent

 

After initializing some local variables to the HTTP_Outbuf and HTTP_Outbufsize, there is a call to HTTP_Put_Header. This puts the following invariant portion of the EtherSmart Wildcard’s standard HTTP header into the specified LBuffer:

 

HTTP/1.1 200 OK

Server: Mosaic Industries Embedded Webserver

Connection: close

Content-Type:

There is a space after the Content-Type: field.  The string count is stored in the first 2 bytes of the specified LBuffer, with the ASCII characters following. The first line announces the webserver as an HTTP/1.1 protocol server; the 200 OK means that the GET request has been received and a valid handler has been found that corresponds to the incoming URL. The second line announces the name of the webserver.  The third line means that the webserver will close each connection after the GET request has been fulfilled, and "persistent connections" are not supported.  The last line announces the content type which is typically filled in by HTTP_Put_Content_Type, but can also be accomplished using a Cat command with any arbitrary string to specify the content type. Note that one and only one empty line terminated by a carriage return/linefeed sequence must follow the header. The call to HTTP_Put_Content_Type does this in Listing 1‑8. HTTP_Put_Content_Type expects as input parameters an LBuffer xaddress and maximum buffer size, a flag that is true if the web content is dynamic or false if it is static, and a constant that specifies the content type to be announced.  As shown in Table 1‑10, there are constants defined for a variety of data types, including text/html, text/plain, image/gif, image/jpeg, image/png, and binary data.  The PNG image type is noteworthy because it is a standard non-proprietary image format.

In this example, the completed header placed in the HTTP_Outbuf by HTTP_Put_Header and HTTP_Put_Content_Type is:

 

HTTP/1.1 200 OK

Server: Mosaic Industries Embedded Webserver

Connection: close

Content-Type: text/html

This announces the page as text/html content.  It is left to the browser to decide whether to cache the page; most browsers will cache web content by default. 

If we had passed a true flag to the HTTP_Put_Content_Type to indicate that the web content was dynamic, the following header would have been produced:

 

HTTP/1.1 200 OK

Server: Mosaic Industries Embedded Webserver

Connection: close

Content-Type: text/html

Cache-Control: no-cache

The last line of this HTTP header for dynamic content tells the browser not to cache the content, thereby forcing the browser to reload the page each time it is requested.  This ensures that the latest version of the dynamically generated web content is presented in the browser window.

Now that the HTTP header is stored in the HTTP_Outbuf, it is ready to be sent out to the web browser.

Rule for Web Handler Functions

All web handler functions must accept a single input parameter (the modulenum) and return no parameters.

 

HTTP Data Transfer Functions

The final two function calls in the Opera_Config_Page function in Listing 1‑8 send out the HTTP header and the HTML web page content, respectively:

 

HTTP_Send_LBuffer(http_outbuf_base, modulenum);

// send out header, ignore #bytes_sent

HTTP_Send_Buffer(OPERA_CONFIG_HTML_XADDR, OPERA_CONFIG_HTML_SIZE, modulenum);

                 // send opera_config.html, ignore #bytes_sent

Recall that the local variable named http_outbuf_base is declared as an xaddress holding a 32-bit extended address, and is initialized to hold the value returned by HTTP_Outbuf. modulenum is the input parameter passed to the Opera_Config_Page function.  HTTP_Send_LBuffer sends out the HTTP header which has been placed into the HTTP_Outbuf. Then HTTP_Send_Buffer sends out the HTML web page.  The HTML source for this page can be found in the file named opera_config.html in the \Resources subdirectory of the EtherSmart demo folder.  The Image Converter program was used to convert this page and the other resources into S-record data that is loaded into flash when the image_data.txt file is downloaded to the Mosaic controller.  The image_headers.h file contains the definitions of the 32-bit xaddress OPERA_CONFIG_HTML_XADDR constant and the 16-bit OPERA_CONFIG_HTML_SIZE constant that refer to the web page resource in memory.

Now we’ve reviewed all of the functions needed to send out the static web page from Listing 1‑8.  It’s as easy as using HTTP_Put_Header and HTTP_Put_Content_Type to create the header, and calling HTTP_Send_LBuffer and HTTP_Send_Buffer to send the header and web content.

Table 1‑11 lists the HTTP data transfer functions that should be invoked inside web service handlers to send out the HTTP header and web content.  HTTP_Send_2Buffers sends two buffers one after another.  HTTP_Numbytes_Sent returns the number of bytes sent by the last execution of HTTP_Send_Buffer, HTTP_Send_LBuffer, or HTTP_Send_2Buffers.

Table 1‑11    HTTP Data Transfer Functions.

HTTP_Get_Timeout_Msec_Ptr

HTTP_Send_Buffer

HTTP_Numbytes_Sent

HTTP_Send_LBuffer

HTTP_Send_2Buffers

HTTP_Timeout_Msec_Ptr

HTTP_Get_Timeout_Msec_Ptr returns the 32-bit xaddress of a 16-bit timeout variable used by the Ether_Connection_Manager during the attempt to identify an incoming web connection.  The default value is 5000, corresponding to 5 seconds.  If an incoming carriage-return/linefeed-delimited line is not available on the connection within the specified timeout, and if the contents of HTTP_Enable_Ptr are nonzero, the input operation will cease when the timeout is reached, and the HTTP identification will then proceed. Increasing the value of this timeout beyond its default value may improve the robustness of web service on some networks.  Note, however, that an incoming serial tunneling connection that does not promptly send a carriage-return/linefeed-delimited line effectively delays the recognition of an incoming serial tunneling (as monitored by Ether_Connect_Status) by the value of this timeout parameter.

HTTP_Timeout_Msec_Ptr returns the xaddress that holds a 16-bit timeout for outgoing HTTP traffic in units of milliseconds.  The maximum allowed timeout is 65,535.  This timeout is used by HTTP_Send_Buffer, HTTP_Send_LBuffer, HTTP_Send_2Buffers, and the HTTP/GUI functions described in a later section. The default set by Ether_Setup_Default is 33000, corresponding to a 33 second timeout for outgoing HTTP traffic.  You may need to increase this value if you are serving large files over slow or congested networks. 

Note that you must use the paged store routine StoreInt to update the timeout parameters.  For example, to change the HTTP incoming (Get) timeout to 3 seconds and the HTTP outgoing timeout to 40 seconds on module number 7, you could execute the following code:

 

xaddress http_get_timeout_msec_ptr = HTTP_Get_Timeout_Msec_Ptr(7);

xaddress http_timeout_msec_ptr = HTTP_Timeout_Msec_Ptr(7);

StoreInt(3000, http_get_timeout_msec_ptr);

StoreInt(40000, http_timeout_msec_ptr);

Web Handlers Are Posted to the Autoserve Array

The EtherSmart embedded webserver is configured by defining and posting a "handler function" for each web address that is implemented. The Opera_Config_Page source code in Listing 1‑8 provides an example of a handler function. Note that all web handler functions must accept a single input parameter (the modulenum) and return no parameters.

When the browser requests the web address URL (Uniform Resource Locator), the webserver looks for a match to the URL in the "Autoserve Array".  If a match is found, the webserver running in the Ethernet task automatically executes the associated handler function which performs any required actions and transmits the web page to the browser. If a match is not found, the HTTP_Default_Handler is executed.  This reports a "404 Page Not Found" error to the browser.

Table 1‑12  lists the routines used to post web service handler functions.  The "Autoserve Array" is a data structure that holds a pointer to each URL string, and the corresponding function pointer (execution address) of the handler associated with that URL.  HTTP_Autoserve_Ptr returns an address that contains the 32-bit base address of this array.  The Autoserve Array is set up by Ether_Info_Init and its calling functions (Ether_Init, Ether_Setup, Ether_Setup_Default, and Ether_Task_Setup) with 32 rows; HTTP_AUTOSERVE_DEFAULT_ROWS equals 32.  This sets the maximum number of URL/handler pairs that can be posted.  If you need to post more handlers, use HTTP_Is_Autoserve_Array to declare and size a new version of the array; see its glossary entry for details.  The functions HTTP_Add_Handler and HTTP_Add_GUI_Handler post the required information into this array, writing to the row pointed to by HTTP_Index_Ptr. Consequently, the programmer does not need to directly access the contents of this low-level data structure.

Table 1‑12    HTTP Functions to Manage Posting of Web Page Handlers.

HTTP_Add_Handler

HTTP_Default_Handler_Ptr

HTTP_AUTOSERVE_DEFAULT_ROWS

HTTP_Index_Ptr

HTTP_Autoserve_Ptr

HTTP_Is_Autoserve_Array

HTTP_Default_Handler

 

Listing 1‑9  presents the Web_Handler_Installation function from the demo program to illustrate how web handlers are posted. Simply pass as parameters to the HTTP_Add_Handler function the base xaddress and length of the URL string, the handler function pointer (as a 32 bit xaddress), and the modulenum.

The first part of Listing 1‑9 defines the URL strings for each web page handler in the demo program.  Note that:

  all of the URLs start with the / (forward slash) character; and,

  it is good practice to always define a single forward slash string as a URL associated with the home page. 

If a user types a bare IP address or computer name into the browser’s address bar, the browser sends a single / character as the URL, and the correct response is typically to respond with the specified device’s home page. 

The next section of Listing 1‑9 defines 32-bit function pointers for each of the handler functions.  This is a bit tricky because the processor has a native 16-bit address space.  While the Forth compiler always uses 32-bit paged xaddresses, the C compiler typically tracks addresses as 16-bit non-paged quantities.  To obtain a 32-bit xaddress that contains both the page and the address of the handler function, we follow the procedure shown in Listing 1‑9.  First we use the #ifdef statement to find out which compiler we are using; the method shown works for the Fabius compiler which is used on all controllers using the V4.xx operating system.  (The new PDQ line of products run the V6.xx operating system and the GCC tool chain, and use a different system to extract the 32-bit handler xaddress.)  The #pragma and #include </mosaic/gui_tk/to_large.h> statements tell the compiler to go into a mode in which 32-bit function pointers can be generated and stored in non-volatile flash memory.  Then the function pointers are defined.  For example, the 32-bit variable

 

   opera_config_page_ptr

is initialized to equal the 32-bit execution xaddress of the Opera_Config_Page routine defined in Listing 1‑8 using the statement:

 

xaddr (*opera_config_page_ptr)(void) = Opera_Config_Page;

After the nonvolatile 32-bit function pointers are captured, the #pragma and to_large.h compiler directives are reversed to return to normal compilation mode before compiling any functions. 

Then the Web_Handler_Installation function is defined to post the handler functions.  This function returns a nonzero error flag if the number of handlers posted exceeds the number of rows in the Autoserve Array (32 by default).  We OR the error value returned by each invocation of HTTP_Add_Handler to produce the overall error result.  The third call to HTTP_Add_Handler in  posts the handler for the Opera_Config_Page routine:

 

error |= HTTP_Add_Handler(STRING_XADDR(opera_url_str), strlen(opera_url_str),

            opera_config_page_ptr, modulenum);

The STRING_XADDR macro is defined in the strdefs.h file which is included at the top of the demo program.  It converts the 16-bit string address to a 32-bit xaddress, inserting the page at the time the calling function runs.  This macro is discussed in more detail in the "EtherSmart Driver Data Structures: Passing String Extended Addresses as Function Parameters" section above.  The strlen function is a standard C routine that returns the length of the specified string.  The opera_config_page_ptr parameter is the 32-bit execution address (function pointer) to the handler routine.  The modulenum completes the input parameter list in the call to HTTP_Add_Handler in Listing 1‑9.

Listing 19     Posting the Web Handler Functions in the Demo Program.

// url strings:

char* slash_url_str = "/"; // synonym for home page url

char* index_url_str = "/index.html"; // home page url

char* opera_url_str = "/opera_configuration.html"; // opera page url

char* form_entry_url_str = "/form_entry.html"; // form entry page url

char* form_response_url_str = "/form_response.cgi"; // form response page url

char* logo_response_url_str = "/logo_response.png"; // logo response page url

char seconds_str[16];   // will hold elapsed seconds string

 

#ifdef      __FABIUS__

#pragma option init=.doubleword    // declare 32-bit function pointers in code area

#include </mosaic/gui_tk/to_large.h>

#endif   // __FABIUS__

 

xaddr (*home_page_ptr)(void) = Home_Page;

xaddr (*opera_config_page_ptr)(void) = Opera_Config_Page;

xaddr (*form_entry_page_ptr)(void) = Form_Entry_Page;

xaddr (*form_response_page_ptr)(void) = Form_Response_Page;

xaddr (*logo_response_page_ptr)(void) = Logo_Response_Page;

 

#ifdef      __FABIUS__

#include </mosaic/gui_tk/fr_large.h>

#pragma option init=.init       // return the initialized variable area to RAM;

#endif   // __FABIUS__

 

int Web_Handler_Installation( int modulenum )

// call this after Ether_Task_Setup_Default

// point browser to raw ip or to ip/index.html to see the home web page.

// urls are case sensitive. any other url’s serve out: page not found.

// returns nonzero error if too many handlers were added

// (limited by AUTOSERVE_DEFAULT_ROWS passed to ether_init)

{  int error = 0; // we’ll OR error results together and return final result

   error |= HTTP_Add_Handler(STRING_XADDR(slash_url_str), strlen(slash_url_str),

            home_page_ptr, modulenum);

   error |= HTTP_Add_Handler(STRING_XADDR(index_url_str), strlen(index_url_str),

            home_page_ptr, modulenum);

   error |= HTTP_Add_Handler(STRING_XADDR(opera_url_str), strlen(opera_url_str),

            opera_config_page_ptr, modulenum);

   error |= HTTP_Add_Handler(STRING_XADDR(form_entry_url_str),

strlen(form_entry_url_str),

            form_entry_page_ptr, modulenum);

   error |= HTTP_Add_Handler(STRING_XADDR(form_response_url_str),

            strlen(form_response_url_str), form_response_page_ptr, modulenum);

   error |= HTTP_Add_Handler(STRING_XADDR(logo_response_url_str),

            strlen(logo_response_url_str), logo_response_page_ptr, modulenum);

   InitElapsedTime();  // start at zero so home page reports correct elapsed time

   return(error);

}

 

<< Previous | Next>>


Home|Site Map|Products|Manuals|Resources|Order|About Us
Copyright (c) 2006 Mosaic Industries, Inc.
Your source for single board computers, embedded controllers, and operator interfaces for instruments and automation