David Culler, Jason Hill, Robert Szewczyk, Alec WooU.C. Berkeley2/9/2001
TinyOS Programming Boot Camp
Part II – Tiny OS Component Design and Tools
2-9-2001 TOS Boot 2 2
Networked Sensor System Challenge
• Managing multiple concurrent flows– some with real-time requirements
• Very limited I/O controller hierarchy– process every bit, or perhaps byte in CPU
• Asynchronous and synchronous devices• Limited storage and processing• At very low power
sensorsactuators
network
storage
2-9-2001 TOS Boot 2 3
TinyOS Execution Contexts
Hardware
Interrupts
eve
nts
commands
Tasks
2-9-2001 TOS Boot 2 4
TinyOS Storage Model
• Single shared stack
• Each component has a static frame– only accessible locally (except msg buffers)
• Msg buffers allocated statically by components, but shared dynamically by ownership discipline
2-9-2001 TOS Boot 2 5
TinyOS Commands and Events
{... status = TOS_CALL_COMMAND(name)(args)...}
TOS_COMMAND(name)(args) {...return status;}
{... status = TOS_SIGNAL_EVENT(name)(args)...}
TOS_EVENT(name)(args) {...return status;}
2-9-2001 TOS Boot 2 6
Commands
• Function call across component boundary– cause action to be initiated
– bounded amount of work
» cannot block
– always return status (0 => error)
» component can refuse to perform command
• share call stack and execution context
• command body has access to local frame
• commands may post tasks or call commands
• commands may not signal events
2-9-2001 TOS Boot 2 7
Events
• Upcall to notify action has occured– must do bounded (and small) amount of work– cannot block– access local frame, shares stack
• Lowest-level events triggered by hardware interrupts– hardware abstraction components perform critical section
and enable interrupts
• Events may signal events• Events may call commands
• Entire event “fountain” must stay within overall application jitter tolerance
2-9-2001 TOS Boot 2 8
FSM Programming Style
• Most components are essentially FSMs
• Composed via events and commands
• non-blocking!
sens_output_init
initc
sens_output_start
startc
/sub_clock_init
/sub_output_init
sens_clock_event
clocke
/getdata
sens_data_ready
datae
/output
clocke
2-9-2001 TOS Boot 2 9
TASKS
• provide concurrency internal to a component– longer running operations
• are preempted by events
• able to perform operations beyond event context
• may call commands
• may signal events
• not preempted by tasks
{...TOS_POST_TASK(name)...}
void TOS_TASK(name) {...}
2-9-2001 TOS Boot 2 11
Typical application use of tasks
• event driven data acquisition
• schedule task to do computational portion
char TOS_EVENT(MAGS_DATA_EVENT)(int data){
struct adc_packet* pack = (struct adc_packet*)(VAR(msg).data);
printf("data_event\n");
VAR(reading) = data;
TOS_POST_TASK(FILTER_DATA);
...
mags.c
2-9-2001 TOS Boot 2 12
Filter Magnetometer Data Task
TOS_TASK(FILTER_DATA){
int tmp;
VAR(first) = VAR(first) - (VAR(first) >> 5);
VAR(first) += VAR(reading);
VAR(second) = VAR(second) - (VAR(second) >> 5);
VAR(second) += VAR(first) >> 5;
VAR(diff) = VAR(diff) - (VAR(diff) >> 5);
tmp = VAR(first) - VAR(second);
if(tmp < 0) tmp = -tmp;
VAR(diff) += tmp;
if((VAR(diff) >> 5) > 85){
TOS_CALL_COMMAND(MAGS_LEDg_on)();
VAR(led_on) = 255;
}
}
2-9-2001 TOS Boot 2 13
Tasks in low-level operation
• transmit packet– send command schedules task to calculate CRC– task initiated byte-level datapump– events keep the pump flowing
• receive packet– receive event schedules task to check CRC– task signals packet ready if OK
• byte-level tx/rx– task scheduled to encode/decode each complete byte– must take less time that byte data transfer
• i2c component– i2c bus has long suspensive operations– tasks used to create split-phase interface– events can procede during bus transactions
2-9-2001 TOS Boot 2 14
High-level use of tasks
• virtual machine interpreter schedules an “interpretation task” on clock event– similar for data event
• may be a long running activity
• utilizes many low-level components
• reschedules itself on each virtual machine instruction
2-9-2001 TOS Boot 2 15
Scheduling
• current sched.c is simple fifo scheduler
• Bounded number of pending tasks
• When idle, shuts down node except clock
• Uses non-blocking task queue data structure
2-9-2001 TOS Boot 2 16
Programming tools
2-9-2001 TOS Boot 2 17
TOS compile time tools
• tools/desc2objs– Generates the list of components that need to be compiled
into an application
– Generates “C” header files from .comp files
• tools/mkheader
• tools/mksuper_desc– Generates the super.h linkage file that wires components
together
• tools/mk_amdisp– Generates the mappings between handler ID’s and handler
function names for the AM_MSG macro
2-9-2001 TOS Boot 2 18
tools/mkheader
• Generates “C” header files from .comp files
• Usage:mkheader component_file
• Example: ./tools/mkheader APP.comp > APP.h
• Looks for ACCEPTS, USES, SIGNALS, HANDLES section of comp files.
2-9-2001 TOS Boot 2 19
tools/desc2objs
• Generates the list of components that need to be compiled into an application
• Walks the graph of description files to determine which components are used by the application
• Looks at .comp files for IMPLEMENTED_BY directives
• Usage:– Desc2objs description_file
• Example:– ./tools/desc2objs apps/cnt_to_leds.desc > Makefile.objs
• Output:CUST_OBJS = MAGS.o system/ADC.o system/AM.o system/CLOCK.o system/LEDS.o
system/MAIN.o system/PACKETOBJ.o system/RFM.o system/SEC_DED_RADIO_BYTE.oHEADER_FILES = MAGS.h system/ADC.h system/AM.h system/CLOCK.h system/LEDS.h
system/MAIN.h system/PACKETOBJ.h system/RFM.h system/SEC_DED_RADIO_BYTE.h
2-9-2001 TOS Boot 2 20
tools/mksuper_desc
• Generates the super.h linkage file that wires components together
• Walks the graph of description files to determine which components are used by the application
• Looks at .comp files for IMPLEMENTED_BY directives and types for each function.
• Automatically generates fan-out code based on number and types of connections to each net.
• Wires components together with #define.
• Usage: mksuper_desc description_file...
2-9-2001 TOS Boot 2 21
tools/mksuper_desc (cont.)
• Treats all of the wiring lines from all the description files together.
• Example Description file excerpt:GENERIC_COMM:COMM_SEND_MSG_COMMAND AM:AM_SEND_MSGCHIRP:CHIRP_SEND_MSG GENERIC_COMM:COMM_SEND_MSG
• Example Output:#define COMM_SEND_MSG_COMMAND AM_SEND_MSG_COMMAND#define CHIRP_SEND_MSG_COMMAND AM_SEND_MSG_COMMAND#define AM_MSG_HANDLER_4_EVENT INT_READING_EVENT
2-9-2001 TOS Boot 2 22
tools/mk_amdisp
• Generates the mappings between handler ID’s and handler function names for the AM_MSG macro
• Sends AM_DISPATCH.mapping through C preprocessor and determines the function names of the active message types that are being handled.
• Inserts macros that map from function name to handler number into am_dispatch.h
• Usage:mk_amdisp
• Output:#define INT_READING_EVENT__AM_DISPATCH 4 INT_READING_EVENT is handles message type 4.
2-9-2001 TOS Boot 2 23
All_headers.c
• Used to type check across all of the component descriptions.
• Compiled into a “.o” but not linked.
• Will reveal errors that arise from:– Wiring the wrong functions together
– Connecting incompatible components together
– Mistakes in .comp files
2-9-2001 TOS Boot 2 24
Listen and Inject
• tools/listen.* & tools/inject.*– Reads from the serial port and prints out packets to the
screen
• Linux uses .c or .java versions, Windows uses .java versions
• Listen reads in packets from the UART and prints them out.
• Inject sends out a single packet out the UART and then proceeds to print out data that is returned.
2-9-2001 TOS Boot 2 25
MakefilePC
• You can compile TinyOS code to run on a PC
• Used as a debugging tool
• Verify application logic and state machine transitions before running code on Mote
• Trust me, it’s worth taking the time to run it on the PC!!!
• Can even debug networking applications
2-9-2001 TOS Boot 2 26
Project: build a component
• Build a few nodes as sens_to_rfm to serve as data sources
• Build generic_base to forward all traffic it picks up to the host
• Using rfm_to_led as a starting point, construct a new application that will aggregate sensor readings and forward min,avg,max to the host– new AGGREGATE.comp and AGGREGATE.c
» int reading handler might build a table of neighbor values
» on change or tick, post task to compute aggregate and send new active message with aggregate
– new agg.desc