@@ -377,6 +377,110 @@ int test_mcu(char silent)
377377 return 1 ;
378378}
379379
380+ // SmartEEPROM NVMCTRL section
381+ int write_user_row (uint32_t * data )
382+ {
383+ //Set WMODE to Manual
384+ NVMCTRL_CTRLA_Type ctrla ;
385+ ctrla .reg = read_half_word (NVMCTRL_CTRLA );
386+ 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 );
387+ ctrla .bit .WMODE = NVMCTRL_CTRLA_WMODE_MAN ;
388+
389+ printf ("Configuring SmartEEPROM... " );
390+
391+ if (!write_half_word (NVMCTRL_CTRLA , ctrla .reg ))
392+ {
393+ printf ("Error setting NVMCTRL.CTRLA.WMODE to Manual\n" );
394+ return 0 ;
395+ }
396+ slp (100 );
397+
398+ // Set user row address
399+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
400+ {
401+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (1)\n" );
402+ return 0 ;
403+ }
404+
405+ // Erase page
406+ NVMCTRL_CTRLB_Type ctrlb ;
407+ ctrlb .reg = 0 ;
408+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_EP ;
409+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
410+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
411+ {
412+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Erase page)\n" , ctrlb .reg );
413+ return 0 ;
414+ }
415+ slp (100 );
416+
417+ // Page buffer clear
418+ ctrlb .reg = 0 ;
419+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_PBC ;
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 (Page buffer clear)\n" , ctrlb .reg );
424+ return 0 ;
425+ }
426+ slp (100 );
427+
428+ // Write in the write buffer
429+ for (int i = 0 ; i < 4 ; i ++ )
430+ {
431+ if (!write_word (NVMCTRL_USER + i * 4 , data [i ]))
432+ {
433+ printf ("Warning: Unable to write NVMCTRL_USER page %i\n" , i );
434+ }
435+ slp (100 );
436+ }
437+
438+ if (!write_word (NVMCTRL_ADDR , NVMCTRL_USER ))
439+ {
440+ printf ("Error setting NVMCTRL_ADDR to NVMCTRL_USER (2)\n" );
441+ return 0 ;
442+ }
443+ slp (100 );
444+
445+ // Write quad word (128bits)
446+ ctrlb .reg = 0 ;
447+ ctrlb .bit .CMD = NVMCTRL_CTRLB_CMD_WQW ;
448+ ctrlb .bit .CMDEX = NVMCTRL_CTRLB_CMDEX_KEY ;
449+ if (!write_half_word (NVMCTRL_CTRLB , ctrlb .reg ))
450+ {
451+ printf ("Error setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word)\n" , ctrlb .reg );
452+ return 0 ;
453+ }
454+
455+ printf ("Success!\n" );
456+ return 1 ;
457+ }
458+
459+ void read_user_row (void )
460+ {
461+ uint32_t user_row [4 ];
462+ printf ("user row: " );
463+ for (int i = 0 ; i < 4 ; i ++ )
464+ {
465+ user_row [i ] = read_word (NVMCTRL_USER + i * 4 );
466+ printf ("0x%08x " , user_row [i ]);
467+ }
468+ printf ("\n" );
469+
470+ NVMCTRL_USER_ROW_MAPPING1_Type * puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type * )(& user_row [1 ]);
471+ if (puser_row1 -> bit .SBLK == 0 && puser_row1 -> bit .PSZ == 0 )
472+ {
473+ printf ("SmartEEPROM not configured, proceed\n" );
474+ puser_row1 -> bit .SBLK = 0x2 ; // 2 blocks
475+ puser_row1 -> bit .PSZ = 0x1 ; // 8 bytes
476+ write_user_row (user_row );
477+ }
478+ else
479+ {
480+ printf ("SmartEEPROM already configured - SBLK: 0x%04x - PSZ: 0x%03x\n" , puser_row1 -> bit .SBLK , puser_row1 -> bit .PSZ );
481+ }
482+ }
483+
380484//Upper case any lower case characters in a string
381485void strlower (char * str )
382486{
@@ -490,6 +594,7 @@ void display_help(void)
490594 printf (" -s --size size Read firmware size of <size>\n" );
491595 printf (" -D --download file Write firmware from <file> into device\n" );
492596 printf (" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n" );
597+ printf (" --smarteep Enable Smart EEPROM MCU feature\n" );
493598 printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
494599 printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
495600 printf (" --restart Restart device after successful programming\n" );
@@ -498,6 +603,7 @@ void display_help(void)
498603
499604#define SW_COLS 1000
500605#define SW_COLW 1001
606+ #define SW_SMARTEEP 1002
501607
502608//Program command line options
503609struct option long_options [] = {
@@ -515,6 +621,7 @@ struct option long_options[] = {
515621 { "addr" , required_argument , 0 , 'a' },
516622 { "size" , required_argument , 0 , 's' },
517623 { "test" , no_argument , 0 , 't' },
624+ { "smarteep" , no_argument , 0 , SW_SMARTEEP },
518625 { "cols" , required_argument , 0 , SW_COLS },
519626 { "colw" , required_argument , 0 , SW_COLW },
520627 { 0 , 0 , 0 , 0 }
@@ -628,6 +735,10 @@ int main(int argc, char *argv[])
628735 testmode = 1 ;
629736 break ;
630737
738+ case SW_SMARTEEP :
739+ command = CMD_READ_USER_ROW ;
740+ break ;
741+
631742 case SW_COLS :
632743 hex_cols = atoi (optarg );
633744 if (hex_cols < 1 )
@@ -751,14 +862,24 @@ int main(int argc, char *argv[])
751862 print_bootloader_version ();
752863 if (verbose ) printf ("Device ID: %08X\n" , mcu -> cidr );
753864
865+ if (command == CMD_READ_USER_ROW )
866+ {
867+ read_user_row ();
868+
869+ if (restart_after_program )
870+ jump_application ();
871+
872+ goto exitProgram ;
873+ }
874+
754875 //Load applet
755876 FILE * fIn ;
756877 char appletfname [128 ] = "" ;
757878 strlower (mcu -> name );
758879
759880 //sprintf(appletfname, "applet-flash-%s.bin", mcu->name);
760881 sprintf (appletfname , "applet-mdflash.bin" ); //make filename non-dependent upon mcu->name
761-
882+
762883 printf ("Applet file: %s\n" , appletfname );
763884
764885 fIn = fopen (appletfname , "rb" );
0 commit comments