Contiki 2.5
loader-arch.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: loader-arch.c,v 1.2 2010/10/19 18:29:04 adamdunkels Exp $
32  */
33 
34 #include "contiki.h"
35 #include "sys/clock.h"
36 
37 #include "net/uip.h"
38 
39 #include "dev/leds.h"
40 #include "dev/eeprom.h"
41 #include "dev/flash.h"
42 
43 #include "loader/loader-arch.h"
44 
45 void *loader_arch_codeaddr, *loader_arch_dataaddr;
46 
47 
48 #define FLASHADDR ((char *)0x8000)
49 #define DATAADDR ((char *)0x900)
50 #define READSIZE 0x10
51 
52 #define beep(n) do { } while (0)
53 #define beep_beep(n) do { } while (0)
54 
55 /*----------------------------------------------------------------------------------*/
56 void
57 loader_arch_load(unsigned short startaddr)
58 {
59  unsigned short tmp;
60  unsigned short codelen, datalen, sumlen;
61  int i, j;
62  unsigned short ptr;
63  unsigned short *flashptr;
64  void (* init)(void *);
65  unsigned char tmpdata[READSIZE];
66  unsigned char sum;
67 
68  /* Read the magic word and version number from the first four bytes
69  in EEPROM. */
70  eeprom_read(startaddr, (char *)&tmp, 2);
71  if(tmp != UIP_HTONS(LOADER_ARCH_MAGIC)) {
72  beep_beep(60000);
73  return;
74  }
75 
76  eeprom_read(startaddr + 2, (char *)&tmp, 2);
77  if(tmp != UIP_HTONS(LOADER_ARCH_VERSION)) {
78  return;
79  }
80 
81  startaddr += 4;
82 
83  /* Read the total lenghth that the checksum covers. */
84  eeprom_read(startaddr, (char *)&sumlen, 2);
85 
86  sumlen = uip_htons(sumlen);
87 
88  sum = 0;
89 
90  for(i = 0; sumlen - i > READSIZE; i += READSIZE) {
91  eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
92 
93  for(j = 0; j < READSIZE; ++j) {
94  sum += tmpdata[j];
95  if(sum < tmpdata[j]) {
96  ++sum;
97  }
98  }
99  }
100  if(sumlen - i > 0) {
101  eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
102 
103  for(j = 0; j < sumlen - i; ++j) {
104  sum += tmpdata[j];
105  if(sum < tmpdata[j]) {
106  ++sum;
107  }
108  }
109  }
110 
111  /* If the checksum was wrong, we beep. The number of beeps indicate
112  the numerival value of the calculated checksum. */
113  if(sum != 0xff) {
114  leds_on(LEDS_RED);
115 
116  for(i = 0; i < (sum >> 4); ++i) {
117  beep_beep(200);
118  for(j = 0; j < 2; ++j) {
119  clock_delay(60000);
120  }
121  }
122 
123  for(j = 0; j < 8; ++j) {
124  clock_delay(60000);
125  }
126 
127  for(i = 0; i < (sum & 0x0f); ++i) {
128  beep_beep(200);
129  for(j = 0; j < 2; ++j) {
130  clock_delay(60000);
131  }
132  }
133 
134  leds_off(LEDS_RED);
135 
136  return;
137 
138  } else {
139  leds_on(LEDS_GREEN);
140  for(i = 0; i < 4; ++i) {
141  beep_beep(200);
142  for(j = 0; j < 2; ++j) {
143  clock_delay(60000);
144  }
145  }
146  leds_off(LEDS_GREEN);
147  }
148 
149 
150  leds_on(LEDS_YELLOW);
151  startaddr += 2;
152 
153  /* Read the size of the code segment from the next two bytes in EEPROM. */
154  eeprom_read(startaddr, (char *)&codelen, 2);
155  /* Convert from network byte order to host byte order. */
156  codelen = uip_htons(codelen);
157 
158 
159  /* Flash program code into ROM. We use the available space in the
160  program's data memory to temporarily store the code before
161  flashing it into ROM. */
162  flash_setup();
163 
164  flashptr = (unsigned short *)FLASHADDR;
165  for(ptr = startaddr + 2; ptr < startaddr + 2 + codelen; ptr += READSIZE) {
166 
167  /* Read data from EEPROM into RAM. */
168  eeprom_read(ptr, DATAADDR, READSIZE);
169 
170  /* Clear flash page on 512 byte boundary. */
171  if((((unsigned short)flashptr) & 0x01ff) == 0) {
172  flash_clear(flashptr);
173  }
174 
175  /* Burn data from RAM into flash ROM. Flash is burned one 16-bit
176  word at a time, so we need to be careful when incrementing
177  pointers. The flashptr is already a short pointer, so
178  incrementing it by one will actually increment the address by
179  two. */
180  for(i = 0; i < READSIZE / 2; ++i) {
181  flash_write(flashptr, ((unsigned short *)DATAADDR)[i]);
182  ++flashptr;
183  }
184  }
185 
186  flash_done();
187 
188  leds_off(LEDS_YELLOW);
189 
190  leds_on(LEDS_GREEN);
191 
192  /* Read the size of the code segment from the first two bytes in EEPROM. */
193  eeprom_read(startaddr + 2 + codelen, (char *)&datalen, 2);
194 
195  /* Convert from network byte order to host byte order. */
196  datalen = uip_htons(datalen);
197 
198  if(datalen > 0) {
199  /* Read the contents of the data memory into RAM. */
200  eeprom_read(startaddr + 2 + codelen + 2, DATAADDR, datalen);
201  }
202 
203  for(i = 0; i < 4; ++i) {
204  beep_beep(2000);
205  clock_delay(20000);
206  }
207 
208  leds_off(LEDS_GREEN);
209 
210  /* Execute the loaded program. */
211  init = ((void (*)(void *))FLASHADDR);
212  init((void *)0);
213 }
214 /*----------------------------------------------------------------------------------*/
215 void
216 loader_arch_free(void *code, void *data)
217 {
218 }
219 /*----------------------------------------------------------------------------------*/