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,

-- 

Reply via email to