ATMEL: host_dfu_task.c Source File

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

# host_dfu_task.c

Go to the documentation of this file.

    00001 /*This file is prepared for Doxygen automatic documentation generation.*/
    00013
    00014 /* Copyright (c) 2009 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  * 4. This software may only be redistributed and used in connection with an Atmel
    00030  * AVR product.
    00031  *
    00032  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
    00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00034  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00042  */
    00043
    00044 //_____  I N C L U D E S ___________________________________________________
    00045
    00046 #include "config.h"
    00047 #include "conf_usb.h"
    00048
    00049 #include "modules/file_system/fat.h"
    00050 #include "modules/file_system/fs_com.h"
    00051 #include "modules/file_system/navigation.h"
    00052 #include "modules/file_system/file.h"
    00053 #include "modules/file_system/nav_utils.h"
    00054
    00055 #include "host_dfu_task.h"
    00056 #include "modules/usb/host_chap9/usb_host_task.h"
    00057 #include "modules/usb/host_chap9/usb_host_enum.h"
    00058 #include "lib_mcu/usb/usb_drv.h"
    00059 #include "lib_mcu/flash/flash.h"
    00060
    00061
    00062 //_____ M A C R O S ________________________________________________________
    00063
    00064
    00065 #ifndef LOG_STR_CODE
    00066 #define LOG_STR_CODE(str)
    00067 #else
    00068 U8 code log_dfu_connect[]="DFU Connected";
    00069 #endif
    00070
    00071 //_____ D E C L A R A T I O N S ____________________________________________
    00072
    00073
    00074 U8  dfu_connected=0;
    00075
    00076 static   U8 buf[MAX_DATA_PER_RECORD];
    00077 static   U8 prog_buf[MAX_DATA_PER_RECORD+FLASH_PAGE_SIZE];
    00078 static   U8 check_buf[MAX_DATA_PER_RECORD+FLASH_PAGE_SIZE];
    00079 static   U8 dfu_status;
    00080
    00081 static   U16 end_addr;
    00082 static   U16 start_addr;
    00083 static   U8 pgm_index=0;
    00084 static   U8 pgm_nb_data=0;
    00085
    00086
    00087 U8 code firmware_name[]=FIRMWARE_NAME;
    00088
    00095 void host_dfu_task_init(void)
    00096 {
    00097    Joy_init();
    00098    Leds_init();
    00099    dfu_connected=0;
    00100 }
    00101
    00108 void host_dfu_task(void)
    00109 {
    00110    if(Is_host_ready())    //Enumeration successfull, device is operationnal
    00111    {
    00112       if(Is_new_device_connection_event())        //New device connected and enumerated...
    00113       {
    00114          // Check host is connected to ATMEL bootloader
    00115          if(Get_VID()==ATMEL_VID && Get_PID()==AT90DFU_PID)
    00116          {
    00117             LOG_STR_CODE(log_dfu_connect);
    00118             dfu_connected=1;
    00119             Led2_on();
    00120          }
    00121          else
    00122          {
    00123             dfu_connected=0;
    00124          }
    00125       }
    00126       if(dfu_connected)
    00127       {
    00128          if(Is_joy_up()||Is_joy_left())
    00129          {
    00130             nav_reset();
    00131             nav_drive_set(0);
    00132             if(nav_partition_mount())
    00133             {
    00134                if(goto_code_name((U8 code *)firmware_name,FALSE,FALSE))
    00135                {
    00136                   Led0_on();
    00137                   Dfu_erase();
    00138                   Led0_off();
    00139                   dfu_load_hex();
    00140                }
    00141             }
    00142          }
    00143       }
    00144    }
    00145
    00146    //Device disconnection...
    00147    if(Is_device_disconnection_event())
    00148    {
    00149       dfu_connected=0;
    00150       Led2_off();
    00151    }
    00152 }
    00153
    00160 U8 dfu_load_hex(void)
    00161 {
    00162    U8 record_type;
    00163    U16 addr;
    00164    U8 nb_data;
    00165    U8 i;
    00166    U8 stop=0;
    00167
    00168    dfu_status=TRUE;
    00169    file_open(FOPEN_MODE_R); // Open hex firmware file
    00170    while (file_eof()==FALSE)
    00171    {
    00172       i=file_getc();
    00173       while(i!=RECORD_MARK)
    00174       {
    00175          i=file_getc();
    00176          if(file_eof())
    00177          {
    00178             stop=1;
    00179             break;
    00180          }
    00181       }
    00182       if(stop) break;
    00183       // Build the hex record information from file
    00184       nb_data=ascii_to_bin(file_getc());
    00185       nb_data=nb_data<<4;
    00186       nb_data+=ascii_to_bin(file_getc());
    00187       addr=ascii_to_bin(file_getc());
    00188       addr=addr<<4;
    00189       addr+=ascii_to_bin(file_getc());
    00190       addr=addr<<4;
    00191       addr+=ascii_to_bin(file_getc());
    00192       addr=addr<<4;
    00193       addr+=ascii_to_bin(file_getc());
    00194       record_type=ascii_to_bin(file_getc());
    00195       record_type=record_type<<4;
    00196       record_type+=ascii_to_bin(file_getc());
    00197       for(i=0;i<nb_data;i++)
    00198       {
    00199          buf[i]=ascii_to_bin(file_getc());
    00200          buf[i]=buf[i]<<4;
    00201          buf[i]+=ascii_to_bin(file_getc());
    00202       }
    00203       // Decode record type
    00204       switch(record_type)
    00205       {
    00206          case DATA_RECORD:
    00207             if(addr!=end_addr+1 && pgm_index!=0) //None consecutive addr, first flush previous buffer
    00208             {
    00209                dfu_flush_prog();
    00210             }
    00211             // Add new data to prog buffer
    00212             for(i=0;i<nb_data;i++)
    00213             {
    00214                prog_buf[pgm_index]=buf[i];
    00215                pgm_index++;
    00216             }
    00217             // Update nb of data to load
    00218             pgm_nb_data+=nb_data;
    00219             // Compute last byte add to load
    00220             if(pgm_nb_data>nb_data)
    00221             {  // Data exist in buffer
    00222                end_addr=end_addr+nb_data;
    00223             }
    00224             else // first load
    00225             {
    00226                end_addr=addr+nb_data-1;
    00227                start_addr=addr;
    00228             }
    00229             //If enough data flush prog buffer
    00230             if(pgm_index>=10*MAX_DATA_PER_RECORD)
    00231             {
    00232                dfu_flush_prog();
    00233             }
    00234             break;
    00235          case PAGE_RECORD:
    00236             if(pgm_index) // Prog buffer not empty ?
    00237             {
    00238                dfu_flush_prog();  // Then flush it
    00239             }
    00240             Dfu_set_page(buf[1]); // Send page change frame
    00241          default:  //Ignore all other record types
    00242             break;
    00243       }
    00244    }
    00245    // Remaining data in buffer before quit?
    00246    if(pgm_index>0)
    00247    {
    00248       dfu_flush_prog();
    00249    }
    00250    file_close();
    00251    Led0_off();
    00252    return dfu_status;
    00253 }
    00254
    00263 void dfu_prog(U16 start,U16 end,U8 *buf)
    00264 {
    00265    U8 i;
    00266    U16 j;
    00267    U8 padding;
    00268
    00269    data_stage[0]=0x01;
    00270    data_stage[1]=0;
    00271    data_stage[2]=MSB(start);
    00272    data_stage[3]=LSB(start);
    00273    data_stage[4]=MSB(end);
    00274    data_stage[5]=LSB(end);
    00275    for(i=6;i<32;i++)
    00276    {
    00277       data_stage[i]=0;
    00278    }
    00279    padding=start%32;
    00280    j=padding;
    00281    while(j)
    00282    {
    00283       data_stage[i]=0x00;
    00284       i++; j--;
    00285    }
    00286    j=end-start+1;
    00287    while(j)
    00288    {
    00289       data_stage[i]=*buf;
    00290       buf++;
    00291       j--;i++;
    00292    }
    00293    Dfu_download(32+end-start+1+padding);
    00294 }
    00295
    00296 void dfu_read(U16 start,U16 end,U8 *buf)
    00297 {
    00298    U16 j;
    00299    U16 i;
    00300
    00301    data_stage[0]=0x03;
    00302    data_stage[1]=0;
    00303    data_stage[2]=MSB(start);
    00304    data_stage[3]=LSB(start);
    00305    data_stage[4]=MSB(end);
    00306    data_stage[5]=LSB(end);
    00307    Dfu_download(6);
    00308    i=end-start+1;
    00309    Dfu_upload(i);
    00310    for(j=0;j<i;j++)
    00311    {
    00312       *buf=data_stage[j];
    00313       buf++;
    00314    }
    00315 }
    00316
    00317 void dfu_flush_prog(void)
    00318 {
    00319    U8 i;
    00320    // All buffer in the same flash memory page ?
    00321    if( MSB(start_addr)== MSB(end_addr))
    00322    {
    00323       dfu_prog(start_addr,end_addr,prog_buf);
    00324    }
    00325    else // No, program in two times
    00326    {
    00327       i=(end_addr%FLASH_PAGE_SIZE);
    00328       dfu_prog(start_addr,end_addr-i-1,prog_buf);
    00329       dfu_prog(end_addr-i,end_addr,&prog_buf[pgm_nb_data-i-1]);
    00330    }
    00331    // Verify on the fly...
    00332    dfu_read(start_addr,end_addr,check_buf);
    00333    for(i=0;i<pgm_nb_data;i++)
    00334    {
    00335       if(prog_buf[i]!=check_buf[i])
    00336       {
    00337          Leds_on();
    00338          dfu_status=FALSE;
    00339       }
    00340    }
    00341    Led0_toggle();
    00342    pgm_index=0;
    00343    pgm_nb_data=0;
    00344 }
    00345
    00346 U8 ascii_to_bin (U8 b)
    00347 {
    00348 b|='a'-'A'; // to_lower: '0'=>'0', 'A'=>'a', 'a'=>'a'
    00349 return ( (b <= '9') ? (b-'0') : (b+10-'a') );
    00350 }
    00351