Skip to content

Commit 22a719b

Browse files
Add SmartEEPROM Support (#62)
* Rework of 49 to latest requirements * update wording * update readme usage * Add progress hints due to sleeps * flush stdout * Update mdloader_common.h Co-authored-by: Joel Challis <[email protected]> Co-authored-by: just-another-jxliu <[email protected]>
1 parent 063b37e commit 22a719b

File tree

3 files changed

+198
-1
lines changed

3 files changed

+198
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Usage: mdloader [options] ...
7474
-s --size size Read firmware size of <size>
7575
-D --download file Write firmware from <file> into device
7676
-t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)
77+
--ignore-eep Ignore differences in SmartEEPROM configuration
7778
--cols count Hex listing column count <count> [8]
7879
--colw width Hex listing column width <width> [4]
7980
--restart Restart device after successful programming

mdloader_common.c

Lines changed: 131 additions & 1 deletion
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 ignore_smarteeprom_config;
3233
int hex_cols;
3334
int hex_colw;
3435

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

386+
static void sleep_between_writes(void)
387+
{
388+
printf(".");
389+
fflush(stdout);
390+
slp(SLEEP_BETWEEN_WRITES);
391+
}
392+
393+
// SmartEEPROM NVMCTRL section
394+
uint8_t write_user_row(uint32_t* data)
395+
{
396+
//Read the current state of NVMCTRL.CTRLA
397+
NVMCTRL_CTRLA_Type ctrla;
398+
ctrla.reg = read_half_word(NVMCTRL_CTRLA);
399+
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);
400+
401+
printf("SmartEEPROM: Configuring...");
402+
403+
//Set WMODE to Manual
404+
ctrla.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN;
405+
if (!write_half_word(NVMCTRL_CTRLA, ctrla.reg))
406+
{
407+
printf("Error: setting NVMCTRL.CTRLA.WMODE to Manual.\n");
408+
return 0;
409+
}
410+
sleep_between_writes();
411+
412+
// Set user row address
413+
if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER))
414+
{
415+
printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n");
416+
return 0;
417+
}
418+
sleep_between_writes();
419+
420+
// Erase page
421+
NVMCTRL_CTRLB_Type ctrlb;
422+
ctrlb.reg = 0;
423+
ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_EP;
424+
ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY;
425+
if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg))
426+
{
427+
printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n", ctrlb.reg);
428+
return 0;
429+
}
430+
sleep_between_writes();
431+
432+
// Page buffer clear
433+
ctrlb.reg = 0;
434+
ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_PBC;
435+
ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY;
436+
if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg))
437+
{
438+
printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n", ctrlb.reg);
439+
return 0;
440+
}
441+
sleep_between_writes();
442+
443+
// Write in the write buffer
444+
for (int i = 0; i < 4; i++)
445+
{
446+
if (!write_word(NVMCTRL_USER + i * 4, data[i]))
447+
{
448+
printf("Error: Unable to write NVMCTRL_USER page %i.\n", i);
449+
return 0;
450+
}
451+
sleep_between_writes();
452+
}
453+
454+
if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER))
455+
{
456+
printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n");
457+
return 0;
458+
}
459+
sleep_between_writes();
460+
461+
// Write quad word (128bits)
462+
ctrlb.reg = 0;
463+
ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_WQW;
464+
ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY;
465+
if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg))
466+
{
467+
printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n", ctrlb.reg);
468+
return 0;
469+
}
470+
sleep_between_writes();
471+
472+
printf(" Success!\n");
473+
return 1;
474+
}
475+
476+
uint8_t configure_smarteeprom(void)
477+
{
478+
uint32_t user_row[4];
479+
for (int i = 0; i < 4; i++)
480+
{
481+
user_row[i] = read_word(NVMCTRL_USER + i * 4);
482+
}
483+
484+
NVMCTRL_USER_ROW_MAPPING1_Type* puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type*)(&user_row[1]);
485+
486+
if (verbose) printf("SmartEEPROM: config - SBLK: 0x%04x - PSZ: 0x%03x.\n", puser_row1->bit.SBLK, puser_row1->bit.PSZ);
487+
488+
if(puser_row1->bit.SBLK == SMARTEEPROM_TARGET_SBLK && puser_row1->bit.PSZ == SMARTEEPROM_TARGET_PSZ)
489+
{
490+
if (verbose) printf("SmartEEPROM: Configured!\n");
491+
return 1;
492+
}
493+
494+
if(ignore_smarteeprom_config)
495+
{
496+
printf("SmartEEPROM: Your settings do not match the recommended values - Some functionality may not work as expected!");
497+
return 1;
498+
}
499+
500+
// Set SmartEEPROM Virtual Size.
501+
puser_row1->bit.SBLK = SMARTEEPROM_TARGET_SBLK;
502+
puser_row1->bit.PSZ = SMARTEEPROM_TARGET_PSZ;
503+
return write_user_row(user_row);
504+
}
505+
385506
//Upper case any lower case characters in a string
386507
void strlower(char *str)
387508
{
@@ -495,6 +616,7 @@ void display_help(void)
495616
printf(" -s --size size Read firmware size of <size>\n");
496617
printf(" -D --download file Write firmware from <file> into device\n");
497618
printf(" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n");
619+
printf(" --ignore-eep Ignore differences in SmartEEPROM configuration\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");
@@ -507,7 +629,8 @@ void display_help(void)
507629
//Program command line options
508630
struct option long_options[] = {
509631
//Flags
510-
{ "restart", no_argument, &restart_after_program, 1 },
632+
{ "restart", no_argument, &restart_after_program, 1 },
633+
{ "ignore-eep", no_argument, &ignore_smarteeprom_config, 1 },
511634
//Other
512635
{ "verbose", no_argument, 0, 'v' },
513636
{ "help", no_argument, 0, 'h' },
@@ -531,6 +654,7 @@ int main(int argc, char *argv[])
531654
testmode = 0;
532655
first_device = 0;
533656
restart_after_program = 0;
657+
ignore_smarteeprom_config = 0;
534658
hex_cols = COLS;
535659
hex_colw = COLW;
536660

@@ -756,7 +880,13 @@ int main(int argc, char *argv[])
756880
print_bootloader_version();
757881
if (verbose) printf("Device ID: %08X\n", mcu->cidr);
758882

883+
if (!configure_smarteeprom())
884+
{
885+
printf("Error: Config feature failed!\n");
886+
goto closePort;
887+
}
759888

889+
//Load applet
760890
memcpy(&appinfo, applet_data + applet_size - sizeof(appinfo_t), sizeof(appinfo_t));
761891
if (appinfo.magic != 0x4142444D)
762892
{

mdloader_common.h

Lines changed: 66 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,72 @@ 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);
186190

191+
// Smart EEPROM specific
192+
#define NVMCTRL 0x41004000
193+
#define NVMCTRL_CTRLA (NVMCTRL)
194+
#define NVMCTRL_CTRLB (NVMCTRL + 4)
195+
#define NVMCTRL_ADDR (NVMCTRL + 0x14)
196+
197+
#define NVMCTRL_CTRLA_WMODE_MAN 0x0
198+
#define NVMCTRL_CTRLB_CMDEX_KEY 0xA5
199+
#define NVMCTRL_CTRLB_CMD_WQW 0x4
200+
#define NVMCTRL_CTRLB_CMD_PBC 0x15
201+
#define NVMCTRL_CTRLB_CMD_EP 0x0
202+
203+
#define NVMCTRL_USER 0x00804000
204+
205+
#define SLEEP_BETWEEN_WRITES 200
206+
207+
// Configured for 4096 bytes - DS60001507E-page 653
208+
#define SMARTEEPROM_TARGET_SBLK 1 // 1 block
209+
#define SMARTEEPROM_TARGET_PSZ 3 // 32 bytes
210+
211+
typedef union {
212+
struct {
213+
uint32_t SBLK : 4; /* bit: 35:32 - Number of NVM Blocks composing a SmartEEPROM sector */
214+
uint32_t PSZ : 3; /* bit: 38:36 - SmartEEPROM Page Size */
215+
uint32_t RAM_ECCDIS : 1; /* bit: 39 - RAM ECC Disable */
216+
uint32_t : 8; /* bit: 47:40 - Factory settings - do not change */
217+
uint32_t WDT_ENABLE : 1; /* bit: 48 - WDT Enable at power-on */
218+
uint32_t WDT_ALWAYS_ON : 1; /* bit: 49 - WDT Always-On at power-on */
219+
uint32_t WDT_PERIOD : 4; /* bit: 53:50 - WDT Period at power-on */
220+
uint32_t WDT_WINDOW : 4; /* bit: 57:54 - WDT Window mode time-out at power - on */
221+
uint32_t WDT_EWOFFSET : 4; /* bit: 61:58 - WDT Early Warning Interrupt Time Offset at power - on */
222+
uint32_t WDT_WEN : 1; /* bit: 62 - WDT Window Mode Enable at power - on */
223+
uint32_t : 1; /* bit: 63 - Factory settings - do not change */
224+
} bit;
225+
uint32_t reg;
226+
} NVMCTRL_USER_ROW_MAPPING1_Type;
227+
228+
typedef union {
229+
struct {
230+
uint16_t : 2; /* bit: 1:0 Reserved */
231+
uint16_t AUTOWS : 1; /* bit: 2 Auto Wait State Enable */
232+
uint16_t SUSPEN : 1; /* bit: 3 Suspend Enable */
233+
uint16_t WMODE : 2; /* bit: 5:4 Write Mode */
234+
uint16_t PRM : 2; /* bit: 7:6 Power Reduction Mode during Sleep */
235+
uint16_t RWS : 4; /* bit: 11:8 NVM Read Wait States */
236+
uint16_t AHBNS0 : 1; /* bit: 12 Force AHB0 access to NONSEQ, burst transfers are continuously rearbitrated */
237+
uint16_t AHBNS1 : 1; /* bit: 13 Force AHB1 access to NONSEQ, burst transfers are continuously rearbitrated */
238+
uint16_t CACHEDIS0 : 1; /* bit: 14 AHB0 Cache Disable */
239+
uint16_t CACHEDIS1 : 1; /* bit: 15 AHB1 Cache Disable */
240+
} bit;
241+
uint16_t reg;
242+
} NVMCTRL_CTRLA_Type;
243+
244+
typedef union {
245+
struct {
246+
uint16_t CMD : 7; /* bit: 6:0 Command */
247+
uint16_t : 1; /* bit: 7 Reserved */
248+
uint16_t CMDEX : 8; /* bit: 15:8 Command Execution */
249+
} bit;
250+
uint16_t reg;
251+
} NVMCTRL_CTRLB_Type;
252+
187253
#endif //_MDLOADER_COMMON_H
188254

0 commit comments

Comments
 (0)