diff --git a/Makefile.include b/Makefile.include index d427d8c6b..cf2d67d2c 100644 --- a/Makefile.include +++ b/Makefile.include @@ -107,11 +107,8 @@ PROJECT_OBJECTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(PROJECT_SOURCEFI ifdef APPS APPDIRS += ${wildcard ${addprefix $(CONTIKI)/apps/, $(APPS)} \ ${addprefix $(CONTIKI)/platform/$(TARGET)/apps/, $(APPS)} \ - ${addprefix , $(APPS)}} - APPINCLUDES = ${foreach APP, $(APPS), ${wildcard ${foreach DIR, $(APPDIRS), $(DIR)/Makefile.$(APP)} \ - $(CONTIKI)/apps/$(APP)/Makefile.$(APP) \ - $(CONTIKI)/platform/$(TARGET)/apps/$(APP)/Makefile.$(APP) \ - $(APP)/Makefile.$(APP)}} + $(APPS)} + APPINCLUDES = ${foreach APP, $(APPS), ${wildcard ${foreach DIR, $(APPDIRS), $(DIR)/Makefile.$(APP)}}} -include $(APPINCLUDES) APP_SOURCES = ${foreach APP, $(APPS), $($(APP)_src)} DSC_SOURCES = ${foreach APP, $(APPS), $($(APP)_dsc)} diff --git a/apps/erbium/erbium.h b/apps/erbium/erbium.h index 1c29ab125..7e491c3f8 100644 --- a/apps/erbium/erbium.h +++ b/apps/erbium/erbium.h @@ -256,6 +256,13 @@ typedef struct periodic_resource_s periodic_resource_t; void name##_handler(void *, void *, uint8_t *, uint16_t, int32_t *); \ resource_t resource_##name = {NULL, flags, url, attributes, name##_handler, NULL, NULL, NULL} +/* + * Macro to define a sub-resource + * Make sure to define its parent resource beforehand and set 'parent' to that name. + */ +#define SUB_RESOURCE(name, flags, url, attributes, parent) \ +resource_t resource_##name = {NULL, flags, url, attributes, parent##_handler, NULL, NULL, NULL} + /* * Macro to define an event resource * Like periodic resources, event resources have a post_handler that manages a subscriber list. diff --git a/apps/webserver-nano/httpd-cgi.c b/apps/webserver-nano/httpd-cgi.c index ba36461e1..7d73adcbc 100644 --- a/apps/webserver-nano/httpd-cgi.c +++ b/apps/webserver-nano/httpd-cgi.c @@ -555,6 +555,11 @@ PT_THREAD(neighbors(struct httpd_state *s, char *ptr)) #if WEBSERVER_CONF_ROUTES extern uip_ds6_route_t uip_ds6_routing_table[]; +#if WEBSERVER_CONF_ROUTE_LINKS +static const char httpd_cgi_rtesl1[] HTTPD_STRING_ATTR = " (uip_mss() - 200)) { s->savei=i;s->savej=j; return numprinted; @@ -607,7 +609,40 @@ static const char httpd_cgi_rtesl3[] HTTPD_STRING_ATTR = ""; numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_addrf); } #endif +{ + static const char httpd_cgi_defr1[] HTTPD_STRING_ATTR = "\nRPL Parent\n"; + static const char httpd_cgi_defr2[] HTTPD_STRING_ATTR = " (%u sec)\n"; +#if 0 + uip_ip6addr_t *nexthop = uip_ds6_defrt_choose(); + if (nexthop) { + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_defr1); + numprinted += httpd_cgi_sprint_ip6(*nexthop, uip_appdata + numprinted); + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_defr2,nexthop->lifetime.start+nexthop->lifetime.interval-clock_seconds()); + } +#else +uip_ds6_defrt_t *locdefrt; +extern uip_ds6_defrt_t uip_ds6_defrt_list[UIP_DS6_DEFRT_NB]; + for(locdefrt = uip_ds6_defrt_list; + locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) { + if(locdefrt->isused) { + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_defr1); +#if WEBSERVER_CONF_ROUTE_LINKS && 0 + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtesl1); + numprinted += httpd_cgi_sprint_ip6(locdefrt->ipaddr, uip_appdata + numprinted); + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtesl2); + numprinted += httpd_cgi_sprint_ip6(locdefrt->ipaddr, uip_appdata + numprinted); + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtesl3); +#else + numprinted += httpd_cgi_sprint_ip6(locdefrt->ipaddr, uip_appdata + numprinted); +#endif + numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_defr2,locdefrt->lifetime.start+locdefrt->lifetime.interval-clock_seconds()); + // break; + } + } + +#endif +} /* Signal that this was the last segment */ s->savei = 0; return numprinted; @@ -717,8 +752,6 @@ uint8_t c; adc_disable(); #endif - snprintf(sensor_extvoltage, sizeof(sensor_extvoltage),"%u mV",1200*0xfff/adc_reading[8]); - static const char httpd_cgi_sensorv[] HTTPD_STRING_ATTR = "ADC chans : %u %u %u %u %u %u %u %u \n"; numprinted+=httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_sensorv, adc_reading[0],adc_reading[1],adc_reading[2],adc_reading[3],adc_reading[4],adc_reading[5],adc_reading[6],adc_reading[7]); @@ -770,7 +803,7 @@ generate_stats(void *arg) uint32_t seconds=clock_seconds(); static const char httpd_cgi_stats[] HTTPD_STRING_ATTR = "\nStatistics\n"; - numprinted=httpd_snprintf((char *)uip_appdata + numprinted, uip_mss() - numprinted, httpd_cgi_stats); + numprinted=httpd_snprintf((char *)uip_appdata, uip_mss(), httpd_cgi_stats); #if ENERGEST_CONF_ON {uint8_t p1,p2; @@ -1024,10 +1057,27 @@ PT_THREAD(ajax_call(struct httpd_state *s, char *ptr)) static int iter; static char buf[128]; static uint8_t numprinted; - + uint16_t dt; PSOCK_BEGIN(&s->sout); -/*TODO:pick up time from ? parameter */ - timer_set(&t, 2*CLOCK_SECOND); + +#if WEBSERVER_CONF_PASSQUERY +/* Get update time from ? string, if present */ +{ + uint8_t i;uint16_t dt=0; + for (i=0;i '9') break; + dt = dt*10 + httpd_query[i]-'0'; + } + if (dt < 1) dt = 1; + // printf("dt %u\n",dt); + timer_set(&t, dt*CLOCK_SECOND); + httpd_query[i]=0; //necessary? + if (dt > WEBSERVER_CONF_TIMEOUT/2) s->ajax_timeout = 2*dt; else s->ajax_timeout = WEBSERVER_CONF_TIMEOUT; +} +#else + timer_set(&t, 2*CLOCK_SECOND); +#endif + iter = 0; while(1) { @@ -1064,7 +1114,8 @@ PT_THREAD(ajax_call(struct httpd_state *s, char *ptr)) adc_disable(); #endif -#if 0 + +#if 1 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]); #else @@ -1074,14 +1125,14 @@ PT_THREAD(ajax_call(struct httpd_state *s, char *ptr)) } if (iter<3) { static const char httpd_cgi_ajax11[] HTTPD_STRING_ATTR = "wt('Econtag ["; - static const char httpd_cgi_ajax12[] HTTPD_STRING_ATTR = "]');"; + 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; isout, buf); + /* Can do fixed intervals or fixed starting points */ +#if FIXED_INTERVALS timer_restart(&t); - PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t)); + PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t)); +#else + PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t)); + timer_reset(&t); +#endif } PSOCK_END(&s->sout); } diff --git a/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.js b/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.js index eb487ac5a..cdd7cebc7 100644 --- a/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.js +++ b/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.js @@ -3,6 +3,7 @@ function e(el){return document.getElementById(el);} function ls(){try{r=new XMLHttpRequest();}catch(e){alert("Browswer does not support Ajax");return false;}r.open("GET","/ajaxdata.shtml",true); x=0;r.onreadystatechange=function(){e('date').innerHTML=(new Date()).toTimeString();if(r.readyState>0){j=r.responseText.substr(x);x+=j.length;eval(j);}};r.send(null);} +function tb(x){var t=e('ss');if(x||t.value=="RUN"){t.value="STOP";ls();}else{t.value="RUN";r.abort();}} function s(el,n,max,text){e(el).innerHTML=''+''+''+''+'
'+text+'  
';} function wt(m){document.title=m;e('v').innerHTML=m;} function dc(n,d){return n.toFixed(d);} @@ -12,7 +13,7 @@ function ax(m){s('ax',m+2000,4000,'Acceleration (X-axis) '+m+'mg');} function ay(m){s('ay',m+2000,4000,'Acceleration (Y-axis) '+m+'mg');} function az(m){s('az',m+2000,4000,'Acceleration (Z-axis) '+m+'mg');} function rs(m){s('rs',n,100,'RSSI '+n);} -function p(c,l,t,r){cp=0.136*c;lt=0.478*t;lr=0.412*r;n=cp+lt+lr;//128rfa1@3v3 +function p(c,l,t,r){cp=0.00109*c;lt=0.00848*t;lr=0.00617*r;n=cp+lt+lr;//mc1322x s('p',n,200,'Power consumption '+dc(n,2)+' mW'); s('pc',cp,100,'CPU power '+dc(cp,2)+' mW'); s('pr',lr,200,'Radio RX power '+dc(lr,2)+' mW'); diff --git a/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.shtml b/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.shtml index ed119783c..455ba3c5e 100644 --- a/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.shtml +++ b/apps/webserver-nano/httpd-fs/makefsdata.ignore/ajax.shtml @@ -1,6 +1,8 @@ %! header %!: /ajax.js -
+ +Interval seconds
+

Sensors

diff --git a/apps/webserver-nano/httpd-fs/makefsdata.ignore/status.shtml b/apps/webserver-nano/httpd-fs/makefsdata.ignore/status.shtml index b6574fbcb..501203f0f 100644 --- a/apps/webserver-nano/httpd-fs/makefsdata.ignore/status.shtml +++ b/apps/webserver-nano/httpd-fs/makefsdata.ignore/status.shtml @@ -1,10 +1,14 @@ %! header -

Addresses

+
Addresses
 %! addresses
-

Neighbors

+ +Neighbors %! neighbors -

Routes

+ +Routes %! routes -

Sensors

+ +Sensors %! sensors -%! file-stats . +
+%! file-stats . \ No newline at end of file diff --git a/apps/webserver-nano/httpd-fs/status.shtml b/apps/webserver-nano/httpd-fs/status.shtml index d18b74e28..501203f0f 100644 --- a/apps/webserver-nano/httpd-fs/status.shtml +++ b/apps/webserver-nano/httpd-fs/status.shtml @@ -1,10 +1,14 @@ %! header -

Addresses
+

Addresses
 %! addresses
-

Neighbors
+ +Neighbors %! neighbors -

Routes
+ +Routes %! routes -

Sensors
+ +Sensors %! sensors -%! file-stats . +

+%! file-stats . \ No newline at end of file diff --git a/apps/webserver-nano/httpd.c b/apps/webserver-nano/httpd.c index 7971832b8..234b76bb3 100644 --- a/apps/webserver-nano/httpd.c +++ b/apps/webserver-nano/httpd.c @@ -94,7 +94,6 @@ static PT_THREAD(send_file(struct httpd_state *s)) { PSOCK_BEGIN(&s->sout); - do { PSOCK_GENERATOR_SEND(&s->sout, generate, s); s->file.len -= s->len; @@ -488,11 +487,18 @@ httpd_appcall(void *state) PT_INIT(&s->outputpt); s->state = STATE_WAITING; s->timer = 0; +#if WEBSERVER_CONF_AJAX + s->ajax_timeout = WEBSERVER_CONF_TIMEOUT; +#endif handle_connection(s); } else if(s != NULL) { if(uip_poll()) { ++s->timer; - if(s->timer >= 20) { +#if WEBSERVER_CONF_AJAX + if(s->timer >= s->ajax_timeout) { +#else + if(s->timer >= WEBSERVER_CONF_TIMEOUT) { +#endif uip_abort(); memb_free(&conns, s); } diff --git a/apps/webserver-nano/httpd.h b/apps/webserver-nano/httpd.h index 3226a79b4..d10d389ef 100644 --- a/apps/webserver-nano/httpd.h +++ b/apps/webserver-nano/httpd.h @@ -76,6 +76,8 @@ #define WEBSERVER_CONF_CONNS 2 #define WEBSERVER_CONF_NAMESIZE 16 #define WEBSERVER_CONF_BUFSIZE 40 +/* Short tcp timeouts allow new connections sooner */ +#define WEBSERVER_CONF_TIMEOUT 20 /* Allow include in .shtml pages, e.g. %!: /header.html */ #define WEBSERVER_CONF_INCLUDE 1 /* Allow cgi in .shtml pages, e.g. %! file-stats . */ @@ -116,13 +118,13 @@ extern char httpd_query[WEBSERVER_CONF_PASSQUERY]; #define WEBSERVER_CONF_LOG 0 /* Include referrer in log */ #define WEBSERVER_CONF_REFERER 0 - /*-----------------------------------------------------------------------------*/ #elif WEBSERVER_CONF_NANO==2 /* webserver-mini having more content */ #define WEBSERVER_CONF_CONNS 2 #define WEBSERVER_CONF_NAMESIZE 20 #define WEBSERVER_CONF_BUFSIZE 40 +#define WEBSERVER_CONF_TIMEOUT 20 /* Allow include in .shtml pages, e.g. %!: /header.html */ #define WEBSERVER_CONF_INCLUDE 1 /* Allow cgi in .shtml pages, e.g. %! file-stats . */ @@ -148,7 +150,7 @@ extern char httpd_query[WEBSERVER_CONF_PASSQUERY]; //#define WEBSERVER_CONF_TICTACTOE 1 //Needs passquery of at least 10 chars #define WEBSERVER_CONF_AJAX 1 #define WEBSERVER_CONF_SHOW_ROOM 0 -//#define WEBSERVER_CONF_PASSQUERY 10 +#define WEBSERVER_CONF_PASSQUERY 10 #if WEBSERVER_CONF_PASSQUERY extern char httpd_query[WEBSERVER_CONF_PASSQUERY]; #endif @@ -171,6 +173,7 @@ extern char httpd_query[WEBSERVER_CONF_PASSQUERY]; #define WEBSERVER_CONF_CONNS 6 #define WEBSERVER_CONF_NAMESIZE 20 #define WEBSERVER_CONF_BUFSIZE 40 +#define WEBSERVER_CONF_TIMEOUT 20 /* Allow include in .shtml pages, e.g. %!: /header.html */ #define WEBSERVER_CONF_INCLUDE 1 /* Allow cgi in .shtml pages, e.g. %! file-stats . */ @@ -285,6 +288,9 @@ struct httpd_state { #if WEBSERVER_CONF_LOADTIME clock_time_t pagetime; #endif +#if WEBSERVER_CONF_AJAX + uint16_t ajax_timeout; +#endif #if WEBSERVER_CONF_NEIGHBORS || WEBSERVER_CONF_ROUTES uint8_t starti,savei,startj,savej; #endif diff --git a/core/net/mac/contikimac.c b/core/net/mac/contikimac.c index 81640793e..d9c83e118 100644 --- a/core/net/mac/contikimac.c +++ b/core/net/mac/contikimac.c @@ -358,11 +358,14 @@ powercycle_turn_radio_on(void) 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 -static volatile rtimer_clock_t sync_cycle_start; -static volatile uint8_t sync_cycle_phase; sync_cycle_start = RTIMER_NOW(); #else cycle_start = RTIMER_NOW(); diff --git a/core/net/sicslowpan.c b/core/net/sicslowpan.c index 432c6831f..cfc11f943 100644 --- a/core/net/sicslowpan.c +++ b/core/net/sicslowpan.c @@ -179,9 +179,6 @@ void uip_log(char *msg); /** \name General variables * @{ */ -/** A pointer to the mac driver */ -const struct mac_driver *sicslowpan_mac; - #ifdef SICSLOWPAN_NH_COMPRESSOR /** A pointer to the additional compressor */ extern struct sicslowpan_nh_compressor SICSLOWPAN_NH_COMPRESSOR; @@ -1766,9 +1763,6 @@ input(void) void sicslowpan_init(void) { - /* remember the mac driver */ - sicslowpan_mac = &NETSTACK_MAC; - /* * Set out output function as the function to be called from uIP to * send a packet. diff --git a/core/net/sicslowpan.h b/core/net/sicslowpan.h index 2af071edf..c79ed2803 100644 --- a/core/net/sicslowpan.h +++ b/core/net/sicslowpan.h @@ -321,6 +321,5 @@ struct sicslowpan_nh_compressor { extern const struct network_driver sicslowpan_driver; -extern const struct mac_driver *sicslowpan_mac; #endif /* __SICSLOWPAN_H__ */ /** @} */ diff --git a/core/net/uip-nd6.c b/core/net/uip-nd6.c index 985703a8d..a52962aef 100644 --- a/core/net/uip-nd6.c +++ b/core/net/uip-nd6.c @@ -145,6 +145,7 @@ create_llao(uint8_t *llao, uint8_t type) { void uip_nd6_ns_input(void) { + uint8_t flags; PRINTF("Received NS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); @@ -154,8 +155,6 @@ uip_nd6_ns_input(void) PRINTF("\n"); UIP_STAT(++uip_stat.nd6.recv); - uint8_t flags; - #if UIP_CONF_IPV6_CHECKS if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) || (uip_is_addr_mcast(&UIP_ND6_NS_BUF->tgtipaddr)) || @@ -390,6 +389,11 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) void uip_nd6_na_input(void) { + uint8_t is_llchange; + uint8_t is_router; + uint8_t is_solicited; + uint8_t is_override; + PRINTF("Received NA from"); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("to"); @@ -403,11 +407,11 @@ uip_nd6_na_input(void) * booleans. the three last one are not 0 or 1 but 0 or 0x80, 0x40, 0x20 * but it works. Be careful though, do not use tests such as is_router == 1 */ - uint8_t is_llchange = 0; - uint8_t is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER)); - uint8_t is_solicited = + is_llchange = 0; + is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER)); + is_solicited = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED)); - uint8_t is_override = + is_override = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE)); #if UIP_CONF_IPV6_CHECKS diff --git a/examples/ipv6/native-border-router/border-router-rdc.c b/examples/ipv6/native-border-router/border-router-rdc.c index 5e4540714..78699122f 100644 --- a/examples/ipv6/native-border-router/border-router-rdc.c +++ b/examples/ipv6/native-border-router/border-router-rdc.c @@ -117,8 +117,10 @@ send_packet(mac_callback_t sent, void *ptr) } else { /* here we send the data over SLIP to the radio-chip */ - + size = 0; +#if SERIALIZE_ATTRIBUTES size = packetutils_serialize_atts(&buf[3], sizeof(buf) - 3); +#endif if(size < 0 || size + packetbuf_totlen() + 3 > sizeof(buf)) { PRINTF("br-rdc: send failed, too large header\n"); mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); diff --git a/examples/ipv6/native-border-router/project-conf.h b/examples/ipv6/native-border-router/project-conf.h index 90576783a..2ab3cda7b 100644 --- a/examples/ipv6/native-border-router/project-conf.h +++ b/examples/ipv6/native-border-router/project-conf.h @@ -45,6 +45,8 @@ #undef WEBSERVER_CONF_CFS_CONNS #define WEBSERVER_CONF_CFS_CONNS 2 +#define SERIALIZE_ATTRIBUTES 1 + #define CMD_CONF_OUTPUT border_router_cmd_output #undef NETSTACK_CONF_RDC diff --git a/examples/ipv6/native-border-router/tun-bridge.c b/examples/ipv6/native-border-router/tun-bridge.c index 54d16339c..970b4cc79 100644 --- a/examples/ipv6/native-border-router/tun-bridge.c +++ b/examples/ipv6/native-border-router/tun-bridge.c @@ -125,13 +125,13 @@ void ifconf(const char *tundev, const char *ipaddr) { #ifdef linux - ssystem("ifconfig %s inet6 `hostname` up", tundev); + ssystem("ifconfig %s inet `hostname` up", tundev); ssystem("ifconfig %s add %s", tundev, ipaddr); #elif defined(__APPLE__) ssystem("ifconfig %s inet6 %s up", tundev, ipaddr); ssystem("sysctl -w net.inet.ip.forwarding=1"); #else - ssystem("ifconfig %s inet6 `hostname` %s up", tundev, ipaddr); + ssystem("ifconfig %s inet `hostname` %s up", tundev, ipaddr); ssystem("sysctl -w net.inet.ip.forwarding=1"); #endif /* !linux */ diff --git a/examples/ipv6/rpl-udp/udp-client.c b/examples/ipv6/rpl-udp/udp-client.c index 67e4de7e8..5a993e3c7 100644 --- a/examples/ipv6/rpl-udp/udp-client.c +++ b/examples/ipv6/rpl-udp/udp-client.c @@ -147,7 +147,9 @@ PROCESS_THREAD(udp_client_process, ev, data) { static struct etimer periodic; static struct ctimer backoff_timer; +#if WITH_COMPOWER static int print = 0; +#endif PROCESS_BEGIN(); diff --git a/platform/cooja/Makefile.cooja b/platform/cooja/Makefile.cooja index e79fdbf1b..d4e80f182 100644 --- a/platform/cooja/Makefile.cooja +++ b/platform/cooja/Makefile.cooja @@ -106,9 +106,9 @@ ifdef SYMBOLS endif ## SYMBOLS ifdef REDEF_PRINTF @echo Redefining printf - -$(foreach OBJ,$^, objcopy --redefine-sym printf=log_printf $(OBJ); ) - -$(foreach OBJ,$^, objcopy --redefine-sym puts=log_puts $(OBJ); ) - -$(foreach OBJ,$^, objcopy --redefine-sym putchar=log_putchar $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym printf=log_printf $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym puts=log_puts $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym putchar=log_putchar $(OBJ); ) endif ## REDEF_PRINTF $(LINK_COMMAND_1) $^ $(LINK_COMMAND_2) diff --git a/platform/cooja/dev/cooja-radio.c b/platform/cooja/dev/cooja-radio.c index 05aa7d49c..ca9552291 100644 --- a/platform/cooja/dev/cooja-radio.c +++ b/platform/cooja/dev/cooja-radio.c @@ -45,9 +45,11 @@ #include "dev/cooja-radio.h" #define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE - #define CCA_SS_THRESHOLD -95 +#define WITH_TURNAROUND 1 +#define WITH_SEND_CCA 1 + const struct simInterface radio_interface; /* COOJA */ @@ -109,16 +111,16 @@ radio_off(void) static void doInterfaceActionsBeforeTick(void) { - if (!simRadioHWOn) { + if(!simRadioHWOn) { simInSize = 0; return; } - if (simReceiving) { + if(simReceiving) { simLastSignalStrength = simSignalStrength; return; } - if (simInSize > 0) { + if(simInSize > 0) { process_poll(&cooja_radio_process); } } @@ -133,7 +135,7 @@ radio_read(void *buf, unsigned short bufsize) { int tmp = simInSize; - if (simInSize == 0) { + if(simInSize == 0) { return 0; } if(bufsize < simInSize) { @@ -148,10 +150,25 @@ radio_read(void *buf, unsigned short bufsize) } /*---------------------------------------------------------------------------*/ static int +channel_clear(void) +{ + if(simSignalStrength > CCA_SS_THRESHOLD) { + return 0; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static int radio_send(const void *payload, unsigned short payload_len) { int radiostate = simRadioHWOn; + /* Simulate turnaround time of 1ms */ +#if WITH_TURNAROUND + simProcessRunValue = 1; + cooja_mt_yield(); +#endif /* WITH_TURNAROUND */ + if(!simRadioHWOn) { /* Turn on radio temporarily */ simRadioHWOn = 1; @@ -166,6 +183,13 @@ radio_send(const void *payload, unsigned short payload_len) return RADIO_TX_ERR; } + /* Transmit on CCA */ +#if WITH_SEND_CCA + if(!channel_clear()) { + return RADIO_TX_COLLISION; + } +#endif /* WITH_SEND_CCA */ + /* Copy packet data to temporary storage */ memcpy(simOutDataBuffer, payload, payload_len); simOutSize = payload_len; @@ -208,15 +232,6 @@ pending_packet(void) return !simReceiving && simInSize > 0; } /*---------------------------------------------------------------------------*/ -static int -channel_clear(void) -{ - if(simSignalStrength > CCA_SS_THRESHOLD) { - return 0; - } - return 1; -} -/*---------------------------------------------------------------------------*/ PROCESS_THREAD(cooja_radio_process, ev, data) { int len; diff --git a/platform/esb/contiki-conf.h b/platform/esb/contiki-conf.h index a577b7fe0..7b3ef0252 100644 --- a/platform/esb/contiki-conf.h +++ b/platform/esb/contiki-conf.h @@ -1,6 +1,10 @@ #ifndef __CONTIKI_CONF_H__ #define __CONTIKI_CONF_H__ +#define PLATFORM_HAS_LEDS 1 +#define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_HAS_BATTERY 1 + /* DCO speed resynchronization for more robust UART, etc. */ #define DCOSYNCH_CONF_ENABLED 1 #define DCOSYNCH_CONF_PERIOD 30 @@ -11,15 +15,6 @@ #define PROFILE_CONF_ON 0 #define ENERGEST_CONF_ON 1 -#ifdef __IAR_SYSTEMS_ICC__ -#define __MSP430F149__ 1 -#define __MSP430__ 1 -#define CC_CONF_INLINE -#define BV(x) (1 << x) -#else -#define CC_CONF_INLINE inline -#endif - #define HAVE_STDINT_H #include "msp430def.h" diff --git a/platform/esb/contiki-esb-main.c b/platform/esb/contiki-esb-main.c index 8267c0738..d052f453b 100644 --- a/platform/esb/contiki-esb-main.c +++ b/platform/esb/contiki-esb-main.c @@ -305,8 +305,6 @@ main(void) watchdog_start(); } } - - return 0; } /*---------------------------------------------------------------------------*/ /* char *arg_alloc(char size) {return NULL;} */ diff --git a/platform/exp5438/Makefile.exp5438 b/platform/exp5438/Makefile.exp5438 index 3f4d54820..a3e57fc90 100644 --- a/platform/exp5438/Makefile.exp5438 +++ b/platform/exp5438/Makefile.exp5438 @@ -1,19 +1,8 @@ # $Id: Makefile.z1,v 1.4 2010/11/07 08:40:24 enricmcalvo Exp $ # msp430flasher -n msp430x5437 -w "Firmware.txt" -v -z [VCC] -ifndef IAR -GCC=1 -endif - -ifdef GCC -CFLAGS+=-Os -g -else -IAR=1 -endif - ifdef IAR -CFLAGS+=-e --vla -Ohz --multiplier=32 --multiplier_location=4C0 --hw_workaround=CPU40 --core=430X --data_model small --double=32 -D__MSP430F5438A__ -CFLAGS += --diag_suppress=Pa050 +CFLAGS+=-e --vla -Ohz --multiplier=32 --multiplier_location=4C0 --hw_workaround=CPU40 --core=430X --data_model small --double=32 -D__MSP430F5438A__=1 #CFLAGS+=--no_cse --no_unroll --no_inline --no_code_motion --no_tbaa --debug -D__MSP430F5438A__ -e --double=32 --dlib_config 'C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.0 Evaluation\430\LIB\DLIB\dl430xsfn.h' --core=430X --data_model=small -Ol --multiplier=32 --multiplier_location=4C0 --hw_workaround=CPU40 endif @@ -43,7 +32,7 @@ help: @echo make help - shows this help @echo make TARGET=exp5438 savetarget - stores selection of target to avoid using TARGET= on every make invokation @echo make program.upload - compiles and uploads program to connected board - @echo make program.upload GCC=1 - uses the mspgcc compiler instead of IAR + @echo make program.upload IAR=1 - uses the IAR compiler instead of mspgcc @echo make program.upload NODEID=x - uploads with node_id set to x CONTIKI_TARGET_DIRS = . dev apps net @@ -70,19 +59,12 @@ contiki-$(TARGET).a: ${addprefix $(OBJECTDIR)/,symbols.o} ifdef IAR STACKSIZE=300 -LDFLAGS_ELF=-B -xm "$(IAR_PATH)/lib/dlib/dl430xsfn.r43" -f "$(IAR_PATH)/config/lnk430f5437.xcl" -l contiki-$(TARGET).map -Felf -yn -s __program_start -D_STACK_SIZE=$(STACKSIZE) -D_DATA16_HEAP_SIZE=$(STACKSIZE) -D_DATA20_HEAP_SIZE=$(STACKSIZE) +LDFLAGSNO += -B -xm "$(IAR_PATH)/lib/dlib/dl430xsfn.r43" -f "$(IAR_PATH)/config/lnk430f5437.xcl" -l contiki-$(TARGET).map -s __program_start -D_STACK_SIZE=$(STACKSIZE) -D_DATA16_HEAP_SIZE=$(STACKSIZE) -D_DATA20_HEAP_SIZE=$(STACKSIZE) +LDFLAGS += $(LDFLAGSNO) -Felf -yn +endif -LDFLAGS_HEX=-B -xm "$(IAR_PATH)/lib/dlib/dl430xsfn.r43" -f "$(IAR_PATH)/config/lnk430f5437.xcl" -l contiki-$(TARGET).map -Fintel-extended -s __program_start -D_STACK_SIZE=$(STACKSIZE) -D_DATA16_HEAP_SIZE=$(STACKSIZE) -D_DATA20_HEAP_SIZE=$(STACKSIZE) - -LDFLAGS+=$(LDFLAGS_ELF) - -%.hex: %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a - $(LD) $(LDFLAGS_HEX) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ - -else %.hex: %.ihex mv $< $@ -endif %.upload: %.hex msp430flasher -n msp430x5438a -e ERASE_MAIN -w $< -v -z [VCC] diff --git a/platform/exp5438/cc2420-arch.c b/platform/exp5438/cc2420-arch.c index 090dd1611..044e894dd 100644 --- a/platform/exp5438/cc2420-arch.c +++ b/platform/exp5438/cc2420-arch.c @@ -31,19 +31,12 @@ #include "contiki.h" - -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include "contiki-net.h" #include "dev/spi.h" #include "dev/cc2420.h" #include "dev/leds.h" +#include "isr_compat.h" #ifndef CONF_SFD_TIMESTAMPS #define CONF_SFD_TIMESTAMPS 0 @@ -54,13 +47,7 @@ #endif /*---------------------------------------------------------------------------*/ -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=CC2420_IRQ_VECTOR -__interrupt void -#else -interrupt(CC2420_IRQ_VECTOR) -#endif -cc24240_fifop_interrupt(void) +ISR(CC2420_IRQ, cc24240_fifop_interrupt) { ENERGEST_ON(ENERGEST_TYPE_IRQ); diff --git a/platform/exp5438/clock.c b/platform/exp5438/clock.c index a7a419380..0b0973c97 100644 --- a/platform/exp5438/clock.c +++ b/platform/exp5438/clock.c @@ -32,18 +32,11 @@ */ #include "contiki-conf.h" - -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include "sys/energest.h" #include "sys/clock.h" #include "sys/etimer.h" #include "rtimer-arch.h" +#include "isr_compat.h" #include "dev/leds.h" @@ -57,13 +50,7 @@ static volatile clock_time_t count = 0; /* last_tar is used for calculating clock_fine, last_ccr might be better? */ static unsigned short last_tar = 0; /*---------------------------------------------------------------------------*/ -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=TIMER1_A1_VECTOR -__interrupt void -#else -interrupt(TIMER1_A1_VECTOR) -#endif -timera1 (void) +ISR(TIMER1_A1, timera1) { ENERGEST_ON(ENERGEST_TYPE_IRQ); diff --git a/platform/exp5438/contiki-exp5438-main.c b/platform/exp5438/contiki-exp5438-main.c index 92bb570a0..f411ae697 100644 --- a/platform/exp5438/contiki-exp5438-main.c +++ b/platform/exp5438/contiki-exp5438-main.c @@ -30,13 +30,6 @@ */ #include "contiki.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include #include #include diff --git a/platform/exp5438/flash.c b/platform/exp5438/flash.c index fe6922734..6f9ca6da6 100644 --- a/platform/exp5438/flash.c +++ b/platform/exp5438/flash.c @@ -36,13 +36,6 @@ */ #include "contiki.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include #include "dev/flash.h" diff --git a/platform/exp5438/hal_lcd.c b/platform/exp5438/hal_lcd.c index 14163f25f..e2475010f 100644 --- a/platform/exp5438/hal_lcd.c +++ b/platform/exp5438/hal_lcd.c @@ -35,11 +35,6 @@ ******************************************************************************/ #include "contiki-conf.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#endif #include "hal_MSP-EXP430F5438.h" #include "hal_lcd_fonts.h" diff --git a/platform/exp5438/leds-arch.c b/platform/exp5438/leds-arch.c index c48f0c376..63cd53262 100644 --- a/platform/exp5438/leds-arch.c +++ b/platform/exp5438/leds-arch.c @@ -42,12 +42,6 @@ #include "contiki-conf.h" #include "dev/leds.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#endif - /* LED ports */ #define LEDS_CONF_RED 0x01 #define LEDS_CONF_GREEN 0x02 diff --git a/platform/exp5438/msp430.c b/platform/exp5438/msp430.c index c12b6b24d..9c91aa6c2 100644 --- a/platform/exp5438/msp430.c +++ b/platform/exp5438/msp430.c @@ -31,12 +31,6 @@ * @(#)$Id: msp430.c,v 1.1 2010/08/24 16:26:38 joxe Exp $ */ #include "contiki.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif #include "dev/watchdog.h" #include "dev/leds.h" #include "net/uip.h" diff --git a/platform/exp5438/platform-conf.h b/platform/exp5438/platform-conf.h index f28c7d1ca..5d853a686 100644 --- a/platform/exp5438/platform-conf.h +++ b/platform/exp5438/platform-conf.h @@ -44,19 +44,6 @@ * changeable! */ #define TYNDALL 1 -/* Test for IAR compiler */ -#ifdef __IAR_SYSTEMS_ICC__ -#include -#include -#define dint() __disable_interrupt() -#define eint() __enable_interrupt() -#define __MSP430F5437__ 1 -#define __MSP430__ 1 -#define CC_CONF_INLINE -#define BV(x) (1 << x) -#else -#define CC_CONF_INLINE inline -#endif /* CPU target speed in Hz */ #define F_CPU 8000000uL // 8MHz by default diff --git a/platform/exp5438/rtimer-arch.c b/platform/exp5438/rtimer-arch.c index 7a1e327d7..24867a9f2 100644 --- a/platform/exp5438/rtimer-arch.c +++ b/platform/exp5438/rtimer-arch.c @@ -39,17 +39,11 @@ */ #include "contiki.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include "sys/energest.h" #include "sys/rtimer.h" #include "sys/process.h" #include "dev/watchdog.h" +#include "isr_compat.h" #define DEBUG 0 #if DEBUG @@ -60,13 +54,8 @@ #endif /*---------------------------------------------------------------------------*/ -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=TIMER1_A0_VECTOR -__interrupt void -#else -interrupt(TIMER1_A0_VECTOR) -#endif - timera0 (void) { +ISR(TIMER1_A0, timera0) +{ ENERGEST_ON(ENERGEST_TYPE_IRQ); watchdog_start(); diff --git a/platform/exp5438/spix.c b/platform/exp5438/spix.c index 2f511e650..478931775 100644 --- a/platform/exp5438/spix.c +++ b/platform/exp5438/spix.c @@ -30,17 +30,12 @@ */ #include "contiki-conf.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#endif /* * This is SPI initialization code for the MSP430X architecture. * */ -unsigned char spi_busy = 0; +/* unsigned char spi_busy = 0; */ /*---------------------------------------------------------------------------*/ /* * Initialize SPI bus. diff --git a/platform/exp5438/uart1x.c b/platform/exp5438/uart1x.c index 7d0c08977..3c1b41b99 100644 --- a/platform/exp5438/uart1x.c +++ b/platform/exp5438/uart1x.c @@ -36,13 +36,6 @@ */ #include "contiki.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif - #include #include "sys/energest.h" @@ -50,6 +43,7 @@ #include "dev/watchdog.h" #include "lib/ringbuf.h" #include "dev/leds.h" +#include "isr_compat.h" static int (*uart1_input_handler)(unsigned char c); @@ -114,13 +108,7 @@ uart1_init(unsigned long ubr) UCA1IE |= UCRXIE; /* Enable UCA1 RX interrupt */ } /*---------------------------------------------------------------------------*/ -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=USCI_A1_VECTOR -__interrupt void -#else -interrupt(USCI_A1_VECTOR) -#endif -uart1_rx_interrupt(void) +ISR(USCI_A1, uart1_rx_interrupt) { uint8_t c; diff --git a/platform/exp5438/watchdog.c b/platform/exp5438/watchdog.c index fc0dbef47..4a5b222d7 100644 --- a/platform/exp5438/watchdog.c +++ b/platform/exp5438/watchdog.c @@ -32,13 +32,8 @@ */ #include "contiki-conf.h" -#ifdef __IAR_SYSTEMS_ICC__ -#include -#else -#include -#include -#endif #include "dev/watchdog.h" +#include "isr_compat.h" static int counter = 0; @@ -76,13 +71,7 @@ printstring(char *s) #endif /* CONTIKI_TARGET_SKY */ #endif /* PRINT_STACK_ON_REBOOT */ /*---------------------------------------------------------------------------*/ -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=WDT_VECTOR -__interrupt void -#else -interrupt(WDT_VECTOR) -#endif -watchdog_interrupt(void) +ISR(WDT, watchdog_interrupt) { #ifdef CONTIKI_TARGET_SKY #if PRINT_STACK_ON_REBOOT diff --git a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/AvrMoteMemory.java b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/AvrMoteMemory.java index 891ebacd8..b0cff21de 100644 --- a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/AvrMoteMemory.java +++ b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/AvrMoteMemory.java @@ -170,4 +170,17 @@ public class AvrMoteMemory implements MoteMemory, AddressMemory { public boolean variableExists(String varName) { return memoryMap.getLocation(varName) != null; } + + public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) { + logger.warn("Not implemented"); + return false; + } + + public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) { + } + + public int parseInt(byte[] memorySegment) { + logger.warn("Not implemented"); + return 0; + } } diff --git a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java index 15a7b6420..5f8c155a8 100644 --- a/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java +++ b/tools/cooja/apps/avrora/src/se/sics/cooja/avrmote/MicaZMote.java @@ -270,9 +270,4 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { public String toString() { return "MicaZ " + getID(); } - - public MemoryMonitor createMemoryMonitor(MemoryEventHandler meh) { - logger.fatal("Not implemented"); - return null; - } } diff --git a/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java b/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java index f56647837..415447472 100644 --- a/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java +++ b/tools/cooja/apps/mrm/java/se/sics/mrm/MRM.java @@ -300,6 +300,11 @@ public class MRM extends AbstractRadioMedium { for (RadioConnection conn : conns) { for (Radio dstRadio : ((MRMRadioConnection) conn).getDestinations()) { double signalStrength = ((MRMRadioConnection) conn).getDestinationSignalStrength(dstRadio); + if (conn.getSource().getChannel() >= 0 && + dstRadio.getChannel() >= 0 && + conn.getSource().getChannel() != dstRadio.getChannel()) { + continue; + } if (dstRadio.getCurrentSignalStrength() < signalStrength) { dstRadio.setCurrentSignalStrength(signalStrength); } @@ -313,6 +318,11 @@ public class MRM extends AbstractRadioMedium { if (intfRadio.getCurrentSignalStrength() < signalStrength) { intfRadio.setCurrentSignalStrength(signalStrength); } + if (conn.getSource().getChannel() >= 0 && + intfRadio.getChannel() >= 0 && + conn.getSource().getChannel() != intfRadio.getChannel()) { + continue; + } if (!intfRadio.isInterfered()) { /*logger.warn("Radio was not interfered: " + intfRadio);*/ diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java index 001ff7990..d2d2e154f 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMote.java @@ -238,7 +238,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /* Create mote address memory */ MapTable map = ((MspMoteType)getType()).getELF().getMap(); MapEntry[] allEntries = map.getAllEntries(); - myMemory = new MspMoteMemory(allEntries, myCpu); + myMemory = new MspMoteMemory(this, allEntries, myCpu); heapStartAddress = map.heapStartAddress; myCpu.reset(); @@ -539,84 +539,4 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc /*return executeCLICommand("line " + myCpu.getPC());*/ } - - public MemoryMonitor createMemoryMonitor(final MemoryEventHandler meh) { - return new MemoryMonitor() { - private boolean started = false; - private int address = -1; - private int size = -1; - private CPUMonitor myMonitor = null; - private boolean isPointer = false; - private MemoryMonitor pointedMemory = null; - public boolean start(int address, int size) { - if (started) { - return started; - } - - final MemoryMonitor thisMonitor = this; - myMonitor = new CPUMonitor() { - public void cpuAction(int type, int adr, int data) { - MemoryEventType t; - if (type == CPUMonitor.MEMORY_WRITE) { - t = MemoryEventType.WRITE; - } else if (type == CPUMonitor.MEMORY_READ) { - t = MemoryEventType.READ; - } else { - t = MemoryEventType.UNKNOWN; - } - - meh.event(thisMonitor, t, adr, data); - } - }; - - /* TODO Make sure no other part of Cooja overrides this! */ - for (int a = address; a < address+size; a++) { - myCpu.addWatchPoint(a, myMonitor); - } - - this.address = address; - this.size = size; - started = true; - return started; - } - public void stop() { - if (!started) { - return; - } - started = false; - - for (int a = address; a < address+size; a++) { - myCpu.removeWatchPoint(a, myMonitor); - } - } - public Mote getMote() { - return MspMote.this; - } - public int getAddress() { - return address; - } - public int getSize() { - return size; - } - - public boolean isPointer() { - return isPointer; - } - public void setPointer(boolean isPointer, MemoryMonitor pointedMemory) { - this.isPointer = isPointer; - this.pointedMemory = pointedMemory; - } - public MemoryMonitor getPointedMemory() { - return pointedMemory; - } - - private BufferAccess lastBufferAccess = null; - public void setLastBufferAccess(BufferAccess ba) { - this.lastBufferAccess = ba; - } - public BufferAccess getLastBufferAccess() { - return lastBufferAccess; - } - }; - } } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMoteMemory.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMoteMemory.java index 9f699aef2..619851780 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMoteMemory.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/MspMoteMemory.java @@ -29,11 +29,16 @@ package se.sics.cooja.mspmote; -import java.util.*; +import java.util.ArrayList; + import org.apache.log4j.Logger; import se.sics.cooja.AddressMemory; +import se.sics.cooja.Mote; import se.sics.cooja.MoteMemory; +import se.sics.cooja.MoteTimeEvent; +import se.sics.cooja.TimeEvent; +import se.sics.mspsim.core.CPUMonitor; import se.sics.mspsim.core.MSP430; import se.sics.mspsim.util.MapEntry; @@ -42,8 +47,10 @@ public class MspMoteMemory implements MoteMemory, AddressMemory { private final ArrayList mapEntries; private MSP430 cpu; + private Mote mote; - public MspMoteMemory(MapEntry[] allEntries, MSP430 cpu) { + public MspMoteMemory(Mote mote, MapEntry[] allEntries, MSP430 cpu) { + this.mote = mote; this.mapEntries = new ArrayList(); for (MapEntry entry: allEntries) { @@ -130,13 +137,7 @@ public class MspMoteMemory implements MoteMemory, AddressMemory { int varAddr = entry.getAddress(); byte[] varData = getMemorySegment(varAddr, 2); - - int retVal = 0; - int pos = 0; - retVal += ((varData[pos++] & 0xFF)) << 8; - retVal += ((varData[pos++] & 0xFF)) << 0; - - return Integer.reverseBytes(retVal) >> 16; // Crop two bytes + return parseInt(varData); } public void setIntValueOf(String varName, int newVal) throws UnknownVariableException { @@ -179,7 +180,6 @@ public class MspMoteMemory implements MoteMemory, AddressMemory { MapEntry entry = getMapEntry(varName); int varAddr = entry.getAddress(); - // TODO Check if small/big-endian when coming from JNI? return getMemorySegment(varAddr, length); } @@ -187,8 +187,74 @@ public class MspMoteMemory implements MoteMemory, AddressMemory { MapEntry entry = getMapEntry(varName); int varAddr = entry.getAddress(); - // TODO Check if small/big-endian when coming from JNI? setMemorySegment(varAddr, data); } + private ArrayList cpuMonitorArray = new ArrayList(); + class MemoryCPUMonitor implements CPUMonitor { + public final MemoryMonitor mm; + public final int address; + public final int size; + + public MemoryCPUMonitor(MemoryMonitor mm, int address, int size) { + this.mm = mm; + this.address = address; + this.size = size; + } + + public void cpuAction(int type, final int adr, int data) { + final MemoryEventType t; + if (type == CPUMonitor.MEMORY_WRITE) { + t = MemoryEventType.WRITE; + } else { + t = MemoryEventType.READ; + } + + /* XXX Workaround to avoid using soon-obsolete data argument. + * This causes a delay between memory rw and listener notifications */ + TimeEvent e = new MoteTimeEvent(mote, 0) { + public void execute(long time) { + mm.memoryChanged(MspMoteMemory.this, t, adr); + } + }; + mote.getSimulation().scheduleEvent(e, mote.getSimulation().getSimulationTime()); + } + } + + public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) { + MemoryCPUMonitor t = new MemoryCPUMonitor(mm, address, size); + cpuMonitorArray.add(t); + + for (int a = address; a < address+size; a++) { + cpu.addWatchPoint(a, t); + } + + return true; + } + + public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) { + for (MemoryCPUMonitor mcm: cpuMonitorArray) { + if (mcm.mm != mm || mcm.address != address || mcm.size != size) { + continue; + } + for (int a = address; a < address+size; a++) { + cpu.removeWatchPoint(a, mcm); + } + cpuMonitorArray.remove(mcm); + break; + } + } + + public int parseInt(byte[] memorySegment) { + if (memorySegment.length < 2) { + return -1; + } + + int retVal = 0; + int pos = 0; + retVal += ((memorySegment[pos++] & 0xFF)) << 8; + retVal += ((memorySegment[pos++] & 0xFF)) << 0; + + return Integer.reverseBytes(retVal) >> 16; + } } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java index d73a75270..18e98f09e 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/interfaces/SkyByteRadio.java @@ -82,8 +82,8 @@ public class SkyByteRadio extends Radio implements CustomDataRadio { private RadioPacket lastOutgoingPacket = null; private RadioPacket lastIncomingPacket = null; - public SkyByteRadio(Mote mote) { - this.mote = (MspMote)mote; + public SkyByteRadio(Mote m) { + this.mote = (MspMote)m; this.cc2420 = (CC2420) this.mote.getCPU().getChip(CC2420.class); if (cc2420 == null) { throw new IllegalStateException("Mote is not equipped with a CC2420"); @@ -98,6 +98,7 @@ public class SkyByteRadio extends Radio implements CustomDataRadio { lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); lastEvent = RadioEvent.TRANSMISSION_STARTED; isTransmitting = true; + len = 0; /*logger.debug("----- SKY TRANSMISSION STARTED -----");*/ setChanged(); notifyObservers(); @@ -133,9 +134,6 @@ public class SkyByteRadio extends Radio implements CustomDataRadio { setChanged(); notifyObservers(); - -// System.out.println("## CC2420 Transmission finished..."); - lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); /*logger.debug("----- SKY TRANSMISSION FINISHED -----");*/ isTransmitting = false; @@ -150,36 +148,59 @@ public class SkyByteRadio extends Radio implements CustomDataRadio { cc2420.addOperatingModeListener(new OperatingModeListener() { public void modeChanged(Chip source, int mode) { if (isReceiverOn()) { + lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); lastEvent = RadioEvent.HW_ON; + setChanged(); + notifyObservers(); } else { - /* Radio was turned off during transmission. - * May for example happen if watchdog triggers */ - if (isTransmitting()) { - logger.fatal("Turning off radio while transmitting"); - lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); - /*logger.debug("----- SKY TRANSMISSION FINISHED -----");*/ - isTransmitting = false; - lastEvent = RadioEvent.TRANSMISSION_FINISHED; - setChanged(); - notifyObservers(); - } - lastEvent = RadioEvent.HW_OFF; + radioOff(); } + } + }); + + cc2420.setChannelListener(new CC2420.ChannelListener() { + public void changedChannel(int channel) { + /* XXX Currently assumes zero channel switch time */ + lastEvent = RadioEvent.UNKNOWN; lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); setChanged(); notifyObservers(); } }); + } - cc2420.setChannelListener(new CC2420.ChannelListener() { - public void changedChannel(int channel) { - /* XXX Currently assumes zero channel switch time */ - lastEvent = RadioEvent.UNKNOWN; - lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); - setChanged(); - notifyObservers(); - } - }); + private void radioOff() { + /* Radio was turned off during transmission. + * May for example happen if watchdog triggers */ + if (isTransmitting()) { + logger.warn("Turning off radio while transmitting, ending packet prematurely"); + + /* Simulate end of packet */ + lastOutgoingPacket = new RadioPacket() { + public byte[] getPacketData() { + return new byte[0]; + } + }; + + lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); + lastEvent = RadioEvent.PACKET_TRANSMITTED; + /*logger.debug("----- SKY PACKET TRANSMITTED -----");*/ + setChanged(); + notifyObservers(); + + /* Register that transmission ended in radio medium */ + lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); + /*logger.debug("----- SKY TRANSMISSION FINISHED -----");*/ + isTransmitting = false; + lastEvent = RadioEvent.TRANSMISSION_FINISHED; + setChanged(); + notifyObservers(); + } + + lastEventTime = SkyByteRadio.this.mote.getSimulation().getSimulationTime(); + lastEvent = RadioEvent.HW_OFF; + setChanged(); + notifyObservers(); } /* Packet radio support */ diff --git a/tools/cooja/build.xml b/tools/cooja/build.xml index 96bdf532d..3ad01fb00 100644 --- a/tools/cooja/build.xml +++ b/tools/cooja/build.xml @@ -108,6 +108,20 @@ The COOJA Simulator + + + + + + + + + + + + + + diff --git a/tools/cooja/config/external_tools_freebsd.config b/tools/cooja/config/external_tools_freebsd.config index b56586733..b0564ec31 100644 --- a/tools/cooja/config/external_tools_freebsd.config +++ b/tools/cooja/config/external_tools_freebsd.config @@ -6,6 +6,7 @@ PATH_AR = ar PATH_SHELL = sh PATH_C_COMPILER = gcc PATH_OBJDUMP=objdump +PATH_OBJCOPY=objcopy OBJDUMP_ARGS=-h CMD_GREP_PROCESSES = grep "^PROCESS_THREAD[ ]*([^,]*,[^,]*,[^)]*)" -o -H REGEXP_PARSE_PROCESSES = ([^/]*.c):PROCESS_THREAD[ ]*\\(([^,]*),[^,]*,[^)]*\\) diff --git a/tools/cooja/config/external_tools_linux.config b/tools/cooja/config/external_tools_linux.config index 9338eebb1..8e433b543 100644 --- a/tools/cooja/config/external_tools_linux.config +++ b/tools/cooja/config/external_tools_linux.config @@ -6,6 +6,7 @@ PATH_AR = ar PATH_SHELL = sh PATH_C_COMPILER = gcc PATH_OBJDUMP=objdump +PATH_OBJCOPY=objcopy OBJDUMP_ARGS=-h CMD_GREP_PROCESSES = grep "^PROCESS_THREAD[ ]*([^,]*,[^,]*,[^)]*)" -o -H REGEXP_PARSE_PROCESSES = ([^/]*.c):PROCESS_THREAD[ ]*\\(([^,]*),[^,]*,[^)]*\\) diff --git a/tools/cooja/config/external_tools_linux_64.config b/tools/cooja/config/external_tools_linux_64.config index 034498805..7609ca905 100644 --- a/tools/cooja/config/external_tools_linux_64.config +++ b/tools/cooja/config/external_tools_linux_64.config @@ -6,6 +6,7 @@ PATH_AR = ar PATH_SHELL = sh PATH_C_COMPILER = gcc PATH_OBJDUMP=objdump +PATH_OBJCOPY=objcopy OBJDUMP_ARGS=-h CMD_GREP_PROCESSES = grep "^PROCESS_THREAD[ ]*([^,]*,[^,]*,[^)]*)" -o -H REGEXP_PARSE_PROCESSES = ([^/]*.c):PROCESS_THREAD[ ]*\\(([^,]*),[^,]*,[^)]*\\) diff --git a/tools/cooja/config/external_tools_macosx.config b/tools/cooja/config/external_tools_macosx.config index 3410dfed4..f15ba75da 100644 --- a/tools/cooja/config/external_tools_macosx.config +++ b/tools/cooja/config/external_tools_macosx.config @@ -6,6 +6,7 @@ PATH_AR = ar PATH_SHELL = sh PATH_C_COMPILER = gcc PATH_OBJDUMP= objdump +PATH_OBJCOPY=objcopy OBJDUMP_ARGS= -h CMD_GREP_PROCESSES = grep "^PROCESS_THREAD[ ]*([^,]*,[^,]*,[^)]*)" -o -H REGEXP_PARSE_PROCESSES = ([^/]*.c):PROCESS_THREAD[ ]*\\(([^,]*),[^,]*,[^)]*\\) diff --git a/tools/cooja/config/external_tools_win32.config b/tools/cooja/config/external_tools_win32.config index dd0477ec9..c35ab48cb 100644 --- a/tools/cooja/config/external_tools_win32.config +++ b/tools/cooja/config/external_tools_win32.config @@ -6,6 +6,7 @@ PATH_AR=ar PATH_SHELL = sh PATH_C_COMPILER = gcc PATH_OBJDUMP=objdump +PATH_OBJCOPY=objcopy OBJDUMP_ARGS=-h CMD_GREP_PROCESSES = grep '^PROCESS_THREAD[ ]*([^,]*,[^,]*,[^)]*)' -o -d skip -D skip -H -r REGEXP_PARSE_PROCESSES = ([^/]*.c):PROCESS_THREAD[ ]*\\(([^,]*),[^,]*,[^)]*\\) @@ -24,7 +25,7 @@ PATH_JAVAC = javac DEFAULT_PROJECTDIRS = [CONTIKI_DIR]/tools/cooja/apps/mrm;[CONTIKI_DIR]/tools/cooja/apps/mspsim;[CONTIKI_DIR]/tools/cooja/apps/avrora;[CONTIKI_DIR]/tools/cooja/apps/serial_socket;[CONTIKI_DIR]/tools/cooja/apps/collect-view PARSE_WITH_COMMAND = true -PARSE_COMMAND=nm -C $(LIBFILE) +PARSE_COMMAND=nm -n -C $(LIBFILE) MAPFILE_DATA_START = ^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$ MAPFILE_DATA_SIZE = ^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$ MAPFILE_BSS_START = ^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$ @@ -35,7 +36,7 @@ MAPFILE_VAR_ADDRESS_2 = [ \t]*$ MAPFILE_VAR_SIZE_1 = ^ MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$ COMMAND_VAR_NAME_ADDRESS = ^([0-9A-Fa-f][0-9A-Fa-f]*)[ \t][^Tt][ \t]([^ ._][^ ]*) -COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]D[ \t]_data_start__$ -COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]D[ \t]_data_end__$ -COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]B[ \t]_bss_start__$ -COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]B[ \t]_bss_end__$ +COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_start__$ +COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]D[ \t].*_data_end__$ +COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_start__$ +COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]B[ \t].*_bss_end__$ diff --git a/tools/cooja/config/test_template.c b/tools/cooja/config/test_template.c index 06103e1f9..072faef94 100644 --- a/tools/cooja/config/test_template.c +++ b/tools/cooja/config/test_template.c @@ -34,9 +34,12 @@ #include #include +/* This is a stripped version of platform/cooja/contiki-cooja-main.c, used by + * Cooja's Contiki Mote Configuration Wizard */ + const struct simInterface *simInterfaces[] = {NULL}; -long ref_var; /* Placed somewhere in the BSS section */ +long referenceVar; /* Placed somewhere in the BSS section */ /* Variables with known memory addresses */ int var1=1; @@ -60,8 +63,9 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_getMemory(JNIEnv *env, jobject obj, jin mem_arr, 0, (size_t) length, - (jbyte *) (((long)rel_addr) + ref_var) + (jbyte *) (((long)rel_addr) + referenceVar) ); + } /*---------------------------------------------------------------------------*/ JNIEXPORT void JNICALL @@ -69,7 +73,7 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_setMemory(JNIEnv *env, jobject obj, jin { jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0); memcpy( - (char*) (((long)rel_addr) + ref_var), + (char*) (((long)rel_addr) + referenceVar), mem, length); (*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0); @@ -85,5 +89,5 @@ Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj) JNIEXPORT void JNICALL Java_se_sics_cooja_corecomm_[CLASS_NAME]_setReferenceAddress(JNIEnv *env, jobject obj, jint addr) { - ref_var = (((long)&ref_var) - ((long)addr)); + referenceVar = (((long)&referenceVar) - ((long)addr)); } diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 67628b0f8..091592634 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -245,6 +245,7 @@ public class GUI extends Observable { "PATH_LINKER", "LINK_COMMAND_1", "LINK_COMMAND_2", "PATH_AR", "AR_COMMAND_1", "AR_COMMAND_2", "PATH_OBJDUMP", "OBJDUMP_ARGS", + "PATH_OBJCOPY", "PATH_JAVAC", "CONTIKI_STANDARD_PROCESSES", @@ -929,7 +930,7 @@ public class GUI extends Observable { menuItem.setToolTipText("Not available in applet version"); } - menuItem = new JMenuItem("Compiler configuration wizard"); + menuItem = new JMenuItem("Contiki mote configuration wizard"); menuItem.setActionCommand("configuration wizard"); menuItem.addActionListener(guiEventHandler); menu.add(menuItem); @@ -940,14 +941,6 @@ public class GUI extends Observable { menu.add(new JMenuItem(showBufferSettingsAction)); - menu.addSeparator(); - - menuItem = new JMenuItem("Java version: " - + System.getProperty("java.version") + " (" - + System.getProperty("java.vendor") + ")"); - menuItem.setEnabled(false); - menu.add(menuItem); - /* Help */ menu = new JMenu("Help"); menu.setMnemonic(KeyEvent.VK_H); @@ -957,6 +950,22 @@ public class GUI extends Observable { menu.add(checkBox); menuBar.add(menu); + menu.addSeparator(); + + menuItem = new JMenuItem("Java version: " + + System.getProperty("java.version") + " (" + + System.getProperty("java.vendor") + ")"); + menuItem.setEnabled(false); + menu.add(menuItem); + menuItem = new JMenuItem("System's \"os.arch\": " + + System.getProperty("os.arch")); + menuItem.setEnabled(false); + menu.add(menuItem); + menuItem = new JMenuItem("System's \"sun.arch.data.model\": " + + System.getProperty("sun.arch.data.model")); + menuItem.setEnabled(false); + menu.add(menuItem); + // Mote plugins popup menu (not available via menu bar) if (menuMotePluginClasses == null) { menuMotePluginClasses = new Vector>(); diff --git a/tools/cooja/java/se/sics/cooja/MoteInterface.java b/tools/cooja/java/se/sics/cooja/MoteInterface.java index 2b43cdaf6..a1e7461b7 100644 --- a/tools/cooja/java/se/sics/cooja/MoteInterface.java +++ b/tools/cooja/java/se/sics/cooja/MoteInterface.java @@ -147,5 +147,11 @@ public abstract class MoteInterface extends Observable { */ public void removed() { } + + /** + * Called when all mote interfaces have been added to mote. + */ + public void added() { + } } diff --git a/tools/cooja/java/se/sics/cooja/MoteMemory.java b/tools/cooja/java/se/sics/cooja/MoteMemory.java index 08184a0d9..00d0460e3 100644 --- a/tools/cooja/java/se/sics/cooja/MoteMemory.java +++ b/tools/cooja/java/se/sics/cooja/MoteMemory.java @@ -31,6 +31,7 @@ package se.sics.cooja; + /** * This interface represents a mote memory. * @@ -44,7 +45,7 @@ package se.sics.cooja; * @see se.sics.cooja.SectionMoteMemory * @author Fredrik Osterlind */ -public interface MoteMemory { +public interface MoteMemory extends AddressMemory { /** * Clears the entire memory. @@ -77,4 +78,14 @@ public interface MoteMemory { */ public int getTotalSize(); + public abstract int parseInt(byte[] memorySegment); + + public enum MemoryEventType { READ, WRITE }; + + public interface MemoryMonitor { + public void memoryChanged(MoteMemory memory, MemoryEventType type, int address); + } + + public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm); + public void removeMemoryMonitor(int address, int size, MemoryMonitor mm); } diff --git a/tools/cooja/java/se/sics/cooja/SectionMoteMemory.java b/tools/cooja/java/se/sics/cooja/SectionMoteMemory.java index 105fbdcac..913706c41 100644 --- a/tools/cooja/java/se/sics/cooja/SectionMoteMemory.java +++ b/tools/cooja/java/se/sics/cooja/SectionMoteMemory.java @@ -23,22 +23,21 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: SectionMoteMemory.java,v 1.7 2010/01/20 13:33:33 fros4943 Exp $ */ package se.sics.cooja; import java.util.ArrayList; -import java.util.Properties; +import java.util.Arrays; +import java.util.HashMap; import org.apache.log4j.Logger; /** * Represents a mote memory consisting of non-overlapping memory sections with - * variables' memory addresses. + * symbol addresses. *

- * When an unhandled memory segment is set a new section is automatically + * When an non-existing memory segment is written, a new section is automatically * created for this segment. *

* @@ -48,28 +47,36 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { private static Logger logger = Logger.getLogger(SectionMoteMemory.class); private ArrayList sections = new ArrayList(); + + /* readonly memory is never written to Contiki core, and is used to provide + * access to, for instance, strings */ + private ArrayList readonlySections = new ArrayList(); - private final Properties addresses; + private final HashMap addresses; + /* used to map Cooja's address space to native (Contiki's) addresses */ + private final int offset; + /** - * Create a new mote memory with information about which variables exist and - * their relative memory addresses. - * - * @param addresses Variable addresses + * @param addresses Symbol addresses + * @param offset Offset for internally used addresses */ - public SectionMoteMemory(Properties addresses) { + public SectionMoteMemory(HashMap addresses, int offset) { this.addresses = addresses; + this.offset = offset; } public String[] getVariableNames() { - return addresses.values().toArray(new String[0]); + return addresses.keySet().toArray(new String[0]); } public int getVariableAddress(String varName) throws UnknownVariableException { + /* Cooja address space */ if (!addresses.containsKey(varName)) { throw new UnknownVariableException(varName); } - return ((Integer) addresses.get(varName)).intValue(); + + return addresses.get(varName).intValue() + offset; } public int getIntegerLength() { @@ -81,16 +88,35 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public byte[] getMemorySegment(int address, int size) { + /* Cooja address space */ + address -= offset; + for (MoteMemorySection section : sections) { if (section.includesAddr(address) && section.includesAddr(address + size - 1)) { return section.getMemorySegment(address, size); } } + + /* Check if in readonly section */ + for (MoteMemorySection section : readonlySections) { + if (section.includesAddr(address) + && section.includesAddr(address + size - 1)) { + return section.getMemorySegment(address, size); + } + } + return null; } + public void setMemorySegmentNative(int address, byte[] data) { + setMemorySegment(address+offset, data); + } + public void setMemorySegment(int address, byte[] data) { + /* Cooja address space */ + address -= offset; + /* TODO XXX Sections may overlap */ for (MoteMemorySection section : sections) { if (section.includesAddr(address) @@ -102,6 +128,13 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { sections.add(new MoteMemorySection(address, data)); } + public void setReadonlyMemorySegment(int address, byte[] data) { + /* Cooja address space */ + address -= offset; + + readonlySections.add(new MoteMemorySection(address, data)); + } + public int getTotalSize() { int totalSize = 0; for (MoteMemorySection section : sections) { @@ -120,67 +153,27 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } /** - * Removes a memory segment from this memory. The section containing the - * segment may be split into two sections. + * Get start address of given section in native address space. * - * @param startAddr Start address - * @param size Length - */ - public void removeSegmentFromMemory(int startAddr, int size) { - for (MoteMemorySection section : sections) { - // Find section containing segment to remove - if (section.includesAddr(startAddr) - && section.includesAddr(startAddr + size - 1)) { - MoteMemorySection oldSection = section; - - byte[] dataFirstPart = oldSection.getMemorySegment( - oldSection.startAddr, (startAddr - oldSection.startAddr)); - byte[] dataSecondPart = oldSection - .getMemorySegment(startAddr + size, (oldSection.startAddr - + oldSection.getSize() - (startAddr + size))); - - MoteMemorySection newSectionFirstPart = new MoteMemorySection( - oldSection.startAddr, dataFirstPart); - MoteMemorySection newSectionSecondPart = new MoteMemorySection( - startAddr + size, dataSecondPart); - - // Remove old section, add new sections - sections.remove(oldSection); - if (newSectionFirstPart.getSize() > 0) { - sections.add(newSectionFirstPart); - } - if (newSectionSecondPart.getSize() > 0) { - sections.add(newSectionSecondPart); - } - } - } - } - - /** - * Get start address of section at given position. - * - * @param sectionNr - * Section position + * @param sectionNr Section position * @return Start address of section */ - public int getStartAddrOfSection(int sectionNr) { + public int getSectionNativeAddress(int sectionNr) { if (sectionNr >= sections.size()) { - return 0; + return -1; } - return sections.get(sectionNr).getStartAddr(); } /** * Get size of section at given position. * - * @param sectionNr - * Section position + * @param sectionNr Section position * @return Size of section */ public int getSizeOfSection(int sectionNr) { if (sectionNr >= sections.size()) { - return 0; + return -1; } return sections.get(sectionNr).getSize(); @@ -189,8 +182,7 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { /** * Get data of section at given position. * - * @param sectionNr - * Section position + * @param sectionNr Section position * @return Data at section */ public byte[] getDataOfSection(int sectionNr) { @@ -206,42 +198,22 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public int getIntValueOf(String varName) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); - + int varAddr = getVariableAddress(varName); byte[] varData = getMemorySegment(varAddr, 4); if (varData == null) { throw new UnknownVariableException(varName); } - int retVal = 0; - int pos = 0; - retVal += ((varData[pos++] & 0xFF)) << 24; - retVal += ((varData[pos++] & 0xFF)) << 16; - retVal += ((varData[pos++] & 0xFF)) << 8; - retVal += ((varData[pos++] & 0xFF)) << 0; - - /* TODO Correct for all platforms? */ - retVal = Integer.reverseBytes(retVal); - - return retVal; + return parseInt(varData); } public void setIntValueOf(String varName, int newVal) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); + int varAddr = getVariableAddress(varName); /* TODO Correct for all platforms? */ int newValToSet = Integer.reverseBytes(newVal); - // Create byte array int pos = 0; byte[] varData = new byte[4]; @@ -254,12 +226,7 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public byte getByteValueOf(String varName) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); - + int varAddr = getVariableAddress(varName); byte[] varData = getMemorySegment(varAddr, 1); if (varData == null) { @@ -270,12 +237,7 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public void setByteValueOf(String varName, byte newVal) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); - + int varAddr = getVariableAddress(varName); byte[] varData = new byte[1]; varData[0] = newVal; @@ -284,24 +246,12 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public byte[] getByteArray(String varName, int length) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); - - // TODO Check if small/big-endian when coming from JNI? + int varAddr = getVariableAddress(varName); return getMemorySegment(varAddr, length); } public void setByteArray(String varName, byte[] data) throws UnknownVariableException { - // Get start address of variable - if (!addresses.containsKey(varName)) { - throw new UnknownVariableException(varName); - } - int varAddr = ((Integer) addresses.get(varName)).intValue(); - - // TODO Check if small/big-endian when coming from JNI? + int varAddr = getVariableAddress(varName); setMemorySegment(varAddr, data); } @@ -310,10 +260,9 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { * * @author Fredrik Osterlind */ - private class MoteMemorySection { + private static class MoteMemorySection { private byte[] data = null; - - private int startAddr; + private final int startAddr; /** * Create a new memory section. @@ -408,14 +357,75 @@ public class SectionMoteMemory implements MoteMemory, AddressMemory { } public SectionMoteMemory clone() { - ArrayList clones = new ArrayList(); + ArrayList sectionsClone = new ArrayList(); for (MoteMemorySection section : sections) { - clones.add(section.clone()); + sectionsClone.add(section.clone()); } - SectionMoteMemory clone = new SectionMoteMemory(addresses); - clone.sections = clones; + SectionMoteMemory clone = new SectionMoteMemory(addresses, offset); + clone.sections = sectionsClone; + clone.readonlySections = readonlySections; return clone; - } + } + + private ArrayList polledMemories = new ArrayList(); + public void pollForMemoryChanges() { + for (PolledMemorySegments mem: polledMemories.toArray(new PolledMemorySegments[0])) { + mem.notifyIfChanged(); + } + } + + private class PolledMemorySegments { + public final MemoryMonitor mm; + public final int address; + public final int size; + private byte[] oldMem; + + public PolledMemorySegments(MemoryMonitor mm, int address, int size) { + this.mm = mm; + this.address = address; + this.size = size; + + oldMem = getMemorySegment(address, size); + } + + private void notifyIfChanged() { + byte[] newMem = getMemorySegment(address, size); + if (Arrays.equals(oldMem, newMem)) { + return; + } + + mm.memoryChanged(SectionMoteMemory.this, MemoryEventType.WRITE, address); + oldMem = newMem; + } + } + + public boolean addMemoryMonitor(int address, int size, MemoryMonitor mm) { + PolledMemorySegments t = new PolledMemorySegments(mm, address, size); + polledMemories.add(t); + return true; + } + + public void removeMemoryMonitor(int address, int size, MemoryMonitor mm) { + for (PolledMemorySegments mcm: polledMemories) { + if (mcm.mm != mm || mcm.address != address || mcm.size != size) { + continue; + } + polledMemories.remove(mcm); + break; + } + } + + public int parseInt(byte[] memorySegment) { + int retVal = 0; + int pos = 0; + retVal += ((memorySegment[pos++] & 0xFF)) << 24; + retVal += ((memorySegment[pos++] & 0xFF)) << 16; + retVal += ((memorySegment[pos++] & 0xFF)) << 8; + retVal += ((memorySegment[pos++] & 0xFF)) << 0; + + retVal = Integer.reverseBytes(retVal); + return retVal; + } } diff --git a/tools/cooja/java/se/sics/cooja/Simulation.java b/tools/cooja/java/se/sics/cooja/Simulation.java index 972acda22..c1e89627a 100644 --- a/tools/cooja/java/se/sics/cooja/Simulation.java +++ b/tools/cooja/java/se/sics/cooja/Simulation.java @@ -790,6 +790,12 @@ public class Simulation extends Observable implements Runnable { motes.add(mote); currentRadioMedium.registerMote(mote, Simulation.this); + + /* Notify mote interfaces that node was added */ + for (MoteInterface i: mote.getInterfaces().getInterfaces()) { + i.added(); + } + setChanged(); notifyObservers(mote); } diff --git a/tools/cooja/java/se/sics/cooja/contikimote/ContikiMote.java b/tools/cooja/java/se/sics/cooja/contikimote/ContikiMote.java index e7345e352..2130d1fcf 100644 --- a/tools/cooja/java/se/sics/cooja/contikimote/ContikiMote.java +++ b/tools/cooja/java/se/sics/cooja/contikimote/ContikiMote.java @@ -152,8 +152,9 @@ public class ContikiMote extends AbstractWakeupMote implements Mote { /* Copy mote memory from Contiki */ myType.getCoreMemory(myMemory); - + /* Poll mote interfaces */ + myMemory.pollForMemoryChanges(); myInterfaceHandler.doActiveActionsAfterTick(); myInterfaceHandler.doPassiveActionsAfterTick(); } diff --git a/tools/cooja/java/se/sics/cooja/contikimote/ContikiMoteType.java b/tools/cooja/java/se/sics/cooja/contikimote/ContikiMoteType.java index ce80fdce6..8dfab0a08 100644 --- a/tools/cooja/java/se/sics/cooja/contikimote/ContikiMoteType.java +++ b/tools/cooja/java/se/sics/cooja/contikimote/ContikiMoteType.java @@ -45,7 +45,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; -import java.util.Properties; +import java.util.HashMap; import java.util.Random; import java.util.Vector; import java.util.regex.Matcher; @@ -199,13 +199,8 @@ public class ContikiMoteType implements MoteType { // Type specific class configuration private ProjectConfig myConfig = null; - private int relAddressOfReferenceVariable = 0; - private CoreComm myCoreComm = null; - // Variable name to address mappings - private Properties varAddresses = new Properties(); - // Initial memory for all motes of this type private SectionMoteMemory initialMemory = null; @@ -403,14 +398,16 @@ public class ContikiMoteType implements MoteType { int dataSectionAddr = -1, dataSectionSize = -1; int bssSectionAddr = -1, bssSectionSize = -1; int commonSectionAddr = -1, commonSectionSize = -1; + int readonlySectionAddr = -1, readonlySectionSize = -1; + HashMap addresses = new HashMap(); if (useCommand) { /* Parse command output */ String[] output = loadCommandData(getContikiFirmwareFile()); if (output == null) { throw new MoteTypeCreationException("No parse command output loaded"); } - boolean parseOK = parseCommandData(output, varAddresses); + boolean parseOK = parseCommandData(output, addresses); if (!parseOK) { logger.fatal("Command output parsing failed"); throw new MoteTypeCreationException("Command output parsing failed"); @@ -422,6 +419,14 @@ public class ContikiMoteType implements MoteType { bssSectionSize = parseCommandBssSectionSize(output); commonSectionAddr = parseCommandCommonSectionAddr(output); commonSectionSize = parseCommandCommonSectionSize(output); + + try { + readonlySectionAddr = parseCommandReadonlySectionAddr(output); + readonlySectionSize = parseCommandReadonlySectionSize(output); + } catch (Exception e) { + readonlySectionAddr = -1; + readonlySectionSize = -1; + } } else { /* Parse command output */ @@ -434,7 +439,7 @@ public class ContikiMoteType implements MoteType { logger.fatal("No map data could be loaded"); throw new MoteTypeCreationException("No map data could be loaded: " + mapFile); } - boolean parseOK = parseMapFileData(mapData, varAddresses); + boolean parseOK = parseMapFileData(mapData, addresses); if (!parseOK) { logger.fatal("Map data parsing failed"); throw new MoteTypeCreationException("Map data parsing failed: " + mapFile); @@ -446,52 +451,99 @@ public class ContikiMoteType implements MoteType { bssSectionSize = parseMapBssSectionSize(mapData); commonSectionAddr = parseMapCommonSectionAddr(mapData); commonSectionSize = parseMapCommonSectionSize(mapData); - + readonlySectionAddr = -1; + readonlySectionSize = -1; + } - if (varAddresses.size() == 0) { + if (dataSectionAddr >= 0) { + logger.info(getContikiFirmwareFile().getName() + + ": data section at 0x" + Integer.toHexString(dataSectionAddr) + + " (" + dataSectionSize + " bytes)"); + } else { + logger.fatal(getContikiFirmwareFile().getName() + ": no data section found"); + } + if (bssSectionAddr >= 0) { + logger.info(getContikiFirmwareFile().getName() + + ": BSS section at 0x" + Integer.toHexString(bssSectionAddr) + + " (" + bssSectionSize + " bytes)"); + } else { + logger.fatal(getContikiFirmwareFile().getName() + ": no BSS section found"); + } + if (commonSectionAddr >= 0) { + logger.info(getContikiFirmwareFile().getName() + + ": common section at 0x" + Integer.toHexString(commonSectionAddr) + + " (" + commonSectionSize + " bytes)"); + } else { + logger.info(getContikiFirmwareFile().getName() + ": no common section found"); + } + if (readonlySectionAddr >= 0) { + logger.info(getContikiFirmwareFile().getName() + + ": readonly section at 0x" + Integer.toHexString(readonlySectionAddr) + + " (" + readonlySectionSize + " bytes)"); + } else { + logger.warn(getContikiFirmwareFile().getName() + ": no readonly section found"); + } + if (addresses.size() == 0) { throw new MoteTypeCreationException("Library variables parsing failed"); } - - try { - /* Relative <-> absolute addresses offset */ - relAddressOfReferenceVariable = (Integer) varAddresses.get("referenceVar"); - } catch (Exception e) { - throw (MoteTypeCreationException) new MoteTypeCreationException( - "JNI call error: " + e.getMessage()).initCause(e); - } - if (dataSectionAddr <= 0 || dataSectionSize <= 0 || bssSectionAddr <= 0 || bssSectionSize <= 0) { throw new MoteTypeCreationException("Library section addresses parsing failed"); } - myCoreComm.setReferenceAddress(relAddressOfReferenceVariable); + try { + /* Relative <-> absolute addresses offset */ + int referenceVar = (Integer) addresses.get("referenceVar"); + myCoreComm.setReferenceAddress(referenceVar); + } catch (Exception e) { + throw (MoteTypeCreationException) new MoteTypeCreationException( + "JNI call error: " + e.getMessage()).initCause(e); + } + /* We first need the value of Contiki's referenceVar, which tells us the + * memory offset between Contiki's variable and the relative addresses that + * were calculated directly from the library file. + * + * This offset will be used in Cooja in the memory abstraction to match + * Contiki's and Cooja's address spaces */ + int offset; + { + SectionMoteMemory tmp = new SectionMoteMemory(addresses, 0); + byte[] data = new byte[dataSectionSize]; + getCoreMemory(dataSectionAddr, dataSectionSize, data); + tmp.setMemorySegment(dataSectionAddr, data); + byte[] bss = new byte[bssSectionSize]; + getCoreMemory(bssSectionAddr, bssSectionSize, bss); + tmp.setMemorySegment(bssSectionAddr, bss); + + offset = tmp.getIntValueOf("referenceVar"); + logger.info(getContikiFirmwareFile().getName() + + ": offsetting Contiki mote address space: " + offset); + } + /* Create initial memory: data+bss+optional common */ - initialMemory = new SectionMoteMemory(varAddresses); + initialMemory = new SectionMoteMemory(addresses, offset); byte[] initialDataSection = new byte[dataSectionSize]; getCoreMemory(dataSectionAddr, dataSectionSize, initialDataSection); - initialMemory.setMemorySegment(dataSectionAddr, initialDataSection); - logger.info(getContikiFirmwareFile().getName() + - ": data section at 0x" + Integer.toHexString(dataSectionAddr) + - " (" + dataSectionSize + " bytes)"); + initialMemory.setMemorySegmentNative(dataSectionAddr, initialDataSection); byte[] initialBssSection = new byte[bssSectionSize]; getCoreMemory(bssSectionAddr, bssSectionSize, initialBssSection); - initialMemory.setMemorySegment(bssSectionAddr, initialBssSection); - logger.info(getContikiFirmwareFile().getName() + - ": BSS section at 0x" + Integer.toHexString(bssSectionAddr) + - " (" + bssSectionSize + " bytes)"); + initialMemory.setMemorySegmentNative(bssSectionAddr, initialBssSection); - if (commonSectionAddr > 0 && commonSectionSize > 0) { + if (commonSectionAddr >= 0 && commonSectionSize > 0) { byte[] initialCommonSection = new byte[commonSectionSize]; getCoreMemory(commonSectionAddr, commonSectionSize, initialCommonSection); - initialMemory.setMemorySegment(commonSectionAddr, initialCommonSection); - logger.info(getContikiFirmwareFile().getName() + - ": common section at 0x" + Integer.toHexString(commonSectionAddr) + - " (" + commonSectionSize + " bytes)"); + initialMemory.setMemorySegmentNative(commonSectionAddr, initialCommonSection); + } + + /* Read "read-only" memory */ + if (readonlySectionAddr >= 0 && readonlySectionSize > 0) { + byte[] readonlySection = new byte[readonlySectionSize]; + getCoreMemory(readonlySectionAddr, readonlySectionSize, readonlySection); + initialMemory.setReadonlyMemorySegment(readonlySectionAddr+offset, readonlySection); } } @@ -524,7 +576,7 @@ public class ContikiMoteType implements MoteType { public void setCoreMemory(SectionMoteMemory mem) { for (int i = 0; i < mem.getNumberOfSections(); i++) { setCoreMemory( - mem.getStartAddrOfSection(i), + mem.getSectionNativeAddress(i) /* native address space */, mem.getSizeOfSection(i), mem.getDataOfSection(i)); } } @@ -538,8 +590,7 @@ public class ContikiMoteType implements MoteType { * @param varAddresses * Properties that should contain the name to addresses mappings. */ - public static boolean parseMapFileData(String[] mapFileData, - Properties varAddresses) { + public static boolean parseMapFileData(String[] mapFileData, HashMap varAddresses) { String[] varNames = getMapFileVarNames(mapFileData); if (varNames == null || varNames.length == 0) { return false; @@ -565,7 +616,7 @@ public class ContikiMoteType implements MoteType { * @param output Command output * @param addresses Variable addresses mappings */ - public static boolean parseCommandData(String[] output, Properties addresses) { + public static boolean parseCommandData(String[] output, HashMap addresses) { int nrNew = 0, nrOld = 0, nrMismatch = 0; Pattern pattern = @@ -615,10 +666,9 @@ public class ContikiMoteType implements MoteType { */ public void getCoreMemory(SectionMoteMemory mem) { for (int i = 0; i < mem.getNumberOfSections(); i++) { - int startAddr = mem.getStartAddrOfSection(i); + int startAddr = mem.getSectionNativeAddress(i); /* native address space */ int size = mem.getSizeOfSection(i); byte[] data = mem.getDataOfSection(i); - getCoreMemory(startAddr, size, data); } } @@ -689,12 +739,10 @@ public class ContikiMoteType implements MoteType { * @param varName Name of variable * @return Relative memory address of variable or -1 if not found */ - public static int getMapFileVarAddress(String[] mapFileData, String varName, Properties varAddresses) { - int varAddr; - String varAddrString; - if ((varAddrString = varAddresses.getProperty(varName)) != null) { - varAddr = Integer.parseInt(varAddrString); - return varAddr; + private static int getMapFileVarAddress(String[] mapFileData, String varName, HashMap varAddresses) { + Integer varAddrInteger; + if ((varAddrInteger = varAddresses.get(varName)) != null) { + return varAddrInteger.intValue(); } String regExp = @@ -704,9 +752,9 @@ public class ContikiMoteType implements MoteType { String retString = getFirstMatchGroup(mapFileData, regExp, 1); if (retString != null) { - varAddresses.setProperty(varName, Integer.toString(Integer.parseInt( - retString.trim(), 16))); - return Integer.parseInt(retString.trim(), 16); + varAddrInteger = Integer.parseInt(retString.trim(), 16); + varAddresses.put(varName, varAddrInteger); + return varAddrInteger.intValue(); } else { return -1; } @@ -760,7 +808,7 @@ public class ContikiMoteType implements MoteType { return varNames.toArray(new String[0]); } - public static String[] getAllVariableNames(String[] lines, + private static String[] getAllVariableNames(String[] lines, int startAddress, int endAddress) { ArrayList varNames = new ArrayList(); @@ -914,6 +962,21 @@ public class ContikiMoteType implements MoteType { } return end - start; } + + private static int parseCommandReadonlySectionAddr(String[] output) { + return parseFirstHexInt("^([0-9A-Fa-f]*)[ \t]t[ \t].text$", output); + } + private static int parseCommandReadonlySectionSize(String[] output) { + int start = parseCommandReadonlySectionAddr(output); + if (start < 0) { + return -1; + } + + /* Extract the last specified address, assuming that the interval covers all the memory */ + String last = output[output.length-1]; + int lastAddress = Integer.parseInt(last.split("[ \t]")[0],16); + return lastAddress - start; + } private static int getRelVarAddr(String mapFileData[], String varName) { String regExp = diff --git a/tools/cooja/java/se/sics/cooja/dialogs/CompileContiki.java b/tools/cooja/java/se/sics/cooja/dialogs/CompileContiki.java index 3234a6cdc..abc9c31bc 100644 --- a/tools/cooja/java/se/sics/cooja/dialogs/CompileContiki.java +++ b/tools/cooja/java/se/sics/cooja/dialogs/CompileContiki.java @@ -495,6 +495,7 @@ public class CompileContiki { env.add(new String[] { "COOJA_SOURCEDIRS", "" }); env.add(new String[] { "COOJA_SOURCEFILES", "" }); env.add(new String[] { "CC", GUI.getExternalToolsSetting("PATH_C_COMPILER") }); + env.add(new String[] { "OBJCOPY", GUI.getExternalToolsSetting("PATH_OBJCOPY") }); env.add(new String[] { "EXTRA_CC_ARGS", ccFlags }); env.add(new String[] { "LD", GUI.getExternalToolsSetting("PATH_LINKER") }); env.add(new String[] { "LINK_COMMAND_1", link1 }); diff --git a/tools/cooja/java/se/sics/cooja/dialogs/ConfigurationWizard.java b/tools/cooja/java/se/sics/cooja/dialogs/ConfigurationWizard.java index 6683c5d6f..f61b82c8d 100644 --- a/tools/cooja/java/se/sics/cooja/dialogs/ConfigurationWizard.java +++ b/tools/cooja/java/se/sics/cooja/dialogs/ConfigurationWizard.java @@ -50,7 +50,7 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.lang.reflect.Constructor; -import java.util.Properties; +import java.util.HashMap; import javax.swing.Box; import javax.swing.BoxLayout; @@ -66,11 +66,12 @@ import javax.swing.JScrollPane; import se.sics.cooja.CoreComm; import se.sics.cooja.GUI; -import se.sics.cooja.SectionMoteMemory; import se.sics.cooja.MoteType.MoteTypeCreationException; +import se.sics.cooja.SectionMoteMemory; import se.sics.cooja.contikimote.ContikiMoteType; /* TODO Test common section */ +/* TODO Test readonly section */ public class ConfigurationWizard extends JDialog { private static final long serialVersionUID = 1L; @@ -141,7 +142,7 @@ public class ConfigurationWizard extends JDialog { private static File cLibraryFile; private static String javaLibraryName; private static CoreComm javaLibrary; - private static Properties addresses; + private static HashMap addresses; private static int relDataSectionAddr; private static int dataSectionSize; private static int relBssSectionAddr; @@ -195,7 +196,7 @@ public class ConfigurationWizard extends JDialog { "Changes made in this wizard are reflected in menu Settings, External tools paths.\n" + "\n" + "NOTE: You do not need to complete this wizard for emulating motes, such as Sky motes.\n", - "Configuration Wizard", + "Contiki mote configuration wizard", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]); @@ -756,7 +757,7 @@ public class ConfigurationWizard extends JDialog { } testOutput.addMessage("### Parsing map file data for addresses"); - addresses = new Properties(); + addresses = new HashMap(); boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses); if (!parseOK) { testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR); @@ -836,7 +837,7 @@ public class ConfigurationWizard extends JDialog { } testOutput.addMessage("### Parsing command output for addresses"); - addresses = new Properties(); + addresses = new HashMap(); boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses); if (!parseOK) { testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR); @@ -930,11 +931,11 @@ public class ConfigurationWizard extends JDialog { testOutput.addMessage("### Testing Contiki library memory replacement"); testOutput.addMessage("### Configuring Contiki using parsed reference address"); - int relRefAddress = (Integer) addresses.get("ref_var"); - if (!addresses.containsKey("ref_var")) { - testOutput.addMessage("Could not find address of ref_var", MessageList.ERROR); + if (!addresses.containsKey("referenceVar")) { + testOutput.addMessage("Could not find address of referenceVar", MessageList.ERROR); return false; } + int relRefAddress = (Integer) addresses.get("referenceVar"); javaLibrary.setReferenceAddress(relRefAddress); testOutput.addMessage("### Creating data and BSS memory sections"); @@ -942,7 +943,7 @@ public class ConfigurationWizard extends JDialog { byte[] initialBssSection = new byte[bssSectionSize]; javaLibrary.getMemory(relDataSectionAddr, dataSectionSize, initialDataSection); javaLibrary.getMemory(relBssSectionAddr, bssSectionSize, initialBssSection); - SectionMoteMemory memory = new SectionMoteMemory(addresses); + SectionMoteMemory memory = new SectionMoteMemory(addresses, 0); memory.setMemorySegment(relDataSectionAddr, initialDataSection); memory.setMemorySegment(relBssSectionAddr, initialBssSection); diff --git a/tools/cooja/java/se/sics/cooja/interfaces/Mote2MoteRelations.java b/tools/cooja/java/se/sics/cooja/interfaces/Mote2MoteRelations.java index 50943debb..913c56a9c 100644 --- a/tools/cooja/java/se/sics/cooja/interfaces/Mote2MoteRelations.java +++ b/tools/cooja/java/se/sics/cooja/interfaces/Mote2MoteRelations.java @@ -48,8 +48,7 @@ import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; -import se.sics.cooja.SimEventCentral.LogOutputEvent; -import se.sics.cooja.SimEventCentral.LogOutputListener; +import se.sics.cooja.SimEventCentral.MoteCountListener; /** * Mote2Mote Relations is used to show mote relations in simulated @@ -83,13 +82,32 @@ public class Mote2MoteRelations extends MoteInterface { private ArrayList relations = new ArrayList(); private GUI gui; - private LogOutputListener logListener; - + private Observer logObserver = new Observer() { + public void update(Observable o, Object arg) { + String msg = ((Log) o).getLastLogMessage(); + handleNewLog(msg); + }; + }; + + private MoteCountListener moteCountListener; + public Mote2MoteRelations(Mote mote) { this.mote = mote; this.gui = mote.getSimulation().getGUI(); + } - mote.getSimulation().getEventCentral().addLogOutputListener(logListener = new LogOutputListener() { + public void added() { + super.added(); + + /* Observe log interfaces */ + for (MoteInterface mi: mote.getInterfaces().getInterfaces()) { + if (mi instanceof Log) { + ((Log)mi).addObserver(logObserver); + } + } + + /* Observe other motes: if removed, remove our relations to them too */ + mote.getSimulation().getEventCentral().addMoteCountListener(moteCountListener = new MoteCountListener() { public void moteWasAdded(Mote mote) { /* Ignored */ } @@ -106,28 +124,28 @@ public class Mote2MoteRelations extends MoteInterface { relations.remove(mote); gui.removeMoteRelation(Mote2MoteRelations.this.mote, mote); } - public void newLogOutput(LogOutputEvent ev) { - if (ev.getMote() != Mote2MoteRelations.this.mote) { - return; - } - handleNewLog(ev.msg); - } - public void removedLogOutput(LogOutputEvent ev) { - /* Ignored */ - } }); } - + public void removed() { super.removed(); + /* Stop observing log interfaces */ + for (MoteInterface mi: mote.getInterfaces().getInterfaces()) { + if (mi instanceof Log) { + ((Log)mi).deleteObserver(logObserver); + } + } + logObserver = null; + + /* Remove all relations to other motes */ Mote[] relationsArr = relations.toArray(new Mote[0]); for (Mote m: relationsArr) { gui.removeMoteRelation(Mote2MoteRelations.this.mote, m); } relations.clear(); - mote.getSimulation().getEventCentral().removeLogOutputListener(logListener); + mote.getSimulation().getEventCentral().removeMoteCountListener(moteCountListener); } private void handleNewLog(String msg) { diff --git a/tools/cooja/java/se/sics/cooja/interfaces/MoteAttributes.java b/tools/cooja/java/se/sics/cooja/interfaces/MoteAttributes.java index ca560c2c2..57310c462 100644 --- a/tools/cooja/java/se/sics/cooja/interfaces/MoteAttributes.java +++ b/tools/cooja/java/se/sics/cooja/interfaces/MoteAttributes.java @@ -46,8 +46,6 @@ import org.jdom.Element; import se.sics.cooja.ClassDescription; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; -import se.sics.cooja.SimEventCentral.LogOutputEvent; -import se.sics.cooja.SimEventCentral.LogOutputListener; import se.sics.cooja.plugins.skins.AttributeVisualizerSkin; /** @@ -86,33 +84,38 @@ public class MoteAttributes extends MoteInterface { private HashMap attributes = new HashMap(); - private LogOutputListener logListener; - + private Observer logObserver = new Observer() { + public void update(Observable o, Object arg) { + String msg = ((Log) o).getLastLogMessage(); + handleNewLog(msg); + }; + }; + public MoteAttributes(Mote mote) { this.mote = mote; - - mote.getSimulation().getEventCentral().addLogOutputListener(logListener = new LogOutputListener() { - public void moteWasAdded(Mote mote) { - /* Ignored */ - } - public void moteWasRemoved(Mote mote) { - /* Ignored */ - } - public void newLogOutput(LogOutputEvent ev) { - if (ev.getMote() != MoteAttributes.this.mote) { - return; - } - handleNewLog(ev.msg); - } - public void removedLogOutput(LogOutputEvent ev) { - /* Ignored */ - } - }); } + public void added() { + super.added(); + + /* Observe log interfaces */ + for (MoteInterface mi: mote.getInterfaces().getInterfaces()) { + if (mi instanceof Log) { + ((Log)mi).addObserver(logObserver); + } + } + } + public void removed() { super.removed(); - mote.getSimulation().getEventCentral().removeLogOutputListener(logListener); + + /* Stop observing log interfaces */ + for (MoteInterface mi: mote.getInterfaces().getInterfaces()) { + if (mi instanceof Log) { + ((Log)mi).deleteObserver(logObserver); + } + } + logObserver = null; } private void handleNewLog(String msg) { diff --git a/tools/cooja/java/se/sics/cooja/interfaces/RimeAddress.java b/tools/cooja/java/se/sics/cooja/interfaces/RimeAddress.java index 478b9a6a5..b7a8907ff 100644 --- a/tools/cooja/java/se/sics/cooja/interfaces/RimeAddress.java +++ b/tools/cooja/java/se/sics/cooja/interfaces/RimeAddress.java @@ -41,13 +41,12 @@ import javax.swing.JPanel; import org.apache.log4j.Logger; import org.jdom.Element; -import se.sics.cooja.AddressMemory; import se.sics.cooja.ClassDescription; import se.sics.cooja.Mote; import se.sics.cooja.MoteInterface; -import se.sics.cooja.MoteTimeEvent; -import se.sics.cooja.Simulation; -import se.sics.cooja.TimeEvent; +import se.sics.cooja.MoteMemory; +import se.sics.cooja.MoteMemory.MemoryEventType; +import se.sics.cooja.MoteMemory.MemoryMonitor; /** * Read-only interface to Rime address read from Contiki variable: rimeaddr_node_addr. @@ -59,37 +58,27 @@ import se.sics.cooja.TimeEvent; @ClassDescription("Rime address") public class RimeAddress extends MoteInterface { private static Logger logger = Logger.getLogger(RimeAddress.class); - private AddressMemory moteMem; + private MoteMemory moteMem; public static final int RIME_ADDR_LENGTH = 2; - + + private MemoryMonitor memMonitor = null; + public RimeAddress(final Mote mote) { - moteMem = (AddressMemory) mote.getMemory(); - - /* Detect startup address (only zeroes) */ - TimeEvent updateWhenAddressReady = new MoteTimeEvent(mote, 0) { - public void execute(long t) { - if (!hasRimeAddress()) { - return; - } - - String addrString = getAddressString(); - addrString = addrString.replace(".", ""); - addrString = addrString.replace("0", ""); - if (!addrString.isEmpty()) { + moteMem = mote.getMemory(); + if (hasRimeAddress()) { + memMonitor = new MemoryMonitor() { + public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) { + if (type != MemoryEventType.WRITE) { + return; + } setChanged(); notifyObservers(); - return; } - - /* Postpone until address has been set */ - mote.getSimulation().scheduleEvent( - this, - mote.getSimulation().getSimulationTime() + Simulation.MILLISECOND); - return; - } - }; - updateWhenAddressReady.execute(0); + }; + /* TODO XXX Timeout? */ + moteMem.addMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); + } } public boolean hasRimeAddress() { @@ -140,6 +129,13 @@ public class RimeAddress extends MoteInterface { this.deleteObserver(observer); } + public void removed() { + super.removed(); + if (memMonitor != null) { + moteMem.removeMemoryMonitor(moteMem.getVariableAddress("rimeaddr_node_addr"), RIME_ADDR_LENGTH, memMonitor); + } + } + public Collection getConfigXML() { return null; } diff --git a/tools/cooja/java/se/sics/cooja/motes/AbstractApplicationMote.java b/tools/cooja/java/se/sics/cooja/motes/AbstractApplicationMote.java index 3777520b2..437b15765 100644 --- a/tools/cooja/java/se/sics/cooja/motes/AbstractApplicationMote.java +++ b/tools/cooja/java/se/sics/cooja/motes/AbstractApplicationMote.java @@ -31,6 +31,7 @@ package se.sics.cooja.motes; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Observable; import java.util.Observer; import java.util.Properties; @@ -90,7 +91,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme public AbstractApplicationMote(MoteType moteType, Simulation sim) { setSimulation(sim); this.moteType = moteType; - this.memory = new SectionMoteMemory(new Properties()); + this.memory = new SectionMoteMemory(new HashMap(), 0); this.moteInterfaces = new MoteInterfaceHandler(this, moteType.getMoteInterfaceClasses()); this.moteInterfaces.getRadio().addObserver(radioDataObserver); requestImmediateWakeup(); @@ -145,7 +146,7 @@ public abstract class AbstractApplicationMote extends AbstractWakeupMote impleme public boolean setConfigXML(Simulation simulation, Collection configXML, boolean visAvailable) { setSimulation(simulation); - this.memory = new SectionMoteMemory(new Properties()); + this.memory = new SectionMoteMemory(new HashMap(), 0); moteInterfaces.getRadio().addObserver(radioDataObserver); for (Element element : configXML) { diff --git a/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java b/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java index 1d9dae44e..c008d017c 100644 --- a/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java +++ b/tools/cooja/java/se/sics/cooja/motes/AbstractEmulatedMote.java @@ -64,27 +64,4 @@ public abstract class AbstractEmulatedMote extends AbstractWakeupMote implements public String getStackTrace() { return null; } - - public interface MemoryMonitor { - public boolean start(int address, int size); - public void stop(); - public Mote getMote(); - public int getAddress(); - public int getSize(); - - public void setLastBufferAccess(BufferAccess ba); - public BufferAccess getLastBufferAccess(); - - public boolean isPointer(); - public void setPointer(boolean isPointer, MemoryMonitor pointedMemory); - public MemoryMonitor getPointedMemory(); - } - - public enum MemoryEventType { READ, WRITE, UNKNOWN }; - public interface MemoryEventHandler { - public void event(MemoryMonitor mm, MemoryEventType type, int adr, int data); - } - - public abstract MemoryMonitor createMemoryMonitor(MemoryEventHandler meh); - } diff --git a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java index 6e4323650..0a22206a5 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/BufferListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Swedish Institute of Computer Science. + * Copyright (c) 2012, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.regex.PatternSyntaxException; @@ -85,27 +86,26 @@ import javax.swing.table.TableRowSorter; import org.apache.log4j.Logger; import org.jdom.Element; -import se.sics.cooja.AddressMemory; import se.sics.cooja.ClassDescription; import se.sics.cooja.GUI; import se.sics.cooja.Mote; +import se.sics.cooja.MoteMemory; +import se.sics.cooja.MoteMemory.MemoryEventType; import se.sics.cooja.Plugin; import se.sics.cooja.PluginType; import se.sics.cooja.SimEventCentral.MoteCountListener; import se.sics.cooja.Simulation; +import se.sics.cooja.TimeEvent; import se.sics.cooja.VisPlugin; import se.sics.cooja.dialogs.TableColumnAdjuster; import se.sics.cooja.dialogs.UpdateAggregator; import se.sics.cooja.interfaces.IPAddress; import se.sics.cooja.motes.AbstractEmulatedMote; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryEventHandler; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryEventType; -import se.sics.cooja.motes.AbstractEmulatedMote.MemoryMonitor; import se.sics.cooja.util.ArrayQueue; import se.sics.cooja.util.StringUtils; /** - * @author Fredrik Osterlind + * @author Fredrik Osterlind, Niclas Finne */ @ClassDescription("Buffer Listener") @PluginType(PluginType.SIM_PLUGIN) @@ -156,10 +156,11 @@ public class BufferListener extends VisPlugin { registerBufferType(NodeIDBuffer.class); registerBufferType(Queuebuf0Buffer.class); /* TODO Add buffers: Queuebuf(1,2,3,4,..). */ - registerBufferType(CustomVariableBuffer.class); /* Special buffer: Custom Variable */ - registerBufferType(CustomPointerBuffer.class); /* Special buffer: Custom Pointer */ + registerBufferType(CustomVariableBuffer.class); + registerBufferType(CustomIntegerBuffer.class); + registerBufferType(CustomPointerBuffer.class); } - + private Parser parser = null; private Buffer buffer = null; public void startPlugin() { @@ -168,7 +169,12 @@ public class BufferListener extends VisPlugin { setParser(ByteArrayParser.class); } if (buffer == null) { - setBuffer(PacketbufBuffer.class); + Buffer b = createBufferInstance(PacketbufBuffer.class); + if (b != null) { + if (b.configure(BufferListener.this)) { + setBuffer(b); + } + } } } @@ -197,58 +203,21 @@ public class BufferListener extends VisPlugin { private boolean hideReads = true; private JCheckBoxMenuItem hideReadsCheckbox; - + private boolean withStackTrace = false; private JCheckBoxMenuItem withStackTraceCheckbox; - - private JMenu parserMenu = new JMenu("Parser"); - private JMenu bufferMenu = new JMenu("Buffer"); - - private ArrayList monitoredMotes = new ArrayList(); - private ArrayList monitoredMemories = new ArrayList(); - private MemoryEventHandler meh = new MemoryEventHandler() { - public void event(MemoryMonitor mm, MemoryEventType type, int adr, int data) { - MemoryMonitor observedMemory = null; - - if (mm.isPointer()) { - /* Stop observing pointed memory */ - observedMemory = mm.getPointedMemory(); - if (observedMemory == null) { - logger.fatal("No reference to pointed memory!"); - } else { - observedMemory.stop(); - monitoredMemories.remove(observedMemory); - } - /* Restart observing pointed memory */ - observedMemory = startObservingMemory( - (AbstractEmulatedMote) observedMemory.getMote(), - buffer.getAddress(observedMemory.getMote()), - buffer.getSize(observedMemory.getMote()) - ); - mm.setPointer(true, observedMemory); - } else { - observedMemory = mm; - } - - /* Display memory event */ - if (!hasHours && simulation.getSimulationTime() > TIME_HOUR) { - hasHours = true; - repaintTimeColumn(); - } - - BufferAccess previous = null; - previous = mm.getLastBufferAccess(); - BufferAccess current = new BufferAccess( - simulation.getSimulationTime(), - observedMemory, - type, - adr, /* XXX May be wrong if pointer, remove these */ - data, - previous - ); - logUpdateAggregator.add(current); - mm.setLastBufferAccess(current); + private JMenu bufferMenu = new JMenu("Buffer"); + private JMenu parserMenu = new JMenu("Show as"); + + private ArrayList motes = new ArrayList(); + private ArrayList memoryMonitors = new ArrayList(); + + private TimeEvent hourTimeEvent = new TimeEvent(0) { + public void execute(long t) { + hasHours = true; + repaintTimeColumn(); + hourTimeEvent = null; } }; @@ -298,6 +267,13 @@ public class BufferListener extends VisPlugin { super("Buffer Listener - " + "?" + " motes", gui); this.simulation = simulation; + if (simulation.getSimulationTime() > TIME_HOUR) { + hasHours = true; + hourTimeEvent = null; + } else { + simulation.scheduleEvent(hourTimeEvent, TIME_HOUR); + } + model = new AbstractTableModel() { private static final long serialVersionUID = 3065150390849332924L; public String getColumnName(int col) { @@ -315,13 +291,13 @@ public class BufferListener extends VisPlugin { public Object getValueAt(int row, int col) { BufferAccess log = logs.get(row); if (col == COLUMN_TIME) { - return log.getTime(); + return log.getTime(formatTimeString, hasHours); } else if (col == COLUMN_FROM) { return log.getID(); } else if (col == COLUMN_TYPE) { return log.getType(); } else if (col == COLUMN_DATA) { - return log.getParsedData(); + return parser.parse(log); } else if (col == COLUMN_SOURCE) { return log.getSource(); } @@ -343,7 +319,7 @@ public class BufferListener extends VisPlugin { if (row < 0 || column < 0) { return super.getToolTipText(e); } - + if (column == COLUMN_SOURCE) { BufferAccess ba = logs.get(row); if (ba.stackTrace != null) { @@ -356,21 +332,11 @@ public class BufferListener extends VisPlugin { } if (column == COLUMN_DATA) { BufferAccess ba = logs.get(row); - if (parser instanceof GraphicalParser) { - return - "

" +
-            StringUtils.hexDump(ba.mem, 4, 4) +
-            "
"; - } - - String baString = ba.getParsedString(); - StringBuilder sb = new StringBuilder(); - sb.append(""); - while (baString.length() > 60) { - sb.append(baString.substring(0, 60)).append("
"); - baString = baString.substring(60); - }; - return sb.append(baString).append("").toString(); + return + "
" +
+          "Address: " + (ba.address==0?"null":String.format("%04x\n", ba.address)) +
+          StringUtils.hexDump(ba.mem, 4, 4) +
+          "
"; } return super.getToolTipText(e); @@ -417,7 +383,7 @@ public class BufferListener extends VisPlugin { if (isSelected) { bgColor = table.getSelectionBackground(); } - + if (value instanceof BufferAccess && parser instanceof GraphicalParser) { graphicalParserPanel.update((BufferAccess) value, (GraphicalParser)parser); graphicalParserPanel.setBackground(bgColor); @@ -425,7 +391,7 @@ public class BufferListener extends VisPlugin { } else { setBackground(bgColor); } - + return super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); } @@ -593,7 +559,7 @@ public class BufferListener extends VisPlugin { repaint(); } }); - + logTable.setComponentPopupMenu(popupMenu); /* Column width adjustment */ @@ -609,7 +575,11 @@ public class BufferListener extends VisPlugin { simulation.getEventCentral().addMoteCountListener(logOutputListener = new MoteCountListener() { public void moteWasAdded(Mote mote) { /* Update title */ - startObserving(mote); + try { + startMonitoring(mote); + } catch (Exception e) { + logger.warn("Could not monitor buffer on: " + mote, e); + } } public void moteWasRemoved(Mote mote) { /* Update title */ @@ -660,75 +630,151 @@ public class BufferListener extends VisPlugin { setLocation(0, gui.getDesktopPane().getHeight() - 300); } - private boolean startObserving(Mote mote) { - if (!(mote instanceof AbstractEmulatedMote)) { - logger.fatal("Failed creating memory monitor: wrong mote type"); - return false; - } - AbstractEmulatedMote am = (AbstractEmulatedMote) mote; - if (!(am.getMemory() instanceof AddressMemory)) { - logger.fatal("Failed creating memory monitor: wrong memory type"); - return false; - } - + private boolean startMonitoring(Mote mote) throws Exception { /* If this is a pointer buffer, * we must observe both the pointer itself, and the pointed to memory */ - int address = buffer.getAddress(am); - int size = buffer.getSize(am); - if (address < 0 || size < 0 || size > MAX_BUFFER_SIZE) { - logger.fatal("Failed start observing memory: bad addr/size: " + address + "/" + size); - return false; - } - - MemoryMonitor mm = startObservingMemory(am, address, size); - if (mm == null) { - return false; - } - boolean pointer = (buffer instanceof PointerBuffer); - if (pointer) { - int pointerAddress = ((PointerBuffer)buffer).getPointerAddress(am); - /* Whenever the pointer changes, we re-register this observation */ - MemoryMonitor pointerMM = startObservingMemory(am, pointerAddress, 2); - pointerMM.setPointer(true, mm); - } - return true; - } - private MemoryMonitor startObservingMemory(AbstractEmulatedMote mote, int address, int size) { - MemoryMonitor mm = mote.createMemoryMonitor(meh); - if (mm == null) { - logger.fatal("Failed creating memory monitor: not implemented"); - return null; - } - - boolean started = mm.start(address, size); - if (!started) { - logger.fatal("Failed creating memory monitor: could not start monitor"); - return null; - } - - monitoredMemories.add(mm); - /* TODO Don't keep pointed memories in this list. - * Instead automatically unregister them from their parent memories. */ - if (!monitoredMotes.contains(mote)) { - monitoredMotes.add(mote); + SegmentMemoryMonitor mm = buffer.createMemoryMonitor(this, mote); + memoryMonitors.add(mm); + if (!motes.contains(mote)) { + motes.add(mote); } updateTitle(); - return mm; + return true; } - private void stopObserving(Mote mote) { - if (!(mote instanceof AbstractEmulatedMote)) { - return; + + public enum MemoryMonitorType { SEGMENT, POINTER, CONSTPOINTER }; + + static class PointerMemoryMonitor extends SegmentMemoryMonitor { + private SegmentMemoryMonitor segmentMonitor = null; + private int lastSegmentAddress = -1; + private final int pointerAddress; + private final int pointerSize; + + public PointerMemoryMonitor( + BufferListener bl, Mote mote, + int pointerAddress, int pointerSize, int segmentSize) + throws Exception { + super(bl, mote, pointerAddress, pointerSize); + this.pointerAddress = pointerAddress; + this.pointerSize = pointerSize; + + registerSegmentMonitor(segmentSize, false); } - for (MemoryMonitor mm: monitoredMemories.toArray(new MemoryMonitor[0])) { - if (mm.getMote() == mote) { - mm.stop(); - monitoredMemories.remove(mm); + private void registerSegmentMonitor(int size, boolean notify) throws Exception { + byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize); + int segmentAddress = mote.getMemory().parseInt(pointerValue); + + segmentMonitor = new SegmentMemoryMonitor(bl, mote, segmentAddress, size); + if (notify) { + segmentMonitor.memoryChanged(mote.getMemory(), MemoryEventType.WRITE, -1); + } + lastSegmentAddress = segmentAddress; + } + + final public void memoryChanged(MoteMemory memory, + se.sics.cooja.MoteMemory.MemoryEventType type, int address) { + if (type == MemoryEventType.READ) { + return; + } + + byte[] pointerValue = mote.getMemory().getMemorySegment(pointerAddress, pointerSize); + int segmentAddress = mote.getMemory().parseInt(pointerValue); + if (segmentAddress == lastSegmentAddress) { + return; + } + + /* Pointer changed - we need to create new segment monitor */ + segmentMonitor.dispose(); + try { + registerSegmentMonitor(segmentMonitor.getSize(), true); + } catch (Exception e) { + logger.warn("Could not re-register memory monitor on: " + mote, e); } } - monitoredMotes.remove(mote); + public MemoryMonitorType getType() { + return MemoryMonitorType.POINTER; + } + + public void dispose() { + super.dispose(); + segmentMonitor.dispose(); + } + } + + static class SegmentMemoryMonitor implements se.sics.cooja.MoteMemory.MemoryMonitor { + protected final BufferListener bl; + protected final Mote mote; + + private final int address; + private final int size; + + private byte[] oldData = null; + + public SegmentMemoryMonitor(BufferListener bl, Mote mote, int address, int size) + throws Exception { + this.bl = bl; + this.mote = mote; + this.address = address; + this.size = size; + + if (address != 0) { + if (!mote.getMemory().addMemoryMonitor(address, size, this)) { + throw new Exception("Could not register memory monitor on: " + mote); + } + } + } + + public Mote getMote() { + return mote; + } + public int getAddress() { + return address; + } + public int getSize() { + return size; + } + public MemoryMonitorType getType() { + return MemoryMonitorType.SEGMENT; + } + + public void dispose() { + if (address != 0) { + mote.getMemory().removeMemoryMonitor(address, size, this); + } + } + + public void memoryChanged(MoteMemory memory, MemoryEventType type, int address) { + byte[] newData = getAddress()==0?null:mote.getMemory().getMemorySegment(getAddress(), getSize()); + addBufferAccess(bl, mote, oldData, newData, type, this.address); + oldData = newData; + } + + void addBufferAccess(BufferListener bl, Mote mote, byte[] oldData, byte[] newData, MemoryEventType type, int address) { + BufferAccess ba = new BufferAccess( + mote, + mote.getSimulation().getSimulationTime(), + address, + newData, + oldData, + type, + bl.withStackTrace + ); + bl.logUpdateAggregator.add(ba); + } + } + + private void stopObserving(Mote mote) { + for (SegmentMemoryMonitor mm: memoryMonitors.toArray(new SegmentMemoryMonitor[0])) { + if (mm.getMote() == mote) { + mm.dispose(); + memoryMonitors.remove(mm); + } + } + + motes.remove(mote); updateTitle(); } @@ -740,37 +786,16 @@ public class BufferListener extends VisPlugin { private void updateTitle() { if (buffer != null) { - String bufferDesc = GUI.getDescriptionOf(buffer); - /* Special buffer: Custom Variable/Custom Pointer */ - if (buffer.getClass() == CustomVariableBuffer.class) { - int offset = ((CustomVariableBuffer)buffer).getOffset(); - if (offset > 0) { - bufferDesc = "&" + ((CustomVariableBuffer)buffer).getVariable() + "[" + offset + "] (" + ((CustomVariableBuffer)buffer).getSize() + ")"; - } else { - bufferDesc = ((CustomVariableBuffer)buffer).getVariable() + " (" + ((CustomVariableBuffer)buffer).getSize() + ")"; - } - } else if (buffer.getClass() == CustomPointerBuffer.class) { - int offset = ((CustomPointerBuffer)buffer).getOffset(); - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + " (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - if (offset > 0) { - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + "[" + offset + "] (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - } else { - bufferDesc = "*" + ((CustomPointerBuffer)buffer).getVariable() + " (" + ((CustomPointerBuffer)buffer).getSize() + ")"; - } - } - - int count=0; - for (MemoryMonitor mm: monitoredMemories) { - if (mm.isPointer()) continue; - count++; - } + String status = buffer.getStatusString(); setTitle("Buffer Listener - " + - bufferDesc + " - " + - count + " buffers on " + monitoredMotes.size() + " motes"); + ((status!=null)?status:GUI.getDescriptionOf(buffer)) + " " + + "- " + memoryMonitors.size() + " buffers on " + motes.size() + " motes"); } } public void closePlugin() { + if (hourTimeEvent != null) hourTimeEvent.remove(); + /* Stop observing motes */ logUpdateAggregator.stop(); simulation.getEventCentral().removeMoteCountListener(logOutputListener); @@ -814,18 +839,9 @@ public class BufferListener extends VisPlugin { element = new Element("buffer"); element.setText(buffer.getClass().getName()); - /* Special buffer: Custom Variable/Custom Pointer */ - if (buffer.getClass() == CustomVariableBuffer.class) { - element.setAttribute("variable", ((CustomVariableBuffer) buffer).getVariable()); - element.setAttribute("size", "" + ((CustomVariableBuffer) buffer).getSize()); - element.setAttribute("offset", "" + ((CustomVariableBuffer) buffer).getOffset()); - } else if (buffer.getClass() == CustomPointerBuffer.class) { - element.setAttribute("variable", ((CustomPointerBuffer) buffer).getVariable()); - element.setAttribute("size", "" + ((CustomPointerBuffer) buffer).getSize()); - element.setAttribute("offset", "" + ((CustomPointerBuffer) buffer).getOffset()); - } + buffer.writeConfig(element); config.add(element); - + return config; } @@ -865,21 +881,15 @@ public class BufferListener extends VisPlugin { } } else if ("buffer".equals(name)) { String bufferClassname = element.getText(); - Class bufferClass = + Class btClass = simulation.getGUI().tryLoadClass(this, Buffer.class, bufferClassname); - if (bufferClass == null) { + if (btClass == null) { logger.warn("Could not create buffer parser: could not find class: " + bufferClassname); } else { - - /* Special buffer: Custom Variable/Custom Pointer */ - if (bufferClass == CustomVariableBuffer.class || - bufferClass == CustomPointerBuffer.class) { - String varName = element.getAttributeValue("variable"); - int varSize = Integer.parseInt(element.getAttributeValue("size")); - int offset = Integer.parseInt(element.getAttributeValue("offset")); - setBuffer(bufferClass, varName, varSize, offset); - } else { - setBuffer(bufferClass); + Buffer b = createBufferInstance(btClass); + if (b != null) { + b.applyConfig(element); + setBuffer(b); } } } @@ -907,13 +917,13 @@ public class BufferListener extends VisPlugin { public boolean include(RowFilter.Entry entry) { if (hideReads) { int row = (Integer) entry.getIdentifier(); - if (logs.get(row).isRead) { + if (logs.get(row).type == MemoryEventType.READ) { return false; } } if (regexp != null) { boolean pass = regexp.include(entry); - + if (inverseFilter && pass) { return false; } else if (!inverseFilter && !pass) { @@ -953,80 +963,63 @@ public class BufferListener extends VisPlugin { }); } - public class BufferAccess { - public final AbstractEmulatedMote mote; - public final long time; - - public final boolean isRead; + public static class BufferAccess { + public static final byte[] NULL_DATA = new byte[0]; - private MemoryMonitor mm; - private int adr; - - public final String typeStr; + public final Mote mote; + public final long time; + + public final byte[] mem; + private boolean[] accessedBitpattern = null; + + public final MemoryEventType type; public final String sourceStr; public final String stackTrace; - public final byte[] mem; - - private boolean[] accessedBitpattern = null; - + public final int address; + public BufferAccess( - long time, MemoryMonitor mm, - MemoryEventType type, int adr, int data, - BufferAccess previous) { + Mote mote, long time, int address, byte[] newData, byte[] oldData, MemoryEventType type, boolean withStackTrace) { + this.mote = mote; this.time = time; - this.mote = (AbstractEmulatedMote) mm.getMote(); - this.mm = mm; - this.adr = adr; - this.isRead = (type == MemoryEventType.READ); - this.mem = mm.getMote().getMemory().getMemorySegment(mm.getAddress(), mm.getSize()); - - /* Apply currently written data, if write operation */ - if (type == MemoryEventType.WRITE) { - if (adr >= mm.getAddress() && adr < mm.getAddress() + mm.getSize()) { - int offset = adr - mm.getAddress(); - byte now = (byte)(0xff&data); - /*byte prev = mem[offset];*/ - /*logger.debug(String.format( - "WRITE: 0x%02x: %02x -> %02x", adr, prev, now));*/ - mem[offset] = now; - } else { - logger.warn(String.format( - "Write operation outside monitored addresses: %x !@ %x - %x", - adr, mm.getAddress(), mm.getAddress()+mm.getSize())); - } - } - + this.mem = newData==null?NULL_DATA:newData; + this.type = type; + this.address = address; + /* Generate diff bit pattern */ - if (previous != null) { - accessedBitpattern = new boolean[previous.mem.length]; - for (int i=0; i < previous.mem.length; i++) { - accessedBitpattern[i] = (previous.mem[i] != mem[i]); + if (newData != null && oldData != null) { + accessedBitpattern = new boolean[newData.length]; + for (int i=0; i < newData.length; i++) { + accessedBitpattern[i] = (oldData[i] != mem[i]); } + } else if (newData != null) { + accessedBitpattern = new boolean[newData.length]; + Arrays.fill(accessedBitpattern, true); } - - typeStr = type.toString(); - String s = mote.getPCString(); - sourceStr = s==null?"[unknown]":s; - if (withStackTrace) { - this.stackTrace = mote.getStackTrace(); + + if (mote instanceof AbstractEmulatedMote) { + String s = ((AbstractEmulatedMote)mote).getPCString(); + sourceStr = s==null?"[unknown]":s; + if (withStackTrace) { + this.stackTrace = ((AbstractEmulatedMote)mote).getStackTrace(); + } else { + this.stackTrace = null; + } } else { + this.sourceStr = "[unknown]"; this.stackTrace = null; } } - public Object getParsedData() { - return parser.parse(mm, adr, this); + public String getAsHex() { + return String.format("%04x", address) + ":" + StringUtils.toHex(mem); } - public String getParsedString() { - return StringUtils.toHex(mem); - } - + public boolean[] getAccessedBitpattern() { return accessedBitpattern; } public String getType() { - return typeStr; + return type.toString(); } public Object getSource() { @@ -1036,8 +1029,8 @@ public class BufferListener extends VisPlugin { public String getID() { return "ID:" + mote.getID(); } - - public String getTime() { + + public String getTime(boolean formatTimeString, boolean hasHours) { if (formatTimeString) { long t = time; long h = (t / TIME_HOUR); @@ -1104,7 +1097,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1153,20 +1146,20 @@ public class BufferListener extends VisPlugin { } int model = logTable.convertRowIndexToModel(view); long time = logs.get(model).time; - + Plugin[] plugins = simulation.getGUI().getStartedPlugins(); for (Plugin p: plugins) { if (!(p instanceof TimeLine)) { continue; } - + /* Select simulation time */ TimeLine plugin = (TimeLine) p; plugin.trySelectTime(time); } } }; - + private Action radioLoggerAction = new AbstractAction("in Radio Logger") { private static final long serialVersionUID = -3041714249257346688L; public void actionPerformed(ActionEvent e) { @@ -1193,7 +1186,7 @@ public class BufferListener extends VisPlugin { private Action showInAllAction = new AbstractAction("All") { private static final long serialVersionUID = -8433490108577001803L; { - putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true)); } public void actionPerformed(ActionEvent e) { @@ -1230,7 +1223,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1260,7 +1253,7 @@ public class BufferListener extends VisPlugin { sb.append("\t"); if (parser instanceof GraphicalParser) { BufferAccess ba = (BufferAccess) logTable.getValueAt(i, COLUMN_DATA); - sb.append(ba.getParsedString()); + sb.append(ba.getAsHex()); } else { sb.append(logTable.getValueAt(i, COLUMN_DATA)); } @@ -1285,7 +1278,7 @@ public class BufferListener extends VisPlugin { }; private void updateParserMenu() { parserMenu.removeAll(); - + for (Class bpClass: bufferParsers) { JCheckBoxMenuItem mi = new JCheckBoxMenuItem(GUI.getDescriptionOf(bpClass), bpClass==parser.getClass()); mi.putClientProperty("CLASS", bpClass); @@ -1300,13 +1293,22 @@ public class BufferListener extends VisPlugin { Class btClass = (Class) ((JMenuItem) e.getSource()).getClientProperty("CLASS"); - setBuffer(btClass); + + Buffer b = createBufferInstance(btClass); + if (b != null) { + if (b.configure(BufferListener.this)) { + setBuffer(b); + } + } } }; private void updateBufferMenu() { bufferMenu.removeAll(); - + for (Class btClass: bufferTypes) { + if (btClass == CustomVariableBuffer.class) { + bufferMenu.addSeparator(); + } JCheckBoxMenuItem mi = new JCheckBoxMenuItem(GUI.getDescriptionOf(btClass), btClass==buffer.getClass()); mi.putClientProperty("CLASS", btClass); mi.addActionListener(bufferSelectedListener); @@ -1325,32 +1327,37 @@ public class BufferListener extends VisPlugin { logger.warn("Could not create buffer parser: " + e.getMessage(), e); return; } - + parser = bp; logTable.getColumnModel().getColumn(COLUMN_DATA).setHeaderValue(GUI.getDescriptionOf(bp)); repaint(); } - - private class VariableInfoComponent { + private static class BufferInput { private JPanel mainPanel = new JPanel(); private JTextField textName = new JTextField(); private JTextField textSize = new JTextField(); private JTextField textOffset = new JTextField(); - public VariableInfoComponent(String name, String size, String offset) { - textName.setText(name); - textSize.setText(size); - textOffset.setText(offset); - + public BufferInput(String name, String size, String offset) { mainPanel.setLayout(new GridLayout(3, 2, 5, 5)); - mainPanel.add(new JLabel("Variable name:")); - mainPanel.add(textName); - mainPanel.add(new JLabel("Buffer size (1-" + MAX_BUFFER_SIZE + "):")); - mainPanel.add(textSize); - mainPanel.add(new JLabel("Offset:")); - mainPanel.add(textOffset); + + if (name != null) { + textName.setText(name); + mainPanel.add(new JLabel("Symbol:")); + mainPanel.add(textName); + } + if (size != null) { + textSize.setText(size); + mainPanel.add(new JLabel("Size (1-" + MAX_BUFFER_SIZE + "):")); + mainPanel.add(textSize); + } + if (size != null) { + textOffset.setText(offset); + mainPanel.add(new JLabel("Offset")); + mainPanel.add(textOffset); + } } public String getName() { return textName.getText(); @@ -1365,91 +1372,36 @@ public class BufferListener extends VisPlugin { return mainPanel; } } - - private void setBuffer(Class btClass) { - setBuffer(btClass, null, -1, -1); - } - private void setBuffer(Class btClass, String varName, int varSize, int varOffset) { - /* Special buffer: Custom Variable/Custom Pointer */ - if ((btClass == CustomVariableBuffer.class || btClass == CustomPointerBuffer.class) - && varName == null) { - String d = (btClass == CustomVariableBuffer.class)?"Variable":"Pointer"; - /* Read variable name */ - String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); - String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "8"); - String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); - VariableInfoComponent infoComponent = - new VariableInfoComponent(suggestName, suggestSize, suggestOffset); - - int result = JOptionPane.showConfirmDialog(BufferListener.this, - infoComponent.getComponent(), - d + " info", - JOptionPane.OK_CANCEL_OPTION); - if (result != JOptionPane.OK_OPTION) { - /* Abort */ - return; - } - varName = infoComponent.getName(); - if (varName == null) { - /* Abort */ - return; - } - try { - varSize = Integer.parseInt(infoComponent.getSize()); - } catch (RuntimeException e) { - logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); - /* Abort */ - return; - } - if (varSize < 1 || varSize > MAX_BUFFER_SIZE) { - /* Abort */ - logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); - return; - } - try { - varOffset = Integer.parseInt(infoComponent.getOffset()); - } catch (RuntimeException e) { - logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); - /* Abort */ - return; - } - } - - /* Generate buffer type */ - Buffer bt = null; + private static Buffer createBufferInstance(Class btClass) { try { - bt = btClass.newInstance(); + return btClass.newInstance(); } catch (InstantiationException e) { logger.warn("Could not create buffer type: " + e.getMessage(), e); - return; + return null; } catch (IllegalAccessException e) { logger.warn("Could not create buffer type: " + e.getMessage(), e); + return null; + } + } + + private void setBuffer(Buffer buffer) { + if (buffer == null) { return; } - /* Special buffer: Custom Variable/Custom Pointer */ - if (btClass == CustomVariableBuffer.class) { - ((CustomVariableBuffer)bt).setInfo(varName, varSize, varOffset); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", varName); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + varSize); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + varOffset); - } else if (btClass == CustomPointerBuffer.class) { - ((CustomPointerBuffer)bt).setInfo(varName, varSize, varOffset); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", varName); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + varSize); - GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + varOffset); - } - - buffer = bt; + this.buffer = buffer; /* Reregister memory monitors */ for (Mote m: simulation.getMotes()) { stopObserving(m); } for (Mote m: simulation.getMotes()) { - /* TODO Check return values */ - startObserving(m); + try { + startMonitoring(m); + } catch (Exception e) { + logger.warn("Could not monitor buffer on: " + m, e); + } } /* Clear previous buffers, update gui */ @@ -1457,7 +1409,7 @@ public class BufferListener extends VisPlugin { updateTitle(); repaint(); } - + public static interface Parser { /** * @param mm Memory monitor @@ -1465,11 +1417,11 @@ public class BufferListener extends VisPlugin { * @param ba Buffer Access object * @return String or custom graphical object */ - public Object parse(MemoryMonitor mm, int address, BufferAccess ba); + public Object parse(BufferAccess ba); } public static abstract class GraphicalParser implements Parser { BufferAccess ba = null; - public Object parse(MemoryMonitor mm, int address, BufferAccess ba) { + public Object parse(BufferAccess ba) { this.ba = ba; return ba; } @@ -1478,28 +1430,71 @@ public class BufferListener extends VisPlugin { } public static abstract class StringParser implements Parser { - public Object parse(MemoryMonitor mm, int address, BufferAccess ba) { - return parseString(mm,address,ba); + public Object parse(BufferAccess ba) { + return parseString(ba); } - /** - * @param mm Memory monitor - * @param address Address that changed. May not contain all changes - * @param ba Buffer Access object - * @return String representation - */ - public abstract String parseString(MemoryMonitor mm, int address, BufferAccess ba); + public abstract String parseString(BufferAccess ba); } + public static interface Buffer { public int getAddress(Mote mote); public int getSize(Mote mote); - - } - public static interface PointerBuffer extends Buffer { - public int getAddress(Mote mote); - public int getSize(Mote mote); - public int getPointerAddress(Mote mote); + public String getStatusString(); + + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception; + + /* + * Called when buffer is created by user to allow user input (AWT thread) + */ + public boolean configure(BufferListener bl); + + /* + * Called when buffer is created from config + */ + public void applyConfig(Element element); + + public void writeConfig(Element element); + } + public static abstract class AbstractBuffer implements Buffer { + public String getStatusString() { + return null; + } + public void writeConfig(Element element) { + } + public void applyConfig(Element element) { + } + public boolean configure(BufferListener bl) { + return true; + } + } + + public static abstract class PointerBuffer extends AbstractBuffer { + public abstract int getPointerAddress(Mote mote); + + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception { + return new PointerMemoryMonitor( + bl, + mote, + getPointerAddress(mote), + mote.getMemory().getIntegerLength(), + getSize(mote) + ); + } + } + public static abstract class SegmentBuffer extends AbstractBuffer { + public SegmentMemoryMonitor createMemoryMonitor(BufferListener bl, Mote mote) + throws Exception { + return new SegmentMemoryMonitor( + bl, + mote, + getAddress(mote), + getSize(mote) + ); + } } public static boolean registerBufferParser(Class bpClass) { @@ -1523,10 +1518,10 @@ public class BufferListener extends VisPlugin { public static void unregisterBufferType(Class btClass) { bufferTypes.remove(btClass); } - + @ClassDescription("Byte array") public static class ByteArrayParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { boolean[] diff = ba.getAccessedBitpattern(); if (diff == null) { return StringUtils.toHex(ba.mem, 4); /* 00112233 00112233 .. */ @@ -1537,7 +1532,6 @@ public class BufferListener extends VisPlugin { int group = 0; for (int i=0; i < ba.mem.length; i++) { if (inRed == diff[i]) { - //logger.debug("same " + i); sb.append(StringUtils.toHex(ba.mem[i])); } else if (!inRed) { /* Diff begins */ @@ -1565,27 +1559,28 @@ public class BufferListener extends VisPlugin { return sb.toString(); } } - + @ClassDescription("Integer array") public static class IntegerParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { StringBuilder sb = new StringBuilder(); - boolean[] diff = ba.getAccessedBitpattern(); - + + int intLen = ba.mote.getMemory().getIntegerLength(); sb.append(""); - for (int i=0; i+1 < ba.mem.length;) { - int val = 0; + for (int i=0; i < ba.mem.length/intLen; i++) { + byte[] mem = Arrays.copyOfRange(ba.mem, i*intLen,(i+1)*intLen); + boolean[] diff = Arrays.copyOfRange(ba.getAccessedBitpattern(), i*intLen,(i+1)*intLen); + int val = ba.mote.getMemory().parseInt(mem); + boolean red = false; - if (diff != null && (diff[i] || diff[i+1])) { - red = true; + for (boolean changed: diff) { + if (changed) red = true; } - val += ((ba.mem[i++] & 0xFF)) << 8; - val += ((ba.mem[i++] & 0xFF)) << 0; - + if (red) { sb.append(""); } - sb.append((Integer.reverseBytes(val) >> 16) + " "); + sb.append(val + " "); if (red) { sb.append(""); } @@ -1597,7 +1592,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("Terminated string") public static class TerminatedStringParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ int i; for (i=0; i < ba.mem.length; i++) { @@ -1613,7 +1608,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("Printable characters") public static class PrintableCharactersParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ return new String(ba.mem).replaceAll("[^\\p{Print}]", ""); } @@ -1621,7 +1616,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("IPv6 address") public static class IPv6AddressParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ if (ba.mem.length < 16) { return "[must monitor at least 16 bytes]"; @@ -1639,7 +1634,7 @@ public class BufferListener extends VisPlugin { @ClassDescription("IPv4 address") public static class IPv4AddressParser extends StringParser { - public String parseString(MemoryMonitor mm, int address, BufferAccess ba) { + public String parseString(BufferAccess ba) { /* TODO Diff? */ if (ba.mem.length < 4) { return "[must monitor at least 4 bytes]"; @@ -1655,7 +1650,7 @@ public class BufferListener extends VisPlugin { return sb.toString(); } } - + static class GrapicalParserPanel extends JPanel { private static final long serialVersionUID = -8375160571675638467L; static final int XOFFSET = 0; @@ -1672,7 +1667,7 @@ public class BufferListener extends VisPlugin { public void paintComponent(Graphics g) { super.paintComponent(g); g.translate(XOFFSET, 0); - + if (getWidth() > getPreferredSize().width + 10 || getWidth() < getPreferredSize().width - 10) { double scale = 1.0*getWidth()/getPreferredSize().width; @@ -1683,7 +1678,7 @@ public class BufferListener extends VisPlugin { } }; private GrapicalParserPanel graphicalParserPanel = new GrapicalParserPanel(); - + @ClassDescription("Graphical: Height") public static class GraphicalHeight4BitsParser extends GraphicalParser { public int getUnscaledWidth() { @@ -1709,7 +1704,7 @@ public class BufferListener extends VisPlugin { } } } - + @ClassDescription("Graphical: Grayscale") public static class GraphicalGrayscale4BitsParser extends GraphicalParser { public int getUnscaledWidth() { @@ -1732,141 +1727,276 @@ public class BufferListener extends VisPlugin { } } } - + @ClassDescription("Variable: node_id") - public static class NodeIDBuffer implements Buffer { + public static class NodeIDBuffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("node_id")) { + if (!mote.getMemory().variableExists("node_id")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("node_id"); + return mote.getMemory().getVariableAddress("node_id"); } public int getSize(Mote mote) { - return 2; + return mote.getMemory().getIntegerLength(); } + } - + @ClassDescription("Queuebuf 0 RAM") - public static class Queuebuf0Buffer implements Buffer { + public static class Queuebuf0Buffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("buframmem")) { + if (!mote.getMemory().variableExists("buframmem")) { return -1; } int offset = 0; - return ((AddressMemory)mote.getMemory()).getVariableAddress("buframmem") + offset; + return mote.getMemory().getVariableAddress("buframmem") + offset; } public int getSize(Mote mote) { return 128; } } - + @ClassDescription("packetbuf_aligned") - public static class PacketbufBuffer implements Buffer { + public static class PacketbufBuffer extends SegmentBuffer { public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbuf_aligned")) { + if (!mote.getMemory().variableExists("packetbuf_aligned")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("packetbuf_aligned"); + return mote.getMemory().getVariableAddress("packetbuf_aligned"); } public int getSize(Mote mote) { return 128; } } - + @ClassDescription("*packetbufptr") - public static class PacketbufPointerBuffer implements PointerBuffer { + public static class PacketbufPointerBuffer extends PointerBuffer { public int getPointerAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbufptr")) { + if (!mote.getMemory().variableExists("packetbufptr")) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress("packetbufptr"); + return mote.getMemory().getVariableAddress("packetbufptr"); } public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists("packetbufptr")) { + if (!mote.getMemory().variableExists("packetbufptr")) { return -1; } - return ((AddressMemory)mote.getMemory()).getIntValueOf("packetbufptr"); + return mote.getMemory().getIntValueOf("packetbufptr"); } public int getSize(Mote mote) { return 128; } } - - @ClassDescription("Custom pointer") - public static class CustomPointerBuffer implements PointerBuffer { + + @ClassDescription("Pointer...") + public static class CustomPointerBuffer extends PointerBuffer { public String variable; public int size; public int offset; - public void setInfo(String variable, int size, int offset) { - this.variable = variable; - this.size = size; - this.offset = offset; - } - public String getVariable() { - return variable; - } - public int getSize() { - return size; - } - public int getOffset() { - return offset; - } - public int getPointerAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress(variable); + return mote.getMemory().getVariableAddress(variable); } public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getIntValueOf(variable)+offset; + return mote.getMemory().getIntValueOf(variable)+offset; } public int getSize(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } return size; } + + public String getStatusString() { + if (offset > 0) { + return "Pointer *" + variable + "[" + offset + "] (" + size + ")"; + } else { + return "Pointer *" + variable + " (" + size + ")"; + } + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + element.setAttribute("size", "" + size); + element.setAttribute("offset", "" + offset); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + size = Integer.parseInt(element.getAttributeValue("size")); + offset = Integer.parseInt(element.getAttributeValue("offset")); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2"); + String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); + BufferInput infoComponent = + new BufferInput(suggestName, suggestSize, suggestOffset); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + try { + size = Integer.parseInt(infoComponent.getSize()); + if (size < 1 || size > MAX_BUFFER_SIZE) { + /* Abort */ + logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); + return false; + } + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); + return false; + } + try { + offset = Integer.parseInt(infoComponent.getOffset()); + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); + /* Abort */ + return false; + } + + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + size); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + offset); + return true; + } } - - @ClassDescription("Custom variable") - public static class CustomVariableBuffer implements Buffer { + + @ClassDescription("Symbol...") + public static class CustomVariableBuffer extends SegmentBuffer { public String variable; public int size; public int offset; - public void setInfo(String variable, int size, int offset) { - this.variable = variable; - this.size = size; - this.offset = offset; - } - public String getVariable() { - return variable; - } - public int getSize() { - return size; - } - public int getOffset() { - return offset; - } - public boolean isPointer() { - return false; - } - public int getAddress(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } - return ((AddressMemory)mote.getMemory()).getVariableAddress(variable)+offset; + return mote.getMemory().getVariableAddress(variable)+offset; } public int getSize(Mote mote) { - if (!((AddressMemory)mote.getMemory()).variableExists(variable)) { + if (!mote.getMemory().variableExists(variable)) { return -1; } return size; } + + public String getStatusString() { + if (offset > 0) { + return "Symbol &" + variable + "[" + offset + "] (" + size + ")"; + } else { + return "Symbol " + variable + " (" + size + ")"; + } + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + element.setAttribute("size", "" + size); + element.setAttribute("offset", "" + offset); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + size = Integer.parseInt(element.getAttributeValue("size")); + offset = Integer.parseInt(element.getAttributeValue("offset")); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + String suggestSize = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "2"); + String suggestOffset = GUI.getExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "0"); + BufferInput infoComponent = + new BufferInput(suggestName, suggestSize, suggestOffset); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + try { + size = Integer.parseInt(infoComponent.getSize()); + if (size < 1 || size > MAX_BUFFER_SIZE) { + /* Abort */ + logger.fatal("Bad buffer size " + infoComponent.getSize() + ": min 1, max " + MAX_BUFFER_SIZE); + return false; + } + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer size " + infoComponent.getSize() + ": " + e.getMessage(), e); + return false; + } + try { + offset = Integer.parseInt(infoComponent.getOffset()); + } catch (RuntimeException e) { + logger.fatal("Failed parsing buffer offset " + infoComponent.getOffset() + ": " + e.getMessage(), e); + /* Abort */ + return false; + } + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARSIZE", "" + size); + GUI.setExternalToolsSetting("BUFFER_LISTENER_VAROFFSET", "" + offset); + return true; + } + } + + @ClassDescription("Integer...") + public static class CustomIntegerBuffer extends SegmentBuffer { + public String variable; + public int getAddress(Mote mote) { + if (!mote.getMemory().variableExists(variable)) { + return -1; + } + return mote.getMemory().getVariableAddress(variable); + } + public int getSize(Mote mote) { + return mote.getMemory().getIntegerLength(); + } + + public String getStatusString() { + return "Integer " + variable; + } + + public void writeConfig(Element element) { + element.setAttribute("variable", variable); + } + public void applyConfig(Element element) { + variable = element.getAttributeValue("variable"); + } + public boolean configure(BufferListener bl) { + String suggestName = GUI.getExternalToolsSetting("BUFFER_LISTENER_VARNAME", "node_id"); + BufferInput infoComponent = + new BufferInput(suggestName, null, null); + + int result = JOptionPane.showConfirmDialog(bl, + infoComponent.getComponent(), + "Symbol info", + JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { + /* Abort */ + return false; + } + variable = infoComponent.getName(); + if (variable == null) { + return false; + } + GUI.setExternalToolsSetting("BUFFER_LISTENER_VARNAME", variable); + return true; + } } - } diff --git a/tools/cooja/java/se/sics/cooja/radiomediums/AbstractRadioMedium.java b/tools/cooja/java/se/sics/cooja/radiomediums/AbstractRadioMedium.java index e404a80ef..b0b4d1e0a 100644 --- a/tools/cooja/java/se/sics/cooja/radiomediums/AbstractRadioMedium.java +++ b/tools/cooja/java/se/sics/cooja/radiomediums/AbstractRadioMedium.java @@ -147,6 +147,11 @@ public abstract class AbstractRadioMedium extends RadioMedium { conn.getSource().setCurrentSignalStrength(SS_STRONG); } for (Radio dstRadio : conn.getDestinations()) { + if (conn.getSource().getChannel() >= 0 && + dstRadio.getChannel() >= 0 && + conn.getSource().getChannel() != dstRadio.getChannel()) { + continue; + } if (dstRadio.getCurrentSignalStrength() < SS_STRONG) { dstRadio.setCurrentSignalStrength(SS_STRONG); } @@ -159,7 +164,11 @@ public abstract class AbstractRadioMedium extends RadioMedium { if (intfRadio.getCurrentSignalStrength() < SS_STRONG) { intfRadio.setCurrentSignalStrength(SS_STRONG); } - + if (conn.getSource().getChannel() >= 0 && + intfRadio.getChannel() >= 0 && + conn.getSource().getChannel() != intfRadio.getChannel()) { + continue; + } if (!intfRadio.isInterfered()) { /*logger.warn("Radio was not interfered");*/ intfRadio.interfereAnyReception(); diff --git a/tools/cooja/java/se/sics/cooja/radiomediums/UDGM.java b/tools/cooja/java/se/sics/cooja/radiomediums/UDGM.java index c0f273883..5981d4e80 100644 --- a/tools/cooja/java/se/sics/cooja/radiomediums/UDGM.java +++ b/tools/cooja/java/se/sics/cooja/radiomediums/UDGM.java @@ -287,6 +287,12 @@ public class UDGM extends AbstractRadioMedium { conn.getSource().setCurrentSignalStrength(SS_STRONG); } for (Radio dstRadio : conn.getDestinations()) { + if (conn.getSource().getChannel() >= 0 && + dstRadio.getChannel() >= 0 && + conn.getSource().getChannel() != dstRadio.getChannel()) { + continue; + } + double dist = conn.getSource().getPosition().getDistanceTo(dstRadio.getPosition()); double maxTxDist = TRANSMITTING_RANGE @@ -303,6 +309,12 @@ public class UDGM extends AbstractRadioMedium { /* Set signal strength to below weak on interfered */ for (RadioConnection conn : conns) { for (Radio intfRadio : conn.getInterfered()) { + if (conn.getSource().getChannel() >= 0 && + intfRadio.getChannel() >= 0 && + conn.getSource().getChannel() != intfRadio.getChannel()) { + continue; + } + double dist = conn.getSource().getPosition().getDistanceTo(intfRadio.getPosition()); double maxTxDist = TRANSMITTING_RANGE