-<html>
- <head>
- <title>TinyOS Tutorial Lesson 15: The TinyOS printf Library</title>
- <link href="../../stylesheets/tutorial.css" rel="stylesheet" Type="text/css">
- </head>
- <body>
-
- <div class="title">Lesson 15: The TinyOS <code><font size=6>printf</font></code> Library</div>
- <div class="subtitle">Last updated August 19th, 2007</div>
-
- <p>This lesson demonstrates how to use the <code>printf</code> library located in
- <code>tos/lib/printf</code> to debug TinyOS applications by printing messages over
- the serial port.</p>
-
- <h1>Overview</h1>
- <p>
- 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.
- </p>
- <p>
- It is common practice when developing desktop applications to print output
- to the terminal screen for debugging purposes. While tools such as
- <code>gdb</code> 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.
- </p>
- <p>
- The TinyOS <code>printf</code> library provides this terminal printing functionality
- to TinyOS applications through motes connected to a pc via their serial interface.
- Messages are printed by calling
- <code>printf</code> 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 (<code>PrintfC</code>),
- and include a <code>"printf.h"</code> header file in any components that actually call
- <code>printf()</code>.
- </p>
- <p>
- Currently, the <code>printf</code> 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.
- </p>
- <h1>The TinyOS <code>printf</code> Library</h1>
- This section provides a basic overview of the TinyOS <code>printf</code> 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 <code>printf</code>
- works and only want to know how to use it, feel free to skip ahead to the next section.
- <hr></hr>
- The entire <code>printf</code> library consists of only 4 files located
- in the <code>tos/lib/printf</code> directory: one module,
- one configuration, one interface file, and one header file.
- <br><br>
- <ul>
- <li><b>PrintfC.nc</b> -- Configuration file providing printf functionality to TinyOS applications
- <li><b>PrintfP.nc</b> -- Module implementing the printf functionality
- <li><b>PrintfFlush.nc</b> -- Interface for flushing printf messages over the serial port to a pc
- <li><b>printf.h</b> -- Header file specifying the printf message format and size of the flush buffer</pre>
- </ul>
- <p>
- The <code>PrintfC</code> configuration is the only component an application needs to wire
- in order to use the functionality provided by the TinyOS <code>printf</code>
- library. Below is the component graph of the <code>PrintfC</code> configuration:
- </p>
- <center><img src=img/printf_components.png></img><p><b>Figure 1: The component
- graph of the PrintfC configuration.</b></p></center>
- <p>
- Conceptually, the operation of the TinyOS <code>printf</code> library is very
- simple. Developers supply strings to <code>printf()</code> 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 <code>PrintfP</code> component and flushed out to a PC in the form of
- TinyOS SerialMessages upon calling the <code>flush()</code> command of the
- <code>PrintfFlush</code> interface.
- </p>
- <p>
- By encapsulating the strings produced by calls to <code>printf()</code> 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 <code>printf</code> 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.
- </p>
- <p>
- Currently, only a single buffer is used to store the strings supplied to
- calls to <code>printf</code> before flushing them. This means that while
- the buffer is being flushed, any calls to <code>printf</code> will fail.
- In the future, we plan to implement a double buffered approach so that
- strings can continue to be buffered at the same time they are being printed.
- </p>
- <p>
- There are also plans to provide a means of flushing messages out to a PC
- without requiring developers to make an explicit <code>flush()</code> call.
- This would allow developers to simply wire in the <code>PrintfC</code> component
- without having to make any calls to any interfaces it provides. In fact,
- the <code>PrintfC</code> 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 <code>printf</code> 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).
- </p>
- <h1>Using the TinyOS <code>printf</code> Library</h1>
-
- <p>
- To help guide the process of using the <code>printf</code> library, a
- <code>TestPrintf</code> 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
- <code>apps/tutorials/Printf</code>. Otherwise, you can obtain it from
- cvs by running the following set of commands from a terminal window:
- </p>
-
- <pre>
-cd $TOSROOT/apps/tutorials
-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 Printf tinyos-2.x/apps/tutorials/Printf</pre>
- <p>
- Just hit enter when prompted for a CVS password. You do not need to enter one.
- </p>
-
- <p>
- If you are not using cvs, you will also have to apply the patch
- found <a href=http://sing.stanford.edu/klueska/tinyos-2.0-printf.patch>here</a>
- in order to allow the <code>printf</code> library to compile correctly for
- atmega128x based platforms (i.e. mica2, micaz):
- </p>
- <pre>
- cp tinyos-2.0-printf.patch $TOSROOT/..
- cd $TOSROOT/..
- patch -p0 < tinyos-2.0-printf.patch</pre>
- <p>
- Note that you may have to use 'sudo' when applying the patch if you run into
- permission problems.
- </p>
-
- <hr></hr>
-
- <p>
- The <code>TestPrintf</code> application demonstrates everything necessary
- to use the <code>printf</code> library. Go ahead and open the
- <code>TestPrintfAppC</code> configuration to see how the various interfaces
- provided by the <code>PrintfC</code> component have been wired in. You will
- want to do something similar in your own applications.
-
- <pre>
-configuration TestPrintfAppC{
-}
-implementation {
- components MainC, TestPrintfC, LedsC;
- components PrintfC;
-
- TestPrintfC.Boot -> MainC;
- TestPrintfC.Leds -> LedsC;
- TestPrintfC.PrintfControl -> PrintfC;
- TestPrintfC.PrintfFlush -> PrintfC;
-}</pre>
-
- <p>
- First, the <code>PrintfControl</code> interface has been wired in to enable turning on and
- off the service providing <code>printf</code> functionality. Turning on
- the <code>Printf</code> service implicity
- turns on the serial port for sending messages. Second, the <code>PrintfFlush</code>
- interface has been wired in to allow the application to control when
- <code>printf</code> messages should be flushed out over the serial line. In this
- application, all <code>printf()</code> commands are called directly within the
- <code>TestPrintfC</code> component. In general, <code>printf()</code> commands can be
- called from any component as long as they have included the <code>"printf.h"</code>
- header file.
- </p>
- <hr></hr>
- <p>
- Before examining the <code>TestPrintfC</code> 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
- <a href="lesson1.html"> lesson 1</a> for detailed instructions.
- </p>
- <p>
- To install the application on the mote, run the following set of commands.
- </p>
- <pre>
-cd $TOSROOT\apps\tests\TestPrintf
-make telosb install bsl,/dev/ttyUSBXXX</pre>
- <p>
- You will notice during the installation process that a pair of java files are
- compiled along with the TinyOS application. The first java file,
- <code>PrintfMsg.java</code>, is generated by <code>mig</code>
- to encapsulate a TinyOS <code>printf</code> 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
- <a href=lesson4.html>lesson 4</a>). The second file, <code>PrintfClient.java</code>
- is used to read <code>printf</code> messages received from a mote and print
- them to your screen.
- </p>
- <p>
- To see the output generated by <code>TestPrintf</code> you need to start the
- <code>PrintfClient</code> by running the following command:
- </p>
- <pre>
-cd $TOSROOT\apps\tests\TestPrintf
-java PrintfClient -comm serial@/dev/ttyUSBXXX:telosb</pre>
-
- <p>
- After resetting the mote, the following output should be printed to your screen:
- </p>
- <pre>
-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</pre>
-
- <p>
- 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.
- </p>
- <p>
- If for some reason you do not receive the output shown above, please refer
- to <a href=lesson4.html>lesson 4</a> 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 <font style=bold>OFF</font> position in order to send
- messages from the mote to the pc.
- </p>
- <hr></hr>
- <p>
- Go ahead and open up <code>TestPrintfC</code> to see how this output is being generated.
- </p>
- <p>
- Upon receiving the booted event, the <code>Printf</code> service is started via a call to
- <code>PrintfControl.start()</code>
- </p>
- <pre>
-event void Boot.booted() {
- call PrintfControl.start();
-}</pre>
- <p>
- Once the <code>Printf</code> service has been started, a
- <code>PrintfControl.startDone()</code> event is generated. In the body of this event
- the first four
- lines of output are generated by making successive calls to <code>printf</code>
- and then flushing the buffer they are stored in.
- </p>
- <pre>
-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();
-}</pre>
- <p>
- Once these first four lines have been flushed out, the <code>PrintfFlush.flushDone()</code>
- 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
- <code>Printf</code> service is stopped via a call to <code>PrintfControl.stop()</code>.
- </p>
- <pre>
-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 <font color=red>...</font>
- printf("Only part of this line should get printed bec <font color=red>...</font>
- call PrintfFlush.flush();
- }
- else call PrintfControl.stop();
- counter++;
-}</pre>
- <p>
- Notice that the last line of output is cut short before being fully printed.
- If you actually read the line printed above it you can see why. The buffer
- used to store TinyOS <code>printf</code> messages before they are flushed
- is by default limited to 250 bytes. If you try and print more characters than
- this before flushing, then only the first 250 characters will actually be printed.
- This buffer size is configurable, however, by specifying the proper CFLAGS option
- in your Makefile.
- </p>
- <pre>
-CFLAGS += -DPRINTF_BUFFER_SIZE=XXX</pre>
- <p>
- Once the the <code>Printf</code> service has been stopped, the
- <code>PrintfControl.stopDone()</code> event is signaled and Led 2 is turned
- on to signify that the application has terminated.
- </p>
- <pre>
- event void PrintfControl.stopDone(error_t error) {
- counter = 0;
- call Leds.led2Toggle();
- printf("This should not be printed...");
- call PrintfFlush.flush();
- }
- </pre>
- <p>
- Notice that the call to <code>printf()</code> inside the body of the
- <code>PrintfControl.stopDone()</code> event never produces any output.
- This is because the <code>Printf</code> service has been stopped before
- this command is called.
- </p>
- <h1>Conclusion</h1>
- <p>
- A few points are worthy of note before jumping in and writing your own applications that
- use the functionality provided by the <code>printf</code> library.
- </p>
- <ol>
- <li>In order to use the <code>printf</code> library, the <code>tos/lib/printf</code>
- 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:
- <pre>
-CFLAGS += -I$(TOSDIR)/lib/printf</pre>
- Remember that changing the <code>printf</code> buffer size is done similarly:
- <pre>
-CFLAGS += -DPRINTF_BUFFER_SIZE=XXX</pre>
- </li>
- <li>You MUST be sure to #include <code>"printf.h"</code> header file in
- every component in which you would like to call the <code>printf()</code>
- command. Failure
- to do so will result in obscure error messages making it difficult to identify
- the problem.</li>
- </ol>
-
-<p>
-Hopefully you now have everything you need to get going with the TinyOS <code>printf</code>
-library. All questions (or comments) about the use of this library should be directed to
-<a href=mailto:tinyos-help@millennium.berkeley.edu>tinyos-help</a> mailing list.
-</p>
-
-<p>
-Enjoy!!
-</p>
-
-<!--
-<a name=#related_docs>
-<h1>Related Documentation</h1>
-</a>
-<ul>
-<li> <a href="../tep102.html">TEP 102: Timers</a>
-<li> <a href="../tep106.html">TEP 106: Schedulers and Tasks</a>
-</ul>
--->
-
-<!-- Begin footer -->
-<br>
-<hr>
-<center>
-<p>< <b><a href="lesson13.html">Previous Lesson</a></b> | <b><a
- href="index.html">Top</a></b> | <b><a href="lesson16.html">Next Lesson </a> ></b>
-</center>
-
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" ^M "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>klueska.com</title>
+</head>
+<frameset>
+<frame src="http://docs.tinyos.net/index.php/The_TinyOS_printf_Library" name="redir_frame" />
+<noframes>
+<body>
+<p>Sorry, your browser does not support frames. Please <a href="http://docs.tinyos.net/index.php/The_TinyOS_printf_Library" target="_top">go here</a>.</p>
</body>
-</html>
+</noframes>
+</frameset>
+</html>
\ No newline at end of file