From f5563d26148c546d77cd4c03cf78daf243895abd Mon Sep 17 00:00:00 2001 From: zvecr Date: Thu, 30 Sep 2021 22:39:11 +0100 Subject: [PATCH 1/6] Rework of 49 to latest requirements --- mdloader_common.c | 124 +++++++++++++++++++++++++++++++++++++++++++++- mdloader_common.h | 66 ++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/mdloader_common.c b/mdloader_common.c index e3cd2f1..9286178 100644 --- a/mdloader_common.c +++ b/mdloader_common.c @@ -29,6 +29,7 @@ char verbose; char testmode; char first_device; int restart_after_program; +int ignore_smarteeprom_config; int hex_cols; int hex_colw; @@ -382,6 +383,118 @@ int test_mcu(char silent) return 1; } +// SmartEEPROM NVMCTRL section +uint8_t write_user_row(uint32_t* data) +{ + //Read the current state of NVMCTRL.CTRLA + NVMCTRL_CTRLA_Type ctrla; + ctrla.reg = read_half_word(NVMCTRL_CTRLA); + 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); + + printf("SmartEEPROM: Configuring... "); + + //Set WMODE to Manual + ctrla.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN; + if (!write_half_word(NVMCTRL_CTRLA, ctrla.reg)) + { + printf("Error: setting NVMCTRL.CTRLA.WMODE to Manual.\n"); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + + // Set user row address + if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER)) + { + printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n"); + return 0; + } + + // Erase page + NVMCTRL_CTRLB_Type ctrlb; + ctrlb.reg = 0; + ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_EP; + ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY; + if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg)) + { + printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n", ctrlb.reg); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + + // Page buffer clear + ctrlb.reg = 0; + ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_PBC; + ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY; + if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg)) + { + printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n", ctrlb.reg); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + + // Write in the write buffer + for (int i = 0; i < 4; i++) + { + if (!write_word(NVMCTRL_USER + i * 4, data[i])) + { + printf("Error: Unable to write NVMCTRL_USER page %i.\n", i); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + } + + if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER)) + { + printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n"); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + + // Write quad word (128bits) + ctrlb.reg = 0; + ctrlb.bit.CMD = NVMCTRL_CTRLB_CMD_WQW; + ctrlb.bit.CMDEX = NVMCTRL_CTRLB_CMDEX_KEY; + if (!write_half_word(NVMCTRL_CTRLB, ctrlb.reg)) + { + printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n", ctrlb.reg); + return 0; + } + slp(SLEEP_BETWEEN_WRITES); + + printf("Success!\n"); + return 1; +} + +uint8_t configure_smarteeprom(void) +{ + uint32_t user_row[4]; + for (int i = 0; i < 4; i++) + { + user_row[i] = read_word(NVMCTRL_USER + i * 4); + } + + NVMCTRL_USER_ROW_MAPPING1_Type* puser_row1 = (NVMCTRL_USER_ROW_MAPPING1_Type*)(&user_row[1]); + + if (verbose) printf("SmartEEPROM: config - SBLK: 0x%04x - PSZ: 0x%03x.\n", puser_row1->bit.SBLK, puser_row1->bit.PSZ); + + if(puser_row1->bit.SBLK == SMARTEEPROM_TARGET_SBLK && puser_row1->bit.PSZ == SMARTEEPROM_TARGET_PSZ) + { + if (verbose) printf("SmartEEPROM: Configured!\n"); + return 1; + } + + if(ignore_smarteeprom_config) + { + printf("SmartEEPROM: Your settings do not match the recommended values. Skipped!"); + return 1; + } + + // Set SmartEEPROM Virtual Size. + puser_row1->bit.SBLK = SMARTEEPROM_TARGET_SBLK; + puser_row1->bit.PSZ = SMARTEEPROM_TARGET_PSZ; + return write_user_row(user_row); +} + //Upper case any lower case characters in a string void strlower(char *str) { @@ -495,6 +608,7 @@ void display_help(void) printf(" -s --size size Read firmware size of \n"); printf(" -D --download file Write firmware from into device\n"); printf(" -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled)\n"); + printf(" --ignore-eep Ignore differences in SmartEEPROM configuration\n"); printf(" --cols count Hex listing column count [%i]\n", COLS); printf(" --colw width Hex listing column width [%i]\n", COLW); printf(" --restart Restart device after successful programming\n"); @@ -507,7 +621,8 @@ void display_help(void) //Program command line options struct option long_options[] = { //Flags - { "restart", no_argument, &restart_after_program, 1 }, + { "restart", no_argument, &restart_after_program, 1 }, + { "ignore-eep", no_argument, &ignore_smarteeprom_config, 1 }, //Other { "verbose", no_argument, 0, 'v' }, { "help", no_argument, 0, 'h' }, @@ -531,6 +646,7 @@ int main(int argc, char *argv[]) testmode = 0; first_device = 0; restart_after_program = 0; + ignore_smarteeprom_config = 0; hex_cols = COLS; hex_colw = COLW; @@ -756,7 +872,13 @@ int main(int argc, char *argv[]) print_bootloader_version(); if (verbose) printf("Device ID: %08X\n", mcu->cidr); + if (!configure_smarteeprom()) + { + printf("Error: Config feature failed!\n"); + goto closePort; + } + //Load applet memcpy(&appinfo, applet_data + applet_size - sizeof(appinfo_t), sizeof(appinfo_t)); if (appinfo.magic != 0x4142444D) { diff --git a/mdloader_common.h b/mdloader_common.h index 0bd8575..fe83544 100644 --- a/mdloader_common.h +++ b/mdloader_common.h @@ -46,6 +46,7 @@ #include #include #include +#include //Atmel files #include "./atmel/applet.h" @@ -163,6 +164,7 @@ int read_byte(int addr); int read_half_word(int addr); int read_word(int addr); int set_terminal_mode(void); +uint8_t configure_smarteeprom(void); //OS specific commands void print_com_example(void); @@ -181,8 +183,72 @@ int filesize(char *fname); int read_data(int addr, int readsize); int write_data(int addr, int writesize, int data); void list_devices(char *first); + +// helpers void strupper(char *str); void strlower(char *str); +// Smart EEPROM specific +#define NVMCTRL 0x41004000 +#define NVMCTRL_CTRLA (NVMCTRL) +#define NVMCTRL_CTRLB (NVMCTRL + 4) +#define NVMCTRL_ADDR (NVMCTRL + 0x14) + +#define NVMCTRL_CTRLA_WMODE_MAN 0x0 +#define NVMCTRL_CTRLB_CMDEX_KEY 0xA5 +#define NVMCTRL_CTRLB_CMD_WQW 0x4 +#define NVMCTRL_CTRLB_CMD_PBC 0x15 +#define NVMCTRL_CTRLB_CMD_EP 0x0 + +#define NVMCTRL_USER 0x00804000 + +#define SLEEP_BETWEEN_WRITES 200 + +// Configured for 2048 bytes - DS60001507E-page 653 +#define SMARTEEPROM_TARGET_SBLK 1 // 1 block +#define SMARTEEPROM_TARGET_PSZ 2 // 16 bytes + +typedef union { + struct { + uint32_t SBLK : 4; /* bit: 35:32 - Number of NVM Blocks composing a SmartEEPROM sector */ + uint32_t PSZ : 3; /* bit: 38:36 - SmartEEPROM Page Size */ + uint32_t RAM_ECCDIS : 1; /* bit: 39 - RAM ECC Disable */ + uint32_t : 8; /* bit: 47:40 - Factory settings - do not change */ + uint32_t WDT_ENABLE : 1; /* bit: 48 - WDT Enable at power-on */ + uint32_t WDT_ALWAYS_ON : 1; /* bit: 49 - WDT Always-On at power-on */ + uint32_t WDT_PERIOD : 4; /* bit: 53:50 - WDT Period at power-on */ + uint32_t WDT_WINDOW : 4; /* bit: 57:54 - WDT Window mode time-out at power - on */ + uint32_t WDT_EWOFFSET : 4; /* bit: 61:58 - WDT Early Warning Interrupt Time Offset at power - on */ + uint32_t WDT_WEN : 1; /* bit: 62 - WDT Window Mode Enable at power - on */ + uint32_t : 1; /* bit: 63 - Factory settings - do not change */ + } bit; + uint32_t reg; +} NVMCTRL_USER_ROW_MAPPING1_Type; + +typedef union { + struct { + uint16_t : 2; /* bit: 1:0 Reserved */ + uint16_t AUTOWS : 1; /* bit: 2 Auto Wait State Enable */ + uint16_t SUSPEN : 1; /* bit: 3 Suspend Enable */ + uint16_t WMODE : 2; /* bit: 5:4 Write Mode */ + uint16_t PRM : 2; /* bit: 7:6 Power Reduction Mode during Sleep */ + uint16_t RWS : 4; /* bit: 11:8 NVM Read Wait States */ + uint16_t AHBNS0 : 1; /* bit: 12 Force AHB0 access to NONSEQ, burst transfers are continuously rearbitrated */ + uint16_t AHBNS1 : 1; /* bit: 13 Force AHB1 access to NONSEQ, burst transfers are continuously rearbitrated */ + uint16_t CACHEDIS0 : 1; /* bit: 14 AHB0 Cache Disable */ + uint16_t CACHEDIS1 : 1; /* bit: 15 AHB1 Cache Disable */ + } bit; + uint16_t reg; +} NVMCTRL_CTRLA_Type; + +typedef union { + struct { + uint16_t CMD : 7; /* bit: 6:0 Command */ + uint16_t : 1; /* bit: 7 Reserved */ + uint16_t CMDEX : 8; /* bit: 15:8 Command Execution */ + } bit; + uint16_t reg; +} NVMCTRL_CTRLB_Type; + #endif //_MDLOADER_COMMON_H From 739078cabb413bd108ef288fd242b4df08332fa8 Mon Sep 17 00:00:00 2001 From: zvecr Date: Wed, 6 Oct 2021 22:23:36 +0100 Subject: [PATCH 2/6] update wording --- mdloader_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdloader_common.c b/mdloader_common.c index 9286178..a1028a4 100644 --- a/mdloader_common.c +++ b/mdloader_common.c @@ -485,7 +485,7 @@ uint8_t configure_smarteeprom(void) if(ignore_smarteeprom_config) { - printf("SmartEEPROM: Your settings do not match the recommended values. Skipped!"); + printf("SmartEEPROM: Your settings do not match the recommended values - Some functionality may not work as expected!"); return 1; } From 773ab51f1f0f4aa8a5c182978657779a7379938f Mon Sep 17 00:00:00 2001 From: zvecr Date: Wed, 6 Oct 2021 22:26:28 +0100 Subject: [PATCH 3/6] update readme usage --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 84e3bd7..08ac833 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Usage: mdloader [options] ... -s --size size Read firmware size of -D --download file Write firmware from into device -t --test Test mode (download/upload writes disabled, upload outputs data to stdout, restart disabled) + --ignore-eep Ignore differences in SmartEEPROM configuration --cols count Hex listing column count [8] --colw width Hex listing column width [4] --restart Restart device after successful programming From fd6754d38d0993b17002c7d2875c4187a0b21412 Mon Sep 17 00:00:00 2001 From: zvecr Date: Thu, 7 Oct 2021 03:09:17 +0100 Subject: [PATCH 4/6] Add progress hints due to sleeps --- mdloader_common.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/mdloader_common.c b/mdloader_common.c index a1028a4..c67c4b3 100644 --- a/mdloader_common.c +++ b/mdloader_common.c @@ -383,6 +383,12 @@ int test_mcu(char silent) return 1; } +static void sleep_between_writes(void) +{ + printf("."); + slp(SLEEP_BETWEEN_WRITES); +} + // SmartEEPROM NVMCTRL section uint8_t write_user_row(uint32_t* data) { @@ -391,7 +397,7 @@ uint8_t write_user_row(uint32_t* data) ctrla.reg = read_half_word(NVMCTRL_CTRLA); 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); - printf("SmartEEPROM: Configuring... "); + printf("SmartEEPROM: Configuring..."); //Set WMODE to Manual ctrla.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN; @@ -400,7 +406,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL.CTRLA.WMODE to Manual.\n"); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); // Set user row address if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER)) @@ -408,6 +414,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (1).\n"); return 0; } + sleep_between_writes(); // Erase page NVMCTRL_CTRLB_Type ctrlb; @@ -419,7 +426,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Erase page).\n", ctrlb.reg); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); // Page buffer clear ctrlb.reg = 0; @@ -430,7 +437,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Page buffer clear).\n", ctrlb.reg); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); // Write in the write buffer for (int i = 0; i < 4; i++) @@ -440,7 +447,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: Unable to write NVMCTRL_USER page %i.\n", i); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); } if (!write_word(NVMCTRL_ADDR, NVMCTRL_USER)) @@ -448,7 +455,7 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL_ADDR to NVMCTRL_USER (2).\n"); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); // Write quad word (128bits) ctrlb.reg = 0; @@ -459,9 +466,9 @@ uint8_t write_user_row(uint32_t* data) printf("Error: setting NVMCTRL_CTRLB to 0x%04x (Write Quad Word).\n", ctrlb.reg); return 0; } - slp(SLEEP_BETWEEN_WRITES); + sleep_between_writes(); - printf("Success!\n"); + printf(" Success!\n"); return 1; } From 619e47545ce487781492e57a3c09c3fc438c3e31 Mon Sep 17 00:00:00 2001 From: zvecr Date: Sat, 9 Oct 2021 20:33:00 +0100 Subject: [PATCH 5/6] flush stdout --- mdloader_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mdloader_common.c b/mdloader_common.c index c67c4b3..5e642de 100644 --- a/mdloader_common.c +++ b/mdloader_common.c @@ -386,6 +386,7 @@ int test_mcu(char silent) static void sleep_between_writes(void) { printf("."); + fflush(stdout); slp(SLEEP_BETWEEN_WRITES); } From 289aa792590747cd252012c5fdcb918b26c93a60 Mon Sep 17 00:00:00 2001 From: just-another-jxliu Date: Wed, 13 Oct 2021 13:03:36 -0700 Subject: [PATCH 6/6] Update mdloader_common.h Co-authored-by: Joel Challis --- mdloader_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mdloader_common.h b/mdloader_common.h index fe83544..7f8d26b 100644 --- a/mdloader_common.h +++ b/mdloader_common.h @@ -204,9 +204,9 @@ void strlower(char *str); #define SLEEP_BETWEEN_WRITES 200 -// Configured for 2048 bytes - DS60001507E-page 653 +// Configured for 4096 bytes - DS60001507E-page 653 #define SMARTEEPROM_TARGET_SBLK 1 // 1 block -#define SMARTEEPROM_TARGET_PSZ 2 // 16 bytes +#define SMARTEEPROM_TARGET_PSZ 3 // 32 bytes typedef union { struct {