⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avratmel.c

📁 tinyos-2.x.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
// $Id: AvrAtmel.C,v 1.4 2006/12/12 18:23:01 vlahan Exp $

/*
 * $Id: AvrAtmel.C,v 1.4 2006/12/12 18:23:01 vlahan Exp $
 *
 ****************************************************************************
 *
 * uisp - The Micro In-System Programmer for Atmel AVR microcontrollers.
 * Copyright (C) 1999, 2000, 2001, 2002  Uros Platise
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 ****************************************************************************
 */

/*
	AvrAtmel.C
	
	Device driver for the Serial Atmel Low Cost Programmer
	Uros Platise (c) 1999
*/

#include "config.h"

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "AvrAtmel.h"

#define AUTO_SELECT	0

/* Low Cost Atmel Programmer AVR Codes
   Valid for software version: SW_MAJOR=2 SW_MINOR=0
   
   Code 0xff is reserved for invalid code. Update the
   TAvrAtmel constructor if Atmel comes up with it.

   The list is current as of AVRProg 1.37 (shipped with AVR Studio 3.54).
*/
TAvrAtmel::SPrgPart TAvrAtmel::prg_part [] = {
  {"S1200A", 0x10, "AT90S1200 rev. A", false}, /* old */
  {"S1200B", 0x11, "AT90S1200 rev. B", false}, /* old */
  {"S1200C", 0x12, "AT90S1200 rev. C", false}, /* old */
  {"S1200",  0x13, "AT90S1200", false},
  {"S2313",  0x20, "AT90S2313", false},
  {"S4414",  0x28, "AT90S4414", false},
  {"S4433",  0x30, "AT90S4433", false},
  {"S2333",  0x34, "AT90S2333", false},
  {"S8515",  0x38, "AT90S8515", false},
  {"M8515",  0x3A, "ATmega8515", false},
  {"M8515b", 0x3B, "ATmega8515 BOOT", false},
  {"M103C",  0x40, "ATmega103 rev. C", false}, /* old */
  {"M103",   0x41, "ATmega103", false},
  {"M603",   0x42, "ATmega603", false},
  {"M128",   0x43, "ATmega128", false},
  {"M128b",  0x44, "ATmega128 BOOT", false},
  {"S2323",  0x48, "AT90S2323", false},
  {"S2343",  0x4C, "AT90S2343", false}, /* ATtiny22 too */
  {"TN11",   0x50, "ATtiny11",  false}, /* parallel */
  {"TN10",   0x51, "ATtiny10",  false}, /* parallel */
  {"TN12",   0x55, "ATtiny12",  false},
  {"TN15",   0x56, "ATtiny15",  false},
  {"TN19",   0x58, "ATtiny19",  false}, /* parallel */
  {"TN28",   0x5C, "ATtiny28",  false}, /* parallel */
  {"TN26",   0x5E, "ATtiny26",  false},
  {"M161",   0x60, "ATmega161", false},
  {"M161b",  0x61, "ATmega161 BOOT", false},
  {"M163",   0x64, "ATmega163", false},
  {"M83",    0x65, "ATmega83",  false}, /* ATmega8535 ??? */
  {"M163b",  0x66, "ATmega163 BOOT", false},
  {"M83b",   0x67, "ATmega83 BOOT", false},
  {"S8535",  0x68, "AT90S8535", false},
  {"S4434",  0x6C, "AT90S4434", false},
  {"C8534",  0x70, "AT90C8534", false}, /* parallel */
  {"C8544",  0x71, "AT90C8544", false}, /* parallel ??? */
  {"M32",    0x72, "ATmega32",  false}, /* XXX no ATmega323 */
  {"M32b",   0x73, "ATmega32 BOOT", false},
  {"M16",    0x74, "ATmega16",  false},
  {"M16b",   0x75, "ATmega16 BOOT", false},
  {"M8",     0x76, "ATmega8",   false},
  {"M8b",    0x77, "ATmega8 BOOT", false},
  {"89C1051",0x80, "AT89C1051", false}, /* parallel */
  {"89C2051",0x81, "AT89C2051", false}, /* parallel */
  {"89C51",  0x82, "AT89C51",   false}, /* parallel */
  {"89LV51", 0x83, "AT89LV51",  false}, /* parallel */
  {"89C52",  0x84, "AT89C52",   false}, /* parallel */
  {"89LV52", 0x85, "AT89LV52",  false}, /* parallel */
  {"S8252",  0x86, "AT89S8252", false},
  {"89S53",  0x87, "AT89S53",   false},
  /* 0x88..0xDF reserved for AT89,
     0xE0..0xFF reserved */
  {"auto",   AUTO_SELECT, "Auto detect", false},  
  {"",       0x00, "", false}
};

/* Private Functions
*/

void TAvrAtmel::EnterProgrammingMode(){
  /* Select Device Type */
  TByte set_device[2] = {'T', desired_avrcode};
  Send(set_device, 2, 1);
  CheckResponse(set_device[0]);

  /* Enter Programming Mode */
  TByte enter_prg[1] = {'P'};
  Send(enter_prg, 1);
  CheckResponse(enter_prg[0]);

  /* Read Signature Bytes */
  TByte sig_bytes[3] = {'s', 0, 0};
  Send(sig_bytes, 1, 3);
  part_number = sig_bytes[0];
  part_family = sig_bytes[1];
  vendor_code = sig_bytes[2];
}

void TAvrAtmel::LeaveProgrammingMode(){
  TByte leave_prg [1] = { 'L' };
  Send(leave_prg, 1);    
}

void TAvrAtmel::CheckResponse(TByte x){
  if (x!=13){throw Error_Device ("Device is not responding correctly.");}
}

void TAvrAtmel::EnableAvr(){
  bool auto_select = desired_avrcode == AUTO_SELECT;
  
  for (unsigned pidx=0; prg_part[pidx].code != AUTO_SELECT; pidx++){
  
    if (!prg_part[pidx].supported && auto_select){continue;}
    if (auto_select){
      desired_avrcode = prg_part[pidx].code;
      Info(2, "Trying with: %s\n", prg_part[pidx].description);
    }    
    EnterProgrammingMode();
    if (!auto_select ||
        !(vendor_code==0 && part_family==1 && part_number==2)){
      break;
    }
    LeaveProgrammingMode();    
  }

 // OverridePart("atmega163"); // XXXXX local hack for broken signature bytes
  
  Identify();
  
  if (auto_select){
    /* If avr was recongnized by the Identify(), try to find better match
       in the support list.
    */    
    unsigned better_pidx = 0;
    TByte better_avrcode = desired_avrcode;
    
    for (unsigned pidx=0; prg_part[pidx].code != AUTO_SELECT; pidx++){
      if (!prg_part[pidx].supported){continue;}      
      if (strstr(prg_part[pidx].description, GetPartName())){
        better_avrcode = prg_part[better_pidx = pidx].code;
      }
    }
    if (better_avrcode != desired_avrcode){
      Info(2, "Retrying with better match: %s\n", 
        prg_part[better_pidx].description);
      desired_avrcode = better_avrcode;
      LeaveProgrammingMode();
      EnterProgrammingMode();
      Identify();
    }
  }
}

void TAvrAtmel::SetAddress(TAddr addr){
  apc_address = addr;
  TByte setAddr [3] = { 'A', (addr>>8)&0xff, addr&0xff};
  Send(setAddr, 3, 1);
  CheckResponse(setAddr [0]);
}

void TAvrAtmel::WriteProgramMemoryPage(){
  SetAddress(page_addr >> 1);
  TByte prg_page [1] = { 'm' };
  Send(prg_page, 1);    
}

/* Device Interface Functions
*/

TByte TAvrAtmel::ReadByte(TAddr addr){
  CheckMemoryRange(addr);
  if (segment==SEG_FLASH){
    TAddr saddr = addr>>1;
    TByte rdF [2] = { 'R', 0 };
    
    if (buf_addr==addr && cache_lowbyte==true){return buf_lowbyte;}
    if (apc_address!=saddr || apc_autoinc==false) SetAddress(saddr);    
    apc_address++;
    Send(rdF, 1, 2);
    /* cache low byte */
    cache_lowbyte = true;
    buf_addr = (saddr<<1) + 1;
    buf_lowbyte = rdF[0];
    return rdF [1 - (addr&1)];
  }
  else if (segment==SEG_EEPROM){    
    SetAddress(addr);
    TByte readEE [1] = { 'd' };    
    Send(readEE, 1);
    return readEE[0];
  }
  else if (segment==SEG_FUSE) {
    TByte readback = 0xff;
    switch (addr) {
    case AVR_FUSE_LOW_ADDR:
      if (TestFeatures(AVR_FUSE_RD))
        readback = ReadFuseLowBits();
#if 0
      /* TRoth/2002-06-03: This case is handled by ReadLockBits() so we don't
         need it here. Can I delete it completely? */
      else if (TestFeatures(AVR_LOCK_RD76))
        readback = ReadLockFuseBits();
#endif
      break;
    case AVR_FUSE_HIGH_ADDR:
      if (TestFeatures(AVR_FUSE_HIGH))
        readback = ReadFuseHighBits();
      else
        Info (1, "Cannot read high fuse bits on this device. Returning 0xff\n");
      break;
    case AVR_CAL_ADDR:
      if (TestFeatures(AVR_CAL_RD))
        readback = ReadCalByte(0);
      else
        Info (1, "Cannot read calibration byte on this device. Returning 0xff\n");
      break;
    case AVR_LOCK_ADDR:
      readback = ReadLockBits();
      break;
    case AVR_FUSE_EXT_ADDR:
      if (TestFeatures(AVR_FUSE_EXT))
        readback = ReadFuseExtBits();
      else
        Info (1, "Cannot read extended fuse bits on this device. Returning 0xff\n");
      break;
    }
    Info(3, "Read fuse/cal/lock: byte %d = 0x%02X\n",
             (int) addr, (int) readback);
    return readback;
  }
  else return 0;
}

void TAvrAtmel::WriteByte(TAddr addr, TByte byte, bool flush_buffer){
  CheckMemoryRange(addr);
  
  /* do not check if byte is already written -- it spoils auto-increment
     feature which reduces the speed for 50%!
  */     
  if (segment==SEG_FLASH){
  
    cache_lowbyte = false;		/* clear read cache buffer */  
    if (!page_size && byte==0xff) return;
  
    /* PAGE MODE PROGRAMMING:
       If page mode is enabled cache page address.
       When current address is out of the page address
       flush page buffer and continue programming.
    */  
    if (page_size){
      Info(4, "Loading data to address: %d (page_addr_fetched=%s)\n", 
	addr, page_addr_fetched?"Yes":"No");

      if (page_addr_fetched && page_addr != (addr & ~(page_size - 1))){
	WriteProgramMemoryPage();
	page_addr_fetched = false;
      }
      if (page_addr_fetched==false){
	page_addr=addr & ~(page_size - 1);
	page_addr_fetched=true;
      }
      if (flush_buffer){WriteProgramMemoryPage();}
    }
    
    TByte wrF [2] = { (addr&1)?'C':'c', byte };
    
    if (apc_address!=(addr>>1) || apc_autoinc==false) SetAddress (addr>>1);
    if (wrF[0]=='C') apc_address++;
    Send(wrF, 2, 1);
    CheckResponse(wrF[0]);
  }
  else if (segment==SEG_EEPROM){
    SetAddress(addr);
    TByte writeEE [2] = { 'D', byte };

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -