First successful programming
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/branches/serialupdi@1516 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
8f67f9c50b
commit
c6902553be
|
@ -40,6 +40,11 @@
|
||||||
#include "updi_link.h"
|
#include "updi_link.h"
|
||||||
#include "updi_state.h"
|
#include "updi_state.h"
|
||||||
#include "updi_readwrite.h"
|
#include "updi_readwrite.h"
|
||||||
|
#include "updi_nvm.h"
|
||||||
|
#include "updi_constants.h"
|
||||||
|
|
||||||
|
static int serialupdi_enter_progmode(PROGRAMMER * pgm);
|
||||||
|
static int serialupdi_leave_progmode(PROGRAMMER * pgm);
|
||||||
|
|
||||||
static void serialupdi_setup(PROGRAMMER * pgm)
|
static void serialupdi_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
|
@ -64,7 +69,7 @@ static int serialupdi_open(PROGRAMMER * pgm, char * port)
|
||||||
return updi_link_open(pgm);
|
return updi_link_open(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_decode_sib(updi_sib_info * sib_info)
|
static int serialupdi_decode_sib(PROGRAMMER * pgm, updi_sib_info * sib_info)
|
||||||
{
|
{
|
||||||
char * str_ptr;
|
char * str_ptr;
|
||||||
|
|
||||||
|
@ -105,12 +110,18 @@ static int serialupdi_decode_sib(updi_sib_info * sib_info)
|
||||||
switch (sib_info->nvm_version) {
|
switch (sib_info->nvm_version) {
|
||||||
case '0':
|
case '0':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 0: 16-bit, page oriented write\n", progname);
|
avrdude_message(MSG_INFO, "%s: NVM type 0: 16-bit, page oriented write\n", progname);
|
||||||
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V0);
|
||||||
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 2: 24-bit, word oriented write\n", progname);
|
avrdude_message(MSG_INFO, "%s: NVM type 2: 24-bit, word oriented write\n", progname);
|
||||||
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V2);
|
||||||
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_24BIT);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 3: 16-bit, page oriented\n", progname);
|
avrdude_message(MSG_INFO, "%s: NVM type 3: 16-bit, page oriented\n", progname);
|
||||||
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V3);
|
||||||
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: Unsupported NVM type: %c, please update software\n", progname, sib_info->nvm_version);
|
avrdude_message(MSG_INFO, "%s: Unsupported NVM type: %c, please update software\n", progname, sib_info->nvm_version);
|
||||||
|
@ -121,9 +132,240 @@ static int serialupdi_decode_sib(updi_sib_info * sib_info)
|
||||||
|
|
||||||
static void serialupdi_close(PROGRAMMER * pgm)
|
static void serialupdi_close(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
|
if (serialupdi_leave_progmode(pgm) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Unable to leave NVM programming mode\n", progname);
|
||||||
|
}
|
||||||
updi_link_close(pgm);
|
updi_link_close(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
APPLY_RESET,
|
||||||
|
RELEASE_RESET
|
||||||
|
} reset_mode;
|
||||||
|
|
||||||
|
static int serialupdi_reset(PROGRAMMER * pgm, reset_mode mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
def reset(self, apply_reset):
|
||||||
|
"""
|
||||||
|
Applies or releases an UPDI reset condition
|
||||||
|
|
||||||
|
:param apply_reset: True to apply, False to release
|
||||||
|
"""
|
||||||
|
if apply_reset:
|
||||||
|
self.logger.info("Apply reset")
|
||||||
|
self.readwrite.write_cs(constants.UPDI_ASI_RESET_REQ, constants.UPDI_RESET_REQ_VALUE)
|
||||||
|
else:
|
||||||
|
self.logger.info("Release reset")
|
||||||
|
self.readwrite.write_cs(constants.UPDI_ASI_RESET_REQ, 0x00)
|
||||||
|
*/
|
||||||
|
switch (mode) {
|
||||||
|
case APPLY_RESET:
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Sending reset request\n", progname);
|
||||||
|
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, UPDI_RESET_REQ_VALUE);
|
||||||
|
case RELEASE_RESET:
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Sending release reset request\n", progname);
|
||||||
|
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, 0x00);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_wait_for_unlock(PROGRAMMER * pgm, unsigned int ms) {
|
||||||
|
/*
|
||||||
|
def wait_unlocked(self, timeout_ms):
|
||||||
|
"""
|
||||||
|
Waits for the device to be unlocked.
|
||||||
|
All devices boot up as locked until proven otherwise
|
||||||
|
|
||||||
|
:param timeout_ms: number of milliseconds to wait
|
||||||
|
"""
|
||||||
|
timeout = Timeout(timeout_ms)
|
||||||
|
|
||||||
|
while not timeout.expired():
|
||||||
|
if not self.readwrite.read_cs(constants.UPDI_ASI_SYS_STATUS) & (
|
||||||
|
1 << constants.UPDI_ASI_SYS_STATUS_LOCKSTATUS):
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.logger.error("Timeout waiting for device to unlock")
|
||||||
|
return False
|
||||||
|
*/
|
||||||
|
unsigned long start_time;
|
||||||
|
unsigned long current_time;
|
||||||
|
struct timeval tv;
|
||||||
|
uint8_t status;
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
|
do {
|
||||||
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) {
|
||||||
|
if (!(status & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS))) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gettimeofday (&tv, NULL);
|
||||||
|
current_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
|
} while ((current_time - start_time) < (ms * 1000));
|
||||||
|
|
||||||
|
avrdude_message(MSG_INFO, "%s: Timeout waiting for device to unlock\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_in_prog_mode(PROGRAMMER * pgm, uint8_t * in_prog_mode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
def in_prog_mode(self):
|
||||||
|
"""
|
||||||
|
Checks whether the NVM PROG flag is up
|
||||||
|
"""
|
||||||
|
if self.readwrite.read_cs(constants.UPDI_ASI_SYS_STATUS) & (1 << constants.UPDI_ASI_SYS_STATUS_NVMPROG):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
*/
|
||||||
|
uint8_t value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Read CS operation failed\n", progname);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value & (1 << UPDI_ASI_SYS_STATUS_NVMPROG)) {
|
||||||
|
*in_prog_mode = 1;
|
||||||
|
} else {
|
||||||
|
*in_prog_mode = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_enter_progmode(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
def enter_progmode(self):
|
||||||
|
"""
|
||||||
|
Enters into NVM programming mode
|
||||||
|
"""
|
||||||
|
# First check if NVM is already enabled
|
||||||
|
if self.in_prog_mode():
|
||||||
|
self.logger.info("Already in NVM programming mode")
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.logger.info("Entering NVM programming mode")
|
||||||
|
|
||||||
|
# Put in the key
|
||||||
|
self.readwrite.write_key(constants.UPDI_KEY_64, constants.UPDI_KEY_NVM)
|
||||||
|
|
||||||
|
# Check key status
|
||||||
|
key_status = self.readwrite.read_cs(constants.UPDI_ASI_KEY_STATUS)
|
||||||
|
self.logger.debug("Key status = 0x%02X", key_status)
|
||||||
|
|
||||||
|
if not key_status & (1 << constants.UPDI_ASI_KEY_STATUS_NVMPROG):
|
||||||
|
self.logger.error("Key status = 0x%02X", key_status)
|
||||||
|
raise IOError("Key not accepted")
|
||||||
|
|
||||||
|
# Toggle reset
|
||||||
|
self.reset(apply_reset=True)
|
||||||
|
self.reset(apply_reset=False)
|
||||||
|
|
||||||
|
# And wait for unlock
|
||||||
|
if not self.wait_unlocked(100):
|
||||||
|
raise IOError("Failed to enter NVM programming mode: device is locked")
|
||||||
|
|
||||||
|
# Check for NVMPROG flag
|
||||||
|
if not self.in_prog_mode():
|
||||||
|
raise IOError("Failed to enter NVM programming mode")
|
||||||
|
|
||||||
|
self.logger.debug("Now in NVM programming mode")
|
||||||
|
return True
|
||||||
|
*/
|
||||||
|
uint8_t in_prog_mode;
|
||||||
|
unsigned char buffer[8];
|
||||||
|
uint8_t key_status;
|
||||||
|
|
||||||
|
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Checking UPDI NVM prog mode failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (in_prog_mode) {
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Already in prog mode\n", progname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
avrdude_message(MSG_INFO, "%s: Entering NVM programming mode\n", progname);
|
||||||
|
|
||||||
|
memcpy(buffer, UPDI_KEY_NVM, sizeof(buffer));
|
||||||
|
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Writing NVM KEY failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Checking KEY status failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Key status: 0x%02X\n", progname, key_status);
|
||||||
|
|
||||||
|
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_NVMPROG))) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Key was not accepted\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_wait_for_unlock(pgm, 100) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Failed to enter NVM programming mode: device is locked\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Checking UPDI NVM prog mode failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_prog_mode) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Failed to enter NVM programming mode\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Entered NVM programming mode\n", progname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_leave_progmode(PROGRAMMER * pgm)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
def leave_progmode(self):
|
||||||
|
"""
|
||||||
|
Disables UPDI which releases any keys enabled
|
||||||
|
"""
|
||||||
|
self.logger.info("Leaving NVM programming mode")
|
||||||
|
self.reset(apply_reset=True)
|
||||||
|
self.reset(apply_reset=False)
|
||||||
|
self.readwrite.write_cs(constants.UPDI_CS_CTRLB,
|
||||||
|
(1 << constants.UPDI_CTRLB_UPDIDIS_BIT) | (1 << constants.UPDI_CTRLB_CCDETDIS_BIT))
|
||||||
|
*/
|
||||||
|
avrdude_message(MSG_INFO, "%s: Leaving NVM programming mode\n", progname);
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updi_write_cs(pgm, UPDI_CS_CTRLB, (1 << UPDI_CTRLB_UPDIDIS_BIT) | (1 << UPDI_CTRLB_CCDETDIS_BIT));
|
||||||
|
}
|
||||||
|
|
||||||
static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
{
|
{
|
||||||
updi_sib_info * sib_info = updi_get_sib_info(pgm);
|
updi_sib_info * sib_info = updi_get_sib_info(pgm);
|
||||||
|
@ -137,15 +379,13 @@ static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
avrdude_message(MSG_INFO, "%s: Read SIB operation failed\n", progname);
|
avrdude_message(MSG_INFO, "%s: Read SIB operation failed\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (serialupdi_decode_sib(sib_info) < 0) {
|
if (serialupdi_decode_sib(pgm, sib_info) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Decode SIB_INFO failed\n", progname);
|
avrdude_message(MSG_INFO, "%s: Decode SIB_INFO failed\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
updi_set_nvm_mode(pgm, sib_info->nvm_version);
|
if (serialupdi_enter_progmode(pgm) < 0) {
|
||||||
if (sib_info->nvm_version == '2') {
|
avrdude_message(MSG_INFO, "%s: Unable to enter NVM programming mode\n", progname);
|
||||||
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_24BIT);
|
return -1;
|
||||||
} else {
|
|
||||||
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -185,19 +425,19 @@ static int serialupdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
|
||||||
{
|
|
||||||
avrdude_message(MSG_INFO, "%s: error: chip erase not implemented yet\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int serialupdi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int serialupdi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
return updi_read_byte(pgm, mem->offset + addr, value);
|
return updi_read_byte(pgm, mem->offset + addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int serialupdi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
unsigned long addr, unsigned char value)
|
||||||
|
{
|
||||||
|
return updi_write_byte(pgm, mem->offset + addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
|
@ -208,7 +448,8 @@ static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
int read_bytes = 0;
|
int read_bytes = 0;
|
||||||
int rc;
|
int rc;
|
||||||
while (remaining_bytes > 0) {
|
while (remaining_bytes > 0) {
|
||||||
rc = updi_read_data(pgm, m->offset + read_offset, m->buf + read_offset, m->readsize);
|
rc = updi_read_data(pgm, m->offset + read_offset, m->buf + read_offset,
|
||||||
|
remaining_bytes > m->readsize ? m->readsize : remaining_bytes);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Paged load operation failed\n", progname);
|
avrdude_message(MSG_INFO, "%s: Paged load operation failed\n", progname);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -228,11 +469,133 @@ static int serialupdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: error: paged write not implemented yet\n",
|
int rc;
|
||||||
|
|
||||||
|
if (serialupdi_enter_progmode(pgm) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Unable to enter NVM programming mode\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_bytes > m->page_size) {
|
||||||
|
unsigned int write_offset = addr;
|
||||||
|
unsigned int remaining_bytes = n_bytes;
|
||||||
|
int write_bytes = 0;
|
||||||
|
while (remaining_bytes > 0) {
|
||||||
|
|
||||||
|
if (strcmp(m->desc, "eeprom")==0) {
|
||||||
|
rc = updi_nvm_write_eeprom(pgm, p, m->offset + write_offset, m->buf + write_offset,
|
||||||
|
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
||||||
|
} else if (strcmp(m->desc, "flash")==0) {
|
||||||
|
rc = updi_nvm_write_flash(pgm, p, m->offset + write_offset, m->buf + write_offset,
|
||||||
|
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Paged write operation failed\n", progname);
|
||||||
|
return rc;
|
||||||
|
} else {
|
||||||
|
write_bytes+=rc;
|
||||||
|
write_offset+=m->page_size;
|
||||||
|
remaining_bytes-=m->page_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return write_bytes;
|
||||||
|
} else {
|
||||||
|
if (strcmp(m->desc, "eeprom")==0) {
|
||||||
|
rc = updi_nvm_write_eeprom(pgm, p, m->offset+addr, m->buf+addr, n_bytes);
|
||||||
|
} else if (strcmp(m->desc, "flash")==0) {
|
||||||
|
rc = updi_nvm_write_flash(pgm, p, m->offset+addr, m->buf+addr, n_bytes);
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_unlock(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
def unlock(self):
|
||||||
|
"""
|
||||||
|
Unlock by chip erase
|
||||||
|
"""
|
||||||
|
# Put in the key
|
||||||
|
self.readwrite.write_key(constants.UPDI_KEY_64, constants.UPDI_KEY_CHIPERASE)
|
||||||
|
|
||||||
|
# Check key status
|
||||||
|
key_status = self.readwrite.read_cs(constants.UPDI_ASI_KEY_STATUS)
|
||||||
|
self.logger.debug("Key status = 0x%02X", key_status)
|
||||||
|
|
||||||
|
if not key_status & (1 << constants.UPDI_ASI_KEY_STATUS_CHIPERASE):
|
||||||
|
raise PymcuprogError("Key not accepted")
|
||||||
|
|
||||||
|
# Toggle reset
|
||||||
|
self.reset(apply_reset=True)
|
||||||
|
self.reset(apply_reset=False)
|
||||||
|
|
||||||
|
# And wait for unlock
|
||||||
|
if not self.wait_unlocked(500):
|
||||||
|
raise PymcuprogError("Failed to chip erase using key")
|
||||||
|
*/
|
||||||
|
unsigned char buffer[8];
|
||||||
|
uint8_t key_status;
|
||||||
|
|
||||||
|
memcpy(buffer, UPDI_KEY_CHIPERASE, sizeof(buffer));
|
||||||
|
|
||||||
|
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Writing NVM KEY failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Checking KEY status failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
avrdude_message(MSG_DEBUG, "%s: Key status: 0x%02X\n", progname, key_status);
|
||||||
|
|
||||||
|
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_CHIPERASE))) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Key not accepted\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialupdi_wait_for_unlock(pgm, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
{
|
||||||
|
if (serialupdi_enter_progmode(pgm) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Unable to enter NVM programming mode\n", progname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updi_nvm_chip_erase(pgm, p) < 0) {
|
||||||
|
avrdude_message(MSG_INFO, "%s: Chip erase failed, device might be locked, attempting unlock now\n", progname);
|
||||||
|
return serialupdi_unlock(pgm, p);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int serialupdi_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
unsigned int baseaddr)
|
||||||
|
{
|
||||||
|
avrdude_message(MSG_INFO, "%s: error: page erase not implemented yet\n",
|
||||||
progname);
|
progname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void serialupdi_initpgm(PROGRAMMER * pgm)
|
void serialupdi_initpgm(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
strcpy(pgm->type, "serialupdi");
|
strcpy(pgm->type, "serialupdi");
|
||||||
|
@ -251,14 +614,16 @@ void serialupdi_initpgm(PROGRAMMER * pgm)
|
||||||
pgm->open = serialupdi_open;
|
pgm->open = serialupdi_open;
|
||||||
pgm->close = serialupdi_close;
|
pgm->close = serialupdi_close;
|
||||||
pgm->read_byte = serialupdi_read_byte;
|
pgm->read_byte = serialupdi_read_byte;
|
||||||
pgm->write_byte = avr_write_byte_default;
|
pgm->write_byte = serialupdi_write_byte;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* optional functions
|
* optional functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
pgm->unlock = serialupdi_unlock;
|
||||||
pgm->paged_write = serialupdi_paged_write;
|
pgm->paged_write = serialupdi_paged_write;
|
||||||
pgm->paged_load = serialupdi_paged_load;
|
pgm->paged_load = serialupdi_paged_load;
|
||||||
|
pgm->page_erase = serialupdi_page_erase;
|
||||||
pgm->setup = serialupdi_setup;
|
pgm->setup = serialupdi_setup;
|
||||||
pgm->teardown = serialupdi_teardown;
|
pgm->teardown = serialupdi_teardown;
|
||||||
|
|
||||||
|
|
|
@ -1239,10 +1239,7 @@ int updi_nvm_wait_ready(PROGRAMMER * pgm, AVRPART *p)
|
||||||
gettimeofday (&tv, NULL);
|
gettimeofday (&tv, NULL);
|
||||||
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
do {
|
do {
|
||||||
if (updi_read_byte(pgm, p->nvm_base + UPDI_NVMCTRL_STATUS, &status) < 0){
|
if (updi_read_byte(pgm, p->nvm_base + UPDI_NVMCTRL_STATUS, &status) >= 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Status read operation failed\n", progname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (status & (1 << UPDI_NVM_STATUS_WRITE_ERROR)) {
|
if (status & (1 << UPDI_NVM_STATUS_WRITE_ERROR)) {
|
||||||
avrdude_message(MSG_INFO, "%s: NVM error\n", progname);
|
avrdude_message(MSG_INFO, "%s: NVM error\n", progname);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1251,6 +1248,7 @@ int updi_nvm_wait_ready(PROGRAMMER * pgm, AVRPART *p)
|
||||||
(1 << UPDI_NVM_STATUS_FLASH_BUSY)))) {
|
(1 << UPDI_NVM_STATUS_FLASH_BUSY)))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
gettimeofday (&tv, NULL);
|
gettimeofday (&tv, NULL);
|
||||||
current_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
current_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
} while ((current_time - start_time) < 10000000);
|
} while ((current_time - start_time) < 10000000);
|
||||||
|
|
Loading…
Reference in New Issue