This is an automated email from Gerrit.

Lars Poeschel (poeschell+open...@mailbox.org) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/5505

-- gerrit

commit 3d17eaeff24865f7a0e764a35fe0daa845e6e556
Author: Lars Poeschel <poeschell+open...@mailbox.org>
Date:   Mon Nov 11 15:36:43 2019 +0100

    avrf.c: Add a driver for the eeprom on avrs
    
    This adds a driver to use the eeprom on avrs with openocds flash
    interface. The eeprom can be read and written.
    BEWARE: Erasing only works in conjunction with the flash. So if you
    erase the flash, the eeprom is also erased an vice versa. This is a
    hardware limitation.
    
    Change-Id: I72f24f07c73c196bd415829fdcb26bc99cf27059
    Signed-off-by: Lars Pöschel <poeschell+open...@mailbox.org>

diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c
index 3f8e322..b7f9153 100644
--- a/src/flash/nor/avrf.c
+++ b/src/flash/nor/avrf.c
@@ -246,6 +246,98 @@ static int avr_jtagprg_readflashpage(struct avr_common 
*avr,
        return ERROR_OK;
 }
 
+static int avr_jtagprg_writeeeprompage(struct avr_common *avr,
+       const uint8_t *page_buf,
+       uint32_t buf_size,
+       uint32_t addr,
+       uint32_t page_size)
+{
+       uint32_t i, poll_value;
+
+       avr_jtag_sendinstr(avr->jtag_info.tap, NULL, 
AVR_JTAG_INS_PROG_COMMANDS);
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2311, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+
+       /* load addr high byte */
+       avr_jtag_senddat(avr->jtag_info.tap,
+               NULL,
+               0x0700 | ((addr >> 8) & 0xFF),
+               AVR_JTAG_REG_ProgrammingCommand_Len);
+
+       for (i = 0; i < page_size; i++) {
+               /* load addr low byte */
+               avr_jtag_senddat(avr->jtag_info.tap,
+                               NULL,
+                               0x0300 | (addr & 0xFF),
+                               AVR_JTAG_REG_ProgrammingCommand_Len);
+
+               if (i < buf_size)
+                       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x1300 | 
page_buf[i], AVR_JTAG_REG_ProgrammingCommand_Len);
+               else
+                       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x1300 | 
0xFF, AVR_JTAG_REG_ProgrammingCommand_Len);
+               avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+               avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x7700, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+               avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3700, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+       }
+
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3100, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3300, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+
+       do {
+               poll_value = 0;
+               avr_jtag_senddat(avr->jtag_info.tap,
+                       &poll_value,
+                       0x3300,
+                       AVR_JTAG_REG_ProgrammingCommand_Len);
+               if (ERROR_OK != mcu_execute_queue())
+                       return ERROR_FAIL;
+               LOG_DEBUG("poll_value = 0x%04" PRIx32 "", poll_value);
+       } while (!(poll_value & 0x0200));
+
+       return ERROR_OK;
+}
+
+static int avr_jtagprg_readeeprompage(struct avr_common *avr,
+       uint32_t *page_buf,
+       uint32_t buf_size,
+       uint32_t addr,
+       uint32_t page_size)
+{
+       uint32_t i;
+
+       avr_jtag_sendinstr(avr->jtag_info.tap, NULL, 
AVR_JTAG_INS_PROG_COMMANDS);
+       avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2303, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+
+       for(i = 0; i < page_size; i++) {
+               /* load addr high byte */
+               avr_jtag_senddat(avr->jtag_info.tap,
+                               NULL,
+                               0x0700 | (((addr + i) >> 8) & 0xFF),
+                               AVR_JTAG_REG_ProgrammingCommand_Len);
+
+               /* load addr low byte */
+               avr_jtag_senddat(avr->jtag_info.tap,
+                               NULL,
+                               0x0300 | ((addr + i) & 0xFF),
+                               AVR_JTAG_REG_ProgrammingCommand_Len);
+
+               /* load addr low byte again for some reason */
+               avr_jtag_senddat(avr->jtag_info.tap,
+                               NULL,
+                               0x3300 | ((addr + i) & 0xFF),
+                               AVR_JTAG_REG_ProgrammingCommand_Len);
+
+               avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x3200, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+               avr_jtag_senddat(avr->jtag_info.tap, &page_buf[i], 0x3300, 
AVR_JTAG_REG_ProgrammingCommand_Len);
+       }
+
+       if (ERROR_OK != mcu_execute_queue())
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
 FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
 {
        struct avrf_flash_bank *avrf_info;
@@ -586,3 +678,230 @@ const struct flash_driver avr_flash = {
        .info = avrf_info,
        .free_driver_priv = default_flash_free_driver_priv,
 };
+
+/*
+ * EEPROM
+ */
+struct avr_eeprom_flash_bank {
+       int ppage_size;
+       int probed;
+       const struct avrf_type *avr_info;
+};
+
+static int avr_eeprom_write(struct flash_bank *bank, const 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;
+
+       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 %" PRId32 "", count);
+
+       if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
+               return ERROR_FAIL;
+
+       cur_size = 0;
+       while (count > 0) {
+               if (count > page_size)
+                       cur_buffer_size = page_size;
+               else
+                       cur_buffer_size = count;
+               avr_jtagprg_writeeeprompage(avr,
+                       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);
+}
+
+static int avr_eeprom_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;
+       uint32_t *tmp_buf;
+
+       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 %" PRId32 "", count);
+
+       if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
+               return ERROR_FAIL;
+
+       tmp_buf = calloc(page_size, sizeof(uint32_t));
+       if (tmp_buf == NULL)
+               return ERROR_FAIL;
+
+       cur_size = 0;
+       while (count > 0) {
+               if (count > page_size)
+                       cur_buffer_size = page_size;
+               else
+                       cur_buffer_size = count;
+
+               avr_jtagprg_readeeprompage(avr,
+                               tmp_buf,
+                               cur_buffer_size,
+                               offset + cur_size,
+                               page_size);
+               for(uint32_t i = 0; i < page_size; i++)
+                       buffer[cur_size + i] = tmp_buf[i];
+
+               count -= cur_buffer_size;
+               cur_size += cur_buffer_size;
+
+               keep_alive();
+       }
+
+       free(tmp_buf);
+
+       return avr_jtagprg_leaveprogmode(avr);
+}
+
+static int avr_eeprom_probe(struct flash_bank *bank)
+{
+       uint8_t ver;
+       int error = ERROR_OK;
+       struct avr_eeprom_flash_bank *avr_eeprom_bank = bank->driver_priv;
+       const struct avrf_type *avr_info = avrf_get_avr_info(bank, &error, 
&ver);
+       int i;
+
+       if (avr_info != NULL) {
+               if (bank->sectors) {
+                       free(bank->sectors);
+                       bank->sectors = NULL;
+               }
+
+               /* chip found */
+               bank->base = 0x00000000;
+               bank->size = (avr_info->eeprom_page_size * 
avr_info->eeprom_page_num);
+               bank->num_sectors = avr_info->eeprom_page_num;
+               bank->sectors = malloc(sizeof(struct flash_sector) * 
avr_info->eeprom_page_num);
+
+               for (i = 0; i < avr_info->eeprom_page_num; i++) {
+                       bank->sectors[i].offset = i * 
avr_info->eeprom_page_size;
+                       bank->sectors[i].size = avr_info->eeprom_page_size;
+                       bank->sectors[i].is_erased = -1;
+                       bank->sectors[i].is_protected = -1;
+               }
+
+               avr_eeprom_bank->probed = 1;
+               avr_eeprom_bank->avr_info = avr_info;
+               return ERROR_OK;
+       } else {
+               if (error == ERROR_FLASH_OPERATION_FAILED) {
+                       /* chip not supported */
+                       LOG_ERROR("device id is not supported for avr");
+                       avr_eeprom_bank->probed = 1;
+                       return ERROR_FAIL;
+               }
+       }
+
+       return error;
+}
+
+static int avr_eeprom_auto_probe(struct flash_bank *bank)
+{
+       struct avr_eeprom_flash_bank *avr_eeprom_bank = bank->driver_priv;
+
+       if (avr_eeprom_bank->probed)
+               return ERROR_OK;
+
+       return avr_eeprom_probe(bank);
+}
+
+static int avr_eeprom_info(struct flash_bank *bank, char *buf, int buf_size)
+{
+       uint8_t ver;
+       int error = ERROR_OK;
+       struct avr_eeprom_flash_bank *avr_eeprom_bank = bank->driver_priv;
+       const struct avrf_type *avr_info = avrf_get_avr_info(bank, &error, 
&ver);
+
+       if (avr_info != NULL) {
+               /* chip found */
+               snprintf(buf, buf_size, "%s - Rev: 0x%" PRIx32 "", 
avr_info->name,
+                               ver);
+               avr_eeprom_bank->avr_info = avr_info;
+       } else
+               if (error == ERROR_FLASH_OPERATION_FAILED)
+                       snprintf(buf, buf_size, "Cannot identify target as a 
avr\n");
+
+       return error;
+}
+
+FLASH_BANK_COMMAND_HANDLER(avr_eeprom_flash_bank_command)
+{
+       struct avr_eeprom_flash_bank *avr_eeprom_bank;
+
+       if (CMD_ARGC < 6)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       avr_eeprom_bank = malloc(sizeof(struct avr_eeprom_flash_bank));
+       if (!avr_eeprom_bank)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       avr_eeprom_bank->probed = 0;
+       bank->driver_priv = avr_eeprom_bank;
+
+       return ERROR_OK;
+}
+
+static const struct command_registration avr_eeprom_exec_command_handlers[] = {
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration avr_eeprom_command_handlers[] = {
+       {
+               .name = "avr_eeprom",
+               .mode = COMMAND_ANY,
+               .help = "AVR EEPROM command group",
+               .usage = "",
+               .chain = avr_eeprom_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+const struct flash_driver avr_eeprom = {
+       .name = "avr_eeprom",
+       .commands = avr_eeprom_command_handlers,
+       .flash_bank_command = avr_eeprom_flash_bank_command,
+       .info = avr_eeprom_info,
+       .probe = avr_eeprom_probe,
+       .auto_probe = avr_eeprom_auto_probe,
+       .read = avr_eeprom_read,
+       .erase = avrf_erase,
+       .erase_check = default_flash_blank_check,
+       .write = avr_eeprom_write,
+       .free_driver_priv = default_flash_free_driver_priv,
+};
diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c
index d52e072..e79e9bf 100644
--- a/src/flash/nor/drivers.c
+++ b/src/flash/nor/drivers.c
@@ -32,6 +32,7 @@ extern const struct flash_driver ath79_flash;
 extern const struct flash_driver atsame5_flash;
 extern const struct flash_driver atsamv_flash;
 extern const struct flash_driver avr_flash;
+extern const struct flash_driver avr_eeprom;
 extern const struct flash_driver bluenrgx_flash;
 extern const struct flash_driver cc3220sf_flash;
 extern const struct flash_driver cc26xx_flash;
@@ -104,6 +105,7 @@ static const struct flash_driver * const flash_drivers[] = {
        &atsame5_flash,
        &atsamv_flash,
        &avr_flash,
+       &avr_eeprom,
        &bluenrgx_flash,
        &cc3220sf_flash,
        &cc26xx_flash,

-- 


_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to