/*---------------------------------------------------------------------------*/ 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 */ }
/*---------------------------------------------------------------------------*/ 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(); }
/** * \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); }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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); } }
/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------------------------------------------------*/ 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); }
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(); }
/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------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; }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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(); } }
/*---------------------------------------------------------------------------*/ rtimer_clock_t timesynch_time(void) { return RTIMER_NOW() + offset; }
/*---------------------------------------------------------------------------*/ 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(¤t_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(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_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; } }
/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------------------------------------------------*/ 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(¤t_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(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_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); }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ 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; }
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; }
/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------------------------------------------------*/ 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(¤t_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(¤t_packet); /* Clear the accumulated power consumption so that it is ready for the next packet. */ compower_clear(¤t_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; }
/*---------------------------------------------------------------------------*/ 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); }