verification of tinyos device drivers using abstract...

Post on 28-Feb-2021

3 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Verification of TinyOS Device Drivers usingAbstract Interpretation

Abdelraouf Ouadjaout Antoine Miné

APR, LIP6, Sorbonne Université

Airbus-LIP6 MeetingFebruary 20th, 2019

Paris, France

1 / 18

Part I

Context

2 / 18

Wireless Sensor Networks

ATmega128 MCU with128KB of program flashand 4KB of SRAM.

CC2420 wireless transceivercompliant with 2.4 GHzIEEE 802.15.4 with250kbps data rate.

3 / 18

Software ArchitectureTinyOS

TinyOS is an open sourceOS developed by Berkely.Mixture of preemptive andcooperative executionmodels.

1 Preemption uses interrupts to avoid active polling and saveenergy.

2 Cooperation uses tasks to avoid monopolizing execution bybreaking it into parts.

4 / 18

Software ArchitectureTinyOS

TinyOS is an open sourceOS developed by Berkely.Mixture of preemptive andcooperative executionmodels.

1 Preemption uses interrupts to avoid active polling and saveenergy.

2 Cooperation uses tasks to avoid monopolizing execution bybreaking it into parts.

4 / 18

Software ArchitectureTinyOS

TinyOS is an open sourceOS developed by Berkely.Mixture of preemptive andcooperative executionmodels.

1 Preemption uses interrupts to avoid active polling and saveenergy.

2 Cooperation uses tasks to avoid monopolizing execution bybreaking it into parts.

4 / 18

Hello World!

1 #defne MAX_READINGS 102 int data[ MAX_READINGS ];3 int idx = 0;45 void main () {6 // Configure timer Timer07 TIMSK = (1 << TOIE0 );89 // Infinite loop

10 while (1) {11 sei ();12 asm volatile ("sleep"::);13 consume_tasks ();14 }15 }

16 ISR( TIMER0_OVF_vect ) {17 // Postpone processing18 post sense ();19 reti ();20 }

21 task void sense () {22 // Do actual work23 warmup_sensor ();24 if (id >= MAX_READINGS ) idx = 0;25 data[idx] = read_sensor ();26 idx ++;27 }

5 / 18

Hello World!

1 #defne MAX_READINGS 102 int data[ MAX_READINGS ];3 int idx = 0;45 void main () {6 // Configure timer Timer07 TIMSK = (1 << TOIE0 );89 // Infinite loop

10 while (1) {11 sei ();12 asm volatile ("sleep"::);13 consume_tasks ();14 }15 }

16 ISR( TIMER0_OVF_vect ) {17 // Postpone processing18 post sense ();19 reti ();20 }

21 task void sense () {22 // Do actual work23 warmup_sensor ();24 if (id >= MAX_READINGS ) idx = 0;25 data[idx] = read_sensor ();26 idx ++;27 }

UNSAFE!

5 / 18

Specifications

ATmega128

Datasheet, pp. 107

Safety Rule

If Timer/Counter0 is used to wake the device up[...], the interrupt logic needs one TOSC1 cycleto be reset. If the time between wake-up and re-entering sleep mode is less than one TOSC1 cycle,the interrupt will not occur, and the device will failto wake up.

Safe Pattern

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

6 / 18

Specifications

ATmega128

Datasheet, pp. 107

Safety Rule

If Timer/Counter0 is used to wake the device up[...], the interrupt logic needs one TOSC1 cycleto be reset. If the time between wake-up and re-entering sleep mode is less than one TOSC1 cycle,the interrupt will not occur, and the device will failto wake up.

Safe Pattern

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

6 / 18

Specifications

ATmega128

Datasheet, pp. 107

Safety Rule

If Timer/Counter0 is used to wake the device up[...], the interrupt logic needs one TOSC1 cycleto be reset. If the time between wake-up and re-entering sleep mode is less than one TOSC1 cycle,the interrupt will not occur, and the device will failto wake up.

Safe Pattern

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

6 / 18

Contributions

We propose an analysis based on abstract interpretation that:Allows developers expressing such functional properties easily.We use an automata-based formalism that is tailored to thesemantics of low-level software/hardware interactions.Supports the cooperative and preemptive execution models ofTinyOS.We manage interrupts masks, tasks queuing and scheduling .Covers all possible concurrent executions.We support software concurrency (due to interrupt preemption), aswell as hardware concurrency (asynchronous device operations).

7 / 18

Contributions

We propose an analysis based on abstract interpretation that:Allows developers expressing such functional properties easily.We use an automata-based formalism that is tailored to thesemantics of low-level software/hardware interactions.Supports the cooperative and preemptive execution models ofTinyOS.We manage interrupts masks, tasks queuing and scheduling .Covers all possible concurrent executions.We support software concurrency (due to interrupt preemption), aswell as hardware concurrency (asynchronous device operations).

7 / 18

Contributions

We propose an analysis based on abstract interpretation that:Allows developers expressing such functional properties easily.We use an automata-based formalism that is tailored to thesemantics of low-level software/hardware interactions.Supports the cooperative and preemptive execution models ofTinyOS.We manage interrupts masks, tasks queuing and scheduling .Covers all possible concurrent executions.We support software concurrency (due to interrupt preemption), aswell as hardware concurrency (asynchronous device operations).

7 / 18

Part II

Concrete Semantics

8 / 18

Abstract Device Properties

An abstract device property is a special register automatondescribing patterns of hardware interactions:

A = (S, s0, sBUG,R, ξ, T )

where:S set of statess0 initial statesBUG bug stateR set of hardware registersξ = {X� | X ∈ R, � ∈ {r ,w}} ∪ {inti | i ∈ I} ∪ {α, sleep}T ⊆ S × ξ × S × StmtC × StmtC

A Be:Xw

g:X & (1<<I)a:Y |= (1<<J);

9 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

ADP Example

ATmega128

Datasheet, pp. 107

Rule

If Timer/Counter0 is used to wake the device up[...], precautions must be taken [...]

1 Write a value to TCCR0, TCNT0, or OCR0.2 Wait until the corresponding Update Busy

flag in ASSR returns to zero.3 Enter Power-save or Extended Standby

mode.

STABLE

SLEEP

e:sleep

UNSTBLe:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUG

e:sleep

e:sleep

10 / 18

Concrete Environments

E = (CV∪R → V)1

× S2× T ?

3

1 Value store of C variables and registersBased on the Cell memory model of Astrée

2 State of the abstract device propertyRegisters are considered as C variables

3 Queue of posted tasksFinite sequence of pointers to functions without parameters

11 / 18

Part III

Abstract Semantics

12 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥

x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.

Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥

x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥

x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.

Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥

x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥

x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.

Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥

x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥

x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.

Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥

x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥

x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.

Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥

x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥

x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥

x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥

x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Interrupt-Modular Analysis

uint8_t x = 0;void main () {

EIMSK = (1 << INT0 );sei ();x++;

}

ISR( INT0_vect ) {x++;reti ();

}

ISR( INT1_vect ) {x--;reti ();

}

⊥, ⊥ ⊥, ⊥x 7→ [0, 0] ⊥, ⊥ ⊥, ⊥x 7→ [0, 0] x 7→ [0, 0], ⊥ ⊥, ⊥x 7→ [1, 1] x 7→ [0, 1], ⊥ ⊥, ⊥x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 0] x 7→ [0, 1], x 7→ [1, 2] ⊥, ⊥x 7→ [0, 2] x 7→ [0, 2], x 7→ [1, 2] ⊥, ⊥

x 7→ [1, 3] x 7→ [0, 3], x 7→ [1, 2] ⊥, ⊥

Scalability IssuePrecise analysis of preemption is too expensive!

Idea

Each interrupt vector is summarized as an input/output pair.Update the input summary of each enabled interrupt.Analyze each interrupt routine independently.Inject the output summary into the current environments.

13 / 18

Abstract Domain

State Partitioning Abstraction

Separate environments with different hardware states.Abstract memory with a cell abstraction C].Keep the set of posted tasks.

D]S = S →(C] × ℘(T )

)

Interrupt-Modular Abstraction

Abstract reachable environments with D].Keep a map from interrupts I to summaries D] ×D].

D]I|S = D]S × I →(D]S ×D

]S

)14 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥

main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥

main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBL

e:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleep

e:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

UNSAFE!

--- a/hello.c+++ b/hello .c

-9,6 +9 ,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0 ;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

Analysis of Hello World

1 int idx = 0;2 ...3 void main () {4 TIMSK = (1 << T0OVF );5 while (1) {6 sei ();7 asm volatile ("sleep"::);8 consume_tasks ();9 }10 }

11 ISR( TIMER0_OVF_vect ) {12 post sense ();13 reti ();14 }

15 task void sense () {16 ...17 idx ++;18 }

STABLE

SLEEP

e:sleepe:sleep

UNSTBLe:int15|16

e:int15|16

BUSY

e:TCCR0w

a:ASSR|=(1<<TCR0UB)

e:αa:ASSR&=~(1<<TCR0UB)

BUGe:sleep

e:sleep

e:sleep

--- a/hello.c+++ b/hello.c

-9,6 +9,8 void main () {}

}ISR( TIMER0_OVF_vect ) {

+ TCCR0 = TCCR0;+ while (ASSR & (1 << TCR0UB ));

post sense ();reti ();

}

Line State ISR input ISR output

main:5STABLEidx 7→ [0, 0]∅

⊥ ⊥main:7STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

⊥main:8 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:12 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

⊥isr:13 ⊥STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:5STABLEidx 7→ [0, 0]∅

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:7STABLEidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

UNSTBLidx 7→ [0, 0]{sense}

main:8UNSTBLidx 7→ [0, 0]{sense}

STABLEidx 7→ [0, 0]∅

SLEEPidx 7→ [0, 0]∅

BUGidx 7→ [0, 0]{sense}

UNSTBLidx 7→ [0, 0]{sense}

15 / 18

ExperimentsImplementation

Prototype implementation called Sada (Static Analysis withDevice Abstraction).Done in OCaml (∼ 4000 lines of code).Using CIL and Apron.Seven ADPs were analyzed related to three devices:

1 Wireless transceiver CC2420.2 Analog switch ADG715.3 ATmega128 timer.

Two driver implementations for each device: TinyOS 1.x and2.x.

Very different design and algorithms.Same property can be used.

16 / 18

ExperimentsResults

Time (s) × {4, 8,©8 }

Driver LoC |I| |T | ADP |S| D]I|S D]I|Q|S

CC2420 1.x 2666 1 1 ASPI-SS 4 12 4 850 4

ASPI-TX 10 21 4 1600 4

CC2420 2.x 10133 2 10 ASPI-SS 4 ∞ 34 4

ASPI-TX 10 ∞ 39 4

ADG715 1.x 2038 1 1 APULL-UP 4 1 8 1 8

ATWI-TX 6 4 4 7 4

ADG715 2.x 4412 1 6 APULL-UP 4 23 4 8 4

ATWI-TX 6 40 8 6 8

Timer 1.x 1627 1 3ASTBL 7 6 ©8 39 ©8AOCR0 4 3 ©8 29 ©8ATCCR0 4 3 4 37 4

Timer 2.x 2384 2 2ASTBL 4 7 4 26 4

AOCR0 4 10 4 38 4

ATCCR0 4 10 ©8 23 ©8

17 / 18

ExperimentsResults

Time (s) × {4, 8,©8 }

Driver LoC |I| |T | ADP |S| D]I|S D]I|Q|S

CC2420 1.x 2666 1 1 ASPI-SS 4 12 4 850 4

ASPI-TX 10 21 4 1600 4

CC2420 2.x 10133 2 10 ASPI-SS 4 ∞ 34 4

ASPI-TX 10 ∞ 39 4

ADG715 1.x 2038 1 1 APULL-UP 4 1 8 1 8

ATWI-TX 6 4 4 7 4

ADG715 2.x 4412 1 6 APULL-UP 4 23 4 8 4

ATWI-TX 6 40 8 6 8

Timer 1.x 1627 1 3ASTBL 7 6 ©8 39 ©8AOCR0 4 3 ©8 29 ©8ATCCR0 4 3 4 37 4

Timer 2.x 2384 2 2ASTBL 4 7 4 26 4

AOCR0 4 10 4 38 4

ATCCR0 4 10 ©8 23 ©8

17 / 18

ExperimentsResults

Time (s) × {4, 8,©8 }

Driver LoC |I| |T | ADP |S| D]I|S D]I|Q|S

CC2420 1.x 2666 1 1 ASPI-SS 4 12 4 850 4

ASPI-TX 10 21 4 1600 4

CC2420 2.x 10133 2 10 ASPI-SS 4 ∞ 34 4

ASPI-TX 10 ∞ 39 4

ADG715 1.x 2038 1 1 APULL-UP 4 1 8 1 8

ATWI-TX 6 4 4 7 4

ADG715 2.x 4412 1 6 APULL-UP 4 23 4 8 4

ATWI-TX 6 40 8 6 8

Timer 1.x 1627 1 3ASTBL 7 6 ©8 39 ©8AOCR0 4 3 ©8 29 ©8ATCCR0 4 3 4 37 4

Timer 2.x 2384 2 2ASTBL 4 7 4 26 4

AOCR0 4 10 4 38 4

ATCCR0 4 10 ©8 23 ©8

17 / 18

ExperimentsResults

Time (s) × {4, 8,©8 }

Driver LoC |I| |T | ADP |S| D]I|S D]I|Q|S

CC2420 1.x 2666 1 1 ASPI-SS 4 12 4 850 4

ASPI-TX 10 21 4 1600 4

CC2420 2.x 10133 2 10 ASPI-SS 4 ∞ 34 4

ASPI-TX 10 ∞ 39 4

ADG715 1.x 2038 1 1 APULL-UP 4 1 8 1 8

ATWI-TX 6 4 4 7 4

ADG715 2.x 4412 1 6 APULL-UP 4 23 4 8 4

ATWI-TX 6 40 8 6 8

Timer 1.x 1627 1 3ASTBL 7 6 ©8 39 ©8AOCR0 4 3 ©8 29 ©8ATCCR0 4 3 4 37 4

Timer 2.x 2384 2 2ASTBL 4 7 4 26 4

AOCR0 4 10 4 38 4

ATCCR0 4 10 ©8 23 ©8

17 / 18

ConclusionSummary, Limitations & Future Work

Device Drivers Verification: Sada

3 Certify the correctness of hardware interactions in devicedrivers.

3 Support both preemptive and cooperative execution models.7 Limited to the tasks system of TinyOS.

+ Consider other systems such as protothreads of Contiki.7 Asynchronous operations are modeled with non-determinisim.

+ Develop specific abstract domains for timing specifications.

18 / 18

top related