Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2006, Technical University of Munich 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$$ 00032 */ 00033 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) 00034 00035 #define ANNOUNCE_BOOT 1 //adds about 600 bytes to program size 00036 #if ANNOUNCE_BOOT 00037 #define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) 00038 #else 00039 #define PRINTA(...) 00040 #endif 00041 00042 #define DEBUG 0 00043 #if DEBUG 00044 #define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) 00045 #else 00046 #define PRINTD(...) 00047 #endif 00048 00049 /* Track interrupt flow through mac, rdc and radio driver */ 00050 //#define DEBUGFLOWSIZE 64 00051 #if DEBUGFLOWSIZE 00052 unsigned char debugflowsize,debugflow[DEBUGFLOWSIZE]; 00053 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c 00054 #else 00055 #define DEBUGFLOW(c) 00056 #endif 00057 00058 #include <avr/pgmspace.h> 00059 #include <avr/fuse.h> 00060 #include <avr/eeprom.h> 00061 #include <stdio.h> 00062 #include <string.h> 00063 #include <dev/watchdog.h> 00064 00065 #include "loader/symbols-def.h" 00066 #include "loader/symtab.h" 00067 00068 #if RF230BB //radio driver using contiki core mac 00069 #include "radio/rf230bb/rf230bb.h" 00070 #include "net/mac/frame802154.h" 00071 #include "net/mac/framer-802154.h" 00072 #include "net/sicslowpan.h" 00073 00074 #else //radio driver using Atmel/Cisco 802.15.4'ish MAC 00075 #include <stdbool.h> 00076 #include "mac.h" 00077 #include "sicslowmac.h" 00078 #include "sicslowpan.h" 00079 #include "ieee-15-4-manager.h" 00080 #endif /*RF230BB*/ 00081 00082 #include "contiki.h" 00083 #include "contiki-net.h" 00084 #include "contiki-lib.h" 00085 00086 #include "dev/rs232.h" 00087 #include "dev/serial-line.h" 00088 #include "dev/slip.h" 00089 00090 #ifdef RAVEN_LCD_INTERFACE 00091 #include "raven-lcd.h" 00092 #endif 00093 00094 #if AVR_WEBSERVER 00095 #include "httpd-fs.h" 00096 #include "httpd-cgi.h" 00097 #endif 00098 00099 #ifdef COFFEE_FILES 00100 #include "cfs/cfs.h" 00101 #include "cfs/cfs-coffee.h" 00102 #endif 00103 00104 #if UIP_CONF_ROUTER&&0 00105 #include "net/routing/rimeroute.h" 00106 #include "net/rime/rime-udp.h" 00107 #endif 00108 00109 #include "net/rime.h" 00110 00111 #include "params.h" 00112 00113 /* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */ 00114 /* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */ 00115 /* STAMPS will print ENERGEST outputs if that is enabled. */ 00116 #define PERIODICPRINTS 1 00117 #if PERIODICPRINTS 00118 //#define PINGS 64 00119 #define ROUTES 600 00120 #define STAMPS 60 00121 #define STACKMONITOR 600 00122 uint32_t clocktime; 00123 #define TESTRTIMER 0 00124 #if TESTRTIMER 00125 uint8_t rtimerflag=1; 00126 struct rtimer rt; 00127 void rtimercycle(void) {rtimerflag=1;} 00128 #endif 00129 #endif 00130 00131 /*-------------------------------------------------------------------------*/ 00132 /*----------------------Configuration of the .elf file---------------------*/ 00133 #if 1 00134 /* The proper way to set the signature is */ 00135 #include <avr/signature.h> 00136 #else 00137 /* Older avr-gcc's may not define the needed SIGNATURE bytes. Do it manually if you get an error */ 00138 typedef struct {const unsigned char B2;const unsigned char B1;const unsigned char B0;} __signature_t; 00139 #define SIGNATURE __signature_t __signature __attribute__((section (".signature"))) 00140 SIGNATURE = { 00141 .B2 = 0x05,//SIGNATURE_2, //ATMEGA1284p 00142 .B1 = 0x97,//SIGNATURE_1, //128KB flash 00143 .B0 = 0x1E,//SIGNATURE_0, //Atmel 00144 }; 00145 #endif 00146 00147 #if !MCU_CONF_LOW_WEAR 00148 /* JTAG, SPI enabled, Internal RC osc, Boot flash size 4K, 6CK+65msec delay, brownout disabled */ 00149 FUSES ={.low = 0xe2, .high = 0x99, .extended = 0xff,}; 00150 #endif 00151 00152 /* Get a pseudo random number using the ADC */ 00153 uint8_t 00154 rng_get_uint8(void) { 00155 uint8_t i,j; 00156 ADCSRA=1<<ADEN; //Enable ADC, not free running, interrupt disabled, fastest clock 00157 for (i=0,j=0;i<4;i++) { 00158 ADMUX = 0; //toggle reference to increase noise 00159 ADMUX =0x1E; //Select AREF as reference, measure 1.1 volt bandgap reference. 00160 ADCSRA|=1<<ADSC; //Start conversion 00161 while (ADCSRA&(1<<ADSC)); //Wait till done 00162 j = (j<<2) + ADC; 00163 } 00164 ADCSRA=0; //Disable ADC 00165 PRINTD("rng issues %d\n",j); 00166 return j; 00167 } 00168 00169 /*-------------------------Low level initialization------------------------*/ 00170 /*------Done in a subroutine to keep main routine stack usage small--------*/ 00171 void initialize(void) 00172 { 00173 watchdog_init(); 00174 watchdog_start(); 00175 00176 #ifdef RAVEN_LCD_INTERFACE 00177 /* First rs232 port for Raven 3290 port */ 00178 rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); 00179 /* Set input handler for 3290 port */ 00180 rs232_set_input(0,raven_lcd_serial_input); 00181 #else 00182 /* Generic or slip connection on uart0 */ 00183 rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); 00184 #endif 00185 00186 /* Second rs232 port for debugging or slip alternative */ 00187 rs232_init(RS232_PORT_1, USART_BAUD_57600,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); 00188 /* Redirect stdout to second port */ 00189 rs232_redirect_stdout(RS232_PORT_1); 00190 clock_init(); 00191 00192 PRINTD("\n\nChecking MCUSR...\n"); 00193 if(MCUSR & (1<<PORF )) PRINTD("Power-on reset.\n"); 00194 if(MCUSR & (1<<EXTRF)) PRINTD("External reset!\n"); 00195 if(MCUSR & (1<<BORF )) PRINTD("Brownout reset!\n"); 00196 if(MCUSR & (1<<WDRF )) PRINTD("Watchdog reset!\n"); 00197 if(MCUSR & (1<<JTRF )) PRINTD("JTAG reset!\n"); 00198 MCUSR = 0; 00199 00200 PRINTD("CLOCK_SECOND %d\n",CLOCK_SECOND); 00201 PRINTD("RTIMER_ARCH_SECOND %lu\n",RTIMER_ARCH_SECOND); 00202 PRINTD("F_CPU %lu\n",F_CPU); 00203 00204 #if STACKMONITOR 00205 /* Simple stack pointer highwater monitor. Checks for magic numbers in the main 00206 * loop. In conjuction with PERIODICPRINTS, never-used stack will be printed 00207 * every STACKMONITOR seconds. 00208 */ 00209 { 00210 extern uint16_t __bss_end; 00211 uint16_t p=(uint16_t)&__bss_end; 00212 do { 00213 *(uint16_t *)p = 0x4242; 00214 p+=10; 00215 } while (p<SP-10); //don't overwrite our own stack 00216 } 00217 #endif 00218 00219 /* Calibrate internal mcu clock against external 32768Hz watch crystal */ 00220 #define CONF_CALIBRATE_OSCCAL 0 00221 #if CONF_CALIBRATE_OSCCAL 00222 void calibrate_rc_osc_32k(); 00223 { 00224 extern uint8_t osccal_calibrated; 00225 uint8_t i; 00226 PRINTD("\nBefore calibration OSCCAL=%x\n",OSCCAL); 00227 for (i=0;i<10;i++) { 00228 calibrate_rc_osc_32k(); 00229 PRINTD("Calibrated=%x\n",osccal_calibrated); 00230 //#include <util/delay_basic.h> 00231 //#define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) 00232 // delay_us(50000); 00233 } 00234 clock_init(); 00235 } 00236 #endif 00237 00238 PRINTA("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING); 00239 00240 /* rtimers needed for radio cycling */ 00241 rtimer_init(); 00242 00243 /* Initialize process subsystem */ 00244 process_init(); 00245 00246 /* etimers must be started before ctimer_init */ 00247 process_start(&etimer_process, NULL); 00248 00249 #if RF230BB 00250 00251 ctimer_init(); 00252 /* Start radio and radio receive process */ 00253 NETSTACK_RADIO.init(); 00254 00255 /* Get a random seed for the 802.15.4 packet sequence number. 00256 * Some layers will ignore duplicates found in a history (e.g. Contikimac) 00257 * causing the initial packets to be ignored after a short-cycle restart. 00258 */ 00259 random_init(rng_get_uint8()); 00260 00261 /* Set addresses BEFORE starting tcpip process */ 00262 00263 rimeaddr_t addr; 00264 if (params_get_eui64(addr.u8)) { 00265 PRINTA("Random EUI64 address generated\n"); 00266 } 00267 00268 #if UIP_CONF_IPV6 00269 memcpy(&uip_lladdr.addr, &addr.u8, sizeof(rimeaddr_t)); 00270 rimeaddr_set_node_addr(&addr); 00271 rf230_set_pan_addr(params_get_panid(),params_get_panaddr(),(uint8_t *)&addr.u8); 00272 #elif WITH_NODE_ID 00273 node_id=get_panaddr_from_eeprom(); 00274 addr.u8[1]=node_id&0xff; 00275 addr.u8[0]=(node_id&0xff00)>>8; 00276 PRINTA("Node ID from eeprom: %X\n",node_id); 00277 uint16_t inv_node_id=((node_id&0xff00)>>8)+((node_id&0xff)<<8); // change order of bytes for rf23x 00278 rimeaddr_set_node_addr(&addr); 00279 rf230_set_pan_addr(params_get_panid(),inv_node_id,NULL); 00280 #else 00281 rimeaddr_set_node_addr(&addr); 00282 rf230_set_pan_addr(params_get_panid(),params_get_panaddr(),(uint8_t *)&addr.u8); 00283 #endif 00284 rf230_set_channel(params_get_channel()); 00285 rf230_set_txpower(params_get_txpower()); 00286 00287 #if UIP_CONF_IPV6 00288 PRINTA("EUI-64 MAC: %x-%x-%x-%x-%x-%x-%x-%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); 00289 #else 00290 PRINTA("MAC address "); 00291 uint8_t i; 00292 for (i=sizeof(rimeaddr_t); i>0; i--){ 00293 PRINTA("%x:",addr.u8[i-1]); 00294 } 00295 PRINTA("\n"); 00296 #endif 00297 00298 /* Initialize stack protocols */ 00299 queuebuf_init(); 00300 NETSTACK_RDC.init(); 00301 NETSTACK_MAC.init(); 00302 NETSTACK_NETWORK.init(); 00303 00304 #if ANNOUNCE_BOOT 00305 PRINTA("%s %s, channel %u , check rate %u Hz tx power %u\n",NETSTACK_MAC.name, NETSTACK_RDC.name, rf230_get_channel(), 00306 CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:NETSTACK_RDC.channel_check_interval()), 00307 rf230_get_txpower()); 00308 #if UIP_CONF_IPV6_RPL 00309 PRINTA("RPL Enabled\n"); 00310 #endif 00311 #if UIP_CONF_ROUTER 00312 PRINTA("Routing Enabled\n"); 00313 #endif 00314 #endif /* ANNOUNCE_BOOT */ 00315 00316 // rime_init(rime_udp_init(NULL)); 00317 // uip_router_register(&rimeroute); 00318 00319 process_start(&tcpip_process, NULL); 00320 00321 #else /* !RF230BB */ 00322 /* Original RF230 combined mac/radio driver */ 00323 /* mac process must be started before tcpip process! */ 00324 process_start(&mac_process, NULL); 00325 process_start(&tcpip_process, NULL); 00326 #endif /* RF230BB */ 00327 00328 #ifdef RAVEN_LCD_INTERFACE 00329 process_start(&raven_lcd_process, NULL); 00330 #endif 00331 00332 /* Autostart other processes */ 00333 autostart_start(autostart_processes); 00334 00335 /*---If using coffee file system create initial web content if necessary---*/ 00336 #if COFFEE_FILES 00337 int fa = cfs_open( "/index.html", CFS_READ); 00338 if (fa<0) { //Make some default web content 00339 PRINTA("No index.html file found, creating upload.html!\n"); 00340 PRINTA("Formatting FLASH file system for coffee..."); 00341 cfs_coffee_format(); 00342 PRINTA("Done!\n"); 00343 fa = cfs_open( "/index.html", CFS_WRITE); 00344 int r = cfs_write(fa, &"It works!", 9); 00345 if (r<0) PRINTA("Can''t create /index.html!\n"); 00346 cfs_close(fa); 00347 // fa = cfs_open("upload.html"), CFW_WRITE); 00348 // <html><body><form action="upload.html" enctype="multipart/form-data" method="post"><input name="userfile" type="file" size="50" /><input value="Upload" type="submit" /></form></body></html> 00349 } 00350 #endif /* COFFEE_FILES */ 00351 00352 /* Add addresses for testing */ 00353 #if 0 00354 { 00355 uip_ip6addr_t ipaddr; 00356 uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); 00357 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); 00358 // uip_ds6_prefix_add(&ipaddr,64,0); 00359 } 00360 #endif 00361 00362 /*--------------------------Announce the configuration---------------------*/ 00363 #if ANNOUNCE_BOOT 00364 { 00365 #if AVR_WEBSERVER 00366 uint8_t i; 00367 char buf1[40],buf[40]; 00368 unsigned int size; 00369 00370 for (i=0;i<UIP_DS6_ADDR_NB;i++) { 00371 if (uip_ds6_if.addr_list[i].isused) { 00372 httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr,buf); 00373 PRINTA("IPv6 Address: %s\n",buf); 00374 } 00375 } 00376 cli(); 00377 eeprom_read_block (buf1,eemem_server_name, sizeof(eemem_server_name)); 00378 eeprom_read_block (buf,eemem_domain_name, sizeof(eemem_domain_name)); 00379 sei(); 00380 buf1[sizeof(eemem_server_name)]=0; 00381 PRINTA("%s",buf1); 00382 buf[sizeof(eemem_domain_name)]=0; 00383 size=httpd_fs_get_size(); 00384 #ifndef COFFEE_FILES 00385 PRINTA(".%s online with fixed %u byte web content\n",buf,size); 00386 #elif COFFEE_FILES==1 00387 PRINTA(".%s online with static %u byte EEPROM file system\n",buf,size); 00388 #elif COFFEE_FILES==2 00389 PRINTA(".%s online with dynamic %u KB EEPROM file system\n",buf,size>>10); 00390 #elif COFFEE_FILES==3 00391 PRINTA(".%s online with static %u byte program memory file system\n",buf,size); 00392 #elif COFFEE_FILES==4 00393 PRINTA(".%s online with dynamic %u KB program memory file system\n",buf,size>>10); 00394 #endif /* COFFEE_FILES */ 00395 00396 #else 00397 PRINTA("Online\n"); 00398 #endif /* AVR_WEBSERVER */ 00399 00400 #endif /* ANNOUNCE_BOOT */ 00401 } 00402 } 00403 00404 #if ROUTES && UIP_CONF_IPV6 00405 static void 00406 ipaddr_add(const uip_ipaddr_t *addr) 00407 { 00408 uint16_t a; 00409 int8_t i, f; 00410 for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { 00411 a = (addr->u8[i] << 8) + addr->u8[i + 1]; 00412 if(a == 0 && f >= 0) { 00413 if(f++ == 0) PRINTF("::"); 00414 } else { 00415 if(f > 0) { 00416 f = -1; 00417 } else if(i > 0) { 00418 PRINTF(":"); 00419 } 00420 PRINTF("%x",a); 00421 } 00422 } 00423 } 00424 #endif 00425 00426 /*-------------------------------------------------------------------------*/ 00427 /*------------------------- Main Scheduler loop----------------------------*/ 00428 /*-------------------------------------------------------------------------*/ 00429 int 00430 main(void) 00431 { 00432 initialize(); 00433 00434 while(1) { 00435 process_run(); 00436 watchdog_periodic(); 00437 00438 #if 0 00439 /* Various entry points for debugging in the AVR Studio simulator. 00440 * Set as next statement and step into the routine. 00441 */ 00442 NETSTACK_RADIO.send(packetbuf_hdrptr(), 42); 00443 process_poll(&rf230_process); 00444 packetbuf_clear(); 00445 len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); 00446 packetbuf_set_datalen(42); 00447 NETSTACK_RDC.input(); 00448 #endif 00449 00450 #if 0 00451 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. 00452 * This can show when that happens. 00453 */ 00454 extern uint8_t rf230_calibrated; 00455 if (rf230_calibrated) { 00456 PRINTD("\nRF230 calibrated!\n"); 00457 rf230_calibrated=0; 00458 } 00459 #endif 00460 00461 /* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */ 00462 #if DEBUGFLOWSIZE 00463 if (debugflowsize) { 00464 debugflow[debugflowsize]=0; 00465 PRINTF("%s",debugflow); 00466 debugflowsize=0; 00467 } 00468 #endif 00469 00470 #if PERIODICPRINTS 00471 #if TESTRTIMER 00472 /* Timeout can be increased up to 8 seconds maximum. 00473 * A one second cycle is convenient for triggering the various debug printouts. 00474 * The triggers are staggered to avoid printing everything at once. 00475 */ 00476 if (rtimerflag) { 00477 rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); 00478 rtimerflag=0; 00479 #else 00480 if (clocktime!=clock_seconds()) { 00481 clocktime=clock_seconds(); 00482 #endif 00483 00484 #if STAMPS 00485 if ((clocktime%STAMPS)==0) { 00486 #if ENERGEST_CONF_ON 00487 #include "lib/print-stats.h" 00488 print_stats(); 00489 #elif RADIOSTATS 00490 extern volatile unsigned long radioontime; 00491 PRINTF("%u(%u)s\n",clocktime,radioontime); 00492 #else 00493 PRINTF("%us\n",clocktime); 00494 #endif 00495 00496 } 00497 #endif 00498 #if TESTRTIMER 00499 clocktime+=1; 00500 #endif 00501 00502 #if PINGS && UIP_CONF_IPV6 00503 extern void raven_ping6(void); 00504 if ((clocktime%PINGS)==1) { 00505 PRINTF("**Ping\n"); 00506 raven_ping6(); 00507 } 00508 #endif 00509 00510 #if ROUTES && UIP_CONF_IPV6 00511 if ((clocktime%ROUTES)==2) { 00512 00513 extern uip_ds6_nbr_t uip_ds6_nbr_cache[]; 00514 extern uip_ds6_route_t uip_ds6_routing_table[]; 00515 extern uip_ds6_netif_t uip_ds6_if; 00516 00517 uint8_t i,j; 00518 PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); 00519 for (i=0;i<UIP_DS6_ADDR_NB;i++) { 00520 if (uip_ds6_if.addr_list[i].isused) { 00521 ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr); 00522 PRINTF("\n"); 00523 } 00524 } 00525 PRINTF("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB); 00526 for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) { 00527 if(uip_ds6_nbr_cache[i].isused) { 00528 ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr); 00529 PRINTF("\n"); 00530 j=0; 00531 } 00532 } 00533 if (j) PRINTF(" <none>"); 00534 PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); 00535 for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) { 00536 if(uip_ds6_routing_table[i].isused) { 00537 ipaddr_add(&uip_ds6_routing_table[i].ipaddr); 00538 PRINTF("/%u (via ", uip_ds6_routing_table[i].length); 00539 ipaddr_add(&uip_ds6_routing_table[i].nexthop); 00540 // if(uip_ds6_routing_table[i].state.lifetime < 600) { 00541 PRINTF(") %lus\n", uip_ds6_routing_table[i].state.lifetime); 00542 // } else { 00543 // PRINTF(")\n"); 00544 // } 00545 j=0; 00546 } 00547 } 00548 if (j) PRINTF(" <none>"); 00549 PRINTF("\n---------\n"); 00550 } 00551 #endif 00552 00553 #if STACKMONITOR 00554 if ((clocktime%STACKMONITOR)==3) { 00555 extern uint16_t __bss_end; 00556 uint16_t p=(uint16_t)&__bss_end; 00557 do { 00558 if (*(uint16_t *)p != 0x4242) { 00559 PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); 00560 break; 00561 } 00562 p+=10; 00563 } while (p<RAMEND-10); 00564 } 00565 #endif 00566 00567 } 00568 #endif /* PERIODICPRINTS */ 00569 00570 #if RF230BB&&0 00571 extern uint8_t rf230processflag; 00572 if (rf230processflag) { 00573 PRINTF("rf230p%d",rf230processflag); 00574 rf230processflag=0; 00575 } 00576 #endif 00577 00578 #if RF230BB&&0 00579 extern uint8_t rf230_interrupt_flag; 00580 if (rf230_interrupt_flag) { 00581 // if (rf230_interrupt_flag!=11) { 00582 PRINTF("**RI%u",rf230_interrupt_flag); 00583 // } 00584 rf230_interrupt_flag=0; 00585 } 00586 #endif 00587 } 00588 return 0; 00589 } 00590 00591 /*---------------------------------------------------------------------------*/ 00592 00593 void log_message(char *m1, char *m2) 00594 { 00595 PRINTF("%s%s\n", m1, m2); 00596 }