Introduction

LogTap is a small component that exposes a simple interface to send packets. It provides a low overhead means for external libraries to safely tap into the TinyOS messaging stack.

LogTap is designed to be added into the configuration of an externally developed application with minimal impact on the application as a whole. Access to the messaging layer is mediated through an AMSender interface. The default wiring of LogTap associates the AMSend interface with an AMSender, providing radio communication on platforms such as the mica2 and teleos targets. The impact of adding LogTap to systems already using the radio is minimal. For example, inclusion of LogTap in applications already using the CC1000 radio stack results in only 336 bytes of additional text and 47 bytes of additional RAM.

Wiring LogTap into an application creates a LogTapC$LogTap$sendLog (or LogTapC_LogTap_sendLog if you have cleaned up the NesC output) that external libraries can call directly. This facilitates the construction of libraries independent of the TinyOS / NesC runtime, but that can still be linked into TinyOS applications and use the TinyOS send interface.

Obtaining the Code

Software to Download

Wiring LogTap into an Application

Wiring LogTap into an application is easy. In the top level configuration for the application simply include the LogTap.h header file and wire LogTap into the system. For example, the configuration for RadioCountToLedsAppC is normally:

#include "RadioCountToLeds.h"

configuration RadioCountToLedsAppC {}
implementation
{
    components MainC, RadioCountToLedsC as App, LedsC;
    components new AMSenderC(AM_RADIO_COUNT_MSG);
    components new AMReceiverC(AM_RADIO_COUNT_MSG);
    components new TimerMilliC();
    components ActiveMessageC;

    App.Boot -> MainC.Boot;

    App.Receive -> AMReceiverC;
    App.AMSend -> AMSenderC;
    App.AMControl -> ActiveMessageC;
    App.Leds -> LedsC;
    App.MilliTimer -> TimerMilliC;
    App.Packet -> AMSenderC;
}

and after adding LogTap becomes:

#include "RadioCountToLeds.h"
#include "LogTap.h"

configuration RadioCountToLedsAppC {}
implementation
{
    components MainC, RadioCountToLedsC as App, LedsC;
    components new AMSenderC(AM_RADIO_COUNT_MSG);
    components new AMReceiverC(AM_RADIO_COUNT_MSG);
    components new TimerMilliC();
    components ActiveMessageC;

    App.Boot -> MainC.Boot;

    App.Receive -> AMReceiverC;
    App.AMSend -> AMSenderC;
    App.AMControl -> ActiveMessageC;
    App.Leds -> LedsC;
    App.MilliTimer -> TimerMilliC;
    App.Packet -> AMSenderC;

    components ActiveMessageC as LogActiveMessageC;
    components new AMSenderC(AM_LOGTAP) as LogAMSenderC;
    components LogTapC;

    LogTapC.Boot -> MainC;
    LogTapC.AMSend -> LogAMSenderC;
    LogTapC.Packet -> LogAMSenderC;
    LogTapC.AMControl -> LogActiveMessageC;
}

The Makefile for the project must also be updated so that the compiler knows where to find LogTap. The original Makefile for RadioCountToLedsC:

COMPONENT=RadioCountToLedsAppC
include $(MAKERULES)

becomes (replacing <path_to_logtap> with your system specific path to the LogTap code):

COMPONENT=RadioCountToLedsAppC
CFLAGS += -I<path_to_logtap>
include $(MAKERULES)

Calling into LogTap From an External Library

Important
Working Directly with NesC Output

The following sample code assumes that all dollar signs within app.c generated by NesC have been replaced with underscores. This can be accomplished from the command line using sed:

sed -e '/^#.*/ d' -e 's/\$/_/g' < app.c > app.clean.c

The following assumes that you are comfortable directly manipulating and manually compiling the C program created by NesC and placed into app.c. But no worries, its not hard.

The Cool Stuff

External libraries can now use the sendLog interface provided by LogTap. Within library code include a declaration for the external LogTapC_LogTap_sendLog function and call the function to send data. For example:

extern uint8_t LogTapC_LogTap_sendLog(uint16_t addr, void *data, uint8_t len);

/* ...Library Code... */

/* Flush the currently active buffer.  */
void flush_buffer(void)
{
    Buffer *buf;
    buf = buffer_table[current_buffer];
    LogTapC_LogTap_sendLog(0, buf, sizeof(Buffer));
}

/* ...More Library Code... */

NesC statically scopes LogTapC_LogTap_sendLog. This must be undone so that the external library can link to it. This is accomplished by looking for all declarations of LogTapC_LogTap_sendLog and removing the static keyword. This can be done with sed:

sed -e "s/__inline static error_t LogTapC_LogTap_sendLog(am_addr_t addr , void \*data , uint8_t len )/__inline error_t LogTapC_LogTap_sendLog(am_addr_t addr , void \*data , uint8_t len )/" < app.clean.c > app.clean.tap.c

Calls from the TinyOS application into the external library can be made by modifying app.clean.tap.c in a similar manner. For example, an application interested in monitoring the IDs handled by postTask in TinyOS may extend SchedulerBasicP_TaskBasic_postTask:

/* ...NesC Code... */

static error_t SchedulerBasicP_TaskBasic_postTask(uint8_t id )
{
    __nesc_atomic_t __nesc_atomic ;
    __nesc_atomic_t tmp ;
    unsigned char __nesc_temp ;
    bool tmp___0 ;
    int tmp___1 ;
    bool tmp___2 ;

    {
        /* ...NesC function body... */
    }
}

/* ...More NesC Code... */

by adding calls to process the IDs:

/* Added before first call of external_library_record_task */
void external_library_record_task(uint8_t id);

/* ...NesC Code... */

static error_t SchedulerBasicP_TaskBasic_postTask(uint8_t id )
{
    __nesc_atomic_t __nesc_atomic ;
    __nesc_atomic_t tmp ;
    unsigned char __nesc_temp ;
    bool tmp___0 ;
    int tmp___1 ;
    bool tmp___2 ;

    external_library_record_task(id);
    {
        /* ...NesC function body... */
    }
}

/* ...More NesC Code... */

The application can now be compiled by adding the library to the build command. For example, for a mica2 mote you would use (substituting <path_to_external_library> with your system specific path):

avr-gcc -g -mmcu=atmega128 -Os app.clean.tap.c -L<path_to_external_library> \
        -lexternal_library -o app.with_lib.elf

Conclusion

LogTap enables creation of external libraries that are able to tap into the TinyOS messaging stack without causing trouble. Development of external libraries using the TinyOS runtime is a lot fun. With a bit of luck LogTap will make this fun accessible to you.

Feel free to email royshea@gmail.com with comments, patches, or flames.