This is an automated email from Gerrit. "Name of user not set <de...@thom.fr.eu.org>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7583
-- gerrit commit 63c305f79d6cc466411ab83c9d5385fb74564e3b Author: François LEGAL <de...@thom.fr.eu.org> Date: Thu Apr 6 18:54:29 2023 +0200 src/flash/nor/avrf : add readback of embedded flash AVR flash is non functionnali. However, I needed to readback the flash of an existing chip, so based on the existing code plus the manual, this allows reading back atmega embedded flash Tested on atmega329p chip Signed-off-by: François LEGAL <de...@thom.fr.eu.org> Change-Id: I054e8736e21c7c8e9c03652974de5cb9bb3e371e diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c index 1d317a10c6..9e9d00a485 100644 --- a/src/flash/nor/avrf.c +++ b/src/flash/nor/avrf.c @@ -61,6 +61,7 @@ static const struct avrf_type avft_chips_info[] = { {"at90usb128", 0x9782, 256, 512, 8, 512}, {"atmega164p", 0x940a, 128, 128, 4, 128}, {"atmega324p", 0x9508, 128, 256, 4, 256}, + {"atmega329p", 0x950b, 128, 256, 4, 256}, {"atmega324pa", 0x9511, 128, 256, 4, 256}, {"atmega644p", 0x960a, 256, 256, 8, 256}, {"atmega1284p", 0x9705, 256, 512, 8, 512}, @@ -87,9 +88,13 @@ static int avr_jtag_read_jtagid(struct avr_common *avr, uint32_t *id) static int avr_jtagprg_enterprogmode(struct avr_common *avr) { avr_jtag_reset(avr, 1); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0xA370, AVR_JTAG_REG_PROGRAMMING_ENABLE_LEN); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; return ERROR_OK; } @@ -99,11 +104,17 @@ static int avr_jtagprg_leaveprogmode(struct avr_common *avr) avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2300, AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_ENABLE); avr_jtag_senddat(avr->jtag_info.tap, NULL, 0, AVR_JTAG_REG_PROGRAMMING_ENABLE_LEN); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; avr_jtag_reset(avr, 0); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; return ERROR_OK; } @@ -193,6 +204,51 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr, return ERROR_OK; } +static int avr_jtagprg_readflashpage(struct avr_common *avr, + const bool ext_addressing, + uint8_t *page_buf, + uint32_t buf_size, + uint32_t addr, + uint32_t page_size) +{ + avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS); + avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2302, AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; + + /* load extended high byte */ + if (ext_addressing) + avr_jtag_senddat(avr->jtag_info.tap, + NULL, + 0x0b00 | ((addr >> 17) & 0xFF), + AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); + + /* load addr high byte */ + avr_jtag_senddat(avr->jtag_info.tap, + NULL, + 0x0700 | ((addr >> 9) & 0xFF), + AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); + + /* load addr low byte */ + avr_jtag_senddat(avr->jtag_info.tap, + NULL, + 0x0300 | ((addr >> 1) & 0xFF), + AVR_JTAG_REG_PROGRAMMING_COMMAND_LEN); + + avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGEREAD); + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; + + for (uint32_t i = 0; i < page_size; i++) + avr_jtag_senddat(avr->jtag_info.tap, (uint32_t *)&page_buf[i], 0, 8); + + if (mcu_execute_queue() != ERROR_OK) + return ERROR_FAIL; + + + return ERROR_OK; +} + FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command) { struct avrf_flash_bank *avrf_info; @@ -285,6 +341,58 @@ static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o return avr_jtagprg_leaveprogmode(avr); } +static int avrf_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct avr_common *avr = target->arch_info; + uint32_t cur_size, cur_buffer_size, page_size; + bool ext_addressing; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + page_size = bank->sectors[0].size; + if ((offset % page_size) != 0) { + LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment", + offset, + page_size); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + LOG_DEBUG("offset is 0x%08" PRIx32 "", offset); + LOG_DEBUG("count is %" PRIu32 "", count); + + if (avr_jtagprg_enterprogmode(avr) != ERROR_OK) + return ERROR_FAIL; + + if (bank->size > 0x20000) + ext_addressing = true; + else + ext_addressing = false; + + cur_size = 0; + while (count > 0) { + if (count > page_size) + cur_buffer_size = page_size; + else + cur_buffer_size = count; + avr_jtagprg_readflashpage(avr, + ext_addressing, + buffer + cur_size, + cur_buffer_size, + offset + cur_size, + page_size); + count -= cur_buffer_size; + cur_size += cur_buffer_size; + + keep_alive(); + } + + return avr_jtagprg_leaveprogmode(avr); +} + #define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) @@ -464,7 +572,7 @@ const struct flash_driver avr_flash = { .flash_bank_command = avrf_flash_bank_command, .erase = avrf_erase, .write = avrf_write, - .read = default_flash_read, + .read = avrf_read, .probe = avrf_probe, .auto_probe = avrf_auto_probe, .erase_check = default_flash_blank_check, --