From: klueska Lesson 15: The TinyOS printf Library
-
+printf
library to
+print debug messages to your PC from a TinyOS application running on a mote.
printf
LibraryThis lesson demonstrates how to use the printf
library located in
+ tos/lib/printf to debug TinyOS applications by printing messages over the serial
+ port.
+ Anyone familiar with TinyOS knows that debugging applications has + traditionally been a very arduous, if not stressful process. While simulators + like TOSSIM can be used to help verify the logical correctness of a program, + unforseen problems inevitably arise once that program is deployed on + real hardware. Debugging such a program typically involves flashing the + three available LEDs in some intricate sequence or resorting to line by line + analysis of a running program through the use of a JTAG. +
+
+ It is common practice when developing desktop applications to print output
+ to the terminal screen for debugging purposes. While tools such as
+ gdb
provide means of stepping though a program line by line,
+ often times developers simply want to quickly print something to the screen
+ to verify that the value of a variable has been set correctly, or determine
+ that some sequence of events is being run in the proper order. It would be
+ absurd to suggest that they only be allowed three bits of information in order
+ to do so.
+
+ The TinyOS printf
library provides this terminal printing functionality
+ to TinyOS applications through motes connected to a pc via their serial interface.
+ Messages are printed by calling
+ printf
commands using a familiar syntax borrowed from the C programming
+ language. In order to use this functionality, developers simply need to include
+ a single component in their top level configuration file (PrintfC
),
+ and include a "printf.h"
header file in any components that actually call
+ printf()
.
+
+ Currently, the printf
library is only supported on msp430 and atmega128x
+ based platforms (e.g. mica2, micaZ, telos, eyesIFX). In the future we hope to add
+ support for other platforms as well.
+
printf
Libraryprintf
library,
+ including the components that make it up and the interfaces they provide.
+ In the following section we walk you through the process of actually using these components
+ to print messages from a mote to your pc. If you dont care how printf
+ works and only want to know how to use it, feel free to skip ahead to the next section.
+ printf
library consists of only 4 files located
+ in the tos/lib/printf
directory: one module,
+ one configuration, one interface file, and one header file.
+
+ The PrintfC
configuration is the only component an application needs to wire
+ in order to use the functionality provided by the TinyOS printf
+ library. Below is the component graph of the PrintfC
configuration:
+
Figure 1: The component + graph of the PrintfC configuration.
+ Conceptually, the operation of the TinyOS printf
library is very
+ simple. Developers supply strings to printf()
commands in a
+ distributed fashion throughout any of the components that make up a complete
+ TinyOS application. These strings are buffered in a central location inside
+ the PrintfP
component and flushed out to a PC in the form of
+ TinyOS SerialMessages upon calling the flush()
command of the
+ PrintfFlush
interface.
+
+ By encapsulating the strings produced by calls to printf()
inside
+ standard TinyOS SerialMessages, applications that use the serial stack for
+ other purposes can share the use of the serial port. Alternate
+ implementations were considered in which printf
would have
+ had exclusive access to the serial port, and explicit flushing would not have
+ been necessary. In the end, we felt it was better to give developers the
+ freedom to decide exactly when messages should be printed, as well as allow them
+ to send multiple types of SerialMessages in a single application.
+
+ Currently, only a single buffer is used to store the strings supplied to
+ calls to printf
before flushing them. This means that while
+ the buffer is being flushed, any calls to printf will fail.
+ In the future, we plan to implement a doubled buffer approach so that
+ strings can continue to be buffered at the same time they are being printed.
+
+ There are also plans to provide a means of flushing messages out to a PC
+ without requiring developers to make an explicit flush()
call.
+ This would allow developers to simply wire in the PrintfC
component
+ without having to make any calls to any interfaces it provides. In fact,
+ the PrintfC
component would not need to provide any interfaces
+ at all. It would start itself up and then run in a loop, periodically
+ flushing the contents of the printf
buffer.
+ Such functionality is useful in applications that do not really care when
+ messages are printed or how long a delay the process of printing introduces
+ to other sections of code. Explicit flushing would still be recommended in
+ applications where the sections of code under examinatation are very timing
+ sensitive (e.g. inside the CC2420 radio stack).
+
printf
Library
+ To help guide the process of using the printf
library, a
+ TestPrintf
application has been created.
+ At present, this application is not included in
+ the official TinyOS distribution (<= 2.0.2). If you are using TinyOS
+ from a cvs checkout, you will find it located under
+ apps/tests/TestPrintf
. Otherwise, you can obtain it from
+ cvs by running the following set of commands from a terminal window:
+
+cd $TOSROOT/apps/tests +cvs -d:pserver:anonymous@tinyos.cvs.sourceforge.net:/cvsroot/tinyos login +cvs -z3 -d:pserver:anonymous@tinyos.cvs.sourceforge.net:/cvsroot/tinyos co -P -d TestPrintf tinyos-2.x/apps/tests/TestPrintf+
+ Just hit enter when prompted for a CVS password. You do not need to enter one. +
+
+ The TestPrintf
application demonstrates everything necessary
+ to use the printf
library. Go ahead and open the
+ TestPrintfAppC
configuration to see how the various interfaces
+ provided by the PrintfC
component have been wired in. You will
+ want to do something similar in your own applications.
+
+
+configuration TestPrintfAppC{ +} +implementation { + components MainC, TestPrintfC, LedsC; + components PrintfC; + + TestPrintfC.Boot -> MainC; + TestPrintfC.Leds -> LedsC; + TestPrintfC.PrintfControl -> PrintfC; + TestPrintfC.PrintfFlush -> PrintfC; +}+ +
+ First, the PrintfControl
interface has been wired in to enable turning on and
+ off the service providing printf
functionality. Turning on
+ the Printf
service implicity
+ turns on the serial port for sending messages. Second, the PrintfFlush
+ interface has been wired in to allow the application to control when
+ printf
messages should be flushed out over the serial line. In this
+ application, all printf()
commands are called directly within the
+ TestPrintfC
component. In general, printf()
commands can be
+ called from any component as long as they have included the "printf.h"
+ header file.
+
+ Before examining the TestPrintfC
component, first install the
+ application on a mote and see what kind of output it produces.
+ Note that the instructions here are only valid for installation on a telosb mote
+ on a linux based TinyOS distribution.
+ For installation on other systems or for other mote platforms, please refer to
+ lesson 1 for detailed instructions.
+
+ To install the application on the mote, run the following set of commands. +
++cd $TOSROOT\apps\tests\TestPrintf +make telosb install bsl,/dev/ttyUSBXXX+
+ You will notice during the installation process that a pair of java files are
+ compiled along with the TinyOS application. The first java file,
+ PrintfMsg.java
, is generated by mig
+ to encapsulate a TinyOS printf
message received over the serial
+ line (for more information on mig and how it generates these files, please refer
+ to the section entitled "MIG: generating packet objects" in
+ lesson 4). The second file, PrintfClient.java
+ is used to read printf
messages received from a mote and print
+ them to your screen.
+
+ To see the output generated by TestPrintf
you need to start the
+ PrintfClient
by running the following command:
+
+cd $TOSROOT\apps\tests\TestPrintf +java PrintfClient -comm serial@/dev/ttyUSBXXX:telosb+ +
+ After resetting the mote, the following output should be printed to your screen: +
++Hi I am writing to you from my TinyOS application!! +Here is a uint8: 123 +Here is a uint16: 12345 +Here is a uint32: 1234567890 +I am now iterating: 0 +I am now iterating: 1 +I am now iterating: 2 +I am now iterating: 3 +I am now iterating: 4 +This is a really short string... +I am generating this string to have just less than 250 +characters since that is the limit of the size I put on my +maximum buffer when I instantiated the PrintfC component. +Only part of this line should get printed bec+ +
+ Note that the 'tty' device (i.e. COM port) specified when starting the PrintfClient + MUST be the one used for communicating with a mote over the serial line. On telos + and mica motes this is the same port that the mote is programmed from. Other motes, + such as eyesIFX, have one port dedicated to programming and another for + communication. Just make sure you use the correct one. +
++ If for some reason you do not receive the output shown above, please refer + to lesson 4 to verify you have done everything + necessary to allow serial communication between your pc and the mote. Remember + that when using the MIB510 programming board that the switch on the very front + of the board must be set to the OFF position in order to send + messages from the mote to the pc. +
+
+ Go ahead and open up TestPrintfC
to see how this output is being generated.
+
+ Upon receiving the booted event, the Printf
service is started via a call to
+ PrintfControl.start()
+
+event void Boot.booted() { + call PrintfControl.start(); +}+
+ Once the Printf
service has been started, a
+ PrintfControl.startDone()
event is generated. In the body of this event
+ the first four
+ lines of output are generated by making successive calls to printf
+ and then flushing the buffer they are stored in.
+
+event void PrintfControl.startDone(error_t error) { + printf("Hi I am writing to you from my TinyOS application!!\n"); + printf("Here is a uint8: %u\n", dummyVar1); + printf("Here is a uint16: %u\n", dummyVar2); + printf("Here is a uint32: %ld\n", dummyVar3); + call PrintfFlush.flush(); +}+
+ Once these first four lines have been flushed out, the PrintfFlush.flushDone()
+ event is signaled. The body of this event first prints the next 5 lines in a loop,
+ followed by the last five lines. Finally, once all lines have been printed, the
+ Printf
service is stopped via a call to PrintfControl.stop()
.
+
+event void PrintfFlush.flushDone(error_t error) { + if(counter < NUM_TIMES_TO_PRINT) { + printf("I am now iterating: %d\n", counter); + call PrintfFlush.flush(); + } + else if(counter == NUM_TIMES_TO_PRINT) { + printf("This is a really short string...\n"); + printf("I am generating this string to have just less ... + printf("Only part of this line should get printed bec ... + call PrintfFlush.flush(); + } + else call PrintfControl.stop(); + counter++; +}+
+ Notice that the last line of output is cut short before being fully printed.
+ If you actually read the line printed above it can see why. The buffer
+ used to store TinyOS printf
messages befor ethey are flushed
+ is limited to a total of 250 bytes. If you try and print more characters then
+ this before flushing, then only the first 250 characters will actually be printed.
+ As of now, this buffer size is fixed and can't be changed. In the future we
+ hope to allow developers to specify custom buffer sizes at the time that
+ they include the PrintfC component in their configuration file.
+
+ Once the the Printf
service has been stopped, the
+ PrintfControl.stopDone()
event is signaled and Led 2 is turned
+ on to signify that the application has terminated.
+
+ event void PrintfControl.stopDone(error_t error) { + counter = 0; + call Leds.led2Toggle(); + printf("This should not be printed..."); + call PrintfFlush.flush(); + } ++
+ Notice that the call to printf()
inside the body of the
+ PrintfControl.stopDone()
event never produces any output.
+ This is because the Printf
service has been stopped before
+ this command is called.
+
+ A few points are worthy of note before jumping in and writing your own applications that
+ use the functionality provided by the printf
library.
+
printf
library is limited to 250 bytes.
+ Do NOT try and increase this value. It is unclear why, but at present,
+ larger buffer sizes result in messages being cut short when printed over the
+ serial line. Tracking down
+ the source of this problem is on our list of things to do.printf
library, the tos/lib/printf
+ directory must be in your include path. The easiest way to include it is
+ by adding the following line directly within the Makefile of your top
+ level application:
+ +CFLAGS += -I$(TOSDIR)/lib/printf
+Hopefully you now have everything you need to get going with the TinyOS printf
+library. All questions (or comments) about the use of this library should be directed to
+tinyos-help mailing list.
+
+Enjoy!! +
+ + + + +< Previous Lesson | Top | Next Lesson > +
diff --git a/doc/html/tutorial/lesson15.html b/doc/html/tutorial/lesson15.html new file mode 100644 index 00000000..ca97a581 --- /dev/null +++ b/doc/html/tutorial/lesson15.html @@ -0,0 +1,360 @@ + +
+
+ + +
+