@@ -29,6 +29,7 @@ char verbose;
2929char testmode ;
3030char first_device ;
3131int restart_after_program ;
32+ int force_smarteeprom_config ;
3233int hex_cols ;
3334int hex_colw ;
3435
@@ -382,6 +383,132 @@ int test_mcu(char silent)
382383 return 1 ;
383384}
384385
386+ // SmartEEPROM NVMCTRL section
387+ uint8_t write_user_row (uint32_t * data )
388+ {
389+ //Read the current state of NVMCTRL.CTRLA
390+ NVMCTRL_CTRLA_Type ctrla ;
391+ ctrla .reg = read_half_word (NVMCTRL_CTRLA );
392+ if (verbose ) printf ("NVMCTRL.CTRLA: 0x%04x\n\tAUTOWS: 0x%01x\n\tSUSPEN: 0x%01x\n\tWMODE: 0x%02x\n\tPRM: 0x%02x\n\tRWS: 0x%04x\n\tAHBNS0: 0x%01x\n\tAHBNS1: 0x%01x\n\tCACHEDIS0: 0x%01x\n\tCACHEDIS1: 0x%01x\n" , ctrla .reg , ctrla .bit .AUTOWS , ctrla .bit .SUSPEN , ctrla .bit .WMODE , ctrla .bit .PRM , ctrla .bit .RWS , ctrla .bit .AHBNS0 , ctrla .bit .AHBNS1 , ctrla .bit .CACHEDIS0 , ctrla .bit .CACHEDIS1 );
393+
394+ printf ("SmartEEPROM: Configuring... " );
395+
396+ //Set WMODE to Manual
397+ ctrla .bit .WMODE = NVMCTRL_CTRLA_WMODE_MAN ;
398+ if (!write_half_word (NVMCTRL_CTRLA , ctrla .reg ))
399+ {
400+ printf ("Error: setting NVMCTRL.CTRLA.WMODE to Manual.\n" );
401+ return 0 ;
402+ }
403+ slp (SLEEP_BETWEEN_WRITES );
404+
405+ // Set user row address
406+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
407+ {
408+ printf ("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n" );
409+ return 0 ;
410+ }
411+
412+ // Erase page
413+ NVMCTRL_CTRLB_Type ctrlb ;
414+ ctrlb .reg = 0 ;
415+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_EP ;
416+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
417+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
418+ {
419+ printf ("Error: setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n" , ctrlb .reg );
420+ return 0 ;
421+ }
422+ slp (SLEEP_BETWEEN_WRITES );
423+
424+ // Page buffer clear
425+ ctrlb .reg = 0 ;
426+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_PBC ;
427+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
428+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
429+ {
430+ printf ("Error: setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n" , ctrlb .reg );
431+ return 0 ;
432+ }
433+ slp (SLEEP_BETWEEN_WRITES );
434+
435+ // Write in the write buffer
436+ for (int i = 0 ; i < 4 ; i ++ )
437+ {
438+ if (!write_word (NVMCTRL_USER + i * 4 , data [i ]))
439+ {
440+ printf ("Error: Unable to write NVMCTRL_USER page %i.\n" , i );
441+ return 0 ;
442+ }
443+ slp (SLEEP_BETWEEN_WRITES );
444+ }
445+
446+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
447+ {
448+ printf ("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n" );
449+ return 0 ;
450+ }
451+ slp (SLEEP_BETWEEN_WRITES );
452+
453+ // Write quad word (128bits)
454+ ctrlb .reg = 0 ;
455+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_WQW ;
456+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
457+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
458+ {
459+ printf ("Error: setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n" , ctrlb .reg );
460+ return 0 ;
461+ }
462+ slp (SLEEP_BETWEEN_WRITES );
463+
464+ printf ("Success!\n" );
465+ return 1 ;
466+ }
467+
468+ uint8_t configure_smarteeprom (void )
469+ {
470+ // Configure for 2048 bytes - DS60001507E-page 653
471+ #define TARGET_SBLK 1 // 1 block
472+ #define TARGET_PSZ 2 // 16 bytes
473+
474+ uint32_t user_row [4 ];
475+ for (int i = 0 ; i < 4 ; i ++ )
476+ {
477+ user_row [i ] = read_word (NVMCTRL_USER + i * 4 );
478+ }
479+
480+ NVMCTRL_USER_ROW_MAPPING1_Type * puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type * )(& user_row [1 ]);
481+
482+ if (verbose ) printf ("SmartEEPROM: config - SBLK: 0x%04x - PSZ: 0x%03x.\n" , puser_row1 -> bit .SBLK , puser_row1 -> bit .PSZ );
483+
484+ if (puser_row1 -> bit .SBLK == TARGET_SBLK && puser_row1 -> bit .PSZ == TARGET_PSZ )
485+ {
486+ if (verbose ) printf ("SmartEEPROM: Configured!\n" );
487+ return 1 ;
488+ }
489+
490+ uint8_t should_reconfigure ;
491+ if (force_smarteeprom_config == FORCE_NONE )
492+ {
493+ should_reconfigure = prompt_yes_no ("SmartEEPROM: Your settings do not match the recommended values. Update setting?" );
494+ }
495+ else
496+ {
497+ should_reconfigure = (force_smarteeprom_config == FORCE_YES );
498+ }
499+
500+ if (!should_reconfigure )
501+ {
502+ printf ("SmartEEPROM: Skipped!\n" );
503+ return 1 ;
504+ }
505+
506+ // Set SmartEEPROM Virtual Size.
507+ puser_row1 -> bit .SBLK = TARGET_SBLK ;
508+ puser_row1 -> bit .PSZ = TARGET_PSZ ;
509+ return write_user_row (user_row );
510+ }
511+
385512//Upper case any lower case characters in a string
386513void strlower (char * str )
387514{
@@ -404,6 +531,21 @@ void strupper(char *str)
404531 }
405532}
406533
534+ //Prompt for Yy/Nn with message
535+ uint8_t prompt_yes_no (const char * msg )
536+ {
537+ printf (msg );
538+ printf (" (y/n):\n" );
539+
540+ char c ;
541+ do {
542+ scanf (" %c" , & c );
543+ c = toupper (c );
544+ } while (c != 'N' && c != 'Y' );
545+
546+ return c == 'Y' ;
547+ }
548+
407549//Return file size of given file
408550int filesize (char * fname )
409551{
@@ -495,6 +637,7 @@ void display_help(void)
495637 printf (" -s --size size Read firmware size of <size>\n" );
496638 printf (" -D --download file Write firmware from <file> into device\n" );
497639 printf (" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n" );
640+ printf (" --forceeep answer Automatic answer to Smart EEPROM re-configuration prompt <y/n>\n" );
498641 printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
499642 printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
500643 printf (" --restart Restart device after successful programming\n" );
@@ -503,6 +646,7 @@ void display_help(void)
503646
504647#define SW_COLS 1000
505648#define SW_COLW 1001
649+ #define SW_FORCEEEP 1002
506650
507651//Program command line options
508652struct option long_options [] = {
@@ -522,6 +666,7 @@ struct option long_options[] = {
522666 { "test" , no_argument , 0 , 't' },
523667 { "cols" , required_argument , 0 , SW_COLS },
524668 { "colw" , required_argument , 0 , SW_COLW },
669+ { "forceeep" , required_argument , 0 , SW_FORCEEEP },
525670 { 0 , 0 , 0 , 0 }
526671};
527672
@@ -531,6 +676,7 @@ int main(int argc, char *argv[])
531676 testmode = 0 ;
532677 first_device = 0 ;
533678 restart_after_program = 0 ;
679+ force_smarteeprom_config = FORCE_NONE ;
534680 hex_cols = COLS ;
535681 hex_colw = COLW ;
536682
@@ -651,6 +797,11 @@ int main(int argc, char *argv[])
651797 }
652798 break ;
653799
800+ case SW_FORCEEEP :
801+ strlower (optarg );
802+ force_smarteeprom_config = (strstr (optarg , "y" ) != NULL ) ? FORCE_YES : FORCE_NO ;
803+ break ;
804+
654805 default :
655806 command = CMD_ABORT ;
656807 break ;
@@ -756,7 +907,13 @@ int main(int argc, char *argv[])
756907 print_bootloader_version ();
757908 if (verbose ) printf ("Device ID: %08X\n" , mcu -> cidr );
758909
910+ if (!configure_smarteeprom ())
911+ {
912+ printf ("Error: Config feature failed!\n" );
913+ goto closePort ;
914+ }
759915
916+ //Load applet
760917 memcpy (& appinfo , applet_data + applet_size - sizeof (appinfo_t ), sizeof (appinfo_t ));
761918 if (appinfo .magic != 0x4142444D )
762919 {
0 commit comments