返回顶部

收藏

轻量线程环境 Protothreads 的示例代码

更多

cpp代码

#include "pt.h"

struct pt pt;
struct timer timer;

PT_THREAD(example(struct pt *pt))
{
  PT_BEGIN(pt);

  while(1) {
    if(initiate_io()) {
      timer_start(&timer);
      PT_WAIT_UNTIL(pt,
         io_completed() ||
         timer_expired(&timer));
      read_data();
    }
  }
  PT_END(pt);
}

通讯处理

#include "pt.h"

PT_THREAD(sender(struct pt *pt))
{
  PT_BEGIN(pt);  
  do {
    send_packet();
    /* Wait until an ackowledgement has been received, or until the
       timer expires. If the timer expires, we should send the packet
       again. */
    timer_set(&timer, TIMEOUT);
    PT_WAIT_UNTIL(pt, acknowledgment_received() ||
                      timer_expired(&timer));
  } while(timer_expired(&timer));  
  PT_END(pt);
}

PT_THREAD(receiver(struct pt *pt))
{
  PT_BEGIN(pt);
  /* Wait until a packet has been received, and send an
     acknowledgment. */
  PT_WAIT_UNTIL(pt, packet_received());
  send_acknowledgement();  
  PT_END(pt);
}

LCD文本滚动

#include "pt.h"
#include "timer.h"

struct state {
  char *text;
  char *scrollptr;
  struct pt pt;
  struct timer timer;
};

PT_THREAD(display_text(struct state *s))
{
  PT_BEGIN(&s->pt);

  /* If the text is shorter than the display size, show it right
     away. */
  if(strlen(s->text) <= LCD_SIZE) {
    lcd_display_text(s->text);
  } else {    
    /* If the text is longer than the display, we should scroll in the
       text from the right with a delay of one second per scroll
       step. We do this in a for() loop, where the loop variable is
       the pointer to the first character to be displayed. */
    for(s->scrollptr = s->text;
        strlen(s->scrollptr) > LCD_SIZE;
    ++s->scrollptr) {
      lcd_display_text(s->scrollptr);

      /* Wait for one second. */
      timer_set(&s->timer, ONE_SECOND);
      PT_WAIT_UNTIL(&s->pt, timer_expired(&s->timer));
    }
  }

  PT_END(&s->pt);
}

锁处理

/*
 * This is the code that has to be entered.
 */
static const char code[4] = {'1', '4', '2', '3'};

/*
 * Declaration of the protothread function implementing the code lock
 * logic. The protothread function is declared using the PT_THREAD()
 * macro. The function is declared with the "static" keyword since it
 * is local to this file. The name of the function is codelock_thread
 * and it takes one argument, pt, of the type struct pt.
 *
 */
static
PT_THREAD(codelock_thread(struct pt *pt))
{
  /* This is a local variable that holds the number of keys that have
   * been pressed. Note that it is declared with the "static" keyword
   * to make sure that the variable is *not* allocated on the stack.
   */
  static int keys;

  /*
   * Declare the beginning of the protothread.
   */
  PT_BEGIN(pt);

  /*
   * We'll let the protothread loop until the protothread is
   * expliticly exited with PT_EXIT().
   */
  while(1) {

    /*
     * We'll be reading key presses until we get the right amount of
     * correct keys.
     */ 
    for(keys = 0; keys < sizeof(code); ++keys) {

      /*
       * If we haven't gotten any keypresses, we'll simply wait for one.
       */
      if(keys == 0) {

    /*
     * The PT_WAIT_UNTIL() function will block until the condition
     * key_pressed() is true.
     */
    PT_WAIT_UNTIL(pt, key_pressed());
      } else {

    /*
     * If the "key" variable was larger than zero, we have already
     * gotten at least one correct key press. If so, we'll not
     * only wait for the next key, but we'll also set a timer that
     * expires in one second. This gives the person pressing the
     * keys one second to press the next key in the code.
     */
    timer_set(&codelock_timer, 1000);

    /*
     * The following statement shows how complex blocking
     * conditions can be easily expressed with protothreads and
     * the PT_WAIT_UNTIL() function.
     */
    PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));

    /*
     * If the timer expired, we should break out of the for() loop
     * and start reading keys from the beginning of the while(1)
     * loop instead.
     */
    if(timer_expired(&codelock_timer)) {
      printf("Code lock timer expired.\n");

      /*
       * Break out from the for() loop and start from the
       * beginning of the while(1) loop.
       */
      break;
    }
      }

      /*
       * Check if the pressed key was correct.
       */
      if(key != code[keys]) {
    printf("Incorrect key '%c' found\n", key);
    /*
     * Break out of the for() loop since the key was incorrect.
     */
    break;
      } else {
    printf("Correct key '%c' found\n", key);
      }
    }

    /*
     * Check if we have gotten all keys.
     */
    if(keys == sizeof(code)) {
      printf("Correct code entered, waiting for 500 ms before unlocking.\n");

      /*
       * Ok, we got the correct code. But to make sure that the code
       * was not just a fluke of luck by an intruder, but the correct
       * code entered by a person that knows the correct code, we'll
       * wait for half a second before opening the lock. If another
       * key is pressed during this time, we'll assume that it was a
       * fluke of luck that the correct code was entered the first
       * time.
       */
      timer_set(&codelock_timer, 500);      
      PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));

      /*
       * If we continued from the PT_WAIT_UNTIL() statement without
       * the timer expired, we don't open the lock.
       */
      if(!timer_expired(&codelock_timer)) {
    printf("Key pressed during final wait, code lock locked again.\n");
      } else {

    /*
     * If the timer expired, we'll open the lock and exit from the
     * protothread.
     */
    printf("Code lock unlocked.\n");
    PT_EXIT(pt);
      }
    }
  }

  /*
   * Finally, we'll mark the end of the protothread.
   */
  PT_END(pt);
}

信号量处理

#include "pt-sem.h"

#define NUM_ITEMS 32
#define BUFSIZE 8

static struct pt_sem full, empty;

static 
PT_THREAD(producer(struct pt *pt))
{
  static int produced;

  PT_BEGIN(pt);

  for(produced = 0; produced < NUM_ITEMS; ++produced) {

    PT_SEM_WAIT(pt, &full);

    add_to_buffer(produce_item());    

    PT_SEM_SIGNAL(pt, &empty);
  }

  PT_END(pt);
}

static 
PT_THREAD(consumer(struct pt *pt))
{
  static int consumed;

  PT_BEGIN(pt);

  for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {

    PT_SEM_WAIT(pt, &empty);

    consume_item(get_from_buffer());    

    PT_SEM_SIGNAL(pt, &full);
  }

  PT_END(pt);
}

static 
PT_THREAD(driver_thread(struct pt *pt))
{
  static struct pt pt_producer, pt_consumer;

  PT_BEGIN(pt);

  PT_SEM_INIT(&empty, 0);
  PT_SEM_INIT(&full, BUFSIZE);

  PT_INIT(&pt_producer);
  PT_INIT(&pt_consumer);

  PT_WAIT_THREAD(pt, producer(&pt_producer) &
             consumer(&pt_consumer));

  PT_END(pt);
}

标签:嵌入式,Protothreads

收藏

0人收藏

支持

0

反对

0