@@ -31,6 +31,7 @@ char first_device;
3131int restart_after_program ;
3232int hex_cols ;
3333int hex_colw ;
34+ int force_smarteeprom_config ;
3435
3536//SAM-BA Settings
3637mailbox_t initparams ;
@@ -382,6 +383,137 @@ int test_mcu(char silent)
382383 return 1 ;
383384}
384385
386+ // SmartEEPROM NVMCTRL section
387+ int 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+
393+ if (verbose )
394+ {
395+ 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 );
396+ }
397+
398+ printf ("Configuring SmartEEPROM... " );
399+
400+ //Set WMODE to Manual
401+ ctrla .bit .WMODE = NVMCTRL_CTRLA_WMODE_MAN ;
402+ if (!write_half_word (NVMCTRL_CTRLA , ctrla .reg ))
403+ {
404+ printf ("Error setting NVMCTRL.CTRLA.WMODE to Manual.\n" );
405+ return 0 ;
406+ }
407+ slp (SLEEP_BETWEEN_WRITES );
408+
409+ // Set user row address
410+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
411+ {
412+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n" );
413+ return 0 ;
414+ }
415+
416+ // Erase page
417+ NVMCTRL_CTRLB_Type ctrlb ;
418+ ctrlb .reg = 0 ;
419+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_EP ;
420+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
421+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
422+ {
423+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n" , ctrlb .reg );
424+ return 0 ;
425+ }
426+ slp (SLEEP_BETWEEN_WRITES );
427+
428+ // Page buffer clear
429+ ctrlb .reg = 0 ;
430+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_PBC ;
431+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
432+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
433+ {
434+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n" , ctrlb .reg );
435+ return 0 ;
436+ }
437+ slp (SLEEP_BETWEEN_WRITES );
438+
439+ // Write in the write buffer
440+ for (int i = 0 ; i < 4 ; i ++ )
441+ {
442+ if (!write_word (NVMCTRL_USER + i * 4 , data [i ]))
443+ {
444+ printf ("Error: Unable to write NVMCTRL_USER page %i.\n" , i );
445+ return 0 ;
446+ }
447+ slp (SLEEP_BETWEEN_WRITES );
448+ }
449+
450+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
451+ {
452+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n" );
453+ return 0 ;
454+ }
455+ slp (SLEEP_BETWEEN_WRITES );
456+
457+ // Write quad word (128bits)
458+ ctrlb .reg = 0 ;
459+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_WQW ;
460+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
461+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
462+ {
463+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n" , ctrlb .reg );
464+ return 0 ;
465+ }
466+
467+ printf ("Success!\n" );
468+ return 1 ;
469+ }
470+
471+ void configure_smarteeprom (void )
472+ {
473+ uint32_t user_row [4 ];
474+ for (int i = 0 ; i < 4 ; i ++ )
475+ {
476+ user_row [i ] = read_word (NVMCTRL_USER + i * 4 );
477+ }
478+
479+ if (verbose )
480+ {
481+ printf ("user row: " );
482+ for (int i = 0 ; i < 4 ; i ++ )
483+ {
484+ printf ("0x%08x " , user_row [i ]);
485+ }
486+ printf ("\n" );
487+ }
488+
489+
490+ NVMCTRL_USER_ROW_MAPPING1_Type * puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type * )(& user_row [1 ]);
491+
492+ // Check current status and proceed accordingly.
493+ if (puser_row1 -> bit .SBLK == 0 && puser_row1 -> bit .PSZ == 0 )
494+ {
495+ printf ("SmartEEPROM not configured, proceed.\n" );
496+ }
497+ else
498+ {
499+ printf ("SmartEEPROM is already configured - SBLK: 0x%04x - PSZ: 0x%03x.\n" , puser_row1 -> bit .SBLK , puser_row1 -> bit .PSZ );
500+ if (force_smarteeprom_config )
501+ {
502+ printf ("--forceeep enabled, reconfiguring SmartEEPROM.\n" );
503+ }
504+ else
505+ {
506+ printf ("Use --forceeep to force SmartEEPROM reconfiguration.\n" );
507+ return ;
508+ }
509+ }
510+
511+ // Set SmartEEPROM Virtual Size to 1024 bytes. Specs in DS60001507E, page 653.
512+ puser_row1 -> bit .SBLK = 0x1 ; // 1 block
513+ puser_row1 -> bit .PSZ = 0x1 ; // 8 bytes
514+ write_user_row (user_row );
515+ }
516+
385517//Upper case any lower case characters in a string
386518void strlower (char * str )
387519{
@@ -495,6 +627,8 @@ void display_help(void)
495627 printf (" -s --size size Read firmware size of <size>\n" );
496628 printf (" -D --download file Write firmware from <file> into device\n" );
497629 printf (" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n" );
630+ printf (" --smarteep Enable Smart EEPROM MCU feature\n" );
631+ printf (" --forceeep Force re-configuration of Smart EEPROM MCU feature. Requires --smarteep.\n" );
498632 printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
499633 printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
500634 printf (" --restart Restart device after successful programming\n" );
@@ -503,11 +637,13 @@ void display_help(void)
503637
504638#define SW_COLS 1000
505639#define SW_COLW 1001
640+ #define SW_SMARTEEP 1002
506641
507642//Program command line options
508643struct option long_options [] = {
509644 //Flags
510645 { "restart" , no_argument , & restart_after_program , 1 },
646+ { "forceeep" , no_argument , & force_smarteeprom_config , 1 },
511647 //Other
512648 { "verbose" , no_argument , 0 , 'v' },
513649 { "help" , no_argument , 0 , 'h' },
@@ -520,6 +656,7 @@ struct option long_options[] = {
520656 { "addr" , required_argument , 0 , 'a' },
521657 { "size" , required_argument , 0 , 's' },
522658 { "test" , no_argument , 0 , 't' },
659+ { "smarteep" , no_argument , 0 , SW_SMARTEEP },
523660 { "cols" , required_argument , 0 , SW_COLS },
524661 { "colw" , required_argument , 0 , SW_COLW },
525662 { 0 , 0 , 0 , 0 }
@@ -533,6 +670,7 @@ int main(int argc, char *argv[])
533670 restart_after_program = 0 ;
534671 hex_cols = COLS ;
535672 hex_colw = COLW ;
673+ force_smarteeprom_config = 0 ;
536674
537675 display_version ();
538676 display_copyright ();
@@ -633,6 +771,10 @@ int main(int argc, char *argv[])
633771 testmode = 1 ;
634772 break ;
635773
774+ case SW_SMARTEEP :
775+ command = CMD_CONFIG_SMARTEEPROM ;
776+ break ;
777+
636778 case SW_COLS :
637779 hex_cols = atoi (optarg );
638780 if (hex_cols < 1 )
@@ -754,7 +896,17 @@ int main(int argc, char *argv[])
754896 printf ("Found MCU: %s\n" , mcu -> name );
755897
756898 print_bootloader_version ();
899+
757900 if (verbose ) printf ("Device ID: %08X\n" , mcu -> cidr );
901+ if (command == CMD_CONFIG_SMARTEEPROM )
902+ {
903+ configure_smarteeprom ();
904+
905+ if (restart_after_program )
906+ jump_application ();
907+
908+ goto exitProgram ;
909+ }
758910
759911
760912 memcpy (& appinfo , applet_data + applet_size - sizeof (appinfo_t ), sizeof (appinfo_t ));
0 commit comments