Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Loughborough University - Computer Science 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 * \file 00034 * Sources for the BATtery MONitor app. It dumps a log entry to the 00035 * external flash periodically as well as upon external trigger. 00036 * 00037 * It started off as a VDD and battery logger but now it also stores 00038 * energest values and other goodies. 00039 * 00040 * \author 00041 * George Oikonomou - <oikonomou@users.sourceforge.net> 00042 */ 00043 00044 #include "contiki.h" 00045 00046 #define DEBUG 0 00047 #if DEBUG 00048 #include <stdio.h> 00049 #define PRINTF(...) printf(__VA_ARGS__) 00050 #else 00051 #define PRINTF(...) 00052 #endif 00053 00054 #include "sys/etimer.h" 00055 #include "sys/energest.h" 00056 #include "dev/sensinode-sensors.h" 00057 #include "dev/n740.h" 00058 #include "dev/m25p16.h" 00059 00060 #define BATMON_LOG_PERIOD 60 /* in seconds */ 00061 /*---------------------------------------------------------------------------*/ 00062 static const uint8_t magic[3] = { 0x0B, 0xEE, 0xF0 }; 00063 /*---------------------------------------------------------------------------*/ 00064 struct record { 00065 uint8_t magic[3]; 00066 uint8_t trigger; 00067 unsigned long c; /* uptime */ 00068 int v; /* VDD (reference) */ 00069 int b; /* Voltage ADC */ 00070 #if ENERGEST_CONF_ON 00071 unsigned long mcu; 00072 unsigned long lpm; 00073 unsigned long irq; 00074 unsigned long tx; 00075 unsigned long rx; 00076 unsigned long f_write; 00077 unsigned long f_read; 00078 #endif 00079 }; 00080 00081 #define RECORD_SIZE 64 00082 #define LAST_WRITE (0xFFFF - RECORD_SIZE) 00083 00084 #define LOG_TRIGGER_PERIODIC 0xFF 00085 /*---------------------------------------------------------------------------*/ 00086 struct flash_address { 00087 uint8_t s; /* sector */ 00088 uint8_t p; /* page */ 00089 uint8_t a; /* address */ 00090 }; 00091 static struct flash_address f; 00092 00093 static struct record r; 00094 static struct sensors_sensor * s; 00095 static struct etimer et; 00096 #define FLASH_START_ADDR 0x1E0000 00097 #define FLASH_END_ADDR 0x1FFFFF 00098 /*---------------------------------------------------------------------------*/ 00099 PROCESS(batmon_process, "Logger Process"); 00100 /*---------------------------------------------------------------------------*/ 00101 static int 00102 find_gap() CC_NON_BANKED 00103 { 00104 uint8_t seq[3]; 00105 uint32_t address = FLASH_START_ADDR; 00106 memset(&f, 0, sizeof(f)); 00107 00108 for(address = FLASH_START_ADDR; address <= FLASH_END_ADDR; address += 00109 RECORD_SIZE) { 00110 n740_analog_deactivate(); 00111 f.s = ((address & 0xFF0000) >> 16); 00112 f.p = ((address & 0xFF00) >> 8); 00113 f.a = address & 0xFF; 00114 m25p16_read_fast((uint8_t *)&f, seq, sizeof(magic)); 00115 n740_analog_activate(); 00116 if(memcmp(seq, magic, sizeof(magic)) != 0) { 00117 PRINTF("BatMon: Resume write @ 0x%02x%02x%02x\n", f.s, f.p, f.a); 00118 return 1; 00119 } 00120 } 00121 00122 /* If we reach here, we ran out of flash */ 00123 return -1; 00124 } 00125 /*---------------------------------------------------------------------------*/ 00126 static void 00127 abort() CC_NON_BANKED 00128 { 00129 PRINTF("BatMon: Abort\n"); 00130 etimer_stop(&et); 00131 process_exit(&batmon_process); 00132 } 00133 /*---------------------------------------------------------------------------*/ 00134 void 00135 batmon_log(uint8_t trigger) 00136 { 00137 uint32_t next; 00138 00139 /* Only continue if the process (us) is running */ 00140 if(!process_is_running(&batmon_process)) { 00141 return; 00142 } 00143 00144 next = f.a; 00145 next |= (((uint32_t) f.p) << 8); 00146 next |= (((uint32_t) f.s) << 16); 00147 00148 memcpy(r.magic, magic, sizeof(magic)); 00149 r.trigger = trigger; 00150 r.c = clock_seconds(); 00151 00152 /* Read VDD and use as ADC reference */ 00153 r.v = s->value(ADC_SENSOR_TYPE_VDD); 00154 00155 /* And then carry on with battery */ 00156 r.b = s->value(ADC_SENSOR_TYPE_BATTERY); 00157 00158 #if ENERGEST_CONF_ON 00159 /* ENERGEST values */ 00160 r.mcu = energest_type_time(ENERGEST_TYPE_CPU); 00161 r.lpm = energest_type_time(ENERGEST_TYPE_LPM); 00162 r.irq = energest_type_time(ENERGEST_TYPE_IRQ); 00163 r.tx = energest_type_time(ENERGEST_TYPE_TRANSMIT); 00164 r.rx = energest_type_time(ENERGEST_TYPE_LISTEN); 00165 r.f_write = energest_type_time(ENERGEST_TYPE_FLASH_WRITE); 00166 r.f_read = energest_type_time(ENERGEST_TYPE_FLASH_READ); 00167 #endif 00168 00169 n740_analog_deactivate(); 00170 /* Make sure we're on */ 00171 if(M25P16_WIP()) { 00172 m25p16_res(); 00173 } 00174 m25p16_pp((uint8_t *)&f, (uint8_t *)&r, sizeof(r)); 00175 n740_analog_activate(); 00176 00177 PRINTF("BatMon: @%lu [%u] ", r.c, r.trigger); 00178 PRINTF("BatMon: 0x%02x%02x%02x\n", f.s, f.p, f.a); 00179 00180 next += RECORD_SIZE; 00181 00182 if(next >= FLASH_END_ADDR) { 00183 abort(); 00184 return; 00185 } 00186 00187 f.s = ((next & 0xFF0000) >> 16); 00188 f.p = ((next & 0xFF00) >> 8); 00189 f.a = next & 0xFF; 00190 00191 if(trigger == LOG_TRIGGER_PERIODIC) { 00192 etimer_reset(&et); 00193 } 00194 } 00195 /*---------------------------------------------------------------------------*/ 00196 PROCESS_THREAD(batmon_process, ev, data) 00197 { 00198 00199 PROCESS_BEGIN(); 00200 00201 PRINTF("BatMon\n", sizeof(r)); 00202 00203 s = sensors_find(ADC_SENSOR); 00204 if (!s) { 00205 PRINTF("BatMon: ADC not found\n"); 00206 PROCESS_EXIT(); 00207 } 00208 00209 n740_analog_deactivate(); 00210 m25p16_res(); 00211 n740_analog_activate(); 00212 00213 /* Find last written location */ 00214 if(find_gap() == -1) { 00215 PRINTF("BatMon: Flash storage full\n"); 00216 PROCESS_EXIT(); 00217 } 00218 00219 etimer_set(&et, BATMON_LOG_PERIOD * CLOCK_SECOND); 00220 00221 while(1) { 00222 PROCESS_YIELD(); 00223 if(ev == PROCESS_EVENT_TIMER && etimer_expired(&et)) { 00224 batmon_log(LOG_TRIGGER_PERIODIC); 00225 } 00226 } 00227 00228 PROCESS_END(); 00229 } 00230 /*---------------------------------------------------------------------------*/