Contiki 2.6

loader-arch.c

00001 /*
00002  * Copyright (c) 2005, Swedish Institute of 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  * @(#)$Id: loader-arch.c,v 1.2 2010/10/19 18:29:04 adamdunkels Exp $
00032  */
00033 
00034 #include "contiki.h"
00035 #include "sys/clock.h"
00036 
00037 #include "net/uip.h"
00038 
00039 #include "dev/leds.h"
00040 #include "dev/eeprom.h"
00041 #include "dev/flash.h"
00042 
00043 #include "loader/loader-arch.h"
00044 
00045 void *loader_arch_codeaddr, *loader_arch_dataaddr;
00046 
00047 
00048 #define FLASHADDR ((char *)0x8000)
00049 #define DATAADDR ((char *)0x900)
00050 #define READSIZE 0x10
00051 
00052 #define beep(n) do { } while (0)
00053 #define beep_beep(n) do { } while (0)
00054 
00055 /*----------------------------------------------------------------------------------*/
00056 void
00057 loader_arch_load(unsigned short startaddr)
00058 {
00059   unsigned short tmp;
00060   unsigned short codelen, datalen, sumlen;
00061   int i, j;
00062   unsigned short ptr;
00063   unsigned short *flashptr;
00064   void (* init)(void *);
00065   unsigned char tmpdata[READSIZE];
00066   unsigned char sum;
00067 
00068   /* Read the magic word and version number from the first four bytes
00069      in EEPROM. */
00070   eeprom_read(startaddr, (char *)&tmp, 2);
00071   if(tmp != UIP_HTONS(LOADER_ARCH_MAGIC)) {
00072     beep_beep(60000);
00073     return;
00074   }
00075 
00076   eeprom_read(startaddr + 2, (char *)&tmp, 2);
00077   if(tmp != UIP_HTONS(LOADER_ARCH_VERSION)) {
00078     return;
00079   }
00080 
00081   startaddr += 4;
00082 
00083   /* Read the total lenghth that the checksum covers. */
00084   eeprom_read(startaddr, (char *)&sumlen, 2);
00085   
00086   sumlen = uip_htons(sumlen);
00087   
00088   sum = 0;
00089 
00090   for(i = 0; sumlen - i > READSIZE; i += READSIZE) {
00091     eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
00092 
00093     for(j = 0; j < READSIZE; ++j) {
00094       sum += tmpdata[j];
00095       if(sum < tmpdata[j]) {
00096         ++sum;
00097       }
00098     }
00099   }
00100   if(sumlen - i > 0) {
00101     eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
00102 
00103     for(j = 0; j < sumlen - i; ++j) {
00104       sum += tmpdata[j];
00105       if(sum < tmpdata[j]) {
00106         ++sum;
00107       }
00108     }
00109   }
00110 
00111   /* If the checksum was wrong, we beep. The number of beeps indicate
00112      the numerival value of the calculated checksum. */
00113   if(sum != 0xff) {
00114     leds_on(LEDS_RED);
00115     
00116     for(i = 0; i < (sum >> 4); ++i) {
00117       beep_beep(200);
00118       for(j = 0; j < 2; ++j) {
00119         clock_delay(60000);
00120       }
00121     }
00122     
00123     for(j = 0; j < 8; ++j) {
00124       clock_delay(60000);
00125     }
00126     
00127     for(i = 0; i < (sum & 0x0f); ++i) {
00128       beep_beep(200);
00129       for(j = 0; j < 2; ++j) {
00130         clock_delay(60000);
00131       }
00132     }
00133 
00134     leds_off(LEDS_RED);
00135     
00136     return;
00137     
00138   } else {
00139     leds_on(LEDS_GREEN);
00140     for(i = 0; i < 4; ++i) {
00141       beep_beep(200);
00142       for(j = 0; j < 2; ++j) {
00143         clock_delay(60000);
00144       }
00145     }
00146     leds_off(LEDS_GREEN);
00147   }
00148 
00149 
00150   leds_on(LEDS_YELLOW);
00151   startaddr += 2;
00152   
00153   /* Read the size of the code segment from the next two bytes in EEPROM. */
00154   eeprom_read(startaddr, (char *)&codelen, 2);
00155   /* Convert from network byte order to host byte order. */
00156   codelen = uip_htons(codelen);
00157   
00158 
00159   /* Flash program code into ROM. We use the available space in the
00160      program's data memory to temporarily store the code before
00161      flashing it into ROM. */
00162   flash_setup();
00163 
00164   flashptr = (unsigned short *)FLASHADDR;
00165   for(ptr = startaddr + 2; ptr < startaddr + 2 + codelen; ptr += READSIZE) {
00166     
00167     /* Read data from EEPROM into RAM. */
00168     eeprom_read(ptr, DATAADDR, READSIZE);
00169 
00170     /* Clear flash page on 512 byte boundary. */
00171     if((((unsigned short)flashptr) & 0x01ff) == 0) {
00172       flash_clear(flashptr);
00173     }
00174     
00175     /* Burn data from RAM into flash ROM. Flash is burned one 16-bit
00176        word at a time, so we need to be careful when incrementing
00177        pointers. The flashptr is already a short pointer, so
00178        incrementing it by one will actually increment the address by
00179        two. */
00180     for(i = 0; i < READSIZE / 2; ++i) {
00181       flash_write(flashptr, ((unsigned short *)DATAADDR)[i]);
00182       ++flashptr;
00183     }
00184   }
00185 
00186   flash_done();
00187 
00188   leds_off(LEDS_YELLOW);
00189 
00190   leds_on(LEDS_GREEN);
00191   
00192   /* Read the size of the code segment from the first two bytes in EEPROM. */
00193   eeprom_read(startaddr + 2 + codelen, (char *)&datalen, 2);
00194   
00195   /* Convert from network byte order to host byte order. */
00196   datalen = uip_htons(datalen);
00197 
00198   if(datalen > 0) {
00199     /* Read the contents of the data memory into RAM. */
00200     eeprom_read(startaddr + 2 + codelen + 2, DATAADDR, datalen);
00201   }
00202 
00203   for(i = 0; i < 4; ++i) {
00204     beep_beep(2000);
00205     clock_delay(20000);
00206   }
00207 
00208   leds_off(LEDS_GREEN);
00209   
00210   /* Execute the loaded program. */
00211   init = ((void (*)(void *))FLASHADDR);
00212   init((void *)0);
00213 }
00214 /*----------------------------------------------------------------------------------*/
00215 void
00216 loader_arch_free(void *code, void *data)
00217 {
00218 }
00219 /*----------------------------------------------------------------------------------*/