Contiki 3.x
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  */
32 
33 #include "contiki.h"
34 #include "sys/clock.h"
35 
36 #include "net/ip/uip.h"
37 
38 #include "dev/leds.h"
39 #include "dev/eeprom.h"
40 #include "dev/flash.h"
41 
42 #include "loader/loader-arch.h"
43 
44 void *loader_arch_codeaddr, *loader_arch_dataaddr;
45 
46 
47 #define FLASHADDR ((char *)0x8000)
48 #define DATAADDR ((char *)0x900)
49 #define READSIZE 0x10
50 
51 #define beep(n) do { } while (0)
52 #define beep_beep(n) do { } while (0)
53 
54 /*----------------------------------------------------------------------------------*/
55 void
56 loader_arch_load(unsigned short startaddr)
57 {
58  unsigned short tmp;
59  unsigned short codelen, datalen, sumlen;
60  int i, j;
61  unsigned short ptr;
62  unsigned short *flashptr;
63  void (* init)(void *);
64  unsigned char tmpdata[READSIZE];
65  unsigned char sum;
66 
67  /* Read the magic word and version number from the first four bytes
68  in EEPROM. */
69  eeprom_read(startaddr, (char *)&tmp, 2);
70  if(tmp != UIP_HTONS(LOADER_ARCH_MAGIC)) {
71  beep_beep(60000);
72  return;
73  }
74 
75  eeprom_read(startaddr + 2, (char *)&tmp, 2);
76  if(tmp != UIP_HTONS(LOADER_ARCH_VERSION)) {
77  return;
78  }
79 
80  startaddr += 4;
81 
82  /* Read the total lenghth that the checksum covers. */
83  eeprom_read(startaddr, (char *)&sumlen, 2);
84 
85  sumlen = uip_htons(sumlen);
86 
87  sum = 0;
88 
89  for(i = 0; sumlen - i > READSIZE; i += READSIZE) {
90  eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
91 
92  for(j = 0; j < READSIZE; ++j) {
93  sum += tmpdata[j];
94  if(sum < tmpdata[j]) {
95  ++sum;
96  }
97  }
98  }
99  if(sumlen - i > 0) {
100  eeprom_read(startaddr + 2 + i, tmpdata, READSIZE);
101 
102  for(j = 0; j < sumlen - i; ++j) {
103  sum += tmpdata[j];
104  if(sum < tmpdata[j]) {
105  ++sum;
106  }
107  }
108  }
109 
110  /* If the checksum was wrong, we beep. The number of beeps indicate
111  the numerival value of the calculated checksum. */
112  if(sum != 0xff) {
113  leds_on(LEDS_RED);
114 
115  for(i = 0; i < (sum >> 4); ++i) {
116  beep_beep(200);
117  for(j = 0; j < 2; ++j) {
118  clock_delay(60000);
119  }
120  }
121 
122  for(j = 0; j < 8; ++j) {
123  clock_delay(60000);
124  }
125 
126  for(i = 0; i < (sum & 0x0f); ++i) {
127  beep_beep(200);
128  for(j = 0; j < 2; ++j) {
129  clock_delay(60000);
130  }
131  }
132 
133  leds_off(LEDS_RED);
134 
135  return;
136 
137  } else {
138  leds_on(LEDS_GREEN);
139  for(i = 0; i < 4; ++i) {
140  beep_beep(200);
141  for(j = 0; j < 2; ++j) {
142  clock_delay(60000);
143  }
144  }
145  leds_off(LEDS_GREEN);
146  }
147 
148 
149  leds_on(LEDS_YELLOW);
150  startaddr += 2;
151 
152  /* Read the size of the code segment from the next two bytes in EEPROM. */
153  eeprom_read(startaddr, (char *)&codelen, 2);
154  /* Convert from network byte order to host byte order. */
155  codelen = uip_htons(codelen);
156 
157 
158  /* Flash program code into ROM. We use the available space in the
159  program's data memory to temporarily store the code before
160  flashing it into ROM. */
161  flash_setup();
162 
163  flashptr = (unsigned short *)FLASHADDR;
164  for(ptr = startaddr + 2; ptr < startaddr + 2 + codelen; ptr += READSIZE) {
165 
166  /* Read data from EEPROM into RAM. */
167  eeprom_read(ptr, DATAADDR, READSIZE);
168 
169  /* Clear flash page on 512 byte boundary. */
170  if((((unsigned short)flashptr) & 0x01ff) == 0) {
171  flash_clear(flashptr);
172  }
173 
174  /* Burn data from RAM into flash ROM. Flash is burned one 16-bit
175  word at a time, so we need to be careful when incrementing
176  pointers. The flashptr is already a short pointer, so
177  incrementing it by one will actually increment the address by
178  two. */
179  for(i = 0; i < READSIZE / 2; ++i) {
180  flash_write(flashptr, ((unsigned short *)DATAADDR)[i]);
181  ++flashptr;
182  }
183  }
184 
185  flash_done();
186 
187  leds_off(LEDS_YELLOW);
188 
189  leds_on(LEDS_GREEN);
190 
191  /* Read the size of the code segment from the first two bytes in EEPROM. */
192  eeprom_read(startaddr + 2 + codelen, (char *)&datalen, 2);
193 
194  /* Convert from network byte order to host byte order. */
195  datalen = uip_htons(datalen);
196 
197  if(datalen > 0) {
198  /* Read the contents of the data memory into RAM. */
199  eeprom_read(startaddr + 2 + codelen + 2, DATAADDR, datalen);
200  }
201 
202  for(i = 0; i < 4; ++i) {
203  beep_beep(2000);
204  clock_delay(20000);
205  }
206 
207  leds_off(LEDS_GREEN);
208 
209  /* Execute the loaded program. */
210  init = ((void (*)(void *))FLASHADDR);
211  init((void *)0);
212 }
213 /*----------------------------------------------------------------------------------*/
214 void
215 loader_arch_free(void *code, void *data)
216 {
217 }
218 /*----------------------------------------------------------------------------------*/
void eeprom_read(eeprom_addr_t addr, unsigned char *buf, int size)
Read data from the EEPROM.
Definition: eeprom.c:49
#define LEDS_RED
LED1 (Red) -&gt; PC0.
Definition: board.h:89
void flash_clear(unsigned short *ptr)
Clear a 16-bit word in flash ROM.
Definition: flash.c:86
Header file for the uIP TCP/IP stack.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1238
#define LEDS_YELLOW
LED2 (Yellow) -&gt; PC1.
Definition: board.h:80
#define LEDS_GREEN
LED3 (Green) -&gt; PC2.
Definition: board.h:81
EEPROM functions.
void beep_beep(int i)
Beep for a specified time.
Definition: beep.c:47
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
Definition: uip6.c:2298
void flash_done(void)
Function that is to be called after flashing is done.
Definition: flash.c:76
void flash_write(unsigned short *ptr, unsigned short word)
Write a 16-bit word to flash ROM.
Definition: flash.c:98
void clock_delay(unsigned int delay)
Obsolete delay function but we implement it here since some code still uses it.
Definition: clock.c:60
void flash_setup(void)
Setup function to be called before any of the flash programming functions.
Definition: flash.c:48