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

📄 avr.c

📁 这是一个非常有价值的参考代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * avrdude - A Downloader/Uploader for AVR device programmers * Copyright (C) 2000-2004  Brian S. Dean <bsd@bsdhome.com> * * 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 *//* $Id: avr.c,v 1.65 2005/09/21 01:26:54 bdean Exp $ */#include "ac_cfg.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/time.h>#include <time.h>#include "avr.h"#include "lists.h"#include "pindefs.h"#include "ppi.h"#include "safemode.h"#define DEBUG 0extern char       * progname;extern char         progbuf[];extern PROGRAMMER * pgm;extern int do_cycles;int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,                           unsigned long addr, unsigned char * value){  unsigned char cmd[4];  unsigned char res[4];  unsigned char data;  OPCODE * readop;  pgm->pgm_led(pgm, ON);  pgm->err_led(pgm, OFF);  /*   * figure out what opcode to use   */  if (mem->op[AVR_OP_READ_LO]) {    if (addr & 0x00000001)      readop = mem->op[AVR_OP_READ_HI];    else      readop = mem->op[AVR_OP_READ_LO];    addr = addr / 2;  }  else {    readop = mem->op[AVR_OP_READ];  }  if (readop == NULL) {#if DEBUG    fprintf(stderr,             "avr_read_byte(): operation not supported on memory type \"%s\"\n",            p->desc);#endif    return -1;  }  memset(cmd, 0, sizeof(cmd));  avr_set_bits(readop, cmd);  avr_set_addr(readop, cmd, addr);  pgm->cmd(pgm, cmd, res);  data = 0;  avr_get_output(readop, res, &data);  pgm->pgm_led(pgm, OFF);  *value = data;  return 0;}/* * read a byte of data from the indicated memory region */int avr_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,                   unsigned long addr, unsigned char * value){  int rc;  if (pgm->read_byte) {    rc = pgm->read_byte(pgm, p, mem, addr, value);    if (rc == 0) {      return rc;    }    /* read_byte() method failed, try again with default. */  }  return avr_read_byte_default(pgm, p, mem, addr, value);}/* * Return the number of "interesting" bytes in a memory buffer, * "interesting" being defined as up to the last non-0xff data * value. This is useful for determining where to stop when dealing * with "flash" memory, since writing 0xff to flash is typically a * no-op. Always return an even number since flash is word addressed. */int avr_mem_hiaddr(AVRMEM * mem){  int i, n;  /* return the highest non-0xff address regardless of how much     memory was read */  for (i=mem->size-1; i>0; i--) {    if (mem->buf[i] != 0xff) {      n = i+1;      if (n & 0x01)        return n+1;      else        return n;    }  }  return 0;}/* * Read the entirety of the specified memory type into the * corresponding buffer of the avrpart pointed to by 'p'.  If size = * 0, read the entire contents, otherwise, read 'size' bytes. * * Return the number of bytes read, or < 0 if an error occurs.   */int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,              int verbose){  unsigned char    rbyte;  unsigned long    i;  unsigned char  * buf;  AVRMEM * mem;  int rc;  mem = avr_locate_mem(p, memtype);  if (mem == NULL) {    fprintf(stderr, "No \"%s\" memory for part %s\n",            memtype, p->desc);    return -1;  }  buf  = mem->buf;  if (size == 0) {    size = mem->size;  }  /*   * start with all 0xff   */  memset(buf, 0xff, size);  if ((strcmp(mem->desc, "flash")==0) || (strcmp(mem->desc, "eeprom")==0)) {    if (pgm->paged_load != NULL) {      /*       * the programmer supports a paged mode read, perhaps more       * efficiently than we can read it directly, so use its routine       * instead       */      if (mem->paged) {        rc = pgm->paged_load(pgm, p, mem, mem->page_size, size);        if (rc < 0)          return rc;      }      else {        rc = pgm->paged_load(pgm, p, mem, pgm->page_size, size);        if (rc < 0)          return rc;      }      if (strcasecmp(mem->desc, "flash") == 0)        return avr_mem_hiaddr(mem);      else        return rc;    }  }  if (strcmp(mem->desc, "signature") == 0) {    if (pgm->read_sig_bytes) {      return pgm->read_sig_bytes(pgm, p, mem);    }  }  for (i=0; i<size; i++) {    rc = avr_read_byte(pgm, p, mem, i, &rbyte);    if (rc != 0) {      fprintf(stderr, "avr_read(): error reading address 0x%04lx\n", i);      if (rc == -1)         fprintf(stderr,                 "    read operation not supported for memory \"%s\"\n",                memtype);      return -2;    }    buf[i] = rbyte;    report_progress(i, size, NULL);  }  if (strcasecmp(mem->desc, "flash") == 0)    return avr_mem_hiaddr(mem);  else    return i;}/* * write a page data at the specified address */int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,                    unsigned long addr){  unsigned char cmd[4];  unsigned char res[4];  OPCODE * wp;  wp = mem->op[AVR_OP_WRITEPAGE];  if (wp == NULL) {    fprintf(stderr,             "avr_write_page(): memory \"%s\" not configured for page writes\n",            mem->desc);    return -1;  }  /*   * if this memory is word-addressable, adjust the address   * accordingly   */  if ((mem->op[AVR_OP_LOADPAGE_LO]) || (mem->op[AVR_OP_READ_LO]))    addr = addr / 2;  pgm->pgm_led(pgm, ON);  pgm->err_led(pgm, OFF);  memset(cmd, 0, sizeof(cmd));  avr_set_bits(wp, cmd);  avr_set_addr(wp, cmd, addr);  pgm->cmd(pgm, cmd, res);  /*   * since we don't know what voltage the target AVR is powered by, be   * conservative and delay the max amount the spec says to wait   */  usleep(mem->max_write_delay);  pgm->pgm_led(pgm, OFF);  return 0;}int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,                   unsigned long addr, unsigned char data){  unsigned char cmd[4];  unsigned char res[4];  unsigned char r;  int ready;  int tries;  unsigned long start_time;  unsigned long prog_time;  unsigned char b;  unsigned short caddr;  OPCODE * writeop;  int rc;  int readok=0;  struct timeval tv;  if (!mem->paged) {    /*      * check to see if the write is necessary by reading the existing     * value and only write if we are changing the value; we can't     * use this optimization for paged addressing.     */    rc = avr_read_byte(pgm, p, mem, addr, &b);    if (rc != 0) {      if (rc != -1) {        return -2;      }      /*       * the read operation is not support on this memory type       */    }    else {      readok = 1;      if (b == data) {        return 0;      }    }  }  /*   * determine which memory opcode to use   */  if (mem->op[AVR_OP_WRITE_LO]) {    if (addr & 0x01)      writeop = mem->op[AVR_OP_WRITE_HI];    else      writeop = mem->op[AVR_OP_WRITE_LO];    caddr = addr / 2;  }  else if (mem->op[AVR_OP_LOADPAGE_LO]) {    if (addr & 0x01)      writeop = mem->op[AVR_OP_LOADPAGE_HI];    else      writeop = mem->op[AVR_OP_LOADPAGE_LO];    caddr = addr / 2;  }  else {    writeop = mem->op[AVR_OP_WRITE];    caddr = addr;  }  if (writeop == NULL) {#if DEBUG    fprintf(stderr,             "avr_write_byte(): write not supported for memory type \"%s\"\n",            mem->desc);#endif    return -1;  }  pgm->pgm_led(pgm, ON);  pgm->err_led(pgm, OFF);  memset(cmd, 0, sizeof(cmd));  avr_set_bits(writeop, cmd);  avr_set_addr(writeop, cmd, caddr);  avr_set_input(writeop, cmd, data);  pgm->cmd(pgm, cmd, res);  if (mem->paged) {    /*     * in paged addressing, single bytes to be written to the memory     * page complete immediately, we only need to delay when we commit     * the whole page via the avr_write_page() routine.     */    pgm->pgm_led(pgm, OFF);    return 0;  }  if (readok == 0) {    /*     * read operation not supported for this memory type, just wait     * the max programming time and then return      */    usleep(mem->max_write_delay); /* maximum write delay */    pgm->pgm_led(pgm, OFF);    return 0;  }  tries = 0;  ready = 0;  while (!ready) {    if ((data == mem->readback[0]) ||        (data == mem->readback[1])) {      /*        * use an extra long delay when we happen to be writing values       * used for polled data read-back.  In this case, polling       * doesn't work, and we need to delay the worst case write time       * specified for the chip.       */      usleep(mem->max_write_delay);      rc = avr_read_byte(pgm, p, mem, addr, &r);      if (rc != 0) {        pgm->pgm_led(pgm, OFF);        pgm->err_led(pgm, OFF);        return -5;      }    }    else {      gettimeofday (&tv, NULL);      start_time = (tv.tv_sec * 1000000) + tv.tv_usec;      do {        /*         * Do polling, but timeout after max_write_delay.

⌨️ 快捷键说明

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