@@ -26,6 +26,7 @@ char first_device;
2626int restart_after_program ;
2727int hex_cols ;
2828int hex_colw ;
29+ int force_smarteeprom_config ;
2930
3031//SAM-BA Settings
3132mailbox_t initparams ;
@@ -377,6 +378,125 @@ int test_mcu(char silent)
377378 return 1 ;
378379}
379380
381+ // SmartEEPROM NVMCTRL section
382+ int write_user_row (uint32_t * data )
383+ {
384+ //Read the current state of NVMCTRL.CTRLA
385+ NVMCTRL_CTRLA_Type ctrla ;
386+ ctrla .reg = read_half_word (NVMCTRL_CTRLA );
387+ 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 );
388+
389+ printf ("Configuring SmartEEPROM... " );
390+
391+ //Set WMODE to Manual
392+ ctrla .bit .WMODE = NVMCTRL_CTRLA_WMODE_MAN ;
393+ if (!write_half_word (NVMCTRL_CTRLA , ctrla .reg ))
394+ {
395+ printf ("Error setting NVMCTRL.CTRLA.WMODE to Manual.\n" );
396+ return 0 ;
397+ }
398+ slp (SLEEP_BETWEEN_WRITES );
399+
400+ // Set user row address
401+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
402+ {
403+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n" );
404+ return 0 ;
405+ }
406+
407+ // Erase page
408+ NVMCTRL_CTRLB_Type ctrlb ;
409+ ctrlb .reg = 0 ;
410+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_EP ;
411+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
412+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
413+ {
414+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n" , ctrlb .reg );
415+ return 0 ;
416+ }
417+ slp (SLEEP_BETWEEN_WRITES );
418+
419+ // Page buffer clear
420+ ctrlb .reg = 0 ;
421+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_PBC ;
422+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
423+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
424+ {
425+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n" , ctrlb .reg );
426+ return 0 ;
427+ }
428+ slp (SLEEP_BETWEEN_WRITES );
429+
430+ // Write in the write buffer
431+ for (int i = 0 ; i < 4 ; i ++ )
432+ {
433+ if (!write_word (NVMCTRL_USER + i * 4 , data [i ]))
434+ {
435+ printf ("Error: Unable to write NVMCTRL_USER page %i.\n" , i );
436+ return 0 ;
437+ }
438+ slp (SLEEP_BETWEEN_WRITES );
439+ }
440+
441+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
442+ {
443+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n" );
444+ return 0 ;
445+ }
446+ slp (SLEEP_BETWEEN_WRITES );
447+
448+ // Write quad word (128bits)
449+ ctrlb .reg = 0 ;
450+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_WQW ;
451+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
452+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
453+ {
454+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n" , ctrlb .reg );
455+ return 0 ;
456+ }
457+
458+ printf ("Success!\n" );
459+ return 1 ;
460+ }
461+
462+ void configure_smarteeprom (void )
463+ {
464+ uint32_t user_row [4 ];
465+ printf ("user row: " );
466+ for (int i = 0 ; i < 4 ; i ++ )
467+ {
468+ user_row [i ] = read_word (NVMCTRL_USER + i * 4 );
469+ printf ("0x%08x " , user_row [i ]);
470+ }
471+ printf ("\n" );
472+
473+ NVMCTRL_USER_ROW_MAPPING1_Type * puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type * )(& user_row [1 ]);
474+
475+ // Check current status and proceed accordingly.
476+ if (puser_row1 -> bit .SBLK == 0 && puser_row1 -> bit .PSZ == 0 )
477+ {
478+ printf ("SmartEEPROM not configured, proceed.\n" );
479+ }
480+ else
481+ {
482+ printf ("SmartEEPROM already configured - SBLK: 0x%04x - PSZ: 0x%03x.\n" , puser_row1 -> bit .SBLK , puser_row1 -> bit .PSZ );
483+ if (force_smarteeprom_config )
484+ {
485+ printf ("--forceeep enabled, proceed.\n" );
486+ }
487+ else
488+ {
489+ printf ("Use --forceeep to force to configure it anyway.\n" );
490+ return ;
491+ }
492+ }
493+
494+ // Set SmartEEPROM Virtual Size.
495+ puser_row1 -> bit .SBLK = 0x1 ; // 1 block
496+ puser_row1 -> bit .PSZ = 0x1 ; // 8 bytes
497+ write_user_row (user_row );
498+ }
499+
380500//Upper case any lower case characters in a string
381501void strlower (char * str )
382502{
@@ -490,6 +610,8 @@ void display_help(void)
490610 printf (" -s --size size Read firmware size of <size>\n" );
491611 printf (" -D --download file Write firmware from <file> into device\n" );
492612 printf (" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n" );
613+ printf (" --smarteep Enable Smart EEPROM MCU feature\n" );
614+ printf (" --forceeep Force re-configuration of Smart EEPROM MCU feature. Requires --smarteep.\n" );
493615 printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
494616 printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
495617 printf (" --restart Restart device after successful programming\n" );
@@ -498,11 +620,13 @@ void display_help(void)
498620
499621#define SW_COLS 1000
500622#define SW_COLW 1001
623+ #define SW_SMARTEEP 1002
501624
502625//Program command line options
503626struct option long_options [] = {
504627 //Flags
505628 { "restart" , no_argument , & restart_after_program , 1 },
629+ { "forceeep" , no_argument , & force_smarteeprom_config , 1 },
506630 //Other
507631 { "verbose" , no_argument , 0 , 'v' },
508632 { "help" , no_argument , 0 , 'h' },
@@ -515,6 +639,7 @@ struct option long_options[] = {
515639 { "addr" , required_argument , 0 , 'a' },
516640 { "size" , required_argument , 0 , 's' },
517641 { "test" , no_argument , 0 , 't' },
642+ { "smarteep" , no_argument , 0 , SW_SMARTEEP },
518643 { "cols" , required_argument , 0 , SW_COLS },
519644 { "colw" , required_argument , 0 , SW_COLW },
520645 { 0 , 0 , 0 , 0 }
@@ -528,6 +653,7 @@ int main(int argc, char *argv[])
528653 restart_after_program = 0 ;
529654 hex_cols = COLS ;
530655 hex_colw = COLW ;
656+ force_smarteeprom_config = 0 ;
531657
532658 display_version ();
533659 display_copyright ();
@@ -628,6 +754,10 @@ int main(int argc, char *argv[])
628754 testmode = 1 ;
629755 break ;
630756
757+ case SW_SMARTEEP :
758+ command = CMD_CONFIG_SMARTEEPROM ;
759+ break ;
760+
631761 case SW_COLS :
632762 hex_cols = atoi (optarg );
633763 if (hex_cols < 1 )
@@ -751,14 +881,24 @@ int main(int argc, char *argv[])
751881 print_bootloader_version ();
752882 if (verbose ) printf ("Device ID: %08X\n" , mcu -> cidr );
753883
884+ if (command == CMD_CONFIG_SMARTEEPROM )
885+ {
886+ configure_smarteeprom ();
887+
888+ if (restart_after_program )
889+ jump_application ();
890+
891+ goto exitProgram ;
892+ }
893+
754894 //Load applet
755895 FILE * fIn ;
756896 char appletfname [128 ] = "" ;
757897 strlower (mcu -> name );
758898
759899 //sprintf(appletfname, "applet-flash-%s.bin", mcu->name);
760900 sprintf (appletfname , "applet-mdflash.bin" ); //make filename non-dependent upon mcu->name
761-
901+
762902 printf ("Applet file: %s\n" , appletfname );
763903
764904 fIn = fopen (appletfname , "rb" );
0 commit comments