Contiki 2.5
flasher.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the Institute nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This file is part of libmc1322x: see http://mc1322x.devl.org
31  * for details.
32  *
33  *
34  */
35 
36 #include <mc1322x.h>
37 #include <board.h>
38 
39 #include "tests.h"
40 #include "config.h"
41 
42 #define DEBUG 1
43 #if DEBUG
44 #define dbg_putchr(...) putchr(__VA_ARGS__)
45 #define dbg_putstr(...) putstr(__VA_ARGS__)
46 #define dbg_put_hex(...) put_hex(__VA_ARGS__)
47 #define dbg_put_hex16(...) put_hex16(__VA_ARGS__)
48 #define dbg_put_hex32(...) put_hex32(__VA_ARGS__)
49 #else
50 #define dbg_putchr(...)
51 #define dbg_putstr(...)
52 #define dbg_put_hex(...)
53 #define dbg_put_hex16(...)
54 #define dbg_put_hex32(...)
55 #endif
56 
57 uint8_t getc(void)
58 {
59  volatile uint8_t c;
60  while(*UART1_URXCON == 0);
61 
62  c = *UART1_UDATA;
63  return c;
64 }
65 
66 
67 void flushrx(void);
68 uint32_t to_u32(volatile uint32_t *c);
69 
70 enum parse_states {
71  SCAN_X,
72  READ_CHARS,
73  PROCESS,
74  MAX_STATE,
75 };
76 
77 void main(void) {
78  nvmType_t type=0;
79  nvmErr_t err;
80  volatile uint8_t c;
81  volatile uint32_t i;
82  volatile uint32_t buf[4];
83  volatile uint32_t len=0;
84  volatile uint32_t state = SCAN_X;
85  volatile uint32_t addr,data;
86 
87 
88  uart_init(INC, MOD, SAMP);
89  disable_irq(UART1);
90 
91  vreg_init();
92 
93  dbg_putstr("Detecting internal nvm\n\r");
94 
95  err = nvm_detect(gNvmInternalInterface_c, &type);
96 
97  dbg_putstr("nvm_detect returned: 0x");
98  dbg_put_hex(err);
99  dbg_putstr(" type is: 0x");
100  dbg_put_hex32(type);
101  dbg_putstr("\n\r");
102 
103  /* erase the flash */
104  err = nvm_erase(gNvmInternalInterface_c, type, 0x7fffffff);
105 
106  dbg_putstr("nvm_erase returned: 0x");
107  dbg_put_hex(err);
108  dbg_putstr("\n\r");
109 
110  dbg_putstr(" type is: 0x");
111  dbg_put_hex32(type);
112  dbg_putstr("\n\r");
113 
114  /* say we are ready */
115  len = 0;
116  putstr("ready");
117  flushrx();
118 
119  /* read the length */
120  for(i=0; i<4; i++) {
121  c = uart1_getc();
122  /* bail if the first byte of the length is zero */
123  len += (c<<(i*8));
124  }
125 
126  dbg_putstr("len: ");
127  dbg_put_hex32(len);
128  dbg_putstr("\n\r");
129 
130  /* write the OKOK magic */
131 
132 #if BOOT_OK
133  ((uint8_t *)buf)[0] = 'O'; ((uint8_t *)buf)[1] = 'K'; ((uint8_t *)buf)[2] = 'O'; ((uint8_t *)buf)[3] = 'K';
134 #elif BOOT_SECURE
135  ((uint8_t *)buf)[0] = 'S'; ((uint8_t *)buf)[1] = 'E'; ((uint8_t *)buf)[2] = 'C'; ((uint8_t *)buf)[3] = 'U';
136 #else
137  ((uint8_t *)buf)[0] = 'N'; ((uint8_t *)buf)[1] = 'O'; ((uint8_t *)buf)[2] = 'N'; ((uint8_t *)buf)[3] = 'O';
138 #endif
139 
140  dbg_putstr(" type is: 0x");
141  dbg_put_hex32(type);
142  dbg_putstr("\n\r");
143 
144  /* don't make a valid boot image if the received length is zero */
145  if(len == 0) {
146  ((uint8_t *)buf)[0] = 'N';
147  ((uint8_t *)buf)[1] = 'O';
148  ((uint8_t *)buf)[2] = 'N';
149  ((uint8_t *)buf)[3] = 'O';
150  }
151 
152  err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)buf, 0, 4);
153 
154  dbg_putstr("nvm_write returned: 0x");
155  dbg_put_hex(err);
156  dbg_putstr("\n\r");
157 
158  /* write the length */
159  err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&len, 4, 4);
160 
161  /* read a byte, write a byte */
162  for(i=0; i<len; i++) {
163  c = getc();
164  err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&c, 8+i, 1);
165  }
166 
167  putstr("flasher done\n\r");
168 
169  state = SCAN_X; addr=0;
170  while((c=getc())) {
171  if(state == SCAN_X) {
172  /* read until we see an 'x' */
173  if(c==0) { break; }
174  if(c!='x'){ continue; }
175  /* go to read_chars once we have an 'x' */
176  state = READ_CHARS;
177  i = 0;
178  }
179  if(state == READ_CHARS) {
180  /* read all the chars up to a ',' */
181  ((uint8_t *)buf)[i++] = c;
182  /* after reading a ',' */
183  /* goto PROCESS state */
184  if((c == ',') || (c == 0)) { state = PROCESS; }
185  }
186  if(state == PROCESS) {
187  if(addr==0) {
188  /*interpret the string as the starting address */
189  addr = to_u32(buf);
190  } else {
191  /* string is data to write */
192  data = to_u32(buf);
193  putstr("writing addr ");
194  put_hex32(addr);
195  putstr(" data ");
196  put_hex32(data);
197  putstr("\n\r");
198  err = nvm_write(gNvmInternalInterface_c, 1, (uint8_t *)&data, addr, 4);
199  addr += 4;
200  }
201  /* look for the next 'x' */
202  state=SCAN_X;
203  }
204  }
205 
206  while(1) {continue;};
207 }
208 
209 void flushrx(void)
210 {
211  volatile uint8_t c;
212  while(*UART1_URXCON !=0) {
213  c = *UART1_UDATA;
214  }
215 }
216 
217 /* Convert from ASCII hex. Returns
218  the value, or 16 if it was space/newline, or
219  32 if some other character. */
220 uint8_t from_hex(uint8_t ch)
221 {
222  if(ch==' ' || ch=='\r' || ch=='\n')
223  return 16;
224 
225  if(ch < '0')
226  goto bad;
227  if(ch <= '9')
228  return ch - '0';
229  ch |= 0x20;
230  if(ch < 'a')
231  goto bad;
232  if(ch <= 'f')
233  return ch - 'a' + 10;
234 bad:
235  return 32;
236 }
237 
238 uint32_t to_u32(volatile uint32_t *c)
239 {
240  volatile uint32_t ret=0;
241  volatile uint32_t i,val;
242 
243  /* c should be /x\d+,/ */
244  i=1; /* skip x */
245  while(((uint8_t *)c)[i] != ',') {
246  ret = ret<<4;
247  val = from_hex(((uint8_t *)c)[i++]);
248  ret += val;
249  }
250  return ret;
251 }
252 
253 
254