Contiki 2.6

flasher.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of libmc1322x: see http://mc1322x.devl.org
00031  * for details. 
00032  *
00033  *
00034  */
00035 
00036 #include <mc1322x.h>
00037 #include <board.h>
00038 
00039 #include "tests.h"
00040 #include "config.h"
00041 
00042 #define DEBUG 1
00043 #if DEBUG
00044 #define dbg_putchr(...) putchr(__VA_ARGS__)
00045 #define dbg_putstr(...) putstr(__VA_ARGS__)
00046 #define dbg_put_hex(...) put_hex(__VA_ARGS__)
00047 #define dbg_put_hex16(...) put_hex16(__VA_ARGS__)
00048 #define dbg_put_hex32(...) put_hex32(__VA_ARGS__)
00049 #else
00050 #define dbg_putchr(...)
00051 #define dbg_putstr(...)
00052 #define dbg_put_hex(...)
00053 #define dbg_put_hex16(...)
00054 #define dbg_put_hex32(...)
00055 #endif
00056 
00057 uint8_t getc(void) 
00058 {
00059         volatile uint8_t c;
00060         while(*UART1_URXCON == 0);
00061         
00062         c = *UART1_UDATA;
00063         return c;
00064 }
00065 
00066 
00067 void flushrx(void);
00068 uint32_t to_u32(volatile uint32_t *c);
00069 
00070 enum parse_states {
00071         SCAN_X,
00072         READ_CHARS,
00073         PROCESS,
00074         MAX_STATE,
00075 };
00076 
00077 void main(void) {
00078         nvmType_t type=0;
00079         nvmErr_t err;
00080         volatile uint8_t c;
00081         volatile uint32_t i;
00082         volatile uint32_t buf[4];
00083         volatile uint32_t len=0;
00084         volatile uint32_t state = SCAN_X;
00085         volatile uint32_t addr,data;
00086 
00087 
00088         uart_init(INC, MOD, SAMP);
00089         disable_irq(UART1);
00090 
00091         vreg_init();
00092 
00093         dbg_putstr("Detecting internal nvm\n\r");
00094 
00095         err = nvm_detect(gNvmInternalInterface_c, &type);
00096                 
00097         dbg_putstr("nvm_detect returned: 0x");
00098         dbg_put_hex(err);
00099         dbg_putstr(" type is: 0x");
00100         dbg_put_hex32(type);
00101         dbg_putstr("\n\r");
00102         
00103         /* erase the flash */
00104         err = nvm_erase(gNvmInternalInterface_c, type, 0x7fffffff); 
00105 
00106         dbg_putstr("nvm_erase returned: 0x");
00107         dbg_put_hex(err);
00108         dbg_putstr("\n\r");
00109 
00110         dbg_putstr(" type is: 0x");
00111         dbg_put_hex32(type);
00112         dbg_putstr("\n\r");
00113 
00114         /* say we are ready */
00115         len = 0;
00116         putstr("ready");
00117         flushrx();
00118 
00119         /* read the length */
00120         for(i=0; i<4; i++) {
00121                 c = uart1_getc();
00122                 /* bail if the first byte of the length is zero */
00123                 len += (c<<(i*8));
00124         }
00125 
00126         dbg_putstr("len: ");
00127         dbg_put_hex32(len);
00128         dbg_putstr("\n\r");
00129         
00130         /* write the OKOK magic */
00131 
00132 #if BOOT_OK
00133         ((uint8_t *)buf)[0] = 'O'; ((uint8_t *)buf)[1] = 'K'; ((uint8_t *)buf)[2] = 'O'; ((uint8_t *)buf)[3] = 'K';     
00134 #elif BOOT_SECURE
00135         ((uint8_t *)buf)[0] = 'S'; ((uint8_t *)buf)[1] = 'E'; ((uint8_t *)buf)[2] = 'C'; ((uint8_t *)buf)[3] = 'U';     
00136 #else
00137         ((uint8_t *)buf)[0] = 'N'; ((uint8_t *)buf)[1] = 'O'; ((uint8_t *)buf)[2] = 'N'; ((uint8_t *)buf)[3] = 'O';
00138 #endif
00139 
00140         dbg_putstr(" type is: 0x");
00141         dbg_put_hex32(type);
00142         dbg_putstr("\n\r");
00143 
00144         /* don't make a valid boot image if the received length is zero */
00145         if(len == 0) {
00146                 ((uint8_t *)buf)[0] = 'N'; 
00147                 ((uint8_t *)buf)[1] = 'O'; 
00148                 ((uint8_t *)buf)[2] = 'N'; 
00149                 ((uint8_t *)buf)[3] = 'O';
00150         }
00151         
00152         err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)buf, 0, 4);
00153 
00154         dbg_putstr("nvm_write returned: 0x");
00155         dbg_put_hex(err);
00156         dbg_putstr("\n\r");
00157 
00158         /* write the length */
00159         err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&len, 4, 4);
00160 
00161         /* read a byte, write a byte */
00162         for(i=0; i<len; i++) {
00163                 c = getc();            
00164                 err = nvm_write(gNvmInternalInterface_c, type, (uint8_t *)&c, 8+i, 1); 
00165         }
00166 
00167         putstr("flasher done\n\r");
00168 
00169         state = SCAN_X; addr=0;
00170         while((c=getc())) {
00171                 if(state == SCAN_X) {
00172                         /* read until we see an 'x' */
00173                         if(c==0) { break; }
00174                         if(c!='x'){ continue; }         
00175                         /* go to read_chars once we have an 'x' */
00176                         state = READ_CHARS;
00177                         i = 0; 
00178                 }
00179                 if(state == READ_CHARS) {
00180                         /* read all the chars up to a ',' */
00181                         ((uint8_t *)buf)[i++] = c;
00182                         /* after reading a ',' */
00183                         /* goto PROCESS state */
00184                         if((c == ',') || (c == 0)) { state = PROCESS; }                         
00185                 }
00186                 if(state == PROCESS) {
00187                         if(addr==0) {
00188                                 /*interpret the string as the starting address */
00189                                 addr = to_u32(buf);                             
00190                         } else {
00191                                 /* string is data to write */
00192                                 data = to_u32(buf);
00193                                 putstr("writing addr ");
00194                                 put_hex32(addr);
00195                                 putstr(" data ");
00196                                 put_hex32(data);
00197                                 putstr("\n\r");
00198                                 err = nvm_write(gNvmInternalInterface_c, 1, (uint8_t *)&data, addr, 4);
00199                                 addr += 4;
00200                         }
00201                         /* look for the next 'x' */
00202                         state=SCAN_X;
00203                 }
00204         }
00205 
00206         while(1) {continue;};
00207 }
00208 
00209 void flushrx(void)
00210 {
00211         volatile uint8_t c;
00212         while(*UART1_URXCON !=0) {
00213                 c = *UART1_UDATA;
00214         }
00215 }
00216 
00217 /* Convert from ASCII hex.  Returns                                                                                                      
00218    the value, or 16 if it was space/newline, or                                                                                          
00219    32 if some other character. */
00220 uint8_t from_hex(uint8_t ch)
00221 {
00222         if(ch==' ' || ch=='\r' || ch=='\n')
00223                 return 16;
00224 
00225         if(ch < '0')
00226                 goto bad;
00227         if(ch <= '9')
00228                 return ch - '0';
00229         ch |= 0x20;
00230         if(ch < 'a')
00231                 goto bad;
00232         if(ch <= 'f')
00233                 return ch - 'a' + 10;
00234 bad:
00235         return 32;
00236 }
00237 
00238 uint32_t to_u32(volatile uint32_t *c) 
00239 {
00240         volatile uint32_t ret=0;
00241         volatile uint32_t i,val;
00242         
00243         /* c should be /x\d+,/ */
00244         i=1; /* skip x */
00245         while(((uint8_t *)c)[i] != ',') {
00246                 ret = ret<<4;
00247                 val = from_hex(((uint8_t *)c)[i++]);
00248                 ret += val;
00249         }
00250         return ret;
00251 }
00252 
00253 
00254