@@ -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,125 @@ 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+ 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 ("Configuring SmartEEPROM... " );
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+
463+ printf ("Success!\n" );
464+ return 1 ;
465+ }
466+
467+ void configure_smarteeprom (void )
468+ {
469+ uint32_t user_row [4 ];
470+ printf ("user row: " );
471+ for (int i = 0 ; i < 4 ; i ++ )
472+ {
473+ user_row [i ] = read_word (NVMCTRL_USER + i * 4 );
474+ printf ("0x%08x " , user_row [i ]);
475+ }
476+ printf ("\n" );
477+
478+ NVMCTRL_USER_ROW_MAPPING1_Type * puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type * )(& user_row [1 ]);
479+
480+ // Check current status and proceed accordingly.
481+ if (puser_row1 -> bit .SBLK == 0 && puser_row1 -> bit .PSZ == 0 )
482+ {
483+ printf ("SmartEEPROM not configured, proceed.\n" );
484+ }
485+ else
486+ {
487+ printf ("SmartEEPROM already configured - SBLK: 0x%04x - PSZ: 0x%03x.\n" , puser_row1 -> bit .SBLK , puser_row1 -> bit .PSZ );
488+ if (force_smarteeprom_config )
489+ {
490+ printf ("--forceeep enabled, proceed.\n" );
491+ }
492+ else
493+ {
494+ printf ("Use --forceeep to force to configure it anyway.\n" );
495+ return ;
496+ }
497+ }
498+
499+ // Set SmartEEPROM Virtual Size.
500+ puser_row1 -> bit .SBLK = 0x1 ; // 1 block
501+ puser_row1 -> bit .PSZ = 0x1 ; // 8 bytes
502+ write_user_row (user_row );
503+ }
504+
385505//Upper case any lower case characters in a string
386506void strlower (char * str )
387507{
@@ -495,6 +615,8 @@ void display_help(void)
495615 printf (" -s --size size Read firmware size of <size>\n" );
496616 printf (" -D --download file Write firmware from <file> into device\n" );
497617 printf (" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n" );
618+ printf (" --smarteep Enable Smart EEPROM MCU feature\n" );
619+ printf (" --forceeep Force re-configuration of Smart EEPROM MCU feature. Requires --smarteep.\n" );
498620 printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
499621 printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
500622 printf (" --restart Restart device after successful programming\n" );
@@ -503,11 +625,13 @@ void display_help(void)
503625
504626#define SW_COLS 1000
505627#define SW_COLW 1001
628+ #define SW_SMARTEEP 1002
506629
507630//Program command line options
508631struct option long_options [] = {
509632 //Flags
510633 { "restart" , no_argument , & restart_after_program , 1 },
634+ { "forceeep" , no_argument , & force_smarteeprom_config , 1 },
511635 //Other
512636 { "verbose" , no_argument , 0 , 'v' },
513637 { "help" , no_argument , 0 , 'h' },
@@ -520,6 +644,7 @@ struct option long_options[] = {
520644 { "addr" , required_argument , 0 , 'a' },
521645 { "size" , required_argument , 0 , 's' },
522646 { "test" , no_argument , 0 , 't' },
647+ { "smarteep" , no_argument , 0 , SW_SMARTEEP },
523648 { "cols" , required_argument , 0 , SW_COLS },
524649 { "colw" , required_argument , 0 , SW_COLW },
525650 { 0 , 0 , 0 , 0 }
@@ -533,6 +658,7 @@ int main(int argc, char *argv[])
533658 restart_after_program = 0 ;
534659 hex_cols = COLS ;
535660 hex_colw = COLW ;
661+ force_smarteeprom_config = 0 ;
536662
537663 display_version ();
538664 display_copyright ();
@@ -633,6 +759,10 @@ int main(int argc, char *argv[])
633759 testmode = 1 ;
634760 break ;
635761
762+ case SW_SMARTEEP :
763+ command = CMD_CONFIG_SMARTEEPROM ;
764+ break ;
765+
636766 case SW_COLS :
637767 hex_cols = atoi (optarg );
638768 if (hex_cols < 1 )
@@ -754,7 +884,17 @@ int main(int argc, char *argv[])
754884 printf ("Found MCU: %s\n" , mcu -> name );
755885
756886 print_bootloader_version ();
887+
757888 if (verbose ) printf ("Device ID: %08X\n" , mcu -> cidr );
889+ if (command == CMD_CONFIG_SMARTEEPROM )
890+ {
891+ configure_smarteeprom ();
892+
893+ if (restart_after_program )
894+ jump_application ();
895+
896+ goto exitProgram ;
897+ }
758898
759899
760900 memcpy (& appinfo , applet_data + applet_size - sizeof (appinfo_t ), sizeof (appinfo_t ));
0 commit comments