Esempio n. 1
0
/*---------------------------------------------------------------------------*/
static void
init(void)
{
    radio_is_on = 0;
    waiting_for_packet = 0;
    PT_INIT(&pt);
    rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1,
               (void (*)(struct rtimer *, void *))powercycle, NULL);

    xmac_is_on = 1;

#if WITH_ENCOUNTER_OPTIMIZATION
    list_init(encounter_list);
    memb_init(&encounter_memb);
#endif /* WITH_ENCOUNTER_OPTIMIZATION */

#if XMAC_CONF_ANNOUNCEMENTS
    announcement_register_listen_callback(listen_callback);
    ctimer_set(&announcement_cycle_ctimer, ANNOUNCEMENT_TIME,
               cycle_announcement, NULL);
#endif /* XMAC_CONF_ANNOUNCEMENTS */
}
Esempio n. 2
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_time_process, ev, data)
{
  struct {
    uint16_t len;
    uint16_t clock;
    uint16_t rtimer;
    uint16_t timesynch;
    uint16_t timesynch_authority;
    uint16_t time[2];
  } msg;
  unsigned long newtime;
  const char *nextptr;
  
  PROCESS_BEGIN();

  if(data != NULL) {
    newtime = shell_strtolong(data, &nextptr);
    if(data != nextptr) {
      shell_set_time(newtime);
    }
  }
  
  msg.clock = (uint16_t)clock_time();
  msg.rtimer = (uint16_t)RTIMER_NOW();
#if TIMESYNCH_CONF_ENABLED
  msg.timesynch = timesynch_time();
  msg.timesynch_authority = timesynch_authority_level();
#else
  msg.timesynch = 0;
  msg.timesynch_authority = -1;
#endif
  msg.time[0] = (uint16_t)(shell_time() >> 16);
  msg.time[1] = (uint16_t)(shell_time());
  msg.len = 6;

  shell_output(&time_command, &msg, sizeof(msg), "", 0);

  PROCESS_END();
}
Esempio n. 3
0
/**
 * \brief Schedules an rtimer task to be triggered at time t
 * \param t The time when the task will need executed. This is an absolute
 *          time, in other words the task will be executed AT time \e t,
 *          not IN \e t ticks
 */
void
rtimer_arch_schedule(rtimer_clock_t t)
{
  rtimer_clock_t now;
  uint32_t primask = __get_PRIMASK();

  __set_PRIMASK(1);

  now = RTIMER_NOW();

  /*
   * New value must be a few ticks in the future.
   */
  if((int32_t)(t - now) < 20) {
    t = now + 20;
  }

  LPC_RITIMER->COMPVAL = t;

   __set_PRIMASK(primask);

  NVIC_EnableIRQ(RIT_IRQn);
}
Esempio n. 4
0
/*---------------------------------------------------------------------------*/
const struct mac_driver *
xmac_init(const struct radio_driver *d)
{
#if WITH_TIMETABLE
  timetable_clear(&xmac_timetable);
#endif
  radio_is_on = 0;
  waiting_for_packet = 0;
  PT_INIT(&pt);
  rtimer_set(&rt, RTIMER_NOW() + xmac_config.off_time, 1,
	     TC(powercycle), NULL);

  xmac_is_on = 1;
  radio = d;
  radio->set_receive_function(input_packet);

  BB_SET("xmac.state_addr", (int) &waiting_for_packet);
  BB_SET(XMAC_RECEIVER, 0);
  BB_SET(XMAC_STROBES, 0);
  BB_SET(XMAC_SEND_WITH_ACK, 0);
  BB_SET(XMAC_SEND_WITH_NOACK, 0);
  return &xmac_driver;
}
Esempio n. 5
0
/*---------------------------------------------------------------------------*/
static void advanceSlot(struct rtimer *t, void *ptr, int status) {
    off(TURN_OFF);
    last = RTIMER_TIME(t);
    if(!(rtimer_set(t, last + REGULAR_SLOT, 1, (void (*)(struct rtimer *, void *))advanceSlot, NULL) == RTIMER_OK)) {
        printf("%s\n", "WPI-MAC: Could not schedule task!!!!!");
    }
    if(current_slot == TOTAL_SLOTS + 1) {
        current_slot = BROADCAST_SLOT;
    } else {
        current_slot++;
    }
    if(current_slot > (TOTAL_SLOTS - 1)) {
        current_slot = BROADCAST_SLOT;
    }
    //printf("Slot is now %u\n", current_slot);

    unsigned char somethingToSend = check_buffers(current_slot);

    if(somethingToSend) {
        // grab the necessary info from our queue
        QueuedPacket *curr = QPQueue[current_slot];
        real_send(curr->sent, curr->ptr, curr->packet);
    } else if(current_slot == BROADCAST_SLOT || current_slot == node_id) { // just need to be awake to listen
        // if(!(rtimer_set(t, last + CONTENTION_PREPARE + (CONTENTION_TICKS * (CONTENTION_SLOTS)), 1, (void (*)(struct rtimer *, void *))async_on, NULL) == RTIMER_OK)){
        //   printf("%s\n", "Could not schedule task!!!!!");
        // }
        rtimer_clock_t stall = last + CONTENTION_PREPARE + (CONTENTION_TICKS * (CONTENTION_SLOTS));
        // printf("STALLLLL: %u %u %u %u\n", RTIMER_NOW(), stall, REGULAR_SLOT, last);
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), stall));
        if(!radio_is_on) on();
    } else {
        // we can snooze
        if(radio_is_on) off(TURN_OFF);

    }

}
Esempio n. 6
0
/*---------------------------------------------------------------------------*/
void
lpm_exit()
{
  if((REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3) == SYS_CTRL_PMCTL_PM0) {
    /* We either just exited PM0 or we were not sleeping in the first place.
     * We don't need to do anything clever */
    return;
  }

  /*
   * When returning from PM1/2, the sleep timer value (used by RTIMER_NOW()) is
   * not up-to-date until a positive edge on the 32-kHz clock has been detected
   * after the system clock restarted. To ensure an updated value is read, wait
   * for a positive transition on the 32-kHz clock by polling the
   * SYS_CTRL_CLOCK_STA.SYNC_32K bit, before reading the sleep timer value.
   */
  while(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K);
  while(!(REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYNC_32K));

  LPM_STATS_ADD(REG(SYS_CTRL_PMCTL) & SYS_CTRL_PMCTL_PM3,
                RTIMER_NOW() - sleep_enter_time);

  /* Adjust the system clock, since it was not counting while we were sleeping
   * We need to convert sleep duration from rtimer ticks to clock ticks */
  clock_adjust();

  /* Restore system clock to the 32 MHz XOSC */
  select_32_mhz_xosc();

  /* Restore PMCTL to PM0 for next pass */
  REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0;

  /* Remember IRQ energest for next pass */
  ENERGEST_IRQ_SAVE(irq_energest);

  ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
}
PROCESS_THREAD(cc26xx_demo_process, ev, data)
{
  PROCESS_EXITHANDLER(broadcast_close(&bc))

  PROCESS_BEGIN();

  gpio_relay_init();
  relay_all_clear();
  
  
  counter = 0;
  broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx);

  etimer_set(&et, CLOCK_SECOND);
  
  while(1) {

    PROCESS_YIELD();

    if(ev == PROCESS_EVENT_TIMER) {
      leds_on(LEDS_PERIODIC);
     
      etimer_set(&et, CLOCK_SECOND*5);
      rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1,
                 rt_callback, NULL);
      counter = Get_ADC_reading();
      packetbuf_copyfrom(&counter, sizeof(counter));
      broadcast_send(&bc);
     // printf("adc data value : %d \r\n",counter);
        
    } 
     watchdog_periodic();
  }

  PROCESS_END();
}
Esempio n. 8
0
/*---------------------------------------------------------------------------*/
static char
powercycle(struct rtimer *t, void *ptr)
{
#if SYNC_CYCLE_STARTS
  static volatile rtimer_clock_t sync_cycle_start;
  static volatile uint8_t sync_cycle_phase;
#endif

  PT_BEGIN(&pt);

#if SYNC_CYCLE_STARTS
  sync_cycle_start = RTIMER_NOW();
#else
  cycle_start = RTIMER_NOW();
#endif

  while(1) {
    static uint8_t packet_seen;
    static rtimer_clock_t t0;
    static uint8_t count;

#if SYNC_CYCLE_STARTS
    /* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
       of CHANNEL_CHECK_RATE */
    if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
      sync_cycle_phase = 0;
      sync_cycle_start += RTIMER_ARCH_SECOND;
      cycle_start = sync_cycle_start;
    } else {
#if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
      cycle_start = sync_cycle_start + ((unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#else
      cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#endif
    }
#else
    cycle_start += CYCLE_TIME;
#endif

    packet_seen = 0;

    for(count = 0; count < CCA_COUNT_MAX; ++count) {
      t0 = RTIMER_NOW();
      if(we_are_sending == 0 && we_are_receiving_burst == 0) {
        powercycle_turn_radio_on();
        /* Check if a packet is seen in the air. If so, we keep the
             radio on for a while (LISTEN_TIME_AFTER_PACKET_DETECTED) to
             be able to receive the packet. We also continuously check
             the radio medium to make sure that we wasn't woken up by a
             false positive: a spurious radio interference that was not
             caused by an incoming packet. */
        if(NETSTACK_RADIO.channel_clear() == 0) {
          packet_seen = 1;
          break;
        }
        powercycle_turn_radio_off();
      }
      schedule_powercycle_fixed(t, RTIMER_NOW() + CCA_SLEEP_TIME);
      PT_YIELD(&pt);
    }

    if(packet_seen) {
      static rtimer_clock_t start;
      static uint8_t silence_periods, periods;
      start = RTIMER_NOW();

      periods = silence_periods = 0;
      while(we_are_sending == 0 && radio_is_on &&
            RTIMER_CLOCK_LT(RTIMER_NOW(),
                            (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {

        /* Check for a number of consecutive periods of
             non-activity. If we see two such periods, we turn the
             radio off. Also, if a packet has been successfully
             received (as indicated by the
             NETSTACK_RADIO.pending_packet() function), we stop
             snooping. */
#if !RDC_CONF_HARDWARE_CSMA
       /* A cca cycle will disrupt rx on some radios, e.g. mc1322x, rf230 */
       /*TODO: Modify those drivers to just return the internal RSSI when already in rx mode */
        if(NETSTACK_RADIO.channel_clear()) {
          ++silence_periods;
        } else {
          silence_periods = 0;
        }
#endif

        ++periods;

        if(NETSTACK_RADIO.receiving_packet()) {
          silence_periods = 0;
        }
        if(silence_periods > MAX_SILENCE_PERIODS) {
          powercycle_turn_radio_off();
          break;
        }
        if(WITH_FAST_SLEEP &&
            periods > MAX_NONACTIVITY_PERIODS &&
            !(NETSTACK_RADIO.receiving_packet() ||
              NETSTACK_RADIO.pending_packet())) {
          powercycle_turn_radio_off();
          break;
        }
        if(NETSTACK_RADIO.pending_packet()) {
          break;
        }

        schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
        PT_YIELD(&pt);
      }
      if(radio_is_on) {
        if(!(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet()) ||
             !RTIMER_CLOCK_LT(RTIMER_NOW(),
                 (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
          powercycle_turn_radio_off();
        }
      }
    }

    if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
      /* Schedule the next powercycle interrupt, or sleep the mcu
	 until then.  Sleeping will not exit from this interrupt, so
	 ensure an occasional wake cycle or foreground processing will
	 be blocked until a packet is detected */
#if RDC_CONF_MCU_SLEEP
      static uint8_t sleepcycle;
      if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
        rtimer_arch_sleep(CYCLE_TIME - (RTIMER_NOW() - cycle_start));
      } else {
        sleepcycle = 0;
        schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
        PT_YIELD(&pt);
      }
#else
      schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
      PT_YIELD(&pt);
#endif
    }
  }

  PT_END(&pt);
}
Esempio n. 9
0
PROCESS_THREAD(hello_world_process, ev, data)
{
  PROCESS_BEGIN();
        //microSD Test
		uint8_t obuffer[514];
		uint8_t ibuffer[514];
		uint16_t j, i;
  		uint32_t start, end;
		//printf("\nChecksum is: %x", microSD_data_crc( buffer ));
		//wdt_disable();
		init:
		printf("\nmicroSD_init() = %u\n", i = microSD_init());
		if( i != 0 )
			goto init;
		printf("Size of uint64_t  = %u\n", sizeof(uint64_t));
		printf("Size of uint32_t  = %u\n", sizeof(uint32_t));
		printf("Size of uint16_t  = %u\n", sizeof(uint16_t));
		printf("Size of int  = %u\n", sizeof(int));
/*		for (j = 0; j < 512; j+=4) {
				obuffer[j] = 'H';
				obuffer[j + 1] = 'e';
				obuffer[j + 2] = 'r';
				obuffer[j + 3] = '\n';

		}*/
		//clock_init();
		//printf("\nmicroSD_set_CRC() = %u", microSD_set_CRC(1));
		//start = clock_time();
		/*for( j = 500; j < 8192; j++ ) {
			printf("\n%u", j);
			retry_write:
			if( microSD_write_block(0L + j, obuffer) != 0 ) {
				printf("\n Error writing block %lu", 0L + j);
				//goto retry_write;
			}
			watchdog_periodic();
			retry_read:
			if( microSD_read_block(0L+j, ibuffer) != 0) {
				goto retry_read;
			}
			watchdog_periodic();
			for (i = 0; i < 512; i+=4) {
				watchdog_periodic();
					if( ibuffer[i] != 'H' || ibuffer[i + 1] != 'e' || ibuffer[i + 2] != 'r' || ibuffer[i + 3] != '\n' ) {
						printf("\n Error in block %u", j);
						for(i = 0; i< 512; i++) {
							if( i%2 == 0 ) {
								printf(" ");
							}
							if( i%32 == 0){
								printf("\n");
							}
							printf("%02x", ibuffer[i]);
						}
						break;
					}
			}
			printf("\nChecksum is       : %x", ( (uint16_t)ibuffer[512] << 8 ) + ibuffer[513]);
			printf("\nChecksum should be: %x", microSD_data_crc( ibuffer ));
		}*/
		rtimer_arch_init();
		start = RTIMER_NOW();
		for( j = 0; j < 30; j++ ) {
			microSD_write_block( j, obuffer );
		}
		end = RTIMER_NOW();
		printf("\nWrite time = %lu (%lu)", end - start, (end - start) / 30);
		rtimer_arch_init();
		start = RTIMER_NOW();
		for( j = 0; j < 30; j++ ) {
			if( microSD_read_block( j, obuffer ) != 0 ) {
				printf("\n Block %u read error", j);
				microSD_init();
				j--;
				continue;
			}
		}
		end = RTIMER_NOW();
		printf("\nRead time = %lu (%lu)", end - start, (end - start) / 30);
		printf("\nSecond = %lu", RTIMER_SECOND);
		printf("\n");
		//if( microSD_write_block(38000L + j, buffer) != 0 ) {
		//	printf("\n Error writing block %lu", 38000L + j);
		//}

		//end = clock_time();
		//printf("\nTime = %lu", (end - start) );
		//printf("\nSecond = %lu", CLOCK_SECOND );
/*
		for (i = 0; i < 8192; i++) {
			if( (j = microSD_read_block(0L+i, buffer)) != 0 ) {
				printf("\nmicroSD_read_block() failed with %u", j);
			}
			for (j = 0; j < 512; j+=4) {
					if( buffer[j] != 'f' ||	buffer[j + 1] != 'e' ||	buffer[j + 2] != 'r' || buffer[j + 3] != '\n' ) {
						printf("\n Error in block %u", i);
						break;
					}
			}
		}
*/
		microSD_switchoff();
                
  PROCESS_END();
}
Esempio n. 10
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ccm_test_process, ev, data)
{
  static const char *const str_res[] = {
    "success",
    "invalid param",
    "NULL error",
    "resource in use",
    "DMA bus error",
    "keystore read error",
    "keystore write error",
    "authentication failed"
  };
  static const uint8_t keys128[][128 / 8] = {
    { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
      0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }
  };
  static const uint8_t keys192[][192 / 8] = {
    { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c,
      0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e,
      0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86 },
    { 0x08, 0x6e, 0x29, 0x67, 0xcd, 0xe9, 0x9e, 0x90,
      0xfa, 0xae, 0xa8, 0xa9, 0x4e, 0x16, 0x8b, 0xf0,
      0xe0, 0x66, 0xc5, 0x03, 0xa8, 0x49, 0xa9, 0xf3 },
    { 0xce, 0xb0, 0x09, 0xae, 0xa4, 0x45, 0x44, 0x51,
      0xfe, 0xad, 0xf0, 0xe6, 0xb3, 0x6f, 0x45, 0x55,
      0x5d, 0xd0, 0x47, 0x23, 0xba, 0xa4, 0x48, 0xe8 },
    { 0x11, 0xfd, 0x45, 0x74, 0x3d, 0x94, 0x6e, 0x6d,
      0x37, 0x34, 0x1f, 0xec, 0x49, 0x94, 0x7e, 0x8c,
      0x70, 0x48, 0x24, 0x94, 0xa8, 0xf0, 0x7f, 0xcc }
  };
  static const uint8_t keys256[][256 / 8] = {
    { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c,
      0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e,
      0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86,
      0xdf, 0x3b, 0xa3, 0xe6, 0xda, 0x3a, 0x13, 0x89 },
    { 0xc6, 0xc1, 0x4c, 0x65, 0x5e, 0x52, 0xc8, 0xa4,
      0xc7, 0xe8, 0xd5, 0x4e, 0x97, 0x4d, 0x69, 0x8e,
      0x1f, 0x21, 0xee, 0x3b, 0xa7, 0x17, 0xa0, 0xad,
      0xfa, 0x61, 0x36, 0xd0, 0x26, 0x68, 0xc4, 0x76 },
    { 0x55, 0x35, 0x21, 0xa7, 0x65, 0xab, 0x0c, 0x3f,
      0xd2, 0x03, 0x65, 0x4e, 0x99, 0x16, 0x33, 0x0e,
      0x18, 0x9b, 0xdf, 0x95, 0x1f, 0xee, 0xe9, 0xb4,
      0x4b, 0x10, 0xda, 0x20, 0x8f, 0xee, 0x7a, 0xcf },
    { 0x90, 0x74, 0xb1, 0xae, 0x4c, 0xa3, 0x34, 0x2f,
      0xe5, 0xbf, 0x6f, 0x14, 0xbc, 0xf2, 0xf2, 0x79,
      0x04, 0xf0, 0xb1, 0x51, 0x79, 0xd9, 0x5a, 0x65,
      0x4f, 0x61, 0xe6, 0x99, 0x69, 0x2e, 0x6f, 0x71 }
  };
  static const struct {
    const void *keys;
    uint8_t key_size;
    uint8_t count;
  } keys[] = {
    { keys128, AES_KEY_STORE_SIZE_KEY_SIZE_128,
      sizeof(keys128) / sizeof(keys128[0]) },
    { keys192, AES_KEY_STORE_SIZE_KEY_SIZE_192,
      sizeof(keys192) / sizeof(keys192[0]) },
    { keys256, AES_KEY_STORE_SIZE_KEY_SIZE_256,
      sizeof(keys256) / sizeof(keys256[0]) }
  };
  static const struct {
    bool encrypt;
    uint8_t len_len;
    uint8_t key_size_index;
    uint8_t key_area;
    uint8_t nonce[NONCE_MAX_LEN];
    uint8_t adata[ADATA_MAX_LEN];
    uint16_t adata_len;
    uint8_t mdata[MDATA_MAX_LEN];
    uint16_t mdata_len;
    uint8_t mic_len;
    uint8_t expected[MDATA_MAX_LEN];
  } vectors[] = {
    {
      true, /* encrypt */
      2, /* len_len */
      0, /* key_size_index */
      0, /* key_area */
      { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
        0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
        0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */
      20, /* mdata_len */
      0, /* mic_len */
      { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0,
        0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6,
        0x2c, 0x61, 0x01, 0x4e } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      0, /* key_size_index */
      1, /* key_area */
      { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */
      { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00,
        0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52,
        0x53, 0x54 }, /* adata */
      26, /* adata_len */
      {}, /* mdata */
      0, /* mdata_len */
      8, /* mic_len */
      { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      0, /* key_size_index */
      0, /* key_area */
      { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
        0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
      { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01,
        0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */
      15, /* adata_len */
      { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
        0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */
      20, /* mdata_len */
      4, /* mic_len */
      { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0,
        0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6,
        0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      0, /* key_size_index */
      0, /* key_area */
      { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
        0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0,
        0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6,
        0x2c, 0x61, 0x01, 0x4e }, /* mdata */
      20, /* mdata_len */
      0, /* mic_len */
      { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
        0x0c, 0x0d, 0x0e, 0x0f } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      0, /* key_size_index */
      1, /* key_area */
      { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */
      { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00,
        0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52,
        0x53, 0x54 }, /* adata */
      26, /* adata_len */
      { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 }, /* mdata */
      8, /* mdata_len */
      8, /* mic_len */
      {} /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      0, /* key_size_index */
      0, /* key_area */
      { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0,
        0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */
      { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01,
        0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */
      15, /* adata_len */
      { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0,
        0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6,
        0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 }, /* mdata */
      24, /* mdata_len */
      4, /* mic_len */
      { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03,
        0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
        0x0c, 0x0d, 0x0e, 0x0f } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      1, /* key_size_index */
      0, /* key_area */
      { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde,
        0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62,
        0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57,
        0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 }, /* mdata */
      24, /* mdata_len */
      16, /* mic_len */
      { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a,
        0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44,
        0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06,
        0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83,
        0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      1, /* key_size_index */
      2, /* key_area */
      { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab,
        0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */
      { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13,
        0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b,
        0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00,
        0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */
      32, /* adata_len */
      {}, /* mdata */
      0, /* mdata_len */
      16, /* mic_len */
      { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a,
        0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 } /* expected */
    }, {
      true, /* encrypt */
      8, /* len_len */
      1, /* key_size_index */
      4, /* key_area */
      { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */
      { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1,
        0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7,
        0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5,
        0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */
      32, /* adata_len */
      { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f,
        0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe,
        0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 }, /* mdata */
      24, /* mdata_len */
      16, /* mic_len */
      { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74,
        0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8,
        0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd,
        0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7,
        0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      1, /* key_size_index */
      6, /* key_area */
      { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa,
        0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */
      { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65,
        0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae,
        0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e,
        0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */
      32, /* adata_len */
      { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d,
        0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff,
        0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 }, /* mdata */
      24, /* mdata_len */
      4, /* mic_len */
      { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf,
        0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76,
        0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf,
        0x1f, 0x2c, 0x5b, 0xad } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      1, /* key_size_index */
      0, /* key_area */
      { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde,
        0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a,
        0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44,
        0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06,
        0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83,
        0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed }, /* mdata */
      40, /* mdata_len */
      16, /* mic_len */
      { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62,
        0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57,
        0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      1, /* key_size_index */
      2, /* key_area */
      { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab,
        0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */
      { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13,
        0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b,
        0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00,
        0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */
      32, /* adata_len */
      { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a,
        0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 }, /* mdata */
      16, /* mdata_len */
      16, /* mic_len */
      {} /* expected */
    }, {
      false, /* decrypt */
      8, /* len_len */
      1, /* key_size_index */
      4, /* key_area */
      { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */
      { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1,
        0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7,
        0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5,
        0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */
      32, /* adata_len */
      { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74,
        0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8,
        0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd,
        0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7,
        0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d }, /* mdata */
      40, /* mdata_len */
      16, /* mic_len */
      { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f,
        0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe,
        0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      1, /* key_size_index */
      6, /* key_area */
      { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa,
        0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */
      { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65,
        0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae,
        0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e,
        0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */
      32, /* adata_len */
      { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf,
        0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76,
        0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf,
        0x1f, 0x2c, 0x5b, 0xad }, /* mdata */
      28, /* mdata_len */
      4, /* mic_len */
      { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d,
        0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff,
        0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      2, /* key_size_index */
      0, /* key_area */
      { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb,
        0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe,
        0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4,
        0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 }, /* mdata */
      24, /* mdata_len */
      16, /* mic_len */
      { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59,
        0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f,
        0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e,
        0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4,
        0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      2, /* key_size_index */
      2, /* key_area */
      { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd,
        0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */
      { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95,
        0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6,
        0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35,
        0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */
      32, /* adata_len */
      {}, /* mdata */
      0, /* mdata_len */
      16, /* mic_len */
      { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46,
        0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e } /* expected */
    }, {
      true, /* encrypt */
      8, /* len_len */
      2, /* key_size_index */
      4, /* key_area */
      { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */
      { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f,
        0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85,
        0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf,
        0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */
      32, /* adata_len */
      { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43,
        0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1,
        0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c }, /* mdata */
      24, /* mdata_len */
      16, /* mic_len */
      { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8,
        0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46,
        0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15,
        0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e,
        0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 } /* expected */
    }, {
      true, /* encrypt */
      2, /* len_len */
      2, /* key_size_index */
      6, /* key_area */
      { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4,
        0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */
      { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb,
        0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82,
        0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3,
        0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */
      32, /* adata_len */
      { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6,
        0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4,
        0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 }, /* mdata */
      24, /* mdata_len */
      4, /* mic_len */
      { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81,
        0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0,
        0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74,
        0x3c, 0xb9, 0xaf, 0xed } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      2, /* key_size_index */
      0, /* key_area */
      { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb,
        0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */
      {}, /* adata */
      0, /* adata_len */
      { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59,
        0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f,
        0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e,
        0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4,
        0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 }, /* mdata */
      40, /* mdata_len */
      16, /* mic_len */
      { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe,
        0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4,
        0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      2, /* key_size_index */
      2, /* key_area */
      { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd,
        0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */
      { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95,
        0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6,
        0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35,
        0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */
      32, /* adata_len */
      { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46,
        0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e }, /* mdata */
      16, /* mdata_len */
      16, /* mic_len */
      {} /* expected */
    }, {
      false, /* decrypt */
      8, /* len_len */
      2, /* key_size_index */
      4, /* key_area */
      { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */
      { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f,
        0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85,
        0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf,
        0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */
      32, /* adata_len */
      { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8,
        0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46,
        0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15,
        0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e,
        0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 }, /* mdata */
      40, /* mdata_len */
      16, /* mic_len */
      { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43,
        0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1,
        0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c } /* expected */
    }, {
      false, /* decrypt */
      2, /* len_len */
      2, /* key_size_index */
      6, /* key_area */
      { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4,
        0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */
      { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb,
        0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82,
        0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3,
        0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */
      32, /* adata_len */
      { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81,
        0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0,
        0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74,
        0x3c, 0xb9, 0xaf, 0xed }, /* mdata */
      28, /* mdata_len */
      4, /* mic_len */
      { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6,
        0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4,
        0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 } /* expected */
    }
  };
  static uint8_t adata[ADATA_MAX_LEN];
  static uint8_t mdata[MDATA_MAX_LEN];
  static uint8_t mic[MIC_MAX_LEN];
  static int i;
  static uint8_t key_size_index = -1, ret;
  static rtimer_clock_t time, time2, total_time;

  PROCESS_BEGIN();

  puts("-----------------------------------------\n"
       "Initializing cryptoprocessor...");
  crypto_init();

  for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) {
    if(key_size_index != vectors[i].key_size_index) {
      key_size_index = vectors[i].key_size_index;
      printf("-----------------------------------------\n"
             "Filling %d-bit key store...\n", 128 + (key_size_index << 6));
      time = RTIMER_NOW();
      ret = aes_load_keys(keys[key_size_index].keys,
              keys[key_size_index].key_size, keys[key_size_index].count, 0);
      time = RTIMER_NOW() - time;
      printf("aes_load_keys(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      PROCESS_PAUSE();
      if(ret != CRYPTO_SUCCESS) {
        break;
      }
    }

    printf("-----------------------------------------\n"
           "Test vector #%d: %s\n"
           "len_len=%d key_area=%d\n"
           "adata_len=%d mdata_len=%d mic_len=%d\n",
           i, vectors[i].encrypt ? "encrypt" : "decrypt",
           vectors[i].len_len, vectors[i].key_area,
           vectors[i].adata_len, vectors[i].mdata_len, vectors[i].mic_len);

    /* adata and mdata have to be in SRAM. */
    rom_util_memcpy(adata, vectors[i].adata, vectors[i].adata_len);
    rom_util_memcpy(mdata, vectors[i].mdata, vectors[i].mdata_len);

    time = RTIMER_NOW();
    if(vectors[i].encrypt) {
      ret = ccm_auth_encrypt_start(vectors[i].len_len, vectors[i].key_area,
                                   vectors[i].nonce, adata,
                                   vectors[i].adata_len, mdata,
                                   vectors[i].mdata_len, mdata,
                                   vectors[i].mic_len, &ccm_test_process);
      time2 = RTIMER_NOW();
      time = time2 - time;
      total_time = time;
      if(ret == CRYPTO_SUCCESS) {
        PROCESS_WAIT_EVENT_UNTIL(ccm_auth_encrypt_check_status());
        time2 = RTIMER_NOW() - time2;
        total_time += time2;
      }
      printf("ccm_auth_encrypt_start(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      if(ret != CRYPTO_SUCCESS) {
        PROCESS_PAUSE();
        continue;
      }
      printf("ccm_auth_encrypt_check_status() wait: %lu us\n",
             (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND));

      time = RTIMER_NOW();
      ret = ccm_auth_encrypt_get_result(mic, vectors[i].mic_len);
      time = RTIMER_NOW() - time;
      total_time += time;
      printf("ccm_auth_encrypt_get_result(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      PROCESS_PAUSE();
      if(ret != CRYPTO_SUCCESS) {
        continue;
      }

      if(rom_util_memcmp(mdata, vectors[i].expected, vectors[i].mdata_len)) {
        puts("Encrypted message does not match expected one");
      } else {
        puts("Encrypted message OK");
      }

      if(rom_util_memcmp(mic, vectors[i].expected + vectors[i].mdata_len,
                         vectors[i].mic_len)) {
        puts("MIC does not match expected one");
      } else {
        puts("MIC OK");
      }
    } else {
      ret = ccm_auth_decrypt_start(vectors[i].len_len, vectors[i].key_area,
                                   vectors[i].nonce, adata,
                                   vectors[i].adata_len, mdata,
                                   vectors[i].mdata_len, mdata,
                                   vectors[i].mic_len, &ccm_test_process);
      time2 = RTIMER_NOW();
      time = time2 - time;
      total_time = time;
      if(ret == CRYPTO_SUCCESS) {
        PROCESS_WAIT_EVENT_UNTIL(ccm_auth_decrypt_check_status());
        time2 = RTIMER_NOW() - time2;
        total_time += time2;
      }
      printf("ccm_auth_decrypt_start(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      if(ret != CRYPTO_SUCCESS) {
        PROCESS_PAUSE();
        continue;
      }
      printf("ccm_auth_decrypt_check_status() wait: %lu us\n",
             (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND));

      time = RTIMER_NOW();
      ret = ccm_auth_decrypt_get_result(mdata, vectors[i].mdata_len,
                                        mic, vectors[i].mic_len);
      time = RTIMER_NOW() - time;
      total_time += time;
      printf("ccm_auth_decrypt_get_result(): %s, %lu us\n", str_res[ret],
             (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND));
      PROCESS_PAUSE();
      if(ret != CRYPTO_SUCCESS) {
        continue;
      }

      if(rom_util_memcmp(mdata, vectors[i].expected,
                         vectors[i].mdata_len - vectors[i].mic_len)) {
        puts("Decrypted message does not match expected one");
      } else {
        puts("Decrypted message OK");
      }
    }

    printf("Total duration: %lu us\n",
           (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND));
  }

  puts("-----------------------------------------\n"
       "Disabling cryptoprocessor...");
  crypto_disable();

  puts("Done!");

  PROCESS_END();
}
Esempio n. 11
0
/*---------------------------------Main Routine----------------------------*/
int
main(void)
{
  /* GCC depends on register r1 set to 0 (?) */
  asm volatile ("clr r1");
  
  /* Initialize in a subroutine to maximize stack space */
  initialize();

#if DEBUG
{struct process *p;
 for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) {
  PRINTA("Process=%p Thread=%p  Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p));
 }
}
#endif

  while(1) {
    process_run();

    watchdog_periodic();

/* Print rssi of all received packets, useful for range testing */
#ifdef RF230_MIN_RX_POWER
    uint8_t lastprint;
    if (rf230_last_rssi != lastprint) {        //can be set in halbb.c interrupt routine
        PRINTA("%u ",rf230_last_rssi);
        lastprint=rf230_last_rssi;
    }
#endif

#if 0
/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver.
 * This can show when that happens.
 */
    extern uint8_t rf230_calibrated;
    if (rf230_calibrated) {
      PRINTA("\nRF230 calibrated!\n");
      rf230_calibrated=0;
    }
#endif

#if TESTRTIMER
/* Timeout can be increased up to 8 seconds maximum.
 * A one second cycle is convenient for triggering the various debug printouts.
 * The triggers are staggered to avoid printing everything at once.
 * My Jackdaw is 4% slow.
 */
    if (rtimerflag) {
      rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
      rtimerflag=0;

#if STAMPS
if ((rtime%STAMPS)==0) {
  PRINTA("%us ",rtime);
  if (rtime%STAMPS*10) PRINTA("\n");
}
#endif
      rtime+=1;

#if PINGS && UIP_CONF_IPV6_RPL
extern void raven_ping6(void);
if ((rtime%PINGS)==1) {
  PRINTA("**Ping\n");
  raven_ping6();
}
#endif

#if ROUTES && UIP_CONF_IPV6_RPL
if ((rtime%ROUTES)==2) {

extern uip_ds6_netif_t uip_ds6_if;

  uint8_t i,j;
  uip_ds6_nbr_t *nbr;

  PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
  for (i=0;i<UIP_DS6_ADDR_NB;i++) {
    if (uip_ds6_if.addr_list[i].isused) {
      uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
      PRINTA("\n");
    }
  }
  PRINTA("\nNeighbors [%u max]\n",NBR_TABLE_MAX_NEIGHBORS);

  for(nbr = nbr_table_head(ds6_neighbors);
      nbr != NULL;
      nbr = nbr_table_next(ds6_neighbors, nbr)) {
    uip_debug_ipaddr_print(&nbr->ipaddr);
    PRINTA("\n");
    j=0;
  }
  if (j) PRINTA("  <none>");
  PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
  uip_ds6_route_t *r;
  for(r = uip_ds6_route_head();
      r != NULL;
      r = uip_ds6_route_next(r)) {
    if(r->isused) {
      uip_debug_ipaddr_print(&r->ipaddr);
      PRINTA("/%u (via ", r->length);
      uip_debug_ipaddr_print(uip_ds6_route_nexthop(r));
 //     if(r->state.lifetime < 600) {
        PRINTA(") %lus\n", r->state.lifetime);
 //     } else {
 //       PRINTA(")\n");
 //     }
      j=0;
    }
  }
  if (j) PRINTA("  <none>");
  PRINTA("\n---------\n");
}
#endif

#if STACKMONITOR && CONFIG_STACK_MONITOR
if ((rtime%STACKMONITOR)==3) {
  extern uint16_t __bss_end;
  uint16_t p=(uint16_t)&__bss_end;
  do {
    if (*(uint16_t *)p != 0x4242) {
      PRINTA("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end);
      break;
    }
    p+=100;
  } while (p<RAMEND-10);
}
#endif

    }
#endif /* TESTRTIMER */

//Use with RF230BB DEBUGFLOW to show path through driver
#if RF230BB&&0
extern uint8_t debugflowsize,debugflow[];  //in rf230bb.c
  if (debugflowsize) {
    debugflow[debugflowsize]=0;
    PRINTA("%s",debugflow);
    debugflowsize=0;
   }
#endif

  }
  return 0;
}
Esempio n. 12
0
/*---------------------------------------------------------------------------*/
static int
transmit(unsigned short transmit_len)
{
  uint8_t counter;
  int ret = RADIO_TX_ERR;
  rtimer_clock_t t0;
  transmit_len; /* hush the warning */

  if(!(rf_flags & RX_ACTIVE)) {
    t0 = RTIMER_NOW();
    on();
    rf_flags |= WAS_OFF;
    while (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
  }

  if(channel_clear() == CC2530_RF_CCA_BUSY) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /*
   * prepare() double checked that TX_ACTIVE is low. If SFD is high we are
   * receiving. Abort transmission and bail out with RADIO_TX_COLLISION
   */
  if(FSMSTAT1 & FSMSTAT1_SFD) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /* Start the transmission */
  RF_TX_LED_ON();
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

  CC2530_CSP_ISTXON();

  counter = 0;
  while(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE) && (counter++ < 3)) {
    clock_delay_usec(6);
  }

  if(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE)) {
    PUTSTRING("RF: TX never active.\n");
    CC2530_CSP_ISFLUSHTX();
    ret = RADIO_TX_ERR;
  } else {
    /* Wait for the transmission to finish */
    while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE);
    ret = RADIO_TX_OK;
  }
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

  if(rf_flags & WAS_OFF){
    off();
  }

  RIMESTATS_ADD(lltx);

  RF_TX_LED_OFF();

  /* OK, sent. We are now ready to send more */
  return ret;
}
Esempio n. 13
0
/*---------------------------------------------------------------------------*/
static int
transmit(unsigned short transmit_len)
{
  uint8_t counter;
  int ret = RADIO_TX_ERR;
  rtimer_clock_t t0;
  uint8_t was_off = 0;

  PRINTF("RF: Transmit\n");

  if(!(rf_flags & RX_ACTIVE)) {
    t0 = RTIMER_NOW();
    on();
    was_off = 1;
    while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
  }

  if(channel_clear() == CC2538_RF_CCA_BUSY) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /*
   * prepare() double checked that TX_ACTIVE is low. If SFD is high we are
   * receiving. Abort transmission and bail out with RADIO_TX_COLLISION
   */
  if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_SFD) {
    RIMESTATS_ADD(contentiondrop);
    return RADIO_TX_COLLISION;
  }

  /* Start the transmission */
  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);

  CC2538_RF_CSP_ISTXON();

  counter = 0;
  while(!((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE))
        && (counter++ < 3)) {
    clock_delay_usec(6);
  }

  if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) {
    PRINTF("RF: TX never active.\n");
    CC2538_RF_CSP_ISFLUSHTX();
    ret = RADIO_TX_ERR;
  } else {
    /* Wait for the transmission to finish */
    while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
    ret = RADIO_TX_OK;
  }
  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
  ENERGEST_ON(ENERGEST_TYPE_LISTEN);

  if(was_off) {
    off();
  }

  RIMESTATS_ADD(lltx);

  return ret;
}
/**
 * \brief Returns a reading from the sensor
 * \param type MPU_9250_SENSOR_TYPE_ACC_[XYZ] or MPU_9250_SENSOR_TYPE_GYRO_[XYZ]
 * \return centi-G (ACC) or centi-Deg/Sec (Gyro)
 */
static int
value(int type)
{
  int rv;
  float converted_val = 0;

  if(state == SENSOR_STATE_DISABLED) {
    PRINTF("MPU: Sensor Disabled\n");
    return CC26XX_SENSOR_READING_ERROR;
  }

  memset(sensor_value, 0, sizeof(sensor_value));

  if((type & MPU_9250_SENSOR_TYPE_ACC) != 0) {
    t0 = RTIMER_NOW();

    while(!int_status() &&
          (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + READING_WAIT_TIMEOUT)));

    rv = acc_read(sensor_value);

    if(rv == 0) {
      return CC26XX_SENSOR_READING_ERROR;
    }

    PRINTF("MPU: ACC = 0x%04x 0x%04x 0x%04x = ",
           sensor_value[0], sensor_value[1], sensor_value[2]);

    /* Convert */
    if(type == MPU_9250_SENSOR_TYPE_ACC_X) {
      converted_val = acc_convert(sensor_value[0]);
    } else if(type == MPU_9250_SENSOR_TYPE_ACC_Y) {
      converted_val = acc_convert(sensor_value[1]);
    } else if(type == MPU_9250_SENSOR_TYPE_ACC_Z) {
      converted_val = acc_convert(sensor_value[2]);
    }
    rv = (int)(converted_val * 100);
  } else if((type & MPU_9250_SENSOR_TYPE_GYRO) != 0) {
    t0 = RTIMER_NOW();

    while(!int_status() &&
          (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + READING_WAIT_TIMEOUT)));

    rv = gyro_read(sensor_value);

    if(rv == 0) {
      return CC26XX_SENSOR_READING_ERROR;
    }

    PRINTF("MPU: Gyro = 0x%04x 0x%04x 0x%04x = ",
           sensor_value[0], sensor_value[1], sensor_value[2]);

    if(type == MPU_9250_SENSOR_TYPE_GYRO_X) {
      converted_val = gyro_convert(sensor_value[0]);
    } else if(type == MPU_9250_SENSOR_TYPE_GYRO_Y) {
      converted_val = gyro_convert(sensor_value[1]);
    } else if(type == MPU_9250_SENSOR_TYPE_GYRO_Z) {
      converted_val = gyro_convert(sensor_value[2]);
    }
    rv = (int)(converted_val * 100);
  } else {
    PRINTF("MPU: Invalid type\n");
    rv = CC26XX_SENSOR_READING_ERROR;
  }

  PRINTF("%ld\n", (long int)(converted_val * 100));

  return rv;
}
Esempio n. 15
0
File: lpm.c Progetto: gnkarn/Contiki
/*---------------------------------------------------------------------------*/
void
lpm_drop()
{
  lpm_registered_module_t *module;
  uint8_t max_pm = LPM_MODE_MAX_SUPPORTED;
  uint8_t module_pm;
  clock_time_t next_event;

  uint32_t domains = LOCKABLE_DOMAINS;

  if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(),
                     RTIMER_NOW() + STANDBY_MIN_DURATION)) {
    lpm_sleep();
    return;
  }

  /* Collect max allowed PM permission from interested modules */
  for(module = list_head(modules_list); module != NULL;
      module = module->next) {
    if(module->request_max_pm) {
      module_pm = module->request_max_pm();
      if(module_pm < max_pm) {
        max_pm = module_pm;
      }
    }
  }

  /* Check if any events fired during this process. Last chance to abort */
  if(process_nevents()) {
    return;
  }

  /* Drop */
  if(max_pm == LPM_MODE_SLEEP) {
    lpm_sleep();
  } else {
    /* Critical. Don't get interrupted! */
    ti_lib_int_master_disable();

    /*
     * Reschedule AON RTC CH1 to fire an event N ticks before the next etimer
     * event
     */
    next_event = etimer_next_expiration_time();

    if(next_event) {
      next_event = next_event - clock_time();
      soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() +
          (next_event * (RTIMER_SECOND / CLOCK_SECOND)));
    }

    /*
     * Notify all registered modules that we are dropping to mode X. We do not
     * need to do this for simple sleep.
     *
     * This is a chance for modules to delay us a little bit until an ongoing
     * operation has finished (e.g. uart TX) or to configure themselves for
     * deep sleep.
     *
     * At this stage, we also collect power domain locks, if any.
     * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time
     * we encounter a lock we just clear the respective bits in the 'domains'
     * variable as required by the lock. In the end the domains variable will
     * just hold whatever has not been cleared
     */
    for(module = list_head(modules_list); module != NULL;
        module = module->next) {
      if(module->shutdown) {
        module->shutdown(max_pm);
      }

      /* Clear the bits specified in the lock */
      domains &= ~module->domain_lock;
    }

    /* Pat the dog: We don't want it to shout right after we wake up */
    watchdog_periodic();

    /* Clear unacceptable bits, just in case a lock provided a bad value */
    domains &= LOCKABLE_DOMAINS;

    /*
     * Freeze the IOs on the boundary between MCU and AON. We only do this if
     * PERIPH is not needed
     */
    if(domains & PRCM_DOMAIN_PERIPH) {
      ti_lib_aon_ioc_freeze_enable();
    }

    /*
     * Among LOCKABLE_DOMAINS, turn off those that are not locked
     *
     * If domains is != 0, pass it as-is
     */
    if(domains) {
      ti_lib_prcm_power_domain_off(domains);
    }

    /*
     * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC
     * is predominantly controlled by the RF driver. In a build with radio
     * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before
     * using the Freq. Synth, and switch back to the RC when it is about to
     * turn back off.
     *
     * If the radio is on, we won't even reach here, and if it's off the HF
     * clock source should already be the HF RC.
     *
     * Nevertheless, request the switch to the HF RC explicitly here.
     */
    oscillators_switch_to_hf_rc();

    /* Configure clock sources for MCU and AUX: No clock */
    ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK);
    ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK);

    /* Full RAM retention. */
    ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION |
                                   MCU_RAM2_RETENTION | MCU_RAM3_RETENTION);

    /* Disable retention of AUX RAM */
    ti_lib_aon_wuc_aux_sram_config(false);

    /*
     * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off
     * already
     */
    ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU |
                                 PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS);

    /* Request JTAG domain power off */
    ti_lib_aon_wuc_jtag_power_off();

    /* Turn off AUX */
    ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF);
    ti_lib_aon_wuc_domain_power_down_enable();
    while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON);

    /* Configure the recharge controller */
    ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE);

    /*
     * If both PERIPH and SERIAL PDs are off, request the uLDO as the power
     * source while in deep sleep.
     */
    if(domains == LOCKABLE_DOMAINS) {
      ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO);
    }

    /* We are only interested in IRQ energest while idle or in LPM */
    ENERGEST_IRQ_RESTORE(irq_energest);
    ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);

    /* Sync the AON interface to ensure all writes have gone through. */
    ti_lib_sys_ctrl_aon_sync();

    /*
     * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of
     * retention mismatch between VIMS logic and cache. We wait to do this
     * until right before deep sleep to be able to use the cache for as long
     * as possible.
     */
    ti_lib_prcm_cache_retention_disable();
    ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF);

    /* Deep Sleep */
    ti_lib_prcm_deep_sleep();

    /*
     * When we reach here, some interrupt woke us up. The global interrupt
     * flag is off, hence we have a chance to run things here. We will wake up
     * the chip properly, and then we will enable the global interrupt without
     * unpending events so the handlers can fire
     */
    wake_up();

    ti_lib_int_master_enable();
  }
}
Esempio n. 16
0
/*---------------------------------------------------------------------------*/
rtimer_clock_t
timesynch_time(void)
{
  return RTIMER_NOW() + offset;
}
Esempio n. 17
0
/*---------------------------------------------------------------------------*/
static int
send_packet(void)
{
  rtimer_clock_t t0;
  rtimer_clock_t t;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  int ret;
#if 0
  struct xmac_hdr *hdr;
#endif
  uint8_t got_strobe_ack = 0;
  uint8_t got_ack = 0;
  uint8_t strobe[MAX_STROBE_SIZE];
  int strobe_len, len;
  int is_broadcast = 0;
/*int is_reliable; */
  struct encounter *e;
  struct queuebuf *packet;
  int is_already_streaming = 0;
  uint8_t collisions;

  /* Create the X-MAC header for the data packet. */
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    is_broadcast = 1;
    PRINTDEBUG("xmac: send broadcast\n");
  } else {
#if UIP_CONF_IPV6
    PRINTDEBUG("xmac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else
    PRINTDEBUG("xmac: send unicast to %u.%u\n",
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
  }
/*  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE); */

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
  len = NETSTACK_FRAMER.create();
  strobe_len = len + sizeof(struct xmac_hdr);
  if(len < 0 || strobe_len > (int)sizeof(strobe)) {
    /* Failed to send */
   PRINTF("xmac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  memcpy(strobe, packetbuf_hdrptr(), len);
  strobe[len] = DISPATCH; /* dispatch */
  strobe[len + 1] = TYPE_STROBE; /* type */

  packetbuf_compact();
  packet = queuebuf_new_from_packetbuf();
  if(packet == NULL) {
    /* No buffer available */
    PRINTF("xmac: send failed, no queue buffer available (of %u)\n",
           QUEUEBUF_CONF_NUM);
    return MAC_TX_ERR;
  }

#if WITH_STREAMING
  if(is_streaming == 1 &&
     (rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   &is_streaming_to) ||
      rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   &is_streaming_to_too))) {
    is_already_streaming = 1;
  }
  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
     PACKETBUF_ATTR_PACKET_TYPE_STREAM) {
    is_streaming = 1;
    if(rimeaddr_cmp(&is_streaming_to, &rimeaddr_null)) {
      rimeaddr_copy(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    } else if(!rimeaddr_cmp(&is_streaming_to, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
      rimeaddr_copy(&is_streaming_to_too, packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
    }
    stream_until = RTIMER_NOW() + DEFAULT_STREAM_TIME;
  }
#endif /* WITH_STREAMING */

  off();

#if WITH_ENCOUNTER_OPTIMIZATION
  /* We go through the list of encounters to find if we have recorded
     an encounter with this particular neighbor. If so, we can compute
     the time for the next expected encounter and setup a ctimer to
     switch on the radio just before the encounter. */
  for(e = list_head(encounter_list); e != NULL; e = list_item_next(e)) {
    const rimeaddr_t *neighbor = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);

    if(rimeaddr_cmp(neighbor, &e->neighbor)) {
      rtimer_clock_t wait, now, expected;

      /* We expect encounters to happen every DEFAULT_PERIOD time
	 units. The next expected encounter is at time e->time +
	 DEFAULT_PERIOD. To compute a relative offset, we subtract
	 with clock_time(). Because we are only interested in turning
	 on the radio within the DEFAULT_PERIOD period, we compute the
	 waiting time with modulo DEFAULT_PERIOD. */

      now = RTIMER_NOW();
      wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD);
      if(wait < 2 * DEFAULT_ON_TIME) {
        wait = DEFAULT_PERIOD;
      }
      expected = now + wait - 2 * DEFAULT_ON_TIME;

#if WITH_ACK_OPTIMIZATION
      /* Wait until the receiver is expected to be awake */
      if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) !=
	 PACKETBUF_ATTR_PACKET_TYPE_ACK &&
	 is_streaming == 0) {
	/* Do not wait if we are sending an ACK, because then the
	   receiver will already be awake. */
	while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
      }
#else /* WITH_ACK_OPTIMIZATION */
      /* Wait until the receiver is expected to be awake */
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), expected));
#endif /* WITH_ACK_OPTIMIZATION */
    }
  }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */

  /* By setting we_are_sending to one, we ensure that the rtimer
     powercycle interrupt do not interfere with us sending the packet. */
  we_are_sending = 1;
  
  t0 = RTIMER_NOW();
  strobes = 0;

  LEDS_ON(LEDS_BLUE);

  /* Send a train of strobes until the receiver answers with an ACK. */

  /* Turn on the radio to listen for the strobe ACK. */
  //  on();
  collisions = 0;
  if(!is_already_streaming) {
    watchdog_stop();
    got_strobe_ack = 0;
    t = RTIMER_NOW();
    for(strobes = 0, collisions = 0;
	got_strobe_ack == 0 && collisions == 0 &&
	  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);
	strobes++) {

      while(got_strobe_ack == 0 &&
	    RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
#if 0
	rtimer_clock_t now = RTIMER_NOW();

	/* See if we got an ACK */
	packetbuf_clear();
	len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
	if(len > 0) {
	  packetbuf_set_datalen(len);
	  if(NETSTACK_FRAMER.parse() >= 0) {
	    hdr = packetbuf_dataptr();
	    if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE_ACK) {
	      if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
			      &rimeaddr_node_addr)) {
		/* We got an ACK from the receiver, so we can immediately send
		   the packet. */
		got_strobe_ack = 1;
		encounter_time = now;
	      } else {
		PRINTDEBUG("xmac: strobe ack for someone else\n");
	      }
	    } else /*if(hdr->dispatch == DISPATCH && hdr->type == TYPE_STROBE)*/ {
	      PRINTDEBUG("xmac: strobe from someone else\n");
	      collisions++;
	    }
	  } else {
	    PRINTF("xmac: send failed to parse %u\n", len);
	  }
	}
#endif /* 0 */
      }
      
      t = RTIMER_NOW();
            /* Send the strobe packet. */
      if(got_strobe_ack == 0 && collisions == 0) {

	if(is_broadcast) {
#if WITH_STROBE_BROADCAST
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#else
	  /* restore the packet to send */
	  queuebuf_to_packetbuf(packet);
	  ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
#endif
          off();
	} else {
#if 0
	  rtimer_clock_t wt;
#endif
          on();
	  ret = NETSTACK_RADIO.send(strobe, strobe_len);
#if 0
	  /* Turn off the radio for a while to let the other side
	     respond. We don't need to keep our radio on when we know
	     that the other side needs some time to produce a reply. */
	  off();
	  wt = RTIMER_NOW();
	  while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + WAIT_TIME_BEFORE_STROBE_ACK));
#endif /* 0 */
#if RDC_CONF_HARDWARE_ACK
          if(ret == RADIO_TX_OK) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#else
          if(detect_ack()) {
            got_strobe_ack = 1;
          } else {
            off();
          }
#endif /* RDC_CONF_HARDWARE_ACK */

        }
      }
    }
  }

#if WITH_ACK_OPTIMIZATION
  /* If we have received the strobe ACK, and we are sending a packet
     that will need an upper layer ACK (as signified by the
     PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */
  if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
			packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) ||
			packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
			PACKETBUF_ATTR_PACKET_TYPE_STREAM)) {
    on(); /* Wait for ACK packet */
    waiting_for_packet = 1;
  } else {
    off();
  }
#endif /* WITH_ACK_OPTIMIZATION */

  /* restore the packet to send */
  queuebuf_to_packetbuf(packet);
  queuebuf_free(packet);

  /* Send the data packet. */
  if((is_broadcast || got_strobe_ack || is_streaming) && collisions == 0) {
    ret = NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());

    if(!is_broadcast) {
#if RDC_CONF_HARDWARE_ACK
      if(ret == RADIO_TX_OK) {
        got_ack = 1;
      }
#else
      if(detect_ack()) {
        got_ack = 1;
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }
  off();

#if WITH_ENCOUNTER_OPTIMIZATION
  if(got_strobe_ack && !is_streaming) {
    register_encounter(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time);
  }
#endif /* WITH_ENCOUNTER_OPTIMIZATION */
  watchdog_start();

  PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
	 packetbuf_totlen(), got_strobe_ack ? "ack" : "no ack");

#if XMAC_CONF_COMPOWER
  /* Accumulate the power consumption for the packet transmission. */
  compower_accumulate(&current_packet);

  /* Convert the accumulated power consumption for the transmitted
     packet to packet attributes so that the higher levels can keep
     track of the amount of energy spent on transmitting the
     packet. */
  compower_attrconv(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_packet);
#endif /* XMAC_CONF_COMPOWER */

  we_are_sending = 0;

  LEDS_OFF(LEDS_BLUE);
  if(collisions == 0) {
    if(is_broadcast == 0 && got_ack == 0) {
      return MAC_TX_NOACK;
    } else {
      return MAC_TX_OK;
    }
  } else {
    someone_is_sending++;
    return MAC_TX_COLLISION;
  }

}
Esempio n. 18
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(aestest, ev, data)
{
    static int i, j;
    unsigned long start, end;
    static struct etimer periodic_timer;

    PROCESS_BEGIN();

    printf("#Fixed AES-128 implementation test for %s.\n", TARGET_NAME);
#ifndef AES_128_CONF
    printf("#Using Contiki software implementation.\n");
#else
    printf("#Using Hardware coprocessor.\n");
#endif
    printf("#Rounds in each sample: %d\n", NROUND);
    printf("#Sample size: %d\n", NSAMPLE);
    printf("#Rtimer clock ticks per second on this platform is : %lu\n",
           (unsigned long) RTIMER_SECOND);
    printf("#datablock address: %u\n", (unsigned int) datablock);

    etimer_set(&periodic_timer, (2 * CLOCK_SECOND));

    //Initialise Data
    for (j = 0; j < NROUND; j++)
        memcpy(datablock[j], fixed_data, AES_BLOCK_LEN);

    for (i = 0; i < NSAMPLE; i++) {
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
        etimer_reset(&periodic_timer);

#ifdef VERBOSE_AESTEST
        printf("#Sample %d/%d\n", i + 1, NSAMPLE);
        PrintBlock("#Key\t: ", Aes128Key, "\n");
        PrintBlock("#Plaintext\t: ", datablock[0], "\n");
#endif

        AES_128.set_key(Aes128Key);

        //Start timing.
        start = RTIMER_NOW();
#ifndef TIMING_FRAMEWORK_TEST
        for (j = 0; j < NROUND; j++) {
            AES_128.encrypt(datablock[j]);
        }
#else
        for (j = 0; j < NROUND * 10; j++) {
            random_rand();
        }
#endif
        end = RTIMER_NOW();

        //Print result.
#ifdef VERBOSE_AESTEST
        PrintBlock("#Ciphertext\t: ", datablock[0], "\n");
        printf("#Round\t: %d\n", NROUND);
        printf("#Start\t: %lu\n", start);
        printf("#End\t: %lu\n", end);
        printf("#Time Elapsed\t:\n");
#endif
        printf("%lu\n", end - start);

        finalise();
    }

    printf("#%d tests done for %s.\n", NSAMPLE, TARGET_NAME);

    PROCESS_END();
}
Esempio n. 19
0
/*---------------------------------------------------------------------------*/
static int
send_one_packet(struct net_buf *buf, mac_callback_t sent, void *ptr)
{
  int ret;
  int last_sent_ok = 0;
#if NULLRDC_ENABLE_RETRANSMISSIONS
  rtimer_clock_t target_time;
  uint8_t tx_attempts = 0;
  uint8_t max_tx_attempts;

  if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) > 0) {
    max_tx_attempts = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
  } else {
    max_tx_attempts = NULLRDC_MAX_RETRANSMISSIONS + 1;
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

  packetbuf_set_addr(buf, PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW
  packetbuf_set_attr(buf, PACKETBUF_ATTR_MAC_ACK, 1);
#endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */

  if(NETSTACK_FRAMER.create_and_secure(buf) < 0) {
    /* Failed to allocate space for headers */
    PRINTF("nullrdc: send failed, too large header\n");
    ret = MAC_TX_ERR_FATAL;
  } else {
#if NULLRDC_802154_AUTOACK
    int is_broadcast;
    uint8_t dsn;
    dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;

    NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());

    is_broadcast = packetbuf_holds_broadcast();

    if(NETSTACK_RADIO.receiving_packet() ||
       (!is_broadcast && NETSTACK_RADIO.pending_packet())) {

      /* Currently receiving a packet over air or the radio has
         already received a packet that needs to be read before
         sending with auto ack. */
      ret = MAC_TX_COLLISION;
    } else {
      if(!is_broadcast) {
        RIMESTATS_ADD(reliabletx);
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
  while(1) {
    /* Transmit packet and check status */
    tx_attempts++;
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */

      switch(NETSTACK_RADIO.transmit(packetbuf_totlen(buf))) {
      case RADIO_TX_OK:
        if(is_broadcast) {
          ret = MAC_TX_OK;
        } else {
          rtimer_clock_t wt;

          /* Check for ack */
          wt = RTIMER_NOW();
          watchdog_periodic();
          while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
            simProcessRunValue = 1;
            cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
          }

          ret = MAC_TX_NOACK;
          if(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet() ||
             NETSTACK_RADIO.channel_clear() == 0) {
            int len;
            uint8_t ackbuf[ACK_LEN];

            if(AFTER_ACK_DETECTED_WAIT_TIME > 0) {
              wt = RTIMER_NOW();
              watchdog_periodic();
              while(RTIMER_CLOCK_LT(RTIMER_NOW(),
                                    wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
      #if CONTIKI_TARGET_COOJA
                  simProcessRunValue = 1;
                  cooja_mt_yield();
      #endif /* CONTIKI_TARGET_COOJA */
              }
            }

            if(NETSTACK_RADIO.pending_packet()) {
              len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
              if(len == ACK_LEN && ackbuf[2] == dsn) {
                /* Ack received */
                RIMESTATS_ADD(ackrx);
                ret = MAC_TX_OK;
              } else {
                /* Not an ack or ack not for us: collision */
                ret = MAC_TX_COLLISION;
              }
            }
          } else {
	    PRINTF("nullrdc tx noack\n");
	  }
        }
        break;
      case RADIO_TX_COLLISION:
        ret = MAC_TX_COLLISION;
        break;
      default:
        ret = MAC_TX_ERR;
        break;
      }
#if NULLRDC_ENABLE_RETRANSMISSIONS
    if(is_broadcast) {
#if !NULLRDC_ENABLE_RETRANSMISSIONS_BCAST
      break;
#else  /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
      if(ret != MAC_TX_COLLISION) {
        /* Retry broadcast frame only upon collision */
        break;
      }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS_BCAST */
    } else {
      /* Frame is unicast. Do not retry unless NO_ACK or COLLISION */
      if((ret != MAC_TX_NOACK) && (ret != MAC_TX_COLLISION)) {
        break;
      }
    }
    /* Do not retry if max attempts reached. */
    if(tx_attempts >= max_tx_attempts) {
      PRINTF("nullrdc: max tx attempts reached\n");
      break;
    }
    /* Block-wait before retrying the frame. */
    target_time = RTIMER_NOW() +
      (RTIMER_SECOND * NULLRDC_TX_RETRY_DELAY_MS / 1000);
    watchdog_periodic();
    while(RTIMER_CLOCK_LT(RTIMER_NOW(), target_time)) {
      /* Wait */
    }
    /* Attempt a new frame (re)transmission */
  }
#endif /* NULLRDC_ENABLE_RETRANSMISSIONS */
    }

#else /* ! NULLRDC_802154_AUTOACK */

    switch(NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf))) {
    case RADIO_TX_OK:
      ret = MAC_TX_OK;
      break;
    case RADIO_TX_COLLISION:
      ret = MAC_TX_COLLISION;
      break;
    case RADIO_TX_NOACK:
      ret = MAC_TX_NOACK;
      break;
    default:
      ret = MAC_TX_ERR;
      break;
    }

#endif /* ! NULLRDC_802154_AUTOACK */
  }
  if(ret == MAC_TX_OK) {
    last_sent_ok = 1;
  }
#if ! NULLRDC_ENABLE_RETRANSMISSIONS
  mac_call_sent_callback(buf, sent, ptr, ret, 1);
#else
  mac_call_sent_callback(buf, sent, ptr, ret, tx_attempts);
#endif /* !NULLRDC_ENABLE_RETRANSMISSIONS */
  return last_sent_ok;
}
Esempio n. 20
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(clock_test_process, ev, data)
{

  PROCESS_BEGIN();

  etimer_set(&et, 2 * CLOCK_SECOND);

  PROCESS_YIELD();

#if TEST_CLOCK_DELAY_USEC
  printf("clock_delay_usec test, (10,000 x i) usec:\n");
  i = 1;
  while(i < 7) {
    start_count = RTIMER_NOW();
    clock_delay_usec(10000 * i);
    end_count = RTIMER_NOW();
    diff = end_count - start_count;
    printf("Requested: %u usec, Real: %u rtimer ticks = ~%u us\n",
           10000 * i, diff, diff * 64);
    i++;
  }
#endif

#if TEST_RTIMER
  printf("Rtimer Test, 1 sec (%u rtimer ticks):\n", RTIMER_SECOND);
  i = 0;
  while(i < 5) {
    etimer_set(&et, 2 * CLOCK_SECOND);
    printf("=======================\n");
    ct = clock_time();
    rt_now = RTIMER_NOW();
    rt_for = rt_now + RTIMER_SECOND;
    printf("Now=%u (clock = %u) - For=%u\n", rt_now, ct, rt_for);
    if(rtimer_set(&rt, rt_for, 1, (rtimer_callback_t) rt_callback, NULL) !=
       RTIMER_OK) {
      printf("Error setting\n");
    }

    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    i++;
  }
#endif

#if TEST_ETIMER
  printf("Clock tick and etimer test, 1 sec (%u clock ticks):\n",
         CLOCK_SECOND);
  i = 0;
  while(i < 10) {
    etimer_set(&et, CLOCK_SECOND);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    etimer_reset(&et);

    count = clock_time();
    printf("%u ticks\n", count);

    leds_toggle(LEDS_RED);
    i++;
  }
#endif

#if TEST_CLOCK_SECONDS
  printf("Clock seconds test (5s):\n");
  i = 0;
  while(i < 10) {
    etimer_set(&et, 5 * CLOCK_SECOND);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    etimer_reset(&et);

    sec = clock_seconds();
    printf("%lu seconds\n", sec);

    leds_toggle(LEDS_GREEN);
    i++;
  }
#endif

  printf("Done!\n");

  PROCESS_END();
}
Esempio n. 21
0
/*---------------------------------------------------------------------------*/
static void
powercycle_turn_radio_off(void)
{
#if CONTIKIMAC_CONF_COMPOWER
  uint8_t was_on = radio_is_on;
#endif /* CONTIKIMAC_CONF_COMPOWER */
  
#if RDC_CONF_HARDWARE_SEND_ACK
  if(we_are_sending == 0 && we_are_receiving_burst == 0) {
#else
  if(we_are_sending == 0 && we_are_receiving_burst == 0 && we_are_acking == 0) {
#endif
    off();
#if CONTIKIMAC_CONF_COMPOWER
    if(was_on && !radio_is_on) {
      compower_accumulate(&compower_idle_activity);
    }
#endif /* CONTIKIMAC_CONF_COMPOWER */
  }
}
/*---------------------------------------------------------------------------*/
static void
powercycle_turn_radio_on(void)
{
#if RDC_CONF_HARDWARE_SEND_ACK
  if(we_are_sending == 0 && we_are_receiving_burst == 0) {
#else
  if(we_are_sending == 0 && we_are_receiving_burst == 0 && we_are_acking == 0) {
#endif
    on();
  }
}
/*---------------------------------------------------------------------------*/
static char
powercycle(struct rtimer *t, void *ptr)
{
#if SYNC_CYCLE_STARTS
  static volatile rtimer_clock_t sync_cycle_start;
  static volatile uint8_t sync_cycle_phase;
#endif

  PT_BEGIN(&pt);

#if SYNC_CYCLE_STARTS
  sync_cycle_start = RTIMER_NOW();
#else
  cycle_start = RTIMER_NOW();
#endif

  while(1) {
    static uint8_t packet_seen;
    static rtimer_clock_t t0;
    static uint8_t count;

#if SYNC_CYCLE_STARTS
    /* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
       of CHANNEL_CHECK_RATE */
    if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
      sync_cycle_phase = 0;
      sync_cycle_start += RTIMER_ARCH_SECOND;
      cycle_start = sync_cycle_start;
    } else {
#if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
      cycle_start = sync_cycle_start + ((unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#else
      cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#endif
    }
#else
    cycle_start += CYCLE_TIME;
#endif

    packet_seen = 0;

    for(count = 0; count < CCA_COUNT_MAX; ++count) {
      t0 = RTIMER_NOW();
      if(we_are_sending == 0 && we_are_receiving_burst == 0) {
        powercycle_turn_radio_on();
        /* Check if a packet is seen in the air. If so, we keep the
             radio on for a while (LISTEN_TIME_AFTER_PACKET_DETECTED) to
             be able to receive the packet. We also continuously check
             the radio medium to make sure that we wasn't woken up by a
             false positive: a spurious radio interference that was not
             caused by an incoming packet. */
        if(NETSTACK_RADIO.channel_clear() == 0) {
          packet_seen = 1;
          break;
        }
        powercycle_turn_radio_off();
      }
      schedule_powercycle_fixed(t, RTIMER_NOW() + CCA_SLEEP_TIME);
      PT_YIELD(&pt);
    }

    if(packet_seen) {
      static rtimer_clock_t start;
      static uint8_t silence_periods, periods;
      start = RTIMER_NOW();

      periods = silence_periods = 0;
      while(we_are_sending == 0 && radio_is_on &&
            RTIMER_CLOCK_LT(RTIMER_NOW(),
                            (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {

        /* Check for a number of consecutive periods of
             non-activity. If we see two such periods, we turn the
             radio off. Also, if a packet has been successfully
             received (as indicated by the
             NETSTACK_RADIO.pending_packet() function), we stop
             snooping. */
#if !RDC_CONF_HARDWARE_CSMA
       /* A cca cycle will disrupt rx on some radios, e.g. mc1322x, rf230 */
       /*TODO: Modify those drivers to just return the internal RSSI when already in rx mode */
        if(NETSTACK_RADIO.channel_clear()) {
          ++silence_periods;
        } else {
          silence_periods = 0;
        }
#endif

        ++periods;

        if(NETSTACK_RADIO.receiving_packet()) {
          silence_periods = 0;
        }
        if(silence_periods > MAX_SILENCE_PERIODS) {
          powercycle_turn_radio_off();
          break;
        }
        if(WITH_FAST_SLEEP &&
            periods > MAX_NONACTIVITY_PERIODS &&
            !(NETSTACK_RADIO.receiving_packet() ||
              NETSTACK_RADIO.pending_packet())) {
          powercycle_turn_radio_off();
          break;
        }
        if(NETSTACK_RADIO.pending_packet()) {
          break;
        }

        schedule_powercycle(t, CCA_CHECK_TIME + CCA_SLEEP_TIME);
        PT_YIELD(&pt);
      }
      if(radio_is_on) {
        if(!(NETSTACK_RADIO.receiving_packet() ||
             NETSTACK_RADIO.pending_packet()) ||
             !RTIMER_CLOCK_LT(RTIMER_NOW(),
                 (start + LISTEN_TIME_AFTER_PACKET_DETECTED))) {
          powercycle_turn_radio_off();
        }
      }
    }

    if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
      /* Schedule the next powercycle interrupt, or sleep the mcu
	 until then.  Sleeping will not exit from this interrupt, so
	 ensure an occasional wake cycle or foreground processing will
	 be blocked until a packet is detected */
#if RDC_CONF_MCU_SLEEP
      static uint8_t sleepcycle;
      if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
        rtimer_arch_sleep(CYCLE_TIME - (RTIMER_NOW() - cycle_start));
      } else {
        sleepcycle = 0;
        schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
        PT_YIELD(&pt);
      }
#else
      schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
      PT_YIELD(&pt);
#endif
    }
  }

  PT_END(&pt);
}
/*---------------------------------------------------------------------------*/
static int
broadcast_rate_drop(void)
{
#if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT
  if(!timer_expired(&broadcast_rate_timer)) {
    broadcast_rate_counter++;
    if(broadcast_rate_counter < CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT) {
      return 0;
    } else {
      return 1;
    }
  } else {
    timer_set(&broadcast_rate_timer, CLOCK_SECOND);
    broadcast_rate_counter = 0;
    return 0;
  }
#else /* CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT */
  return 0;
#endif /* CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT */
}
/*---------------------------------------------------------------------------*/
static int
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
	    struct rdc_buf_list *buf_list,
            int is_receiver_awake)
{
  rtimer_clock_t t0;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  uint8_t got_strobe_ack = 0;
  int hdrlen, len;
  uint8_t is_broadcast = 0;
  uint8_t is_reliable = 0;
  uint8_t is_known_receiver = 0;
  uint8_t collisions;
  int transmit_len;
  int ret;
  uint8_t contikimac_was_on;
  uint8_t seqno;
#if WITH_CONTIKIMAC_HEADER
  struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */

  /* Exit if RDC and radio were explicitly turned off */
   if(!contikimac_is_on && !contikimac_keep_radio_on) {
    PRINTF("contikimac: radio is turned off\n");
    return MAC_TX_ERR_FATAL;
  }
 
  if(packetbuf_totlen() == 0) {
    PRINTF("contikimac: send_packet data len 0\n");
    return MAC_TX_ERR_FATAL;
  }

#if !NETSTACK_CONF_BRIDGE_MODE
  /* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
#endif
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    is_broadcast = 1;
    PRINTDEBUG("contikimac: send broadcast\n");

    if(broadcast_rate_drop()) {
      return MAC_TX_COLLISION;
    }
  } else {
#if UIP_CONF_IPV6
    PRINTDEBUG("contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else /* UIP_CONF_IPV6 */
    PRINTDEBUG("contikimac: send unicast to %u.%u\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
  }
  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

#if WITH_CONTIKIMAC_HEADER
  hdrlen = packetbuf_totlen();
  if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
    /* Failed to allocate space for contikimac header */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  chdr = packetbuf_hdrptr();
  chdr->id = CONTIKIMAC_ID;
  chdr->len = hdrlen;
  
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    packetbuf_hdr_remove(sizeof(struct hdr));
    return MAC_TX_ERR_FATAL;
  }
  hdrlen += sizeof(struct hdr);
#else
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
#endif

  /* Make sure that the packet is longer or equal to the shortest
     packet length. */
  transmit_len = packetbuf_totlen();
  if(transmit_len < SHORTEST_PACKET_SIZE) {
    /* Pad with zeroes */
    uint8_t *ptr;
    ptr = packetbuf_dataptr();
    memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen());

    PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen());
    transmit_len = SHORTEST_PACKET_SIZE;
  }


  packetbuf_compact();

#ifdef NETSTACK_ENCRYPT
  NETSTACK_ENCRYPT();
#endif /* NETSTACK_ENCRYPT */

  transmit_len = packetbuf_totlen();

  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);

  /* Remove the MAC-layer header since it will be recreated next time around. */
  packetbuf_hdr_remove(hdrlen);

  if(!is_broadcast && !is_receiver_awake) {
#if WITH_PHASE_OPTIMIZATION
    ret = phase_wait(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     CYCLE_TIME, GUARD_TIME,
                     mac_callback, mac_callback_ptr, buf_list);
    if(ret == PHASE_DEFERRED) {
      return MAC_TX_DEFERRED;
    }
    if(ret != PHASE_UNKNOWN) {
      is_known_receiver = 1;
    }
#endif /* WITH_PHASE_OPTIMIZATION */ 
  }
  


  /* By setting we_are_sending to one, we ensure that the rtimer
     powercycle interrupt do not interfere with us sending the packet. */
  we_are_sending = 1;

  /* If we have a pending packet in the radio, we should not send now,
     because we will trash the received packet. Instead, we signal
     that we have a collision, which lets the packet be received. This
     packet will be retransmitted later by the MAC protocol
     instread. */
  if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) {
    we_are_sending = 0;
    PRINTF("contikimac: collision receiving %d, pending %d\n",
           NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
    return MAC_TX_COLLISION;
  }
  
  /* Switch off the radio to ensure that we didn't start sending while
     the radio was doing a channel check. */
  off();


  strobes = 0;

  /* Send a train of strobes until the receiver answers with an ACK. */
  collisions = 0;

  got_strobe_ack = 0;

  /* Set contikimac_is_on to one to allow the on() and off() functions
     to control the radio. We restore the old value of
     contikimac_is_on when we are done. */
  contikimac_was_on = contikimac_is_on;
  contikimac_is_on = 1;

#if !RDC_CONF_HARDWARE_CSMA
    /* Check if there are any transmissions by others. */
    /* TODO: why does this give collisions before sending with the mc1322x? */
  if(is_receiver_awake == 0) {
    int i;
    for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
      t0 = RTIMER_NOW();
      on();
#if CCA_CHECK_TIME > 0
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
#endif
      if(NETSTACK_RADIO.channel_clear() == 0) {
        collisions++;
        off();
        break;
      }
      off();
      t0 = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
    }
  }

  if(collisions > 0) {
    we_are_sending = 0;
    off();
    PRINTF("contikimac: collisions before sending\n");
    contikimac_is_on = contikimac_was_on;
    return MAC_TX_COLLISION;
  }
#endif /* RDC_CONF_HARDWARE_CSMA */

#if !RDC_CONF_HARDWARE_ACK
  if(!is_broadcast) {
    /* Turn radio on to receive expected unicast ack.  Not necessary
       with hardware ack detection, and may trigger an unnecessary cca
       or rx cycle */
     on();
  }
#endif

  watchdog_periodic();
  t0 = RTIMER_NOW();
  seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
  for(strobes = 0, collisions = 0;
      got_strobe_ack == 0 && collisions == 0 &&
      RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {

    watchdog_periodic();

    if(!is_broadcast && (is_receiver_awake || is_known_receiver) &&
       !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
      PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
      break;
    }

    len = 0;

    {
      rtimer_clock_t wt;
      rtimer_clock_t txtime;
      int ret;

      txtime = RTIMER_NOW();
      ret = NETSTACK_RADIO.transmit(transmit_len);

#if RDC_CONF_HARDWARE_ACK
     /* For radios that block in the transmit routine and detect the
	ACK in hardware */
      if(ret == RADIO_TX_OK) {
        if(!is_broadcast) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        }
      } else if (ret == RADIO_TX_NOACK) {
      } else if (ret == RADIO_TX_COLLISION) {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
      }
      wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#else /* RDC_CONF_HARDWARE_ACK */
     /* Wait for the ACK packet */
      wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }

      if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
                           NETSTACK_RADIO.pending_packet() ||
                           NETSTACK_RADIO.channel_clear() == 0)) {
        uint8_t ackbuf[ACK_LEN];
        wt = RTIMER_NOW();
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }

        len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
        //PRINTF("%u %u vs %u", len, ackbuf[ACK_LEN - 1], seqno);
        if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        } else {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
        }
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }

  off();

  PRINTF("contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes,
         packetbuf_totlen(),
         got_strobe_ack ? "ack" : "no ack",
         collisions ? "collision" : "no collision");

#if CONTIKIMAC_CONF_COMPOWER
  /* Accumulate the power consumption for the packet transmission. */
  compower_accumulate(&current_packet);

  /* Convert the accumulated power consumption for the transmitted
     packet to packet attributes so that the higher levels can keep
     track of the amount of energy spent on transmitting the
     packet. */
  compower_attrconv(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

  contikimac_is_on = contikimac_was_on;
  we_are_sending = 0;

  /* Determine the return value that we will return from the
     function. We must pass this value to the phase module before we
     return from the function.  */
  if(collisions > 0) {
    ret = MAC_TX_COLLISION;
  } else if(!is_broadcast && !got_strobe_ack) {
    ret = MAC_TX_NOACK;
  } else {
    ret = MAC_TX_OK;
  }

#if WITH_PHASE_OPTIMIZATION
  if(is_known_receiver && got_strobe_ack) {
    PRINTF("no miss %d wake-ups %d\n",
	   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           strobes);
  }

  if(!is_broadcast) {
    if(collisions == 0 && is_receiver_awake == 0) {
      phase_update(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   encounter_time, ret);
    }
  }
#endif /* WITH_PHASE_OPTIMIZATION */

  return ret;
}
/*---------------------------------------------------------------------------*/
static void
qsend_packet(mac_callback_t sent, void *ptr)
{
  int ret = send_packet(sent, ptr, NULL, 0);
  if(ret != MAC_TX_DEFERRED) {
    mac_call_sent_callback(sent, ptr, ret, 1);
  }
}
/*-------------------------------------------------------------------------*/
int
main(void)
{
  initialize();

#ifdef LOWPOWER
  rf2xx_set_txpower(0xf);
#endif

  while(1) {
    process_run();
    watchdog_periodic();

#if 0
/* Various entry points for debugging in the AVR Studio simulator.
 * Set as next statement and step into the routine.
 */
    NETSTACK_RADIO.send(packetbuf_hdrptr(), 42);
    process_poll(&rf230_process);
    packetbuf_clear();
    len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
    packetbuf_set_datalen(42);
    NETSTACK_RDC.input();
#endif

#if 0
/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver.
 * This can show when that happens.
 */
    extern uint8_t rf230_calibrated;
    if (rf230_calibrated) {
      PRINTD("\nRF230 calibrated!\n");
      rf230_calibrated=0;
    }
#endif

/* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */
#if DEBUGFLOWSIZE
  if (debugflowsize) {
    debugflow[debugflowsize]=0;
    PRINTF("%s",debugflow);
    debugflowsize=0;
   }
#endif

#if PERIODICPRINTS
#if TESTRTIMER
/* Timeout can be increased up to 8 seconds maximum.
 * A one second cycle is convenient for triggering the various debug printouts.
 * The triggers are staggered to avoid printing everything at once.
 * My raven is 6% slow.
 */
    if (rtimerflag) {
      rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
      rtimerflag=0;
#else
  if (clocktime!=clock_seconds()) {
     clocktime=clock_seconds();
#endif

#if STAMPS
if ((clocktime%STAMPS)==0) {
#if ENERGEST_CONF_ON
#include "lib/print-stats.h"
  print_stats();
#elif RADIOSTATS
extern volatile unsigned long radioontime;
  PRINTF("%u(%u)s\n",clocktime,radioontime);
#else
  PRINTF("%us\n",clocktime);
#endif

}
#endif
#if TESTRTIMER
      clocktime+=1;
#endif

#if PINGS && UIP_CONF_IPV6
extern void raven_ping6(void);
if ((clocktime%PINGS)==1) {
  PRINTF("**Ping\n");
  raven_ping6();
}
#endif

#if ROUTES && UIP_CONF_IPV6
if ((clocktime%ROUTES)==2) {

extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
extern uip_ds6_route_t uip_ds6_routing_table[];
extern uip_ds6_netif_t uip_ds6_if;

  uint8_t i,j;
  PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
  for (i=0;i<UIP_DS6_ADDR_NB;i++) {
    if (uip_ds6_if.addr_list[i].isused) {
      ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr);
      PRINTF("\n");
    }
  }
  PRINTF("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB);
  for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
    if(uip_ds6_nbr_cache[i].isused) {
      ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
      PRINTF("\n");
      j=0;
    }
  }
  if (j) PRINTF("  <none>");
  PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
  for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
    if(uip_ds6_routing_table[i].isused) {
      ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
      PRINTF("/%u (via ", uip_ds6_routing_table[i].length);
      ipaddr_add(&uip_ds6_routing_table[i].nexthop);
 //     if(uip_ds6_routing_table[i].state.lifetime < 600) {
        PRINTF(") %lus\n", uip_ds6_routing_table[i].state.lifetime);
 //     } else {
 //       PRINTF(")\n");
 //     }
      j=0;
    }
  }
  if (j) PRINTF("  <none>");
  PRINTF("\n---------\n");
}
#endif

#if STACKMONITOR
if ((clocktime%STACKMONITOR)==3) {
  extern uint16_t __bss_end;
  uint16_t p=(uint16_t)&__bss_end;
  do {
    if (*(uint16_t *)p != 0x4242) {
      PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end);
      break;
    }
    p+=10;
  } while (p<RAMEND-10);
}
#endif

    }
#endif /* PERIODICPRINTS */

//Use with RF230BB DEBUGFLOW to show path through driver
#if RF230BB&&0
extern uint8_t rf230processflag;
    if (rf230processflag) {
      PRINTF("rf230p%d",rf230processflag);
      rf230processflag=0;
    }
#endif

#if RF230BB&&0
extern uint8_t rf230_interrupt_flag;
    if (rf230_interrupt_flag) {
 //   if (rf230_interrupt_flag!=11) {
        PRINTF("**RI%u",rf230_interrupt_flag);
 //   }
      rf230_interrupt_flag=0;
    }
#endif
  }
  return 0;
}

/*---------------------------------------------------------------------------*/
void
log_message(char *m1, char *m2)
{
  PRINTF("%s%s\n", m1, m2);
}
Esempio n. 23
0
/*---------------------------------------------------------------------------*/
static char
transmitter(struct rtimer *t, void *ptr)
{
  int r;
  rtimer_clock_t now, rest, period_start, slot_start;

  /* Calculate slot start time */
  now = RTIMER_NOW();
  rest = now % PERIOD_LENGTH;
  period_start = now - rest;
  slot_start = period_start + MY_SLOT*SLOT_LENGTH;

  /* Check if we are inside our slot */
  if(now < slot_start ||
      now > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
    PRINTF("TIMER We are outside our slot: %u != [%u,%u]\n", now, slot_start, slot_start + SLOT_LENGTH);
    while(now > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
      slot_start += PERIOD_LENGTH;
    }

    PRINTF("TIMER Rescheduling until %u\n", slot_start);
    r = rtimer_set(&rtimer, slot_start, 1,
        (void (*)(struct rtimer *, void *))transmitter, NULL);
    if(r) {
      PRINTF("TIMER Error #1: %d\n", r);
    }

    return 1;
  }

  /* Transmit queued packets */
  while(nextsend != freeslot) {
    PRINTF("RADIO Transmitting packet #%i\n", id[nextsend]);
    if(!radio->send(queuebuf_dataptr(data[nextsend]),
		    queuebuf_datalen(data[nextsend]))) {
      sent_counter++;
      PRINTF("RADIO Transmit OK for #%i, total=%i\n", id[nextsend], sent_counter);
      DLEDS_TOGGLE(LEDS_GREEN);
    } else {
      PRINTF("RADIO Transmit failed for #%i, total=%i\n", id[nextsend], sent_counter);
      DLEDS_TOGGLE(LEDS_RED);
    }

    nextsend = (nextsend + 1) % NUM_PACKETS;

    /* Recalculate new slot */
    if(RTIMER_NOW() > slot_start + SLOT_LENGTH - GUARD_PERIOD) {
      PRINTF("TIMER No more time to transmit\n");
      break;
    }
  }

  /* Calculate time of our next slot */
  slot_start += PERIOD_LENGTH;
  PRINTF("TIMER Rescheduling until %u\n", slot_start);
  r = rtimer_set(&rtimer, slot_start, 1,
      (void (*)(struct rtimer *, void *))transmitter, NULL);
  if(r) {
    PRINTF("TIMER Error #2: %d\n", r);
  }

  return 0;
}
Esempio n. 24
0
/*---------------------------------------------------------------------------*/
static int
cc2420_transmit(unsigned short payload_len)
{
  int i, txpower;
  uint8_t total_len;
#if CC2420_CONF_CHECKSUM
  uint16_t checksum;
#endif /* CC2420_CONF_CHECKSUM */

  GET_LOCK();

  txpower = 0;
  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Remember the current transmission power */
    txpower = cc2420_get_txpower();
    /* Set the specified transmission power */
    set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
  }

  total_len = payload_len + AUX_LEN;
  
  /* The TX FIFO can only hold one packet. Make sure to not overrun
   * FIFO by waiting for transmission to start here and synchronizing
   * with the CC2420_TX_ACTIVE check in cc2420_send.
   *
   * Note that we may have to wait up to 320 us (20 symbols) before
   * transmission starts.
   */
#ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
#error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
#else
#define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
#endif

#if WITH_SEND_CCA
  strobe(CC2420_SRXON);
  BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
  strobe(CC2420_STXONCCA);
#else /* WITH_SEND_CCA */
  strobe(CC2420_STXON);
#endif /* WITH_SEND_CCA */
  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
    if(CC2420_SFD_IS_1) {
      {
    	radio_TX_time = RTIMER_NOW();
        rtimer_clock_t sfd_timestamp;
        sfd_timestamp = cc2420_sfd_start_time;

        //printf("Sfd time = %u\n",sfd_timestamp);

        if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
           PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
          /* Write timestamp to last two bytes of packet in TXFIFO. */
          //CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2);
        	CC2420_WRITE_RAM(&radio_TX_time, CC2420RAM_TXFIFO + payload_len - 1, 2);

        }
      }

      if(!(status() & BV(CC2420_TX_ACTIVE))) {
        /* SFD went high but we are not transmitting. This means that
           we just started receiving a packet, so we drop the
           transmission. */
        RELEASE_LOCK();
        return RADIO_TX_COLLISION;
      }
      if(receive_on) {
	ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
      }
      ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
      /* We wait until transmission has ended so that we get an
	 accurate measurement of the transmission time.*/
      BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);

#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
      ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
#endif
      ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
      if(receive_on) {
	ENERGEST_ON(ENERGEST_TYPE_LISTEN);
      } else {
	/* We need to explicitly turn off the radio,
	 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
	off();
      }

      if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
        /* Restore the transmission power */
        set_txpower(txpower & 0xff);
      }

      RELEASE_LOCK();
      return RADIO_TX_OK;
    }
  }

  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
     transmitted because of other channel activity. */
  RIMESTATS_ADD(contentiondrop);
  PRINTF("cc2420: do_send() transmission never started\n");

  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
    /* Restore the transmission power */
    set_txpower(txpower & 0xff);
  }

  RELEASE_LOCK();
  return RADIO_TX_COLLISION;
}
Esempio n. 25
0
/*---------------------------------------------------------------------------*/
void
lpm_enter()
{
  rtimer_clock_t lpm_exit_time;
  rtimer_clock_t duration;

  /*
   * If either the RF or the registered peripherals are on, dropping to PM1/2
   * would equal pulling the rug (32MHz XOSC) from under their feet. Thus, we
   * only drop to PM0. PM0 is also used if max_pm==0.
   */
  if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) != 0
     || !periph_permit_pm1() || max_pm == 0) {
    enter_pm0();

    /* We reach here when the interrupt context that woke us up has returned */
    return;
  }

  /*
   * Registered peripherals were off. Radio was off: Some Duty Cycling in place.
   * rtimers run on the Sleep Timer. Thus, if we have a scheduled rtimer
   * task, a Sleep Timer interrupt will fire and will wake us up.
   * Choose the most suitable PM based on anticipated deep sleep duration
   */
  lpm_exit_time = rtimer_arch_next_trigger();
  duration = lpm_exit_time - RTIMER_NOW();

  if(duration < DEEP_SLEEP_PM1_THRESHOLD || lpm_exit_time == 0) {
    /* Anticipated duration too short or no scheduled rtimer task. Use PM0 */
    enter_pm0();

    /* We reach here when the interrupt context that woke us up has returned */
    return;
  }

  /* If we reach here, we -may- (but may as well not) be dropping to PM1+. We
   * know the registered peripherals and RF are off so we can switch to the
   * 16MHz RCOSC. */
  select_16_mhz_rcosc();

  /*
   * Switching the System Clock from the 32MHz XOSC to the 16MHz RC OSC may
   * have taken a while. Re-estimate sleep duration.
   */
  duration = lpm_exit_time - RTIMER_NOW();

  if(duration < DEEP_SLEEP_PM1_THRESHOLD) {
    /*
     * oops... The clock switch took some time and now the remaining sleep
     * duration is too short. Restore the clock source to the 32MHz XOSC and
     * abort the LPM attempt altogether. We can't drop to PM0,
     * we need to yield to main() since we may have events to service now.
     */
    select_32_mhz_xosc();

    return;
  } else if(duration >= DEEP_SLEEP_PM2_THRESHOLD && max_pm == 2) {
    /* Long sleep duration and PM2 is allowed. Use it */
    REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM2;
  } else {
    /*
     * Anticipated duration too short for PM2 but long enough for PM1 and we
     * are allowed to use PM1
     */
    REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM1;
  }

  /* We are only interested in IRQ energest while idle or in LPM */
  ENERGEST_IRQ_RESTORE(irq_energest);
  ENERGEST_OFF(ENERGEST_TYPE_CPU);
  ENERGEST_ON(ENERGEST_TYPE_LPM);

  /* Remember the current time so we can adjust the clock when we wake up */
  sleep_enter_time = RTIMER_NOW();

  /*
   * Last chance to abort entering Deep Sleep.
   *
   * - There is the slight off-chance that a SysTick interrupt fired while we
   *   were trying to make up our mind. This may have raised an event.
   * - The Sleep Timer may have fired
   *
   * Check if there is still a scheduled rtimer task and check for pending
   * events before going to Deep Sleep
   */
  if(process_nevents() || rtimer_arch_next_trigger() == 0) {
    /* Event flag raised or rtimer inactive.
     * Turn on the 32MHz XOSC, restore PMCTL and abort */
    select_32_mhz_xosc();

    REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM0;
  } else {
    /* All clear. Assert WFI and drop to PM1/2. This is now un-interruptible */
    assert_wfi();
  }

  /*
   * We reach here after coming back from PM1/2. The interrupt context that
   * woke us up has returned. lpm_exit() has run, it has switched the system
   * clock source back to the 32MHz XOSC, it has adjusted the system clock,
   * it has restored PMCTL and it has done energest housekeeping
   */
  return;
}
Esempio n. 26
0
                     0xB9BF9243, 0xE644A8BE, 0x55159A59, 0x6F9E52A6 },
    .hash        = { 0x65637572, 0x20612073, 0x68206F66, 0x20686173,
                     0x69732061, 0x68697320, 0x6F2C2054, 0x48616C6C },
  };
  static uint32_t public_x[8] = { 0x5fa58f52, 0xe47cfbf2, 0x300c28c5, 0x6375ba10,
                                  0x62684e91, 0xda0a9a8f, 0xf9f2ed29, 0x36dfe2c6 };
  static uint32_t public_y[8] = { 0xc772f829, 0x4fabc36f, 0x09daed0b, 0xe93f9872,
                                  0x35a7cfab, 0x5a3c7869, 0xde1ab878, 0x71a0d4fc };

  memcpy(state.public.x, public_x, sizeof(public_x));
  memcpy(state.public.y, public_y, sizeof(public_y));

  /*
   * Verify
   */
  time = RTIMER_NOW();
  PT_SPAWN(&(ecdsa_verify_test.pt), &(state.pt), ecc_dsa_verify(&state));
  time = RTIMER_NOW() - time;
  printf("ecc_dsa_verify(), %lu ms\n",
         (uint32_t)((uint64_t)time * 1000 / RTIMER_SECOND));

  if(state.result) {
    puts("signature verification failed");
  } else {
    puts("signature verification OK");
  }

  puts("-----------------------------------------\n"
       "Disabling pka...");
  pka_disable();
/*---------------------------------Main Routine----------------------------*/
int
main(void)
{
  /* GCC depends on register r1 set to 0 (?) */
  asm volatile ("clr r1");
  
  /* Initialize in a subroutine to maximize stack space */
  initialize();
#if DEBUG
{struct process *p;
 for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) {
  printf_P(PSTR("Process=%p Thread=%p  Name=\"%s\" \n"),p,p->thread,p->name);
 }
}
#endif
  while(1) {
    process_run();

    watchdog_periodic();

/* Print rssi of all received packets, useful for range testing */
#ifdef RF230_MIN_RX_POWER
    uint8_t lastprint;
    if (rf230_last_rssi != lastprint) {        //can be set in halbb.c interrupt routine
        printf_P(PSTR("%u "),rf230_last_rssi);
        lastprint=rf230_last_rssi;
    }
#endif

#if TESTRTIMER
    if (rtimerflag) {  //8 seconds is maximum interval, my jackdaw 4% slow
      rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
      rtimerflag=0;
#if STAMPS
      if ((rtime%STAMPS)==0) {
        printf("%us ",rtime);
      }
#endif
      rtime+=1;
#if PINGS
      if ((rtime%PINGS)==0) {
        PRINTF("**Ping\n");
        pingsomebody();
      }
#endif
    }
#endif /* TESTRTIMER */

/* Use with rf230bb.c DEBUGFLOW to show the sequence of driver calls from the uip stack */
#if RF230BB&&0
extern uint8_t debugflowsize,debugflow[];
  if (debugflowsize) {
    debugflow[debugflowsize]=0;
    printf("%s",debugflow);
    debugflowsize=0;
   }
#endif

/* Use for low level interrupt debugging */
#if RF230BB&&0
extern uint8_t rf230interruptflag;   //in halbb.c
extern uint8_t rf230processflag;     //in rf230bb.c
  if (rf230processflag) {
    printf("**RF230 process flag %u\n\r",rf230processflag);
    rf230processflag=0;
  }
  if (rf230interruptflag) {
//  if (rf230interruptflag!=11) {
      printf("**RF230 Interrupt %u\n\r",rf230interruptflag);
 // }
    rf230interruptflag=0;
  }
#endif
  }

  return 0;
}
Esempio n. 28
0
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc2538_demo_process, ev, data)
{

  PROCESS_EXITHANDLER(broadcast_close(&bc))

  PROCESS_BEGIN();

  counter = 0;
  broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx);
  printf("temp:%u.%u\nhumidity:%u.%u\n",(int)tc,((int)(tc*10))%10 , (int)hc,((int)(hc*10))%10);
  while(1) {
    etimer_set(&et, CLOCK_SECOND*10);

    //ivanm
    // Configure ADC, Internal reference, 512 decimation rate (12bit)
    //
    SOCADCSingleConfigure(SOCADC_12_BIT, SOCADC_REF_INTERNAL);
    //
    // Trigger single conversion on AIN6 (connected to LV_ALS_OUT).
    //
    SOCADCSingleStart(SOCADC_VDD);
    //
    // Wait until conversion is completed
    //
    while(!SOCADCEndOfCOnversionGet())
    {
    }
    //
    // Get data and shift down based on decimation rate
    //
    ui1Dummy = SOCADCDataGet() >> SOCADC_12_BIT_RSHIFT;
    printf("konverzija(ADC) = 0x%08x\n",ui1Dummy);
    PROCESS_YIELD();

    if(ev == PROCESS_EVENT_TIMER) {
      leds_on(LEDS_PERIODIC);
      printf("Counter = 0x%08x\n", counter);
      err = s_measure(&temperature, checksum, TEMP);

             	  			if (err == 0)
             	  			{
             	  				//printf("Temperature (ADC value) = 0x%4x\n", temperature);

             	  				err = s_measure(&humidity, checksum, HUMI);

             	  				if (err == 0)
             	  				{
             	  					//printf("Humidity (ADC value) = 0x%4x\n", humidity);

             	  					//tc=sht11_TemperatureC(temperature);
             	  					//hc=sht11_Humidity(temperature,humidity);
             	  					tc=0;
             	  					hc=0;
             	  					printf("temp:%u.%u\nhumidity:%u.%u\n",(int)tc,((int)(tc*10))%10 , (int)hc,((int)(hc*10))%10);
             	  				}
             	  				else
             	  					printf("SHT11 error - could not read humidity!\n");
             	  			}
             	  			else
             	  				printf("SHT11 error - could not read temperature!\n");

      etimer_set(&et, CLOCK_SECOND);
      rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1,
                 rt_callback, NULL);
    } else if(ev == sensors_event) {
      if(data == &button_select_sensor) {
    	  if (swt==0)
    	  {
    		packetbuf_copyfrom(&temperature, sizeof(temperature));
    	  	broadcast_send(&bc);
        	swt=1;
    	  }
          else
          {
        	packetbuf_copyfrom(&humidity, sizeof(humidity));
    	  	broadcast_send(&bc);
        	swt=0;
          }

      } else if(data == &button_left_sensor || data == &button_right_sensor) {
        leds_toggle(LEDS_BUTTON);
      } else if(data == &button_down_sensor) {
        cpu_cpsid();
        leds_on(LEDS_REBOOT);
        watchdog_reboot();
      } else if(data == &button_up_sensor) {
        sys_ctrl_reset();
      }
    } else if(ev == serial_line_event_message) {
      leds_toggle(LEDS_SERIAL_IN);
    }
    counter++;
    /* put measaruement sht11 here*/

  }

  PROCESS_END();
}
Esempio n. 29
0
/*---------------------------------------------------------------------------*/
static int
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
	    struct rdc_buf_list *buf_list,
            int is_receiver_awake)
{
  rtimer_clock_t t0;
  rtimer_clock_t encounter_time = 0;
  int strobes;
  uint8_t got_strobe_ack = 0;
  int hdrlen, len;
  uint8_t is_broadcast = 0;
  uint8_t is_reliable = 0;
  uint8_t is_known_receiver = 0;
  uint8_t collisions;
  int transmit_len;
  int ret;
  uint8_t contikimac_was_on;
  uint8_t seqno;
#if WITH_CONTIKIMAC_HEADER
  struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */

  /* Exit if RDC and radio were explicitly turned off */
   if(!contikimac_is_on && !contikimac_keep_radio_on) {
    PRINTF("contikimac: radio is turned off\n");
    return MAC_TX_ERR_FATAL;
  }
 
  if(packetbuf_totlen() == 0) {
    PRINTF("contikimac: send_packet data len 0\n");
    return MAC_TX_ERR_FATAL;
  }

#if !NETSTACK_CONF_BRIDGE_MODE
  /* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &rimeaddr_node_addr);
#endif
  if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) {
    is_broadcast = 1;
    PRINTDEBUG("contikimac: send broadcast\n");

    if(broadcast_rate_drop()) {
      return MAC_TX_COLLISION;
    }
  } else {
#if UIP_CONF_IPV6
    PRINTDEBUG("contikimac: send unicast to %02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[2],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[3],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[4],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[5],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[6],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[7]);
#else /* UIP_CONF_IPV6 */
    PRINTDEBUG("contikimac: send unicast to %u.%u\n",
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
               packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]);
#endif /* UIP_CONF_IPV6 */
  }
  is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) ||
    packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);

  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);

#if WITH_CONTIKIMAC_HEADER
  hdrlen = packetbuf_totlen();
  if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) {
    /* Failed to allocate space for contikimac header */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
  chdr = packetbuf_hdrptr();
  chdr->id = CONTIKIMAC_ID;
  chdr->len = hdrlen;
  
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    packetbuf_hdr_remove(sizeof(struct hdr));
    return MAC_TX_ERR_FATAL;
  }
  hdrlen += sizeof(struct hdr);
#else
  /* Create the MAC header for the data packet. */
  hdrlen = NETSTACK_FRAMER.create();
  if(hdrlen < 0) {
    /* Failed to send */
    PRINTF("contikimac: send failed, too large header\n");
    return MAC_TX_ERR_FATAL;
  }
#endif

  /* Make sure that the packet is longer or equal to the shortest
     packet length. */
  transmit_len = packetbuf_totlen();
  if(transmit_len < SHORTEST_PACKET_SIZE) {
    /* Pad with zeroes */
    uint8_t *ptr;
    ptr = packetbuf_dataptr();
    memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen());

    PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen());
    transmit_len = SHORTEST_PACKET_SIZE;
  }


  packetbuf_compact();

#ifdef NETSTACK_ENCRYPT
  NETSTACK_ENCRYPT();
#endif /* NETSTACK_ENCRYPT */

  transmit_len = packetbuf_totlen();

  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);

  /* Remove the MAC-layer header since it will be recreated next time around. */
  packetbuf_hdr_remove(hdrlen);

  if(!is_broadcast && !is_receiver_awake) {
#if WITH_PHASE_OPTIMIZATION
    ret = phase_wait(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                     CYCLE_TIME, GUARD_TIME,
                     mac_callback, mac_callback_ptr, buf_list);
    if(ret == PHASE_DEFERRED) {
      return MAC_TX_DEFERRED;
    }
    if(ret != PHASE_UNKNOWN) {
      is_known_receiver = 1;
    }
#endif /* WITH_PHASE_OPTIMIZATION */ 
  }
  


  /* By setting we_are_sending to one, we ensure that the rtimer
     powercycle interrupt do not interfere with us sending the packet. */
  we_are_sending = 1;

  /* If we have a pending packet in the radio, we should not send now,
     because we will trash the received packet. Instead, we signal
     that we have a collision, which lets the packet be received. This
     packet will be retransmitted later by the MAC protocol
     instread. */
  if(NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet()) {
    we_are_sending = 0;
    PRINTF("contikimac: collision receiving %d, pending %d\n",
           NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
    return MAC_TX_COLLISION;
  }
  
  /* Switch off the radio to ensure that we didn't start sending while
     the radio was doing a channel check. */
  off();


  strobes = 0;

  /* Send a train of strobes until the receiver answers with an ACK. */
  collisions = 0;

  got_strobe_ack = 0;

  /* Set contikimac_is_on to one to allow the on() and off() functions
     to control the radio. We restore the old value of
     contikimac_is_on when we are done. */
  contikimac_was_on = contikimac_is_on;
  contikimac_is_on = 1;

#if !RDC_CONF_HARDWARE_CSMA
    /* Check if there are any transmissions by others. */
    /* TODO: why does this give collisions before sending with the mc1322x? */
  if(is_receiver_awake == 0) {
    int i;
    for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
      t0 = RTIMER_NOW();
      on();
#if CCA_CHECK_TIME > 0
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
#endif
      if(NETSTACK_RADIO.channel_clear() == 0) {
        collisions++;
        off();
        break;
      }
      off();
      t0 = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_SLEEP_TIME)) { }
    }
  }

  if(collisions > 0) {
    we_are_sending = 0;
    off();
    PRINTF("contikimac: collisions before sending\n");
    contikimac_is_on = contikimac_was_on;
    return MAC_TX_COLLISION;
  }
#endif /* RDC_CONF_HARDWARE_CSMA */

#if !RDC_CONF_HARDWARE_ACK
  if(!is_broadcast) {
    /* Turn radio on to receive expected unicast ack.  Not necessary
       with hardware ack detection, and may trigger an unnecessary cca
       or rx cycle */
     on();
  }
#endif

  watchdog_periodic();
  t0 = RTIMER_NOW();
  seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
  for(strobes = 0, collisions = 0;
      got_strobe_ack == 0 && collisions == 0 &&
      RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + STROBE_TIME); strobes++) {

    watchdog_periodic();

    if(!is_broadcast && (is_receiver_awake || is_known_receiver) &&
       !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
      PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
      break;
    }

    len = 0;

    {
      rtimer_clock_t wt;
      rtimer_clock_t txtime;
      int ret;

      txtime = RTIMER_NOW();
      ret = NETSTACK_RADIO.transmit(transmit_len);

#if RDC_CONF_HARDWARE_ACK
     /* For radios that block in the transmit routine and detect the
	ACK in hardware */
      if(ret == RADIO_TX_OK) {
        if(!is_broadcast) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        }
      } else if (ret == RADIO_TX_NOACK) {
      } else if (ret == RADIO_TX_COLLISION) {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
      }
      wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#else /* RDC_CONF_HARDWARE_ACK */
     /* Wait for the ACK packet */
      wt = RTIMER_NOW();
      while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }

      if(!is_broadcast && (NETSTACK_RADIO.receiving_packet() ||
                           NETSTACK_RADIO.pending_packet() ||
                           NETSTACK_RADIO.channel_clear() == 0)) {
        uint8_t ackbuf[ACK_LEN];
        wt = RTIMER_NOW();
        while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }

        len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
        if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
          got_strobe_ack = 1;
          encounter_time = txtime;
          break;
        } else {
          PRINTF("contikimac: collisions while sending\n");
          collisions++;
        }
      }
#endif /* RDC_CONF_HARDWARE_ACK */
    }
  }

  off();

  PRINTF("contikimac: send (strobes=%u, len=%u, %s, %s), done\n", strobes,
         packetbuf_totlen(),
         got_strobe_ack ? "ack" : "no ack",
         collisions ? "collision" : "no collision");

#if CONTIKIMAC_CONF_COMPOWER
  /* Accumulate the power consumption for the packet transmission. */
  compower_accumulate(&current_packet);

  /* Convert the accumulated power consumption for the transmitted
     packet to packet attributes so that the higher levels can keep
     track of the amount of energy spent on transmitting the
     packet. */
  compower_attrconv(&current_packet);

  /* Clear the accumulated power consumption so that it is ready for
     the next packet. */
  compower_clear(&current_packet);
#endif /* CONTIKIMAC_CONF_COMPOWER */

  contikimac_is_on = contikimac_was_on;
  we_are_sending = 0;

  /* Determine the return value that we will return from the
     function. We must pass this value to the phase module before we
     return from the function.  */
  if(collisions > 0) {
    ret = MAC_TX_COLLISION;
  } else if(!is_broadcast && !got_strobe_ack) {
    ret = MAC_TX_NOACK;
  } else {
    ret = MAC_TX_OK;
  }

#if WITH_PHASE_OPTIMIZATION
  if(is_known_receiver && got_strobe_ack) {
    PRINTF("no miss %d wake-ups %d\n",
	   packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
           strobes);
  }

  if(!is_broadcast) {
    if(collisions == 0 && is_receiver_awake == 0) {
      phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
		   encounter_time, ret);
    }
  }
#endif /* WITH_PHASE_OPTIMIZATION */

  return ret;
}
Esempio n. 30
0
/*---------------------------------------------------------------------------*/
static
PT_THREAD(ajax_call(struct httpd_state *s, char *ptr))
{
  static struct timer t;
  static int iter;
  static char buf[128];
  static uint8_t numprinted;
  
  PSOCK_BEGIN(&s->sout);
/*TODO:pick up time from ? parameter */
  timer_set(&t, 2*CLOCK_SECOND);
  iter = 0;
  
  while(1) {
  	iter++;

#if CONTIKI_TARGET_SKY
    SENSORS_ACTIVATE(sht11_sensor);
    SENSORS_ACTIVATE(light_sensor);
    numprinted = snprintf(buf, sizeof(buf),
	     "t(%d);h(%d);l1(%d);l2(%d);",
	     sht11_sensor.value(SHT11_SENSOR_TEMP),
	     sht11_sensor.value(SHT11_SENSOR_HUMIDITY),
         light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC),
         light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR));
    SENSORS_DEACTIVATE(sht11_sensor);
    SENSORS_DEACTIVATE(light_sensor);

#elif CONTIKI_TARGET_MB851
  SENSORS_ACTIVATE(acc_sensor);    
  numprinted = snprintf(buf, sizeof(buf),"t(%d);ax(%d);ay(%d);az(%d);",
	     temperature_sensor.value(0),
	     acc_sensor.value(ACC_X_AXIS),
	     acc_sensor.value(ACC_Y_AXIS),
	     acc_sensor.value(ACC_Z_AXIS));   
  SENSORS_DEACTIVATE(acc_sensor);

#elif CONTIKI_TARGET_REDBEE_ECONOTAG
{	uint8_t c;
	adc_reading[8]=0;
	adc_init();
	while (adc_reading[8]==0) adc_service();
    adc_disable();
    numprinted = snprintf(buf, sizeof(buf),"b(%u);adc(%u,%u,%u,%u,%u,%u,%u,%u);",
        1200*0xfff/adc_reading[8],adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]);
}
		
#elif CONTIKI_TARGET_MINIMAL_NET
static uint16_t c0=0x3ff,c1=0x3ff,c2=0x3ff,c3=0x3ff,c4=0x3ff,c5=0x3ff,c6=0x3ff,c7=0x3ff;
    numprinted = snprintf(buf, sizeof(buf), "t(%d);b(%u);v(%u);",273+(rand()&0x3f),3300-iter/10,iter);
	numprinted += snprintf(buf+numprinted, sizeof(buf)-numprinted,"adc(%u,%u,%u,%u,%u,%u,%u,%u);",c0,c1,c2,c3,c4,c5,c6,c7);
	c0+=(rand()&0xf)-8;
	c1+=(rand()&0xf)-8;
	c2+=(rand()&0xf)-7;
	c3+=(rand()&0x1f)-15;
	c4+=(rand()&0x3)-1;
	c5+=(rand()&0xf)-8;
	c6+=(rand()&0xf)-8;
	c7+=(rand()&0xf)-8;
  if (iter==1) {
    static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('Minimal-net ";
	static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "');";
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax11);
#if WEBSERVER_CONF_PRINTADDR
/* Note address table is filled from the end down */
{int i;
    for (i=0; i<UIP_DS6_ADDR_NB;i++) {
      if (uip_ds6_if.addr_list[i].isused) {
	    numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, buf + numprinted);
	    break;
	  }
    }
}
#endif
	numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax12);
  }

#elif CONTIKI_TARGET_AVR_ATMEGA128RFA1
{ uint8_t i;int16_t tmp,bat;
  BATMON = 16; //give BATMON time to stabilize at highest range and lowest voltage
/* Measure internal temperature sensor, see atmega128rfa1 datasheet */
/* This code disabled by default for safety.
   Selecting an internal reference will short it to anything connected to the AREF pin
 */
#if 1
  ADCSRB|=1<<MUX5;          //this bit buffered till ADMUX written to!
  ADMUX =0xc9;              // Select internal 1.6 volt ref, temperature sensor ADC channel
  ADCSRA=0x85;              //Enable ADC, not free running, interrupt disabled, clock divider 32 (250 KHz@ 8 MHz)
//  while ((ADCSRB&(1<<AVDDOK))==0);  //wait for AVDD ok
//  while ((ADCSRB&(1<<REFOK))==0);  //wait for ref ok 
  ADCSRA|=1<<ADSC;          //Start throwaway conversion
  while (ADCSRA&(1<<ADSC)); //Wait till done
  ADCSRA|=1<<ADSC;          //Start another conversion
  while (ADCSRA&(1<<ADSC)); //Wait till done
  tmp=ADC;                  //Read adc
  tmp=11*tmp-2728+(tmp>>2); //Convert to celcius*10 (should be 11.3*h, approximate with 11.25*h)
  ADCSRA=0;                 //disable ADC
  ADMUX=0;                  //turn off internal vref      
#endif
/* Bandgap can't be measured against supply voltage in this chip. */
/* Use BATMON register instead */
  for ( i=16; i<31; i++) {
    BATMON = i;
    if ((BATMON&(1<<BATMON_OK))==0) break;
  }
  bat=2550-75*16-75+75*i;  //-75 to take the floor of the 75 mv transition window
  static const char httpd_cgi_ajax10[] HTTPD_STRING_ATTR ="t(%u),b(%u);adc(%d,%d,%u,%u,%u,%u,%u,%lu);";
  numprinted = httpd_snprintf(buf, sizeof(buf),httpd_cgi_ajax10,tmp,bat,iter,tmp,bat,sleepcount,OCR2A,0,clock_time(),clock_seconds());
  if (iter==1) {
    static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('128rfa1 [";
	static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "]');";
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax11);
#if WEBSERVER_CONF_PRINTADDR
/* Note address table is filled from the end down */
{int i;
    for (i=0; i<UIP_DS6_ADDR_NB;i++) {
      if (uip_ds6_if.addr_list[i].isused) {
	    numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, buf + numprinted);
	    break;
	  }
    }
}
#endif
	numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax12);
  }
}
#elif CONTIKI_TARGET_AVR_RAVEN
{ int16_t tmp,bat;
#if 1
/* Usual way to get AVR supply voltage, measure 1.1v bandgap using Vcc as reference.
 * This connects the bandgap to the AREF pin, so enable only if there is no external AREF!
 * A capacitor may be connected to this pin to reduce reference noise.
 */
  ADMUX =0x5E;              //Select AVCC as reference, measure 1.1 volt bandgap reference.
  ADCSRA=0x87;              //Enable ADC, not free running, interrupt disabled, clock divider  128 (62 KHz@ 8 MHz)
  ADCSRA|=1<<ADSC;          //Start throwaway conversion
  while (ADCSRA&(1<<ADSC)); //Wait till done
  ADCSRA|=1<<ADSC;          //Start another conversion
  while (ADCSRA&(1<<ADSC)); //Wait till done
//bat=1126400UL/ADC;        //Get supply voltage (factor nominally 1100*1024)
  bat=1198070UL/ADC;        //My Raven
  ADCSRA=0;                 //disable ADC
  ADMUX=0;                  //turn off internal vref
#else
  bat=3300;  
#endif
   
  tmp=420;
  
  static const char httpd_cgi_ajax10[] HTTPD_STRING_ATTR ="t(%u),b(%u);adc(%d,%d,%u,%u,%u,%u,%u,%lu);";
  numprinted = httpd_snprintf(buf, sizeof(buf),httpd_cgi_ajax10,tmp,bat,iter,tmp,bat,sleepcount,OCR2A,0,clock_time(),clock_seconds());
  if (iter<3) {
    static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('Raven [";
	static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "]');";
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax11);
#if WEBSERVER_CONF_PRINTADDR
/* Note address table is filled from the end down */
{int i;
    for (i=0; i<UIP_DS6_ADDR_NB;i++) {
      if (uip_ds6_if.addr_list[i].isused) {
	    numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, buf + numprinted);
	    break;
	  }
    }
}
#endif
	numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax12);
  }
}

//#elif CONTIKI_TARGET_IS_SOMETHING_ELSE
#else
{
  static const char httpd_cgi_ajax10[] HTTPD_STRING_ATTR ="v(%u);";
  numprinted = httpd_snprintf(buf, sizeof(buf),httpd_cgi_ajax10,iter);
  if (iter==1) {
    static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('Contiki Ajax ";
	static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "');";
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax11);
#if WEBSERVER_CONF_PRINTADDR
/* Note address table is filled from the end down */
{int i;
    for (i=0; i<UIP_DS6_ADDR_NB;i++) {
      if (uip_ds6_if.addr_list[i].isused) {
	    numprinted += httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, buf + numprinted);
	    break;
	  }
    }
}
#endif
	numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajax12);
  }
}
#endif
 
#if CONTIKIMAC_CONF_COMPOWER
#include "sys/compower.h"
{
//sl=compower_idle_activity.transmit/RTIMER_ARCH_SECOND;
//sl=compower_idle_activity.listen/RTIMER_ARCH_SECOND;
}
#endif

#if RIMESTATS_CONF_ON

#include "net/rime/rimestats.h"
    static const char httpd_cgi_ajaxr1[] HTTPD_STRING_ATTR ="rime(%lu,%lu,%lu,%lu);";
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajaxr1,
		rimestats.tx,rimestats.rx,rimestats.lltx-rimestats.tx,rimestats.llrx-rimestats.rx);
#endif

#if ENERGEST_CONF_ON
{
#if 1
/* Send on times in percent since last update. Handle 16 bit rtimer wraparound. */
/* Javascript must convert based on platform cpu, tx, rx power, e.g. 20ma*3v3=66mW*(% on time/100) */
	static rtimer_clock_t last_send;
	rtimer_clock_t delta_time;
    static unsigned long last_cpu, last_lpm, last_listen, last_transmit;
    energest_flush();
	delta_time=RTIMER_NOW()-last_send;
	if (RTIMER_CLOCK_LT(RTIMER_NOW(),last_send)) delta_time+=RTIMER_ARCH_SECOND;
	last_send=RTIMER_NOW();
    static const char httpd_cgi_ajaxe1[] HTTPD_STRING_ATTR = "p(%lu,%lu,%lu,%lu);";	
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajaxe1,
	    (100UL*(energest_total_time[ENERGEST_TYPE_CPU].current - last_cpu))/delta_time,
		(100UL*(energest_total_time[ENERGEST_TYPE_LPM].current - last_lpm))/delta_time,
        (100UL*(energest_total_time[ENERGEST_TYPE_TRANSMIT].current - last_transmit))/delta_time,
        (100UL*(energest_total_time[ENERGEST_TYPE_LISTEN].current - last_listen))/delta_time);
    last_cpu = energest_total_time[ENERGEST_TYPE_CPU].current;
    last_lpm = energest_total_time[ENERGEST_TYPE_LPM].current;
    last_transmit = energest_total_time[ENERGEST_TYPE_TRANSMIT].current;
    last_listen = energest_total_time[ENERGEST_TYPE_LISTEN].current;
#endif
#if 1
/* Send cumulative on times in percent*100 */
	uint16_t cpp,txp,rxp;
	uint32_t sl,clockseconds=clock_seconds();
//	energest_flush();
//	sl=((10000UL*energest_total_time[ENERGEST_TYPE_CPU].current)/RTIMER_ARCH_SECOND)/clockseconds;
    sl=energest_total_time[ENERGEST_TYPE_CPU].current/RTIMER_ARCH_SECOND;
    cpp=(10000UL*sl)/clockseconds;
//    txp=((10000UL*energest_total_time[ENERGEST_TYPE_TRANSMIT].current)/RTIMER_ARCH_SECOND)/clockseconds;
    sl=energest_total_time[ENERGEST_TYPE_TRANSMIT].current/RTIMER_ARCH_SECOND;
    txp=(10000UL*sl)/clockseconds;

 //   rxp=((10000UL*energest_total_time[ENERGEST_TYPE_LISTEN].current)/RTIMER_ARCH_SECOND)/clockseconds;
    sl=energest_total_time[ENERGEST_TYPE_LISTEN].current/RTIMER_ARCH_SECOND;
    rxp=(10000UL*sl)/clockseconds;

    static const char httpd_cgi_ajaxe2[] HTTPD_STRING_ATTR = "ener(%u,%u,%u);";	
    numprinted += httpd_snprintf(buf+numprinted, sizeof(buf)-numprinted,httpd_cgi_ajaxe2,cpp,txp,rxp);
#endif
}
#endif /* ENERGEST_CONF_ON */
 
    PSOCK_SEND_STR(&s->sout, buf);
    timer_restart(&t);
	PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t));
}
  PSOCK_END(&s->sout);
}