Skip to content

Commit 1ca9830

Browse files
committed
Rework of 49
1 parent 41e9c89 commit 1ca9830

File tree

2 files changed

+226
-0
lines changed

2 files changed

+226
-0
lines changed

mdloader_common.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ char verbose;
2929
char testmode;
3030
char first_device;
3131
int restart_after_program;
32+
int force_smarteeprom_config;
3233
int hex_cols;
3334
int hex_colw;
3435

@@ -382,6 +383,132 @@ int test_mcu(char silent)
382383
return 1;
383384
}
384385

386+
// SmartEEPROM NVMCTRL section
387+
uint8_t 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+
if (verbose) 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("SmartEEPROM: Configuring... ");
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+
slp(SLEEP_BETWEEN_WRITES);
463+
464+
printf("Success!\n");
465+
return 1;
466+
}
467+
468+
uint8_t configure_smarteeprom(void)
469+
{
470+
// Configure for 2048 bytes - DS60001507E-page 653
471+
#define TARGET_SBLK 1 // 1 block
472+
#define TARGET_PSZ 2 // 16 bytes
473+
474+
uint32_t user_row[4];
475+
for (int i = 0; i < 4; i++)
476+
{
477+
user_row[i] = read_word(NVMCTRL_USER + i * 4);
478+
}
479+
480+
NVMCTRL_USER_ROW_MAPPING1_Type* puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type*)(&user_row[1]);
481+
482+
if (verbose) printf("SmartEEPROM: config - SBLK: 0x%04x - PSZ: 0x%03x.\n", puser_row1->bit.SBLK, puser_row1->bit.PSZ);
483+
484+
if(puser_row1->bit.SBLK == TARGET_SBLK && puser_row1->bit.PSZ == TARGET_PSZ)
485+
{
486+
if (verbose) printf("SmartEEPROM: Configured!\n");
487+
return 1;
488+
}
489+
490+
uint8_t should_reconfigure;
491+
if(force_smarteeprom_config == FORCE_NONE)
492+
{
493+
should_reconfigure = prompt_yes_no("SmartEEPROM: Your settings do not match the recommended values. Update setting?");
494+
}
495+
else
496+
{
497+
should_reconfigure = (force_smarteeprom_config == FORCE_YES);
498+
}
499+
500+
if(!should_reconfigure)
501+
{
502+
printf("SmartEEPROM: Skipped!\n");
503+
return 1;
504+
}
505+
506+
// Set SmartEEPROM Virtual Size.
507+
puser_row1->bit.SBLK = TARGET_SBLK;
508+
puser_row1->bit.PSZ = TARGET_PSZ;
509+
return write_user_row(user_row);
510+
}
511+
385512
//Upper case any lower case characters in a string
386513
void strlower(char *str)
387514
{
@@ -404,6 +531,21 @@ void strupper(char *str)
404531
}
405532
}
406533

534+
//Prompt for Yy/Nn with message
535+
uint8_t prompt_yes_no(const char* msg)
536+
{
537+
printf(msg);
538+
printf(" (y/n):\n");
539+
540+
char c;
541+
do {
542+
scanf(" %c", &c);
543+
c = toupper(c);
544+
} while(c != 'N' && c != 'Y');
545+
546+
return c == 'Y';
547+
}
548+
407549
//Return file size of given file
408550
int filesize(char *fname)
409551
{
@@ -495,6 +637,7 @@ void display_help(void)
495637
printf(" -s --size size Read firmware size of <size>\n");
496638
printf(" -D --download file Write firmware from <file> into device\n");
497639
printf(" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n");
640+
printf(" --forceeep answer Automatic answer to Smart EEPROM re-configuration prompt <y/n>\n");
498641
printf(" --cols count Hex listing column count <count> [%i]\n", COLS);
499642
printf(" --colw width Hex listing column width <width> [%i]\n", COLW);
500643
printf(" --restart Restart device after successful programming\n");
@@ -503,6 +646,7 @@ void display_help(void)
503646

504647
#define SW_COLS 1000
505648
#define SW_COLW 1001
649+
#define SW_FORCEEEP 1002
506650

507651
//Program command line options
508652
struct option long_options[] = {
@@ -522,6 +666,7 @@ struct option long_options[] = {
522666
{ "test", no_argument, 0, 't' },
523667
{ "cols", required_argument, 0, SW_COLS },
524668
{ "colw", required_argument, 0, SW_COLW },
669+
{ "forceeep", required_argument, 0, SW_FORCEEEP },
525670
{ 0, 0, 0, 0 }
526671
};
527672

@@ -531,6 +676,7 @@ int main(int argc, char *argv[])
531676
testmode = 0;
532677
first_device = 0;
533678
restart_after_program = 0;
679+
force_smarteeprom_config = FORCE_NONE;
534680
hex_cols = COLS;
535681
hex_colw = COLW;
536682

@@ -651,6 +797,11 @@ int main(int argc, char *argv[])
651797
}
652798
break;
653799

800+
case SW_FORCEEEP:
801+
strlower(optarg);
802+
force_smarteeprom_config = (strstr(optarg, "y") != NULL) ? FORCE_YES : FORCE_NO;
803+
break;
804+
654805
default:
655806
command = CMD_ABORT;
656807
break;
@@ -756,7 +907,13 @@ int main(int argc, char *argv[])
756907
print_bootloader_version();
757908
if (verbose) printf("Device ID: %08X\n", mcu->cidr);
758909

910+
if (!configure_smarteeprom())
911+
{
912+
printf("Error: Config feature failed!\n");
913+
goto closePort;
914+
}
759915

916+
//Load applet
760917
memcpy(&appinfo, applet_data + applet_size - sizeof(appinfo_t), sizeof(appinfo_t));
761918
if (appinfo.magic != 0x4142444D)
762919
{

mdloader_common.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <string.h>
4747
#include <stdint.h>
4848
#include <getopt.h>
49+
#include <ctype.h>
4950

5051
//Atmel files
5152
#include "./atmel/applet.h"
@@ -163,6 +164,7 @@ int read_byte(int addr);
163164
int read_half_word(int addr);
164165
int read_word(int addr);
165166
int set_terminal_mode(void);
167+
uint8_t configure_smarteeprom(void);
166168

167169
//OS specific commands
168170
void print_com_example(void);
@@ -181,8 +183,75 @@ int filesize(char *fname);
181183
int read_data(int addr, int readsize);
182184
int write_data(int addr, int writesize, int data);
183185
void list_devices(char *first);
186+
187+
// helpers
184188
void strupper(char *str);
185189
void strlower(char *str);
190+
uint8_t prompt_yes_no(const char* msg);
191+
192+
// Smart EEPROM specific
193+
#define NVMCTRL 0x41004000
194+
#define NVMCTRL_CTRLA (NVMCTRL)
195+
#define NVMCTRL_CTRLB (NVMCTRL + 4)
196+
#define NVMCTRL_ADDR (NVMCTRL + 0x14)
197+
198+
#define NVMCTRL_CTRLA_WMODE_MAN 0x0
199+
#define NVMCTRL_CTRLB_CMDEX_KEY 0xA5
200+
#define NVMCTRL_CTRLB_CMD_WQW 0x4
201+
#define NVMCTRL_CTRLB_CMD_PBC 0x15
202+
#define NVMCTRL_CTRLB_CMD_EP 0x0
203+
204+
#define NVMCTRL_USER 0x00804000
205+
206+
#define SLEEP_BETWEEN_WRITES 200
207+
208+
enum eep_force_type {
209+
FORCE_NONE = 0,
210+
FORCE_NO,
211+
FORCE_YES,
212+
};
213+
214+
typedef union {
215+
struct {
216+
uint32_t SBLK : 4; /* bit: 35:32 - Number of NVM Blocks composing a SmartEEPROM sector */
217+
uint32_t PSZ : 3; /* bit: 38:36 - SmartEEPROM Page Size */
218+
uint32_t RAM_ECCDIS : 1; /* bit: 39 - RAM ECC Disable */
219+
uint32_t : 8; /* bit: 47:40 - Factory settings - do not change */
220+
uint32_t WDT_ENABLE : 1; /* bit: 48 - WDT Enable at power-on */
221+
uint32_t WDT_ALWAYS_ON : 1; /* bit: 49 - WDT Always-On at power-on */
222+
uint32_t WDT_PERIOD : 4; /* bit: 53:50 - WDT Period at power-on */
223+
uint32_t WDT_WINDOW : 4; /* bit: 57:54 - WDT Window mode time-out at power - on */
224+
uint32_t WDT_EWOFFSET : 4; /* bit: 61:58 - WDT Early Warning Interrupt Time Offset at power - on */
225+
uint32_t WDT_WEN : 1; /* bit: 62 - WDT Window Mode Enable at power - on */
226+
uint32_t : 1; /* bit: 63 - Factory settings - do not change */
227+
} bit;
228+
uint32_t reg;
229+
} NVMCTRL_USER_ROW_MAPPING1_Type;
230+
231+
typedef union {
232+
struct {
233+
uint16_t : 2; /* bit: 1:0 Reserved */
234+
uint16_t AUTOWS : 1; /* bit: 2 Auto Wait State Enable */
235+
uint16_t SUSPEN : 1; /* bit: 3 Suspend Enable */
236+
uint16_t WMODE : 2; /* bit: 5:4 Write Mode */
237+
uint16_t PRM : 2; /* bit: 7:6 Power Reduction Mode during Sleep */
238+
uint16_t RWS : 4; /* bit: 11:8 NVM Read Wait States */
239+
uint16_t AHBNS0 : 1; /* bit: 12 Force AHB0 access to NONSEQ, burst transfers are continuously rearbitrated */
240+
uint16_t AHBNS1 : 1; /* bit: 13 Force AHB1 access to NONSEQ, burst transfers are continuously rearbitrated */
241+
uint16_t CACHEDIS0 : 1; /* bit: 14 AHB0 Cache Disable */
242+
uint16_t CACHEDIS1 : 1; /* bit: 15 AHB1 Cache Disable */
243+
} bit;
244+
uint16_t reg;
245+
} NVMCTRL_CTRLA_Type;
246+
247+
typedef union {
248+
struct {
249+
uint16_t CMD : 7; /* bit: 6:0 Command */
250+
uint16_t : 1; /* bit: 7 Reserved */
251+
uint16_t CMDEX : 8; /* bit: 15:8 Command Execution */
252+
} bit;
253+
uint16_t reg;
254+
} NVMCTRL_CTRLB_Type;
186255

187256
#endif //_MDLOADER_COMMON_H
188257

0 commit comments

Comments
 (0)