Difference between revisions of "Protothreads"

From emboxit
Jump to: navigation, search
 
m (1 revision)
 
(No difference)

Latest revision as of 16:51, 11 September 2015

To understand it

1. Turn radio on.
2. Wait for Tawake milliseconds.
3. Turn radio off, but only if all communication has completed.
4. If communication has not completed, wait until it has completed. Then turn off the radio.
5. Wait for Tsleep milliseconds. If the radio could not be turned off before Tsleep milliseconds 
     because of remaining communication, do not turn the radio off at all.
6. Repeat from step 1.


Pt events.PNG Pt protothreads.PNG Pt expanded.PNG
With the event-driven model, the programmer must explicitly design and implement a state machine. 
With protothreads, the state machine is automatically generated.


The non-obviousness of the C switch implementation of local continuations is that the technique appears to cause problems 
when a conditional blocking statement is used inside a nested C control statement.
For example, the case 13: statement in Figure 4 appears inside an if block, while the corresponding switch statement is located at a higher block.

*** However, this is a valid use of the C switch statement: case statements may be located anywhere inside a switch block. ***

They do not need to be in the same level of nesting, but can be located anywhere, even inside nested if or for blocks.
This use of the switch statement is likely to first have been publicly described by Du [2]. 
The same technique has later been used by Tatham to implement coroutines in C [13].


  • Protothreads: Simplifying event-driven programming of networked embedded tiny devices MuneebAli




Protothreads Home

What goes on behind the magical macros in the C protothreads library? Why are they macros? How do the macros work? Read on for the explanation.
In the C implementation of protothreads, all protothread operations are hidden behind C macros. 
The reason for building the protothread library on C macros rather than C functions is that protothreads alter the flow of control. 
This is typically difficult to do with C functions since such an implementation typically would require low-level assembly code to work. 
By implementing protothreads with macros, it is possible for them to alter the flow of control using only standard C constructs.

This page explains how protothreads work under the hood. 
We do this by taking a look at how the C preprocessor expands the protothread macros, and by looking at how the resulting C code is executed.

Download


Protothread Examples From third parties


An easy example for Arduino I have tested

  • protothread and arduino, a first easy example From blog: "build hardware and write code for it"
2011.09.13
Library downloaded and installed
to C:\Program Files\arduino-0022\libraries
removed files “example-buffer.c”, “example-codelock.c” and “example-small.c”
Code is compiled with no errors
My Version:
//NX 2011.09.13
//NX Modify to use 2 Leds  
//NX Each Protothread toggles different Led
//NX Third Led toggles in the main loop
//NX Works
//NX Each Protothread here is only a non blocking wait and Led toggle
//NX But protothread can  do much more (more waits, conditionals, change STATEs...)
//NX It is a clever and low-cost Thread

#include <pt.h>   // include protothread library

//#define LEDPIN 7  // LEDPIN is a constant 

static struct pt pt1, pt2; // each protothread needs one of these

void setup() {
  pinMode(7, OUTPUT); // LED init
  pinMode(6, OUTPUT); // LED init
  pinMode(5, OUTPUT); // LED init
  PT_INIT(&pt1);  // initialise the two
  PT_INIT(&pt2);  // protothread variables
}

void toggleLED(unsigned char pin_no) {
  boolean ledstate = digitalRead(pin_no); // get LED state
  ledstate ^= 1;   // toggle LED state using xor
  digitalWrite(pin_no, ledstate); // write inversed state back
}

/* This function toggles the LED after 'interval' ms passed */
static int protothread1(struct pt *pt, int interval) {
  static unsigned long timestamp = 0;
  PT_BEGIN(pt);
  while(1) { // never stop 
    /* each time the function is called the second boolean
    *  argument "millis() - timestamp > interval" is re-evaluated
    *  and if false the function exits after that. */
    PT_WAIT_UNTIL(pt, millis() - timestamp > interval );
    timestamp = millis(); // take a new timestamp
    toggleLED(7);
  }
  PT_END(pt);
}
/* exactly the same as the protothread1 function */
static int protothread2(struct pt *pt, int interval) {
  static unsigned long timestamp = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timestamp > interval );
    timestamp = millis();
    toggleLED(6);
  }
  PT_END(pt);
}

void loop() {
  protothread1(&pt1, 50);    // schedule the two protothreads
  protothread2(&pt2, 200);   // by calling them infinitely
  toggleLED(5);              // NX To measure the loop frequency: ~11.2 KHz ~100us                            
} 


I wrote a little example to demonstrate the possibilities of protothread and an avr µc. 
I decided to use some arduino specific functions like pinMode(), digitalWrite() and digitalRead() 
because i think this way it is very easy to understand what's happening in the code. 
But you should always keep in mind that these functions are up to 50 times slower than direct port access. 
It's easy to change the read and write functions to direct port access later on in a project if more I/O power is needed. 
For me arduino is a rapid prototyping platform.

What the code does, is that it toggles an LED every n ms using two independent protothreads for it. One pt toggles every 1000ms, the other one every 900ms. 
The result is an erratic blinking pattern. Download the protothread library and unpack it into your library directory, 
changing the name to 'pt' without version numbers. 
I had to delete the file 'example-buffer.c' in the 'pt' dir for some strange compiler reason, after that it compiled just fine.

PtArduino1.PNG





Dr. Dobb's

On the plus side, protothreads take no direct stack space, and require 2 or 4 bytes of overhead per thread. 
On the down side, they are cooperative only, threads lose their local variables and stack context when they block, and you can't use a switch statement inside of a thread.

Actually, library is a misnomer. The entire system is a clever use of C macros and unusual usage of C constructs like switch and while. 
Here is a simple protothread (lifted from one of the examples that ships with the library).:


bartjanssen

After downloading and unpacking, remove “example-buffer.c”, “example-codelock.c” and “example-small.c” from the unpacked directory.  
Then copy or move the pt-directory to “Arduino/Java/libraries” and rename it to “pt“.
Then in your Arduino Project include “pt.h” to make use of the library.


After installing protothreads 1.4 delete the example-*.c files from the directory or protothreads will not work!

Download the working example .pde file for Arduino (0022) .


Vijay Kumar

Mon, 28 Mar 2011
I did a lightning talk on Protothreads at the ChennaiPy user group meeting last week. This post contains the code examples demonstrated during the talk.

The code was written to show how Protothreads work, but it is not the best way to implement Protothreads. 
For one, the examples use 100% of the CPU, because the scheduler does not block. For a more complete implementation, check the source code of the Kiwi project.