📄 avr.c
字号:
/* * 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 + -