Skip to content

Commit

Permalink
Merge pull request #1897 from stefanrueger/avr_write_byte_default
Browse files Browse the repository at this point in the history
Fix avr_write_byte()
  • Loading branch information
stefanrueger committed Aug 23, 2024
2 parents 720d21f + 5c16bee commit 284612f
Showing 1 changed file with 15 additions and 19 deletions.
34 changes: 15 additions & 19 deletions src/avr.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, con
if(v != NULL)
vmem = avr_locate_mem(v, mem->desc);

if(mem->size < 0) // Sanity check
if(mem->size <= 0) // Sanity check
return -1;

led_clr(pgm, LED_ERR);
Expand Down Expand Up @@ -417,6 +417,7 @@ int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, con
led_clr(pgm, LED_PGM);
return avr_mem_hiaddr(mem);
}

// HW programmers need a page size > 1, bootloader typ only offer paged r/w
if((pgm->paged_load && mem->page_size > 1 && mem->size%mem->page_size == 0) ||
(is_spm(pgm) && avr_has_paged_access(pgm, p, mem))) {
Expand Down Expand Up @@ -650,8 +651,7 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
unsigned char r;
int ready;
int tries;
unsigned long start_time;
unsigned long prog_time;
unsigned long start, now;
unsigned char b;
unsigned short caddr;
OPCODE *writeop;
Expand Down Expand Up @@ -729,6 +729,8 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
goto success;
}

int bm = avr_mem_bitmask(p, mem, addr);

if(!mem->paged && (p->flags & AVRPART_IS_AT90S1200) == 0) {
/*
* Check to see if the write is necessary by reading the existing value and
Expand All @@ -749,23 +751,17 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
// Read operation is not support on this memory
} else {
readok = 1;
if(b == data)
if((b & bm) == (data & bm))
goto success;
}
}

// 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];
writeop = mem->op[addr & 1? AVR_OP_WRITE_HI: AVR_OP_WRITE_LO];
caddr = addr/2;
} else if(mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) {
if(addr & 0x01)
writeop = mem->op[AVR_OP_LOADPAGE_HI];
else
writeop = mem->op[AVR_OP_LOADPAGE_LO];
writeop = mem->op[addr & 1? AVR_OP_LOADPAGE_HI: AVR_OP_LOADPAGE_LO];
caddr = addr/2;
} else {
writeop = mem->op[AVR_OP_WRITE];
Expand Down Expand Up @@ -802,8 +798,8 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
tries = 0;
ready = 0;
while(!ready) {

if((data == mem->readback[0]) || (data == mem->readback[1])) {
if(!(mem_is_eeprom(mem) || mem_is_in_flash(mem)) || // Only poll for flash or eeprom
data == mem->readback[0] || data == mem->readback[1]) { // ... unless data is readback
/*
* 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
Expand All @@ -816,21 +812,21 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
goto rcerror;
}
} else {
start_time = avr_ustimestamp();
start = avr_ustimestamp();
do {
// Do polling, but timeout after max_write_delay
rc = pgm->read_byte(pgm, p, mem, addr, &r);
if(rc != 0) {
rc = -4;
goto rcerror;
}
prog_time = avr_ustimestamp();
} while(r != data && mem->max_write_delay >= 0 && prog_time - start_time < (unsigned long) mem->max_write_delay);
now = avr_ustimestamp();
} while(r != data && mem->max_write_delay >= 0 && (int) (now-start) < mem->max_write_delay);
}

// At this point we either have a valid readback or the max_write_delay is expired

if(r == data) {
if((r & bm) == (data & bm)) {
ready = 1;
} else if(mem->pwroff_after_write) {
/*
Expand Down Expand Up @@ -1234,7 +1230,7 @@ int avr_mem_bitmask(const AVRPART *p, const AVRMEM *mem, int addr) {
int bitmask = mem->bitmask;

// Collective memory fuses will have a different bitmask for each address (ie, fuse)
if(mem_is_fuses(mem) && addr >= 0 && addr < 16) { // Get right fuse in fuses memory
if(mem_is_fuses(mem) && addr >= 0 && addr < mem->size) { // Get right fuse in fuses memory
AVRMEM *dfuse = avr_locate_fuse_by_offset(p, addr);

if(dfuse) {
Expand Down

0 comments on commit 284612f

Please sign in to comment.