2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
|
|
|
* Copyright (C) 2021 Dawid Buchwald
|
|
|
|
*
|
|
|
|
* 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$ */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Based on pymcuprog
|
|
|
|
* See https://github.com/microchip-pic-avr-tools/pymcuprog
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ac_cfg.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "avrdude.h"
|
|
|
|
#include "libavrdude.h"
|
|
|
|
#include "updi_nvm.h"
|
|
|
|
#include "updi_state.h"
|
|
|
|
#include "updi_constants.h"
|
|
|
|
#include "updi_readwrite.h"
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
DONT_USE_WORD_ACCESS,
|
|
|
|
USE_WORD_ACCESS
|
|
|
|
} access_mode;
|
|
|
|
|
|
|
|
#define USE_DEFAULT_COMMAND 0xFF
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_chip_erase_V0(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def chip_erase(self):
|
|
|
|
"""
|
|
|
|
Does a chip erase using the NVM controller
|
|
|
|
|
|
|
|
Note that on locked devices this is not possible
|
|
|
|
and the ERASE KEY has to be used instead, see the unlock method
|
|
|
|
"""
|
|
|
|
self.logger.info("Chip erase using NVM CTRL")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before chip erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_CHIP_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after chip erase")
|
|
|
|
|
|
|
|
return True
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("Chip erase using NVM CTRL\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("UPDI chip erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_flash_page_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_flash_page(self, address):
|
|
|
|
"""
|
|
|
|
Erasing single flash page using the NVM controller (v0)
|
|
|
|
|
|
|
|
:param address: Start address of page to erase
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase flash page at address 0x%08X", address)
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before flash page erase")
|
|
|
|
|
|
|
|
# Dummy write
|
|
|
|
self.readwrite.write_data(address, [0xFF])
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after flash page erase")
|
|
|
|
*/
|
|
|
|
unsigned char data[1];
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
data[0] = 0xFF;
|
|
|
|
if (updi_write_data(pgm, address, data, 1) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("dummy write operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("UPDI flash page erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_eeprom_V0(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_eeprom(self):
|
|
|
|
"""
|
|
|
|
Erase EEPROM memory only (v0)
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase EEPROM")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before EEPROM erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_ERASE_EEPROM)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase EEPROM\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_EEPROM) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("UPDI EEPROM erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_user_row_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_user_row(self, address, size):
|
|
|
|
"""
|
|
|
|
Erase User Row memory only (v0)
|
|
|
|
|
|
|
|
:param address: Start address of user row
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase user row")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before user row erase")
|
|
|
|
|
|
|
|
# On this NVM version user row is implemented as EEPROM
|
|
|
|
# When erasing single EEPROM pages a dummy write is needed for each location to be erased
|
|
|
|
for offset in range(size):
|
|
|
|
self.readwrite.write_data(address+offset, [0xFF])
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after user row erase")
|
|
|
|
*/
|
|
|
|
uint16_t offset;
|
|
|
|
unsigned char data[1];
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase user row\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
data[0]=0xFF;
|
|
|
|
for (offset = 0; offset<size; offset++)
|
|
|
|
{
|
|
|
|
if (updi_write_data(pgm, address+offset, data, 1) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data operation failed at offset 0x%04x\n", offset);
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("erase page operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode, uint8_t nvm_command);
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_eeprom_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size);
|
2021-12-18 15:47:37 +00:00
|
|
|
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_flash_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_flash(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to flash (v0)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_nvm(address, data, use_word_access=True)
|
|
|
|
*/
|
|
|
|
return nvm_write_V0(pgm, p, address, buffer, size, USE_WORD_ACCESS, USE_DEFAULT_COMMAND);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_user_row_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_user_row(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to user row (v0)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
# On this NVM variant user row is implemented as EEPROM
|
|
|
|
return self.write_eeprom(address, data)
|
|
|
|
*/
|
|
|
|
return nvm_write_eeprom_V0(pgm, p, address, buffer, size);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_eeprom_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_eeprom(self, address, data):
|
|
|
|
"""
|
|
|
|
Write data to EEPROM (v0)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_nvm(address, data, use_word_access=False,
|
|
|
|
nvmcommand=constants.UPDI_V0_NVMCTRL_CTRLA_ERASE_WRITE_PAGE)
|
|
|
|
*/
|
|
|
|
return nvm_write_V0(pgm, p, address, buffer, size, DONT_USE_WORD_ACCESS, UPDI_V0_NVMCTRL_CTRLA_ERASE_WRITE_PAGE);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_fuse_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint8_t value) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_fuse(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes one fuse value (v0)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Check that NVM controller is ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready before fuse write")
|
|
|
|
|
|
|
|
# Write address to NVMCTRL ADDR
|
|
|
|
self.logger.debug("Load NVM address")
|
|
|
|
self.readwrite.write_byte(self.device.nvmctrl_address + constants.UPDI_NVMCTRL_ADDRL, address & 0xFF)
|
|
|
|
self.readwrite.write_byte(self.device.nvmctrl_address + constants.UPDI_NVMCTRL_ADDRH, (address >> 8) & 0xFF)
|
|
|
|
|
|
|
|
# Write data
|
|
|
|
self.logger.debug("Load fuse data")
|
|
|
|
self.readwrite.write_byte(self.device.nvmctrl_address + constants.UPDI_NVMCTRL_DATAL, data[0] & 0xFF)
|
|
|
|
|
|
|
|
# Execute
|
|
|
|
self.logger.debug("Execute fuse write")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_WRITE_FUSE)
|
|
|
|
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready after fuse write")
|
|
|
|
*/
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("load NVM address\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_write_byte(pgm, p->nvm_base + UPDI_NVMCTRL_ADDRL, address & 0xFF) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("UPDI write ADDRL operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_write_byte(pgm, p->nvm_base + UPDI_NVMCTRL_ADDRH, (address >> 8) & 0xFF) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write ADDRH operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("load fuse data\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_write_byte(pgm, p->nvm_base + UPDI_NVMCTRL_DATAL, value & 0xFF) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write DATAL operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("execute fuse write\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_WRITE_FUSE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write fuse operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode, uint8_t nvm_command)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
def write_nvm(self, address, data, use_word_access, nvmcommand=constants.UPDI_V0_NVMCTRL_CTRLA_WRITE_PAGE):
|
|
|
|
"""
|
|
|
|
Writes a page of data to NVM (v0)
|
|
|
|
|
|
|
|
By default the PAGE_WRITE command is used, which
|
|
|
|
requires that the page is already erased.
|
|
|
|
By default word access is used (flash)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
:param use_word_access: write whole words?
|
|
|
|
:param nvmcommand: command to use for commit
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Check that NVM controller is ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready before page buffer clear")
|
|
|
|
|
|
|
|
# Clear the page buffer
|
|
|
|
self.logger.debug("Clear page buffer")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V0_NVMCTRL_CTRLA_PAGE_BUFFER_CLR)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready after page buffer clear")
|
|
|
|
|
|
|
|
# Load the page buffer by writing directly to location
|
|
|
|
if use_word_access:
|
|
|
|
self.readwrite.write_data_words(address, data)
|
|
|
|
else:
|
|
|
|
self.readwrite.write_data(address, data)
|
|
|
|
|
|
|
|
# Write the page to NVM, maybe erase first
|
|
|
|
self.logger.debug("Committing data")
|
|
|
|
self.execute_nvm_command(nvmcommand)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready again
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready after page write")
|
|
|
|
*/
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("clear page buffer\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_PAGE_BUFFER_CLR) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("clear page operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (mode == USE_WORD_ACCESS) {
|
|
|
|
if (updi_write_data_words(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data words operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (updi_write_data(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("committing data\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (nvm_command == USE_DEFAULT_COMMAND) {
|
|
|
|
nvm_command = UPDI_V0_NVMCTRL_CTRLA_WRITE_PAGE;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, nvm_command) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("commit data command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_chip_erase_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def chip_erase(self):
|
|
|
|
"""
|
|
|
|
Does a chip erase using the NVM controller
|
|
|
|
Note that on locked devices this it not possible
|
|
|
|
and the ERASE KEY has to be used instead
|
|
|
|
"""
|
|
|
|
self.logger.info("Chip erase using NVM CTRL")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM controller to be ready before chip erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM controller to be ready after chip erase")
|
|
|
|
|
|
|
|
return True
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("chip erase using NVM CTRL\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("chip erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_flash_page_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_flash_page(self, address):
|
|
|
|
"""
|
|
|
|
Erasing single flash page using the NVM controller (v1)
|
|
|
|
|
|
|
|
:param address: Start address of page to erase
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase flash page at address 0x%08X", address)
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before flash page erase")
|
|
|
|
|
|
|
|
# Erase command
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_FLASH_PAGE_ERASE)
|
|
|
|
|
|
|
|
# Dummy write
|
|
|
|
self.readwrite.write_data(address, [0xFF])
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after flash page erase")
|
|
|
|
|
|
|
|
# Remove command from NVM controller
|
|
|
|
self.logger.debug("Clear NVM command")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
*/
|
|
|
|
unsigned char data[1];
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
data[0] = 0xFF;
|
|
|
|
if (updi_write_data(pgm, address, data, 1) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("dummy write operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("flash page erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_eeprom_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_eeprom(self):
|
|
|
|
"""
|
|
|
|
Erase EEPROM memory only (v1)
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase EEPROM")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before EEPROM erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
|
|
|
|
|
|
|
# Remove command from NVM controller
|
|
|
|
self.logger.debug("Clear NVM command")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase EEPROM\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("EEPROM erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("clear NVM command\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("sending empty command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_user_row_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_user_row(self, address, size):
|
|
|
|
"""
|
|
|
|
Erase User Row memory only (v1)
|
|
|
|
|
|
|
|
:param address: Start address of user row
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
# size is not used for this NVM version
|
|
|
|
_dummy = size
|
|
|
|
# On this NVM version user row is implemented as flash
|
|
|
|
return self.erase_flash_page(address)
|
|
|
|
*/
|
|
|
|
return nvm_erase_flash_page_V2(pgm, p, address);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode);
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_flash_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_flash(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to flash (v1)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_nvm(address, data, use_word_access=True)
|
|
|
|
*/
|
|
|
|
return nvm_write_V2(pgm, p, address, buffer, size, USE_WORD_ACCESS);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_user_row_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_user_row(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to user row (v1)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
# On this NVM variant user row is implemented as Flash
|
|
|
|
return self.write_nvm(address, data, use_word_access=False)
|
|
|
|
*/
|
|
|
|
return nvm_write_V2(pgm, p, address, buffer, size, DONT_USE_WORD_ACCESS);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_eeprom_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_eeprom(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to NVM (EEPROM)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
nvm_command = constants.UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE
|
|
|
|
|
|
|
|
# Check that NVM controller is ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM ready before command write")
|
|
|
|
|
|
|
|
# Write the command to the NVM controller
|
|
|
|
self.logger.info("NVM EEPROM erase/write command")
|
|
|
|
self.execute_nvm_command(nvm_command)
|
|
|
|
|
|
|
|
# Write the data
|
|
|
|
self.readwrite.write_data(address, data)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready again
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM ready after data write")
|
|
|
|
|
|
|
|
# Remove command from NVM controller
|
|
|
|
self.logger.info("Clear NVM command")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
*/
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("NVM EEPROM erase/write command\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("EEPROM erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_write_data(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("clear NVM command\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("clear NVM command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_fuse_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint8_t value) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_fuse(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes one fuse value
|
|
|
|
V1 fuses are EEPROM-based
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_eeprom(address, data)
|
|
|
|
*/
|
|
|
|
unsigned char buffer[1];
|
|
|
|
buffer[0]=value;
|
|
|
|
return nvm_write_eeprom_V2(pgm, p, address, buffer, 1);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
def write_nvm(self, address, data, use_word_access):
|
|
|
|
"""
|
|
|
|
Writes data to NVM (version 1)
|
|
|
|
This version of the NVM block has no page buffer, so words are written directly.
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
:param use_word_access: write in whole words?
|
|
|
|
"""
|
|
|
|
nvm_command = constants.UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE
|
|
|
|
|
|
|
|
# Check that NVM controller is ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM controller to be ready before page buffer clear")
|
|
|
|
|
|
|
|
# Write the command to the NVM controller
|
|
|
|
self.logger.info("NVM write command")
|
|
|
|
self.execute_nvm_command(nvm_command)
|
|
|
|
|
|
|
|
# Write the data
|
|
|
|
if use_word_access:
|
|
|
|
self.readwrite.write_data_words(address, data)
|
|
|
|
else:
|
|
|
|
self.readwrite.write_data(address, data)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready again
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise Exception("Timeout waiting for NVM controller to be ready after data write")
|
|
|
|
|
|
|
|
# Remove command from NVM controller
|
|
|
|
self.logger.info("Clear NVM command")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
*/
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("NVM write command\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("clear page operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (mode == USE_WORD_ACCESS) {
|
|
|
|
if (updi_write_data_words(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data words operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (updi_write_data(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("wait for ready chip failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("clear NVM command\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("clear NVM command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_chip_erase_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def chip_erase(self):
|
|
|
|
"""
|
|
|
|
Does a chip erase using the NVM controller
|
|
|
|
|
|
|
|
Note that on locked devices this is not possible
|
|
|
|
and the ERASE KEY has to be used instead, see the unlock method
|
|
|
|
"""
|
|
|
|
self.logger.info("Chip erase using NVM CTRL")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before chip erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_CHIP_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
status = self.wait_nvm_ready()
|
|
|
|
|
|
|
|
# Remove command
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
|
|
|
|
if not status:
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after chip erase")
|
|
|
|
|
|
|
|
return True
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("Chip erase using NVM CTRL\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("chip erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("sending empty command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_flash_page_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_flash_page(self, address):
|
|
|
|
"""
|
|
|
|
Erasing single flash page using the NVM controller (v3)
|
|
|
|
|
|
|
|
:param address: Start address of page to erase
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase flash page at address 0x%08X", address)
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before flash page erase")
|
|
|
|
|
|
|
|
# Dummy write
|
|
|
|
self.readwrite.write_data(address, [0xFF])
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
status = self.wait_nvm_ready()
|
|
|
|
|
|
|
|
# Remove command
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
|
|
|
|
if not status:
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after flash page erase")
|
|
|
|
*/
|
|
|
|
unsigned char data[1];
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
data[0] = 0xFF;
|
|
|
|
if (updi_write_data(pgm, address, data, 1) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("dummy write operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("flash page erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_eeprom_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_eeprom(self):
|
|
|
|
"""
|
|
|
|
Erase EEPROM memory only
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase EEPROM")
|
|
|
|
|
|
|
|
# Wait until NVM CTRL is ready to erase
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready before EEPROM erase")
|
|
|
|
|
|
|
|
# Erase
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_EEPROM_ERASE)
|
|
|
|
|
|
|
|
# And wait for it
|
|
|
|
status = self.wait_nvm_ready()
|
|
|
|
|
|
|
|
# Remove command
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
|
|
|
|
if not status:
|
|
|
|
raise IOError("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase EEPROM\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("EEPROM erase command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("sending empty command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_erase_user_row_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def erase_user_row(self, address, size):
|
|
|
|
"""
|
|
|
|
Erase User Row memory only
|
|
|
|
|
|
|
|
:param address: Start address of user row
|
|
|
|
:type address: int
|
|
|
|
"""
|
|
|
|
self.logger.info("Erase user row")
|
|
|
|
|
|
|
|
# On this NVM version user row is implemented as FLASH
|
|
|
|
return self.erase_flash_page(self, address)
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("erase user row at address 0x%06X\n", address);
|
2021-12-18 15:47:37 +00:00
|
|
|
|
|
|
|
return nvm_erase_flash_page_V3(pgm, p, address);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode, uint8_t nvm_command);
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_flash_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_flash(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to flash (v3)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_nvm(address, data, use_word_access=True)
|
|
|
|
*/
|
|
|
|
return nvm_write_V3(pgm, p, address, buffer, size, USE_WORD_ACCESS, USE_DEFAULT_COMMAND);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_user_row_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_user_row(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes data to user row (v3)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
# On this NVM variant user row is implemented as FLASH
|
|
|
|
return self.write_nvm(address, data, use_word_access=True)
|
|
|
|
*/
|
|
|
|
return nvm_write_V3(pgm, p, address, buffer, size, USE_WORD_ACCESS, USE_DEFAULT_COMMAND);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_eeprom_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_eeprom(self, address, data):
|
|
|
|
"""
|
|
|
|
Write data to EEPROM (v3)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_nvm(address, data, use_word_access=False,
|
|
|
|
nvmcommand=constants.UPDI_V3_NVMCTRL_CTRLA_EEPROM_PAGE_ERASE_WRITE)
|
|
|
|
*/
|
|
|
|
return nvm_write_V3(pgm, p, address, buffer, size, DONT_USE_WORD_ACCESS, UPDI_V3_NVMCTRL_CTRLA_EEPROM_PAGE_ERASE_WRITE);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_fuse_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint8_t value) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def write_fuse(self, address, data):
|
|
|
|
"""
|
|
|
|
Writes one fuse value (v3)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
"""
|
|
|
|
return self.write_eeprom(address, data)
|
|
|
|
*/
|
|
|
|
unsigned char buffer[1];
|
|
|
|
buffer[0] = value;
|
|
|
|
return nvm_write_eeprom_V3(pgm, p, address, buffer, 1);
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
static int nvm_write_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer,
|
2021-12-18 15:47:37 +00:00
|
|
|
uint16_t size, access_mode mode, uint8_t nvm_command)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
def write_nvm(self, address, data, use_word_access, nvmcommand=constants.UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_WRITE):
|
|
|
|
"""
|
|
|
|
Writes a page of data to NVM (v3)
|
|
|
|
|
|
|
|
By default the PAGE_WRITE command is used, which
|
|
|
|
requires that the page is already erased.
|
|
|
|
By default word access is used (flash)
|
|
|
|
|
|
|
|
:param address: address to write to
|
|
|
|
:param data: data to write
|
|
|
|
:param use_word_access: write whole words?
|
|
|
|
:param nvmcommand: command to use for commit
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Check that NVM controller is ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready before page buffer clear")
|
|
|
|
|
|
|
|
# Clear the page buffer
|
|
|
|
self.logger.debug("Clear page buffer")
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_BUFFER_CLEAR)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready after page buffer clear")
|
|
|
|
|
|
|
|
# Load the page buffer by writing directly to location
|
|
|
|
if use_word_access:
|
|
|
|
self.readwrite.write_data_words(address, data)
|
|
|
|
else:
|
|
|
|
self.readwrite.write_data(address, data)
|
|
|
|
|
|
|
|
# Write the page to NVM, maybe erase first
|
|
|
|
self.logger.debug("Committing data")
|
|
|
|
self.execute_nvm_command(nvmcommand)
|
|
|
|
|
|
|
|
# Wait for NVM controller to be ready again
|
|
|
|
if not self.wait_nvm_ready():
|
|
|
|
raise PymcuprogError("Timeout waiting for NVM controller to be ready after page write")
|
|
|
|
|
|
|
|
# Remove command
|
|
|
|
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
|
|
|
*/
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("clear page buffer\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_BUFFER_CLEAR) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("clear page operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (mode == USE_WORD_ACCESS) {
|
|
|
|
if (updi_write_data_words(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data words operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (updi_write_data(pgm, address, buffer, size) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("write data operation failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("committing data\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
if (nvm_command == USE_DEFAULT_COMMAND) {
|
|
|
|
nvm_command = UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_WRITE;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, nvm_command) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("commit data command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("updi_nvm_wait_ready() failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("sending empty command failed\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_chip_erase_V0(pgm, p);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_chip_erase_V2(pgm, p);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_chip_erase_V3(pgm, p);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_erase_flash_page(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_erase_flash_page_V0(pgm, p, address);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_erase_flash_page_V2(pgm, p, address);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_erase_flash_page_V3(pgm, p, address);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_erase_eeprom(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_erase_eeprom_V0(pgm, p);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_erase_eeprom_V2(pgm, p);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_erase_eeprom_V3(pgm, p);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_erase_user_row(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_erase_user_row_V0(pgm, p, address, size);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_erase_user_row_V2(pgm, p, address, size);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_erase_user_row_V3(pgm, p, address, size);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_write_flash(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_write_flash_V0(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_write_flash_V2(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_write_flash_V3(pgm, p, address, buffer, size);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_write_user_row(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_write_user_row_V0(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_write_user_row_V2(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_write_user_row_V3(pgm, p, address, buffer, size);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_write_eeprom(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, unsigned char *buffer, uint16_t size) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_write_eeprom_V0(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_write_eeprom_V2(pgm, p, address, buffer, size);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_write_eeprom_V3(pgm, p, address, buffer, size);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_write_fuse(const PROGRAMMER *pgm, const AVRPART *p, uint32_t address, uint8_t value) {
|
2021-12-18 15:47:37 +00:00
|
|
|
switch(updi_get_nvm_mode(pgm))
|
|
|
|
{
|
|
|
|
case UPDI_NVM_MODE_V0:
|
|
|
|
return nvm_write_fuse_V0(pgm, p, address, value);
|
|
|
|
case UPDI_NVM_MODE_V2:
|
|
|
|
return nvm_write_fuse_V2(pgm, p, address, value);
|
|
|
|
case UPDI_NVM_MODE_V3:
|
|
|
|
return nvm_write_fuse_V3(pgm, p, address, value);
|
|
|
|
default:
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("invalid NVM Mode %d\n", updi_get_nvm_mode(pgm));
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_wait_ready(const PROGRAMMER *pgm, const AVRPART *p) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def wait_nvm_ready(self):
|
|
|
|
"""
|
|
|
|
Waits for the NVM controller to be ready
|
|
|
|
"""
|
|
|
|
timeout = Timeout(10000) # 10 sec timeout, just to be sure
|
|
|
|
|
|
|
|
self.logger.debug("Wait NVM ready")
|
|
|
|
while not timeout.expired():
|
|
|
|
status = self.readwrite.read_byte(self.device.nvmctrl_address + constants.UPDI_NVMCTRL_STATUS)
|
|
|
|
if status & (1 << constants.UPDI_NVM_STATUS_WRITE_ERROR):
|
|
|
|
self.logger.error("NVM error")
|
|
|
|
return False
|
|
|
|
|
|
|
|
if not status & ((1 << constants.UPDI_NVM_STATUS_EEPROM_BUSY) |
|
|
|
|
(1 << constants.UPDI_NVM_STATUS_FLASH_BUSY)):
|
|
|
|
return True
|
|
|
|
|
|
|
|
self.logger.error("Wait NVM ready timed out")
|
|
|
|
return False
|
|
|
|
*/
|
|
|
|
unsigned long start_time;
|
|
|
|
unsigned long current_time;
|
|
|
|
uint8_t status;
|
2022-11-25 22:09:02 +00:00
|
|
|
start_time = avr_ustimestamp();
|
2021-12-18 15:47:37 +00:00
|
|
|
do {
|
|
|
|
if (updi_read_byte(pgm, p->nvm_base + UPDI_NVMCTRL_STATUS, &status) >= 0) {
|
|
|
|
if (status & (1 << UPDI_NVM_STATUS_WRITE_ERROR)) {
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("unable to write NVM status\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!(status & ((1 << UPDI_NVM_STATUS_EEPROM_BUSY) |
|
|
|
|
(1 << UPDI_NVM_STATUS_FLASH_BUSY)))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2022-11-25 22:09:02 +00:00
|
|
|
current_time = avr_ustimestamp();
|
2021-12-18 15:47:37 +00:00
|
|
|
} while ((current_time - start_time) < 10000000);
|
|
|
|
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_error("wait NVM ready timed out\n");
|
2021-12-18 15:47:37 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Use const in PROGRAMMER function arguments where appropriate
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
2022-08-17 15:05:28 +00:00
|
|
|
int updi_nvm_command(const PROGRAMMER *pgm, const AVRPART *p, uint8_t command) {
|
2021-12-18 15:47:37 +00:00
|
|
|
/*
|
|
|
|
def execute_nvm_command(self, command):
|
|
|
|
"""
|
|
|
|
Executes an NVM COMMAND on the NVM CTRL
|
|
|
|
|
|
|
|
:param command: command to execute
|
|
|
|
"""
|
|
|
|
self.logger.debug("NVMCMD %d executing", command)
|
|
|
|
return self.readwrite.write_byte(self.device.nvmctrl_address + constants.UPDI_NVMCTRL_CTRLA, command)
|
|
|
|
*/
|
2022-10-17 14:44:55 +00:00
|
|
|
pmsg_debug("NVMCMD %d executing\n", command);
|
2021-12-18 15:47:37 +00:00
|
|
|
|
|
|
|
return updi_write_byte(pgm, p->nvm_base + UPDI_NVMCTRL_CTRLA, command);
|
|
|
|
}
|