diff --git a/platform/avr-ravenusb/contiki-raven-main.c b/platform/avr-ravenusb/contiki-raven-main.c index 4a6bb7401..9884a13da 100644 --- a/platform/avr-ravenusb/contiki-raven-main.c +++ b/platform/avr-ravenusb/contiki-raven-main.c @@ -42,9 +42,9 @@ #define DEBUG 0 #if DEBUG -#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) #else -#define PRINTF(...) +#define PRINTD(...) #endif #include @@ -67,6 +67,13 @@ /* Set ANNOUNCE to send boot messages to USB or RS232 serial port */ #define ANNOUNCE 1 +/* But only if a serial port exists */ +#if USB_CONF_SERIAL||USB_CONF_RS232 +#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) +#endif + #include "usb_task.h" #if USB_CONF_SERIAL #include "cdc_task.h" @@ -101,11 +108,13 @@ rimeaddr_t macLongAddr; #include "ieee-15-4-manager.h" #endif /* RF230BB */ -/* Test rtimers, also useful for pings and time stamps in simulator */ +/* Test rtimers, also useful for pings, time stamps, routes, stack monitor */ #define TESTRTIMER 0 #if TESTRTIMER #define PINGS 0 -#define STAMPS 30 +#define STAMPS 60 +#define ROUTES 120 +#define STACKMONITOR 600 uint8_t rtimerflag=1; uint16_t rtime; struct rtimer rt; @@ -116,6 +125,7 @@ void rtimercycle(void) {rtimerflag=1;} /*---------------------------------------------------------------------------*/ /*--------------------------------- RPL ----------------------------------*/ /*---------------------------------------------------------------------------*/ +/* TODO: Put rpl code into another file, once it stabilizes */ /* Set up fallback interface links to direct stack tcpip output to ethernet */ static void init(void) @@ -126,12 +136,11 @@ static void output(void) { // if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) { - /* Do not bounce packets back over SLIP if the packet was received - over SLIP */ -// PRINTF("slip-bridge: Destination off-link but no route\n"); + /* Do not bounce packets back over USB if the packet was received from USB */ +// PRINTA("JACKDAW router: Destination off-link but no route\n"); // } else { - PRINTF("SUT: %u\n", uip_len); - mac_LowpanToEthernet(); + PRINTD("SUT: %u\n", uip_len); + mac_LowpanToEthernet(); //bounceback trap is done in lowpanToEthernet // } } const struct uip_fallback_interface rpl_interface = { @@ -157,11 +166,12 @@ PROCESS_THREAD(border_router_process, ev, data) memcpy_P(buf,dag_id,sizeof(dag_id)); dag = rpl_set_root((uip_ip6addr_t *)buf); -/* Assign bbbb::200 to the uip stack, and bbbb::1 to the host network interface, e.g. $ip -6 address add bbbb::1/64 dev usb0 */ -/* Note the jackdaw uip stack will get packets intended for usb if they have the same address! */ +/* Assign separate addresses to the jackdaw uip stack and the host network interface, but with the same prefix */ +/* E.g. bbbb::200 to the jackdaw and bbbb::1 to the host network interface with $ip -6 address add bbbb::1/64 dev usb0 */ +/* Otherwise the host will trap packets intended for the jackdaw, just as the jackdaw will trap RF packets intended for the host */ /* $ifconfig usb0 -arp on Ubuntu to skip the neighbor solicitations. Add explicit neighbors on other OSs */ if(dag != NULL) { - PRINTF("created a new RPL dag\n"); + PRINTD("created a new RPL dag\n"); #if UIP_CONF_ROUTER_RECEIVE_RA //Contiki stack will shut down until assigned an address from the interface RA @@ -181,6 +191,7 @@ PROCESS_THREAD(border_router_process, ev, data) while(1) { PROCESS_YIELD(); + /* Local and global dag repair can be done from the jackdaw menu */ // rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64); // rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); @@ -194,74 +205,47 @@ PROCESS_THREAD(border_router_process, ev, data) /*-------------------------------------------------------------------------*/ /*----------------------Configuration of the .elf file---------------------*/ -typedef struct {unsigned char B2;unsigned char B1;unsigned char B0;} __signature_t; +#if 1 +/* The proper way to set the signature is */ +#include +#else +/* Older avr-gcc's may not define the needed SIGNATURE bytes. Do it manually if you get an error */ +typedef struct {const unsigned char B2;const unsigned char B1;const unsigned char B0;} __signature_t; #define SIGNATURE __signature_t __signature __attribute__((section (".signature"))) SIGNATURE = { -/* Older AVR-GCCs may not define the SIGNATURE_n bytes so use explicit values */ .B2 = 0x82,//SIGNATURE_2, //AT90USB128x .B1 = 0x97,//SIGNATURE_1, //128KB flash .B0 = 0x1E,//SIGNATURE_0, //Atmel }; +#endif + FUSES ={.low = 0xde, .high = 0x99, .extended = 0xff,}; -/* Put default MAC address in EEPROM */ -#if !JACKDAW_CONF_USE_SETTINGS -uint8_t mac_address[8] EEMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16}; -#endif - -static uint8_t get_channel_from_eeprom() { -#if JACKDAW_CONF_USE_SETTINGS - uint8_t chan = settings_get_uint8(SETTINGS_KEY_CHANNEL, 0); - if(!chan) - chan = RF_CHANNEL; - return chan; -#else - uint8_t eeprom_channel; - uint8_t eeprom_check; - - eeprom_channel = eeprom_read_byte((uint8_t *)9); - eeprom_check = eeprom_read_byte((uint8_t *)10); - - if(eeprom_channel==~eeprom_check) - return eeprom_channel; - +/* Save the default settings into program flash memory */ +uint8_t default_mac_address[8] PROGMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16}; #ifdef CHANNEL_802_15_4 - return(CHANNEL_802_15_4); +uint8_t default_channel PROGMEM = CHANNEL_802_15_4; #else - return 26; -#endif - +uint8_t default_channel PROGMEM = 26; #endif - -} - -static bool -get_eui64_from_eeprom(uint8_t macptr[8]) { -#if JACKDAW_CONF_USE_SETTINGS - size_t size = 8; - - if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)macptr, &size)==SETTINGS_STATUS_OK) - return true; - - // Fallback to reading the traditional mac address - eeprom_read_block ((void *)macptr, 0, 8); +#ifdef IEEE802154_PANID +uint16_t default_panid PROGMEM = IEEE802154_PANID; #else - eeprom_read_block ((void *)macptr, &mac_address, 8); +uint16_t default_panid PROGMEM = 0xABCD; +#endif +#ifdef IEEE802154_PANADDR +uint16_t default_panaddr PROGMEM = IEEE802154_PANID; +#else +uint16_t default_panaddr PROGMEM = 0; +#endif +#ifdef RF230_MAX_TX_POWER +uint8_t default_txpower PROGMEM = RF230_MAX_TX_POWER; +#else +uint8_t default_txpower PROGMEM = 0; #endif - return macptr[0]!=0xFF; -} #if JACKDAW_CONF_RANDOM_MAC -static bool -set_eui64_to_eeprom(const uint8_t macptr[8]) { -#if JACKDAW_CONF_USE_SETTINGS - return settings_set(SETTINGS_KEY_EUI64, macptr, 8)==SETTINGS_STATUS_OK; -#else - eeprom_write_block((void *)macptr, &mac_address, 8); - return true; -#endif -} - +#include "rng.h" static void generate_new_eui64(uint8_t eui64[8]) { eui64[0] = 0x02; @@ -275,33 +259,141 @@ generate_new_eui64(uint8_t eui64[8]) { } #endif /* JACKDAW_CONF_RANDOM_MAC */ -static uint16_t -get_panid_from_eeprom(void) { -#if JACKDAW_CONF_USE_SETTINGS - uint16_t x = settings_get_uint16(SETTINGS_KEY_PAN_ID, 0); - if(!x) - x = IEEE802154_PANID; +#if !JACKDAW_CONF_USE_SETTINGS +/****************************No settings manager*****************************/ +/* If not using the settings manager, put the default values into EEMEM + * These can be manually changed and kept over program reflash. + * The channel and bit complement are used to check EEMEM integrity, + * If corrupt all values will be rewritten with the default flash values. + * To make this work, get the channel before anything else. + */ + +uint8_t eemem_mac_address[8] EEMEM = {0x02, 0x12, 0x13, 0xff, 0xfe, 0x14, 0x15, 0x16}; +#ifdef CHANNEL_802_15_4 +uint8_t eemem_channel[2] EEMEM = {CHANNEL_802_15_4, ~CHANNEL_802_15_4}; +#else +uint8_t eemem_channel[2] EMEM = {26, ~26}; +#endif +#ifdef IEEE802154_PANID +uint16_t eemem_panid EEMEM = IEEE802154_PANID; +#else +uint16_t eemem_panid EEMEM = 0xABCD; +#endif +#ifdef IEEE802154_PANADDR +uint16_t eemem_panaddr EEMEM = IEEE802154_PANID; +#else +uint16_t eemem_panaddr EEMEM = 0; +#endif +#ifdef RF230_MAX_TX_POWER +uint8_t eemem_txpower EEMEM = RF230_MAX_TX_POWER; +#else +uint8_t eemem_txpower EEMEM = 0; +#endif +static uint8_t get_channel_from_eeprom() { + uint8_t x[2]; + *(uint16_t *)x = eeprom_read_word ((uint16_t *)&eemem_channel); + if((uint8_t)x[0]!=(uint8_t)~x[1]) {//~x[1] can promote comparison to 16 bit +/* Verification fails, rewrite everything */ + uint8_t mac[8]; +#if JACKDAW_CONF_RANDOM_MAC + PRINTA("Generating random MAC address.\n"); + generate_new_eui64(&mac); +#else + {uint8_t i; for (i=0;i<8;i++) mac[i] = pgm_read_byte_near(default_mac_address+i);} +#endif + eeprom_write_block(&mac, &eemem_mac_address, 8); + eeprom_write_word(&eemem_panid , pgm_read_word_near(&default_panid)); + eeprom_write_word(&eemem_panaddr, pgm_read_word_near(&default_panaddr)); + eeprom_write_byte(&eemem_txpower, pgm_read_byte_near(&default_txpower)); + x[0] = pgm_read_byte_near(&default_channel); + x[1]= ~x[0]; + eeprom_write_word((uint16_t *)&eemem_channel, *(uint16_t *)x); + } + return x[0]; +} +static bool get_eui64_from_eeprom(uint8_t macptr[8]) { + eeprom_read_block ((void *)macptr, &eemem_mac_address, 8); + return macptr[0]!=0xFF; +} +static uint16_t get_panid_from_eeprom(void) { + return eeprom_read_word(&eemem_panid); +} +static uint16_t get_panaddr_from_eeprom(void) { + return eeprom_read_word (&eemem_panaddr); +} +static uint8_t get_txpower_from_eeprom(void) +{ + return eeprom_read_byte(&eemem_txpower); +} + +#else /* !JACKDAW_CONF_USE_SETTINGS */ +/******************************Settings manager******************************/ +static uint8_t get_channel_from_eeprom() { + uint8_t x = settings_get_uint8(SETTINGS_KEY_CHANNEL, 0); + if(!x) x = pgm_read_byte_near(&default_channel); return x; -#else - // TODO: Writeme! - return IEEE802154_PANID; -#endif } - -static uint16_t -get_panaddr_from_eeprom(void) { -#if JACKDAW_CONF_USE_SETTINGS - return settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0); +static bool get_eui64_from_eeprom(uint8_t macptr[8]) { + size_t size = 8; + if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)macptr, &size)==SETTINGS_STATUS_OK) { + PRINTD("<=Get EEPROM MAC address.\n"); + return true; + } +#if JACKDAW_CONF_RANDOM_MAC + PRINTA("--Generating random MAC address.\n"); + generate_new_eui64(macptr); #else - // TODO: Writeme! - return 0; + {uint8_t i;for (i=0;i<8;i++) macptr[i] = pgm_read_byte_near(default_mac_address+i);} #endif + settings_add(SETTINGS_KEY_EUI64,(unsigned char*)macptr,8); + PRINTA("->Set EEPROM MAC address.\n"); + return true; } - +static uint16_t get_panid_from_eeprom(void) { + uint16_t x; + if (settings_check(SETTINGS_KEY_PAN_ID,0)) { + x = settings_get_uint16(SETTINGS_KEY_PAN_ID,0); + PRINTD("<-Get EEPROM PAN ID of %04x.\n",x); + } else { + x=pgm_read_word_near(&default_panid); + if (settings_add_uint16(SETTINGS_KEY_PAN_ID,x)==SETTINGS_STATUS_OK) { + PRINTA("->Set EEPROM PAN ID to %04x.\n",x); + } + } + return x; +} +static uint16_t get_panaddr_from_eeprom(void) { + uint16_t x; + if (settings_check(SETTINGS_KEY_PAN_ADDR,0)) { + x = settings_get_uint16(SETTINGS_KEY_PAN_ADDR,0); + PRINTD("<-Get EEPROM PAN address of %04x.\n",x); + } else { + x=pgm_read_word_near(&default_panaddr); + if (settings_add_uint16(SETTINGS_KEY_PAN_ADDR,x)==SETTINGS_STATUS_OK) { + PRINTA("->Set EEPROM PAN address to %04x.\n",x); + } + } + return x; +} +static uint8_t get_txpower_from_eeprom(void) { + uint8_t x; + if (settings_check(SETTINGS_KEY_TXPOWER,0)) { + x = settings_get_uint8(SETTINGS_KEY_TXPOWER,0); + PRINTD("<-Get EEPROM tx power of %d. (0=max)\n",x); + } else { + x=pgm_read_byte_near(&default_txpower); + if (settings_add_uint8(SETTINGS_KEY_TXPOWER,x)==SETTINGS_STATUS_OK) { + PRINTA("->Set EEPROM tx power of %d. (0=max)\n",x); + } + } + return x; +} +#endif /* !JACKDAW_CONF_USE_SETTINGS */ /*-------------------------------------------------------------------------*/ /*-----------------------------Low level initialization--------------------*/ static void initialize(void) { + watchdog_init(); watchdog_start(); @@ -315,7 +407,7 @@ uint16_t p=(uint16_t)&__bss_end; do { *(uint16_t *)p = 0x4242; p+=100; - } while (pnext)) { - printf_P(PSTR("Process=%p Thread=%p Name=\"%s\" \n"),p,p->thread,p->name); + PRINTA("Process=%p Thread=%p Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p)); } } #endif + while(1) { process_run(); @@ -512,57 +590,118 @@ main(void) #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); + 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 - if (rtimerflag) { //8 seconds is maximum interval, my jackdaw 4% slow +/* 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) { - printf("%us ",rtime); - } +if ((rtime%STAMPS)==0) { + PRINTA("%us ",rtime); + if (rtime%STAMPS*10) PRINTA("\n"); +} #endif rtime+=1; -#if PINGS - if ((rtime%PINGS)==0) { - PRINTF("**Ping\n"); - pingsomebody(); - } + +#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_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; + PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); + for (i=0;i"); + PRINTA("\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) { + uip_debug_ipaddr_print(&uip_ds6_routing_table[i].ipaddr); + PRINTA("/%u (via ", uip_ds6_routing_table[i].length); + uip_debug_ipaddr_print(&uip_ds6_routing_table[i].nexthop); + // if(uip_ds6_routing_table[i].state.lifetime < 600) { + PRINTA(") %lus\n", uip_ds6_routing_table[i].state.lifetime); + // } else { + // PRINTA(")\n"); + // } + j=0; + } + } + if (j) PRINTA(" "); + 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