Hi, Attached is the patch that allows me to program both flash and eeprom of atmega128.
Indeed it's not elegant but so is the whole AVR support :| The question i still have no idea how to answer is how to properly implement verification support? The problem is that the memory in question is NOR and so the driver was implemented as a nor driver. But since OCD doesn't work with AVR in openocd i have no chance to use regular commands to readout flash and eeprom contents. Datasheet mentions special JTAG commands that let one to read it back (similar to the programming) but i have no idea how to proceed openocd-architecture-wise. Probably avrf driver should be implemented like nand? Thanks a lot to everybody involved, Happy hacking! -- Be free, use free (http://www.gnu.org/philosophy/free-sw.html) software! mailto:fercer...@gmail.com
>From fdf77aadc9e5fc75dc2f7f455d7a6ece65722c80 Mon Sep 17 00:00:00 2001 From: Paul Fertser <fercer...@gmail.com> Date: Wed, 13 Jan 2010 16:22:38 +0300 Subject: [PATCH] atmega128: implement EEPROM flashing This patch implements flashing EEPROM over JTAG, represented as bank 1. Tested on atmega128. Signed-off-by: Paul Fertser <fercer...@gmail.com> --- src/flash/nor/avrf.c | 87 +++++++++++++++++++++++++++++++++++++++++++---- src/flash/nor/avrf.h | 7 ++++ tcl/target/mega128.cfg | 6 +++- 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c index 6c2d17f..2a67a08 100644 --- a/src/flash/nor/avrf.c +++ b/src/flash/nor/avrf.c @@ -180,11 +180,61 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr, uint8_t *page_buf, return ERROR_OK; } +static int avr_jtagprg_writeeeprompage(struct avr_common *avr, 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); + addr++; + + 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, 0x13FF, AVR_JTAG_REG_ProgrammingCommand_Len); + } + // latch data + 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); + } + + // write page + 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; +} + + FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command) { struct avrf_flash_bank *avrf_info; + int is_flash; - if (CMD_ARGC < 6) + if (CMD_ARGC < 7) { LOG_WARNING("incomplete flash_bank avr configuration"); return ERROR_FLASH_BANK_INVALID; @@ -194,6 +244,8 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command) bank->driver_priv = avrf_info; avrf_info->probed = 0; + COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], is_flash); + avrf_info->type = is_flash; return ERROR_OK; } @@ -248,7 +300,14 @@ static int avrf_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, { cur_buffer_size = count; } - avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size); + if (((struct avrf_flash_bank*)(bank->driver_priv))->type == FLASH) + { + avr_jtagprg_writeflashpage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size ); + } + else + { + avr_jtagprg_writeeeprompage(avr, buffer + cur_size, cur_buffer_size, offset + cur_size, page_size ); + } count -= cur_buffer_size; cur_size += cur_buffer_size; @@ -302,16 +361,28 @@ static int avrf_probe(struct flash_bank *bank) if (avr_info != NULL) { + int page_size; + int page_num; + + if (avrf_info->type == FLASH) { + page_size = avr_info->flash_page_size; + page_num = avr_info->flash_page_num; + } else { + page_size = avr_info->eeprom_page_size; + page_num = avr_info->eeprom_page_num; + } + // chip found bank->base = 0x00000000; - bank->size = (avr_info->flash_page_size * avr_info->flash_page_num); - bank->num_sectors = avr_info->flash_page_num; - bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num); - for (i = 0; i < avr_info->flash_page_num; i++) + bank->size = (page_size * page_num); + bank->num_sectors = page_num; + bank->sectors = malloc(sizeof(struct flash_sector) * page_num); + + for (i = 0; i < page_num; i++) { - bank->sectors[i].offset = i * avr_info->flash_page_size; - bank->sectors[i].size = avr_info->flash_page_size; + bank->sectors[i].offset = i * page_size; + bank->sectors[i].size = page_size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } diff --git a/src/flash/nor/avrf.h b/src/flash/nor/avrf.h index 1a69e86..43bd523 100644 --- a/src/flash/nor/avrf.h +++ b/src/flash/nor/avrf.h @@ -30,10 +30,17 @@ struct avrf_type int eeprom_page_num; }; +enum flash_type +{ + FLASH, + EEPROM +}; + struct avrf_flash_bank { int ppage_size; int probed; + enum flash_type type; }; #endif /* AVRF_H */ diff --git a/tcl/target/mega128.cfg b/tcl/target/mega128.cfg index 2cf31d6..94bbfd2 100644 --- a/tcl/target/mega128.cfg +++ b/tcl/target/mega128.cfg @@ -23,7 +23,10 @@ target create $_TARGETNAME avr -endian $_ENDIAN -chain-position $_TARGETNAME #$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size 16384 -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME +# flash +flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME 0 +# eeprom +flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME 1 #to use it, script will be like: #init @@ -36,6 +39,7 @@ flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME #poll #avr mass_erase 0 #flash write_image E:/Versaloon/Software/CAMERAPROTOCOLAGENT.hex +#flash write_bank 1 E:/Versaloon/Software/CAMERAPROTOCOLAGENT.eeprom.bin 0 #reset run #shutdown # -- 1.5.6.5
_______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development