firm_upgrade.c File Reference

#include "config.h"
#include "conf_usb.h"
#include "modules/file_system/fat.h"
#include "modules/file_system/fs_com.h"
#include "modules/file_system/navigation.h"
#include "modules/file_system/file.h"
#include "modules/file_system/nav_utils.h"
#include "lib_mcu/flash/flash_lib.h"
#include "stdio.h"
#include "string.h"

Include dependency graph for firm_upgrade.c:

Go to the source code of this file.

Data Structures

struct  St_hex_line

Defines

#define HOST_UPGRADE_MODE   DISABLE
#define MAX_DATA_LINE   16
#define UPGRADE_SIZE_MAX   50
#define UPGRADE_ADDR   0x333

Functions

code char
msg_to_upgrade[50] 
At (0x333)
static void firm_upgrade_displayzone (void)
 Displays on UART the space used to upgrade firmware.
static void firm_upgrade_status (char *status)
 This function creates a file on disk with the status of upgrade.
static Bool firm_upgrade_searchfile (const char *filename)
 Searchs a HEX file in the U-Disks.
static Bool firm_upgrade_readhexline (St_hex_line *line)
 Reads and decodes a text line with HEX format.
static U8 firm_upgrade_ascii2bin (U8 ascii)
 This function is used to convert a ascii character into 4 bit number '5' => 5 'A' => 10.
static U8 firm_upgrade_readbyte (void)
 This function reads and converts two ascii characters into byte number '51' => 0x51 'A1' => 0xA1.
void firm_upgrade_run (void)
 This function runs the upgrade process.


Detailed Description

This file contains the feature USB host bootloader with Udisk (see AppNote AVR916).

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file firm_upgrade.c.


Define Documentation

#define HOST_UPGRADE_MODE   DISABLE

Definition at line 51 of file firm_upgrade.c.

#define MAX_DATA_LINE   16

Definition at line 73 of file firm_upgrade.c.

Referenced by firm_upgrade_run().

#define UPGRADE_SIZE_MAX   50

Definition at line 76 of file firm_upgrade.c.

Referenced by firm_upgrade_displayzone(), and firm_upgrade_run().

#define UPGRADE_ADDR   0x333

Definition at line 77 of file firm_upgrade.c.

Referenced by firm_upgrade_run().


Function Documentation

code char msg_to_upgrade [ 50 ] At ( 0x333   ) 

static void firm_upgrade_displayzone ( void   )  [static]

Displays on UART the space used to upgrade firmware.

Definition at line 223 of file firm_upgrade.c.

References UPGRADE_SIZE_MAX.

Referenced by firm_upgrade_run().

00224 {
00225    char ram_msg_upgrade[UPGRADE_SIZE_MAX+1];
00226 
00227    // Move data from FLASH to RAM, because printf don't support flash
00228    for( U8 u8_i=0; u8_i<UPGRADE_SIZE_MAX; u8_i++ )
00229    {
00230      ram_msg_upgrade[u8_i] = msg_to_upgrade[u8_i];
00231    }
00232    ram_msg_upgrade[UPGRADE_SIZE_MAX]=0;   // Add terminator in case of
00233    printf( "\"" );
00234    printf( ram_msg_upgrade );
00235    printf( "\"\r\n" );
00236 } 

Here is the caller graph for this function:

static void firm_upgrade_status ( char *  status  )  [static]

This function creates a file on disk with the status of upgrade.

Parameters:
status to write

Definition at line 333 of file firm_upgrade.c.

References file_close(), file_open(), file_write_buf(), FOPEN_MODE_W, FS_ERR_FILE_EXIST, fs_g_status, and nav_file_create().

Referenced by firm_upgrade_run().

00334 {
00335    char file_status_name[] = "status.txt";
00336 
00337    printf( status );
00338    printf( "\n\r" );
00339    
00340    // Create a status file if possible
00341    if( !nav_file_create((FS_STRING)file_status_name) )
00342    {
00343       if( fs_g_status != FS_ERR_FILE_EXIST )
00344          return; // Error during creation file
00345       // File exist then continue
00346    }
00347    if( file_open(FOPEN_MODE_W) )
00348    {
00349       // Write status in file
00350       file_write_buf( (unsigned char*) status, strlen(status) );
00351       file_close();
00352    }
00353 }

Here is the call graph for this function:

Here is the caller graph for this function:

static Bool firm_upgrade_searchfile ( const char *  filename  )  [static]

Searchs a HEX file in the U-Disks.

Parameters:
file name to search
Returns:
TRUE, if file found

Definition at line 245 of file firm_upgrade.c.

References FALSE, nav_drive_nb(), nav_drive_set(), nav_partition_mount(), nav_setcwd(), and TRUE.

Referenced by firm_upgrade_run().

00246 {  
00247    U8 u8_drive_lun;
00248 
00249    //** Search "Hello.txt" file in all USB-Disk
00250    u8_drive_lun = 1; // 1 is USB lun in this demo (0 = DataFlash, 1 = USB Host)
00251    while( 1 )
00252    {
00253       if( u8_drive_lun >= nav_drive_nb() )
00254          return FALSE;
00255       // Mount USB disk
00256       nav_drive_set( u8_drive_lun );
00257       if( nav_partition_mount() )
00258       {
00259          // Mount OK then seacrh file
00260          if( nav_setcwd((FS_STRING)filename,TRUE,FALSE) )
00261             break;   // File Found
00262       }
00263       u8_drive_lun++;   // Go to next USB disk
00264    }
00265    return TRUE;
00266 }

Here is the call graph for this function:

Here is the caller graph for this function:

static Bool firm_upgrade_readhexline ( St_hex_line line  )  [static]

Reads and decodes a text line with HEX format.

Parameters:
line Specify in struct:
  • u8_nb_data, number max. of data supported
  • datas, init. buffer to fill
Returns:
TRUE, if line supported and line struct filled

Definition at line 277 of file firm_upgrade.c.

References St_hex_line::datas, FALSE, file_getc(), firm_upgrade_readbyte(), LSB, MSB, St_hex_line::u16_add, St_hex_line::u8_nb_data, and St_hex_line::u8_type.

Referenced by firm_upgrade_run().

00278 {  
00279    U8 u8_i, u8_nb_data, u8_crc=0;
00280    U8 *ptr_data;
00281    
00282    // Check header line
00283    if( ':' != file_getc())
00284       return FALSE;
00285    
00286    // Get data size
00287    u8_nb_data = firm_upgrade_readbyte();
00288    u8_crc += u8_nb_data;
00289    if( u8_nb_data > line->u8_nb_data )
00290       return FALSE;
00291    line->u8_nb_data = u8_nb_data;
00292    
00293    // Get data address 
00294    line->u16_add = (((U16)firm_upgrade_readbyte())<<8) | firm_upgrade_readbyte();
00295    u8_crc += LSB(line->u16_add);
00296    u8_crc += MSB(line->u16_add);
00297    
00298    // Read record type
00299    // - 00, data record, contains data and 16-bit address. The format described above. 
00300    // - 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. 
00301    // - 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. 
00302    // - 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. 
00303    // - 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. 
00304    // - 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.
00305    line->u8_type = firm_upgrade_readbyte();
00306    u8_crc += line->u8_type;
00307    
00308    // Get data
00309    ptr_data = line->datas;
00310    for( u8_i=0; u8_i<u8_nb_data; u8_i++ )
00311    {
00312       *ptr_data = firm_upgrade_readbyte();
00313       u8_crc += *ptr_data;
00314       ptr_data++;
00315    }
00316    
00317    // Check CRC
00318    // 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)
00319    // together will always result in a value wherein the least significant byte is zero (0x00). 
00320    u8_crc += firm_upgrade_readbyte();
00321    
00322    // Read end of line = '\r' and '\n'
00323    file_getc();file_getc();
00324    
00325    return( 0 == u8_crc );
00326 }

Here is the call graph for this function:

Here is the caller graph for this function:

static U8 firm_upgrade_ascii2bin ( U8  ascii  )  [static]

This function is used to convert a ascii character into 4 bit number '5' => 5 'A' => 10.

Parameters:
ASCII characters to convert
Returns:
converted byte

Definition at line 363 of file firm_upgrade.c.

Referenced by firm_upgrade_readbyte().

00364 {
00365    U8 byte=0;
00366    if( ('0'<=ascii) && (ascii<='9') )
00367       byte = ascii-'0';
00368    if( ('a'<=ascii) && (ascii<='f') )
00369       byte = (ascii-'a'+10);
00370    if( ('A'<=ascii) && (ascii<='F') )
00371       byte = (ascii-'A'+10);
00372    return byte;
00373 }

Here is the caller graph for this function:

static U8 firm_upgrade_readbyte ( void   )  [static]

This function reads and converts two ascii characters into byte number '51' => 0x51 'A1' => 0xA1.

Returns:
converted byte

Definition at line 380 of file firm_upgrade.c.

References file_getc(), and firm_upgrade_ascii2bin().

Referenced by firm_upgrade_readhexline().

00381 {
00382    U8 ascii_msb ,ascii_lsb;
00383    ascii_msb = file_getc();
00384    ascii_lsb = file_getc();
00385    return (firm_upgrade_ascii2bin(ascii_msb)<<4) | firm_upgrade_ascii2bin(ascii_lsb);
00386 }

Here is the call graph for this function:

Here is the caller graph for this function:

void firm_upgrade_run ( void   ) 

This function runs the upgrade process.

//! The status of process is display on UART and writed in a status file on U-Disk.
//! 

Definition at line 111 of file firm_upgrade.c.

Referenced by host_ms_task().

00112 {
00113    Fs_index sav_index;
00114    U8 u8_i, save_int;
00115    St_hex_line hex_line;
00116    U8 datas[MAX_DATA_LINE];
00117    char filename[30];
00118 
00119    hex_line.datas    = datas; // Init data buffer used
00120    hex_line.u8_type  = 0;     // Autotrize only type 0
00121 
00122    // Save current position to resolve it before exit routine
00123    sav_index = nav_getindex();
00124    
00125    printf("\n\rDislpay upgrade zone BEFORE upgrade:\n\r");
00126    firm_upgrade_displayzone();
00127 
00128    printf("Search upgrade file\n\r...\r");
00129    if( !firm_upgrade_searchfile( "upgrade*" ) )
00130    {
00131       firm_upgrade_status("No upgrade file");
00132       nav_gotoindex(&sav_index);
00133       return;
00134    }
00135    
00136    nav_file_getname( filename, 50 );
00137    printf("Open upgrade file \"%s\"\n\r...\r", filename );
00138    if( !file_open(FOPEN_MODE_R) )
00139    {
00140       firm_upgrade_status("!! Error to open upgrade file");
00141       nav_gotoindex(&sav_index);       // Restore previous position
00142       return;
00143    }
00144    
00145    printf("Check upgrade file\n\r...\r");
00146    while (!file_eof())
00147    { 
00148       // For each text line, check upgrade zone
00149       hex_line.u8_nb_data = MAX_DATA_LINE;
00150       if( !firm_upgrade_readhexline( &hex_line ) )
00151       {
00152          file_close();
00153          firm_upgrade_status("!! Error in HEX file format");
00154          nav_gotoindex(&sav_index);
00155          return;
00156       }
00157 
00158       if( (hex_line.u16_add                      <  UPGRADE_ADDR)
00159       ||  (hex_line.u16_add+hex_line.u8_nb_data) > (UPGRADE_ADDR+UPGRADE_SIZE_MAX) )
00160       {
00161          file_close();
00162          firm_upgrade_status("!! Upgrade zone not autorized");
00163          nav_gotoindex(&sav_index);
00164          return;
00165       }
00166    }
00167    
00168    printf("Program FLASH\n\r...\r");
00169    // Check bootloader
00170    if( !flash_lib_check() )
00171    {
00172       file_close();
00173       firm_upgrade_status("!! The bootloder if not loaded");
00174       nav_gotoindex(&sav_index);
00175       return;
00176    }
00177    
00178    file_seek(0,FS_SEEK_SET);              // Restart at beginning of file
00179    while (!file_eof())
00180    { 
00181       // For each text line, check upgrade zone
00182       hex_line.u8_nb_data = MAX_DATA_LINE;
00183       if( !firm_upgrade_readhexline( &hex_line ) )
00184       {
00185          file_close();
00186          firm_upgrade_status("!! Error in HEX file format");
00187          nav_gotoindex(&sav_index);
00188          return;
00189       }
00190 
00191       // Disabling the interrupt
00192       save_int=Get_interrupt_state();
00193       Disable_interrupt();
00194       // Writing the flash with a check of highest flash address 
00195       flash_wr_block( hex_line.datas, hex_line.u16_add, hex_line.u8_nb_data );
00196       // Read data in flash and check programmation with buffer
00197       for( u8_i=0; u8_i<hex_line.u8_nb_data; u8_i++ )
00198       {
00199          if( hex_line.datas[u8_i] != flash_rd_byte((U8 farcode*)hex_line.u16_add) )
00200          {
00201             file_close();
00202             firm_upgrade_status("!! Programmation in flash BAD\n\r!!! Check if the bootloader is loaded in chip.");
00203             nav_gotoindex(&sav_index);
00204             return;
00205          }
00206          hex_line.u16_add++;
00207       }     
00208       // Restore interrupt state
00209       if(save_int) { Enable_interrupt(); }
00210    }
00211 
00212    file_close();
00213    firm_upgrade_status("Upgrade successfull");
00214    nav_gotoindex(&sav_index);
00215    
00216    printf("Dislpay upgrade zone AFTER upgrade:\n\r");
00217    firm_upgrade_displayzone();
00218 }

Here is the caller graph for this function:


Generated on Wed Sep 23 09:37:14 2009 for ATMEL by  doxygen 1.5.3