0% found this document useful (0 votes)
102 views

TinyOS, An Embedded Operating System

Uploaded by

tanooskar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
102 views

TinyOS, An Embedded Operating System

Uploaded by

tanooskar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

BAKKALAUREATSARBEIT

TinyOS, an Embedded Operating


System

ausgeführt zum Zwecke der Erlangung des akademischen Grades


eines Bakkalaureus der Technischen Informatik

unter der Leitung von

Dipl.-Ing. Alexander Kössler


Institut für Technische Informatik 182-2

durchgeführt von

Harald Glanzer Matr.Nr. 0727156


Markus Hartmann Matr.Nr. 9808811

Wien, im September 2012 ...........................


TinyOS, an Embedded Operating
System

Subject of this work is to give an introduction to the TinyOS Embedded


Operating System. It explains the internal structure of the OS and points
out its characteristics by comparing it to another embedded Operating
System called MicroC/OS-II. By presenting several modules which have
been written in the course of this project thesis the usage and practical
applicability of TinyOS are shown. A setupguide for the used toolchain
is provided in order to enable a quick and simple start into application
developement.

i
Contents
1 Introduction 1
1.1 Motivation and Objectives . . . . . . . . . . . . . . . . . . . . . 1
1.2 Structure of the Thesis . . . . . . . . . . . . . . . . . . . . . . . 2
2 TinyOS 3
2.1 What is TinyOS . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 History of TinyOS . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Supported Platforms . . . . . . . . . . . . . . . . . . . . . . . . 4
2.4 TinyOS Hardware Abstraction . . . . . . . . . . . . . . . . . . . 5
2.5 TinyOS Internals . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.5.1 Basic Scheduler . . . . . . . . . . . . . . . . . . . . . . . 6
2.5.2 Microcontroller Power Management . . . . . . . . . . . . 6
2.5.3 Boot Sequence . . . . . . . . . . . . . . . . . . . . . . . 7
2.5.4 Ressource Arbitration . . . . . . . . . . . . . . . . . . . 8
3 nesC 11
3.1 Fundamental Programming Hints . . . . . . . . . . . . . . . . . 11
3.2 Namespace, Components, and Interfaces . . . . . . . . . . . . . 12
3.3 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.4 Async Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.5 Split-Phase Interfaces . . . . . . . . . . . . . . . . . . . . . . . . 16
3.6 Generic Components . . . . . . . . . . . . . . . . . . . . . . . . 17
3.7 Parameterized Interfaces and Configurations . . . . . . . . . . . 18
3.8 Wiring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.8.1 Modules vs. Configurations . . . . . . . . . . . . . . . . 19
3.8.2 Wiring-Operators . . . . . . . . . . . . . . . . . . . . . . 19

4 MicroC/OS-II 22
4.1 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.2 Differences TinyOS - MicroC/OS-II . . . . . . . . . . . . . . . . 23
4.2.1 Real-Time . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.2 Scheduler . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2.3 Mutual Exclusion . . . . . . . . . . . . . . . . . . . . . . 24
4.2.4 Intertask Communication . . . . . . . . . . . . . . . . . 25
4.2.5 Task Synchronisation . . . . . . . . . . . . . . . . . . . . 25
4.2.6 Memory Footprint . . . . . . . . . . . . . . . . . . . . . 25

ii
5 bigAVR6 26
5.1 The Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.1.1 Onboard - Features . . . . . . . . . . . . . . . . . . . . . 26
5.1.2 Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.2 Supported Modules . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.2.1 Character LCD 2x16 . . . . . . . . . . . . . . . . . . . . 27
5.2.2 GLCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.2.3 Touch Screen . . . . . . . . . . . . . . . . . . . . . . . . 31
5.2.4 MMC . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.2.5 MP3 extension board . . . . . . . . . . . . . . . . . . . . 34
5.2.6 Ethernet board . . . . . . . . . . . . . . . . . . . . . . . 36
5.2.7 UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.2.8 RTC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2.9 Printf Library . . . . . . . . . . . . . . . . . . . . . . . . 43
5.3 Supported Microcontrollers . . . . . . . . . . . . . . . . . . . . . 44
5.3.1 ATmega128 . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.3.2 ATmega1280 . . . . . . . . . . . . . . . . . . . . . . . . 45
6 Resources used 46
Bibliography 47
A Setup Guide 48
A.0.3 Visualize Components . . . . . . . . . . . . . . . . . . . 49
B Pin Configuration of bigAVR6 50

iii
1 Introduction
This work is about the porting of TinyOS for the bigAVR6 platform for use
in the Microcontroller Lab Course at the Vienna University of Technology.
TinyOS is an open-source operating system, designed for use with wireless
embedded sensor networks. There are 2 major stable branches, v.1.x and v2.x,
which are not compatible to each other. TinyOS 2.x introduced some major
improvements, for example the task scheduler was completely redesigned. In
it’s new version, the whole project is now distributed under the new BSD license
too.
Because of TinyOS’s component-based architecture, a high-level programmer
does not have to rewrite all the used components from scratch, as long as the
necessary modules are already exisiting. So, implementing new applications or
changing exisiting ones is an easy and fast task. There are already existing
implementations for a range of popular hardware motes, as for example the
mica, iris and teleosa motes.
For developing applications in TinyOS, nesC is used. nesC stands for Net-
work Embedded Systems C, which is very similar to C/C++. Components in
nesC are related to objects in C++.
Embedded systems are designed for one or a few specific tasks, perhaps in
combination with realtime constraints. TinyOS was originally developed for
wireless, battery powered sensor networks, so one of the main requirements is
low power consumption to achieve high operation times – flexibility is not that
important.
This work captures topics from porting TinyOS to the bigAVR6 platform
as well as extending it by adding software-modules for high-level use of the
platform modules. It is also explained how to get a build environment running
from scratch for writing applications or extending the modules for an exisiting
platform.

1.1 Motivation and Objectives


One goal of this work is to provide an easy-to-use manual for using TinyOS
to the reader, so that a build environement can be set up from scratch step-
by-step with very little previous knowledge needed. By comparing TinyOS to

1
1 Introduction 1.2 Structure of the Thesis

MicroC/OS-II, another embedded operating system, the specific characteris-


tics of TinyOS will get much clearer. Finally, by guiding through the software
modules written for the bigAVR6-board, the reader will get familiar with how
to practically extend the TinyOS framework by using as much of the preex-
isting components and how to properly integrate his own code into TinyOS
applications.

1.2 Structure of the Thesis


The thesis is structured as follows:
Chapter 2 gives an overview over TinyOS and explains its internals.
Chapter 3 gives an introduction to nesC.
Chapter 5 introduces the developement platform bigAVR6, for which TinyOS
was ported to by the authors, and explains the supported devices for this
platform.
Chapter 4 introduces another embedded operation system, named
MicroC/OS-II, and compares it’s main characteristics to TinyOS.
Appendix A provides a Setup guide for the TinyOS toolchain.
Appendix B shows an overview for the bigAVR6 pin configuration.

2
2 TinyOS

2.1 What is TinyOS


TinyOS is a free and open operating system for hardware motes, written in
nesC. A hardware mote is a microcontroller based node in a wireless sensor
network, capable of reading sensory information, processing and exchanging
its data with other nodes. Communication typically happens via a wireless
network, to reduce the cost for deployment and maintenance. Additionally, in
many environments wires are not feasible.
Development of TinyOS started as a collaboration of Berkeley University
with Intel Research and Crossbow Technology, a california based company.
The following requirements were defined for TinyOS:
• Require very few resources
• Allow fine-grained concurrency
• Adapt to hardware evolution
• Support a wide range of applications
• Robust design
• Support a diverse set of platforms
One of TinyOS’s most important features is that TinyOS applications are
built out of components, which are connected (or wired) to each other by
interfaces. Components can easily be developed, extended and reused. Another
advantage is that a component can be built in software or hardware, increasing
flexibility.

2.2 History of TinyOS


Developement of TinyOS started in 1999 at Berkeley university. The first
supported platform was a mote called ’WeC’, shown in Figure 2.1. For com-
munication, this platform is equipped with a radio device, SPI- and UART
interfaces. An Atmel AVR AT90LS8535 microprocessor, clocked with 4MHz,
is used as MCU.

3
2 TinyOS 2.3 Supported Platforms

Figure 2.1: WeC Mote

Over the next years, the ’rene’ and ’mica’ platforms were developed. In the
year 2002, work on the nesC programming language began. Until that, TinyOS
consisted of a mixture of C files and Perl scripts. In the same year, TinyOS
1.0, the first TinyOS implemented in nesC, was released.
Improvement of TinyOS 1.x went on until February 2006, when TinyOS 2.0
beta1 was released. Version 2.1 was finished in April 2007. Among numerous
bugfixes, a cc2420 wireless radio stack implementation was added in this release.
TinyOS 2.2 was released some months later, which included an cc2420 stack
reimplementation and bugfixes. After that, in August 2008, support for the
’iris’ and ’shimmer’ platforms was added by distribution of version 2.1.
At the time of this writing, the latest TinyOS version is 2.1.1, which was
released in April 2010. Most important add-ons were support for the ’mulle’,
’epic’ and ’shimmer2’ - platforms.

2.3 Supported Platforms


In the current version, a range of hardware motes are supported out-of-the-box.
A brief description of this platforms and its most important communication de-
vices are given in the following list. Obviously, most of this platforms provide
interfaces for UART, I2C, SPI, or other peripherals, depending on the micro-
controller and extension boards used, too. These features are not listed here.
• btnode3: Atmega128L cpu and radio/bluetooth communication devices
• epic: MSP430 cpu and CC2420 radio chip
• eyesIFX: MSP430F149/F1611 and TDA5250 wireless transceiver
• intelmote2: PXA271 XScale cpu and CC2420 radio chip
• iris: Atmega1281 and AT86RF230 radio chip
• mica: Atmega103 and TR1000 radio chip

4
2 TinyOS 2.4 TinyOS Hardware Abstraction

• mica2: Atmega128L and Chipcon 868/916 radio chip


• mica2dot: Atmega128 and cc1000 transceiver
• micaz: Atmega128 and CC2420 radio chip
• mulle: Renesas M16C and AT86RF230 transceiver
• sam3s ek: SAM3S4C chip and cc2520 transceiver
• sam3u ek: SAM3S4C chip and cc2420 transceiver
• shimmer / shimmer2 / shimmer2r : MSP430 cpu and CC2420 transceiver
• span: MSP430 cpu and CC2420 transceiver
• telosa / telosb: MSP430 cpu and CC2420 transceiver
• tinynode: MSP430 cpu and Semtech SX1211 transceiver
• ucmini: Atmega128RFA1 cpu(low power transceiver cpu integrated)
• z1: MSP430 cpu and CC2420 transceiver

2.4 TinyOS Hardware Abstraction


Many of the supported hardware platforms use the same cpu and/or communi-
cation hardware. Hardware abstraction is used to avoid rewriting of code, mak-
ing it easier to port applications from one platform to another. Additionally,
application development itself gets easier, too. On the other hand, abstraction
means generalisation, which is problematic because hardware motes only have
very limited resources and strict energy-efficiency requirements. TinyOS uses a
3-level Hardware Abstraction Architecture to provide a flexible and performant
framework to build applications on, as shown in Figure 2.2.
• Hardware Presentation Layer (HPL): Low Level components, directly
accessing the hardware.
• Hardware Adaption Layer (HAL): Platform specific abstractions hiding
a bit of the complexity from hardware resources, allowed to perform ar-
bitration and resource control.
• Hardware Interface Layer (HIL): Hardware independent application in-
terface
The 3-level Hardware Abstraction tries to provide a balance between effi-
ciency and portability. In contrast to other embedded operating Systems that
use only 2 layer abstraction, the third TinyOS layer provides more flexibility.
For maximum performance, a Platform specific application can directly hook
into the HAL, circumventing the HIL. h

5
2 TinyOS 2.5 TinyOS Internals

Figure 2.2: Hardware Abstraction Architecture

2.5 TinyOS Internals


2.5.1 Basic Scheduler
By default, TinyOS 2.x uses a non-preemptive FIFO scheduler with a max-
imum of 255 parameterless tasks waiting for execution. A task can only be
scheduled once at a time, if periodic execution is needed the task has to re-post
itself. The scheduler itself consists of an interminable for-loop, that pops (=
executes) one task after the other, in sequence as the tasks got pushed. If
no tasks are waiting for execution, the scheduler enters a powersaving-mode
immediately.
Because the scheduler of TinyOS is implemented as a component it is possible
to replace this default FIFO-scheduler with a selfwritten one. See [LS] for
details how to implement a selfwritten scheduler.

2.5.2 Microcontroller Power Management


To reduce power consumption, a microcontroller should always run in the lowest
power state possible. For example, if you want to run an embedded system that
is powered by two AA batteries with a capacitiy of 2.7Ah, for one year, you
reach an average of about 1mW of power consumption. Clearly, this can only
be achieved by saving energy whenever possible.

6
2 TinyOS 2.5 TinyOS Internals

As mentioned before, TinyOS enters a low power mode if the task queue is
empty. Normally, microcontrollers support a range of low power modes, for
example the ATmega128 supports up to 6 different power saving modes. To
decide what mode fits best, TinyOS examines the control- and statusregisters
to find the active components, and decides subsequently which power mode to
use.
For example, on an ATmega128-based asynchronous operated platform, the
cpu-specific powersaving-mode IDLE has to be choosen if one or more timer,
SPI, UART or I2C are in use. If the ADC-submodule is working, another mode,
ADC Noise Reduction, is entered. If none of this modules are active and the
task queue is empty, the cpu is set to POWER DOWN, from which it only can
resume by some external interrupts/resets or a SPI address match interrupt.
Because entering powersaving modes always comes with wakeup latency,
problems can arise if some higher-level hardware modules have timing con-
strains and the wakeup latency is too big. To solve this, the powersaving
mode found by examing the control- and statusregisters can be overridden
by a higher-level module. For example, when going to a sleepmode just be-
fore an alarm of a timer would occur, the wakeup latency could probably
cause a miss of this alarm. Therefore, a component can provide an inter-
face named McuPowerOverride featuring a command lowestState that, wired
against McuSleepC, will be called when a powersave mode is requested, and
can override the valid powersaving mode. The enabled powersaving mode is
the weakest one of all implementations of the interface.

2.5.3 Boot Sequence


When TinyOS is booting up, it uses 3 interfaces:
• Init
• Scheduler
• Boot
Init has only one command called init() which is implemented in Scheduler,
PlatformInit and SoftwareInit. PlatformInit is execuded directly after Sched-
uler initialization, wires to PlatformC and provides initializations which must
happen in a specific order. Components who do not directly depend on hard-
ware resources should wire to SoftwareInit. If a specific initialization ordering
is required, every component itself is responsible for establishing that order.
Finally, Boot signals the completion of the bootup-process to the application.

7
2 TinyOS 2.5 TinyOS Internals

2.5.4 Ressource Arbitration


One major task of every operating system is the management of available re-
sources, like communication interfaces that are used by different components.
TinyOS distinguishes between 3 different kinds of abstractions:
• dedicated resources
• virtualized resources
• shared resources
A dedicated resource is a resource which is allocated by one and only one
subsystem all the time. Obvious, no sharing policy is needed here. Examples
for such resources are counters and interrupts.
Virtualized resources are used by multiple clients through software virtu-
alization. Here, every client interacts like using a dedicated reosource. Because
virtualization is done in software, there is no upper bound on the number
of clients (apart from memory/efficiency constraints), with all virtualized in-
stances being multiplexed on top of the underlying resource. Clearly, this
virtualization goes along with cpu-overhead.
For example, this concept is used for timers on ATmega128-based platforms.
Every time a new timer is instantiated, TinyOS builds a virtual timer on top
of one physical timer.
The shared resource concept is used for modules that need exclusive access
to a resource for some time. An arbiter is responsible for multiplexing between
the different clients that want to use the resource. As long as a client holds a
resource, it has complete access to it. TinyOS arbiters assume that clients are
cooperative, that means that a client only acquires a resource when needed,
and only holds it as long as needed, releasing it as soon as possible. No concept
of preemption is used here, so when client B needs a resource he cannot force
Client A to release it.
The arbiter, the centralized place that knows whether a resource is busy or
not, is an interface that must be instantiated by every client that wants to
use the resource. After that, the client can request the resource. The request
is queued by the arbiter if the resource is busy. As soon as the resource is
available, a special event “granted” is signaled to the client, who has now
exclusive access to it. It is the client’s responsibility to release it so soon as
possible. To avoid monopolizing a resource a request for a resource is only
queued if there is no other request of this client queued yet. It is also possible
to issue an “ImmediateRequest” command. If available the resource is granted
without an event, otherwise an error code is returned.

8
2 TinyOS 2.5 TinyOS Internals

An example for such a shared resource would be a bus, for example SPI as
shown in codelistings 2.1 and 2.2. This listings are part of an implementation
for sending and receiving IEEE8023 - frames with an 10MBit ENC28J60 chip.
A microcontroller can communicate with this chip by SPI. Given that at least
one other component could need independent access to SPI too, IEEE8023C re-
quests the bus whenever data has to be exchanged between the microcontroller
and the ethernet chip. Once the resource SPI is available, the arbiter signals
this to IEEE8023C, which has implemented the proper handler for this situ-
ation, named Resource.granted(). After this handler was called, IEEE8023C
is in full control of the SPI bus, regardless of other components that may be
using SPI too. After finishing it’s work, IEEE8023C MUST free the resource
by calling Resouce.release(). From this time on, other components can use the
resource.
Listing 2.1: IEEE8023P.nc
#i n c l u d e ” IEEE8023 . h”

module IEEE8023P
{
p r o v i d e s i n t e r f a c e IEEE8023 ;
u s e s i n t e r f a c e GeneralIO a s ssMMC ;
u s e s i n t e r f a c e GeneralIO a s ssETH ;
u s e s i n t e r f a c e GeneralIO a s rstETH ;
u s e s i n t e r f a c e HplAtm128Interrupt a s intETH ;
u s e s i n t e r f a c e SpiByte ;
uses i n t e r f a c e Resource ;
}

implementation
{

command u i n t 8 t IEEE8023 . i n i t ( )
{
/∗
. . . unimportant code i s not shown h e r e . . .
∗/

/∗
queue a r e q u e s t f o r t h i s r e s o u r c e now . . .
∗/
i f ( c a l l R e s o u r c e . r e q u e s t ( ) == FAIL )
{
r e t u r n FAIL ;
}
else
{
stateETH = IEEE8023 INITIALIZING ;
r e t u r n SUCCESS ;
}
}

/∗
e v e n t h a n d l e r w i l l be c a l l e d when r e q u e s t was queued and
r e s o u r c e becomes a v a i l a b l e
∗/
event void Resource . granted ( void )

9
2 TinyOS 2.5 TinyOS Internals

{
/∗
we a r e now i n f u l l c o n t r o l o f t h e r e s o u r c e
r e a d / w r i t e data t o r e s o u r c e
∗/

c a l l Resource . r e l e a s e ( ) ;
/∗
NO MORE a c c e s s t o t h e r e s o u r c e now
queue a n o t h e r r e q u e s t t o g e t i n c o n t r o l a g a i n
∗/
}

Listing 2.2: IEEE8023C.nc


c o n f i g u r a t i o n IEEE8023C
{
p r o v i d e s i n t e r f a c e IEEE8023 ;
}

implementation
{
components IEEE8023P ;
components Atm128SpiC a s SPI ;

IEEE8023 = IEEE8023P ;
IEEE8023P . SpiByte −> SPI . SpiByte ;
IEEE8023P . R e s o u r c e −> SPI . R e s o u r c e [ 0 ] ;

/∗
unimportant components and w i r i n g not shown h e r e
∗/

10
3 nesC

3.1 Fundamental Programming Hints


Before diving into this C - dialect, the most important programming hints are
listed, as given in [Lev]
• It’s dangerous to signal events from commands, as you might cause a very
long call loop, corrupt memory and crash your program.
• Keep tasks short.
• Keep code synchronous when you can. Code should be async only if its
timing is very important or if it might be used by something whose timing
is important.
• Keep atomic sections short, and have as few of them as possible. Be
careful about calling out to other components from within an atomic
section.
• Only one component should be able to modify a pointer’s data at any
time. In the best case, only one component should be storing the pointer
at any time.
• Allocate all state in components. If your application requirements neces-
sitate a dynamic memory pool, encapsulate it in a component and try to
limit the set of users.
• Conserve memory by using enums rather than const variables for integer
constants, and don’t declare variables with an enum type.
• In the top-level configuration of a software abstraction, auto-wire Init to
MainC. This removes the burden of wiring Init from the programmer,
which removes unnecessary work from the boot sequence and removes
the possibility of bugs from forgetting to wire.
• If a component is a usable abstraction by itself, its name should end
with C. If it is intended to be an internal and private part of a larger
abstraction, its name should end with P. Never wire to P components
from outside your package (directory).
• Use the as keyword liberally.

11
3 nesC 3.2 Namespace, Components, and Interfaces

• Never ignore combine warnings.


• If a function has an argument which is one of a small number of con-
stants, consider defining it as a few separate functions to prevent bugs.
If the functions of an interface all have an argument that’s almost always
a constant within a large range, consider using a parameterized interface
to save code space. If the functions of an interface all have an argument
that’s a constant within a large range but only certain valid values, imple-
ment it as a parameterized interface but expose it as individual interfaces,
to both minimize code size and prevent bugs.
• If a component depends on unique, then #define a string to use in a
header file, to prevent bugs from string typos.
• Never, ever use the ’packed’ attribute.
• Always use platform independent types when defining message formats.
• If you have to perform significant computation on a platform indepen-
dent type or access it many (hundreds or more) times, then temporarily
copying it to a native type can be a good idea.

3.2 Namespace, Components, and Interfaces


nesC applications consist of components that get wired together. A component
can be a configuration or a module. Modules implement some functionality,
while configurations describe how components are put together.
nesC uses a purely local namespace. This means that a component has to
declare all the functions it calls. An advantage in this approach is that all
the functions that get called are known at compile time - no RAM is used
for storing function pointers, and no runtime allocation is required. This is
possible because of the nature of nesC - applications: this applications run on
embedded systems with well-defined and tightly specified uses, and it is much
more important to save memory than to provide flexibility by dynamic linking.
This declaration is done in the specification of the component. In this code-
block, the component declares what functions it provides and what functions
it uses. This would be such a specification:
module doSomethingC {
p r o v i d e s command <r e t u r n v a l u e > p r o v i d e d F u n c t i o n a l i t y (<arguments >);
u s e s command <r e t u r n v a l u e > u s e d F u n c t i o n a l i t y (<arguments >);
}

In practice, instead of declaring the individual functions, a component spec-


ifies what interfaces are used and provided. When specifying that a certain
interface is used, the component can use or call all of the functions that are

12
3 nesC 3.2 Namespace, Components, and Interfaces

implemented by this interface. As this functions can be implemented by differ-


ent components in different ways, a configuration is needed: there, the calling
component is connected to another component that provides the needed func-
tions through it’s interfaces. This action is called wiring.
Consider this code example, taken from the TinyOS powermanagement sub-
system:
i n t e r f a c e StdControl {
command e r r o r t s t a r t ( ) ;
command e r r o r t s t o p ( ) ;
}

This interface named StdControl is used by components that need to turn


off or on other components, while StdControl is provided by components that
represent an abstraction or a service.
For example, it should be possible to enable and disable UART-transmission.
So, the UART-module provides the interface StdControl. Mind the keyword
as in the following code snippet. This keyword just renames the interface for
local use and can be ommited.
module HplAtm128UartP {
...
p r o v i d e s i n t e r f a c e S t d C o n t r o l a s Uart0TxControl ;
...
}

The actual work is done in the module’s implementation. Keep in mind that
the module providing an interface MUST implement all of the commands of
the interface:

...

command e r r o r t Uart0TxControl . s t a r t ( ) {
SET BIT (UCSR0B, TXEN) ;
c a l l McuPowerState . update ( ) ;
return SUCCESS ;
}

command e r r o r t Uart0TxControl . s t o p ( ) {
CLR BIT (UCSR0B, TXEN) ;
c a l l McuPowerState . update ( ) ;
return SUCCESS ;
}

...

The next listing shows how wiring works:


c o n f i g u r a t i o n Atm128Uart0C {
provides i n t e r f a c e StdControl ;
...
}

implementation {

13
3 nesC 3.2 Namespace, Components, and Interfaces

components new Atm128UartP ( ) a s UartP ;


S t d C o n t r o l = UartP ;
UartByte = UartP ;
UartStream = UartP ;
UartP . Counter = Counter ;

components HplAtm128UartC a s HplUartC ;


UartP . HplUartTxControl −> HplUartC . Uart0TxControl ;
...
}

So, every higher-level component can switch on and off transmission on the
Uart0 interface, and the implementation also notifies the system that some
hardware was started or stopped, an information that is used by the power-
manangement system, as described earlier. Codelisting 3.1 demonstrates how
an application can make use of such an interface.
At first, we define what components we want to use, and how they are
put(wired ) together.
Listing 3.1: MyPowersavingAppC.nc
/∗ tab :4
Harald Glanzer , 0727156 TU Wien

Boot hardware , and t u r n on UART0 − TX when sy s te m i s up

t h i s program u s e s t h e g i v e n components MainC and Atm128Uart0C


component ’ MyPowersavingC ’ i s t h e app i t s e l f
∗/

c o n f i g u r a t i o n MyPowersavingAppC
{
}
implementation
{
components MainC ;
components Atm128Uart0C ;
components MyPowersavingC ;

/∗
w i r e our app t o t h e i n t e r f a c e ’ Boot ’
t h i s i n t e r f a c e i s p r o v i d e d by component ’MainC ’
∗/
MyPowersavingC −> MainC . Boot ;

/∗
w i r e our app t o t h e i n t e r f a c e ’ S t d C o n t r o l ’
t h i s i n t e r f a c e i s p r o v i d e d by component ’ Atm128Uart0C ’
∗/
MyPowersavingC −> Atm128Uart0C . S t d C o n t r o l ;
}

After that, we can use the interfaces provided by the used components. See
listing 3.2 for how that works.
Listing 3.2: MyPowersavingC.nc
/∗

14
3 nesC 3.3 Tasks

Harald Glanzer , 0727156 TU Wien

i n t e r f a c e ’ Boot ’ p r o v i d e s t h e e v e n t ’ b o o t e t ’ t o us ,
which MUST BE implemented by t h e u s e r o f ’ Boot ’

A d d i t i o n a l l y , we a r e u s i n g t h e g e n e r i c i n t e r f a c e S t d C o n t r o l
t h i s i n t e r f a c e i s p r o v i d e d by v a r i o u s components − t h i s app
u s e s t h e i n t e r f a c e p r o v i d e d by ’ Atm128Uart0C ’ , so we can
e n a b l e / d i s a b l e TX f o r UART0

s e e f i l e MyPowersavingAppC . nc f o r how t h e w i r i n g works


∗/

module MyPowersavingC @ s a f e ( )
{
u s e s i n t e r f a c e Boot ;
uses i n t e r f a c e StdControl ;
}
implementation
{
/∗
when s ys t e m has ’ b o o t e t ’ up , we w i l l r e c e i v e t h i s e v e n t and
can t a k e o v e r from h e r e . . .
∗/
e v e n t void Boot . bo ot ed ( )
{
c a l l StdControl . s t a r t ( ) ;
}
}

Any Application can be easily ported to another Platform by just rewiring


the Components, as long as all the interfaces are provided.

3.3 Tasks
In TinyOS, a module can post a task to the scheduler, which will get executed
at some point later. Because a task is a deferred procedure call, there is no
return value. Additionally, there are no parameters for tasks, though it is
possible to write an own implementation of the task interface. A declaration
of a task has this form:
t a s k void c h e c k I n t e r r u p t f l a g ( ) ;

Adding this task to the scheduler is done by the post keyword:


post c h e c kI n te rr u p t f l a g ( ) ;

Tasks are non-preemptive, in other words, no task will ever get interrupted
by the TinyOS scheduler. The advantage is that the programmer never has to
worry about tasks corrupting each other’s data. On the other hand, tasks never
should be too long because otherwise other tasks maybe could get delayed. So,
a task that has to do long computations should be broken into multiple tasks.

15
3 nesC 3.4 Async Functions

TinyOS needs about 80 microcontroller clock cycles to post and execute a


task, so there’s a tradeoff between lots of short tasks and fewer, but longer
running tasks - no hard rule can be given here.

3.4 Async Functions


As stated before, a task will always run until it has finished. This is not true
under all circumstances, because a task can be disrupted by an interrupt. Such
functions that run preemptively, triggered by an interrupt and from outside the
task context, are labeled with the async keyword. Consequently, all commands
that are called and all events that get signalled by such functions are async as
well and must be marked async too.
To get an async function into a syncronous context, the only way possible is
by using tasks. For example, receiving UART bytes will normally be done inter-
rupt driven, so the corresponding interrupt vector will be called asyncronously.
If the received data is handled by a higher level component in a syncronous
function, the interrupt handler can post a task to get from the asyncronous
interrupt context to a syncronous task context.

3.5 Split-Phase Interfaces


As stated before, it should be possible in TinyOS to build a certain function-
ality either in software or in hardware. Because hardware is almost always
non-blocking, the software must be non-blocking as well to guarantee this ex-
changeability. A traditional approach for solving this problem is to use multiple
threads: one thread requests an operation and is then put on a waiting queue,
and another thread continues with some other work. The waiting thread is wo-
ken up as soon as the operation has finished and interrupts the other running
thread.
A problem with threads is that they need RAM – a resource that is very
precious on embedded systems. Every thread has it’s own private stack that
has to be untouched as long as the thread is suspended, so this part of memory
is wasted storage.
So, instead of threads, TinyOS uses the split-phase model: A program that
wants to execute some functionality (sampling a sensor; sending a data packet)
requests the operation, returning immediatly afterwards. When the operation
has finished, this new state is signaled to the requester by an event. This is
an important aspect of split-phase interfaces: They are bidirectional. There is

16
3 nesC 3.6 Generic Components

a downcall – generally a command – that starts an operation and the corre-


sponding upcall, or event, to signal the completion.
The following code snippet gives an example for such an interface:
i n t e r f a c e Send {
command e r r o r t send ( m e s s a g e t ∗ msg , u i n t 8 t l e n ) ;
e v e n t void sendDone ( m e s s a g e t ∗ msg , e r r o r t e r r o r ) ;
command e r r o r t c a n c e l ( m e s s a g e t ∗ msg ) ;
command void ∗ g e t P a y l o a d ( m e s s a g e t ∗ msg ) ;
command u i n t 8 t maxPayloadLength ( m e s s a g e t ∗ msg ) ;
}

A component that uses such a (split-phase) interface MUST implement all


of the events. So, a higher-level component that wants to make use of the
Send interface by calling the send function must implement an event called
sendDone, that will be signalled by the send function.
When using split-phase interfaces, it is important to remember the first pro-
gramming hint: Signaling events from commands is dangerous, because this
can cause long call loops or corrupt memory caused by exploding stack size.
So instead of using commands, the correct way is to use tasks.

3.6 Generic Components


In TinyOS components are singletons, every configuration that names a com-
ponent names the same component. Generic components can have multiple
instances, and essentially provide a new copy with the parameter values substi-
tuted every time they are instantiated. While this leads to increased executable
code, it decreases the source code and improves code readabibility.
Generic components have the keyword generic before their signature and are
intantiated with the keyword new. The following examples are based on code
snippets from [Lev]:
Listing 3.3: Generic Module
g e n e r i c module BitVectorC ( u i n t 1 6 t m a x b i t s ) {
provides interface Init ;
provides i n t e r f a c e BitVector ;
}
implementation {
u i n t 8 t b i t s [ ( max bits + 7) / 8 ] ;
...
}

Listing 3.4: Generic Configuration


g e n e r i c c o n f i g u r a t i o n ExampleVectorC ( u i n t 1 6 t m a x b i t s ) {
...
provides i n t e r f a c e BitVector as Bits8 ;
provides i n t e r f a c e BitVector as Bits2 ;

17
3 nesC 3.7 Parameterized Interfaces and Configurations

provides i n t e r f a c e BitVector as Bits3 ;


}
implementation {
components new BitVectorC ( 8 ) a s BV1 ;
components new BitVectorC ( 1 0 ) a s BV2 ;
components new BitVectorC ( m a x b i t s ) a s BV3 ;

...

B i t s 1 = BV1 ;
B i t s 2 = BV2 ;
B i t s 3 = BV3 ;
}

Listing 3.4 generates 3 instances of BitVectorC, where BV3 is set to the value
of max bits which is defined at the instantiation of the configuration.
Without generic components it would be necessary to write different modules
for all the max bits values.

3.7 Parameterized Interfaces and Configurations


We have seen one way of providing independent instances in the last section in
form of generalization. In some applications however this approach has some
drawbacks. For example when listening to UDP Packets on different Ports.
It would be possible to implement a generic interface leading to configurations
like
components new UdpReceive (UDP PORT A) a s Receive1 ;
components new UdpReceive (UDP PORT B) a s Receive2 ;

but this would mean unnecessary code repeation and also force the caller to
pass the argument as a run-time parameter.
Parameterized interfaces are in essence an array of interfaces and look as
followed:
i n t e r f a c e UdpReceive {
e v e n t void r e c e i v e d ( i n a d d r t ∗ s r c I p , u i n t 1 6 t s r c P o r t ,
u i n t 8 t ∗ data , u i n t 1 6 t l e n ) ;
}

module UdpTransceiverP {
<... >
p r o v i d e s i n t e r f a c e UdpReceive [ u i n t 1 6 t p o r t ] ;
<... >
}
implementation {
<... >
default e v e n t void UdpReceive . r e c e i v e d [ u i n t 1 6 t p o r t ] ( i n a d d r t ∗ s r c I p ,
u i n t 1 6 t s r c P o r t , u i n t 8 t ∗ data , u i n t 1 6 t l e n ) {
<... >
}
<... >
}

18
3 nesC 3.8 Wiring

providing us with 65535 possible different receivers.

3.8 Wiring
As said before, in nesC a component can only call functions and access variables
whithin its local namespace. To call functions outside it’s scope, a set of names
in one component, generally an interface, must be mapped to a set of names
in another component. This operation is called wiring.

3.8.1 Modules vs. Configurations


Components can either be Modules or Configurations – both use and provide
interfaces. This set of used and provided interfaces defines the signature of the
component.
The difference between Modules and Configurations lies in their implemen-
tation: while configurations are implemented by other components, which they
wire, modules are executable code. Modules are written for the most part in
standard - C.

3.8.2 Wiring-Operators
There are 3 operators for wiring components together:
• <-
• ->
• =
The first two operators are interchangeable, for example this two lines are
identical:
MyComponent . U s e d I n t e r f a c e −> OtherComponent . P r o v i d e d I n t e r f a c e ;
OtherComponent . P r o v i d e d I n t e r f a c e <− MyComponent . U s e d I n t e r f a c e ;

In short, the arrow always points from the user of an interface to the provider
of that interface:
User −> P r o v i d e r ;

As soon as MyComponent is connected this way to OtherComponent, My-


Component can use all of the functions provided by ProvidedInterface. Ad-
ditionally, UsedInterface MUST implement all the handlers OtherComponent
offers events for.

19
3 nesC 3.8 Wiring

If MyComponent wants to call a function provided by OtherComponent, the


call would look like this:
c a l l U s e d I n t e r f a c e . FunctionName(< a r g u m e n t l i s t >);

To implement the handler for the events that can be signaled by Provided-
Interface, a construct of this form in UsedInterface is neccessary:
e v e n t <r e t u r n t y p e > U s e d I n t e r f a c e . EventName(< a r g u m e n t l i s t >)
{
/∗
code t o h a n d l e t h e new s i t u a t i o n , as s i g n a l l e d by t h i s e v e n t
∗/
}

The third operator ’=’ exports an interface. It defines how the configuration
of an interface is implemented, by delegating it to another component. In
contrast, the ’arrow’ - operator combines components that already exist.
Listing 3.5: GlcdC.nc
/∗ ∗
∗ High l e v e l i m p l e m e n t a t i o n f o r KS0108 Glcd
∗ @author : Markus Hartmann e988811@student . t u w i e n . ac . a t
∗ @date : 01.02.2012
∗/

c o n f i g u r a t i o n GlcdC
{
p r o v i d e s i n t e r f a c e Glcd ;
}

implementation
{
components MainC ;
components GlcdP ;
components HplKS0108C ;

Glcd = GlcdP . Glcd ;


GlcdP . Hpl −> HplKS0108C ;
MainC . S o f t w a r e I n i t −> GlcdP . I n i t ;
}

The difference is explained on the basis of codelisting 3.5, the top-level con-
figuration for a component that provides functionality for a graphical display.
This component provides the interface Glcd which can be used by a high-level
programmer to easily use such a display. GlcdC consists of the private com-
ponent GlcdP and uses the interface HPL provided by HplKS0108C and Init
provided by MainC. Glcd is an interface of the configuration itself, implemented
in the component GlcdP and mapped to by using “=”. The interface Glcd gets
exported by the configuration so that other, higher-level components can use
this interface by specifying that component GlcdC with interface Glcd is used.
Opposite to that, component HplKS0108C is used “inside” to get the work
done (hidden from the user of GlcdC, no functionality is exported to a higher

20
3 nesC 3.8 Wiring

level). GlcdC wires itself to the SoftwareInit interface from MainC, which calles
the init() function after startup.

21
4 MicroC/OS-II
To emphasize the characteristics of TinyOS, another OS called OS-II is pre-
sented. The MicroC kernel was developed by Jean J. Labrosse.

4.1 Basics
MicroC/OS-II is a portable, ROMable, scalable preemptive real-time multitask-
ing kernel, written in ANSI-C. Small portions of the sourcecode are written in
assembler to adapt to different processor architectures. MicroC/OS-II is based
on MicroC/OS, also called The Real Time Kernel, which was published in 1992.
MicroC/OS v1.11 is compatible to its successor.
MicroC/OS-II is used in all kinds of embedded systems, ranging from engine
controls to audio equiment.
Important characteristics of this real-time multitasking OS are:
• Scaleable, with a minimum RAM footprint of 6KByte
• Maximum RAM footprint 24KByte
• Preemptive scheduler
• 10 Kernel services
• 80 System calls
• Support for semaphores
• Support for event flags
• Support for message queues
• Support for message mailboxes
• Up to 250 application tasks
• Constant / deterministic execution time for most services provided
• Support for large number of processor architectures
• Supported processors range from 8bit to 64bit architectures
• Supports multi-threaded applications

22
4 MicroC/OS-II 4.2 Differences TinyOS - MicroC/OS-II

4.2 Differences TinyOS - MicroC/OS-II

4.2.1 Real-Time
A real-time system is a system where not only the correctness of a calculation is
important, but also the instant when this calculation was finished. The most
import features of a real-time kernel are minimal and predictable interrupt
latency and task switching latency.
While MicroC/OS-II supports a timely determinstic behaviour, no such as-
sertion can be given for TinyOS.

4.2.2 Scheduler
MicroC/OS-II has a preemptive scheduler – that means that every task gets
only a limited time for using the CPU. The time a task gets for execution also
depends on the task’s priority – all tasks MUST have different priorities –
because otherwise additional round-robin scheduling or similar would be nec-
essary to handle tasks with equal priority. More important tasks get higher
priority.
A task can be in 5 different states, as shown in figure 4.1:

Figure 4.1: Statemachine for Tasks

• Dormant: task is loaded in memory but not ready to run yet


• Ready: task is ready to run, but higher-priority task is running at the
moment
• Running: task is in control of the CPU
• ISR: interrupt has occured, CPU is executing ISR instead of task
• Waiting: task waits for an event (completion of IO operation, ...)

23
4 MicroC/OS-II 4.2 Differences TinyOS - MicroC/OS-II

In contrast, TinyOS knows only 3 states:


• Queued: task is queued, but a sooner queued task is running at the
moment
• Running: task is in control of the CPU
• ISR: interrupt has occured, CPU is executing ISR instead of task
Also, as already said, TinyOS uses a non-preemptive scheduler - see Chap-
ter 2 for details.
TinyOS also provides a thread library called TOSThreads which supports
preempitve applocation level threads. However, this library has not been ported
for the bigAVR6 or bigAVR6 1280 platform.

4.2.3 Mutual Exclusion


Whenever different tasks need to share data with each other, some points must
be ensured to avoid data corruption and resource contention. Problems arise,
for example, if task A gets scheduled and accesses a data element that is also
needed by task B. If task A gets preempted by task B before task A’s calcula-
tions are finished, task B works on incomplete data, possibly invalidating it’s
calculations. To prevent such situations, MicroC/OS-II provides the following
mechanisms:
• Disabling/Enabling of interrupts with macros
• Semaphores
By disabling interrupts, a task or ISR can assure that it won’t get preempted
by an ISR or by a task, so this is an easy way to grant mutual exclusion.
Drawbacks of this solution are that the system obviously can’t react to other,
possibly important, interrupts. Additionally, because the Micro/OS-II kernel
uses timeslicing, the task scheduler is deactivated because no timer interrupts
are handled. Therefore, a badly designed task can halt the whole system if it
enters a deadlock or some kind of infinite loop.
Semaphores, developed by Edsger W. Dijkstra, are software constructs that
can be used for the same goal. Additionally, they can be used for syncronizing
tasks, as described in the following section.
Because TinyOS uses a non-preemptive scheduler, no such constructs are
necessary. Because a task cannot get suspended (apart from an interrupt) by
another task, every task is responsible to keep it’s data in a consistent state.

24
4 MicroC/OS-II 4.2 Differences TinyOS - MicroC/OS-II

4.2.4 Intertask Communication


The process of sharing data between different tasks or ISRs is called inter-
task communication. Therefore, MicroC/OS-II supports the following ways of
sharing data between tasks
• Message Mailboxes
• Message Queues
MircoC/OS-II provides kernel services to send messages by depositing a
pointer variable into a task’s mailbox. A task that expects such a message
is suspended and put onto a waitinglist. If the message arrives within a time-
out, the highest-priority task that is waiting for the message is woken up.
A message queue is basically an array of such message mailboxes.
In TinyOS, a task can share data by sharing a pointer or by passing a pa-
rameter (if supported by the used Task interface).

4.2.5 Task Synchronisation


• Semaphores
• Event Flags
Aside from using semaphores for granting mutual exclusion, this software
constructs can also be used to synchronize a task with an ISR or other tasks.
Additionally, MicroC/OS-II offers kernel services to set, clear and wait for
event flags.
Syncronisation in TinyOS is implemented by events.

4.2.6 Memory Footprint


When using a kernel to manage tasks, the total memory that is needed consists
of the application code size + the kernel code size. A minimum ram footprint
of 6kByte is given by the developer of MicroC/OS-II.

25
5 bigAVR6
5.1 The Hardware
This development board, as shown in Figure 5.1, is produced by mikroElek-
tronika and supports 64- and 100-pin AVR TQFP packages.

5.1.1 Onboard - Features


• 2 x UART
• high-speed CAN transceiver MCP2551
• USB 2.0 (if supported by MCU)
• MMC/SD card slot
• digital thermometer DS1820
• onboard USB 2.0 programmer
• real-time clock DS1307
• 86 LEDs to indicate logic state of all microcontroller-pins
• 86 push buttons to control microcontroller digital inputs
• IDC10 connectors for all microcontroller pins
• DIP - switches to separate port pins from pull-up/down resistors
• potentiometer for testing the ADC - channels
• 1KBit serial EEPROM 24AA01

5.1.2 Extensions
• 2x16 Character LCD, directly connectable via on-boad connectors
• 64x128 GLCD with touchscreen foil, directly connectable via on-boad
connectors
• IEEE802.3 extensionboard 10MBit
• SmartMP3 decoder board
• ...

26
5 bigAVR6 5.2 Supported Modules

Figure 5.1: bigAVR6 platform, [Mika]

5.2 Supported Modules


5.2.1 Character LCD 2x16
A 2x16 alphanumeric LCD module is available for displaying ASCII - charac-
ters. The display backlight can be turned on with switch SW15/8, as shown in
schematic 5.2, the brightness can be adjusted with potentiometer P1

Figure 5.2: LCD 2x16, [Mika]

The logic level of the following pins MUST NOT be touched by the pro-
grammer when using the LCD2x16:

27
5 bigAVR6 5.2 Supported Modules

• PORT C: PC2, PC3, PC4, PC5, PC6, PC7,


To use the LCD, component BufferedLcdC with interface BufferedLcd can
be used. The display initializes itself by wiring to MainC.SoftwareInit. See
listing 5.1 for the available commands. After initializing, data can be written
to the LCD memory, and the display is updated by calling forceRefresh(). A
command autoRefresh(uint32 t period) is provided which will start a timer and
call forceRefresh() every period milliseconds. It should be noticed that once-
written data is preserved unless the corresponding position is overwritten by
new text or the display is cleared.
Listing 5.1: BufferedLcd.nc
/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 22.01.2012
∗/

#include <a v r / pgmspace . h>

i n t e r f a c e BufferedLcd {
/∗ ∗
∗ @param p e r i o d r e f r e s h p e r i o d i n ms , s e t t o 0 t o d i s a b l e a u t o r e f r e s h
∗/
command void a u t o R e f r e s h ( u i n t 3 2 t p e r i o d ) ;
command void c l e a r ( ) ;
command void w r i t e ( char ∗ s t r i n g ) ;
command void w r i t e P ( const char ∗ s t r i n g ) ;
command void goTo ( u i n t 8 t l i n e , u i n t 8 t c o l ) ;
command void f o r c e R e f r e s h ( ) ;
}

When examing schematic 5.2, one can see that there is a design flaw existing:
pin RW is bound to GND. Because of this (low=write operation), no read
operation is possible. Accordingly, it is not possible to read the corresponding
register to determine whether a write-operation has already finished. To handle
this problem and give the LCD controller enough time to process a write-
operation(needed for initializing, clearing the display and writing characters to
it), there are two options:
• use busywaiting - blocking
• use a timer - non-blocking
With the first solution - busy waiting - the time to wait can be minimized
to the absolutely necessary time, but obviously the time spent in the spinloop
is lost cpu time, which is bad.
The second solution - using the generic timer interface TimerMilliC - doesn’t
waste cpu time(apart from the extratime spent in the timer’s interrupt vector),
but problematic about this solution is that the existing timer-framework doesn’t
provide good granularity. The minimal periodic time that can be achieved

28
5 bigAVR6 5.2 Supported Modules

is about 20msec, which is hereby the waiting time for every character when
sending a string to the display. While this is not problematic when initializing
or clearing the display, a considerable delay is introduced when text is written
to the display.
The interface provided uses busy waiting to write a single character. To
minimize the time while refreshing the display, only changed lines are rewritten.

5.2.2 GLCD
The GLCD extension consists of a KS0108B GLCD dot matrix liquid crystal
graphic display with a resolution of 128 x 64 pixel. As the schematics show in
Figure 5.3, SW15/8 must be turned on to activate the GLCD-backlight, the
contrast can be changed with potentiometer P3.
The logic level of the following pins MUST NOT be touched by the pro-
grammer when using the GLCD and the touchscreen:
• PORT A: all ports reserved for GLCD
• PORT E: PE2, PE3, PE4, PE5, PE6, PE7 reserved for GLCD
• PORT F: PF0, PF1 reserved for touchscreen
• PORT G: PG3, PG4 reserved for touchscreen

Figure 5.3: GLCD schematics, [Mika]

To use the GLCD in an application, component GlcdC with interface Glcd


can be used. This interface (as shown in lising 5.2) provides high-level functions

29
5 bigAVR6 5.2 Supported Modules

for writing and drawing objects such as dots, rectangles and circles. GlcdC itself
is wired to HplKS0108C for low-level functions and to MainC.SoftwareInit. The
latter ensures that the hardware is initialized properly without any necessary
action on the users side.
Listing 5.2: Glcd.nc
/∗ ∗
∗ High l e v e l i n t e r f a c e f o r KS0108 GLCD D i s p l a y
∗ @author : Markus Hartmann e988811@student . t u w i e n . ac . a t
∗ @date : 01.02.2012
∗/

#include ”KS0108 . h”

i n t e r f a c e Glcd
{

/∗ ∗
∗ Set p i x e l

∗ @param x−c o o r d i n a t e
∗ @param y−c o o r d i n a t e

∗ @return SUCCESS

∗/
command e r r o r t s e t P i x e l ( const u i n t 8 t x , const u i n t 8 t y ) ;

/∗ ∗
∗ Clear p i x e l

∗ @param x−c o o r d i n a t e
∗ @param y−c o o r d i n a t e

∗ @return SUCCESS

∗/
command e r r o r t c l e a r P i x e l ( const u i n t 8 t x , const u i n t 8 t y ) ;

/∗ ∗
∗ Invert pixel

∗ @param x−c o o r d i n a t e
∗ @param y−c o o r d i n a t e

∗ @return SUCCESS

∗/
command e r r o r t i n v e r t P i x e l ( const u i n t 8 t x , const u i n t 8 t y ) ;

/∗ ∗
∗ Draw l i n e

∗ @param f i r s t p o i n t x
∗ @param f i r s t p o i n t y
∗ @param se c on d p o i n t x
∗ @param se c on d p o i n t y

∗ @return SUCCESS

∗/

30
5 bigAVR6 5.2 Supported Modules

command e r r o r t drawLine ( const u i n t 8 t x1 , const u i n t 8 t y1 ,


const u i n t 8 t x2 , const u i n t 8 t y2 ) ;

/∗ ∗
∗ Draw r e c t a n g l e

∗ @param upper l e f t x
∗ @param upper l e f t y
∗ @param l o w e r r i g h t x
∗ @param l o w e r r i g h t y

∗ @return SUCCESS

∗/
command e r r o r t drawRect ( const u i n t 8 t x1 , const u i n t 8 t y1 ,
const u i n t 8 t x2 , const u i n t 8 t y2 ) ;

/∗ ∗
∗ Draw e l l i p s e

∗ @param c e n t e r x
∗ @param c e n t e r y
∗ @param r a d i u s h o r i z o n t a l
∗ @param r a d i u s v e r t i c a l

∗ @return SUCCESS

∗/
command e r r o r t d r a w E l l i p s e ( const u i n t 8 t x , const u i n t 8 t y ,
const u i n t 8 t r a d i u s h , const u i n t 8 t r a d i u s v ) ;

/∗ ∗
∗ F i l l Display with pattern

∗ @param p a t t e r n

∗ @return SUCCESS

∗/
command e r r o r t f i l l ( u i n t 8 t p a t t e r n ) ;

/∗ ∗
∗ drawText

∗ @param t e x t
∗ @param x−c o o r d i n a t e o f l o w e r l e f t e d g e
∗ @param y−c o o r d i n a t e o f l o w e r l e f t e d g e

∗ @return SUCCESS

∗/
command void drawText ( const char ∗ t e x t , const u i n t 8 t x , const u i n t 8 t y ) ;

5.2.3 Touch Screen


The GLCD is combined with a touchscreen foil, sticked onto the GLCD-surface.
Activate SW13/1,2,3,4 to use it. The internal low-level module HplTouchScreen

31
5 bigAVR6 5.2 Supported Modules

uses ADC channels 0 and 1 to detect pressure. Interface TouchScreen (List-


ing 5.3) provides commands to request coordinates and to calibrate the Screen.
As shown in Figure 5.4 interface Glcd is already provided by TouchScreen, and
can be used without utilizing component GlcdC directly.
TouchScreenDemoC . TouchScreen −> TouchScreenC . TouchScreen ;
TouchScreenDemoC . Glcd −> TouchScreenC . Glcd ;

Figure 5.4: TouchScreen components

Listing 5.3: TouchScreen.nc


/∗ ∗
∗ I n t e r f a c e f o r TouchScreen
∗ @author : Markus Hartmann e988811@student . t u w i e n . ac . a t
∗ @date : 13.02.2012
∗/

#include ” TouchScreen . h”

i n t e r f a c e TouchScreen
{

/∗ ∗

∗ @param x o f f s e t
∗ @param y o f f s e t

∗ @return SUCCESS
∗/
command e r r o r t c a l i b r a t e ( i n t 8 t x o f f s e t , i n t 8 t y o f f s e t ) ;

/∗ ∗

∗ @param p o i n t e r t o b u f f e r f o r c o o r d i n a t e s

32
5 bigAVR6 5.2 Supported Modules

∗ @return SUCCESS i f r e q u e s t was a c c e p t e d


∗ EBUSY i f a n o t h e r r e q u e s t i s p e n d i n g
∗/
command e r r o r t g e t C o o r d i n a t e s ( t s c o o r d i n a t e s t ∗ xy ) ;

/∗ ∗
∗ N o t i f i c a t i o n t h a t c o o r d i n a t e s are ready

∗/
e v e n t void c o o r d i n a t e s R e a d y ( void ) ;
}

5.2.4 MMC
A MMC/SD connector is available onboard so that memory cards can be
interfaced to the microcontroller via SPI. As shown in Figure 5.5, activate
SW15/3/4/5/6/7 to use it. Because the memory card is powered with 3.3V,
whereas the microcontroller needs 5V supply, a 74LVCC3245 bus transceiver
is used to obtain the needed voltage levels.
The logic level of the following pins MUST NOT be touched by the pro-
grammer when using the MMC:
• PORT B: PB1, PB2, PB3 reserved for MMC: SCK / MISO / MOSI
• PORT G: PG1, PG2 reserved for MMC: CS / CD

Figure 5.5: MMC/SD Schematics, [Mika]

Component SdcardC provides interface Sdcard to enable an application pro-


grammer to easily read RAW - data from a MMC. No write functionality is
supported yet. The available functions are shown in Listing 5.4.
To read data, init() must be called first to initialize the memorycard. Af-
ter initialization the event initDone(error t) is signaled, indicating the current
status by the passed value error t. Afterwards, data can be read from the
memorycard by calling

33
5 bigAVR6 5.2 Supported Modules

c a l l Sdcard . r e a d B l o c k ( blockAddr , ∗ b u f f e r ) ;

After completion, event readBlockDone(uint8 t *buffer, error t error) is sig-


naled to the application and data is available by a pointer, in units of 32 byte
blocks.
Listing 5.4: Sdcard.nc
/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 12.03.2012

∗ b a s e d on an i m p l e m e n t a t i o n o f Harald Glanzer , 0727156 TU Wien
∗/

i n t e r f a c e Sdcard {
command e r r o r t i n i t ( ) ;
e v e n t void i n i t D o n e ( e r r o r t e r r o r ) ;
command e r r o r t r e a d B l o c k ( u i n t 3 2 t blockAddr , u i n t 8 t ∗ b u f f e r ) ;
e v e n t void readBlockDone ( u i n t 8 t ∗ b u f f e r , e r r o r t e r r o r ) ;
command b o o l i n s e r t e d ( ) ;
}

The following limitations are to be noticed:


• Read Only Access
• Raw data, no filesystem supported
• Data is always read in 32 byte blocks

5.2.5 MP3 extension board


The SmartMP3 extension board shown in Figure 5.6 consists of a VS1011e
decoder chip and a SD card module. The card module can be used with com-
ponent SdCardC as described in Section 5.2.4. CS, CD and MISO from the
MMC module MUST be deactivated via SW15/4/6/7.

Figure 5.6: MP3 board, [Mika]

34
5 bigAVR6 5.2 Supported Modules

The board is connected via SPI, the maximum speed for reading registers is
2MHZ (sufficiently below CLKI6
= 4, 1M HZ according to manual), the max-
imum for sending data 4MHZ. The module is wired to SoftwareInit for ini-
tialization and provides high level functions with interface MP3 as shown in
Listing 5.5.
Listing 5.5: MP3.nc
/∗ ∗
∗ @author : Markus Hartmann <e9808811@student . t u w i e n . ac . at>
∗ @date : 31.07.2012
∗/

i n t e r f a c e MP3
{
/∗ ∗
∗ S t a r t and s t o p s i n e t e s t

∗ @param on TRUE t o s t a r t − FALSE t o s t o p

∗ @return SUCCESS i f command was s u c c e s s f u l l y s e n t o v e r SPI
∗/
command e r r o r t s i n e T e s t ( b o o l on ) ;

/∗ ∗
∗ S e t volume

∗ @param volume Volume t o be s e t

∗ @return SUCCESS i f command was s u c c e s s f u l l y s e n t o v e r SPI
∗/
command e r r o r t setVolume ( u i n t 8 t volume ) ;

/∗ ∗
∗ Send d a t a

∗ @param d a t a A p o i n t t o a d a t a b u f f e r where t h e d a t a i s s t o r e d
∗ @param l e n Length o f t h e message t o be s e n t − d a t a must be a t l e a s t as l a r g e as l e n

∗ @return SUCCESS i f r e q u e s t was g r a n t e d and s e n d i n g t h e d a t a s t a r t e d
∗/
command e r r o r t sendData ( u i n t 8 t ∗ data , u i n t 8 t l e n ) ;

/∗ ∗
∗ Check i f VS1011e i s r e a d y t o a c c e p t new d a t a

∗ @return FALSE i f VS1011e i s b u s y or s e n d i n g o f d a t a i s i n p r o g r e s s − o t h e r w i s e TRUE
∗/
command b o o l i s B u s y ( void ) ;

/∗ ∗
∗ Read de c od e time

∗ @param d a t a A p o i n t t o a d a t a b u f f e r where t h e d ec o de time w i l l be s t o r e d

∗ @return SUCCESS i f command was s u c c e s s f u l l y s e n t o v e r SPI
∗/
command e r r o r t readTime ( u i n t 1 6 t ∗ time ) ;

35
5 bigAVR6 5.2 Supported Modules

/∗ ∗
∗ S e t d e co d e time

∗ @param time The time t o s e t

∗ @return SUCCESS i f command was s u c c e s s f u l l y s e n t o v e r SPI
∗/
command e r r o r t setTime ( u i n t 1 6 t time ) ;
}

5.2.6 Ethernet board

Figure 5.7: Ethernet Board, [Mikb]

This extension board, shown in Figure 5.7, can be used for sending and
receiving IEEE802.3 frames, and therefore embedding the development board
into a network. The board features an ethernet controller ENC28J60 that
exchanges data with a microcontroller via SPI. The board can be connected to
dsPIC, AVR-8051 and PIC by three 10-pin IDC connectors 1 . The board needs
3.3V voltage supply, but has a 74LVXc3245 bus transceiver chip for running
the board with 5V logic levels. Therefore, jumper J1 has to be set correctly.
A basic UDP/IP/ARP stack has been implemented, with the following lim-
itations:
• No UDP - level checksum
• No IP - level options
• No IP - level fragmentation
• ARP request/reply only
1
Because MikroElektronika did not manage to make the pin layout compatible with the
bigAVR6 board, it is necessary to use single pin connectors.

36
5 bigAVR6 5.2 Supported Modules

For using the extension board with the bigAVR6, the following requirements
have to be provided:
• Jumper J1 on the Ethernetboard must be set to 5V
• SPI-AVR-8051 VCC must be connected to 5V
• SPI-AVR-8051 GND must be connected to ground
• SPI-AVR-8051 CS must be connected to PORT B0
• SPI-AVR-8051 SCK must be connected to PORT B1
• SPI-AVR-8051 MOSI must be connected to PORT B2
• SPI-AVR-8051 MISO must be connected to PORT B3
• SPI-AVR-8051 RST must be connected to PORT B4
• SPI-AVR-8051 INT must be connected to PORT D0
Obviously, the state of this connected pins MUST NOT be touched by the
programmer.
IMPORTANT NOTE
RS-232 Port B CAN NOT BE USED together with this component
because Port D, which is used as the external interrupt source from the ether-
netboard, is also used as UART1(=RS-232 Port B) RX pin. Instead, RS-232
Port A MUST be used if the UDP-services are also needed.
Also, jumper J21 MUST BE set to onboard programmer for IEEE8023C
to function!
The Ethernet Board module Enc28j60C uses Interface Mac, which is pro-
vided by LlcTransceiverC and provides a control interface by itself. A complete
wiring example is shown in Listing 5.6 .
Listing 5.6: UdpAppC.nc
/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 12.12.2011
∗/

#include ” debug . h”
#include ” u d p c o n f i g . h”

c o n f i g u r a t i o n UdpAppC {

implementation {
components MainC ;
components UdpDemoC ;
components new UdpC(UDP PORT ) ;
#i f n d e f WLAN
components Enc28j60C a s EthernetC ;

37
5 bigAVR6 5.2 Supported Modules

#e l s e
components Mrf24wC a s EthernetC ;
#endif
components new T i m e r M i l l i C ( ) a s Timer ;
components LlcTransceiverC ;
components BufferedLcdC a s LcdC ;
components IpTransceiverC ;
components StdoDebugC ;
components PingC ;

UdpDemoC −> MainC . Boot ;


UdpDemoC . UdpSend −> UdpC ;
UdpDemoC . UdpReceive −> UdpC ;
UdpDemoC . C o n t r o l −> EthernetC ;
UdpDemoC . Timer −> Timer ;
L l c T r a n s c e i v e r C . Mac −> EthernetC ;
UdpDemoC . I p C o n t r o l −> I p T r a n s c e i v e r C ;
UdpDemoC . Lcd −> LcdC ;
#i f d e f WLAN
UdpDemoC . WlanControl −> EthernetC ;
#endif
}

When the application wants to send data to or receive data from a remote
host, it requests hardware control by calling the start function of the Split
Control interface. After receiving the event
void s t a r t D o n e ( e r r o r t e r r o r )

Data can be sent and received by using component UdpC which provides
interface UdpSend and UdpReceive, shown in 5.7 and 5.8.
Listing 5.7: UdpSend.nc
/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 12.12.2011

∗ b a s e d on an i m p l e m e n t a t i o n o f Harald Glanzer , 0727156 TU Wien
∗/

#include ”udp . h”

i n t e r f a c e UdpSend {
command e r r o r t send ( i n a d d r t ∗ d s t I p , u i n t 1 6 t d s t P o r t , u i n t 8 t ∗ data , u i n t 1 6 t l e n ) ;
e v e n t void sendDone ( e r r o r t e r r o r ) ;
}

Listing 5.8: UdpReceive.nc


/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 12.12.2011

∗ b a s e d on an i m p l e m e n t a t i o n o f Harald Glanzer , 0727156 TU Wien
∗/

i n t e r f a c e UdpReceive {
e v e n t void r e c e i v e d ( i n a d d r t ∗ s r c I p , u i n t 1 6 t s r c P o r t , u i n t 8 t ∗ data , u i n t 1 6 t l e n ) ;
}

38
5 bigAVR6 5.2 Supported Modules

Afterwards, the data is handed down the stack, as shown in Figure 5.8.
At first, an UDP header is generated, and the payload, as assigned by the
application, is attached to it. As mentioned above, NO checksum is generated
at this level - if needed, a checksum must be calculated at application level.
This UDP packet(payload + UDP-header) is then handed to the next level,
the IP level.
At this level, a checksum is generated, which includes the IP-header only. In
the next step, a routing-decision has to be made: either the packet is addressed
to a host inside the Network (the remote host has the same network-adress than
the IP that has been assigned to the bigAVR6 board), or the packet must hop
outside. In the first case, the packet can be sent to the host directly, otherwise,
it must be sent to the default gateway, which can be assigned with the IpControl
interface provided by IpTransceiverC as seen in 5.9. Note the ’,’ instead of the
usual ’.’ between the numbers:
#d e f i n e GATEWAY 1 9 2 , 1 6 8 , 0 , 1
i n a d d r t cgw = { . b y t e s {GATEWAY} } ;
c a l l I p C o n t r o l . setGateway(&cgw ) ;

Listing 5.9: IpControl.nc


/∗ ∗
∗ @author : Andreas Hagmann <ahagmann@ecs . t u w i e n . ac . at>
∗ @date : 12.12.2011

∗ b a s e d on an i m p l e m e n t a t i o n o f Harald Glanzer , 0727156 TU Wien
∗/

i n t e r f a c e IpControl {
command void s e t I p ( i n a d d r t ∗ i p ) ;
command void setGateway ( i n a d d r t ∗ gateway ) ;
command void setNetmask ( i n a d d r t ∗ netmask ) ;

command i n a d d r t ∗ g e t I p ( ) ;
command i n a d d r t ∗ getGateway ( ) ;
command i n a d d r t ∗ getNetmask ( ) ;
}

When the proper destination IP has been found, an ARP lookup is done in
a cache. If no ARP entry is found for the destionation IP, a lookup is sent
automatically. Be aware that, if no MAC is found, the ARP-request triggering
packet is lost and must be resent by the application. If the MAC is known, it is
extracted from the MAC cache, and component IEEE802.3 takes over control,
where the frameheader and the payload (data + udp-header + ip-header) is
copied into the transmit memory of the ENC28J60 by SPI. Afterwards, the
communication is started, and the completion is signaled to the application.
The MAC address is calculated out of TOS NODE ID and can be set during
installation with
make <p l a t f o r m > i n s t a l l ,< id >

39
5 bigAVR6 5.2 Supported Modules

Note that there is no space after the comma!


To receive a packet from remote hosts, the packet must either has the
proper destination MAC set, or must be a multicast frame(destination
0xFFFFFFFFFFFF), otherwise the Ethernet controller chip ENC28J60 will
not accept it. If a valid MAC is present, the ENC28J60 will autonomously
copy the packet into the receive buffer and signal completion by an interrupt.
The packet will be read out by component Enc28j60C and handed over to the
IP-level. If the packet is an ARP - request, a corresponding reply will be sent,
otherwise the payload will be handed over one level higher, which is the UDP
- level. Note that the IP-checksum will NOT be checked. At UDP level, the
actual payload will get extracted and is handed over to the application.

Figure 5.8: UDP Stack

Network Sniffing

For testing purposes, the command line tool netcat can be used. As example,
a constant string should be sent to the ip 192.168.1.100, destinationport 4443,
as shown in the following listing.
...
dstIP [ 0 ] = 192;
dstIP [ 1 ] = 168;
dstIP [ 2 ] = 1 ;

40
5 bigAVR6 5.2 Supported Modules

dstIP [ 3 ] = 100;
c a l l UDP. sendData ( ( u i n t 1 6 t ∗ ) ” h e l l o world ” , ( u i n t 8 t ∗ ) dstIP ,
8 0 , 4 4 4 3 , s i z e o f ( ” h e l l o world ” ) ) ;
...

To receive the string on the corresponding host, this command line can be
used:
nc −u − l 4443

This starts netcat in listening mode, specifies that UDP instead of TCP
should be used and that it should bind to port 4443. Port 4443 belongs to the
so-called unprivileged ports, where a ’normal’, unpriviliged user can bind to.
All ports greater thant 1023 belong to this group.

5.2.7 UART
There are 2 UART ports available onboard, RS-232 port A and port B. Compo-
nent PlatformSerialC is wired to port A and provides the following interfaces:
• StdControl to start/stop the Hardware
• UartControl to set speed and mode
• UartByte to send a single byte
• UartStream to send a String
To use the UartStream interface, receive interrupt must be enabled by hand.
A short example for wiring:
components P l a t f o r m S e r i a l C ;
components UartC ;

UartC . U a r t C o n t r o l −> P l a t f o r m S e r i a l C ;
UartC . UartStream −> P l a t f o r m S e r i a l C ;

And sending and receiving data:


c a l l Uart . s t a r t ( ) ;
c a l l U a r t C o n t r o l . s e t S p e e d ( TOS UART 115200 ) ;
c a l l U a r t C o n t r o l . s e t P a r i t y (TOS UART PARITY NONE ) ;

c a l l UartStream . send ( ( u i n t 8 t ∗ ) ” H a l l o Du ! \ n” , 1 0 ) ;
c a l l UartStream . e n a b l e R e c e i v e I n t e r r u p t ( ) ;
c a l l UartStream . r e c e i v e ( r c v B u f f e r , s i z e o f ( r c v B u f f e r ) ) ;

Switch SW15/5/6 respective SW15/7/8 must be used to active the ports, as


shown in Figure 5.9.
The logic level of the following pins MUST NOT be touched by the pro-
grammer when using the UART components:
• RS-232 A: Port E PE0, PE1

41
5 bigAVR6 5.2 Supported Modules

• RS-232 B: Port E PD2, PD3


Additionally, the following restrictions have to be noticed:
• RS-232 Port A: disable Jumper J21(set to on board programmer)
• RS-232 Port B: Port PD3 servers as TX, but also connected to RTC.
Disable with switch SW15/1

Figure 5.9: RS-232 Ports, [Mika]

5.2.8 RTC
The DS1307 Real Time Clock provides date and time with granulation of 1
second and an configureable square wave output. DS1307C provides interface
RTC as shown in 5.10 with functions to set the time, start/stop the clock and
configure the square wave output.
Listing 5.10: RTC.nc
/∗ ∗
∗ @author Markus Hartmann e988811@student . t u w i e n . ac . a t
∗/

#include ”RTC. h”

i n t e r f a c e RTC{

/∗ ∗
∗ S t a r t s the Realtime Clock

∗ @param d a t a S t a r t s t h e Clock , s e t t i n g d a t e / time
∗ I f NULL i s p a s s e d , t h e c l o c k i s s t a r t e d w i t h o u t
∗ changing anything .

42
5 bigAVR6 5.2 Supported Modules

∗ @return SUCCESS i f b u s a v a i l a b l e and r e q u e s t a c c e p t e d .


∗/
command e r r o r t s t a r t ( r t c t i m e t ∗ data ) ;

/∗ ∗
∗ S t o p s t h e R e a l t i m e C l o c k − The s e c o n d s a r e s e t t o 0

∗ @return SUCCESS i f b u s a v a i l a b l e and r e q u e s t a c c e p t e d .
∗/
command e r r o r t s t o p ( void ) ;

/∗ ∗
∗ Read time

∗ @param d a t a A p o i n t t o a d a t a b u f f e r where t h e r e s u l t s w i l l be s t o r e d

∗ @return SUCCESS i f b u s a v a i l a b l e and r e q u e s t a c c e p t e d .
∗/
command e r r o r t readTime ( r t c t i m e t ∗ data ) ;

/∗ ∗
∗ N o t i f i c a t i o n t h a t the r e s u l t s are ready

∗/
e v e n t void timeReady ( void ) ;

/∗ ∗
∗ C o n t r o l t h e Squarewave o u t p u t

∗ @param s q u a r e C o n f i g Output f r e q u e n c y o f t h e s q u a r e w a v e g e n e r a t o r o f t h e r t c :
∗ RTC SQW OFF, − D i s a b l e squarewave output
∗ RTC SQW 1HZ, − E n a b l e s 1Hz s q u a r e w a v e o u t p u t
∗ RTC SQW 4KHZ, − E n a b l e s 4kHz o u t p u t
∗ RTC SQW 8KHZ, − E n a b l e s 8kHz o u t p u t
∗ RTC SQW 32KHZ − E n a b l e s 32 kHz o u t p u t

∗ @return SUCCESS i f b u s a v a i l a b l e and r e q u e s t a c c e p t e d .
∗/
command e r r o r t setSquareWave ( r t c s q w t s q u a r e C o n f i g ) ;
}

The DS1307 is controlled via I2C, which is a shared resource in TinyOS. If


the I2C Bus is not available, a call to an RTC function will fail and return an
error. A 3V battery enables operation of the real-time clock even if the board
is disconnected from power supply.
The I2C Bus by default uses PortD0 and PortD1, the square wave out-
put is on PortD3 and/or PortE6. The I2C Ports are defined in tos/chip-
s/atm128/i2c/HplAtm128I2CBusC.nc - as seen in 5.10 it would also be possible
to use E4 and E5, although this is not currently supported by TinyOS.

5.2.9 Printf Library


Although not a hardware module, the Printf Library is highly dependent on
the underlying modules. To use it, one must declare the corresponding stdo
component in the configuration, include printf.h and - if used for debugging

43
5 bigAVR6 5.3 Supported Microcontrollers

Figure 5.10: DS1307 Ports, [Mika]

- debug.h. No additional wiring is necessary. There are 3 stdo components


available:
• 1. StdoUartC
sends output via RS232 port B
• 2. StdoGlcdC
shows output on the graphical lcd
• 3. StdoDebugC
sends printf and debug output via uart1 in debug mode
shows printf on the graphical lcd in normal mode
To enable debug mode without changing code use the following line for com-
pilation:
>env ‘ ‘CFLAGS=−DDEBUG ’ ’ make bigAVR6 ( i n s t a l l )

5.3 Supported Microcontrollers


Components HplAtm128[0]GeneralIOFastPortC were added to provide inter-
face GeneralIOPort for use with both Microcontrollers.

5.3.1 ATmega128
The ATmega128 Microcontroller is supported natively by TinyOS. However,
there is one necessary change to operate it with the bigAVR6 platform:
The original implementation was operated with an asynchronus timer sys-
tem driven by the clock output of the (ZigBee) wireless transceiver. As the

44
5 bigAVR6 5.3 Supported Microcontrollers

bigAVR6 development board has no external clock to listen to, it had to be


changed to synchroneous operation. The changed/added files can be found
under (tos/chips ecs/atm128/timerSync). Also it is now required to spec-
ify the correct clock frequency “MHZ” with a define in (tos/platforms/bi-
gAVR6/hartware.h)
MHZ has to be 8 or 16 - otherwise compilation will fail.

IMPORTANT NOTE:
It is possible to use a wrong value for MHZ - for example 8 when operating
with 16 MHz. The correctness of this value can not checked and may lead
to wrong baudrate calculation, incorrect timer signals and other undefined
behavior.

5.3.2 ATmega1280
The ATmega1280 is not supported by the original TinyOS, but is largely
identical with the supported ATmega1281. The same changes regarding asyn-
chronus/synchronus operation had to be made as within the ATmega128.
In addition it was necessary to change the HplAtm1280GeneralIOSlowPinP
as the ATmega1280 supports more pins and needs 16Bit Addresses to access
its Ports.

45
6 Resources used
• http://www.youtube.com/watch?v=j6hRsue5b30 / lecture about tinyos
• http://www.tinyos.net/tinyos-2.x/doc/html/tep2.html
• http://www.tinyos.net/tinyos-2.x/doc/html/tep106.html
• http://www.tinyos.net/tinyos-2.x/doc/html/tep108.html
• http://www.tinyos.net/tinyos-2.x/doc/html/tep112.html
• http://www.tinyos.net/tinyos-2.x/doc/pdf/tinyos-programming.pdf

46
Bibliography
[Lev] Philip Levis. TinyOS Programming. Treitlstr. 3/3/182-1, 1040 Vienna,
Austria. Available at http://www.tinyos.net/tinyos-2.x/doc/pdf/
tinyos-programming.pdf.
[LS] Philip Levis and Cory Sharp. Scheduler and Tasks. Treitlstr. 3/3/182-
1, 1040 Vienna, Austria. Available at http://www.tinyos.net/
tinyos-2.x/doc/html/tep106.html.
[Mika] MikroElektronika. BIGAVR6 User Manual. MikroElektronika. Avail-
able at http://www.mikroe.com/eng/downloads/get/352/bigavr6_
manual_v100.pdf”.
[Mikb] MikroElektronika. MikroElektronika Homepage. MikroElektron-
ika. Available at http://www.mikroe.com/eng/products/view/165/
smartmp3-board/”.
[Vie] ECS TU Vienna. Getting Started Guide. ECS TU Vienna. Available at
http://ti.tuwien.ac.at/ecs/teaching/courses/mclu/manuals/
getting-started-guide/at_download/file”.

47
A Setup Guide
It is assumed that avr-gcc and avrprog2 are already installed and working. The
following setup guide is from [Vie]
If not already installed, you have to install git by executing

sudo apt-get install git

Download the according binary packages of the nesC compiler and some
tool available from the course homepage http://ti.tuwien.ac.at/ecs/
teaching/courses/mclu/misc/tinyos-packages. For the correct path ask
your adviser of the course. If you don’t know if you need the 32 bit or 64 bit
packages find it out by

uname -m

If it says x86 64 you need the amd64 packages, i386 otherwise.


Install the nesC compiler including some tools, execute following lines in your
terminal when running a 32 bit linux:

sudo dpkg -i nesc_1.3.1-20100325_i386.deb


tinyos-tools-ecs_1.4.0-20100326_i386.deb

or in your 64 bit environment:

sudo dpkg -i nesc_1.3.1-20100325_amd64.deb


tinyos-tools-ecs_1.4.0-20100326_amd64.deb

Get TinyOS using

git clone <<insert repository path here>>

Get the repository path from your course advisor.

48
A Setup Guide

Syntax highlighting
Here you can find a TinyOS syntax highlighting file for ”gedit”: http://www.
keally.org/2009/02/20/tinyos-and-nesc-syntax-highlighting/

Envoironment variables
Enter in a terminal:
echo "export TOSROOT=/home/user/TOS_ECS" >> ~/.profile

echo "export TOSDIR=\$TOSROOT/tos" >> ~/.profile

echo "export MAKERULES=\$TOSROOT/support/make/Makerules" >> ~/.profile


where /home/user has to be replaced with the correct path.
You can always change your settings by editing your .profile file and reload
it with
. ~/.profile
To compile a TinyOS program for the bigAVR6 1280 platform enter
make bigAVR6_1280
make bigAVR6_1280 install,<TOS_NODE_ID>
where bigAVR6 1280 can be replaced with any supported platform. The id
after install is optional.

A.0.3 Visualize Components


TinyOS has a documentation feature called nesdoc which generates documen-
tation automatically. To generate documentation for an application enter
make bigAVR6_1280 docs
You will now find the documentation under $TOSROOT/doc/nesdoc/bi-
gAVR6 1280.

To visualize your entire application you can enter

make bigAVR6_1280 appdoc

which will generate a YourAppC.png file in the app directory.

49
B Pin Configuration of bigAVR6
PORTA
A0 A1
A2 A3 LCD128x64
LCD128x64 A4 A5 LCD128x64
LCD128x64 A6 A7 LCD128x64
PORTB
DS1820 B0 B1 SPI SCK
SPI MOSI B2 B3 SPI MISO
B4 B5
B6 B7
PORTC
C0 C1
LCD2x16 C2 C3 LCD2x16
LCD2x16 C4 C5 LCD2x16
LCD2x16 C6 C7 LCD2x16
PORTD
RTC EEPROM D0 D1 EEPROM RTC
RS-232B D2 D3 RS-232B RTC
D4 D5 CAN
CAN D6 D7
PORTE
RS-232A E0 E1 RS-232A
LCD128x64 E2 E3 LCD128x64
EEPROM RTC LCD128x64 E4 E5 LCD128x64 RTC EEPROM
RTC LCD128x64 E6 E7 LCD128x64
PORTF
Touch Panel F0 F1 Touch Panel
F2 F3
F4 F5
F6 F7

50
B Pin Configuration of bigAVR6

PORTG
DS1820 G0 G1 MMC CS
MMC CD G2 G3 Touch Panel
Touch Panel G4 G5
G6 G7

51

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy