@@ -31,6 +31,7 @@ char first_device;
31
31
int restart_after_program ;
32
32
int hex_cols ;
33
33
int hex_colw ;
34
+ int force_smarteeprom_config ;
34
35
35
36
//SAM-BA Settings
36
37
mailbox_t initparams ;
@@ -382,6 +383,137 @@ int test_mcu(char silent)
382
383
return 1 ;
383
384
}
384
385
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
+
385
517
//Upper case any lower case characters in a string
386
518
void strlower (char * str )
387
519
{
@@ -495,6 +627,8 @@ void display_help(void)
495
627
printf (" -s --size size Read firmware size of <size>\n" );
496
628
printf (" -D --download file Write firmware from <file> into device\n" );
497
629
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" );
498
632
printf (" --cols count Hex listing column count <count> [%i]\n" , COLS );
499
633
printf (" --colw width Hex listing column width <width> [%i]\n" , COLW );
500
634
printf (" --restart Restart device after successful programming\n" );
@@ -503,11 +637,13 @@ void display_help(void)
503
637
504
638
#define SW_COLS 1000
505
639
#define SW_COLW 1001
640
+ #define SW_SMARTEEP 1002
506
641
507
642
//Program command line options
508
643
struct option long_options [] = {
509
644
//Flags
510
645
{ "restart" , no_argument , & restart_after_program , 1 },
646
+ { "forceeep" , no_argument , & force_smarteeprom_config , 1 },
511
647
//Other
512
648
{ "verbose" , no_argument , 0 , 'v' },
513
649
{ "help" , no_argument , 0 , 'h' },
@@ -520,6 +656,7 @@ struct option long_options[] = {
520
656
{ "addr" , required_argument , 0 , 'a' },
521
657
{ "size" , required_argument , 0 , 's' },
522
658
{ "test" , no_argument , 0 , 't' },
659
+ { "smarteep" , no_argument , 0 , SW_SMARTEEP },
523
660
{ "cols" , required_argument , 0 , SW_COLS },
524
661
{ "colw" , required_argument , 0 , SW_COLW },
525
662
{ 0 , 0 , 0 , 0 }
@@ -533,6 +670,7 @@ int main(int argc, char *argv[])
533
670
restart_after_program = 0 ;
534
671
hex_cols = COLS ;
535
672
hex_colw = COLW ;
673
+ force_smarteeprom_config = 0 ;
536
674
537
675
display_version ();
538
676
display_copyright ();
@@ -633,6 +771,10 @@ int main(int argc, char *argv[])
633
771
testmode = 1 ;
634
772
break ;
635
773
774
+ case SW_SMARTEEP :
775
+ command = CMD_CONFIG_SMARTEEPROM ;
776
+ break ;
777
+
636
778
case SW_COLS :
637
779
hex_cols = atoi (optarg );
638
780
if (hex_cols < 1 )
@@ -754,7 +896,17 @@ int main(int argc, char *argv[])
754
896
printf ("Found MCU: %s\n" , mcu -> name );
755
897
756
898
print_bootloader_version ();
899
+
757
900
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
+ }
758
910
759
911
760
912
memcpy (& appinfo , applet_data + applet_size - sizeof (appinfo_t ), sizeof (appinfo_t ));
0 commit comments