- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# 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).

- Compiler: IAR EWAVR and GNU GCC for AVR
- Supported devices: AT90USB1287, AT90USB1286, AT90USB647, AT90USB646

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 48 of file firm_upgrade.c.

#define MAX_DATA_LINE 16

Definition at line 70 of file firm_upgrade.c.

Referenced by firm_upgrade_run().

#define UPGRADE_SIZE_MAX 50

Definition at line 73 of file firm_upgrade.c.

Referenced by firm_upgrade_displayzone(), and firm_upgrade_run().

#define UPGRADE_ADDR 0x333

Definition at line 74 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 220 of file firm_upgrade.c.

References UPGRADE_SIZE_MAX.

Referenced by firm_upgrade_run().

    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 }

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 330 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().

    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 }

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 242 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().

    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 }

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 274 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().

    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 }

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 360 of file firm_upgrade.c.

Referenced by firm_upgrade_readbyte().

    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 }

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 377 of file firm_upgrade.c.

References file_getc(), and firm_upgrade_ascii2bin().

Referenced by firm_upgrade_readhexline().

    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 }

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 108 of file firm_upgrade.c.

Referenced by host_ms_task().

    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 }

Here is the caller graph for this function: