From 030d5596e1e6d8484669d899bc5aaecb7216cbcd Mon Sep 17 00:00:00 2001 From: MX682X <58419867+MX682X@users.noreply.github.com> Date: Sun, 22 Jun 2025 19:00:00 +0200 Subject: [PATCH] fix PDI Bootmem write, maybe --- src/pickit5.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/pickit5.c b/src/pickit5.c index 192ed8b7..53e970d6 100644 --- a/src/pickit5.c +++ b/src/pickit5.c @@ -170,6 +170,10 @@ static int pickit5_tpi_write(const PROGRAMMER *pgm, const AVRPART *p, static int pickit5_jtag_write_fuse(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned char value); static int pickit5_jtag_read_fuse(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned char *value); +// PDI-Specific +static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr, int len, unsigned char *value); + // Extra functions static int pickit5_get_fw_info(const PROGRAMMER *pgm); static int pickit5_set_vtarget(const PROGRAMMER *pgm, double v); @@ -825,7 +829,7 @@ static void pickit5_enable(PROGRAMMER *pgm, const AVRPART *p) { mem->readsize = mem->size < 512? mem->size : 512; } } - if(both_xmegajtag(pgm, p) || both_pdi(pgm, p)) { + if(both_xmegajtag(pgm, p)) { // True Page size is needed for a PDI fix, so don't increase them if((mem = avr_locate_flash(p))) { mem->page_size = mem->size < 1024? mem->size : 1024; mem->readsize = mem->size < 1024? mem->size : 1024; @@ -1252,6 +1256,67 @@ static int pickit5_updi_read_byte(const PROGRAMMER *pgm, const AVRPART *p, */ } +/* a little workaround function to write application and boot from one function */ +static int pickit5_pdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, int len, unsigned char *value) { + pmsg_debug("%s\n", __func__); + unsigned short page_size = mem->page_size; + if (len % page_size != 0) { // sanity + pmsg_error("length %i is not a multiple of page size %i, aborting.\n", len, page_size); + return -1; + } + + unsigned char flash_cmd[] = { + 0x91, 0x00, // Load script paramter to r00 + 0x91, 0x01, // Load script paramter to r01 + 0x90, 0x04, 0xCA, 0x01, 0x00, 0x01, // Set r04 to value 0x10001CA (NVM CMD) + 0x90, 0x05, 0xC4, 0x01, 0x00, 0x01, // Set r05 to value 0x10001C4 (NVM Data) + 0x90, 0x06, 0xCF, 0x01, 0x00, 0x01, // Set r06 to value 0x10001CF (NVM Status) + 0x9B, 0x07, 0x23, // Set r07 to value 0x23 (NVM Load Page Buffer) + 0x9B, 0x08, 0x2F, // Set r08 to value 0x2F (NVM Erase and write flash page) + 0x9B, 0x09, 0xFF, // Set r09 to value 0xFF (Dummy Flash write value) + 0x9C, 0x0A, page_size, (page_size >> 8), // Load word (page size) to r09 + + 0x1E, 0x03, 0x04, // load byte from NVM Command register (r04) + 0x6C, 0x0B, // Move temp_reg to r11 + 0x1E, 0x03, 0x05, // Load byte from NVM Data register (r05) + 0x6C, 0x0C, // Move temp_reg to r12 + + 0x60, 0x03, 0x01, // copy r01 to r03 + 0x93, 0x03, page_size, (page_size >> 8), // Integer divide r03 by page size + 0xAD, 0x03, // while (r03 --) { + + 0x1E, 0x06, 0x04, 0x07, // Load "load page command" to NVM Cmd Reg + 0x1E, 0x09, 0x00, // Set pointer for indirect addressing to r00 + 0x1E, 0x10, 0x0A, // Set repeat counter to number in r09 + 0x1E, 0x0A, 0x0A, // read from data stream and send it to the device + + 0x1E, 0x06, 0x04, 0x08, // Load "Erase and write flash page" command into NVM Cmd buffer + 0x1E, 0x06, 0x00, 0x09, // Triger NVM Cmd by writing to the first address (r0, 0xFF) + 0xA2, // Do { + 0x1E, 0x03, 0x06, // Check status reg (r06) + 0xA5, 0x80, 0x00, 0x00, 0x00, // } while ((status reg & 0x80 != 0x00)) + 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, // for at most 100 times + 0xAE, // } (End of Loop) + + 0x1E, 0x06, 0x05, 0x0C, // Store byte in r12 to SRAM Address in r05 + 0x1E, 0x06, 0x04, 0x0B, // Store byte in r11 to SRAM Address in r04 + 0x92, 0x00, page_size, (page_size >> 8), 0x00, 0x00, // Increment r00 by page size + 0x5A, // Set Error Status + }; + + addr += mem->offset; + + unsigned char param[8]; + pickit5_uint32_to_array(¶m[0], addr); + pickit5_uint32_to_array(¶m[4], len); + + int rc = pickit5_download_data(pgm, flash_cmd, sizeof(flash_cmd), param, sizeof(param), value, len); + if(rc < 0) + rc = LIBAVRDUDE_EXIT; + return rc; +} + // Return numbers of byte written static int pickit5_write_array(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, int len, unsigned char *value) { @@ -1270,7 +1335,9 @@ static int pickit5_write_array(const PROGRAMMER *pgm, const AVRPART *p, if(is_debugwire(pgm) && !mem_is_in_flash(mem)) // For flash programming, stay in ISP mode pickit5_isp_switch_to_dw(pgm, p); if(is_tpi(pgm)) - pickit5_tpi_write(pgm, p, mem, addr, len, value); + return pickit5_tpi_write(pgm, p, mem, addr, len, value); + if(is_pdi(pgm) && mem_is_in_flash(mem)) + return pickit5_pdi_flash_write(pgm, p, mem, addr, len, value); const unsigned char *write_bytes = NULL; unsigned int write_bytes_len = 0;