firm_upgrade.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00013 
00014 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
00015  *
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that the following conditions are met:
00018  *
00019  * 1. Redistributions of source code must retain the above copyright notice,
00020  * this list of conditions and the following disclaimer.
00021  *
00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
00023  * this list of conditions and the following disclaimer in the documentation
00024  * and/or other materials provided with the distribution.
00025  *
00026  * 3. The name of ATMEL may not be used to endorse or promote products derived
00027  * from this software without specific prior written permission.
00028  *
00029  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00030  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00031  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00032  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00033  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00034  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00035  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00036  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00037  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00038  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00039  */
00040 
00041 //_____  I N C L U D E S ___________________________________________________
00042 
00043 #include "config.h"
00044 #include "conf_usb.h"
00045 
00046 #ifndef HOST_UPGRADE_MODE
00047 #  warning HOST_UPGRADE_MODE not defined as ENABLE or DISABLE, using DISABLE...
00048 #  define HOST_UPGRADE_MODE  DISABLE
00049 #endif
00050 
00051 // File system includes required for SYNC mode
00052 #if (HOST_UPGRADE_MODE==ENABLE)
00053 
00054 #  ifndef __ICCAVR__
00055 #  error HOST_UPGRADE_MODE feature run only under IAR
00056 #  endif
00057 
00058 #include "modules/file_system/fat.h"
00059 #include "modules/file_system/fs_com.h"
00060 #include "modules/file_system/navigation.h"
00061 #include "modules/file_system/file.h"
00062 #include "modules/file_system/nav_utils.h"
00063 #include "lib_mcu/flash/flash_lib.h"
00064 #include "stdio.h"
00065 #include "string.h"
00066 
00067 //_____ M A C R O S ________________________________________________________
00068  
00069 // Maximum of data by line in HEX file
00070 #define  MAX_DATA_LINE        16
00071 
00072 // Define the upgrade zone autorized
00073 #define  UPGRADE_SIZE_MAX     50
00074 #define  UPGRADE_ADDR         0x333    
00075    
00076 
00077 //_____ D E C L A R A T I O N S ____________________________________________
00078 
00079 // This array allocs a space in flash (=code)
00080 // which will upgraded by the feature "USB host bootloader with Udisk"
00081 code char msg_to_upgrade[UPGRADE_SIZE_MAX] At(UPGRADE_ADDR);
00082 
00083 // Struct used to decode HEX file
00084 typedef struct
00085 {
00086    U8      u8_nb_data;  // Nb data included in line
00087    U16     u16_add;     // Address to store data
00088    U8      u8_type;     // Type of line
00089    U8*     datas;       // Datas included in line
00090 }  St_hex_line;
00091      
00092   
00093 // Internal routines used to upgrade firmware
00094 static   void  firm_upgrade_displayzone   ( void );
00095 static   void  firm_upgrade_status        ( char *status );
00096 static   Bool  firm_upgrade_searchfile    ( const char* filename );
00097 static   Bool  firm_upgrade_readhexline   ( St_hex_line* line );
00098 static   U8    firm_upgrade_ascii2bin     ( U8 ascii );
00099 static   U8    firm_upgrade_readbyte      ( void );
00100 
00101 
00108 void firm_upgrade_run( void )
00109 {
00110    Fs_index sav_index;
00111    U8 u8_i, save_int;
00112    St_hex_line hex_line;
00113    U8 datas[MAX_DATA_LINE];
00114    char filename[30];
00115 
00116    hex_line.datas    = datas; // Init data buffer used
00117    hex_line.u8_type  = 0;     // Autotrize only type 0
00118 
00119    // Save current position to resolve it before exit routine
00120    sav_index = nav_getindex();
00121    
00122    printf("\n\rDislpay upgrade zone BEFORE upgrade:\n\r");
00123    firm_upgrade_displayzone();
00124 
00125    printf("Search upgrade file\n\r...\r");
00126    if( !firm_upgrade_searchfile( "upgrade*" ) )
00127    {
00128       firm_upgrade_status("No upgrade file");
00129       nav_gotoindex(&sav_index);
00130       return;
00131    }
00132    
00133    nav_file_getname( filename, 50 );
00134    printf("Open upgrade file \"%s\"\n\r...\r", filename );
00135    if( !file_open(FOPEN_MODE_R) )
00136    {
00137       firm_upgrade_status("!! Error to open upgrade file");
00138       nav_gotoindex(&sav_index);       // Restore previous position
00139       return;
00140    }
00141    
00142    printf("Check upgrade file\n\r...\r");
00143    while (!file_eof())
00144    { 
00145       // For each text line, check upgrade zone
00146       hex_line.u8_nb_data = MAX_DATA_LINE;
00147       if( !firm_upgrade_readhexline( &hex_line ) )
00148       {
00149          file_close();
00150          firm_upgrade_status("!! Error in HEX file format");
00151          nav_gotoindex(&sav_index);
00152          return;
00153       }
00154 
00155       if( (hex_line.u16_add                      <  UPGRADE_ADDR)
00156       ||  (hex_line.u16_add+hex_line.u8_nb_data) > (UPGRADE_ADDR+UPGRADE_SIZE_MAX) )
00157       {
00158          file_close();
00159          firm_upgrade_status("!! Upgrade zone not autorized");
00160          nav_gotoindex(&sav_index);
00161          return;
00162       }
00163    }
00164    
00165    printf("Program FLASH\n\r...\r");
00166    // Check bootloader
00167    if( !flash_lib_check() )
00168    {
00169       file_close();
00170       firm_upgrade_status("!! The bootloder if not loaded");
00171       nav_gotoindex(&sav_index);
00172       return;
00173    }
00174    
00175    file_seek(0,FS_SEEK_SET);              // Restart at beginning of file
00176    while (!file_eof())
00177    { 
00178       // For each text line, check upgrade zone
00179       hex_line.u8_nb_data = MAX_DATA_LINE;
00180       if( !firm_upgrade_readhexline( &hex_line ) )
00181       {
00182          file_close();
00183          firm_upgrade_status("!! Error in HEX file format");
00184          nav_gotoindex(&sav_index);
00185          return;
00186       }
00187 
00188       // Disabling the interrupt
00189       save_int=Get_interrupt_state();
00190       Disable_interrupt();
00191       // Writing the flash with a check of highest flash address 
00192       flash_wr_block( hex_line.datas, hex_line.u16_add, hex_line.u8_nb_data );
00193       // Read data in flash and check programmation with buffer
00194       for( u8_i=0; u8_i<hex_line.u8_nb_data; u8_i++ )
00195       {
00196          if( hex_line.datas[u8_i] != flash_rd_byte((U8 farcode*)hex_line.u16_add) )
00197          {
00198             file_close();
00199             firm_upgrade_status("!! Programmation in flash BAD\n\r!!! Check if the bootloader is loaded in chip.");
00200             nav_gotoindex(&sav_index);
00201             return;
00202          }
00203          hex_line.u16_add++;
00204       }     
00205       // Restore interrupt state
00206       if(save_int) { Enable_interrupt(); }
00207    }
00208 
00209    file_close();
00210    firm_upgrade_status("Upgrade successfull");
00211    nav_gotoindex(&sav_index);
00212    
00213    printf("Dislpay upgrade zone AFTER upgrade:\n\r");
00214    firm_upgrade_displayzone();
00215 }
00216 
00217 
00220 static   void firm_upgrade_displayzone( void )
00221 {
00222    char ram_msg_upgrade[UPGRADE_SIZE_MAX+1];
00223 
00224    // Move data from FLASH to RAM, because printf don't support flash
00225    for( U8 u8_i=0; u8_i<UPGRADE_SIZE_MAX; u8_i++ )
00226    {
00227      ram_msg_upgrade[u8_i] = msg_to_upgrade[u8_i];
00228    }
00229    ram_msg_upgrade[UPGRADE_SIZE_MAX]=0;   // Add terminator in case of
00230    printf( "\"" );
00231    printf( ram_msg_upgrade );
00232    printf( "\"\r\n" );
00233 } 
00234    
00235 
00242 static   Bool firm_upgrade_searchfile( const char* filename )
00243 {  
00244    U8 u8_drive_lun;
00245 
00246    //** Search "Hello.txt" file in all USB-Disk
00247    u8_drive_lun = 1; // 1 is USB lun in this demo (0 = DataFlash, 1 = USB Host)
00248    while( 1 )
00249    {
00250       if( u8_drive_lun >= nav_drive_nb() )
00251          return FALSE;
00252       // Mount USB disk
00253       nav_drive_set( u8_drive_lun );
00254       if( nav_partition_mount() )
00255       {
00256          // Mount OK then seacrh file
00257          if( nav_setcwd((FS_STRING)filename,TRUE,FALSE) )
00258             break;   // File Found
00259       }
00260       u8_drive_lun++;   // Go to next USB disk
00261    }
00262    return TRUE;
00263 }
00264 
00265 
00274 static   Bool firm_upgrade_readhexline( St_hex_line* line )
00275 {  
00276    U8 u8_i, u8_nb_data, u8_crc=0;
00277    U8 *ptr_data;
00278    
00279    // Check header line
00280    if( ':' != file_getc())
00281       return FALSE;
00282    
00283    // Get data size
00284    u8_nb_data = firm_upgrade_readbyte();
00285    u8_crc += u8_nb_data;
00286    if( u8_nb_data > line->u8_nb_data )
00287       return FALSE;
00288    line->u8_nb_data = u8_nb_data;
00289    
00290    // Get data address 
00291    line->u16_add = (((U16)firm_upgrade_readbyte())<<8) | firm_upgrade_readbyte();
00292    u8_crc += LSB(line->u16_add);
00293    u8_crc += MSB(line->u16_add);
00294    
00295    // Read record type
00296    // - 00, data record, contains data and 16-bit address. The format described above. 
00297    // - 01, End Of File record, a file termination record. No data. Has to be the last line of the file, only one per file permitted. Usually ':00000001FF'. Originally the End Of File record could contain a start address for the program being loaded, e.g. :00AB2F0125 would make a jump to address AB2F. This was convenient when programs were loaded from punched paper tape. 
00298    // - 02, Extended Segment Address Record, segment-base address. Used when 16 bits are not enough, identical to 80x86 real mode addressing. The address specified by the 02 record is multiplied by 16 (shifted 4 bits left) and added to the subsequent 00 record addresses. This allows addressing of up to a megabyte of address space. The address field of this record has to be 0000, the byte count is 02 (the segment is 16-bit). The least significant hex digit of the segment address is always 0. 
00299    // - 03, Start Segment Address Record. For 80x86 processors, it specifies the initial content of the CS:IP registers. The address field is 0000, the byte count is 04, the first two bytes are the CS value, the latter two are the IP value. 
00300    // - 04, Extended Linear Address Record, allowing for fully 32 bit addressing. The address field is 0000, the byte count is 02. The two data bytes represent the upper 16 bits of the 32 bit address, when combined with the address of the 00 type record. 
00301    // - 05, Start Linear Address Record. The address field is 0000, the byte count is 04. The 4 data bytes represent the 32-bit value loaded into the EIP register of the 80386 and higher CPU.
00302    line->u8_type = firm_upgrade_readbyte();
00303    u8_crc += line->u8_type;
00304    
00305    // Get data
00306    ptr_data = line->datas;
00307    for( u8_i=0; u8_i<u8_nb_data; u8_i++ )
00308    {
00309       *ptr_data = firm_upgrade_readbyte();
00310       u8_crc += *ptr_data;
00311       ptr_data++;
00312    }
00313    
00314    // Check CRC
00315    // If the checksum is correct, adding all the bytes (the Byte count, both bytes in Address, the Record type, each Data byte and the Checksum)
00316    // together will always result in a value wherein the least significant byte is zero (0x00). 
00317    u8_crc += firm_upgrade_readbyte();
00318    
00319    // Read end of line = '\r' and '\n'
00320    file_getc();file_getc();
00321    
00322    return( 0 == u8_crc );
00323 }
00324 
00325       
00330 static   void firm_upgrade_status( char *status )
00331 {
00332    char file_status_name[] = "status.txt";
00333 
00334    printf( status );
00335    printf( "\n\r" );
00336    
00337    // Create a status file if possible
00338    if( !nav_file_create((FS_STRING)file_status_name) )
00339    {
00340       if( fs_g_status != FS_ERR_FILE_EXIST )
00341          return; // Error during creation file
00342       // File exist then continue
00343    }
00344    if( file_open(FOPEN_MODE_W) )
00345    {
00346       // Write status in file
00347       file_write_buf( (unsigned char*) status, strlen(status) );
00348       file_close();
00349    }
00350 }
00351 
00352 
00360 static   U8 firm_upgrade_ascii2bin(U8 ascii)
00361 {
00362    U8 byte=0;
00363    if( ('0'<=ascii) && (ascii<='9') )
00364       byte = ascii-'0';
00365    if( ('a'<=ascii) && (ascii<='f') )
00366       byte = (ascii-'a'+10);
00367    if( ('A'<=ascii) && (ascii<='F') )
00368       byte = (ascii-'A'+10);
00369    return byte;
00370 }
00371 
00377 static   U8 firm_upgrade_readbyte( void )
00378 {
00379    U8 ascii_msb ,ascii_lsb;
00380    ascii_msb = file_getc();
00381    ascii_lsb = file_getc();
00382    return (firm_upgrade_ascii2bin(ascii_msb)<<4) | firm_upgrade_ascii2bin(ascii_lsb);
00383 }
00384 
00385 #endif // (HOST_UPGRADE_MODE==ENABLE)
00386 

Generated on Fri May 15 15:41:36 2009 for ATMEL by  doxygen 1.5.3