Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AVR-EB parts #1491

Merged
merged 7 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/avr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,10 +1165,10 @@ int avr_signature(const PROGRAMMER *pgm, const AVRPART *p) {
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(str_eq(mem->desc, "fuses") && addr < 10) { // Get right fuse in fuses memory
if(str_eq(mem->desc, "fuses") && addr >=0 && addr < 16) { // Get right fuse in fuses memory
char memtype[64];
AVRMEM *dfuse;
sprintf(memtype, "fuse%d", addr);
sprintf(memtype, "fuse%x", addr);
if((dfuse = avr_locate_mem(p, memtype)) && dfuse->size == 1)
bitmask = dfuse->bitmask;
}
Expand Down Expand Up @@ -1401,11 +1401,12 @@ const char *avr_mem_order[100] = {
"fuse4", "tcd0cfg", "fuse5", "syscfg0",
"fuse6", "syscfg1", "fuse7", "append",
"codesize", "fuse8", "fuse9", "bootend",
"bootsize", "fuses", "lock", "lockbits",
"tempsense", "signature", "prodsig", "sernum",
"calibration", "osccal16", "osccal20", "osc16err",
"osc20err", "usersig", "userrow", "data",
"io", "sib",
"bootsize", "fusea" "pdicfg", "fuses",
"lock", "lockbits", "tempsense", "signature",
"prodsig", "sernum", "calibration", "osccal16",
"osccal20", "osc16err", "osc20err", "bootrow",
"usersig", "userrow", "data", "io",
"sib",
};

void avr_add_mem_order(const char *str) {
Expand Down Expand Up @@ -1441,8 +1442,8 @@ int avr_mem_is_eeprom_type(const AVRMEM *mem) {
return avr_memtype_is_eeprom_type(mem->desc);
}

int avr_memtype_is_usersig_type(const char *memtype) {
return memtype && (str_eq(memtype, "usersig") || str_eq(memtype, "userrow"));
int avr_memtype_is_usersig_type(const char *memtype) { // Bootrow is subsumed under usersig type
return memtype && (str_eq(memtype, "bootrow") || str_eq(memtype, "usersig") || str_eq(memtype, "userrow"));
}

int avr_mem_is_usersig_type(const AVRMEM *mem) {
Expand Down
85 changes: 45 additions & 40 deletions src/avrcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,31 @@
* int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
*
* avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
* routines are available and if the device memory type is flash, EEPROM or
* usersig. The AVRXMEGA memories application, apptable and boot are subsumed
* under flash. Userrow is subsumed under usersig provided avrdude.conf has a
* memory alias from usersig to userrow. In all other cases the cached
* read/write functions fall back to pgm->read_byte() and pgm->write_byte(),
* respectively. Bytewise cached read always gets its data from the cache,
* possibly after reading a page from the device memory. Bytewise cached
* write with an address in memory range only ever modifies the cache. Any
* modifications are written to the device after calling avr_flush_cache() or
* when attempting to read or write from a location outside the address range
* of the device memory.
* routines are available and if the device memory type is flash, EEPROM,
* bootrow or usersig. The AVRXMEGA memories application, apptable and boot
* are subsumed under flash. Userrow is subsumed under usersig provided
* avrdude.conf has a memory alias from usersig to userrow. In all other
* cases the cached read/write functions fall back to pgm->read_byte() and
* pgm->write_byte(), respectively. Bytewise cached read always gets its data
* from the cache, possibly after reading a page from the device memory.
* Bytewise cached write with an address in memory range only ever modifies
* the cache. Any modifications are written to the device after calling
* avr_flush_cache() or when attempting to read or write from a location
* outside the address range of the device memory.
*
* avr_flush_cache() synchronises pending writes to flash, EEPROM and usersig
* with the device. With some programmer and part combinations, flash (and
* sometimes EEPROM, too) looks like a NOR memory, ie, a write can only clear
* bits, never set them. For NOR memories a page erase or, if not available,
* a chip erase needs to be issued before writing arbitrary data. Usersig is
* generally unaffected by a chip erase, so will need a page erase. When a
* memory looks like a NOR memory, either page erase is deployed (eg, with
* parts that have PDI/UPDI interfaces), or if that is not available, both
* EEPROM and flash caches are fully read in, a pgm->chip_erase() command is
* issued and both EEPROM and flash are written back to the device. Hence, it
* can take minutes to ensure that a single previously cleared bit is set
* and, therefore, this routine should be called sparingly.
* avr_flush_cache() synchronises pending writes to flash, EEPROM, bootrow
* and usersig with the device. With some programmer and part combinations,
* flash (and sometimes EEPROM, too) looks like a NOR memory, ie, a write can
* only clear bits, never set them. For NOR memories a page erase or, if not
* available, a chip erase needs to be issued before writing arbitrary data.
* Bootrow and usersig are generally unaffected by a chip erase, so will need
* a page erase. When a memory looks like a NOR memory, either page erase is
* deployed (eg, with parts that have PDI/UPDI interfaces), or if that is not
* available, both EEPROM and flash caches are fully read in, a
* pgm->chip_erase() command is issued and both EEPROM and flash are written
* back to the device. Hence, it can take minutes to ensure that a single
* previously cleared bit is set and, therefore, this routine should be
* called sparingly.
*
* avr_chip_erase_cached() erases the chip and discards pending writes() to
* flash or EEPROM. It presets the flash cache to all 0xff alleviating the
Expand All @@ -90,7 +91,7 @@
* has these clear bits on the device. Only with this evidence is the EEPROM
* cache preset to all 0xff otherwise the cache discards all pending writes
* to EEPROM and is left unchanged otherwise. avr_chip_erase_cached() does not
* affect the usersig cache.
* affect the bootrow or usersig cache.
*
* The avr_page_erase_cached() function erases a page and synchronises it
* with the cache.
Expand Down Expand Up @@ -120,7 +121,7 @@
* - Programmer must have paged routines
* - Memory has positive page size, which is a power of two
* - Memory has positive size, which is a multiple of the page size
* - Memory is flash, EEPROM or usersig type
* - Memory is flash, EEPROM, bootrow or usersig type
*
* Note that in this definition the page size can be 1
*/
Expand Down Expand Up @@ -256,7 +257,7 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p,

static int initCache(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p) {
AVRMEM *basemem = avr_locate_mem(p,
cp == pgm->cp_flash? "flash": cp == pgm->cp_eeprom? "eeprom": "usersig");
cp == pgm->cp_flash? "flash": cp == pgm->cp_eeprom? "eeprom": cp == pgm->cp_bootrow? "bootrow": "usersig");

if(!basemem || !avr_has_paged_access(pgm, basemem))
return LIBAVRDUDE_GENERAL_FAILURE;
Expand Down Expand Up @@ -357,11 +358,12 @@ typedef struct {
} CacheDesc_t;


// Write flash, EEPROM and usersig caches to device and free them
// Write flash, EEPROM, bootrow and usersig caches to device and free them
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
CacheDesc_t mems[3] = {
CacheDesc_t mems[] = {
{ avr_locate_mem(p, "flash"), pgm->cp_flash, 1, 0, -1, 0 },
{ avr_locate_mem(p, "eeprom"), pgm->cp_eeprom, 0, 1, -1, 0 },
{ avr_locate_mem(p, "bootrow"), pgm->cp_bootrow, 0, 0, -1, 0 },
{ avr_locate_mem(p, "usersig"), pgm->cp_usersig, 0, 0, -1, 0 },
};

Expand Down Expand Up @@ -453,7 +455,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
AVR_Cache *cp = mems[i].cp;
if(!mem)
continue;
if(avr_mem_is_usersig_type(mem)) // CE does not affect usersig
if(avr_mem_is_usersig_type(mem)) // CE does not affect bootrow/usersig
continue;

for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size)
Expand All @@ -469,7 +471,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
AVR_Cache *cp = mems[i].cp;
if(!mem)
continue;
if(avr_mem_is_usersig_type(mem)) // CE does not affect usersig
if(avr_mem_is_usersig_type(mem)) // CE does not affect bootrow/usersig
continue;

for(int ird = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
Expand Down Expand Up @@ -498,7 +500,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
AVR_Cache *cp = mems[i].cp;
if(!mem)
continue;
if(avr_mem_is_usersig_type(mem)) // CE does not affect usersig
if(avr_mem_is_usersig_type(mem)) // CE does not affect bootrow/usersig
continue;

if(mems[i].isflash) {
Expand Down Expand Up @@ -590,15 +592,15 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {

/*
* Read byte via a read/write cache
* - Used if paged routines available and if memory is flash, EEPROM or usersig
* - Used if paged routines available and if memory is flash, EEPROM, bootrow or usersig
* - Otherwise fall back to pgm->read_byte()
* - Out of memory addr: synchronise cache and, if successful, pretend reading a zero
* - Cache is automagically created and initialised if needed
*/
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char *value) {

// Use pgm->read_byte() if not flash/EEPROM/usersig or no paged access
// Use pgm->read_byte() if not flash/EEPROM/bootrow/usersig or no paged access
if(!avr_has_paged_access(pgm, mem))
return fallback_read_byte(pgm, p, mem, addr, value);

Expand All @@ -611,7 +613,8 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
}

AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom:
avr_mem_is_usersig_type(mem)? pgm->cp_usersig: pgm->cp_flash;
avr_mem_is_flash_type(mem)? pgm->cp_flash:
str_eq(mem->desc, "bootrow")? pgm->cp_bootrow: pgm->cp_usersig;

if(!cp->cont) // Init cache if needed
if(initCache(cp, pgm, p) < 0)
Expand All @@ -633,7 +636,7 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *

/*
* Write byte via a read/write cache
* - Used if paged routines available and if memory is flash, EEPROM or usersig
* - Used if paged routines available and if memory is flash, EEPROM, bootrow or usersig
* - Otherwise fall back to pgm->write_byte()
* - Out of memory addr: synchronise cache with device and return whether successful
* - If programmer indicates a readonly spot, return LIBAVRDUDE_SOFTFAIL
Expand All @@ -642,7 +645,7 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
unsigned long addr, unsigned char data) {

// Use pgm->write_byte() if not flash/EEPROM/usersig or no paged access
// Use pgm->write_byte() if not flash/EEPROM/bootrow/usersig or no paged access
if(!avr_has_paged_access(pgm, mem))
return fallback_write_byte(pgm, p, mem, addr, data);

Expand All @@ -651,7 +654,8 @@ int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
return avr_flush_cache(pgm, p);

AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom:
avr_mem_is_usersig_type(mem)? pgm->cp_usersig: pgm->cp_flash;
avr_mem_is_flash_type(mem)? pgm->cp_flash:
str_eq(mem->desc, "bootrow")? pgm->cp_bootrow: pgm->cp_usersig;

if(!cp->cont) // Init cache if needed
if(initCache(cp, pgm, p) < 0)
Expand Down Expand Up @@ -682,7 +686,7 @@ int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) {
CacheDesc_t mems[3] = {
{ avr_locate_mem(p, "flash"), pgm->cp_flash, 1, 0, -1, 0 },
{ avr_locate_mem(p, "eeprom"), pgm->cp_eeprom, 0, 1, -1, 0 },
// usersig is unaffected by CE
// bootrow/usersig is unaffected by CE
};
int rc;

Expand Down Expand Up @@ -754,7 +758,8 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
}

AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom:
avr_mem_is_usersig_type(mem)? pgm->cp_usersig: pgm->cp_flash;
avr_mem_is_flash_type(mem)? pgm->cp_flash:
str_eq(mem->desc, "bootrow")? pgm->cp_bootrow: pgm->cp_usersig;

if(!cp->cont) // Init cache if needed
if(initCache(cp, pgm, p) < 0)
Expand All @@ -780,7 +785,7 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM

// Free cache(s) discarding any pending writes
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p_unused) {
AVR_Cache *mems[3] = { pgm->cp_flash, pgm->cp_eeprom, pgm->cp_usersig };
AVR_Cache *mems[] = { pgm->cp_flash, pgm->cp_eeprom, pgm->cp_bootrow, pgm->cp_usersig };

for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
AVR_Cache *cp = mems[i];
Expand Down
16 changes: 11 additions & 5 deletions src/avrdude.1
Original file line number Diff line number Diff line change
Expand Up @@ -823,8 +823,10 @@ A.k.a. syscfg1: system configuration 1
A.k.a. append or codesize: either the end of the application code section or the code size in blocks of 256/512 bytes
.It fuse8
A.k.a. bootend or bootsize: end of the boot section or the boot size in blocks of 256/512 bytes
.It fusea
A.k.a. pdicfg: configures/locks updi access; it is the only fuse that consists of two bytes
.It fuses
A "logical" memory of 9 bytes containing all fuseN of a part, which can be
A "logical" memory of up to 16 bytes containing all fuseX of a part, which can be
used to program all fuses at the same time
.It osc16err
Two bytes typically describing the 16 MHz oscillator frequency error at 3 V and 5 V, respectively
Expand All @@ -840,6 +842,10 @@ Production signature (calibration) area
Serial number with a unique ID for the part (10 bytes)
.It tempsense
Temperature sensor calibration values
.It bootrow
Extra page of memory that is only accessible by the MCU in bootloader
code; UDPI can read and write this memory only when the device is
unlocked; bootrow is not erased during chip erase
.It userrow
Extra page of EEPROM memory that can be used for firmware settings; this
memory is not erased during a chip erase
Expand Down Expand Up @@ -1048,7 +1054,7 @@ Can be used as an alias for dump.
Manually program the respective memory cells, starting at address
.Ar addr ,
using the data items provided.
The terminal implements reading from and writing to flash, EEPROM and
The terminal implements reading from and writing to flash, EEPROM, bootrow and
usersig type memories normally through a cache and paged access functions.
All other memories are directly written to without use of a cache. Some
older parts without paged access, depending on the programmer, might also
Expand Down Expand Up @@ -1130,11 +1136,11 @@ Erase the entire specified memory.
.It Ar erase memory addr len
Erase a section of the specified memory.
.It Ar flush
Synchronise with the device all pending writes to flash, EEPROM and
Synchronise with the device all pending writes to flash, EEPROM, bootrow and
usersig. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, i.e., a write can only clear bits,
never set them. For NOR memories a page erase or, if not available, a chip
erase needs to be issued before writing arbitrary data. Usersig is
erase needs to be issued before writing arbitrary data. Bootrow and usersig are
generally unaffected by a chip erase. When a memory looks like a NOR
memory, either page erase is deployed (e.g., with parts that have PDI/UPDI
interfaces), or if that is not available, both EEPROM and flash caches are
Expand All @@ -1149,7 +1155,7 @@ actually written to the device when using the
command, at the end of the terminal session after typing
.Ar quit ,
or after EOF on input is encountered. The abort command resets the cache
discarding all previous writes to the flash, EEPROM and usersig cache.
discarding all previous writes to the flash, EEPROM, bootrow and usersig cache.
.It Ar config {<-f|-a|-v>}
Show all configuration properties of the part; these are usually bitfields
in fuses or lock bits bytes that can take on values, which typically have
Expand Down
Loading