> ## Chapter 4. Applications Running on the DeviceMate Unit

> There are several sample programs provided for the DeviceMate unit. Depending on the subsystems being used, an application running on the DeviceMate unit may set up FS2, run a web server, be a SMTP mail client and/or run a serial-based console.

> This chapter will be mainly concerned with running `samples\dmunit\devmate.c`. This application enables the TCP/IP subsystem, the web page variables subsystem, the watchdog subsystem and the message logging subsystem. Any application running on the target that uses one or more of these subsystems will be able to "talk" to the DeviceMate unit.

> Dynamic C v 7.10 or later is needed to configure, compile and load `devmate.c` onto the DeviceMate. In the documentation for Dynamic C the term "target" is used to refer to the controller board that is connected to Dynamic C via the programming cable. When "target" is used by Dynamic C it is limited to that definition. When using Dynamic C, any menus, dialog boxes, or other messages that use the term "target" are (almost) NEVER referring to a device that is serially connected to a DeviceMate unit. Dynamic C is (almost) ALWAYS referring to the controller board that it is connected to it via the programming cable. The exception is when using the remote program download feature. After the Ethernet loader is running on the DeviceMate unit, Dynamic C will recognize the device serially connected to the DeviceMate as the target.

> In the documentation for a DeviceMate system (meaning there are 2 controller boards), the term "target" always refers to the device that is connected serially to the DeviceMate.

> ### 4.1 Configuration of Subsystems

> A subsystem is enabled by an application by including a statement such as the following:

>     #define USE_TC_SMTP

> in the code.

> Subsystem Name | Request for Service Macro | Libraries for DeviceMate unit
> E-mail | `USE_TC_SMTP` | targetproc_tcp.lib
> File System | `USE_TC_FS` | targetproc_fs.lib
> Message Logging | `USE_TC_LOG` | targetproc_log.lib
> Remote Program Download | `USE_TC_LOADER` | targetproc_loader.lib
> TCP/IP | `USE_TC_TCPIP` | targetproc_tcp.lib
> Watchdogs | `USE_TC_WD` | targetproc_wd.lib
> Web page Variables | `USE_TC_VAR` | targetproc_var.lib

> #### 4.1.1 Library Support

> The request for service macros are located in `tc_conf.lib`. The statement

>      #use "tc_conf.lib"

> must appear in an application program running on the DeviceMate unit that wishes to use one or more of the subsystems. This statement must follow any `USE_TC_*` defines.

> Other Dynamic C libraries are required for several of the subsystems. An application that runs a web server must include the following statements:

>     #use dcrtcp.lib
>     #use http.lib

> An application that uses the serial-based console must include:

>     #use dcrtcp.lib
>     #use zconsole.lib

> And any application that uses the Dynamic C file system must include the statement:

>     #use fs2.lib

> #### 4.1.2 Function Chains

> Applications running on the DeviceMate unit must call `targetproc_init()`. This function initializes the serial ISR, then it calls two function chains that initialize everything else.

> To drive the software, an application running on the DeviceMate unit must repeatedly call `targetproc_tick()`. This function activates the function chain that calls tick functions for each of the subsystems.

> #### 4.1.3 Configuration Macros Common to all Subsystems

> #### TC_I_AM_DEVMATE

> This macro must be defined in an application running on the DeviceMate unit.

> ### 4.2 Sample Program Code

> The following program will accept variable updates from the target. The sample program, `var.c`, running on the target will update the variables referenced in the web page `devmate_var.shtml`. Notice that this web page was imported via the `#import` directive. In an actual application `devmate_var.shtml` would probably be loaded from the target via the file system subsystem.

> #### Program Name: devmate.c

>     #define TC_I_AM_DEVMATE
>     #define MY_IP_ADDRESS "10.10.6.100"
>     #define MY_NETMASK "255.255.255.0"
>     #define MY_GATEWAY "10.10.6.1"
>     #define MY_NAMESERVER "10.10.6.1"

>     #define SSPEC_MAXSPEC 10
>     #define TARGETPROC_VAR_BUFFERSIZE 1024
>     #define MAX_TCP_SOCKET_BUFFERS 8
>     #define MAX_UDP_SOCKET_BUFFERS 2
>     #define LOG_USE_XMEM
>     #define LOG_XMEM_SIZE 500

>     #memmap xmem

>     #define USE_TC_VAR
>     #define USE_TC_TCPIP
>     #define USE_TC_WD
>     #define USE_TC_LOG
>     #use "tc_conf.lib"

>     #use "dcrtcp.lib"
>     #use "http.lib"
>     #ximport "samples\dmunit\pages\devmate_var.shtml" var_html
>     const HttpType http_types[] ={
>        { ".shtml", "text/html", shtml_handler}, // ssi
>        { ".html", "text/html", NULL},           // html
>        { ".cgi", "", NULL},                     // cgi
>        { ".gif", "image/gif", NULL}
>     };

>     const HttpSpec http_flashspec[] ={
>        { HTTPSPEC_FILE,"/var.shtml", var_html, NULL, 0, NULL, NULL}
>     };
>     void main(void){
>        LogEntry loginfo;
>        int status;
>        char buf[200];

>        targetproc_init();
>        sock_init();
>        http_init();
>        tcp_reserveport(80);
>     #define LOG_TEST_STRING "~~~{ Started test run. }~~~"

>        status = log_put(LOG_MAKEPRI(2,LOG_INFO), 0, LOG_TEST_STRING, strlen(LOG_TEST_STRING));

>        if (status != 0)
>           printf("Failed to add 1st message: %d\n", status);

>        for (;;) {
>           targetproc_tick();
>           http_handler();
>        }
>     }

> ### 4.3 Subsystem Distinctions

> Each subsystem has a set of requirements apart from those that are shared by all of the subsystems.

> #### 4.3.1 TCP/IP Subsystem Configuration

> A TCP/IP stack runs on the DeviceMate unit when `USE_TC_TCPIP` is defined. That means that the entire Dynamic C TCP/IP protocol suite is available. For more information on the protocols, see the Dynamic C TCP/IP User's Manual.

> #### MY_IP_ADDRESS
> MY_NETMASK
> MY_GATEWAY
> MY_NAMESERVER

> Network address information is required. Modify these macros to match your system.

> #### TARGETPROC_TCP_MAXRESOLVE

> Defaults to 4. Specifies maximum number of concurrent DNS resolve requests that may be outstanding at any time. This macro may be defined to zero to disable the DNS resolver.

> #### TARGETPROC_TCP_MAXSOCK

> Defaults to 6. Maximum number of sockets (implemented as XTC "channels") that are allowed. Generally, this limits the number of sockets on the target since the target is assumed to be more resource-constrained than the DeviceMate. The actual maximum is determined by the minumum value configured on the target or DeviceMate processors. Note that this value does not include the so-called "control" channel (channel 0).

> #### 4.3.2 Web Page Variables Subsystem Configuration

> Applications using the variables subsystem may run an HTTP server on the DeviceMate. This allows remote viewing of the variables.

> #### MY_IP_ADDRESS
> MY_NETMASK
> MY_GATEWAY

> Network address information is required. Modify these macros to match your system.

> #### SSPEC_MAXSPEC

> This limits the total number of variables that can be on the DeviceMate, even if `DEVMATE_VAR_MAXVARS` on the target processor is larger. Note that files are also included in `SSPEC_MAXSPEC`. It defaults to 10.

> #### TARGETPROC_VAR_BUFFERSIZE

> This defines the size in bytes of the xmem buffer in which to store the variables. It defaults to 1024.

> #### 4.3.2.1 HTML Files

> To include an HTML file in the web server, add it to the `http_flashspec` array.

>     const HttpSpec http_flashspec[] =
>     {
>        {HTTPSPEC_FILE, "/", index_html, NULL, 0, NULL, NULL},
>        {HTTPSPEC_FILE, "/index.html", index_html, NULL, 0, NULL, NULL}
>     };

> For more information on running a web server, please see the Dynamic C TCP/IP User's Manual.

> #### 4.3.3 File System Subsystem Configuration

> The file system subsystem uses the Dynamic C filesystem mk 2 (FS2). To set up FS2 on the DeviceMate unit, the first thing to do is determine your file system needs. FS2 allows flexibility regarding the file system structure and placement. The choices that are available depend on the hardware being used and what the system is doing. FS2 can be in RAM, the first Flash, the second Flash (if one is available) or a combination of these. Further partitioning of these storage devices may be done.

> Please read the chapter, "Flash File System" in the Dynamic C User's Manual. There you will find all the necessary information for setting up FS2. You may need to edit `Bios\RabbitBios.c` to make room for the file system.

> After determining your file system needs, the second step is configuration of both the file system subsystem and FS2. This is done using the configuration macros and functions in the next two sections.

> #### 4.3.3.1 FS2 Configuration Macros

> The `FS2_*` macros are from the Dynamic C library `fs2.lib`.

> #### CONSOLE_TARGETPROC_FS_BACKUP

> This is a convenience macro for the `console_backup[]` array (see the documentation for `zconsole.lib`). This macro will include support for backing up the table that holds the file name to file number mapping information, aka the spec table.

> #### CONSOLE_TARGETPROC_FS_WITH_HTTP_BACKUP

> This is another convenience macro for the `console_backup[]` array. This one includes support for backing up information for the HTTP server (that is, supporting the GET, PUT, GETV, PUTV, CREATEV commands of the console). If this is used in the `console_backup[]` array, then `CONSOLE_HTTP_BACKUP` should not be used (this includes everything in `CONSOLE_HTTP_BACKUP``).`

> #### FS2_USE_PROGRAM_FLASH

> Default: 0, do not use first (program) flash. To use the first flash, `#define` this macro to be the number of kilobytes to allocate to FS2. The minimum of `FS2_USE_PROGRAM_FLASH` and `XMEM_RESERVE_SIZE` will be used (defined in `Bios\RabbitBios.c`).

> #### FS_MAX_DEVICES

> This macro defines the maximum number of physical media. If it is not defined in the program code, it will default to 1, 2, or 3, depending on the values of `FS2_USE_PROGRAM_FLASH`, `XMEM_RESERVE_SIZE` and `FS2_RAM_RESERVE`.

> - `XMEM_RESERVE_SIZE` is defined in the BIOS and determines the amount of space reserved in the first flash that will not be used for xmem code space. This is defined to 0x0000.
> - `FS2_RAM_RESERVE` is also defined in the BIOS and determines the amount of space used for FS2 in RAM. If some battery-backed RAM is to be used by FS2, then this macro must be modified to specify the amount of RAM to reserve. This should be a multiple of 4096 bytes. The memory is reserved near the top of RAM. Note that this RAM will be reserved whether or not the application actually uses FS2.

> #### FS_MAX_FILES

> This macro is used to specify the maximum number of files that are allowed to coexist in the entire file system. Most applications will have a fixed number of files defined, so this parameter can be set to that number to avoid wasting root data memory. The default is 12 files. The maximum value for this parameter is 255.

> #### FS_MAX_LX

> This macro defines the maximum logical extents. You must increase `FS_MAX_LX` by 1 for each new partition your application creates. If this is not defined in the program code it will default to `FS_MAX_DEVICES`.

> #### MY_IP_ADDRESS
> MY_NETMASK

> If network address information is required, modify these macros to match your system.

> #### TARGETPROC_FS_BACKUP_FILE1

> File number used for the first backup file for the spec table. It defaults to 254. The spec table holds the mapping of file names to file numbers.

> #### TARGETPROC_FS_BACKUP_FILE2

> File number used for the second backup file for the spec table. It defaults to 255. Two backup files are used for the spec table so that the file name/number mapping is preserved even if the power cycles while data is being saved.

> #### TARGETPROC_FS_ENABLE_BACKUP

> This macro enables the backing up of the spec table.

> #### TARGETPROC_FS_ENABLE_ZCONSOLE

> This macro will allow the console to backup the spec table (the mapping from file name to file number). Enabling this means that the user should not use `TARGETPROC_FS_BACKUP_FILE1`, `TARGETPROC_FS_BACKUP_FILE2`, or `TARGETPROC_FS_USEBACKUPLX`, since `zconsole.lib` handles the details of `backing up the spec table.`

> #### TARGETPROC_FS_USEBACKUPLX

> This macro indicates the logical extent (LX) to use for backing up the spec table. The backup logical extent can be separate from the file logical extent, so that the user can always guarantee that enough space is available for backing up the spec table.

> #### TARGETPROC_FS_USELX

> This macro identifies the logical extent in FS2 that the target can access. This must be defined. It is used in the following way in the application code:

>     FSLXnum fs_ext;                       // Used to store a number that
>                                           // identifies a logical extent in FS2.
>     #define TARGETPROC_FS_USELX (fs_ext)  // The variable fs_ext will be
>                                           // filled in later.

> The LX number of interest is determined at runtime, so have a statement similar to the following one in `main()`:

>     fs_ext = fs_get_flash_lx();

> #### 4.3.3.2 Configuration Functions

> All of the FS2 API is available to an application running on the DeviceMate unit. Some of the functions are listed below. Full function descriptions for the FS2 API are available through the Help menu in Dynamic C and in the Dynamic C User's Manual.

> - `fs_init()` - Initialize the Dynamic C file system.
> - `fs_get_lx()` - Return the current logical extent (LX) number for file creation.
> - `fs_get_flash_lx()` - Returns the LX number for the 2nd flash device if it is available. If it is not available the LX number for the program flash is returned if space was set aside in the program flash for the FS2. (This is done with `FS2_USE_PROGRAM_FLASH` and `XMEM_RESERVE_SIZE`.)
> - `fs_get_ram_lx()` - Returns the LX number for the RAM file system if space has been allocated for this use in the BIOS.
> - `fs_get_other_lx()` - Returns the LX number of the non-preferred flash device. This is the program flash if it has been configured for use by the file system.
> - `lx_format()` - Format a specified logical extent.

> #### 4.3.3.3 Backup Files for Spec Table

> The following two functions are intended for use by an application running on the DeviceMate unit. Look at `samples\dmunit\devmate_fs.c` to see how the spec table is backed up using FS2 partitioning capabilities and `targetproc_fs_backup_bytes()`.

> ## targetproc_fs_backup_loaded

>     int targetproc_fs_backup_loaded(void);

> ### Description

> Indicates if the backup spec table (that is, the index of file names) has been successfully loaded. This function should be called after `targetproc_init()` to give the filesystem subsystem an opportunity to load the spec table. If it returns zero, then the user code may want to take some action, such as reformatting the FS2. Note that this function will always return zero if `TARGETPROC_FS_ENABLE_BACKUP` has not been defined.

> ### Return Value

> `0`: Error, the spec table was not successfully loaded.
> `1`: The spec table was successfully loaded.

> ### Library

> targetproc_fs.lib

> ## targetproc_fs_backup_bytes

>     int targetproc_fs_backup_bytes(void);

> ### Description

> Returns the number of bytes that the file system subsystem needs for a spec table backup file (i.e., the table that maps file names to numbers). There are two backup files, so space must be reserved in the file system for both of them.

> ### Return Value

> ³ `0`: Number of bytes in a spec table backup file.
> `-1`: `TARGETPROC_FS_ENABLE_BACKUP` is not defined.

> ### Library

> targetproc_fs.lib

> #### 4.3.4 Message Logging Subsystem

> The message logging subsystem on the DeviceMate unit acts as an interface between the target (over XTC) and the logging back-end implemented by `log.lib`. Messages may be stored in the file system (FS2), in an xmem buffer, or sent to the stdio window for debugging.

> If FS2 is used, it must be set up on the DeviceMate unit prior to running an application on the target that makes use of it. For information on setting up FS2, please see the Dynamic C User's Manual.

> #### 4.3.4.1 Storage of Log Entries

> The API function to write a logging message, `log_put()`, is called with a facility/priority code as its first parameter. This code is mapped to a storage destination (or destinations) via the configuration macro, `LOG_MAP(facpri)`. From zero to 4 destinations may be specified for any facility/priotity code.

> The storage destination is comprised of two components: the destination class and a stream number. The class is specified by the 2 most significant bits of the 8-bit destination number, and the stream is the lower 6 bits. The storage destinations are defined as follows:

> Table 1. Storage Destination Macros
> Name of Macro | Value of Macro
> LOG_DEST_NONE | 0x00
> LOG_DEST_STDOUT | 0x01
> LOG_DEST_FS2 | 0x40
> LOG_DEST_XMEM | 0xC0

> NOTE | The logging message will only print to the stdio window if the format specifier for the message is zero, meaning ASCII. The format specifier is communicated by the application running on the target as the high 8 bits of the first parameter in a call to `devmate_log_put()`.

> Some storage destinations do not have streams, such as the xmem buffer and stdout. Currently, only the file system storage option uses streams; up to 64 streams are allowed. An FS2 stream is the file in which to store the log entries. The log entries may be stored in multiple files, but by default there is only one FS2 stream defined. This can be changed by `LOG_FS2_MAXSTRM`.

> The facility/priority code used in the storage destination mapping is communicated by the application running on the target as the low 8 bits of the first parameter in a call to `devmate_log_put()`.

> #### 4.3.4.2 Configuration Macros

> There are numerous macros associated with the the message logging subsystem. Most are in `log.lib`. The defaults are suitable for an initial test configuration.

> #### LOG_USE_FS2
> LOG_USE_XMEM

> One or both of these macros may be defined to allow the specified storage class to be used as a logging destination. Both of these destination classes are "retrievable" in that the stored entries may be retrieved at runtime using `log_seek()`, `log_next()` and `log_prev()`. If you define `LOG_USE_FS2`, then the `fs2.lib` library is automatically included.

> You must initialize the filesystem before calling any logging functions, since the logging subsystem does not do this!

> If you do not define `LOG_USE_FS2`, then the filesystem library is not included, and you do not have to initialize it (unless your application uses it independently).

> If you define `LOG_USE_XMEM`, then a single xmem buffer is allocated for storing log entries. If FS2 is not also used, this has the advantage of being faster and using much less root code space. The disadvantage is that the log entries will be lost when the application boots up, and obviously there will be less xmem space for the application.

> #### LOG_FS2_MAXSTRM

> Define the maximum number of FS2 streams. Default 1.

> #### LOG_FS2_FILENO(strm)

> Define the FS2 file number (0-255) to use for a given stream. Defaults to 123 independent of stream (i.e., every stream maps to file number 123).

> #### LOG_FS2_DATALX(strm)
> LOG_FS2_METALX(strm)

> Define FS2 logical extent numbers for given stream. Defaults to the preferred flash extent, independent of stream.

> #### LOG_FS2_SIZE (strm)

> Define the FS2 stream size in bytes. When the stream exceeds this amount, either the oldest messages will be discarded (if circular) or the new message will not be added (non-circular). The actual file size may exceed the specified value by up to 256 bytes. The default is 8000 bytes. By carefully specifying this value, you can ensure that the filesystem capacity will not be exceeded because of an unexpected number of log messages.

> #### LOG_MAP(facpri)

> Map from facility/priority to destination class and stream. The result should be an unsigned long, which allows up to 4 dest/streams to be specified. Each dest/stream is a single byte, with the 2 MSBs specifying the destination class, and the 6 LSBs specifying the stream number within that class. A zero byte is special, it means "no destination."

> The mapping must be constant--a particular input always gives the same output. The mapping must not be a function of anything other than the input parameter.

> In general, this macro could be overridden to an arbitrarily complex function of the `facpri`, however the default should be sufficient for most purposes.

> Table 2. Default destination mapping
> Facility | Priority | Destination
> 0 | any | The first of FS2 or XMEM which is configured. If neither is configured, then STDOUT. Stream 0.
> 1 | any | STDOUT (intended for debugging).
> 2 | any | Same as for facility zero, plus STDOUT.
> 3 | any | Reserved for future use.
> 4-31 | any | Ignored.

> These defaults are implemented by the function `_log_default_map()`. You can change this function rather than changing the macro to achieve the same result.

> If any of the returned destinations are invalid (e.g. stream number higher than the maximum configured for that class), then the destination will be deemed to be "nowhere" --no error is returned in this case. If more than one of the four possible destinations is the same, then the same message will be logged multiple times to that destination.

> #### LOG_XMEM_SIZE

> Define to the xmem buffer size. This is similar to the meaning of `LOG_FS2_SIZE`, except that the size is never exceeded.

> #### LOG_FS2_CIRCULAR (strm)

> Define to 1 if the specified FS2 stream is "circular" i.e. when full, the oldest entries are automatically deleted to make room for the new entry. If defined to zero, then the message logging subsystem will refuse to add new entries when the stream becomes full. When a non-circular log is full, it can only be re-used by calling `log_clean()` on it. A circular log would not normally ever need cleaning. Defaults to 1.

> #### LOG_XMEM_CIRCULAR

> Define to 0 or 1 to make the xmem buffer log non-circular (0) or circular (1). See `LOG_FS2_CIRCULAR` above for details. Defaults to 1.

> #### FS2_USE_PROGRAM_FLASH

> Set aside this many kilobytes in the program flash. You will also need to edit `bios\rabbitbios.c` to set an appropriate value to `XMEM_RESERVE_SIZE`. The definition here may be larger or smaller--the minimum of the two specifications will be used.

> #### 4.3.4.3 Function Reference

> These API functions are not exclusively used by applications running on a DeviceMate unit. They are from the back-end logging utility available in Dynamic C v 7.10 (or later).

> ## log_clean

>     int log_clean( LogDest ld );

> ### Definition

> Reset only the specified destination class and stream (encoded as a `LogDest` value). This is only applicable to filesystem or XMEM destinations since they are locally persistent storage. XMEM is automatically cleaned at start-up time, since it is not assumed to be non-volatile. If this operation is not applicable, zero is returned with no further action.

> ### Parameters

> #### ld

> Destination class and stream. Use one of the constants `LOG_DEST_FS2` or `LOG_DEST_XMEM`, then OR in the stream number (0-63).

> ### Return Value

> `0`: Success
> `-2`: Stream out of range for the storage class specified

> ### Library

> log.lib

> ## log_close

>     int log_close( LogDestClass ldc );

> ### Definition

> Close the specified class, enumerating all streams. If the destination class is already closed, returns success.

> ### Parameters

> #### ldc

> Destination class. Use one of the constants `LOG_DEST_FS2`, `LOG_DEST_XMEM`, or `LOG_DEST_ALL`. The latter case closes all open destinations.

> ### Return Value

> `0`: Success

> ### Library

> log.lib

> ## log_condition

>     int log_condition(LogDest ldst);

> ### Definition

> Return the state of the specified log destination.

> ### Parameters

> #### ldst

> Destination class and stream. Use one of the constants `LOG_DEST_FS2` or `LOG_DEST_XMEM`, then OR in the stream number (0-63).

> ### Return Value

> `0`: Destination not open
> `1`: Destination OK
> `2`: Destination reached limit of its space quota
> `-1`: Error in destination.
> `-2`: Destination class or stream is not configured

> ### Library

> log.lib

> ## log_format

>     char * log_format(LogEntry * le, char * buffer, int length, int pfx);

> ### Definition

> Given the log entry returned by `log_next()` or `log_prev()`, format the entry as an ASCII string. The string is constructed in Unix "syslog" format:

>     <%d>%.15s %.8s[%d]: %s

> where the substitutions are:

> `%d`: facility/priority as decimal number (0-255)
> `%.15s`: date/time as "Mon dd hh:mm:ss"
> `%s`: process name - taken from `LOG_UDP_PNAME(0)` if defined, else "" (empty).

> `%d`: process ID, but the entry serial number is used instead.

> `%s`: the log entry data.

> A null terminator is always added at `buffer`[`length`-1], or at the end of the string if it fits in the buffer. If `pfx` is zero, then the above syslog prefix is not generated.

> ### Parameters

> #### le

> Log entry result from `log_next/log_prev()`.

> #### buffer

> Storage for result. Must be at least `length` bytes long.

> #### length

> Length of buffer. For the maximum sized log entry, the buffer should be 158 bytes. The minimum length must be greater than or equal to 43 (if `pfx` true) else 1. If a bad length is passed, the function returns without writing to `buffer`.

> #### pfx

> `0`: message text only; do not generate syslog prefix.
> `1`: prefix plus message text.
> `2`: prefix only (up to ']', then null terminator).

> ### Return Value

> Address of `buffer`, or `NULL` if bad length passed.

> ### Library

> log.lib

> ### See Also

> log_next, log_prev

> ## log_map

>      uint32 log_map(LogFacPri lfp);

> ### Definition

> Return the log destination class and stream, for a given facility/priority code. The result is up to 4 destinations packed into a longword. This function merely invokes the macro `LOG_MAP()`, which may be overridden by the application, but defaults to just the filesystem.

> ### Parameters

> #### lfp

> Facility/priority code. This is a single-byte code specified whenever any log message is added. Facility is coded in the 5 MSBs, and priority in the 3 LSBs.

> ### Return Value

> Up to 4 destinations for a message of the specified facility and priority. Each byte in the resulting long word represents a destination/stream. A zero byte indicates no destination. If the result is all zeros, then a message of this type would be discarded.

> ### Library

> log.lib

> ## log_next

>     int log_next(LogDest ldst, LogEntry * le);

> ### Definition

> Retrieve next log entry. You must call `log_seek()` before calling this function the first time. Retrieval of stored log messages proceeds, for example, as follows:

>     log_seek(ldst, 0);     // seek to start
>     log_next(ldst, &L);    // get 1st entry
>     log_next(ldst, &L);    // get 2nd entry
>     log_prev(ldst, &L);    // get 2nd entry again
>     log_prev(ldst, &L);    // get 1st entry
>     log_prev(ldst, &L);    // returns -1

> ### Parameters

> #### ldst

> Destination class and stream. Use one of the constants `LOG_DEST_FS2` or `LOG_DEST_XMEM`, then OR in the stream number (0-63).

> #### le

> Storage for result.

> ### Return Value

> ³ `0`: Length of log entry data.
> `-1`: End of log or not open.
> `-2`: Not a readable log destination class.

> ### Library

> log.lib

> ## log_open

>     int log_open( LogDestClass ldc, int clean );

> ### Definition

> Open the specified logging destination class. If necessary, this enumerates all possible streams within the class, opening them all (necessary only for FS2 class, since each file needs to be opened). Class `LOG_DEST_ALL` opens all configured classes.

> If `clean` is true, then the destination will be erased before it is used, if that makes sense for the class.

> ### Parameters

> #### ldc

> Destination class: `LOG_DEST_FS2`, `LOG_DEST_XMEM` or `LOG_DEST_ALL`.

> #### clean

> Boolean, should the destination be erased before using?

> ### Return Value

> `0`: Success.
> `-1`: Error, unknown destination class.

> ### Library

> log.lib

> ## log_prev

>     int log_prev(LogDest ldst, LogEntry * le);

> ### Definition

> Retrieve previous log entry. You must call `log_seek()` before calling this function the first time. Retrieval of stored log messages proceeds, for example, as follows:

>     log_seek(ldst, 1);  // seek to end
>     log_prev(ldst, &L); // get last entry
>     log_prev(ldst, &L); // get 2nd last entry
>     log_next(ldst, &L); // get 2nd last entry again
>     log_next(ldst, &L); // get last entry
>     log_next(ldst, &L); // returns -1

> ### Parameters

> #### ldst

> Destination class and stream. Use one of the constants `LOG_DEST_FS2` or `LOG_DEST_XMEM`, then OR in the stream number (0-63).

> #### le

> Storage for result.

> ### Return Value

> ³ `0`: Length of log entry data.
> `-1`: Start of log or not open.
> `-2`: Not a readable log destination class.

> ### Library

> log.lib

> ### See Also

> log_seek, log_next

> ## log_put

>     int log_put(LogFacPri ifp, uint8 fmt, char * data, int length);

> ### Definition

> Add a log entry. The specified facility/priority (`ifp`) is mapped to the appropriate destination(s), as configured by the macros. If the destination exists, then the log entry is added. Otherwise, the entry is quietly ignored. If a destination is unable to fit the log entry, and the destination is configured as circular, then the first few entries may be deleted to make room. If this cannot be done, or an unrecoverable error occurs, then -2 is returned. For non-circular destinations, -2 is returned when the destination becomes full.

> Since multiple log destinations can result from the given facility/priority, it can be difficult to determine which actual destination caused an error. You can use the `log_map()` function to determine the destinations, then check each destination's state using `log_condition()`.

> ### Parameters

> #### ifp

> Facility/priority code. Facility in 5 MSBs, priority in 3 LSBs.

> #### fmt

> Format code. 0 for ascii string, others user-defined.

> #### data

> Pointer to first byte of data to store.

> #### length

> Length of data. Must be between 0 and 115 (`LOG_MAX_MESSAGE`) inclusive.

> ### Return Value

> `0`: Success.
> `-1`: Message too long (over 115 bytes).

> `-2`: Unrecoverable error in destination. This return code usually means that the destination is unusable and further entries for that destination will probably meet the same fate. This can also mean that the destination has not been opened.

> ### Library

> log.lib

> ## log_seek

>     int log_seek(LogDest ldst, int whence);

> ### Definition

> Position log for readback. The next call to `log_next()` will return the first entry in the log (if `whence`=0), or `log_prev()` will return the last entry (if `whence`=1).

> ### Parameters

> #### ldst

> Destination class and stream. Use one of the constants `LOG_DEST_FS2` or `LOG_DEST_XMEM`, then OR in the stream number (0-63).

> #### whence

> Location to start reading back from.
> 0: first entry
> 1: last entry
> Other values are reserved.

> ### Return Value

> `0`: Success.
> `-1`: Log empty.
> `-2`: Unrecoverable error or not open.
> `-3`: Not a seekable or configured log destination class.
> `-4`: Invalid `whence` parameter.

> ### Library

> log.lib

> ### See Also

> log_next, log_prev

> #### 4.3.5 Remote Program Download

> This feature is available for any Rabbit-based target. The DeviceMate unit will allow the download of a program to the target from a remote location. The remote program download feature is different from the other DeviceMate features because it works only with Rabbit-based targets and it does not require an application to be running on the target. The target may be a blank slate.

> #### 4.3.5.1 Setting Up the DeviceMate as a Conduit

> 1. Open up Dynamic C v 7.10 or later.
> 2. Open the file `samples\dmunit\loader.c` and change the IP address information to match the address of the DeviceMate unit.
> 3. Download `loader.c` to the DMU using the serial connection. Run the program. If `TARGETPROC_LOADER_DEBUG` is defined, a message will print to the stdio window letting you know `loader.c` is listening for a connection.
> 4. Using the Options | Communications dialog box, choose "Use TCP/IP Connection" and fill in the Network Address and Control Port information for the DeviceMate. If the DeviceMate is behind a firewall you will probably have to enter the proxy IP/Port numbers for the firewall instead. Click "OK."

> From this point the DeviceMate is a conduit for communication between the remote location and the DeviceMate's target device. The DeviceMate reads STATUS and drives RESET, SMODE0 and SMODE1on the target through the serial interface.

> Hit Ctrl-Y to reset the target. Now you can download a program to the target in the usual way.

> #### 4.3.5.2 Communication Between DeviceMate Unit and Target

> Any program that is downloaded to the target through the DeviceMate must have the following code in it to force all communications to talk directly to the Ethernet Loader (`loader.c`) running on the DMU.

>     #define USE_TC_LOADER
>     #use "tc_conf.lib"

> Both of these statements are in `loader.c`. The current software forces the DeviceMate to use its serial port B for downloading to the target's serial port A.

> #### 4.3.6 Watchdog Subsystem Configuration

> The watchdog subsystem running on the DeviceMate unit accepts messages from the target to create, remove and hit watchdogs. If a watchdog is not hit within the amount of time specified in the call to `devmate_wd_add()`, the DeviceMate calls a function that will reset the target .

> Developers working with nonRabbit targets must supply a pointer to a reset function for their device.

> #### TARGETPROC_WD_NUMTXBUF

> This determines the maximum number of transmit buffers on DeviceMate. Default is 1.

> #### TARGETPROC_WD_NUMRXBUF

> This determines the maximum number of receive buffers on DeviceMate. Default is 2.

> #### TARGETPROC_WD_MAXWD

> This determines the maximum number of watchdogs on DeviceMate. Default is 12.

> #### TARGETPROC_WD_RESETFUNCTION

> This is a pointer to a function that will reset the target. If it is not defined in the application code, it defaults to `_targetproc_wd_resetfunction`.

Z-World http://www.zworld.com Voice: (530) 757-3737 FAX: (530) 757-3792 sales@zworld.com