⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd_load.c.l

📁 嵌入式试验箱S3C2410的bootloader源代码
💻 L
📖 第 1 页 / 共 3 页
字号:
01 /*02  * (C) Copyright 2000-200403  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.04  *05  * See file CREDITS for list of people who contributed to this06  * project.07  *08  * This program is free software; you can redistribute it and/or09  * modify it under the terms of the GNU General Public License as10  * published by the Free Software Foundation; either version 2 of11  * the License, or (at your option) any later version.12  *13  * This program is distributed in the hope that it will be useful,14  * but WITHOUT ANY WARRANTY; without even the implied warranty of15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the16  * GNU General Public License for more details.17  *18  * You should have received a copy of the GNU General Public License19  * along with this program; if not, write to the Free Software20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,21  * MA 02111-1307 USA22  */23 24 /*25  * Serial up- and download support26  */27 #include <common.h>28 #include <command.h>29 #include <s_record.h>30 #include <net.h>31 #include <exports.h>32 #include <xyzModem.h>33 34 DECLARE_GLOBAL_DATA_PTR;35 36 #if (CONFIG_COMMANDS & CFG_CMD_LOADB)37 /* support xmodem, www.arm9.net */38 static ulong load_serial_xmodem (ulong offset);39 static ulong load_serial_ymodem (ulong offset);40 #endif41 42 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)43 static ulong load_serial (ulong offset);44 static int read_record (char *buf, ulong len);45 # if (CONFIG_COMMANDS & CFG_CMD_SAVES)46 static int save_serial (ulong offset, ulong size);47 static int write_record (char *buf);48 # endif /* CFG_CMD_SAVES */49 50 static int do_echo = 1;51 #endif /* CFG_CMD_LOADS */52 53 /* -------------------------------------------------------------------- */54 55 #if (CONFIG_COMMANDS & CFG_CMD_LOADS)56 int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])57 {58     ulong offset = 0;59     ulong addr;60     int i;61     char *env_echo;62     int rcode = 0;63 #ifdef  CFG_LOADS_BAUD_CHANGE64     int load_baudrate, current_baudrate;65 66     load_baudrate = current_baudrate = gd->baudrate;67 #endif68 69     if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {70         do_echo = 1;71     } else {72         do_echo = 0;73     }74 75 #ifdef  CFG_LOADS_BAUD_CHANGE76     if (argc >= 2) {77         offset = simple_strtoul(argv[1], NULL, 16);78     }79     if (argc == 3) {80         load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);81 82         /* default to current baudrate */83         if (load_baudrate == 0)84             load_baudrate = current_baudrate;85     }86     if (load_baudrate != current_baudrate) {87         printf ("## Switch baudrate to %d bps and press ENTER ...\n",88             load_baudrate);89         udelay(50000);90         gd->baudrate = load_baudrate;91         serial_setbrg ();92         udelay(50000);93         for (;;) {94             if (getc() == '\r')95                 break;96         }97     }98 #else   /* ! CFG_LOADS_BAUD_CHANGE */99     if (argc == 2) {100         offset = simple_strtoul(argv[1], NULL, 16);101     }102 #endif  /* CFG_LOADS_BAUD_CHANGE */103 104     printf ("## Ready for S-Record download ...\n");105 106     addr = load_serial (offset);107 108     /*109      * Gather any trailing characters (for instance, the ^D which110      * is sent by 'cu' after sending a file), and give the111      * box some time (100 * 1 ms)112      */113     for (i=0; i<100; ++i) {114         if (tstc()) {115             (void) getc();116         }117         udelay(1000);118     }119 120     if (addr == ~0) {121         printf ("## S-Record download aborted\n");122         rcode = 1;123     } else {124         printf ("## Start Addr      = 0x%08lX\n", addr);125         load_addr = addr;126     }127 128 #ifdef  CFG_LOADS_BAUD_CHANGE129     if (load_baudrate != current_baudrate) {130         printf ("## Switch baudrate to %d bps and press ESC ...\n",131             current_baudrate);132         udelay (50000);133         gd->baudrate = current_baudrate;134         serial_setbrg ();135         udelay (50000);136         for (;;) {137             if (getc() == 0x1B) /* ESC */138                 break;139         }140     }141 #endif142     return rcode;143 }144 145 static ulong146 load_serial (ulong offset)147 {148     char    record[SREC_MAXRECLEN + 1]; /* buffer for one S-Record  */149     char    binbuf[SREC_MAXBINLEN];     /* buffer for binary data   */150     int binlen;             /* no. of data bytes in S-Rec.  */151     int type;               /* return code for record type  */152     ulong   addr;               /* load address from S-Record   */153     ulong   size;               /* number of bytes transferred  */154     char    buf[32];155     ulong   store_addr;156     ulong   start_addr = ~0;157     ulong   end_addr   =  0;158     int line_count =  0;159 160     while (read_record(record, SREC_MAXRECLEN + 1) >= 0) {161         type = srec_decode (record, &binlen, &addr, binbuf);162 163         if (type < 0) {164             return (~0);        /* Invalid S-Record     */165         }166 167         switch (type) {168         case SREC_DATA2:169         case SREC_DATA3:170         case SREC_DATA4:171             store_addr = addr + offset;172 #ifndef CFG_NO_FLASH173             if (addr2info(store_addr)) {174             int rc;175 176             rc = flash_write((char *)binbuf,store_addr,binlen);177             if (rc != 0) {178                 flash_perror (rc);179                 return (~0);180             }181             } else182 #endif183             {184             memcpy ((char *)(store_addr), binbuf, binlen);185             }186             if ((store_addr) < start_addr)187             start_addr = store_addr;188             if ((store_addr + binlen - 1) > end_addr)189             end_addr = store_addr + binlen - 1;190             break;191         case SREC_END2:192         case SREC_END3:193         case SREC_END4:194             udelay (10000);195             size = end_addr - start_addr + 1;196             printf ("\n"197                 "## First Load Addr = 0x%08lX\n"198                 "## Last  Load Addr = 0x%08lX\n"199                 "## Total Size      = 0x%08lX = %ld Bytes\n",200                 start_addr, end_addr, size, size201             );202             flush_cache (start_addr, size);203             sprintf(buf, "%lX", size);204             setenv("filesize", buf);205             return (addr);206         case SREC_START:207             break;208         default:209             break;210         }211         if (!do_echo) { /* print a '.' every 100 lines */212             if ((++line_count % 100) == 0)213                 putc ('.');214         }215     }216 217     return (~0);            /* Download aborted     */218 }219 220 static int221 read_record (char *buf, ulong len)222 {223     char *p;224     char c;225 226     --len;  /* always leave room for terminating '\0' byte */227 228     for (p=buf; p < buf+len; ++p) {229         c = getc();     /* read character       */230         if (do_echo)231             putc (c);   /* ... and echo it      */232 233         switch (c) {234         case '\r':235         case '\n':236             *p = '\0';237             return (p - buf);238         case '\0':239         case 0x03:          /* ^C - Control C       */240             return (-1);241         default:242             *p = c;243         }244 245         /* Check for the console hangup (if any different from serial) */246         if (gd->jt[XF_getc] != getc) {247         if (ctrlc()) {248             return (-1);249         }250         }251     }252 253     /* line too long - truncate */254     *p = '\0';255     return (p - buf);256 }257 258 #if (CONFIG_COMMANDS & CFG_CMD_SAVES)259 260 int do_save_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])261 {262     ulong offset = 0;263     ulong size   = 0;264 #ifdef  CFG_LOADS_BAUD_CHANGE265     int save_baudrate, current_baudrate;266 267     save_baudrate = current_baudrate = gd->baudrate;268 #endif269 270     if (argc >= 2) {271         offset = simple_strtoul(argv[1], NULL, 16);272     }273 #ifdef  CFG_LOADS_BAUD_CHANGE274     if (argc >= 3) {275         size = simple_strtoul(argv[2], NULL, 16);276     }277     if (argc == 4) {278         save_baudrate = (int)simple_strtoul(argv[3], NULL, 10);279 280         /* default to current baudrate */281         if (save_baudrate == 0)282             save_baudrate = current_baudrate;283     }284     if (save_baudrate != current_baudrate) {285         printf ("## Switch baudrate to %d bps and press ENTER ...\n",286             save_baudrate);287         udelay(50000);288         gd->baudrate = save_baudrate;289         serial_setbrg ();290         udelay(50000);291         for (;;) {292             if (getc() == '\r')293                 break;294         }295     }296 #else   /* ! CFG_LOADS_BAUD_CHANGE */297     if (argc == 3) {298         size = simple_strtoul(argv[2], NULL, 16);299     }300 #endif  /* CFG_LOADS_BAUD_CHANGE */301 302     printf ("## Ready for S-Record upload, press ENTER to proceed ...\n");303     for (;;) {304         if (getc() == '\r')305             break;306     }307     if(save_serial (offset, size)) {308         printf ("## S-Record upload aborted\n");309     } else {310         printf ("## S-Record upload complete\n");311     }312 #ifdef  CFG_LOADS_BAUD_CHANGE313     if (save_baudrate != current_baudrate) {314         printf ("## Switch baudrate to %d bps and press ESC ...\n",315             (int)current_baudrate);316         udelay (50000);317         gd->baudrate = current_baudrate;318         serial_setbrg ();319         udelay (50000);320         for (;;) {321             if (getc() == 0x1B) /* ESC */322                 break;323         }324     }325 #endif326     return 0;327 }328 329 #define SREC3_START             "S0030000FC\n"330 #define SREC3_FORMAT            "S3%02X%08lX%s%02X\n"331 #define SREC3_END               "S70500000000FA\n"332 #define SREC_BYTES_PER_RECORD   16333 334 static int save_serial (ulong address, ulong count)335 {336     int i, c, reclen, checksum, length;337     char *hex = "0123456789ABCDEF";338     char    record[2*SREC_BYTES_PER_RECORD+16]; /* buffer for one S-Record  */339     char    data[2*SREC_BYTES_PER_RECORD+1];    /* buffer for hex data  */340 341     reclen = 0;342     checksum  = 0;343 344     if(write_record(SREC3_START))           /* write the header */345         return (-1);346     do {347         if(count) {                     /* collect hex data in the buffer  */348             c = *(volatile uchar*)(address + reclen);   /* get one byte    */349             checksum += c;                          /* accumulate checksum */350             data[2*reclen]   = hex[(c>>4)&0x0f];351             data[2*reclen+1] = hex[c & 0x0f];352             data[2*reclen+2] = '\0';353             ++reclen;354             --count;355         }356         if(reclen == SREC_BYTES_PER_RECORD || count == 0) {357             /* enough data collected for one record: dump it */358             if(reclen) {    /* build & write a data record: */359                 /* address + data + checksum */360                 length = 4 + reclen + 1;361 362                 /* accumulate length bytes into checksum */363                 for(i = 0; i < 2; i++)364                     checksum += (length >> (8*i)) & 0xff;365 366                 /* accumulate address bytes into checksum: */367                 for(i = 0; i < 4; i++)368                     checksum += (address >> (8*i)) & 0xff;369 370                 /* make proper checksum byte: */371                 checksum = ~checksum & 0xff;372 373                 /* output one record: */374                 sprintf(record, SREC3_FORMAT, length, address, data, checksum);375                 if(write_record(record))376                     return (-1);377             }378             address  += reclen;  /* increment address */379             checksum  = 0;380             reclen    = 0;381         }382     }383     while(count);384     if(write_record(SREC3_END)) /* write the final record */385         return (-1);386     return(0);387 }388 389 static int390 write_record (char *buf)391 {392     char c;393 394     while((c = *buf++))395         putc(c);396 397     /* Check for the console hangup (if any different from serial) */398 399     if (ctrlc()) {400         return (-1);401     }402     return (0);403 }404 # endif /* CFG_CMD_SAVES */405 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -