@@ -170,6 +170,10 @@ static int pickit5_tpi_write(const PROGRAMMER *pgm, const AVRPART *p,
170170static int pickit5_jtag_write_fuse (const PROGRAMMER * pgm , const AVRPART * p , const AVRMEM * mem , unsigned char value );
171171static int pickit5_jtag_read_fuse (const PROGRAMMER * pgm , const AVRPART * p , const AVRMEM * mem , unsigned char * value );
172172
173+ // PDI-Specific
174+ static int pickit5_pdi_flash_write (const PROGRAMMER * pgm , const AVRPART * p , const AVRMEM * mem ,
175+ unsigned long addr , int len , unsigned char * value );
176+
173177// Extra functions
174178static int pickit5_get_fw_info (const PROGRAMMER * pgm );
175179static int pickit5_set_vtarget (const PROGRAMMER * pgm , double v );
@@ -825,7 +829,7 @@ static void pickit5_enable(PROGRAMMER *pgm, const AVRPART *p) {
825829 mem -> readsize = mem -> size < 512 ? mem -> size : 512 ;
826830 }
827831 }
828- if (both_xmegajtag (pgm , p ) || both_pdi ( pgm , p )) {
832+ if (both_xmegajtag (pgm , p )) { // True Page size is needed for a PDI fix, so don't increase them
829833 if ((mem = avr_locate_flash (p ))) {
830834 mem -> page_size = mem -> size < 1024 ? mem -> size : 1024 ;
831835 mem -> readsize = mem -> size < 1024 ? mem -> size : 1024 ;
@@ -1252,6 +1256,67 @@ static int pickit5_updi_read_byte(const PROGRAMMER *pgm, const AVRPART *p,
12521256 */
12531257}
12541258
1259+ /* a little workaround function to write application and boot from one function */
1260+ static int pickit5_pdi_flash_write (const PROGRAMMER * pgm , const AVRPART * p ,
1261+ const AVRMEM * mem , unsigned long addr , int len , unsigned char * value ) {
1262+ pmsg_debug ("%s\n" , __func__ );
1263+ unsigned short page_size = mem -> page_size ;
1264+ if (len % page_size != 0 ) { // sanity
1265+ pmsg_error ("length %i is not a multiple of page size %i, aborting.\n" , len , page_size );
1266+ return -1 ;
1267+ }
1268+
1269+ unsigned char flash_cmd [] = {
1270+ 0x91 , 0x00 , // Load script paramter to r00
1271+ 0x91 , 0x01 , // Load script paramter to r01
1272+ 0x90 , 0x04 , 0xCA , 0x01 , 0x00 , 0x01 , // Set r04 to value 0x10001CA (NVM CMD)
1273+ 0x90 , 0x05 , 0xC4 , 0x01 , 0x00 , 0x01 , // Set r05 to value 0x10001C4 (NVM Data)
1274+ 0x90 , 0x06 , 0xCF , 0x01 , 0x00 , 0x01 , // Set r06 to value 0x10001CF (NVM Status)
1275+ 0x9B , 0x07 , 0x23 , // Set r07 to value 0x23 (NVM Load Page Buffer)
1276+ 0x9B , 0x08 , 0x2F , // Set r08 to value 0x2F (NVM Erase and write flash page)
1277+ 0x9B , 0x09 , 0xFF , // Set r09 to value 0xFF (Dummy Flash write value)
1278+ 0x9C , 0x0A , page_size , (page_size >> 8 ), // Load word (page size) to r09
1279+
1280+ 0x1E , 0x03 , 0x04 , // load byte from NVM Command register (r04)
1281+ 0x6C , 0x0B , // Move temp_reg to r11
1282+ 0x1E , 0x03 , 0x05 , // Load byte from NVM Data register (r05)
1283+ 0x6C , 0x0C , // Move temp_reg to r12
1284+
1285+ 0x60 , 0x03 , 0x01 , // copy r01 to r03
1286+ 0x93 , 0x03 , page_size , (page_size >> 8 ), // Integer divide r03 by page size
1287+ 0xAD , 0x03 , // while (r03 --) {
1288+
1289+ 0x1E , 0x06 , 0x04 , 0x07 , // Load "load page command" to NVM Cmd Reg
1290+ 0x1E , 0x09 , 0x00 , // Set pointer for indirect addressing to r00
1291+ 0x1E , 0x10 , 0x0A , // Set repeat counter to number in r09
1292+ 0x1E , 0x0A , 0x0A , // read from data stream and send it to the device
1293+
1294+ 0x1E , 0x06 , 0x04 , 0x08 , // Load "Erase and write flash page" command into NVM Cmd buffer
1295+ 0x1E , 0x06 , 0x00 , 0x09 , // Triger NVM Cmd by writing to the first address (r0, 0xFF)
1296+ 0xA2 , // Do {
1297+ 0x1E , 0x03 , 0x06 , // Check status reg (r06)
1298+ 0xA5 , 0x80 , 0x00 , 0x00 , 0x00 , // } while ((status reg & 0x80 != 0x00))
1299+ 0x00 , 0x00 , 0x00 , 0x00 , 0x64 , 0x00 , // for at most 100 times
1300+ 0xAE , // } (End of Loop)
1301+
1302+ 0x1E , 0x06 , 0x05 , 0x0C , // Store byte in r12 to SRAM Address in r05
1303+ 0x1E , 0x06 , 0x04 , 0x0B , // Store byte in r11 to SRAM Address in r04
1304+ 0x92 , 0x00 , page_size , (page_size >> 8 ), 0x00 , 0x00 , // Increment r00 by page size
1305+ 0x5A , // Set Error Status
1306+ };
1307+
1308+ addr += mem -> offset ;
1309+
1310+ unsigned char param [8 ];
1311+ pickit5_uint32_to_array (& param [0 ], addr );
1312+ pickit5_uint32_to_array (& param [4 ], len );
1313+
1314+ int rc = pickit5_download_data (pgm , flash_cmd , sizeof (flash_cmd ), param , sizeof (param ), value , len );
1315+ if (rc < 0 )
1316+ rc = LIBAVRDUDE_EXIT ;
1317+ return rc ;
1318+ }
1319+
12551320// Return numbers of byte written
12561321static int pickit5_write_array (const PROGRAMMER * pgm , const AVRPART * p ,
12571322 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,
12701335 if (is_debugwire (pgm ) && !mem_is_in_flash (mem )) // For flash programming, stay in ISP mode
12711336 pickit5_isp_switch_to_dw (pgm , p );
12721337 if (is_tpi (pgm ))
1273- pickit5_tpi_write (pgm , p , mem , addr , len , value );
1338+ return pickit5_tpi_write (pgm , p , mem , addr , len , value );
1339+ if (is_pdi (pgm ) && mem_is_in_flash (mem ))
1340+ return pickit5_pdi_flash_write (pgm , p , mem , addr , len , value );
12741341
12751342 const unsigned char * write_bytes = NULL ;
12761343 unsigned int write_bytes_len = 0 ;
0 commit comments