mirror of
https://github.com/avrdudes/avrdude.git
synced 2026-09-22 17:16:24 +03:00
Updated NVM controller code to latest pymcuprog
This commit is contained in:
@@ -34,7 +34,6 @@
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
#include "updi_nvm.h"
|
||||
#include "updi_nvm_v0.h"
|
||||
#include "updi_state.h"
|
||||
#include "updi_constants.h"
|
||||
@@ -62,9 +61,9 @@
|
||||
#define UPDI_V0_NVMCTRL_CTRLA_WRITE_FUSE 0x07
|
||||
|
||||
// NVMCTRL STATUS
|
||||
#define UPDI_V0_NVM_STATUS_WRITE_ERROR 2
|
||||
#define UPDI_V0_NVM_STATUS_EEPROM_BUSY 1
|
||||
#define UPDI_V0_NVM_STATUS_FLASH_BUSY 0
|
||||
#define UPDI_V0_NVM_STATUS_WRITE_ERROR_BIT 2
|
||||
#define UPDI_V0_NVM_STATUS_EEPROM_BUSY_BIT 1
|
||||
#define UPDI_V0_NVM_STATUS_FLASH_BUSY_BIT 0
|
||||
|
||||
#define USE_DEFAULT_COMMAND 0xFF
|
||||
|
||||
@@ -100,16 +99,16 @@ int updi_nvm_chip_erase_V0(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
return True
|
||||
*/
|
||||
pmsg_debug("Chip erase using NVM CTRL\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
pmsg_error("UPDI chip erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -142,8 +141,8 @@ int updi_nvm_erase_flash_page_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
*/
|
||||
unsigned char data[1];
|
||||
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
data[0] = 0xFF;
|
||||
@@ -151,12 +150,12 @@ int updi_nvm_erase_flash_page_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
pmsg_error("dummy write operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
||||
pmsg_error("UPDI flash page erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -182,16 +181,16 @@ int updi_nvm_erase_eeprom_V0(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
raise IOError("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
||||
*/
|
||||
pmsg_debug("erase EEPROM\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_EEPROM) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_EEPROM) < 0) {
|
||||
pmsg_error("UPDI EEPROM erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -227,8 +226,8 @@ int updi_nvm_erase_user_row_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t
|
||||
uint16_t offset;
|
||||
unsigned char data[1];
|
||||
pmsg_debug("erase user row\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
data[0]=0xFF;
|
||||
@@ -239,12 +238,12 @@ int updi_nvm_erase_user_row_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_ERASE_PAGE) < 0) {
|
||||
pmsg_error("erase page operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -327,8 +326,8 @@ int updi_nvm_write_fuse_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t add
|
||||
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) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("load NVM address\n");
|
||||
@@ -346,12 +345,12 @@ int updi_nvm_write_fuse_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t add
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("execute fuse write\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_WRITE_FUSE) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_WRITE_FUSE) < 0) {
|
||||
pmsg_error("write fuse operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -401,17 +400,17 @@ static int nvm_write_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
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) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("clear page buffer\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V0_NVMCTRL_CTRLA_PAGE_BUFFER_CLR) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, UPDI_V0_NVMCTRL_CTRLA_PAGE_BUFFER_CLR) < 0) {
|
||||
pmsg_error("clear page operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (mode == USE_WORD_ACCESS) {
|
||||
@@ -429,12 +428,12 @@ static int nvm_write_V0(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
if (nvm_command == USE_DEFAULT_COMMAND) {
|
||||
nvm_command = UPDI_V0_NVMCTRL_CTRLA_WRITE_PAGE;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, nvm_command) < 0) {
|
||||
if (updi_nvm_command_V0(pgm, p, nvm_command) < 0) {
|
||||
pmsg_error("commit data command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V0(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V0() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -468,12 +467,12 @@ int updi_nvm_wait_ready_V0(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
start_time = avr_ustimestamp();
|
||||
do {
|
||||
if (updi_read_byte(pgm, p->nvm_base + UPDI_V0_NVMCTRL_STATUS, &status) >= 0) {
|
||||
if (status & (1 << UPDI_V0_NVM_STATUS_WRITE_ERROR)) {
|
||||
if (status & (1 << UPDI_V0_NVM_STATUS_WRITE_ERROR_BIT)) {
|
||||
pmsg_error("unable to write NVM status\n");
|
||||
return -1;
|
||||
}
|
||||
if (!(status & ((1 << UPDI_V0_NVM_STATUS_EEPROM_BUSY) |
|
||||
(1 << UPDI_V0_NVM_STATUS_FLASH_BUSY)))) {
|
||||
if (!(status & ((1 << UPDI_V0_NVM_STATUS_EEPROM_BUSY_BIT) |
|
||||
(1 << UPDI_V0_NVM_STATUS_FLASH_BUSY_BIT)))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
#include "updi_nvm.h"
|
||||
#include "updi_nvm_v2.h"
|
||||
#include "updi_state.h"
|
||||
#include "updi_constants.h"
|
||||
@@ -55,16 +54,20 @@
|
||||
|
||||
// NVMCTRL v2 CTRLA
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_NOCMD 0x00
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_NOOP 0x01
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE 0x02
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_FLASH_PAGE_ERASE 0x08
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_EEPROM_WRITE 0x12
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE 0x13
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_EEPROM_BYTE_ERASE 0x18
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE 0x20
|
||||
#define UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE 0x30
|
||||
|
||||
// NVMCTRL STATUS
|
||||
#define UPDI_V2_NVM_STATUS_WRITE_ERROR 2
|
||||
#define UPDI_V2_NVM_STATUS_EEPROM_BUSY 1
|
||||
#define UPDI_V2_NVM_STATUS_FLASH_BUSY 0
|
||||
#define UPDI_V2_NVM_STATUS_WRITE_ERROR_MASK 0x30
|
||||
#define UPDI_V2_NVM_STATUS_WRITE_ERROR_BIT 4
|
||||
#define UPDI_V2_NVM_STATUS_EEPROM_BUSY_BIT 1
|
||||
#define UPDI_V2_NVM_STATUS_FLASH_BUSY_BIT 0
|
||||
|
||||
#define USE_DEFAULT_COMMAND 0xFF
|
||||
|
||||
@@ -79,35 +82,45 @@ int updi_nvm_chip_erase_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
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
|
||||
|
||||
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")
|
||||
self.logger.debug("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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready before chip erase")
|
||||
|
||||
# Erase
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE)
|
||||
self.execute_nvm_command(self.NVMCMD_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")
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
return True
|
||||
# Remove command from NVM controller
|
||||
self.logger.debug("Clear NVM command")
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
if not status:
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after chip erase")
|
||||
*/
|
||||
int status;
|
||||
pmsg_debug("chip erase using NVM CTRL\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V2(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
pmsg_error("chip erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V2(pgm, p);
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("command buffer erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -117,35 +130,41 @@ int updi_nvm_erase_flash_page_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
/*
|
||||
def erase_flash_page(self, address):
|
||||
"""
|
||||
Erasing single flash page using the NVM controller (v1)
|
||||
Erasing single flash page using the NVM controller
|
||||
|
||||
:param address: Start address of page to erase
|
||||
:type address: int
|
||||
"""
|
||||
self.logger.info("Erase flash page at address 0x%08X", address)
|
||||
self.logger.debug("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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("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)
|
||||
self.execute_nvm_command(self.NVMCMD_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")
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command from NVM controller
|
||||
self.logger.debug("Clear NVM command")
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
if not status:
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after flash page erase")
|
||||
*/
|
||||
unsigned char data[1];
|
||||
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
int status;
|
||||
pmsg_debug("erase flash page at address 0x%08X\n", address);
|
||||
if (updi_nvm_wait_ready_V2(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
||||
pmsg_error("flash page erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
data[0] = 0xFF;
|
||||
@@ -153,12 +172,14 @@ int updi_nvm_erase_flash_page_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
pmsg_error("dummy write operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
||||
pmsg_error("flash page erase command failed\n");
|
||||
status = updi_nvm_wait_ready_V2(pgm, p);
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("command buffer erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -168,41 +189,44 @@ int updi_nvm_erase_eeprom_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
/*
|
||||
def erase_eeprom(self):
|
||||
"""
|
||||
Erase EEPROM memory only (v1)
|
||||
Erase EEPROM memory only
|
||||
"""
|
||||
self.logger.info("Erase EEPROM")
|
||||
self.logger.debug("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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready before EEPROM erase")
|
||||
|
||||
# Erase
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE)
|
||||
self.execute_nvm_command(self.NVMCMD_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")
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command from NVM controller
|
||||
self.logger.debug("Clear NVM command")
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
if not status:
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
||||
*/
|
||||
int status;
|
||||
pmsg_debug("erase EEPROM\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V2(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
||||
pmsg_error("EEPROM erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V2(pgm, p);
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("command buffer erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -264,35 +288,39 @@ int updi_nvm_write_eeprom_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t a
|
||||
Writes data to NVM (EEPROM)
|
||||
|
||||
:param address: address to write to
|
||||
:type address: int
|
||||
:param data: data to write
|
||||
:type data: list of bytes
|
||||
"""
|
||||
nvm_command = constants.UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE
|
||||
nvm_command = self.NVMCMD_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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM ready before command write")
|
||||
|
||||
# Write the command to the NVM controller
|
||||
self.logger.info("NVM EEPROM erase/write command")
|
||||
self.logger.debug("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")
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command from NVM controller
|
||||
self.logger.info("Clear NVM command")
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
||||
self.logger.debug("Clear NVM command")
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
if not status:
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM ready after data write")
|
||||
*/
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
int status;
|
||||
if (updi_nvm_wait_ready_V2(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("NVM EEPROM erase/write command\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE) < 0) {
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_EEPROM_ERASE_WRITE) < 0) {
|
||||
pmsg_error("EEPROM erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -300,13 +328,14 @@ int updi_nvm_write_eeprom_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t a
|
||||
pmsg_error("write data operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V2(pgm, p);
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("command buffer erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("clear NVM command failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -333,23 +362,29 @@ static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
uint16_t size, access_mode mode)
|
||||
{
|
||||
/*
|
||||
def write_nvm(self, address, data, use_word_access):
|
||||
def write_nvm(self, address, data, use_word_access=True):
|
||||
"""
|
||||
Writes data to NVM (version 1)
|
||||
Writes data to NVM.
|
||||
|
||||
This version of the NVM block has no page buffer, so words are written directly.
|
||||
|
||||
:param address: address to write to
|
||||
:type address: int
|
||||
:param data: data to write
|
||||
:param use_word_access: write in whole words?
|
||||
:type data: list of bytes
|
||||
:param use_word_access: True for 16-bit writes (eg: flash)
|
||||
:type use_word_access: bool, defaults to True
|
||||
:raises: PymcuprogSerialUpdiNvmTimeout if a timeout occurred
|
||||
:raises: PymcuprogSerialUpdiNvmError if an error condition is encountered
|
||||
"""
|
||||
nvm_command = constants.UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE
|
||||
nvm_command = self.NVMCMD_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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("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.logger.debug("NVM write command")
|
||||
self.execute_nvm_command(nvm_command)
|
||||
|
||||
# Write the data
|
||||
@@ -359,19 +394,21 @@ static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
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")
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command from NVM controller
|
||||
self.logger.info("Clear NVM command")
|
||||
self.execute_nvm_command(constants.UPDI_V2_NVMCTRL_CTRLA_NOCMD)
|
||||
self.logger.debug("Clear NVM command")
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
if not status:
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after data write")
|
||||
*/
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
int status;
|
||||
if (updi_nvm_wait_ready_V2(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("NVM write command\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE) < 0) {
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_FLASH_WRITE) < 0) {
|
||||
pmsg_error("clear page operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -386,13 +423,14 @@ static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("wait for ready chip failed\n");
|
||||
status = updi_nvm_wait_ready_V2(pgm, p);
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command_V2(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("command buffer erase failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("clear NVM command\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V2_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("clear NVM command failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V2() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -400,21 +438,26 @@ static int nvm_write_V2(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
|
||||
int updi_nvm_wait_ready_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
/*
|
||||
def wait_nvm_ready(self):
|
||||
def wait_nvm_ready(self, timeout_ms=100):
|
||||
"""
|
||||
Waits for the NVM controller to be ready
|
||||
|
||||
:param timeout_ms: Timeout period in milliseconds
|
||||
:type timeout_ms: int, defaults to 100
|
||||
:returns: True if 'ready', False if timeout occurred before ready
|
||||
:rtype: bool
|
||||
:raises: PymcuprogSerialUpdiNvmError if an error condition is encountered
|
||||
"""
|
||||
timeout = Timeout(10000) # 10 sec timeout, just to be sure
|
||||
timeout = Timeout(timeout_ms)
|
||||
|
||||
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_V0_NVM_STATUS_WRITE_ERROR):
|
||||
self.logger.error("NVM error")
|
||||
return False
|
||||
status = self.readwrite.read_byte(self.device.nvmctrl_address + self.NVMCTRL_STATUS)
|
||||
if status & self.STATUS_WRITE_ERROR_bm:
|
||||
self.logger.error("NVM error (%d)", status >> self.STATUS_WRITE_ERROR_bp)
|
||||
raise PymcuprogSerialUpdiNvmError(msg="NVM error", code=(status >> self.STATUS_WRITE_ERROR_bp))
|
||||
|
||||
if not status & ((1 << constants.UPDI_NVM_STATUS_EEPROM_BUSY) |
|
||||
(1 << constants.UPDI_NVM_STATUS_FLASH_BUSY)):
|
||||
if not status & ((1 << self.STATUS_EEPROM_BUSY_bp) | (1 << self.STATUS_FLASH_BUSY_bp)):
|
||||
return True
|
||||
|
||||
self.logger.error("Wait NVM ready timed out")
|
||||
@@ -426,12 +469,12 @@ int updi_nvm_wait_ready_V2(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
start_time = avr_ustimestamp();
|
||||
do {
|
||||
if (updi_read_byte(pgm, p->nvm_base + UPDI_V2_NVMCTRL_STATUS, &status) >= 0) {
|
||||
if (status & (1 << UPDI_V2_NVM_STATUS_WRITE_ERROR)) {
|
||||
pmsg_error("unable to write NVM status\n");
|
||||
if (status & UPDI_V2_NVM_STATUS_WRITE_ERROR_MASK) {
|
||||
pmsg_error("unable to write NVM status, error %d\n", status >> UPDI_V2_NVM_STATUS_WRITE_ERROR_BIT);
|
||||
return -1;
|
||||
}
|
||||
if (!(status & ((1 << UPDI_V2_NVM_STATUS_EEPROM_BUSY) |
|
||||
(1 << UPDI_V2_NVM_STATUS_FLASH_BUSY)))) {
|
||||
if (!(status & ((1 << UPDI_V2_NVM_STATUS_EEPROM_BUSY_BIT) |
|
||||
(1 << UPDI_V2_NVM_STATUS_FLASH_BUSY_BIT)))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
#include "updi_nvm.h"
|
||||
#include "updi_nvm_v3.h"
|
||||
#include "updi_state.h"
|
||||
#include "updi_constants.h"
|
||||
@@ -68,9 +67,10 @@
|
||||
#define UPDI_V3_NVMCTRL_CTRLA_EEPROM_ERASE 0x30
|
||||
|
||||
// NVMCTRL STATUS
|
||||
#define UPDI_V3_NVM_STATUS_WRITE_ERROR 2
|
||||
#define UPDI_V3_NVM_STATUS_EEPROM_BUSY 1
|
||||
#define UPDI_V3_NVM_STATUS_FLASH_BUSY 0
|
||||
#define UPDI_V3_NVM_STATUS_WRITE_ERROR_MASK 0x70
|
||||
#define UPDI_V3_NVM_STATUS_WRITE_ERROR_BIT 2
|
||||
#define UPDI_V3_NVM_STATUS_EEPROM_BUSY_BIT 1
|
||||
#define UPDI_V3_NVM_STATUS_FLASH_BUSY_BIT 0
|
||||
|
||||
#define USE_DEFAULT_COMMAND 0xFF
|
||||
|
||||
@@ -86,44 +86,43 @@ int updi_nvm_chip_erase_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
"""
|
||||
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
|
||||
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")
|
||||
self.logger.debug("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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready before chip erase")
|
||||
|
||||
# Erase
|
||||
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_CHIP_ERASE)
|
||||
self.execute_nvm_command(self.NVMCMD_CHIP_ERASE)
|
||||
|
||||
# And wait for it
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command
|
||||
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
|
||||
if not status:
|
||||
raise IOError("Timeout waiting for NVM controller to be ready after chip erase")
|
||||
|
||||
return True
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after chip erase")
|
||||
*/
|
||||
int status;
|
||||
pmsg_debug("Chip erase using NVM CTRL\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_CHIP_ERASE) < 0) {
|
||||
pmsg_error("chip erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V3(pgm, p);
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -133,36 +132,37 @@ int updi_nvm_erase_flash_page_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
/*
|
||||
def erase_flash_page(self, address):
|
||||
"""
|
||||
Erasing single flash page using the NVM controller (v3)
|
||||
Erasing single flash page using the NVM controller
|
||||
|
||||
:param address: Start address of page to erase
|
||||
:type address: int
|
||||
"""
|
||||
self.logger.info("Erase flash page at address 0x%08X", address)
|
||||
self.logger.debug("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")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("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)
|
||||
self.execute_nvm_command(self.NVMCMD_FLASH_PAGE_ERASE)
|
||||
|
||||
# And wait for it
|
||||
status = self.wait_nvm_ready()
|
||||
|
||||
# Remove command
|
||||
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
||||
self.execute_nvm_command(self.NVMCMD_NOCMD)
|
||||
|
||||
if not status:
|
||||
raise IOError("Timeout waiting for NVM controller to be ready after flash page erase")
|
||||
raise PymcuprogSerialUpdiNvmTimeout("Timeout waiting for NVM controller to be ready after flash page erase")
|
||||
*/
|
||||
int status;
|
||||
unsigned char data[1];
|
||||
pmsg_debug("erase flash page at address 0x%06X\n", address);
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
data[0] = 0xFF;
|
||||
@@ -170,12 +170,17 @@ int updi_nvm_erase_flash_page_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32
|
||||
pmsg_error("dummy write operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_ERASE) < 0) {
|
||||
pmsg_error("flash page erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V3(pgm, p);
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -205,21 +210,23 @@ int updi_nvm_erase_eeprom_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
if not status:
|
||||
raise IOError("Timeout waiting for NVM controller to be ready after EEPROM erase")
|
||||
*/
|
||||
int status;
|
||||
pmsg_debug("erase EEPROM\n");
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_EEPROM_ERASE) < 0) {
|
||||
pmsg_error("EEPROM erase command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
status = updi_nvm_wait_ready_V3(pgm, p);
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
if (status < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -354,17 +361,17 @@ static int nvm_write_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
# Remove command
|
||||
self.execute_nvm_command(constants.UPDI_V3_NVMCTRL_CTRLA_NOCMD)
|
||||
*/
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("clear page buffer\n");
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_BUFFER_CLEAR) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_BUFFER_CLEAR) < 0) {
|
||||
pmsg_error("clear page operation failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (mode == USE_WORD_ACCESS) {
|
||||
@@ -382,15 +389,15 @@ static int nvm_write_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
if (nvm_command == USE_DEFAULT_COMMAND) {
|
||||
nvm_command = UPDI_V3_NVMCTRL_CTRLA_FLASH_PAGE_WRITE;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, nvm_command) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, nvm_command) < 0) {
|
||||
pmsg_error("commit data command failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_wait_ready(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready() failed\n");
|
||||
if (updi_nvm_wait_ready_V3(pgm, p) < 0) {
|
||||
pmsg_error("updi_nvm_wait_ready_V3() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (updi_nvm_command(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
if (updi_nvm_command_V3(pgm, p, UPDI_V3_NVMCTRL_CTRLA_NOCMD) < 0) {
|
||||
pmsg_error("sending empty command failed\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -400,21 +407,26 @@ static int nvm_write_V3(const PROGRAMMER *pgm, const AVRPART *p, uint32_t addres
|
||||
|
||||
int updi_nvm_wait_ready_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
/*
|
||||
def wait_nvm_ready(self):
|
||||
def wait_nvm_ready(self, timeout_ms=100):
|
||||
"""
|
||||
Waits for the NVM controller to be ready
|
||||
|
||||
:param timeout_ms: Timeout period in milliseconds
|
||||
:type timeout_ms: int, defaults to 100
|
||||
:returns: True if 'ready', False if timeout occurred before ready
|
||||
:rtype: bool
|
||||
:raises: PymcuprogSerialUpdiNvmError if an error condition is encountered
|
||||
"""
|
||||
timeout = Timeout(10000) # 10 sec timeout, just to be sure
|
||||
timeout = Timeout(timeout_ms)
|
||||
|
||||
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_V0_NVM_STATUS_WRITE_ERROR):
|
||||
self.logger.error("NVM error")
|
||||
return False
|
||||
status = self.readwrite.read_byte(self.device.nvmctrl_address + self.NVMCTRL_STATUS)
|
||||
if status & self.STATUS_WRITE_ERROR_bm:
|
||||
self.logger.error("NVM error (%d)", status >> self.STATUS_WRITE_ERROR_bp)
|
||||
raise PymcuprogSerialUpdiNvmError(msg="NVM error", code=(status >> self.STATUS_WRITE_ERROR_bp))
|
||||
|
||||
if not status & ((1 << constants.UPDI_NVM_STATUS_EEPROM_BUSY) |
|
||||
(1 << constants.UPDI_NVM_STATUS_FLASH_BUSY)):
|
||||
if not status & ((1 << self.STATUS_EEPROM_BUSY_bp) | (1 << self.STATUS_FLASH_BUSY_bp)):
|
||||
return True
|
||||
|
||||
self.logger.error("Wait NVM ready timed out")
|
||||
@@ -426,12 +438,12 @@ int updi_nvm_wait_ready_V3(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
start_time = avr_ustimestamp();
|
||||
do {
|
||||
if (updi_read_byte(pgm, p->nvm_base + UPDI_V3_NVMCTRL_STATUS, &status) >= 0) {
|
||||
if (status & (1 << UPDI_V3_NVM_STATUS_WRITE_ERROR)) {
|
||||
pmsg_error("unable to write NVM status\n");
|
||||
if (status & UPDI_V3_NVM_STATUS_WRITE_ERROR_MASK) {
|
||||
pmsg_error("unable to write NVM status, error code %d\n", status >> UPDI_V3_NVM_STATUS_WRITE_ERROR_BIT);
|
||||
return -1;
|
||||
}
|
||||
if (!(status & ((1 << UPDI_V3_NVM_STATUS_EEPROM_BUSY) |
|
||||
(1 << UPDI_V3_NVM_STATUS_FLASH_BUSY)))) {
|
||||
if (!(status & ((1 << UPDI_V3_NVM_STATUS_EEPROM_BUSY_BIT) |
|
||||
(1 << UPDI_V3_NVM_STATUS_FLASH_BUSY_BIT)))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user