www.pudn.com > SMSC USB2.0.zip > upgrade.c


/*============================================================================ 
  ____________________________________________________________________________ 
                                ______________________________________________ 
   SSSS  M   M          CCCC          Standard Microsystems Corporation 
  S      MM MM   SSSS  C                    Austin Design Center 
   SSS   M M M  S      C                 11000 N. Mopac Expressway 
      S  M   M   SSS   C                Stonelake Bldg. 6, Suite 500 
  SSSS   M   M      S   CCCC                Austin, Texas 78759 
                SSSS            ______________________________________________ 
  ____________________________________________________________________________ 
 
  Copyright(C) 1999, Standard Microsystems Corporation 
  All Rights Reserved. 
 
  This program code listing is proprietary to SMSC and may not be copied, 
  distributed, or used without a license to do so.  Such license may have 
  Limited or Restricted Rights. Please refer to the license for further 
  clarification. 
  ____________________________________________________________________________ 
 
  Notice: The program contained in this listing is a proprietary trade 
  secret of SMSC, Hauppauge, New York, and is copyrighted 
  under the United States Copyright Act of 1976 as an unpublished work, 
  pursuant to Section 104 and Section 408 of Title XVII of the United 
  States code. Unauthorized copying, adaption, distribution, use, or 
  display is prohibited by this law. 
  ____________________________________________________________________________ 
 
  Use, duplication, or disclosure by the Government is subject to 
  restrictions as set forth in subparagraph(c)(1)(ii) of the Rights 
  in Technical Data and Computer Software clause at DFARS 52.227-7013. 
  Contractor/Manufacturer is Standard Microsystems Corporation, 
  80 Arkay Drive, Hauppauge, New York, 1178-8847. 
  ____________________________________________________________________________ 
  ____________________________________________________________________________ 
 
   -  
  ____________________________________________________________________________ 
 
  comments tbd 
  ____________________________________________________________________________ 
 
  Revision History 
  Date      Who  Comment 
  ________  ___  _____________________________________________________________ 
  05/31/00  tbh  initial version 
  11/05/01  tbh  eliminate dfu jumper, replaced with PCON.GF0 
  07/09/02  tbh  changed (g_cdm0 <= _dfu_timer.u16) to 
                 (g_cdm0 < _dfu_timer.u16) in dfu_mnger(k_msg_usbrst) 
                 and in dfu_cpex(k_msg_transaction_done) to compensate 
                 for faster enuumeration where the initial reset comes 
                 while g_cdm0 is still zero. 
============================================================================*/ 
#define __manager__ 
#include "..\inc\minimos.h" 
#include "upgrade.h" 
 
//------------------------------------------------------------------------------ 
t_uw16 _dfu_timer; 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   _flash_select_lower_bank 
// 
// Declaration: 
//   void _flash_select_lower_bank(void); 
// 
// Purpose: 
//   Select the lower 64K bank of the 128K flash chip (the DFU loader). 
// 
// Arguments: 
//   None 
// 
// Return: 
//   None 
// 
// Notes: 
//   Only call while executing from RAM. 
// 
// Since: 
//   dfu-1.0 
//------------------------------------------------------------------------------ 
#define _flash_select_lower_bank();                                            \ 
{                                                                              \ 
  _mcu_register_clr_bits(x_gpioa_dir, kbm_gpio6);                              \ 
  _mcu_register_clr_bits(x_gpioa_out, kbm_gpio6);                              \ 
} 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   _flash_execute_from_ram 
// 
// Declaration: 
//   void _flash_execute_from_ram(void); 
// 
// Purpose: 
//   Begin execution from RAM, at the current program counter. 
// 
// Arguments: 
//   None 
// 
// Return: 
//   None 
// 
// Notes: 
//   Be sure to copy the code into RAM before calling. 
// 
// Since: 
//   dfu-1.0 
//------------------------------------------------------------------------------ 
#define _flash_execute_from_ram()  \ 
  _mcu_register_set_bits(x_util_config, kbm_util_config_sram_sw) 
 
//+----------------------------------------------------------------------------- 
// Name: 
//   _flash_execute_from_flash 
// 
// Declaration: 
//   void _flash_execute_from_flash(void); 
// 
// Purpose: 
//   Begin execution from flash, at the current program counter. 
// 
// Arguments: 
//   None 
// 
// Return: 
//   None 
// 
// Notes: 
//   Only call while executing from RAM. 
// 
// Since: 
//   dfu-1.0 
//------------------------------------------------------------------------------ 
#define _flash_execute_from_flash()  \ 
  _mcu_register_clr_bits(x_util_config, kbm_util_config_sram_sw) 
 
//------------------------------------------------------------------------------ 
// Declaration: 
//   static void flash_coerce_dfu(); 
// 
// Purpose: 
//   Forces the DFU loader to execute. 
// 
// Arguments: 
//   None. 
// 
// Return: 
//   None. 
// 
// Note: 
//   This function must be copied to sram at 0x400 and executed from sram because 
//   it changes code banks to the lower 64k.  It is linked elsewhere at some 
//   address not overlapping 0x0400..0x06FF.  It is relocated to 0x0400 on the fly. 
//   Therefore it cannot call any functions, do any jumps (other that the reset), 
//   or depend on the contents of the flash space outside 0x0400..0x06FF. 
// 
// Since: 
//   dfu-1.0 
//------------------------------------------------------------------------------ 
static void flash_coerce_dfu(void) reentrant; 
static void flash_coerce_dfu() reentrant 
{ 
  trace0(0, dfu, 0, "flash_coerce_dfu()"); 
  _flash_select_lower_bank(); 
  _mcu_reboot(); 
} 
 
//------------------------------------------------------------------------------ 
// Declaration: 
//   static void dfu_copy_flash_to_sram(); 
// 
// Purpose: 
//   Copies the flash range flash_coerce_dfu() to flash_coerce_dfu()+100 
//   from code space to xdata space at 0x0400 (into the executable sram) 
//   This relocates the code into the sram (required because the dfu loader 
//   cannot write code from 0x0400..0x06FF, forcing the function to exist 
//   outside the range) so it can be executed there. 
// 
// Arguments: 
//   None. 
// 
// Return: 
//   None. 
// 
// Note: 
//   If an error occurrs then mcu is halted and a diagnostic dumped on the trace fifo. 
// 
// Since: 
//   dfu-1.0 
//------------------------------------------------------------------------------ 
static void dfu_copy_flash_to_sram(void) reentrant; 
static void dfu_copy_flash_to_sram() reentrant 
{ 
  trace0(0, dfu, 0, "dfu_copy_flash_to_sram()"); 
  mcu_begin_critical_section(); 
  // turn the sram back into xdata space 
  _flash_execute_from_flash(); 
  // copy flash_coerce_dfu() into sram 
  memcpy((uint8 xdata *)(0x0400), (uint8 code *)(flash_coerce_dfu), 100); 
  if (memcmp((uint8 xdata *)(0x0400), (uint8 code *)(flash_coerce_dfu), 100)) 
  { 
    trace0(0, dfu, 0, "ERROR: copy failed."); 
    mcu_halt(); 
  } 
  mcu_end_critical_section(); 
} 
 
//------------------------------------------------------------------------------ 
// Declaration: 
//  uint8 dfu_mngr(t_message *msgp); 
// 
// Purpose: 
//  This is the manager for all things related to the dfu interface. 
// 
// Arguments: 
//  None. 
// 
// Return: 
//  k_success 
//  K-error 
// 
// Note: 
//  Do NOT yield from this routine.  It is NOT part of any thread.  It does 
//  not execute in an any thread's context.  Yielding from within this function 
//  will cause your firmware to crash. 
// 
// $$$ the initial version of the sie is made with a maximum of 1 
// interface.  so, dfu must be broken to accept class commands off the 
// runtime interface.  at least until the VCI hooks are implemented in the sie. 
//------------------------------------------------------------------------------ 
t_result dfu_mngr(t_message_ref msgp) reentrant 
{ 
  trace0(0, dfu, 0, "dfu_mngr()"); 
  switch (message_rd_id(msgp)) 
  { 
    case k_msg_usbrst: 
      trace0(0, dfu, 0, "k_msg_usbrst"); 
      // if we are timing the DFU_DETACH request then check to see if time to enter dfu mode... 
      if (g_cdm0 < _dfu_timer.u16) 
      { 
        _dfu_timer.u16 = 0; 
        // load the "relocatable" flash_coerce_dfu() into sram 
        dfu_copy_flash_to_sram(); 
        mcu_begin_critical_section(); 
        // communicate between app and loader via GF0 of PCON register 
        _cpu_register_setbit(PCON, 2); 
        // make sram executable so flash_coerce_dfu() can run from sram 
        _flash_execute_from_ram(); 
        trace0(0, dfu, 0, "dfu_mngr: coerce dfu"); 
        // jump to flash_coerce_dfu() at its new address in sram 
        ((t_code_fragment)0x0400)(); 
      } 
      return k_success; 
 
    default: 
      trace0(0, dfu, 0, "error"); 
      // unexpected message 
      return k_error; 
  } 
  // unexpected message 
  return k_error; 
} 
 
//------------------------------------------------------------------------------ 
// Declaration: 
//  uint8 dfu_cpex(t_message *msgp); 
// 
// Purpose: 
//  Watches for the DFU_DETACH message. 
// 
// Arguments: 
//  None. 
// 
// Return: 
//  k_success - Causes the protocol engine to complete the status stage successfully. 
//  k_error - Causes the protocol engine to stall the control pipe. 
//  k_in_progress - For k_msg_source_payload, causes the protocol engine to deliver 
//   another empty packet buffer to the cpex to be loaded for transmission. 
//   For k_msg_sink_payload, informs the protocol engine that the cpex expects at 
//   least one more payload buffer to be delivered to it by the protocol engine. 
//  k_finished - For k_msg_source_payload and k_msg_sink_payload, informs the 
//   protocol engine that the data phase is complete and no more data is expected 
//   in either direction. 
// 
// Note: 
//  Do NOT yield from this routine.  It is part of the protocol engine's thread. 
//  It executes in the context of g_ix_ctl_thread.  Yielding from within this 
//  function will cause the protocol engine's state machine to float belly up. 
//  And that will cause your firmware to shuffle off this mortal coil, post haste. 
//------------------------------------------------------------------------------ 
t_result dfu_cpex(t_message_ref msgp) reentrant 
{ 
  t_usb_rqst *rqstp; 
  rqstp = (t_usb_rqst *)message_rd_arg(msgp); 
  switch (message_rd_id(msgp)) 
  { 
    case k_hci_dfu_detach: 
    case k_hvd_dfu_detach: 
      mcu_begin_critical_section(); 
      trace0(0, dfu, 0, "dfu_cpex: k_hci_dfu_detach / k_hvd_detach"); 
      // communicate between app and loader via GF0 of PCON register 
      _cpu_register_setbit(PCON, 2); 
      // start up the detach timeout 
      _dfu_timer.u8.hi = rqstp->wValueHi; 
      _dfu_timer.u8.lo = rqstp->wValueLo; 
      g_cdm0 = 0; 
      mcu_end_critical_section(); 
      // now wait for the usb reset 
      return k_success; 
 
    case k_msg_transaction_done: 
      trace0(0, dfu, 0, "dfu_cpex: k_msg_transaction_done"); 
      // if we are timing the DFU_DETACH request then check to see if time to enter dfu mode... 
      if (g_cdm0 < _dfu_timer.u16) 
      { 
        _dfu_timer.u16 = 0; 
        // load the "relocatable" flash_coerce_dfu() into sram 
        dfu_copy_flash_to_sram(); 
        mcu_begin_critical_section(); 
        // communicate between app and loader via GF0 of PCON register 
        _cpu_register_setbit(PCON, 2); 
        // make sram executable so flash_coerce_dfu() can run from sram 
        _flash_execute_from_ram(); 
        trace0(0, dfu, 0, "dfu_cpex: coerce dfu"); 
        // jump to flash_coerce_dfu() at its new address in sram 
        ((t_code_fragment)0x0400)(); 
      } 
      return k_success; 
 
    default: 
      return k_error; 
  } 
  return k_error; 
} 
 
//---eof------------------------------------------------------------------------