From 24c302752ee54e39106ed914972d814314a009d1 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 Dec 2016 22:53:44 +0100 Subject: [PATCH 01/68] flash/nor/at91sam4: remove FWS=6, rename at91samg to atsamg FWS=6 workaround removed, as this appears to be a copy-paste error from the SAM3X family. Originally addressed in http://openocd.zylin.com/3837 but not all occurences were removed. Atmel changed chip naming and removed 91 prefix for atsamg, samd... Change-Id: Ia2b43da82b2ff9b1c85fdb456a0a198ab095243d Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3926 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/at91sam4.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index ff75b4188..d101c9b4c 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -464,7 +464,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -499,7 +499,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -532,7 +532,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -565,7 +565,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -598,7 +598,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -631,7 +631,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -1279,7 +1279,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -1295,7 +1295,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 1, .base_address = FLASH_BANK1_BASE_1024K_SD, .controller_address = 0x400e0c00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -1305,10 +1305,10 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /* at91samg53n19 */ + /* atsamg53n19 */ { .chipid_cidr = 0x247e0ae0, - .name = "at91samg53n19", + .name = "atsamg53n19", .total_flash_size = 512 * 1024, .total_sram_size = 96 * 1024, .n_gpnvms = 2, @@ -1323,7 +1323,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, From 278f63174d6f09bd45edd4fcf8f2bf85b3ff9096 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 14 Jul 2016 20:52:13 +0200 Subject: [PATCH 02/68] flash/nor: at91samd modified to use real erase sector size Before this change SAMD driver defined "sector" equal to a flash protection block. Oversize sectors (16kB for the biggest flash size) made problems for flashing firmware split to two or more parts. Removed superfluous test of sector protection before erase. Change-Id: I8e6a6bda6ccd91eda2df67ec48270c69faa1bdd1 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3546 Tested-by: jenkins Reviewed-by: Stian Skjelstad Reviewed-by: Freddie Chopin --- src/flash/nor/at91samd.c | 83 ++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index f018e893d..ad88c5143 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -25,7 +25,7 @@ #include -#define SAMD_NUM_SECTORS 16 +#define SAMD_NUM_PROT_BLOCKS 16 #define SAMD_PAGE_SIZE_MAX 1024 #define SAMD_FLASH ((uint32_t)0x00000000) /* physical Flash memory */ @@ -286,6 +286,7 @@ struct samd_info { uint32_t page_size; int num_pages; int sector_size; + int prot_block_size; bool probed; struct target *target; @@ -319,7 +320,7 @@ static const struct samd_part *samd_find_part(uint32_t id) static int samd_protect_check(struct flash_bank *bank) { - int res; + int res, prot_block; uint16_t lock; res = target_read_u16(bank->target, @@ -328,8 +329,8 @@ static int samd_protect_check(struct flash_bank *bank) return res; /* Lock bits are active-low */ - for (int i = 0; i < bank->num_sectors; i++) - bank->sectors[i].is_protected = !(lock & (1<num_prot_blocks; prot_block++) + bank->prot_blocks[prot_block].is_protected = !(lock & (1u<size = part->flash_kb * 1024; - chip->sector_size = bank->size / SAMD_NUM_SECTORS; - res = samd_get_flash_page_info(bank->target, &chip->page_size, &chip->num_pages); if (res != ERROR_OK) { @@ -397,21 +396,23 @@ static int samd_probe(struct flash_bank *bank) part->flash_kb, chip->num_pages, chip->page_size); } + /* Erase granularity = 1 row = 4 pages */ + chip->sector_size = chip->page_size * 4; + /* Allocate the sector table */ - bank->num_sectors = SAMD_NUM_SECTORS; - bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); + bank->num_sectors = chip->num_pages / 4; + bank->sectors = alloc_block_array(0, chip->sector_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; - /* Fill out the sector information: all SAMD sectors are the same size and - * there is always a fixed number of them. */ - for (int i = 0; i < bank->num_sectors; i++) { - bank->sectors[i].size = chip->sector_size; - bank->sectors[i].offset = i * chip->sector_size; - /* mark as unknown */ - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = -1; - } + /* 16 protection blocks per device */ + chip->prot_block_size = bank->size / SAMD_NUM_PROT_BLOCKS; + + /* Allocate the table of protection blocks */ + bank->num_prot_blocks = SAMD_NUM_PROT_BLOCKS; + bank->prot_blocks = alloc_block_array(0, chip->prot_block_size, bank->num_prot_blocks); + if (!bank->prot_blocks) + return ERROR_FAIL; samd_protect_check(bank); @@ -606,9 +607,10 @@ out_user_row: return res; } -static int samd_protect(struct flash_bank *bank, int set, int first, int last) +static int samd_protect(struct flash_bank *bank, int set, int first_prot_bl, int last_prot_bl) { - struct samd_info *chip = (struct samd_info *)bank->driver_priv; + int res = ERROR_OK; + int prot_block; /* We can issue lock/unlock region commands with the target running but * the settings won't persist unless we're able to modify the LOCK regions @@ -618,18 +620,16 @@ static int samd_protect(struct flash_bank *bank, int set, int first, int last) return ERROR_TARGET_NOT_HALTED; } - int res = ERROR_OK; - - for (int s = first; s <= last; s++) { - if (set != bank->sectors[s].is_protected) { - /* Load an address that is within this sector (we use offset 0) */ + for (prot_block = first_prot_bl; prot_block <= last_prot_bl; prot_block++) { + if (set != bank->prot_blocks[prot_block].is_protected) { + /* Load an address that is within this protection block (we use offset 0) */ res = target_write_u32(bank->target, SAMD_NVMCTRL + SAMD_NVMCTRL_ADDR, - ((s * chip->sector_size) >> 1)); + bank->prot_blocks[prot_block].offset >> 1); if (res != ERROR_OK) goto exit; - /* Tell the controller to lock that sector */ + /* Tell the controller to lock that block */ res = samd_issue_nvmctrl_command(bank->target, set ? SAMD_NVM_CMD_LR : SAMD_NVM_CMD_UR); if (res != ERROR_OK) @@ -644,7 +644,7 @@ static int samd_protect(struct flash_bank *bank, int set, int first, int last) * locked. See Table 9-3 in the SAMD20 datasheet for more details. */ res = samd_modify_user_row(bank->target, set ? 0x0000 : 0xFFFF, - 48 + first, 48 + last); + 48 + first_prot_bl, 48 + last_prot_bl); if (res != ERROR_OK) LOG_WARNING("SAMD: protect settings were not made persistent!"); @@ -656,10 +656,9 @@ exit: return res; } -static int samd_erase(struct flash_bank *bank, int first, int last) +static int samd_erase(struct flash_bank *bank, int first_sect, int last_sect) { - int res; - int rows_in_sector; + int res, s; struct samd_info *chip = (struct samd_info *)bank->driver_priv; if (bank->target->state != TARGET_HALTED) { @@ -673,26 +672,12 @@ static int samd_erase(struct flash_bank *bank, int first, int last) return ERROR_FLASH_BANK_NOT_PROBED; } - /* The SAMD NVM has row erase granularity. There are four pages in a row - * and the number of rows in a sector depends on the sector size, which in - * turn depends on the Flash capacity as there is a fixed number of - * sectors. */ - rows_in_sector = chip->sector_size / (chip->page_size * 4); - /* For each sector to be erased */ - for (int s = first; s <= last; s++) { - if (bank->sectors[s].is_protected) { - LOG_ERROR("SAMD: failed to erase sector %d. That sector is write-protected", s); - return ERROR_FLASH_OPERATION_FAILED; - } - - /* For each row in that sector */ - for (int r = s * rows_in_sector; r < (s + 1) * rows_in_sector; r++) { - res = samd_erase_row(bank->target, r * chip->page_size * 4); - if (res != ERROR_OK) { - LOG_ERROR("SAMD: failed to erase sector %d", s); - return res; - } + for (s = first_sect; s <= last_sect; s++) { + res = samd_erase_row(bank->target, bank->sectors[s].offset); + if (res != ERROR_OK) { + LOG_ERROR("SAMD: failed to erase sector %d at 0x%08" PRIx32, s, bank->sectors[s].offset); + return res; } } From a0a504569b5ae4d6e485414c43be0fd4bb216bab Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 30 Nov 2016 21:48:59 +0100 Subject: [PATCH 03/68] flash Kinetis: add KE1xZ and KE1xF families MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new Kinetis KE1x families use FTFE flash controller unlike KE0x. Also SDID coding corresponds to new K, KL and KV families. That's why KE1x is handled by kinetis driver instead of kinetis_ke Change-Id: Ibb73e28e41dfbb086e761e1f006b089825dab854 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3896 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- doc/openocd.texi | 4 +++- src/flash/nor/kinetis.c | 53 ++++++++++++++++++++++++++++++++++++++--- tcl/target/ke1xf.cfg | 9 +++++++ tcl/target/ke1xz.cfg | 9 +++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 tcl/target/ke1xf.cfg create mode 100644 tcl/target/ke1xz.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index 59d2d4f1a..24d4a8994 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5361,10 +5361,12 @@ nor is Chip Erase (only Sector Erase is implemented).} @deffn {Flash Driver} kinetis @cindex kinetis -Kx and KLx members of the Kinetis microcontroller family from Freescale include +Kx, KLx, KVx and KE1x members of the Kinetis microcontroller family +from NXP (former Freescale) include internal flash and use ARM Cortex-M0+ or M4 cores. The driver automatically recognizes flash size and a number of flash banks (1-4) using the chip identification register, and autoconfigures itself. +Use kinetis_ke driver for KE0x devices. @example flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 7e9bbdef4..86d3154c5 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -89,6 +89,7 @@ #define FLEXRAM 0x14000000 +#define MSCM_OCMDR0 0x40001400 #define FMC_PFB01CR 0x4001f004 #define FTFx_FSTAT 0x40020000 #define FTFx_FCNFG 0x40020001 @@ -187,6 +188,7 @@ #define KINETIS_SDID_SERIESID_MASK 0x00F00000 #define KINETIS_SDID_SERIESID_K 0x00000000 #define KINETIS_SDID_SERIESID_KL 0x00100000 +#define KINETIS_SDID_SERIESID_KE 0x00200000 #define KINETIS_SDID_SERIESID_KW 0x00500000 #define KINETIS_SDID_SERIESID_KV 0x00600000 @@ -198,6 +200,8 @@ #define KINETIS_SDID_SUBFAMID_KX4 0x04000000 #define KINETIS_SDID_SUBFAMID_KX5 0x05000000 #define KINETIS_SDID_SUBFAMID_KX6 0x06000000 +#define KINETIS_SDID_SUBFAMID_KX7 0x07000000 +#define KINETIS_SDID_SUBFAMID_KX8 0x08000000 #define KINETIS_SDID_FAMILYID_MASK 0xF0000000 #define KINETIS_SDID_FAMILYID_K0X 0x00000000 @@ -209,6 +213,11 @@ #define KINETIS_SDID_FAMILYID_K7X 0x70000000 #define KINETIS_SDID_FAMILYID_K8X 0x80000000 +/* The field originally named DIEID has new name/meaning on KE1x */ +#define KINETIS_SDID_PROJECTID_MASK KINETIS_SDID_DIEID_MASK +#define KINETIS_SDID_PROJECTID_KE1xF 0x00000080 +#define KINETIS_SDID_PROJECTID_KE1xZ 0x00000100 + struct kinetis_flash_bank { bool probed; uint32_t sector_size; @@ -232,9 +241,10 @@ struct kinetis_flash_bank { enum { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, - FS_PROGRAM_PHRASE = 4, /* Unsupported */ - FS_INVALIDATE_CACHE_K = 8, - FS_INVALIDATE_CACHE_L = 0x10, + FS_PROGRAM_PHRASE = 4, /* Unsupported */ + FS_INVALIDATE_CACHE_K = 8, /* using FMC->PFB0CR/PFB01CR */ + FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ + FS_INVALIDATE_CACHE_MSCM = 0x20, } flash_support; }; @@ -1184,9 +1194,16 @@ static void kinetis_invalidate_flash_cache(struct flash_bank *bank) if (kinfo->flash_support & FS_INVALIDATE_CACHE_K) target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0); + /* Set CINV_WAY bits - request invalidate of all cache ways */ + /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */ else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L) target_write_u8(bank->target, MCM_PLACR + 1, 0x04); + /* set bit CFCC - Clear Flash Controller Cache */ + + else if (kinfo->flash_support & FS_INVALIDATE_CACHE_MSCM) + target_write_u32(bank->target, MSCM_OCMDR0, 0x30); + /* disable data prefetch and flash speculate */ return; } @@ -1743,6 +1760,36 @@ static int kinetis_probe(struct flash_bank *bank) } break; + case KINETIS_SDID_SERIESID_KE: + /* KE1x-series */ + switch (kinfo->sim_sdid & + (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) { + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX5 | KINETIS_SDID_PROJECTID_KE1xZ: + /* KE1xZ: FTFE, 2kB sectors */ + pflash_sector_size_bytes = 2<<10; + nvm_sector_size_bytes = 2<<10; + kinfo->max_flash_prog_size = 1<<9; + num_blocks = 2; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + break; + + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xF: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX6 | KINETIS_SDID_PROJECTID_KE1xF: + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX8 | KINETIS_SDID_PROJECTID_KE1xF: + /* KE1xF: FTFE, 4kB sectors */ + pflash_sector_size_bytes = 4<<10; + nvm_sector_size_bytes = 2<<10; + kinfo->max_flash_prog_size = 1<<10; + num_blocks = 2; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + break; + + default: + LOG_ERROR("Unsupported KE FAMILYID SUBFAMID"); + } + break; + default: LOG_ERROR("Unsupported K-series"); } diff --git a/tcl/target/ke1xf.cfg b/tcl/target/ke1xf.cfg new file mode 100644 index 000000000..94b175f2d --- /dev/null +++ b/tcl/target/ke1xf.cfg @@ -0,0 +1,9 @@ +# +# NXP (Freescale) Kinetis KE1xF devices +# + +set CHIPNAME ke + +source [find target/kx.cfg] + +flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/ke1xz.cfg b/tcl/target/ke1xz.cfg new file mode 100644 index 000000000..db2d1a428 --- /dev/null +++ b/tcl/target/ke1xz.cfg @@ -0,0 +1,9 @@ +# +# NXP (Freescale) Kinetis KE1xZ devices +# + +set CHIPNAME ke + +source [find target/klx.cfg] + +flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME From fffe8e672572da46046b12a5d6b037057059393e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 2 Dec 2016 18:09:27 +0100 Subject: [PATCH 04/68] tcl/target: make sure kex.cfg is not used for Kinetis KE1x families MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Config file renamed to ke0x.cfg and a notice added to texi. While on ke0x.cfg CPUTAPID setting fixed: device has SWD port only, no JTAG. Removed per device configs as they set CHIPNAME and nothing more. Let's use reasonably universal chip name 'ke' set in family config. Change-Id: I313db87a59f25f968eb3c27df155780b67becee8 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3897 Tested-by: jenkins Reviewed-by: Ivan Meleca Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- doc/openocd.texi | 5 +++-- tcl/target/ke02.cfg | 6 ------ tcl/target/ke04.cfg | 6 ------ tcl/target/ke06.cfg | 6 ------ tcl/target/{kex.cfg => ke0x.cfg} | 8 ++------ 5 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 tcl/target/ke02.cfg delete mode 100644 tcl/target/ke04.cfg delete mode 100644 tcl/target/ke06.cfg rename tcl/target/{kex.cfg => ke0x.cfg} (90%) diff --git a/doc/openocd.texi b/doc/openocd.texi index 24d4a8994..ac09db5e2 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5448,10 +5448,11 @@ Command disables watchdog timer. @deffn {Flash Driver} kinetis_ke @cindex kinetis_ke -KE members of the Kinetis microcontroller family from Freescale include +KE0x members of the Kinetis microcontroller family from Freescale include internal flash and use ARM Cortex-M0+. The driver automatically recognizes -the KE family and sub-family using the chip identification register, and +the KE0x sub-family using the chip identification register, and autoconfigures itself. +Use kinetis (not kinetis_ke) driver for KE1x devices. @example flash bank $_FLASHNAME kinetis_ke 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/ke02.cfg b/tcl/target/ke02.cfg deleted file mode 100644 index 8311920ad..000000000 --- a/tcl/target/ke02.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# -# Freescale Kinetis KE02 devices -# - -set CHIPNAME ke02 -source [find target/kex.cfg] diff --git a/tcl/target/ke04.cfg b/tcl/target/ke04.cfg deleted file mode 100644 index f63d77c5e..000000000 --- a/tcl/target/ke04.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# -# Freescale Kinetis KE04 devices -# - -set CHIPNAME ke04 -source [find target/kex.cfg] diff --git a/tcl/target/ke06.cfg b/tcl/target/ke06.cfg deleted file mode 100644 index 3465b8b33..000000000 --- a/tcl/target/ke06.cfg +++ /dev/null @@ -1,6 +0,0 @@ -# -# Freescale Kinetis KE06 devices -# - -set CHIPNAME ke06 -source [find target/kex.cfg] diff --git a/tcl/target/kex.cfg b/tcl/target/ke0x.cfg similarity index 90% rename from tcl/target/kex.cfg rename to tcl/target/ke0x.cfg index dca8a35ab..7927e0ae0 100644 --- a/tcl/target/kex.cfg +++ b/tcl/target/ke0x.cfg @@ -1,5 +1,5 @@ # -# Freescale Kinetis KE series devices +# Freescale Kinetis KE0x series devices # source [find target/swj-dp.tcl] @@ -21,11 +21,7 @@ if { [info exists WORKAREASIZE] } { if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { - if { [using_jtag] } { - set _CPUTAPID 0x4ba00477 - } { - set _CPUTAPID 0x2ba01477 - } + set _CPUTAPID 0x0bc11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID From 97d296637e1d08e3198f970ffc2f9f8843d03e49 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 2 Dec 2016 15:47:01 +0100 Subject: [PATCH 05/68] flash Kinetis: add KL8x family, fix erase check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Secure devices KL81Z7 and KL82Z7 have no SERIESID field in ID register so they have to be decoded in Kx branch (not KLx). The flash controller in KL8x and also in K8x devices does not implement FTFx_CMD_BLOCKSTAT command. Fix kinetis_blank_check() to work properly using FTFx_CMD_SECTSTAT command only. Introduce a new flag FS_NO_CMD_BLOCKSTAT to avoid use of FTFx_CMD_BLOCKSTAT on these devices. Change-Id: I3ff58718480acd8cce69f618f71667b6b1d9c4f3 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3898 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 86d3154c5..08f011df4 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -212,6 +212,7 @@ #define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000 #define KINETIS_SDID_FAMILYID_K8X 0x80000000 +#define KINETIS_SDID_FAMILYID_KL8X 0x90000000 /* The field originally named DIEID has new name/meaning on KE1x */ #define KINETIS_SDID_PROJECTID_MASK KINETIS_SDID_DIEID_MASK @@ -245,6 +246,7 @@ struct kinetis_flash_bank { FS_INVALIDATE_CACHE_K = 8, /* using FMC->PFB0CR/PFB01CR */ FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ FS_INVALIDATE_CACHE_MSCM = 0x20, + FS_NO_CMD_BLOCKSTAT = 0x40, } flash_support; }; @@ -849,6 +851,12 @@ static int kinetis_ftfx_decode_error(uint8_t fstat) return ERROR_FLASH_OPERATION_FAILED; } +static int kinetis_ftfx_clear_error(struct target *target) +{ + /* reset error flags */ + return target_write_u8(target, FTFx_FSTAT, 0x70); +} + static int kinetis_ftfx_prepare(struct target *target) { @@ -871,7 +879,7 @@ static int kinetis_ftfx_prepare(struct target *target) } if (fstat != 0x80) { /* reset error flags */ - result = target_write_u8(target, FTFx_FSTAT, 0x70); + result = kinetis_ftfx_clear_error(target); } return result; } @@ -1704,7 +1712,15 @@ static int kinetis_probe(struct flash_bank *bank) /* K80FN256, K81FN256, K82FN256 */ pflash_sector_size_bytes = 4<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + break; + + case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX1: + case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX2: + /* KL81Z128, KL82Z128 */ + pflash_sector_size_bytes = 2<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; break; default: @@ -2094,23 +2110,26 @@ static int kinetis_blank_check(struct flash_bank *bank) return result; if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) { - bool block_dirty = false; + bool block_dirty = true; + bool use_block_cmd = !(kinfo->flash_support & FS_NO_CMD_BLOCKSTAT); uint8_t ftfx_fstat; - if (kinfo->flash_class == FC_FLEX_NVM) { + if (use_block_cmd && kinfo->flash_class == FC_FLEX_NVM) { uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */ if (fcfg1_depart != 0xf && fcfg1_depart != 0) - block_dirty = true; + use_block_cmd = false; } - if (!block_dirty) { + if (use_block_cmd) { /* check if whole bank is blank */ result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); - if (result != ERROR_OK || (ftfx_fstat & 0x01)) - block_dirty = true; + if (result != ERROR_OK) + kinetis_ftfx_clear_error(bank->target); + else if ((ftfx_fstat & 0x01) == 0) + block_dirty = false; } if (block_dirty) { @@ -2126,6 +2145,7 @@ static int kinetis_blank_check(struct flash_bank *bank) bank->sectors[i].is_erased = !(ftfx_fstat & 0x01); } else { LOG_DEBUG("Ignoring errored PFlash sector blank-check"); + kinetis_ftfx_clear_error(bank->target); bank->sectors[i].is_erased = -1; } } From 16f364a5919567712ba5ec8cd36133941306983f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 3 Dec 2016 12:14:10 +0100 Subject: [PATCH 06/68] flash Kinetis: add KV5x family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real time control MCU has a Cortex-M7 and numerous changes in flash layout. Introduced a new ID of MDM-AP. While on it a LOG_DEBUG format error fixed. Change-Id: I1018660ce0c3dd63ac5e2563408fabff3c3daef7 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3900 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 68 ++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 08f011df4..d386b1bdb 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -209,6 +209,7 @@ #define KINETIS_SDID_FAMILYID_K2X 0x20000000 #define KINETIS_SDID_FAMILYID_K3X 0x30000000 #define KINETIS_SDID_FAMILYID_K4X 0x40000000 +#define KINETIS_SDID_FAMILYID_K5X 0x50000000 #define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000 #define KINETIS_SDID_FAMILYID_K8X 0x80000000 @@ -228,10 +229,6 @@ struct kinetis_flash_bank { /* same as bank->base for pflash, differs for FlexNVM */ uint32_t protection_block; /* number of first protection block in this bank */ - uint32_t sim_sdid; - uint32_t sim_fcfg1; - uint32_t sim_fcfg2; - enum { FC_AUTO = 0, FC_PFLASH, @@ -247,7 +244,15 @@ struct kinetis_flash_bank { FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ FS_INVALIDATE_CACHE_MSCM = 0x20, FS_NO_CMD_BLOCKSTAT = 0x40, + FS_WIDTH_256BIT = 0x80, } flash_support; + + /* device parameters - should be same for all probed banks of one device */ + uint32_t sim_sdid; + uint32_t sim_fcfg1; + uint32_t sim_fcfg2; + + uint32_t progr_accel_ram; }; #define MDM_AP 1 @@ -605,6 +610,7 @@ deassert_reset_and_exit: static const uint32_t kinetis_known_mdm_ids[] = { 0x001C0000, /* Kinetis-K Series */ 0x001C0020, /* Kinetis-L/M/V/E Series */ + 0x001C0030, /* Kinetis with a Cortex-M7, in time of writing KV58 */ }; /* @@ -1251,7 +1257,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) bank->sectors[i].is_erased = 1; - if (bank->base == 0 + if (kinfo->prog_base == 0 && bank->sectors[i].offset <= FCF_ADDRESS && bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) { if (allow_fcf_writes) { @@ -1346,13 +1352,13 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer memset(buffer_aligned, 0xff, size_aligned); memcpy(buffer_aligned + align_begin, buffer, size); - result = target_write_memory(bank->target, FLEXRAM, + result = target_write_memory(bank->target, kinfo->progr_accel_ram, 4, size_aligned / 4, buffer_aligned); LOG_DEBUG("section @ %08" PRIx32 " aligned begin %" PRIu32 ", end %" PRIu32, bank->base + offset, align_begin, align_end); } else - result = target_write_memory(bank->target, FLEXRAM, + result = target_write_memory(bank->target, kinfo->progr_accel_ram, 4, size_aligned / 4, buffer); LOG_DEBUG("write section @ %08" PRIx32 " with length %" PRIu32 " bytes", @@ -1374,8 +1380,16 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer break; } - if (ftfx_fstat & 0x01) + if (ftfx_fstat & 0x01) { LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); + if (kinfo->prog_base == 0 && offset == FCF_ADDRESS + FCF_SIZE + && (kinfo->flash_support & FS_WIDTH_256BIT)) { + LOG_ERROR("Flash write immediately after the end of Flash Config Field shows error"); + LOG_ERROR("because the flash memory is 256 bits wide (data were written correctly)."); + LOG_ERROR("Either change the linker script to add a gap of 16 bytes after FCF"); + LOG_ERROR("or set 'kinetis fcf_source write'"); + } + } buffer += size; offset += size; @@ -1405,7 +1419,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, } } - LOG_DEBUG("flash write @08%" PRIx32, bank->base + offset); + LOG_DEBUG("flash write @ %08" PRIx32, bank->base + offset); if (fallback == 0) { /* program section command */ @@ -1488,6 +1502,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, int result; bool set_fcf = false; int sect = 0; + struct kinetis_flash_bank *kinfo = bank->driver_priv; result = kinetis_check_run_mode(bank->target); if (result != ERROR_OK) @@ -1498,7 +1513,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, if (result != ERROR_OK) return result; - if (bank->base == 0 && !allow_fcf_writes) { + if (kinfo->prog_base == 0 && !allow_fcf_writes) { if (bank->sectors[1].offset <= FCF_ADDRESS) sect = 1; /* 1kb sector, FCF in 2nd sector */ @@ -1520,7 +1535,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, return result; } - result = target_read_memory(bank->target, FCF_ADDRESS, 4, FCF_SIZE / 4, fcf_current); + result = target_read_memory(bank->target, bank->base + FCF_ADDRESS, 4, FCF_SIZE / 4, fcf_current); if (result == ERROR_OK && memcmp(fcf_current, fcf_buffer, FCF_SIZE) == 0) set_fcf = false; @@ -1555,10 +1570,12 @@ static int kinetis_probe(struct flash_bank *bank) uint32_t nvm_size = 0, pf_size = 0, df_size = 0, ee_size = 0; unsigned num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0, pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0; + unsigned maxaddr_shift = 13; struct target *target = bank->target; struct kinetis_flash_bank *kinfo = bank->driver_priv; kinfo->probed = false; + kinfo->progr_accel_ram = FLEXRAM; result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid); if (result != ERROR_OK) @@ -1771,6 +1788,19 @@ static int kinetis_probe(struct flash_bank *bank) kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; + case KINETIS_SDID_FAMILYID_K5X | KINETIS_SDID_SUBFAMID_KX6: + case KINETIS_SDID_FAMILYID_K5X | KINETIS_SDID_SUBFAMID_KX8: + /* KV5x: FTFE, 8kB sectors */ + pflash_sector_size_bytes = 8<<10; + maxaddr_shift = 14; + kinfo->max_flash_prog_size = 1<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_WIDTH_256BIT; + bank->base = 0x10000000; + kinfo->prog_base = 0; + kinfo->progr_accel_ram = 0x18000000; + break; + default: LOG_ERROR("Unsupported KV FAMILYID SUBFAMID"); } @@ -1931,9 +1961,9 @@ static int kinetis_probe(struct flash_bank *bank) * Checking fcfg2_maxaddr0 later in this routine is pointless then */ if (fcfg2_pflsh) - pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks; + pf_size = ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) * num_blocks; else - pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks / 2; + pf_size = ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) * num_blocks / 2; if (pf_size != 2048<<10) LOG_WARNING("SIM_FCFG1 PFSIZE = 0xf: please check if pflash is %u KB", pf_size>>10); @@ -1959,8 +1989,10 @@ static int kinetis_probe(struct flash_bank *bank) /* pflash, banks start at address zero */ kinfo->flash_class = FC_PFLASH; bank->size = (pf_size / num_pflash_blocks); - bank->base = 0x00000000 + bank->size * bank->bank_number; - kinfo->prog_base = bank->base; + if (bank->base == 0) { + bank->base = 0x00000000 + bank->size * bank->bank_number; + kinfo->prog_base = bank->base; + } kinfo->sector_size = pflash_sector_size_bytes; /* pflash is divided into 32 protection areas for * parts with more than 32K of PFlash. For parts with @@ -2013,16 +2045,16 @@ static int kinetis_probe(struct flash_bank *bank) return ERROR_FLASH_BANK_INVALID; } - if (bank->bank_number == 0 && ((uint32_t)fcfg2_maxaddr0 << 13) != bank->size) + if (bank->bank_number == 0 && ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) != bank->size) LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr0); if (fcfg2_pflsh) { - if (bank->bank_number == 1 && ((uint32_t)fcfg2_maxaddr1 << 13) != bank->size) + if (bank->bank_number == 1 && ((uint32_t)fcfg2_maxaddr1 << maxaddr_shift) != bank->size) LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr1); } else { if ((unsigned)bank->bank_number == first_nvm_bank - && ((uint32_t)fcfg2_maxaddr1 << 13) != df_size) + && ((uint32_t)fcfg2_maxaddr1 << maxaddr_shift) != df_size) LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr1); } From 1fdc62ef65b4fc1dfb15507985cdcd90faafa389 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 Dec 2016 10:15:06 +0100 Subject: [PATCH 07/68] flash Kinetis: split kinetis_chip from kinetis_flash_bank MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kinetis flash driver probed and decoded chip repeatedly for each flash bank. Bank ordering used global bank number so multi-target configuration was broken. The change introduces kinetis_probe_chip() which reads SIM SDID and SIM FCFG registers, decodes Kinetis series and family and fills struct kinetis_chip. This probe runs once for all banks. struct kinetis_chip contains pointers to all flash banks embeded in the MCU. It simplifies iteration over all or specific MCU banks. kinetis_probe_chip() generates MCU name and some informational messages are improved. Change-Id: I990db5c63ba490667eec0e5459086d83936662fb Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3924 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 740 ++++++++++++++++++++++++++-------------- 1 file changed, 480 insertions(+), 260 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index d386b1bdb..8ebdbbea6 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -192,6 +192,7 @@ #define KINETIS_SDID_SERIESID_KW 0x00500000 #define KINETIS_SDID_SERIESID_KV 0x00600000 +#define KINETIS_SDID_SUBFAMID_SHIFT 24 #define KINETIS_SDID_SUBFAMID_MASK 0x0F000000 #define KINETIS_SDID_SUBFAMID_KX0 0x00000000 #define KINETIS_SDID_SUBFAMID_KX1 0x01000000 @@ -203,6 +204,7 @@ #define KINETIS_SDID_SUBFAMID_KX7 0x07000000 #define KINETIS_SDID_SUBFAMID_KX8 0x08000000 +#define KINETIS_SDID_FAMILYID_SHIFT 28 #define KINETIS_SDID_FAMILYID_MASK 0xF0000000 #define KINETIS_SDID_FAMILYID_K0X 0x00000000 #define KINETIS_SDID_FAMILYID_K1X 0x10000000 @@ -221,12 +223,15 @@ #define KINETIS_SDID_PROJECTID_KE1xZ 0x00000100 struct kinetis_flash_bank { + struct kinetis_chip *k_chip; bool probed; + unsigned bank_number; /* bank number in particular chip */ + struct flash_bank *bank; + uint32_t sector_size; - uint32_t max_flash_prog_size; uint32_t protection_size; uint32_t prog_base; /* base address for FTFx operations */ - /* same as bank->base for pflash, differs for FlexNVM */ + /* usually same as bank->base for pflash, differs for FlexNVM */ uint32_t protection_block; /* number of first protection block in this bank */ enum { @@ -235,6 +240,31 @@ struct kinetis_flash_bank { FC_FLEX_NVM, FC_FLEX_RAM, } flash_class; +}; + +#define KINETIS_MAX_BANKS 4u + +struct kinetis_chip { + struct target *target; + bool probed; + + uint32_t sim_sdid; + uint32_t sim_fcfg1; + uint32_t sim_fcfg2; + uint32_t fcfg2_maxaddr0_shifted; + uint32_t fcfg2_maxaddr1_shifted; + + unsigned num_pflash_blocks, num_nvm_blocks; + unsigned pflash_sector_size, nvm_sector_size; + unsigned max_flash_prog_size; + + uint32_t pflash_base; + uint32_t pflash_size; + uint32_t nvm_base; + uint32_t nvm_size; /* whole FlexNVM */ + uint32_t dflash_size; /* accessible rest of FlexNVM if EEPROM backup uses part of FlexNVM */ + + uint32_t progr_accel_ram; enum { FS_PROGRAM_SECTOR = 1, @@ -247,14 +277,51 @@ struct kinetis_flash_bank { FS_WIDTH_256BIT = 0x80, } flash_support; - /* device parameters - should be same for all probed banks of one device */ - uint32_t sim_sdid; - uint32_t sim_fcfg1; - uint32_t sim_fcfg2; + char name[40]; - uint32_t progr_accel_ram; + unsigned num_banks; + struct kinetis_flash_bank banks[KINETIS_MAX_BANKS]; }; +struct kinetis_type { + uint32_t sdid; + char *name; +}; + +static const struct kinetis_type kinetis_types_old[] = { + { KINETIS_K_SDID_K10_M50, "MK10D%s5" }, + { KINETIS_K_SDID_K10_M72, "MK10D%s7" }, + { KINETIS_K_SDID_K10_M100, "MK10D%s10" }, + { KINETIS_K_SDID_K10_M120, "MK10F%s12" }, + { KINETIS_K_SDID_K11, "MK11D%s5" }, + { KINETIS_K_SDID_K12, "MK12D%s5" }, + + { KINETIS_K_SDID_K20_M50, "MK20D%s5" }, + { KINETIS_K_SDID_K20_M72, "MK20D%s7" }, + { KINETIS_K_SDID_K20_M100, "MK20D%s10" }, + { KINETIS_K_SDID_K20_M120, "MK20F%s12" }, + { KINETIS_K_SDID_K21_M50, "MK21D%s5" }, + { KINETIS_K_SDID_K21_M120, "MK21F%s12" }, + { KINETIS_K_SDID_K22_M50, "MK22D%s5" }, + { KINETIS_K_SDID_K22_M120, "MK22F%s12" }, + + { KINETIS_K_SDID_K30_M72, "MK30D%s7" }, + { KINETIS_K_SDID_K30_M100, "MK30D%s10" }, + + { KINETIS_K_SDID_K40_M72, "MK40D%s7" }, + { KINETIS_K_SDID_K40_M100, "MK40D%s10" }, + + { KINETIS_K_SDID_K50_M72, "MK50D%s7" }, + { KINETIS_K_SDID_K51_M72, "MK51D%s7" }, + { KINETIS_K_SDID_K53, "MK53D%s10" }, + + { KINETIS_K_SDID_K60_M100, "MK60D%s10" }, + { KINETIS_K_SDID_K60_M150, "MK60F%s15" }, + + { KINETIS_K_SDID_K70_M150, "MK70F%s15" }, +}; + + #define MDM_AP 1 #define MDM_REG_STAT 0x00 @@ -733,20 +800,61 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) return ERROR_OK; } + +static struct kinetis_chip *kinetis_get_chip(struct target *target) +{ + struct flash_bank *bank_iter; + struct kinetis_flash_bank *k_bank; + + /* iterate over all kinetis banks */ + for (bank_iter = flash_bank_list(); bank_iter; bank_iter = bank_iter->next) { + if (bank_iter->driver != &kinetis_flash + || bank_iter->target != target) + continue; + + k_bank = bank_iter->driver_priv; + if (!k_bank) + continue; + + if (k_bank->k_chip) + return k_bank->k_chip; + } + return NULL; +} + FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) { - struct kinetis_flash_bank *bank_info; + struct target *target = bank->target; + struct kinetis_chip *k_chip; + struct kinetis_flash_bank *k_bank; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; LOG_INFO("add flash_bank kinetis %s", bank->name); - bank_info = malloc(sizeof(struct kinetis_flash_bank)); + k_chip = kinetis_get_chip(target); - memset(bank_info, 0, sizeof(struct kinetis_flash_bank)); + if (k_chip == NULL) { + k_chip = calloc(sizeof(struct kinetis_chip), 1); + if (k_chip == NULL) { + LOG_ERROR("No memory"); + return ERROR_FAIL; + } - bank->driver_priv = bank_info; + k_chip->target = target; + } + + if (k_chip->num_banks >= KINETIS_MAX_BANKS) { + LOG_ERROR("Only %u Kinetis flash banks are supported", KINETIS_MAX_BANKS); + return ERROR_FAIL; + } + + bank->driver_priv = k_bank = &(k_chip->banks[k_chip->num_banks]); + k_bank->k_chip = k_chip; + k_bank->bank_number = k_chip->num_banks; + k_bank->bank = bank; + k_chip->num_banks++; return ERROR_OK; } @@ -903,8 +1011,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t buffer_size = 2048; /* Default minimum value */ struct working_area *write_algorithm; struct working_area *source; - struct kinetis_flash_bank *kinfo = bank->driver_priv; - uint32_t address = kinfo->prog_base + offset; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + uint32_t address = k_bank->prog_base + offset; uint32_t end_address; struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; @@ -1014,12 +1122,12 @@ static int kinetis_protect(struct flash_bank *bank, int set, int first, int last static int kinetis_protect_check(struct flash_bank *bank) { - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; int result; int i, b; uint32_t fprot; - if (kinfo->flash_class == FC_PFLASH) { + if (k_bank->flash_class == FC_PFLASH) { /* read protection register */ result = target_read_u32(bank->target, FTFx_FPROT3, &fprot); @@ -1028,7 +1136,7 @@ static int kinetis_protect_check(struct flash_bank *bank) /* Every bit protects 1/32 of the full flash (not necessarily just this bank) */ - } else if (kinfo->flash_class == FC_FLEX_NVM) { + } else if (k_bank->flash_class == FC_FLEX_NVM) { uint8_t fdprot; /* read protection register */ @@ -1043,7 +1151,7 @@ static int kinetis_protect_check(struct flash_bank *bank) return ERROR_FLASH_BANK_INVALID; } - b = kinfo->protection_block; + b = k_bank->protection_block; for (i = 0; i < bank->num_prot_blocks; i++) { if ((fprot >> b) & 1) bank->prot_blocks[i].is_protected = 0; @@ -1063,10 +1171,13 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) uint8_t fsec = 0xfe; /* set MCU unsecure */ uint8_t fdprot = 0xff; int i; + unsigned bank_idx; + unsigned num_blocks; uint32_t pflash_bit; uint8_t dflash_bit; struct flash_bank *bank_iter; - struct kinetis_flash_bank *kinfo; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; memset(fcf, 0xff, FCF_SIZE); @@ -1075,18 +1186,19 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) /* iterate over all kinetis banks */ /* current bank is bank 0, it contains FCF */ - for (bank_iter = bank; bank_iter; bank_iter = bank_iter->next) { - if (bank_iter->driver != &kinetis_flash - || bank_iter->target != bank->target) + num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; + for (bank_idx = 0; bank_idx < num_blocks; bank_idx++) { + k_bank = &(k_chip->banks[bank_idx]); + bank_iter = k_bank->bank; + + if (bank_iter == NULL) { + LOG_WARNING("Missing bank %u configuration, FCF protection flags may be incomplette", bank_idx); continue; + } kinetis_auto_probe(bank_iter); - kinfo = bank->driver_priv; - if (!kinfo) - continue; - - if (kinfo->flash_class == FC_PFLASH) { + if (k_bank->flash_class == FC_PFLASH) { for (i = 0; i < bank_iter->num_prot_blocks; i++) { if (bank_iter->prot_blocks[i].is_protected == 1) fprot &= ~pflash_bit; @@ -1094,7 +1206,7 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) pflash_bit <<= 1; } - } else if (kinfo->flash_class == FC_FLEX_NVM) { + } else if (k_bank->flash_class == FC_FLEX_NVM) { for (i = 0; i < bank_iter->num_prot_blocks; i++) { if (bank_iter->prot_blocks[i].is_protected == 1) fdprot &= ~dflash_bit; @@ -1202,21 +1314,21 @@ static int kinetis_check_run_mode(struct target *target) } -static void kinetis_invalidate_flash_cache(struct flash_bank *bank) +static void kinetis_invalidate_flash_cache(struct kinetis_chip *k_chip) { - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct target *target = k_chip->target; - if (kinfo->flash_support & FS_INVALIDATE_CACHE_K) - target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0); + if (k_chip->flash_support & FS_INVALIDATE_CACHE_K) + target_write_u8(target, FMC_PFB01CR + 2, 0xf0); /* Set CINV_WAY bits - request invalidate of all cache ways */ /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */ - else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L) - target_write_u8(bank->target, MCM_PLACR + 1, 0x04); + else if (k_chip->flash_support & FS_INVALIDATE_CACHE_L) + target_write_u8(target, MCM_PLACR + 1, 0x04); /* set bit CFCC - Clear Flash Controller Cache */ - else if (kinfo->flash_support & FS_INVALIDATE_CACHE_MSCM) - target_write_u32(bank->target, MSCM_OCMDR0, 0x30); + else if (k_chip->flash_support & FS_INVALIDATE_CACHE_MSCM) + target_write_u32(target, MSCM_OCMDR0, 0x30); /* disable data prefetch and flash speculate */ return; @@ -1226,7 +1338,7 @@ static void kinetis_invalidate_flash_cache(struct flash_bank *bank) static int kinetis_erase(struct flash_bank *bank, int first, int last) { int result, i; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; result = kinetis_check_run_mode(bank->target); if (result != ERROR_OK) @@ -1247,7 +1359,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) */ for (i = first; i <= last; i++) { /* set command and sector address */ - result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, kinfo->prog_base + bank->sectors[i].offset, + result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, k_bank->prog_base + bank->sectors[i].offset, 0, 0, 0, 0, 0, 0, 0, 0, NULL); if (result != ERROR_OK) { @@ -1257,7 +1369,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) bank->sectors[i].is_erased = 1; - if (kinfo->prog_base == 0 + if (k_bank->prog_base == 0 && bank->sectors[i].offset <= FCF_ADDRESS && bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) { if (allow_fcf_writes) { @@ -1275,7 +1387,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) } } - kinetis_invalidate_flash_cache(bank); + kinetis_invalidate_flash_cache(k_bank->k_chip); return ERROR_OK; } @@ -1315,7 +1427,8 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer uint32_t offset, uint32_t count) { int result = ERROR_OK; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; uint8_t *buffer_aligned = NULL; /* * Kinetis uses different terms for the granularity of @@ -1323,8 +1436,8 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer * the generic term "chunk". The largest possible * Kinetis "chunk" is 16 bytes (128 bits). */ - uint32_t prog_section_chunk_bytes = kinfo->sector_size >> 8; - uint32_t prog_size_bytes = kinfo->max_flash_prog_size; + uint32_t prog_section_chunk_bytes = k_bank->sector_size >> 8; + uint32_t prog_size_bytes = k_chip->max_flash_prog_size; while (count > 0) { uint32_t size = prog_size_bytes - offset % prog_size_bytes; @@ -1352,13 +1465,13 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer memset(buffer_aligned, 0xff, size_aligned); memcpy(buffer_aligned + align_begin, buffer, size); - result = target_write_memory(bank->target, kinfo->progr_accel_ram, + result = target_write_memory(bank->target, k_chip->progr_accel_ram, 4, size_aligned / 4, buffer_aligned); LOG_DEBUG("section @ %08" PRIx32 " aligned begin %" PRIu32 ", end %" PRIu32, bank->base + offset, align_begin, align_end); } else - result = target_write_memory(bank->target, kinfo->progr_accel_ram, + result = target_write_memory(bank->target, k_chip->progr_accel_ram, 4, size_aligned / 4, buffer); LOG_DEBUG("write section @ %08" PRIx32 " with length %" PRIu32 " bytes", @@ -1371,7 +1484,7 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer /* execute section-write command */ result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTWRITE, - kinfo->prog_base + offset - align_begin, + k_bank->prog_base + offset - align_begin, chunk_count>>8, chunk_count, 0, 0, 0, 0, 0, 0, &ftfx_fstat); @@ -1382,8 +1495,8 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer if (ftfx_fstat & 0x01) { LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); - if (kinfo->prog_base == 0 && offset == FCF_ADDRESS + FCF_SIZE - && (kinfo->flash_support & FS_WIDTH_256BIT)) { + if (k_bank->prog_base == 0 && offset == FCF_ADDRESS + FCF_SIZE + && (k_chip->flash_support & FS_WIDTH_256BIT)) { LOG_ERROR("Flash write immediately after the end of Flash Config Field shows error"); LOG_ERROR("because the flash memory is 256 bits wide (data were written correctly)."); LOG_ERROR("Either change the linker script to add a gap of 16 bytes after FCF"); @@ -1405,9 +1518,10 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { int result, fallback = 0; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; - if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { + if (!(k_chip->flash_support & FS_PROGRAM_SECTOR)) { /* fallback to longword write */ fallback = 1; LOG_INFO("This device supports Program Longword execution only."); @@ -1424,8 +1538,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, if (fallback == 0) { /* program section command */ kinetis_write_sections(bank, buffer, offset, count); - } - else if (kinfo->flash_support & FS_PROGRAM_LONGWORD) { + } else if (k_chip->flash_support & FS_PROGRAM_LONGWORD) { /* program longword command, not supported in FTFE */ uint8_t *new_buffer = NULL; @@ -1452,7 +1565,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t words_remaining = count / 4; - kinetis_disable_wdog(bank->target, kinfo->sim_sdid); + kinetis_disable_wdog(bank->target, k_chip->sim_sdid); /* try using a block write */ result = kinetis_write_block(bank, buffer, offset, words_remaining); @@ -1468,7 +1581,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, LOG_DEBUG("write longword @ %08" PRIx32, (uint32_t)(bank->base + offset)); - result = kinetis_ftfx_command(bank->target, FTFx_CMD_LWORDPROG, kinfo->prog_base + offset, + result = kinetis_ftfx_command(bank->target, FTFx_CMD_LWORDPROG, k_bank->prog_base + offset, buffer[3], buffer[2], buffer[1], buffer[0], 0, 0, 0, 0, &ftfx_fstat); @@ -1491,7 +1604,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, return ERROR_FLASH_OPERATION_FAILED; } - kinetis_invalidate_flash_cache(bank); + kinetis_invalidate_flash_cache(k_chip); return result; } @@ -1502,7 +1615,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, int result; bool set_fcf = false; int sect = 0; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; result = kinetis_check_run_mode(bank->target); if (result != ERROR_OK) @@ -1513,7 +1626,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, if (result != ERROR_OK) return result; - if (kinfo->prog_base == 0 && !allow_fcf_writes) { + if (k_bank->prog_base == 0 && !allow_fcf_writes) { if (bank->sectors[1].offset <= FCF_ADDRESS) sect = 1; /* 1kb sector, FCF in 2nd sector */ @@ -1562,37 +1675,49 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, } -static int kinetis_probe(struct flash_bank *bank) +static int kinetis_probe_chip(struct kinetis_chip *k_chip) { - int result, i; + int result; uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg1_depart; - uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1; - uint32_t nvm_size = 0, pf_size = 0, df_size = 0, ee_size = 0; - unsigned num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0, - pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0; + uint8_t fcfg2_pflsh; + uint32_t ee_size = 0; + uint32_t pflash_size_k, nvm_size_k, dflash_size_k; + uint32_t pflash_size_m; + unsigned num_blocks = 0; unsigned maxaddr_shift = 13; - struct target *target = bank->target; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct target *target = k_chip->target; - kinfo->probed = false; - kinfo->progr_accel_ram = FLEXRAM; + unsigned familyid = 0, subfamid = 0; + unsigned cpu_mhz = 120; + unsigned idx; + bool use_nvm_marking = false; + char flash_marking[8], nvm_marking[2]; + char name[40]; - result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid); + k_chip->probed = false; + k_chip->pflash_sector_size = 0; + k_chip->pflash_base = 0; + k_chip->nvm_base = 0x10000000; + k_chip->progr_accel_ram = FLEXRAM; + + name[0] = '\0'; + + result = target_read_u32(target, SIM_SDID, &k_chip->sim_sdid); if (result != ERROR_OK) return result; - if ((kinfo->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) { + if ((k_chip->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) { /* older K-series MCU */ - uint32_t mcu_type = kinfo->sim_sdid & KINETIS_K_SDID_TYPE_MASK; + uint32_t mcu_type = k_chip->sim_sdid & KINETIS_K_SDID_TYPE_MASK; switch (mcu_type) { case KINETIS_K_SDID_K10_M50: case KINETIS_K_SDID_K20_M50: /* 1kB sectors */ - pflash_sector_size_bytes = 1<<10; - nvm_sector_size_bytes = 1<<10; + k_chip->pflash_sector_size = 1<<10; + k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1602,11 +1727,11 @@ static int kinetis_probe(struct flash_bank *bank) case KINETIS_K_SDID_K40_M100: case KINETIS_K_SDID_K50_M72: /* 2kB sectors, 1kB FlexNVM sectors */ - pflash_sector_size_bytes = 2<<10; - nvm_sector_size_bytes = 1<<10; + k_chip->pflash_sector_size = 2<<10; + k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; - kinfo->max_flash_prog_size = 1<<10; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: case KINETIS_K_SDID_K20_M100: @@ -1618,43 +1743,57 @@ static int kinetis_probe(struct flash_bank *bank) case KINETIS_K_SDID_K53: case KINETIS_K_SDID_K60_M100: /* 2kB sectors */ - pflash_sector_size_bytes = 2<<10; - nvm_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; + k_chip->nvm_sector_size = 2<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: /* 4kB sectors (MK21FN1M0, MK21FX512, MK22FN1M0, MK22FX512) */ - pflash_sector_size_bytes = 4<<10; - kinfo->max_flash_prog_size = 1<<10; - nvm_sector_size_bytes = 4<<10; + k_chip->pflash_sector_size = 4<<10; + k_chip->max_flash_prog_size = 1<<10; + k_chip->nvm_sector_size = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: case KINETIS_K_SDID_K60_M150: case KINETIS_K_SDID_K70_M150: /* 4kB sectors */ - pflash_sector_size_bytes = 4<<10; - nvm_sector_size_bytes = 4<<10; + k_chip->pflash_sector_size = 4<<10; + k_chip->nvm_sector_size = 4<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; default: LOG_ERROR("Unsupported K-family FAMID"); } + + for (idx = 0; idx < ARRAY_SIZE(kinetis_types_old); idx++) { + if (kinetis_types_old[idx].sdid == mcu_type) { + strcpy(name, kinetis_types_old[idx].name); + use_nvm_marking = true; + break; + } + } + } else { /* Newer K-series or KL series MCU */ - switch (kinfo->sim_sdid & KINETIS_SDID_SERIESID_MASK) { + familyid = (k_chip->sim_sdid & KINETIS_SDID_FAMILYID_MASK) >> KINETIS_SDID_FAMILYID_SHIFT; + subfamid = (k_chip->sim_sdid & KINETIS_SDID_SUBFAMID_MASK) >> KINETIS_SDID_SUBFAMID_SHIFT; + + switch (k_chip->sim_sdid & KINETIS_SDID_SERIESID_MASK) { case KINETIS_SDID_SERIESID_K: - switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { + use_nvm_marking = true; + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K0X | KINETIS_SDID_SUBFAMID_KX2: /* K02FN64, K02FN128: FTFA, 2kB sectors */ - pflash_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + cpu_mhz = 100; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { @@ -1664,171 +1803,203 @@ static int kinetis_probe(struct flash_bank *bank) if (result != ERROR_OK) return result; - if (((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN1M) && + if (((k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN1M) && ((sopt1 & KINETIS_SOPT1_RAMSIZE_MASK) == KINETIS_SOPT1_RAMSIZE_K24FN1M)) { /* MK24FN1M */ - pflash_sector_size_bytes = 4<<10; + k_chip->pflash_sector_size = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; - kinfo->max_flash_prog_size = 1<<10; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->max_flash_prog_size = 1<<10; + subfamid = 4; /* errata 1N83J fix */ break; } - if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN128 - || (kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN256 - || (kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN512) { + if ((k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN128 + || (k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN256 + || (k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN512) { /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ - pflash_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); break; } case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX4: - pflash_sector_size_bytes = 4<<10; - if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { + k_chip->pflash_sector_size = 4<<10; + if ((k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; - kinfo->max_flash_prog_size = 1<<10; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->max_flash_prog_size = 1<<10; break; - case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX3: case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX1: /* errata 7534 - should be K63 */ + case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX2: /* errata 7534 - should be K64 */ + subfamid += 2; /* errata 7534 fix */ + case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX3: /* K63FN1M0 */ case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX4: - case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX2: /* errata 7534 - should be K64 */ /* K64FN1M0, K64FX512 */ - pflash_sector_size_bytes = 4<<10; - nvm_sector_size_bytes = 4<<10; - kinfo->max_flash_prog_size = 1<<10; + k_chip->pflash_sector_size = 4<<10; + k_chip->nvm_sector_size = 4<<10; + k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: /* K26FN2M0 */ case KINETIS_SDID_FAMILYID_K6X | KINETIS_SDID_SUBFAMID_KX6: /* K66FN2M0, K66FX1M0 */ - pflash_sector_size_bytes = 4<<10; - nvm_sector_size_bytes = 4<<10; - kinfo->max_flash_prog_size = 1<<10; + k_chip->pflash_sector_size = 4<<10; + k_chip->nvm_sector_size = 4<<10; + k_chip->max_flash_prog_size = 1<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + cpu_mhz = 180; break; case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0: case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1: case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2: /* K80FN256, K81FN256, K82FN256 */ - pflash_sector_size_bytes = 4<<10; + k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + cpu_mhz = 150; break; case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX1: case KINETIS_SDID_FAMILYID_KL8X | KINETIS_SDID_SUBFAMID_KX2: /* KL81Z128, KL82Z128 */ - pflash_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; + use_nvm_marking = false; + snprintf(name, sizeof(name), "MKL8%uZ%%s7", + subfamid); break; default: LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); } + + if (name[0] == '\0') + snprintf(name, sizeof(name), "MK%u%uF%%s%u", + familyid, subfamid, cpu_mhz / 10); break; case KINETIS_SDID_SERIESID_KL: /* KL-series */ - pflash_sector_size_bytes = 1<<10; - nvm_sector_size_bytes = 1<<10; + k_chip->pflash_sector_size = 1<<10; + k_chip->nvm_sector_size = 1<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + + cpu_mhz = 48; + if (subfamid == 3 && (familyid == 1 || familyid == 2)) + subfamid = 7; + snprintf(name, sizeof(name), "MKL%u%uZ%%s%u", + familyid, subfamid, cpu_mhz / 10); break; case KINETIS_SDID_SERIESID_KV: /* KV-series */ - switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0: /* KV10: FTFA, 1kB sectors */ - pflash_sector_size_bytes = 1<<10; + k_chip->pflash_sector_size = 1<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + strcpy(name, "MKV10Z%s7"); break; case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1: /* KV11: FTFA, 2kB sectors */ - pflash_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + strcpy(name, "MKV11Z%s7"); break; case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: /* KV30: FTFA, 2kB sectors, 1 block */ case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1: /* KV31: FTFA, 2kB sectors, 2 blocks */ - pflash_sector_size_bytes = 2<<10; + k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX4: case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX6: /* KV4x: FTFA, 4kB sectors */ - pflash_sector_size_bytes = 4<<10; + k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + cpu_mhz = 168; break; case KINETIS_SDID_FAMILYID_K5X | KINETIS_SDID_SUBFAMID_KX6: case KINETIS_SDID_FAMILYID_K5X | KINETIS_SDID_SUBFAMID_KX8: /* KV5x: FTFE, 8kB sectors */ - pflash_sector_size_bytes = 8<<10; - maxaddr_shift = 14; - kinfo->max_flash_prog_size = 1<<10; + k_chip->pflash_sector_size = 8<<10; + k_chip->max_flash_prog_size = 1<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_WIDTH_256BIT; - bank->base = 0x10000000; - kinfo->prog_base = 0; - kinfo->progr_accel_ram = 0x18000000; + maxaddr_shift = 14; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_WIDTH_256BIT; + k_chip->pflash_base = 0x10000000; + k_chip->progr_accel_ram = 0x18000000; + cpu_mhz = 240; break; default: LOG_ERROR("Unsupported KV FAMILYID SUBFAMID"); } + + if (name[0] == '\0') + snprintf(name, sizeof(name), "MKV%u%uF%%s%u", + familyid, subfamid, cpu_mhz / 10); break; case KINETIS_SDID_SERIESID_KE: /* KE1x-series */ - switch (kinfo->sim_sdid & + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ: case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX5 | KINETIS_SDID_PROJECTID_KE1xZ: /* KE1xZ: FTFE, 2kB sectors */ - pflash_sector_size_bytes = 2<<10; - nvm_sector_size_bytes = 2<<10; - kinfo->max_flash_prog_size = 1<<9; + k_chip->pflash_sector_size = 2<<10; + k_chip->nvm_sector_size = 2<<10; + k_chip->max_flash_prog_size = 1<<9; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + + cpu_mhz = 72; + snprintf(name, sizeof(name), "MKE%u%uZ%%s%u", + familyid, subfamid, cpu_mhz / 10); break; case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xF: case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX6 | KINETIS_SDID_PROJECTID_KE1xF: case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX8 | KINETIS_SDID_PROJECTID_KE1xF: /* KE1xF: FTFE, 4kB sectors */ - pflash_sector_size_bytes = 4<<10; - nvm_sector_size_bytes = 2<<10; - kinfo->max_flash_prog_size = 1<<10; + k_chip->pflash_sector_size = 4<<10; + k_chip->nvm_sector_size = 2<<10; + k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + + cpu_mhz = 168; + snprintf(name, sizeof(name), "MKE%u%uF%%s%u", + familyid, subfamid, cpu_mhz / 10); break; default: @@ -1841,37 +2012,37 @@ static int kinetis_probe(struct flash_bank *bank) } } - if (pflash_sector_size_bytes == 0) { - LOG_ERROR("MCU is unsupported, SDID 0x%08" PRIx32, kinfo->sim_sdid); + if (k_chip->pflash_sector_size == 0) { + LOG_ERROR("MCU is unsupported, SDID 0x%08" PRIx32, k_chip->sim_sdid); return ERROR_FLASH_OPER_UNSUPPORTED; } - result = target_read_u32(target, SIM_FCFG1, &kinfo->sim_fcfg1); + result = target_read_u32(target, SIM_FCFG1, &k_chip->sim_fcfg1); if (result != ERROR_OK) return result; - result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2); + result = target_read_u32(target, SIM_FCFG2, &k_chip->sim_fcfg2); if (result != ERROR_OK) return result; - LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid, - kinfo->sim_fcfg1, kinfo->sim_fcfg2); + LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, k_chip->sim_sdid, + k_chip->sim_fcfg1, k_chip->sim_fcfg2); - fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f); - fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f); - fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f); - fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); + fcfg1_nvmsize = (uint8_t)((k_chip->sim_fcfg1 >> 28) & 0x0f); + fcfg1_pfsize = (uint8_t)((k_chip->sim_fcfg1 >> 24) & 0x0f); + fcfg1_eesize = (uint8_t)((k_chip->sim_fcfg1 >> 16) & 0x0f); + fcfg1_depart = (uint8_t)((k_chip->sim_fcfg1 >> 8) & 0x0f); - fcfg2_pflsh = (uint8_t)((kinfo->sim_fcfg2 >> 23) & 0x01); - fcfg2_maxaddr0 = (uint8_t)((kinfo->sim_fcfg2 >> 24) & 0x7f); - fcfg2_maxaddr1 = (uint8_t)((kinfo->sim_fcfg2 >> 16) & 0x7f); + fcfg2_pflsh = (uint8_t)((k_chip->sim_fcfg2 >> 23) & 0x01); + k_chip->fcfg2_maxaddr0_shifted = ((k_chip->sim_fcfg2 >> 24) & 0x7f) << maxaddr_shift; + k_chip->fcfg2_maxaddr1_shifted = ((k_chip->sim_fcfg2 >> 16) & 0x7f) << maxaddr_shift; if (num_blocks == 0) - num_blocks = fcfg2_maxaddr1 ? 2 : 1; - else if (fcfg2_maxaddr1 == 0 && num_blocks >= 2) { + num_blocks = k_chip->fcfg2_maxaddr1_shifted ? 2 : 1; + else if (k_chip->fcfg2_maxaddr1_shifted == 0 && num_blocks >= 2) { num_blocks = 1; LOG_WARNING("MAXADDR1 is zero, number of flash banks adjusted to 1"); - } else if (fcfg2_maxaddr1 != 0 && num_blocks == 1) { + } else if (k_chip->fcfg2_maxaddr1_shifted != 0 && num_blocks == 1) { num_blocks = 2; LOG_WARNING("MAXADDR1 is non zero, number of flash banks adjusted to 2"); } @@ -1884,17 +2055,17 @@ static int kinetis_probe(struct flash_bank *bank) case 0x07: case 0x09: case 0x0b: - nvm_size = 1 << (14 + (fcfg1_nvmsize >> 1)); + k_chip->nvm_size = 1 << (14 + (fcfg1_nvmsize >> 1)); break; case 0x0f: - if (pflash_sector_size_bytes >= 4<<10) - nvm_size = 512<<10; + if (k_chip->pflash_sector_size >= 4<<10) + k_chip->nvm_size = 512<<10; else /* K20_100 */ - nvm_size = 256<<10; + k_chip->nvm_size = 256<<10; break; default: - nvm_size = 0; + k_chip->nvm_size = 0; break; } @@ -1923,20 +2094,20 @@ static int kinetis_probe(struct flash_bank *bank) case 0x04: case 0x05: case 0x06: - df_size = nvm_size - (4096 << fcfg1_depart); + k_chip->dflash_size = k_chip->nvm_size - (4096 << fcfg1_depart); break; case 0x08: - df_size = 0; + k_chip->dflash_size = 0; break; case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: - df_size = 4096 << (fcfg1_depart & 0x7); + k_chip->dflash_size = 4096 << (fcfg1_depart & 0x7); break; default: - df_size = nvm_size; + k_chip->dflash_size = k_chip->nvm_size; break; } } @@ -1948,7 +2119,7 @@ static int kinetis_probe(struct flash_bank *bank) case 0x09: case 0x0b: case 0x0d: - pf_size = 1 << (14 + (fcfg1_pfsize >> 1)); + k_chip->pflash_size = 1 << (14 + (fcfg1_pfsize >> 1)); break; case 0x0f: /* a peculiar case: Freescale states different sizes for 0xf @@ -1957,104 +2128,155 @@ static int kinetis_probe(struct flash_bank *bank) * K22P121M120SF7RM 512 KB ... duplicate of code 0xb * K22P100M120SF5RM 1024 KB ... duplicate of code 0xd * K26P169M180SF5RM 2048 KB ... the only unique value - * fcfg2_maxaddr0 seems to be the only clue to pf_size - * Checking fcfg2_maxaddr0 later in this routine is pointless then + * fcfg2_maxaddr0 seems to be the only clue to pflash_size + * Checking fcfg2_maxaddr0 in bank probe is pointless then */ if (fcfg2_pflsh) - pf_size = ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) * num_blocks; + k_chip->pflash_size = k_chip->fcfg2_maxaddr0_shifted * num_blocks; else - pf_size = ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) * num_blocks / 2; - if (pf_size != 2048<<10) - LOG_WARNING("SIM_FCFG1 PFSIZE = 0xf: please check if pflash is %u KB", pf_size>>10); + k_chip->pflash_size = k_chip->fcfg2_maxaddr0_shifted * num_blocks / 2; + if (k_chip->pflash_size != 2048<<10) + LOG_WARNING("SIM_FCFG1 PFSIZE = 0xf: please check if pflash is %u KB", k_chip->pflash_size>>10); break; default: - pf_size = 0; + k_chip->pflash_size = 0; break; } - LOG_DEBUG("FlexNVM: %" PRIu32 " PFlash: %" PRIu32 " FlexRAM: %" PRIu32 " PFLSH: %d", - nvm_size, pf_size, ee_size, fcfg2_pflsh); + if (k_chip->flash_support & FS_PROGRAM_SECTOR && k_chip->max_flash_prog_size == 0) { + k_chip->max_flash_prog_size = k_chip->pflash_sector_size; + /* Program section size is equal to sector size by default */ + } - num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh); - first_nvm_bank = num_pflash_blocks; - num_nvm_blocks = num_blocks - num_pflash_blocks; + k_chip->num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh); + k_chip->num_nvm_blocks = num_blocks - k_chip->num_pflash_blocks; - LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM", - num_blocks, num_pflash_blocks, num_nvm_blocks); + if (use_nvm_marking) { + nvm_marking[0] = k_chip->num_nvm_blocks ? 'X' : 'N'; + nvm_marking[1] = '\0'; + } else + nvm_marking[0] = '\0'; - LOG_INFO("Probing flash info for bank %d", bank->bank_number); + pflash_size_k = k_chip->pflash_size / 1024; + pflash_size_m = pflash_size_k / 1024; + if (pflash_size_m) + snprintf(flash_marking, sizeof(flash_marking), "%s%" PRIu32 "M0xxx", nvm_marking, pflash_size_m); + else + snprintf(flash_marking, sizeof(flash_marking), "%s%" PRIu32 "xxx", nvm_marking, pflash_size_k); - if ((unsigned)bank->bank_number < num_pflash_blocks) { + snprintf(k_chip->name, sizeof(k_chip->name), name, flash_marking); + LOG_INFO("Kinetis %s detected: %u flash blocks", k_chip->name, num_blocks); + LOG_INFO("%u PFlash banks: %" PRIu32 "k total", k_chip->num_pflash_blocks, pflash_size_k); + if (k_chip->num_nvm_blocks) { + nvm_size_k = k_chip->nvm_size / 1024; + dflash_size_k = k_chip->dflash_size / 1024; + LOG_INFO("%u FlexNVM banks: %" PRIu32 "k total, %" PRIu32 "k available as data flash, %" PRIu32 "bytes FlexRAM", + k_chip->num_nvm_blocks, nvm_size_k, dflash_size_k, ee_size); + } + + k_chip->probed = true; + return ERROR_OK; +} + +static int kinetis_probe(struct flash_bank *bank) +{ + int result, i; + uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1; + unsigned num_blocks, first_nvm_bank; + uint32_t size_k; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; + + k_bank->probed = false; + + if (!k_chip->probed) { + result = kinetis_probe_chip(k_chip); + if (result != ERROR_OK) + return result; + } + + num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; + first_nvm_bank = k_chip->num_pflash_blocks; + + if (k_bank->bank_number < k_chip->num_pflash_blocks) { /* pflash, banks start at address zero */ - kinfo->flash_class = FC_PFLASH; - bank->size = (pf_size / num_pflash_blocks); - if (bank->base == 0) { - bank->base = 0x00000000 + bank->size * bank->bank_number; - kinfo->prog_base = bank->base; - } - kinfo->sector_size = pflash_sector_size_bytes; + k_bank->flash_class = FC_PFLASH; + bank->size = (k_chip->pflash_size / k_chip->num_pflash_blocks); + bank->base = k_chip->pflash_base + bank->size * k_bank->bank_number; + k_bank->prog_base = 0x00000000 + bank->size * k_bank->bank_number; + k_bank->sector_size = k_chip->pflash_sector_size; /* pflash is divided into 32 protection areas for * parts with more than 32K of PFlash. For parts with * less the protection unit is set to 1024 bytes */ - kinfo->protection_size = MAX(pf_size / 32, 1024); - bank->num_prot_blocks = 32 / num_pflash_blocks; - kinfo->protection_block = bank->num_prot_blocks * bank->bank_number; + k_bank->protection_size = MAX(k_chip->pflash_size / 32, 1024); + bank->num_prot_blocks = 32 / k_chip->num_pflash_blocks; + k_bank->protection_block = bank->num_prot_blocks * k_bank->bank_number; - } else if ((unsigned)bank->bank_number < num_blocks) { + size_k = bank->size / 1024; + LOG_DEBUG("Kinetis bank %u: %" PRIu32 "k PFlash, FTFx base 0x%08" PRIx32 ", sect %u", + k_bank->bank_number, size_k, k_bank->prog_base, k_bank->sector_size); + + } else if (k_bank->bank_number < num_blocks) { /* nvm, banks start at address 0x10000000 */ - unsigned nvm_ord = bank->bank_number - first_nvm_bank; + unsigned nvm_ord = k_bank->bank_number - first_nvm_bank; uint32_t limit; - kinfo->flash_class = FC_FLEX_NVM; - bank->size = (nvm_size / num_nvm_blocks); - bank->base = 0x10000000 + bank->size * nvm_ord; - kinfo->prog_base = 0x00800000 + bank->size * nvm_ord; - kinfo->sector_size = nvm_sector_size_bytes; - if (df_size == 0) { - kinfo->protection_size = 0; + k_bank->flash_class = FC_FLEX_NVM; + bank->size = k_chip->nvm_size / k_chip->num_nvm_blocks; + bank->base = k_chip->nvm_base + bank->size * nvm_ord; + k_bank->prog_base = 0x00800000 + bank->size * nvm_ord; + k_bank->sector_size = k_chip->nvm_sector_size; + if (k_chip->dflash_size == 0) { + k_bank->protection_size = 0; } else { - for (i = df_size; ~i & 1; i >>= 1) + for (i = k_chip->dflash_size; ~i & 1; i >>= 1) ; if (i == 1) - kinfo->protection_size = df_size / 8; /* data flash size = 2^^n */ + k_bank->protection_size = k_chip->dflash_size / 8; /* data flash size = 2^^n */ else - kinfo->protection_size = nvm_size / 8; /* TODO: verify on SF1, not documented in RM */ + k_bank->protection_size = k_chip->nvm_size / 8; /* TODO: verify on SF1, not documented in RM */ } - bank->num_prot_blocks = 8 / num_nvm_blocks; - kinfo->protection_block = bank->num_prot_blocks * nvm_ord; + bank->num_prot_blocks = 8 / k_chip->num_nvm_blocks; + k_bank->protection_block = bank->num_prot_blocks * nvm_ord; - /* EEPROM backup part of FlexNVM is not accessible, use df_size as a limit */ - if (df_size > bank->size * nvm_ord) - limit = df_size - bank->size * nvm_ord; + /* EEPROM backup part of FlexNVM is not accessible, use dflash_size as a limit */ + if (k_chip->dflash_size > bank->size * nvm_ord) + limit = k_chip->dflash_size - bank->size * nvm_ord; else limit = 0; if (bank->size > limit) { bank->size = limit; LOG_DEBUG("FlexNVM bank %d limited to 0x%08" PRIx32 " due to active EEPROM backup", - bank->bank_number, limit); + k_bank->bank_number, limit); } - } else if ((unsigned)bank->bank_number == num_blocks) { - LOG_ERROR("FlexRAM support not yet implemented"); - return ERROR_FLASH_OPER_UNSUPPORTED; + size_k = bank->size / 1024; + LOG_DEBUG("Kinetis bank %u: %" PRIu32 "k FlexNVM, FTFx base 0x%08" PRIx32 ", sect %u", + k_bank->bank_number, size_k, k_bank->prog_base, k_bank->sector_size); + } else { LOG_ERROR("Cannot determine parameters for bank %d, only %d banks on device", - bank->bank_number, num_blocks); + k_bank->bank_number, num_blocks); return ERROR_FLASH_BANK_INVALID; } - if (bank->bank_number == 0 && ((uint32_t)fcfg2_maxaddr0 << maxaddr_shift) != bank->size) + fcfg2_pflsh = (uint8_t)((k_chip->sim_fcfg2 >> 23) & 0x01); + fcfg2_maxaddr0 = (uint8_t)((k_chip->sim_fcfg2 >> 24) & 0x7f); + fcfg2_maxaddr1 = (uint8_t)((k_chip->sim_fcfg2 >> 16) & 0x7f); + + if (k_bank->bank_number == 0 && k_chip->fcfg2_maxaddr0_shifted != bank->size) LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr0); + if (fcfg2_pflsh) { - if (bank->bank_number == 1 && ((uint32_t)fcfg2_maxaddr1 << maxaddr_shift) != bank->size) + if (k_bank->bank_number == 1 && k_chip->fcfg2_maxaddr1_shifted != bank->size) LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr1); } else { - if ((unsigned)bank->bank_number == first_nvm_bank - && ((uint32_t)fcfg2_maxaddr1 << maxaddr_shift) != df_size) + if (k_bank->bank_number == first_nvm_bank + && k_chip->fcfg2_maxaddr1_shifted != k_chip->dflash_size) LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed," " please report to OpenOCD mailing list", fcfg2_maxaddr1); } @@ -2068,26 +2290,20 @@ static int kinetis_probe(struct flash_bank *bank) bank->prot_blocks = NULL; } - if (kinfo->sector_size == 0) { + if (k_bank->sector_size == 0) { LOG_ERROR("Unknown sector size for bank %d", bank->bank_number); return ERROR_FLASH_BANK_INVALID; } - if (kinfo->flash_support & FS_PROGRAM_SECTOR - && kinfo->max_flash_prog_size == 0) { - kinfo->max_flash_prog_size = kinfo->sector_size; - /* Program section size is equal to sector size by default */ - } - - bank->num_sectors = bank->size / kinfo->sector_size; + bank->num_sectors = bank->size / k_bank->sector_size; if (bank->num_sectors > 0) { /* FlexNVM bank can be used for EEPROM backup therefore zero sized */ - bank->sectors = alloc_block_array(0, kinfo->sector_size, bank->num_sectors); + bank->sectors = alloc_block_array(0, k_bank->sector_size, bank->num_sectors); if (!bank->sectors) return ERROR_FAIL; - bank->prot_blocks = alloc_block_array(0, kinfo->protection_size, bank->num_prot_blocks); + bank->prot_blocks = alloc_block_array(0, k_bank->protection_size, bank->num_prot_blocks); if (!bank->prot_blocks) return ERROR_FAIL; @@ -2095,16 +2311,16 @@ static int kinetis_probe(struct flash_bank *bank) bank->num_prot_blocks = 0; } - kinfo->probed = true; + k_bank->probed = true; return ERROR_OK; } static int kinetis_auto_probe(struct flash_bank *bank) { - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; - if (kinfo && kinfo->probed) + if (k_bank && k_bank->probed) return ERROR_OK; return kinetis_probe(bank); @@ -2116,19 +2332,23 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size) "(ANY)", "PFlash", "FlexNVM", "FlexRAM" }; - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; + uint32_t size_k = bank->size / 1024; - (void) snprintf(buf, buf_size, - "%s driver for %s flash bank %s at 0x%8.8" PRIx32 "", - bank->driver->name, bank_class_names[kinfo->flash_class], - bank->name, bank->base); + snprintf(buf, buf_size, + "%s %s: %" PRIu32 "k %s bank %s at 0x%08" PRIx32, + bank->driver->name, k_chip->name, + size_k, bank_class_names[k_bank->flash_class], + bank->name, bank->base); return ERROR_OK; } static int kinetis_blank_check(struct flash_bank *bank) { - struct kinetis_flash_bank *kinfo = bank->driver_priv; + struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; int result; /* suprisingly blank check does not work in VLPR and HSRUN modes */ @@ -2141,13 +2361,13 @@ static int kinetis_blank_check(struct flash_bank *bank) if (result != ERROR_OK) return result; - if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) { + if (k_bank->flash_class == FC_PFLASH || k_bank->flash_class == FC_FLEX_NVM) { bool block_dirty = true; - bool use_block_cmd = !(kinfo->flash_support & FS_NO_CMD_BLOCKSTAT); + bool use_block_cmd = !(k_chip->flash_support & FS_NO_CMD_BLOCKSTAT); uint8_t ftfx_fstat; - if (use_block_cmd && kinfo->flash_class == FC_FLEX_NVM) { - uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); + if (use_block_cmd && k_bank->flash_class == FC_FLEX_NVM) { + uint8_t fcfg1_depart = (uint8_t)((k_chip->sim_fcfg1 >> 8) & 0x0f); /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */ if (fcfg1_depart != 0xf && fcfg1_depart != 0) use_block_cmd = false; @@ -2155,7 +2375,7 @@ static int kinetis_blank_check(struct flash_bank *bank) if (use_block_cmd) { /* check if whole bank is blank */ - result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base, + result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, k_bank->prog_base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result != ERROR_OK) @@ -2170,7 +2390,7 @@ static int kinetis_blank_check(struct flash_bank *bank) for (i = 0; i < bank->num_sectors; i++) { /* normal margin */ result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTSTAT, - kinfo->prog_base + bank->sectors[i].offset, + k_bank->prog_base + bank->sectors[i].offset, 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result == ERROR_OK) { @@ -2198,7 +2418,9 @@ static int kinetis_blank_check(struct flash_bank *bank) COMMAND_HANDLER(kinetis_nvm_partition) { - int result, i; + int result; + unsigned bank_idx; + unsigned num_blocks, first_nvm_bank; unsigned long par, log2 = 0, ee1 = 0, ee2 = 0; enum { SHOW_INFO, DF_SIZE, EEBKP_SIZE } sz_type = SHOW_INFO; bool enable; @@ -2207,8 +2429,7 @@ COMMAND_HANDLER(kinetis_nvm_partition) uint8_t flex_nvm_partition_code = 0; uint8_t ee_split = 3; struct target *target = get_current_target(CMD_CTX); - struct flash_bank *bank; - struct kinetis_flash_bank *kinfo; + struct kinetis_chip *k_chip; uint32_t sim_fcfg1; if (CMD_ARGC >= 2) { @@ -2323,14 +2544,13 @@ COMMAND_HANDLER(kinetis_nvm_partition) command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU."); - for (i = 1; i < 4; i++) { - bank = get_flash_bank_by_num_noprobe(i); - if (bank == NULL) - break; - - kinfo = bank->driver_priv; - if (kinfo && kinfo->flash_class == FC_FLEX_NVM) - kinfo->probed = false; /* re-probe before next use */ + k_chip = kinetis_get_chip(target); + if (k_chip) { + first_nvm_bank = k_chip->num_pflash_blocks; + num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; + for (bank_idx = first_nvm_bank; bank_idx < num_blocks; bank_idx++) + k_chip->banks[bank_idx].probed = false; /* re-probe before next use */ + k_chip->probed = false; } command_print(CMD_CTX, "FlexNVM banks will be re-probed to set new data flash size."); From c4d4c32a504f1a63f0200efdd175d21bfe8cc3af Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 Dec 2016 15:20:33 +0100 Subject: [PATCH 08/68] flash Kinetis: implement automatic bank creation based on device probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kinetis flash driver services huge number of MCU types. They have one, two or four flash banks with option of FlexNVM. It would require ~36 config files just for Kx series, more for KLx, KVx and KE1x. The change implements alternative approach: - configuration file creates just one pflash bank (common for all devices) - when a device is probed, additional pflash or flexnvm banks are created based on flash layout of the connected MCU - created banks have names with optional numbering e.g. kx.pflash0 kx.pflash1 kx.flexnvm0 kx.flexnvm1 - the first bank gets renamed if numbering is used Automatic bank creation is enabled by tcl command 'kinetis create_banks'. Used solution has a drawback: other banks than pflash0 are not accessible until pflash0 is probed. Fortunately gdb attach and standard programming accesses banks in right sequence. Change-Id: I5b9037cbefdb8a4176b7715fbcc3af4da4c1ab60 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3925 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- doc/openocd.texi | 6 +++ src/flash/nor/kinetis.c | 102 ++++++++++++++++++++++++++++++++++++++++ tcl/target/ke1xf.cfg | 2 - tcl/target/ke1xz.cfg | 2 - tcl/target/klx.cfg | 6 ++- tcl/target/kx.cfg | 6 ++- 6 files changed, 116 insertions(+), 8 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index ac09db5e2..5fd43009d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5372,6 +5372,12 @@ Use kinetis_ke driver for KE0x devices. flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME @end example +@deffn Command {kinetis create_banks} +Configuration command enables automatic creation of additional flash banks +based on real flash layout of device. Banks are created during device probe. +Use 'flash probe 0' to force probe. +@end deffn + @deffn Command {kinetis fcf_source} [protection|write] Select what source is used when writing to a Flash Configuration Field. @option{protection} mode builds FCF content from protection bits previously diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 8ebdbbea6..dc3dc4597 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -356,6 +356,7 @@ static const struct kinetis_type kinetis_types_old[] = { static bool allow_fcf_writes; static uint8_t fcf_fopt = 0xff; +static bool create_banks; struct flash_driver kinetis_flash; @@ -859,6 +860,87 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) return ERROR_OK; } + +static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) +{ + unsigned bank_idx; + unsigned num_blocks; + struct kinetis_flash_bank *k_bank; + struct flash_bank *bank; + char base_name[80], name[80], num[4]; + char *class, *p; + + num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; + if (num_blocks > KINETIS_MAX_BANKS) { + LOG_ERROR("Only %u Kinetis flash banks are supported", KINETIS_MAX_BANKS); + return ERROR_FAIL; + } + + bank = k_chip->banks[0].bank; + if (bank && bank->name) { + strncpy(base_name, bank->name, sizeof(base_name)); + p = strstr(base_name, ".pflash"); + if (p) { + *p = '\0'; + if (k_chip->num_pflash_blocks > 1) { + /* rename first bank if numbering is needed */ + snprintf(name, sizeof(name), "%s.pflash0", base_name); + free((void *)bank->name); + bank->name = strdup(name); + } + } + } else { + strncpy(base_name, target_name(k_chip->target), sizeof(base_name)); + p = strstr(base_name, ".cpu"); + if (p) + *p = '\0'; + } + + for (bank_idx = 1; bank_idx < num_blocks; bank_idx++) { + k_bank = &(k_chip->banks[bank_idx]); + bank = k_bank->bank; + + if (bank) + continue; + + num[0] = '\0'; + + if (bank_idx < k_chip->num_pflash_blocks) { + class = "pflash"; + if (k_chip->num_pflash_blocks > 1) + snprintf(num, sizeof(num), "%u", bank_idx); + } else { + class = "flexnvm"; + if (k_chip->num_nvm_blocks > 1) + snprintf(num, sizeof(num), "%u", + bank_idx - k_chip->num_pflash_blocks); + } + + bank = calloc(sizeof(struct flash_bank), 1); + if (bank == NULL) + return ERROR_FAIL; + + bank->target = k_chip->target; + bank->driver = &kinetis_flash; + bank->default_padded_value = bank->erased_value = 0xff; + + snprintf(name, sizeof(name), "%s.%s%s", + base_name, class, num); + bank->name = strdup(name); + + bank->driver_priv = k_bank = &(k_chip->banks[k_chip->num_banks]); + k_bank->k_chip = k_chip; + k_bank->bank_number = bank_idx; + k_bank->bank = bank; + if (k_chip->num_banks <= bank_idx) + k_chip->num_banks = bank_idx + 1; + + flash_bank_add(bank); + } + return ERROR_OK; +} + + /* Disable the watchdog on Kinetis devices */ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) { @@ -2176,6 +2258,10 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) } k_chip->probed = true; + + if (create_banks) + kinetis_create_missing_banks(k_chip); + return ERROR_OK; } @@ -2596,6 +2682,16 @@ COMMAND_HANDLER(kinetis_fopt_handler) return ERROR_OK; } +COMMAND_HANDLER(kinetis_create_banks_handler) +{ + if (CMD_ARGC > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + create_banks = true; + + return ERROR_OK; +} + static const struct command_registration kinetis_security_command_handlers[] = { { @@ -2666,6 +2762,12 @@ static const struct command_registration kinetis_exec_command_handlers[] = { .usage = "[num]", .handler = kinetis_fopt_handler, }, + { + .name = "create_banks", + .mode = COMMAND_CONFIG, + .help = "Driver creates additional banks if device with two/four flash blocks is probed", + .handler = kinetis_create_banks_handler, + }, COMMAND_REGISTRATION_DONE }; diff --git a/tcl/target/ke1xf.cfg b/tcl/target/ke1xf.cfg index 94b175f2d..b1200cec2 100644 --- a/tcl/target/ke1xf.cfg +++ b/tcl/target/ke1xf.cfg @@ -5,5 +5,3 @@ set CHIPNAME ke source [find target/kx.cfg] - -flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/ke1xz.cfg b/tcl/target/ke1xz.cfg index db2d1a428..6a3f509ed 100644 --- a/tcl/target/ke1xz.cfg +++ b/tcl/target/ke1xz.cfg @@ -5,5 +5,3 @@ set CHIPNAME ke source [find target/klx.cfg] - -flash bank flexnvm kinetis 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/klx.cfg b/tcl/target/klx.cfg index 0df6612f7..c2de9f7d5 100644 --- a/tcl/target/klx.cfg +++ b/tcl/target/klx.cfg @@ -1,5 +1,6 @@ # -# Freescale Kinetis KL series devices +# NXP (former Freescale) Kinetis KL series devices +# Also used for Cortex-M0+ equipped members of KVx and KE1xZ series # source [find target/swj-dp.tcl] @@ -31,8 +32,9 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -set _FLASHNAME $_CHIPNAME.flash +set _FLASHNAME $_CHIPNAME.pflash flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME +kinetis create_banks # Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual # specifies up to 1MHz for VLPR mode. diff --git a/tcl/target/kx.cfg b/tcl/target/kx.cfg index b39ee3dd1..cf777135c 100644 --- a/tcl/target/kx.cfg +++ b/tcl/target/kx.cfg @@ -1,5 +1,6 @@ # -# Freescale Kinetis Kx series devices +# NXP (former Freescale) Kinetis Kx series devices +# Also used for Cortex-M4 equipped members of KVx and KE1xF series # source [find target/swj-dp.tcl] @@ -35,8 +36,9 @@ target create $_TARGETNAME cortex_m -chain-position $_CHIPNAME.cpu $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -set _FLASHNAME $_CHIPNAME.flash +set _FLASHNAME $_CHIPNAME.pflash flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME +kinetis create_banks adapter_khz 1000 From 5a2608bbbc55a63b940fe9da10aaf0c73fcd23dc Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 26 Dec 2016 19:59:10 +0100 Subject: [PATCH 09/68] flash Kinetis: handle all types of watchdog, disable in reset-init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Active watchdog forces reset during armv7m_checksum_memory() in verify_image command if run just after reset init. COP watchdog in KL series and WDOG32 in KE1 series have longer timeout however they need to be disabled too. The change extends 'kinetis disable_wdog' command to optionally probe the chip and use appropriate algorithm to disable watchdog. Setting of cache type is also split from flash_support flags. Tcl command 'kinetis disable_wdog' is called in reset-init event. Change-Id: I3191e230f38b679ed74f2a97fe323ef8fb3fe22e Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3901 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- contrib/loaders/watchdog/Makefile | 2 +- .../loaders/watchdog/armv7m_kinetis_wdog.inc | 5 +- .../loaders/watchdog/armv7m_kinetis_wdog.s | 14 +- .../watchdog/armv7m_kinetis_wdog32.inc | 5 + .../loaders/watchdog/armv7m_kinetis_wdog32.s | 81 +++++ src/flash/nor/kinetis.c | 293 +++++++++++++----- tcl/target/klx.cfg | 16 +- tcl/target/kx.cfg | 8 + 8 files changed, 326 insertions(+), 98 deletions(-) create mode 100644 contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc create mode 100644 contrib/loaders/watchdog/armv7m_kinetis_wdog32.s diff --git a/contrib/loaders/watchdog/Makefile b/contrib/loaders/watchdog/Makefile index 623e74407..ed6d8f4e5 100644 --- a/contrib/loaders/watchdog/Makefile +++ b/contrib/loaders/watchdog/Makefile @@ -6,7 +6,7 @@ ARM_OBJCOPY ?= $(ARM_CROSS_COMPILE)objcopy ARM_AFLAGS = -EL -mthumb -arm: armv7m_kinetis_wdog.inc +arm: armv7m_kinetis_wdog.inc armv7m_kinetis_wdog32.inc armv7m_%.elf: armv7m_%.s $(ARM_AS) $(ARM_AFLAGS) $< -o $@ diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc b/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc index 4b6579e0c..317d084dd 100644 --- a/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog.inc @@ -1,4 +1,3 @@ /* Autogenerated with ../../../src/helper/bin2char.sh */ -0x04,0x4b,0x05,0x4a,0xda,0x81,0x05,0x4a,0xda,0x81,0x01,0x24,0x1a,0x88,0xa2,0x43, -0x1a,0x80,0x06,0xe0,0x00,0x20,0x05,0x40,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00, -0x00,0x00,0x00,0xbe, +0x04,0x4a,0xc2,0x81,0x04,0x4a,0xc2,0x81,0x01,0x24,0x02,0x88,0xa2,0x43,0x02,0x80, +0x05,0xe0,0x00,0x00,0x20,0xc5,0x00,0x00,0x28,0xd9,0x00,0x00,0x00,0x00,0x00,0xbe, diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog.s b/contrib/loaders/watchdog/armv7m_kinetis_wdog.s index bac924ab8..d7241927c 100644 --- a/contrib/loaders/watchdog/armv7m_kinetis_wdog.s +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog.s @@ -19,7 +19,9 @@ /* Disable watchdog for Kinetis Kx and KVx - Parameters: none + Parameters: + r0 ... WDOG base (in) + Used instruction set should work on both Cortex-M4 and M0+ */ @@ -28,7 +30,6 @@ .cpu cortex-m0 .thumb -WDOG_ADDR = 0x40052000 /* WDOG registers offsets */ WDOG_STCTRLH = 0 WDOG_UNLOCK = 0x0e @@ -39,17 +40,16 @@ WDOG_KEY2 = 0xd928 .thumb_func start: /* WDOG_UNLOCK = 0xC520 */ - ldr r3, =WDOG_ADDR ldr r2, =WDOG_KEY1 - strh r2, [r3, WDOG_UNLOCK] + strh r2, [r0, WDOG_UNLOCK] /* WDOG_UNLOCK = 0xD928 */ ldr r2, =WDOG_KEY2 - strh r2, [r3, WDOG_UNLOCK] + strh r2, [r0, WDOG_UNLOCK] /* WDOG_STCTRLH clear bit 0 */ movs r4, #1 - ldrh r2, [r3, WDOG_STCTRLH] + ldrh r2, [r0, WDOG_STCTRLH] bics r2, r4 - strh r2, [r3, WDOG_STCTRLH] + strh r2, [r0, WDOG_STCTRLH] /* OpenOCD checks exit point address. Jump to the very end. */ b done diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc new file mode 100644 index 000000000..4ee06ed1f --- /dev/null +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc @@ -0,0 +1,5 @@ +/* Autogenerated with ../../../src/helper/bin2char.sh */ +0x02,0x68,0x08,0x4b,0x1a,0x42,0x08,0x4b,0x01,0xd0,0x43,0x60,0x02,0xe0,0x83,0x80, +0x1b,0x0c,0x83,0x80,0x80,0x24,0xa2,0x43,0x20,0x24,0x22,0x43,0x02,0x60,0x03,0x4b, +0x83,0x60,0x06,0xe0,0x00,0x20,0x00,0x00,0x20,0xc5,0x28,0xd9,0x00,0x04,0x00,0x00, +0x00,0x00,0x00,0xbe, diff --git a/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s new file mode 100644 index 000000000..bf58327e9 --- /dev/null +++ b/contrib/loaders/watchdog/armv7m_kinetis_wdog32.s @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2017 Tomas Vanek * + * vanekt@fbl.cz * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc. * + ***************************************************************************/ + +/* + Disable watchdog, 32-bit version for newer Kinetis + Parameters: + r0 ... WDOG32 base (in) + + Used instruction set should work on both Cortex-M4 and M0+ +*/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + +/* WDOG registers offsets */ +WDOG_CS = 0 +WDOG_CNT = 4 +WDOG_TOVAL = 8 + +WDOG_KEY = 0xd928c520 + + .thumb_func +start: +/* test WDOG_CS bit CMD32EN */ + ldr r2, [r0, WDOG_CS] + ldr r3, =0x2000 + tst r2, r3 + ldr r3, =WDOG_KEY + beq cmd16 + +/* WDOG_CNT = key */ + str r3, [r0, WDOG_CNT] + b unlocked + +cmd16: +/* WDOG_CNT = key, halfword by halfword */ + strh r3, [r0, WDOG_CNT] + lsrs r3, r3, #16 + strh r3, [r0, WDOG_CNT] + +/* WDOG_CS: clear EN bit 7, set UPDATE bit 5 */ +unlocked: + movs r4, #0x80 + bics r2, r4 + movs r4, #0x20 + orrs r2, r4 + str r2, [r0, WDOG_CS] +/* All active WDOG registers have to be updated, set dummy timeout */ +/* WDOG_TOVAL = 0x400 */ + ldr r3, =0x400 + str r3, [r0, WDOG_TOVAL] +/* OpenOCD checks exit point address. Jump to the very end. */ + b done + + .pool + +/* Avoid padding at .text segment end. Otherwise exit point check fails. */ + .skip ( . - start + 2) & 2, 0 +done: + bkpt #0 + + .end + diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index dc3dc4597..1f2383d00 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -100,11 +100,18 @@ #define SIM_SOPT1 0x40047000 #define SIM_FCFG1 0x4004804c #define SIM_FCFG2 0x40048050 -#define WDOG_STCTRH 0x40052000 +#define SIM_COPC 0x40048100 +#define WDOG_BASE 0x40052000 +#define WDOG32_KE1X 0x40052000 +#define WDOG32_KL28 0x40076000 #define SMC_PMCTRL 0x4007E001 #define SMC_PMSTAT 0x4007E003 #define MCM_PLACR 0xF000300C +/* Offsets */ +#define WDOG_STCTRLH_OFFSET 0 +#define WDOG32_CS_OFFSET 0 + /* Values */ #define PM_STAT_RUN 0x01 #define PM_STAT_VLPR 0x04 @@ -270,13 +277,26 @@ struct kinetis_chip { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, FS_PROGRAM_PHRASE = 4, /* Unsupported */ - FS_INVALIDATE_CACHE_K = 8, /* using FMC->PFB0CR/PFB01CR */ - FS_INVALIDATE_CACHE_L = 0x10, /* using MCM->PLACR */ - FS_INVALIDATE_CACHE_MSCM = 0x20, + FS_NO_CMD_BLOCKSTAT = 0x40, FS_WIDTH_256BIT = 0x80, } flash_support; + enum { + KINETIS_CACHE_NONE, + KINETIS_CACHE_K, /* invalidate using FMC->PFB0CR/PFB01CR */ + KINETIS_CACHE_L, /* invalidate using MCM->PLACR */ + KINETIS_CACHE_MSCM, /* devices like KE1xF, invalidate MSCM->OCMDR0 */ + } cache_type; + + enum { + KINETIS_WDOG_NONE, + KINETIS_WDOG_K, + KINETIS_WDOG_COP, + KINETIS_WDOG32_KE1X, + KINETIS_WDOG32_KL28, + } watchdog_type; + char name[40]; unsigned num_banks; @@ -362,6 +382,7 @@ static bool create_banks; struct flash_driver kinetis_flash; static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count); +static int kinetis_probe_chip(struct kinetis_chip *k_chip); static int kinetis_auto_probe(struct flash_bank *bank); @@ -941,11 +962,53 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) } -/* Disable the watchdog on Kinetis devices */ -int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) +static int kinetis_disable_wdog_algo(struct target *target, size_t code_size, const uint8_t *code, uint32_t wdog_base) { struct working_area *wdog_algorithm; struct armv7m_algorithm armv7m_info; + struct reg_param reg_params[1]; + int retval; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = target_alloc_working_area(target, code_size, &wdog_algorithm); + if (retval != ERROR_OK) + return retval; + + retval = target_write_buffer(target, wdog_algorithm->address, + code_size, code); + if (retval == ERROR_OK) { + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_info.core_mode = ARM_MODE_THREAD; + + init_reg_param(®_params[0], "r0", 32, PARAM_IN); + buf_set_u32(reg_params[0].value, 0, 32, wdog_base); + + retval = target_run_algorithm(target, 0, NULL, 1, reg_params, + wdog_algorithm->address, + wdog_algorithm->address + code_size - 2, + 500, &armv7m_info); + + destroy_reg_param(®_params[0]); + + if (retval != ERROR_OK) + LOG_ERROR("Error executing Kinetis WDOG unlock algorithm"); + } + + target_free_working_area(target, wdog_algorithm); + + return retval; +} + +/* Disable the watchdog on Kinetis devices + * Standard Kx WDOG peripheral checks timing and therefore requires to run algo. + */ +static int kinetis_disable_wdog_kx(struct target *target) +{ + const uint32_t wdog_base = WDOG_BASE; uint16_t wdog; int retval; @@ -953,14 +1016,7 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) #include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog.inc" }; - /* Decide whether the connected device needs watchdog disabling. - * Disable for all Kx and KVx devices, return if it is a KLx */ - - if ((sim_sdid & KINETIS_SDID_SERIESID_MASK) == KINETIS_SDID_SERIESID_KL) - return ERROR_OK; - - /* The connected device requires watchdog disabling. */ - retval = target_read_u16(target, WDOG_STCTRH, &wdog); + retval = target_read_u16(target, wdog_base + WDOG_STCTRLH_OFFSET, &wdog); if (retval != ERROR_OK) return retval; @@ -968,60 +1024,116 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) /* watchdog already disabled */ return ERROR_OK; } - LOG_INFO("Disabling Kinetis watchdog (initial WDOG_STCTRLH = 0x%x)", wdog); + LOG_INFO("Disabling Kinetis watchdog (initial WDOG_STCTRLH = 0x%04" PRIx16 ")", wdog); - if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; + retval = kinetis_disable_wdog_algo(target, sizeof(kinetis_unlock_wdog_code), kinetis_unlock_wdog_code, wdog_base); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u16(target, wdog_base + WDOG_STCTRLH_OFFSET, &wdog); + if (retval != ERROR_OK) + return retval; + + LOG_INFO("WDOG_STCTRLH = 0x%04" PRIx16, wdog); + return (wdog & 0x1) ? ERROR_FAIL : ERROR_OK; +} + +static int kinetis_disable_wdog32(struct target *target, uint32_t wdog_base) +{ + uint32_t wdog_cs; + int retval; + + static const uint8_t kinetis_unlock_wdog_code[] = { +#include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog32.inc" + }; + + retval = target_read_u32(target, wdog_base + WDOG32_CS_OFFSET, &wdog_cs); + if (retval != ERROR_OK) + return retval; + + if ((wdog_cs & 0x80) == 0) + return ERROR_OK; /* watchdog already disabled */ + + LOG_INFO("Disabling Kinetis watchdog (initial WDOG_CS 0x%08" PRIx32 ")", wdog_cs); + + retval = kinetis_disable_wdog_algo(target, sizeof(kinetis_unlock_wdog_code), kinetis_unlock_wdog_code, wdog_base); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u32(target, wdog_base + WDOG32_CS_OFFSET, &wdog_cs); + if (retval != ERROR_OK) + return retval; + + if ((wdog_cs & 0x80) == 0) + return ERROR_OK; /* watchdog disabled successfully */ + + LOG_ERROR("Cannot disable Kinetis watchdog (WDOG_CS 0x%08" PRIx32 "), issue 'reset init'", wdog_cs); + return ERROR_FAIL; +} + +static int kinetis_disable_wdog(struct kinetis_chip *k_chip) +{ + struct target *target = k_chip->target; + uint8_t sim_copc; + int retval; + + if (!k_chip->probed) { + retval = kinetis_probe_chip(k_chip); + if (retval != ERROR_OK) + return retval; } - retval = target_alloc_working_area(target, sizeof(kinetis_unlock_wdog_code), &wdog_algorithm); - if (retval != ERROR_OK) - return retval; + switch (k_chip->watchdog_type) { + case KINETIS_WDOG_K: + return kinetis_disable_wdog_kx(target); - retval = target_write_buffer(target, wdog_algorithm->address, - sizeof(kinetis_unlock_wdog_code), (uint8_t *)kinetis_unlock_wdog_code); - if (retval != ERROR_OK) { - target_free_working_area(target, wdog_algorithm); - return retval; + case KINETIS_WDOG_COP: + retval = target_read_u8(target, SIM_COPC, &sim_copc); + if (retval != ERROR_OK) + return retval; + + if ((sim_copc & 0xc) == 0) + return ERROR_OK; /* watchdog already disabled */ + + LOG_INFO("Disabling Kinetis watchdog (initial SIM_COPC 0x%02" PRIx8 ")", sim_copc); + retval = target_write_u8(target, SIM_COPC, sim_copc & ~0xc); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u8(target, SIM_COPC, &sim_copc); + if (retval != ERROR_OK) + return retval; + + if ((sim_copc & 0xc) == 0) + return ERROR_OK; /* watchdog disabled successfully */ + + LOG_ERROR("Cannot disable Kinetis watchdog (SIM_COPC 0x%02" PRIx8 "), issue 'reset init'", sim_copc); + return ERROR_FAIL; + + case KINETIS_WDOG32_KE1X: + return kinetis_disable_wdog32(target, WDOG32_KE1X); + + case KINETIS_WDOG32_KL28: + return kinetis_disable_wdog32(target, WDOG32_KL28); + + default: + return ERROR_OK; } - - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_THREAD; - - retval = target_run_algorithm(target, 0, NULL, 0, NULL, wdog_algorithm->address, - wdog_algorithm->address + (sizeof(kinetis_unlock_wdog_code) - 2), - 10000, &armv7m_info); - - if (retval != ERROR_OK) - LOG_ERROR("error executing kinetis wdog unlock algorithm"); - - retval = target_read_u16(target, WDOG_STCTRH, &wdog); - if (retval != ERROR_OK) - return retval; - LOG_INFO("WDOG_STCTRLH = 0x%x", wdog); - - target_free_working_area(target, wdog_algorithm); - - return retval; } COMMAND_HANDLER(kinetis_disable_wdog_handler) { int result; - uint32_t sim_sdid; struct target *target = get_current_target(CMD_CTX); + struct kinetis_chip *k_chip = kinetis_get_chip(target); + + if (k_chip == NULL) + return ERROR_FAIL; if (CMD_ARGC > 0) return ERROR_COMMAND_SYNTAX_ERROR; - result = target_read_u32(target, SIM_SDID, &sim_sdid); - if (result != ERROR_OK) { - LOG_ERROR("Failed to read SIMSDID"); - return result; - } - - result = kinetis_disable_wdog(target, sim_sdid); + result = kinetis_disable_wdog(k_chip); return result; } @@ -1400,20 +1512,26 @@ static void kinetis_invalidate_flash_cache(struct kinetis_chip *k_chip) { struct target *target = k_chip->target; - if (k_chip->flash_support & FS_INVALIDATE_CACHE_K) + switch (k_chip->cache_type) { + case KINETIS_CACHE_K: target_write_u8(target, FMC_PFB01CR + 2, 0xf0); /* Set CINV_WAY bits - request invalidate of all cache ways */ /* FMC_PFB0CR has same address and CINV_WAY bits as FMC_PFB01CR */ + break; - else if (k_chip->flash_support & FS_INVALIDATE_CACHE_L) + case KINETIS_CACHE_L: target_write_u8(target, MCM_PLACR + 1, 0x04); /* set bit CFCC - Clear Flash Controller Cache */ + break; - else if (k_chip->flash_support & FS_INVALIDATE_CACHE_MSCM) + case KINETIS_CACHE_MSCM: target_write_u32(target, MSCM_OCMDR0, 0x30); /* disable data prefetch and flash speculate */ + break; - return; + default: + break; + } } @@ -1647,7 +1765,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, uint32_t words_remaining = count / 4; - kinetis_disable_wdog(bank->target, k_chip->sim_sdid); + kinetis_disable_wdog(k_chip); /* try using a block write */ result = kinetis_write_block(bank, buffer, offset, words_remaining); @@ -1791,6 +1909,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) if ((k_chip->sim_sdid & (~KINETIS_SDID_K_SERIES_MASK)) == 0) { /* older K-series MCU */ uint32_t mcu_type = k_chip->sim_sdid & KINETIS_K_SDID_TYPE_MASK; + k_chip->cache_type = KINETIS_CACHE_K; + k_chip->watchdog_type = KINETIS_WDOG_K; switch (mcu_type) { case KINETIS_K_SDID_K10_M50: @@ -1799,7 +1919,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 1<<10; k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1812,7 +1932,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 2<<10; k_chip->nvm_sector_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: @@ -1828,7 +1948,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 2<<10; k_chip->nvm_sector_size = 2<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: @@ -1837,7 +1957,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->max_flash_prog_size = 1<<10; k_chip->nvm_sector_size = 4<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: @@ -1847,7 +1967,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 4<<10; k_chip->nvm_sector_size = 4<<10; num_blocks = 4; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; default: LOG_ERROR("Unsupported K-family FAMID"); @@ -1869,12 +1989,15 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) switch (k_chip->sim_sdid & KINETIS_SDID_SERIESID_MASK) { case KINETIS_SDID_SERIESID_K: use_nvm_marking = true; + k_chip->cache_type = KINETIS_CACHE_K; + k_chip->watchdog_type = KINETIS_WDOG_K; + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K0X | KINETIS_SDID_SUBFAMID_KX2: /* K02FN64, K02FN128: FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; cpu_mhz = 100; break; @@ -1890,7 +2013,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* MK24FN1M */ k_chip->pflash_sector_size = 4<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; subfamid = 4; /* errata 1N83J fix */ break; @@ -1901,7 +2024,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); @@ -1912,12 +2035,12 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) if ((k_chip->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; k_chip->max_flash_prog_size = 1<<10; break; @@ -1932,7 +2055,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 4<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: @@ -1943,7 +2066,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 4<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 4; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; cpu_mhz = 180; break; @@ -1953,7 +2076,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* K80FN256, K81FN256, K82FN256 */ k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_NO_CMD_BLOCKSTAT; cpu_mhz = 150; break; @@ -1962,7 +2085,9 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KL81Z128, KL82Z128 */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L | FS_NO_CMD_BLOCKSTAT; + k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_NO_CMD_BLOCKSTAT; + k_chip->cache_type = KINETIS_CACHE_L; + use_nvm_marking = false; snprintf(name, sizeof(name), "MKL8%uZ%%s7", subfamid); @@ -1982,7 +2107,9 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->pflash_sector_size = 1<<10; k_chip->nvm_sector_size = 1<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; + k_chip->watchdog_type = KINETIS_WDOG_COP; cpu_mhz = 48; if (subfamid == 3 && (familyid == 1 || familyid == 2)) @@ -1993,12 +2120,14 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case KINETIS_SDID_SERIESID_KV: /* KV-series */ + k_chip->watchdog_type = KINETIS_WDOG_K; switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0: /* KV10: FTFA, 1kB sectors */ k_chip->pflash_sector_size = 1<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; strcpy(name, "MKV10Z%s7"); break; @@ -2006,7 +2135,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV11: FTFA, 2kB sectors */ k_chip->pflash_sector_size = 2<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; strcpy(name, "MKV11Z%s7"); break; @@ -2016,7 +2146,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV31: FTFA, 2kB sectors, 2 blocks */ k_chip->pflash_sector_size = 2<<10; /* autodetect 1 or 2 blocks */ - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_K; break; case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: @@ -2025,7 +2156,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* KV4x: FTFA, 4kB sectors */ k_chip->pflash_sector_size = 4<<10; num_blocks = 1; - k_chip->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_K; cpu_mhz = 168; break; @@ -2053,6 +2185,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case KINETIS_SDID_SERIESID_KE: /* KE1x-series */ + k_chip->watchdog_type = KINETIS_WDOG32_KE1X; switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK | KINETIS_SDID_PROJECTID_MASK)) { case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX4 | KINETIS_SDID_PROJECTID_KE1xZ: @@ -2062,7 +2195,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 2<<10; k_chip->max_flash_prog_size = 1<<9; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_L; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + k_chip->cache_type = KINETIS_CACHE_L; cpu_mhz = 72; snprintf(name, sizeof(name), "MKE%u%uZ%%s%u", @@ -2077,7 +2211,8 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->nvm_sector_size = 2<<10; k_chip->max_flash_prog_size = 1<<10; num_blocks = 2; - k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_MSCM; + k_chip->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + k_chip->cache_type = KINETIS_CACHE_MSCM; cpu_mhz = 168; snprintf(name, sizeof(name), "MKE%u%uF%%s%u", diff --git a/tcl/target/klx.cfg b/tcl/target/klx.cfg index c2de9f7d5..7dd0404f9 100644 --- a/tcl/target/klx.cfg +++ b/tcl/target/klx.cfg @@ -37,7 +37,8 @@ flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME kinetis create_banks # Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual -# specifies up to 1MHz for VLPR mode. +# specifies up to 1MHz for VLPR mode and up to 24MHz for run mode; +# Table 17 of Sub-Family Data Sheet rev4 lists 25MHz as the maximum frequency. adapter_khz 1000 reset_config srst_nogate @@ -53,10 +54,9 @@ if {![using_hla]} { cortex_m reset_config sysresetreq } -# Table 5-1. Clock Summary of KL25 Sub-Family Reference Manual -# specifies up to 24MHz for run mode; Table 17 of Sub-Family Data -# Sheet rev4 lists 25MHz as the maximum frequency. -# Uncoment only if VLPR mode is not used -#$_TARGETNAME configure -event reset-init { -# adapter_khz 24000 -#} +# Disable watchdog not to disturb OpenOCD algorithms running on MCU +# (e.g. armv7m_checksum_memory() in verify_image) +# Flash driver also disables watchdog before FTFA flash programming. +$_TARGETNAME configure -event reset-init { + kinetis disable_wdog +} diff --git a/tcl/target/kx.cfg b/tcl/target/kx.cfg index cf777135c..7b0351706 100644 --- a/tcl/target/kx.cfg +++ b/tcl/target/kx.cfg @@ -54,3 +54,11 @@ if {![using_hla]} { # perform a soft reset cortex_m reset_config sysresetreq } + +# Disable watchdog not to disturb OpenOCD algorithms running on MCU +# (e.g. armv7m_checksum_memory() in verify_image) +# Flash driver also disables watchdog before FTFA flash programming. +$_TARGETNAME configure -event reset-init { + kinetis disable_wdog +} + From 8dcb91fb83e59d475af9da377066021ae2e03969 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 10 Mar 2017 21:43:46 +0100 Subject: [PATCH 10/68] flash Kinetis: add KL28 device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device differs a lot from others in KL series. Unfortunately the System Integration Module, where device identification resides, moved to a new address so probe now have to try both addresses of SIM_SDID. Introduce a new bank creation option: -sim-base to ensure error free probe. WDOG32 is slightly different from KE1x and on different address. System Mode Controler changed layout to word aligned. Change-Id: I2c9dca0c4ad4228fcc941d6078d15f5e394833ff Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4059 Tested-by: jenkins Reviewed-by: Joakim Nohlgård Reviewed-by: Freddie Chopin --- doc/openocd.texi | 5 ++ src/flash/nor/kinetis.c | 139 ++++++++++++++++++++++++++++++++++------ 2 files changed, 123 insertions(+), 21 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 5fd43009d..d26c55a68 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5368,6 +5368,11 @@ recognizes flash size and a number of flash banks (1-4) using the chip identification register, and autoconfigures itself. Use kinetis_ke driver for KE0x devices. +The @var{kinetis} driver defines option: +@itemize +@item -sim-base @var{addr} ... base of System Integration Module where chip identification resides. Driver tries two known locations if option is omitted. +@end itemize + @example flash bank $_FLASHNAME kinetis 0 0 0 0 $_TARGETNAME @end example diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 1f2383d00..cc86f971a 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -96,19 +96,25 @@ #define FTFx_FCCOB3 0x40020004 #define FTFx_FPROT3 0x40020010 #define FTFx_FDPROT 0x40020017 -#define SIM_SDID 0x40048024 -#define SIM_SOPT1 0x40047000 -#define SIM_FCFG1 0x4004804c -#define SIM_FCFG2 0x40048050 +#define SIM_BASE 0x40047000 +#define SIM_BASE_KL28 0x40074000 #define SIM_COPC 0x40048100 + /* SIM_COPC does not exist on devices with changed SIM_BASE */ #define WDOG_BASE 0x40052000 #define WDOG32_KE1X 0x40052000 #define WDOG32_KL28 0x40076000 #define SMC_PMCTRL 0x4007E001 #define SMC_PMSTAT 0x4007E003 +#define SMC32_PMCTRL 0x4007E00C +#define SMC32_PMSTAT 0x4007E014 #define MCM_PLACR 0xF000300C /* Offsets */ +#define SIM_SOPT1_OFFSET 0x0000 +#define SIM_SDID_OFFSET 0x1024 +#define SIM_FCFG1_OFFSET 0x104c +#define SIM_FCFG2_OFFSET 0x1050 + #define WDOG_STCTRLH_OFFSET 0 #define WDOG32_CS_OFFSET 0 @@ -272,6 +278,7 @@ struct kinetis_chip { uint32_t dflash_size; /* accessible rest of FlexNVM if EEPROM backup uses part of FlexNVM */ uint32_t progr_accel_ram; + uint32_t sim_base; enum { FS_PROGRAM_SECTOR = 1, @@ -297,6 +304,11 @@ struct kinetis_chip { KINETIS_WDOG32_KL28, } watchdog_type; + enum { + KINETIS_SMC, + KINETIS_SMC32, + } sysmodectrlr_type; + char name[40]; unsigned num_banks; @@ -844,11 +856,25 @@ static struct kinetis_chip *kinetis_get_chip(struct target *target) return NULL; } +static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const char *argv[]) +{ + int i; + for (i = 0; i < argc; i++) { + if (strcmp(argv[i], "-sim-base") == 0) { + if (i + 1 < argc) + k_chip->sim_base = strtoul(argv[++i], NULL, 0); + } else + LOG_ERROR("Unsupported flash bank option %s", argv[i]); + } + return ERROR_OK; +} + FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) { struct target *target = bank->target; struct kinetis_chip *k_chip; struct kinetis_flash_bank *k_bank; + int retval; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; @@ -865,6 +891,11 @@ FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) } k_chip->target = target; + + /* only the first defined bank can define chip options */ + retval = kinetis_chip_options(k_chip, CMD_ARGC - 6, CMD_ARGV + 6); + if (retval != ERROR_OK) + return retval; } if (k_chip->num_banks >= KINETIS_MAX_BANKS) { @@ -1467,17 +1498,44 @@ static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t fa } -static int kinetis_check_run_mode(struct target *target) +static int kinetis_read_pmstat(struct kinetis_chip *k_chip, uint8_t *pmstat) +{ + int result; + uint32_t stat32; + struct target *target = k_chip->target; + + switch (k_chip->sysmodectrlr_type) { + case KINETIS_SMC: + result = target_read_u8(target, SMC_PMSTAT, pmstat); + return result; + + case KINETIS_SMC32: + result = target_read_u32(target, SMC32_PMSTAT, &stat32); + if (result == ERROR_OK) + *pmstat = stat32 & 0xff; + return result; + } + return ERROR_FAIL; +} + +static int kinetis_check_run_mode(struct kinetis_chip *k_chip) { int result, i; - uint8_t pmctrl, pmstat; + uint8_t pmstat; + struct target *target; + + if (k_chip == NULL) { + LOG_ERROR("Chip not probed."); + return ERROR_FAIL; + } + target = k_chip->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - result = target_read_u8(target, SMC_PMSTAT, &pmstat); + result = kinetis_read_pmstat(k_chip, &pmstat); if (result != ERROR_OK) return result; @@ -1487,13 +1545,21 @@ static int kinetis_check_run_mode(struct target *target) if (pmstat == PM_STAT_VLPR) { /* It is safe to switch from VLPR to RUN mode without changing clock */ LOG_INFO("Switching from VLPR to RUN mode."); - pmctrl = PM_CTRL_RUNM_RUN; - result = target_write_u8(target, SMC_PMCTRL, pmctrl); + + switch (k_chip->sysmodectrlr_type) { + case KINETIS_SMC: + result = target_write_u8(target, SMC_PMCTRL, PM_CTRL_RUNM_RUN); + break; + + case KINETIS_SMC32: + result = target_write_u32(target, SMC32_PMCTRL, PM_CTRL_RUNM_RUN); + break; + } if (result != ERROR_OK) return result; for (i = 100; i; i--) { - result = target_read_u8(target, SMC_PMSTAT, &pmstat); + result = kinetis_read_pmstat(k_chip, &pmstat); if (result != ERROR_OK) return result; @@ -1539,8 +1605,9 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) { int result, i; struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; - result = kinetis_check_run_mode(bank->target); + result = kinetis_check_run_mode(k_chip); if (result != ERROR_OK) return result; @@ -1816,8 +1883,9 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, bool set_fcf = false; int sect = 0; struct kinetis_flash_bank *k_bank = bank->driver_priv; + struct kinetis_chip *k_chip = k_bank->k_chip; - result = kinetis_check_run_mode(bank->target); + result = kinetis_check_run_mode(k_chip); if (result != ERROR_OK) return result; @@ -1902,7 +1970,18 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) name[0] = '\0'; - result = target_read_u32(target, SIM_SDID, &k_chip->sim_sdid); + if (k_chip->sim_base) + result = target_read_u32(target, k_chip->sim_base + SIM_SDID_OFFSET, &k_chip->sim_sdid); + else { + result = target_read_u32(target, SIM_BASE + SIM_SDID_OFFSET, &k_chip->sim_sdid); + if (result == ERROR_OK) + k_chip->sim_base = SIM_BASE; + else { + result = target_read_u32(target, SIM_BASE_KL28 + SIM_SDID_OFFSET, &k_chip->sim_sdid); + if (result == ERROR_OK) + k_chip->sim_base = SIM_BASE_KL28; + } + } if (result != ERROR_OK) return result; @@ -2004,7 +2083,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { /* MK24FN1M reports as K22, this should detect it (according to errata note 1N83J) */ uint32_t sopt1; - result = target_read_u32(target, SIM_SOPT1, &sopt1); + result = target_read_u32(target, k_chip->sim_base + SIM_SOPT1_OFFSET, &sopt1); if (result != ERROR_OK) return result; @@ -2112,8 +2191,21 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) k_chip->watchdog_type = KINETIS_WDOG_COP; cpu_mhz = 48; - if (subfamid == 3 && (familyid == 1 || familyid == 2)) + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX3: + case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX3: subfamid = 7; + break; + + case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX8: + cpu_mhz = 72; + k_chip->pflash_sector_size = 2<<10; + num_blocks = 2; + k_chip->watchdog_type = KINETIS_WDOG32_KL28; + k_chip->sysmodectrlr_type = KINETIS_SMC32; + break; + } + snprintf(name, sizeof(name), "MKL%u%uZ%%s%u", familyid, subfamid, cpu_mhz / 10); break; @@ -2234,11 +2326,11 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) return ERROR_FLASH_OPER_UNSUPPORTED; } - result = target_read_u32(target, SIM_FCFG1, &k_chip->sim_fcfg1); + result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &k_chip->sim_fcfg1); if (result != ERROR_OK) return result; - result = target_read_u32(target, SIM_FCFG2, &k_chip->sim_fcfg2); + result = target_read_u32(target, k_chip->sim_base + SIM_FCFG2_OFFSET, &k_chip->sim_fcfg2); if (result != ERROR_OK) return result; @@ -2573,7 +2665,7 @@ static int kinetis_blank_check(struct flash_bank *bank) int result; /* suprisingly blank check does not work in VLPR and HSRUN modes */ - result = kinetis_check_run_mode(bank->target); + result = kinetis_check_run_mode(k_chip); if (result != ERROR_OK) return result; @@ -2653,6 +2745,8 @@ COMMAND_HANDLER(kinetis_nvm_partition) struct kinetis_chip *k_chip; uint32_t sim_fcfg1; + k_chip = kinetis_get_chip(target); + if (CMD_ARGC >= 2) { if (strcmp(CMD_ARGV[0], "dataflash") == 0) sz_type = DF_SIZE; @@ -2665,7 +2759,11 @@ COMMAND_HANDLER(kinetis_nvm_partition) } switch (sz_type) { case SHOW_INFO: - result = target_read_u32(target, SIM_FCFG1, &sim_fcfg1); + if (k_chip == NULL) { + LOG_ERROR("Chip not probed."); + return ERROR_FAIL; + } + result = target_read_u32(target, k_chip->sim_base + SIM_FCFG1_OFFSET, &sim_fcfg1); if (result != ERROR_OK) return result; @@ -2748,7 +2846,7 @@ COMMAND_HANDLER(kinetis_nvm_partition) LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8, flex_nvm_partition_code, ee_size_code); - result = kinetis_check_run_mode(target); + result = kinetis_check_run_mode(k_chip); if (result != ERROR_OK) return result; @@ -2765,7 +2863,6 @@ COMMAND_HANDLER(kinetis_nvm_partition) command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU."); - k_chip = kinetis_get_chip(target); if (k_chip) { first_nvm_bank = k_chip->num_pflash_blocks; num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; From 2c8602ed9f084d6680cec7d0ca1d5dc71c865a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Tue, 11 Apr 2017 09:55:41 +0200 Subject: [PATCH 11/68] flash Kinetis: Add support for newer KW series MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for flashing newer members of the NXP Kinetis KW family Supported devices: - KW20Z - KW30Z - KW40Z - KW21Z - KW31Z - KW41Z The earlier KW2xD and KW01Z devices are already supported by the code for the older K-series. Verified working on the FRDM-KW41Z development board. Tested flashing both via GDB `load` and directly via OpenOCD flash write commands. Change-Id: I73eae477127a8b54a33005b3b526b5439450a808 Signed-off-by: Joakim Nohlgård Reviewed-on: http://openocd.zylin.com/4104 Tested-by: jenkins Reviewed-by: Johann Fischer Reviewed-by: Tomas Vanek --- src/flash/nor/kinetis.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index cc86f971a..12efefbd9 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -2210,6 +2210,45 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) familyid, subfamid, cpu_mhz / 10); break; + case KINETIS_SDID_SERIESID_KW: + /* Newer KW-series (all KW series except KW2xD, KW01Z) */ + cpu_mhz = 48; + switch (k_chip->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { + case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX0: + /* KW40Z */ + case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: + /* KW30Z */ + case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX0: + /* KW20Z */ + /* FTFA, 1kB sectors */ + k_chip->pflash_sector_size = 1<<10; + k_chip->nvm_sector_size = 1<<10; + /* autodetect 1 or 2 blocks */ + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; + k_chip->watchdog_type = KINETIS_WDOG_COP; + break; + case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX1: + /* KW41Z */ + case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1: + /* KW31Z */ + case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX1: + /* KW21Z */ + /* FTFA, 2kB sectors */ + k_chip->pflash_sector_size = 2<<10; + k_chip->nvm_sector_size = 2<<10; + /* autodetect 1 or 2 blocks */ + k_chip->flash_support = FS_PROGRAM_LONGWORD; + k_chip->cache_type = KINETIS_CACHE_L; + k_chip->watchdog_type = KINETIS_WDOG_COP; + break; + default: + LOG_ERROR("Unsupported KW FAMILYID SUBFAMID"); + } + snprintf(name, sizeof(name), "MKW%u%uZ%%s%u", + familyid, subfamid, cpu_mhz / 10); + break; + case KINETIS_SDID_SERIESID_KV: /* KV-series */ k_chip->watchdog_type = KINETIS_WDOG_K; From 2de82d39a2df0bfc040f753549eabcb5b737beb1 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Nov 2016 08:18:45 +0100 Subject: [PATCH 12/68] flash/nor/tcl: Respect flash bank boundary in verify_bank Respect the flash bank boundary and compare only the remaining content of the bank even if the file content is larger. Change-Id: I4d75979c7893fdd4d18372fa6b0321a0486b4fa9 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3859 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/tcl.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index b93d12694..ed5f77eea 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -705,6 +705,7 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) struct fileio *fileio; size_t read_cnt; size_t filesize; + size_t length; int differ; if (CMD_ARGC < 2 || CMD_ARGC > 3) @@ -741,14 +742,26 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) return retval; } - buffer_file = malloc(filesize); + length = MIN(filesize, p->size - offset); + + if (!length) { + LOG_INFO("Nothing to compare with flash bank"); + fileio_close(fileio); + return ERROR_OK; + } + + if (length != filesize) + LOG_INFO("File content exceeds flash bank size. Only comparing the " + "first %zu bytes of the file", length); + + buffer_file = malloc(length); if (buffer_file == NULL) { LOG_ERROR("Out of memory"); fileio_close(fileio); return ERROR_FAIL; } - retval = fileio_read(fileio, filesize, buffer_file, &read_cnt); + retval = fileio_read(fileio, length, buffer_file, &read_cnt); fileio_close(fileio); if (retval != ERROR_OK) { LOG_ERROR("File read failure"); @@ -756,20 +769,20 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) return retval; } - if (read_cnt != filesize) { + if (read_cnt != length) { LOG_ERROR("Short read"); free(buffer_file); return ERROR_FAIL; } - buffer_flash = malloc(filesize); + buffer_flash = malloc(length); if (buffer_flash == NULL) { LOG_ERROR("Out of memory"); free(buffer_file); return ERROR_FAIL; } - retval = flash_driver_read(p, buffer_flash, offset, read_cnt); + retval = flash_driver_read(p, buffer_flash, offset, length); if (retval != ERROR_OK) { LOG_ERROR("Flash read error"); free(buffer_flash); @@ -780,15 +793,15 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) if (duration_measure(&bench) == ERROR_OK) command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - read_cnt, CMD_ARGV[1], p->bank_number, offset, - duration_elapsed(&bench), duration_kbps(&bench, read_cnt)); + length, CMD_ARGV[1], p->bank_number, offset, + duration_elapsed(&bench), duration_kbps(&bench, length)); - differ = memcmp(buffer_file, buffer_flash, read_cnt); + differ = memcmp(buffer_file, buffer_flash, length); command_print(CMD_CTX, "contents %s", differ ? "differ" : "match"); if (differ) { uint32_t t; int diffs = 0; - for (t = 0; t < read_cnt; t++) { + for (t = 0; t < length; t++) { if (buffer_flash[t] == buffer_file[t]) continue; command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", From bdc71c5252995d55298ba7bba49adec074104619 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Nov 2016 08:39:03 +0100 Subject: [PATCH 13/68] flash/nor/tcl: Make write_bank parameter optional Make the 'offset' parameter optional, if omitted simply start at the beginning of the flash bank. Additionally, check if the argument is out of bounds of the flash bank. Change-Id: I8e9632b539ad9e83211e1ac6a06da4c8109cbc60 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3860 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 5 +++-- src/flash/nor/tcl.c | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index d26c55a68..329b70594 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4715,9 +4715,10 @@ each block, and the specified length must stay within that bank. @end deffn @comment no current checks for errors if fill blocks touch multiple banks! -@deffn Command {flash write_bank} num filename offset +@deffn Command {flash write_bank} num filename [offset] Write the binary @file{filename} to flash bank @var{num}, -starting at @var{offset} bytes from the beginning of the bank. +starting at @var{offset} bytes from the beginning of the bank. If @var{offset} +is omitted, start at the beginning of the flash bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index ed5f77eea..2bc0f8a9e 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -585,7 +585,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) uint8_t *buffer; struct fileio *fileio; - if (CMD_ARGC != 3) + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; struct duration bench; @@ -596,7 +596,16 @@ COMMAND_HANDLER(handle_flash_write_bank_command) if (ERROR_OK != retval) return retval; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + offset = 0; + + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + + if (offset > p->size) { + LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank", + offset); + return ERROR_COMMAND_ARGUMENT_INVALID; + } if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) return ERROR_FAIL; @@ -921,10 +930,9 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "write_bank", .handler = handle_flash_write_bank_command, .mode = COMMAND_EXEC, - .usage = "bank_id filename offset", - .help = "Write binary data from file to flash bank, " - "starting at specified byte offset from the " - "beginning of the bank.", + .usage = "bank_id filename [offset]", + .help = "Write binary data from file to flash bank. Allow optional " + "offset from beginning of the bank (defaults to zero).", }, { .name = "write_image", From 7112e5f57afffb3b387283f2f6048bf45f25c840 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Nov 2016 09:02:11 +0100 Subject: [PATCH 14/68] flash/nor/tcl: Respect flash bank boundary in write_bank Respect the flash bank boundary and write only to the remaining part of the bank even if the file content is larger. Change-Id: I8f4c1b161c103a77bdb30c6bf052293b5ed48c41 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3861 Tested-by: jenkins Reviewed-by: Paul Fertser Reviewed-by: Tomas Vanek --- src/flash/nor/tcl.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 2bc0f8a9e..ab3b1eaf5 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -583,6 +583,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) { uint32_t offset; uint8_t *buffer; + size_t length; struct fileio *fileio; if (CMD_ARGC < 2 || CMD_ARGC > 3) @@ -617,20 +618,38 @@ COMMAND_HANDLER(handle_flash_write_bank_command) return retval; } - buffer = malloc(filesize); + length = MIN(filesize, p->size - offset); + + if (!length) { + LOG_INFO("Nothing to write to flash bank"); + fileio_close(fileio); + return ERROR_OK; + } + + if (length != filesize) + LOG_INFO("File content exceeds flash bank size. Only writing the " + "first %zu bytes of the file", length); + + buffer = malloc(length); if (buffer == NULL) { fileio_close(fileio); LOG_ERROR("Out of memory"); return ERROR_FAIL; } size_t buf_cnt; - if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { + if (fileio_read(fileio, length, buffer, &buf_cnt) != ERROR_OK) { free(buffer); fileio_close(fileio); return ERROR_FAIL; } - retval = flash_driver_write(p, buffer, offset, buf_cnt); + if (buf_cnt != length) { + LOG_ERROR("Short read"); + free(buffer); + return ERROR_FAIL; + } + + retval = flash_driver_write(p, buffer, offset, length); free(buffer); buffer = NULL; @@ -638,8 +657,8 @@ COMMAND_HANDLER(handle_flash_write_bank_command) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { command_print(CMD_CTX, "wrote %zu bytes from file %s to flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - filesize, CMD_ARGV[1], p->bank_number, offset, - duration_elapsed(&bench), duration_kbps(&bench, filesize)); + length, CMD_ARGV[1], p->bank_number, offset, + duration_elapsed(&bench), duration_kbps(&bench, length)); } fileio_close(fileio); From 1725abc3c0b69660cfe3e43ee3f3dbb479821b31 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Nov 2016 09:19:21 +0100 Subject: [PATCH 15/68] flash/nor/tcl: Make read_bank parameters optional Make 'offset' and 'length' parameters optional, if both are omitted simply read the whole flash bank. Additionally, check if the 'offset' and 'length' arguments are out of bounds of the flash bank. Change-Id: Ib9c1b0538a2c78ebcf702e2da11468dff407f8ff Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3862 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 6 ++++-- src/flash/nor/tcl.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 329b70594..30d8aaeb4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4722,9 +4722,11 @@ is omitted, start at the beginning of the flash bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash read_bank} num filename offset length +@deffn Command {flash read_bank} num filename [offset [length]] Read @var{length} bytes from the flash bank @var{num} starting at @var{offset} -and write the contents to the binary @file{filename}. +and write the contents to the binary @file{filename}. If @var{offset} is +omitted, start at the beginning of the flash bank. If @var{length} is omitted, +read the remaining bytes from the flash bank. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index ab3b1eaf5..e5e280111 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -674,7 +674,7 @@ COMMAND_HANDLER(handle_flash_read_bank_command) uint32_t length; size_t written; - if (CMD_ARGC != 4) + if (CMD_ARGC < 2 || CMD_ARGC > 4) return ERROR_COMMAND_SYNTAX_ERROR; struct duration bench; @@ -682,11 +682,31 @@ COMMAND_HANDLER(handle_flash_read_bank_command) struct flash_bank *p; int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); + if (ERROR_OK != retval) return retval; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length); + offset = 0; + + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + + if (offset > p->size) { + LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank", + offset); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + length = p->size - offset; + + if (CMD_ARGC > 3) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length); + + if (offset + length > p->size) { + LOG_ERROR("Length of %" PRIu32 " bytes with offset 0x%8.8" PRIx32 + " is out of range of the flash bank", length, offset); + return ERROR_COMMAND_ARGUMENT_INVALID; + } buffer = malloc(length); if (buffer == NULL) { @@ -966,10 +986,9 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "read_bank", .handler = handle_flash_read_bank_command, .mode = COMMAND_EXEC, - .usage = "bank_id filename offset length", - .help = "Read binary data from flash bank to file, " - "starting at specified byte offset from the " - "beginning of the bank.", + .usage = "bank_id filename [offset [length]]", + .help = "Read binary data from flash bank to file. Allow optional " + "offset from beginning of the bank (defaults to zero).", }, { .name = "verify_bank", From 868a100143ad74fb194040df7da6895b0e55d0a3 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Thu, 22 Jun 2017 14:23:58 +0200 Subject: [PATCH 16/68] target: Fix snprintf format string and argument mismatch in md output Commit 47b8cf842 changed the fixed type of the value argument to snprint but didn't change the format string to match for sizes != 64 bit. Change-Id: I908b06f49ab69d04224282949190a0de883048e0 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/4167 Tested-by: jenkins Reviewed-by: Stian Skjelstad Reviewed-by: Philipp Guehring --- src/target/target.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index e04ecc470..8f9766694 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3024,16 +3024,16 @@ static void handle_md_output(struct command_context *cmd_ctx, const char *value_fmt; switch (size) { case 8: - value_fmt = "%16.16llx "; + value_fmt = "%16.16"PRIx64" "; break; case 4: - value_fmt = "%8.8x "; + value_fmt = "%8.8"PRIx64" "; break; case 2: - value_fmt = "%4.4x "; + value_fmt = "%4.4"PRIx64" "; break; case 1: - value_fmt = "%2.2x "; + value_fmt = "%2.2"PRIx64" "; break; default: /* "can't happen", caller checked */ From b3cf9a665c00b7a7309a936d117e9f098943ad6b Mon Sep 17 00:00:00 2001 From: Richard Watts Date: Mon, 2 Jan 2017 11:56:36 +0000 Subject: [PATCH 17/68] flash/nor/efm32: Support EZR32HG devices. Recognise the family number for Silicon Labs EZR32HG devices and select the correct flash page size. Change-Id: I876e930f3a9f679557fa0d0acac33e9bbfb28c46 Signed-off-by: Richard Watts Reviewed-on: http://openocd.zylin.com/3934 Tested-by: jenkins Reviewed-by: Fredrik Hederstierna Reviewed-by: Jonas Norling Reviewed-by: Freddie Chopin --- src/flash/nor/efm32.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index 81c1a379c..117cd8a1b 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -48,6 +48,7 @@ #define EFM_FAMILY_ID_HAPPY_GECKO 77 #define EZR_FAMILY_ID_WONDER_GECKO 120 #define EZR_FAMILY_ID_LEOPARD_GECKO 121 +#define EZR_FAMILY_ID_HAPPY_GECKO 122 #define EFM32_FLASH_ERASE_TMO 100 #define EFM32_FLASH_WDATAREADY_TMO 100 @@ -178,7 +179,8 @@ static int efm32x_read_info(struct flash_bank *bank, EFM_FAMILY_ID_TINY_GECKO == efm32_info->part_family) efm32_info->page_size = 512; else if (EFM_FAMILY_ID_ZERO_GECKO == efm32_info->part_family || - EFM_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family) + EFM_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family || + EZR_FAMILY_ID_HAPPY_GECKO == efm32_info->part_family) efm32_info->page_size = 1024; else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family || EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) { @@ -236,6 +238,7 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size) switch (info->part_family) { case EZR_FAMILY_ID_WONDER_GECKO: case EZR_FAMILY_ID_LEOPARD_GECKO: + case EZR_FAMILY_ID_HAPPY_GECKO: printed = snprintf(buf, buf_size, "EZR32 "); break; default: @@ -270,6 +273,7 @@ static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size) printed = snprintf(buf, buf_size, "Zero Gecko"); break; case EFM_FAMILY_ID_HAPPY_GECKO: + case EZR_FAMILY_ID_HAPPY_GECKO: printed = snprintf(buf, buf_size, "Happy Gecko"); break; } From 6767c1c1a31aac084467aa50d5810f7a4ca563f4 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Fri, 30 Jun 2017 11:54:38 -0700 Subject: [PATCH 18/68] zynq_7000: Add expected id for Zynq 7z100 devices As found on the NI Project Sulfur SDR board. Change-Id: I47bdd38ae85cf45cedad8797ea03bf3105153320 Signed-off-by: Moritz Fischer Reviewed-on: http://openocd.zylin.com/4176 Tested-by: jenkins Reviewed-by: Freddie Chopin --- tcl/target/zynq_7000.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tcl/target/zynq_7000.cfg b/tcl/target/zynq_7000.cfg index b11de3287..70a861625 100644 --- a/tcl/target/zynq_7000.cfg +++ b/tcl/target/zynq_7000.cfg @@ -10,7 +10,8 @@ set _TARGETNAME $_CHIPNAME.cpu jtag newtap zynq_pl bs -irlen 6 -ircapture 0x1 -irmask 0x03 \ -expected-id 0x23727093 \ -expected-id 0x13722093 \ - -expected-id 0x03727093 + -expected-id 0x03727093 \ + -expected-id 0x03736093 jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4ba00477 From e6fe4dddb97835a60cc512fea977550d7ae4056f Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Wed, 3 May 2017 12:17:45 -0500 Subject: [PATCH 19/68] rtos: style corrections for uCOS-III This patch corrects a number of style infractions in RTOS support for uC/OS-III. These were missed during initial review last year prior to the 0.10.0 release. Change-Id: Ia2139f6ca381d4087fd8ee989f7a03ac474d7440 Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/4120 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/rtos/rtos_ucos_iii_stackings.c | 55 ++++++------ src/rtos/rtos_ucos_iii_stackings.h | 4 +- src/rtos/uCOS-III.c | 133 ++++++++++++++--------------- 3 files changed, 95 insertions(+), 97 deletions(-) diff --git a/src/rtos/rtos_ucos_iii_stackings.c b/src/rtos/rtos_ucos_iii_stackings.c index f2f5564fd..c260b7f80 100644 --- a/src/rtos/rtos_ucos_iii_stackings.c +++ b/src/rtos/rtos_ucos_iii_stackings.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2016 by Square, Inc. * + * Copyright (C) 2017 by Square, Inc. * * Steven Stallion * * * * This program is free software; you can redistribute it and/or modify * @@ -20,34 +20,35 @@ #include "config.h" #endif -#include "rtos.h" -#include "rtos_standard_stackings.h" -#include "target/armv7m.h" +#include +#include +#include +#include -static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = { - { 0x20, 32 }, /* r0 */ - { 0x24, 32 }, /* r1 */ - { 0x28, 32 }, /* r2 */ - { 0x2c, 32 }, /* r3 */ - { 0x00, 32 }, /* r4 */ - { 0x04, 32 }, /* r5 */ - { 0x08, 32 }, /* r6 */ - { 0x0c, 32 }, /* r7 */ - { 0x10, 32 }, /* r8 */ - { 0x14, 32 }, /* r9 */ - { 0x18, 32 }, /* r10 */ - { 0x1c, 32 }, /* r11 */ - { 0x30, 32 }, /* r12 */ - { -2, 32 }, /* sp */ - { 0x34, 32 }, /* lr */ - { 0x38, 32 }, /* pc */ - { 0x3c, 32 }, /* xPSR */ +static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[] = { + { 0x20, 32 }, /* r0 */ + { 0x24, 32 }, /* r1 */ + { 0x28, 32 }, /* r2 */ + { 0x2c, 32 }, /* r3 */ + { 0x00, 32 }, /* r4 */ + { 0x04, 32 }, /* r5 */ + { 0x08, 32 }, /* r6 */ + { 0x0c, 32 }, /* r7 */ + { 0x10, 32 }, /* r8 */ + { 0x14, 32 }, /* r9 */ + { 0x18, 32 }, /* r10 */ + { 0x1c, 32 }, /* r11 */ + { 0x30, 32 }, /* r12 */ + { -2, 32 }, /* sp */ + { 0x34, 32 }, /* lr */ + { 0x38, 32 }, /* pc */ + { 0x3c, 32 }, /* xPSR */ }; const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = { - 0x40, /* stack_registers_size */ - -1, /* stack_growth_direction */ - ARMV7M_NUM_CORE_REGS, /* num_output_registers */ - rtos_generic_stack_align8, /* stack_alignment */ - rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */ + 0x40, /* stack_registers_size */ + -1, /* stack_growth_direction */ + ARRAY_SIZE(rtos_uCOS_III_Cortex_M_stack_offsets), /* num_output_registers */ + rtos_generic_stack_align8, /* stack_alignment */ + rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */ }; diff --git a/src/rtos/rtos_ucos_iii_stackings.h b/src/rtos/rtos_ucos_iii_stackings.h index c462cd745..f4703da37 100644 --- a/src/rtos/rtos_ucos_iii_stackings.h +++ b/src/rtos/rtos_ucos_iii_stackings.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2016 by Square, Inc. * + * Copyright (C) 2017 by Square, Inc. * * Steven Stallion * * * * This program is free software; you can redistribute it and/or modify * @@ -23,7 +23,7 @@ #include "config.h" #endif -#include "rtos.h" +#include extern const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking; diff --git a/src/rtos/uCOS-III.c b/src/rtos/uCOS-III.c index 75cfe52bd..9021167db 100644 --- a/src/rtos/uCOS-III.c +++ b/src/rtos/uCOS-III.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2016 by Square, Inc. * + * Copyright (C) 2017 by Square, Inc. * * Steven Stallion * * * * This program is free software; you can redistribute it and/or modify * @@ -20,14 +20,14 @@ #include "config.h" #endif +#include #include -#include -#include "target/target.h" -#include "target/target_type.h" -#include "rtos.h" -#include "helper/log.h" -#include "helper/types.h" -#include "rtos/rtos_ucos_iii_stackings.h" +#include +#include +#include +#include + +#include "rtos_ucos_iii_stackings.h" #ifndef UCOS_III_MAX_STRLEN #define UCOS_III_MAX_STRLEN 64 @@ -55,18 +55,18 @@ struct uCOS_III_params { static const struct uCOS_III_params uCOS_III_params_list[] = { { - "cortex_m", /* target_name */ - sizeof(uint32_t), /* pointer_width */ - 0, /* thread_stack_offset */ - 0, /* thread_name_offset */ - 0, /* thread_state_offset */ - 0, /* thread_priority_offset */ - 0, /* thread_prev_offset */ - 0, /* thread_next_offset */ - false, /* thread_offsets_updated */ - 1, /* threadid_start */ + "cortex_m", /* target_name */ + sizeof(uint32_t), /* pointer_width */ + 0, /* thread_stack_offset */ + 0, /* thread_name_offset */ + 0, /* thread_state_offset */ + 0, /* thread_priority_offset */ + 0, /* thread_prev_offset */ + 0, /* thread_next_offset */ + false, /* thread_offsets_updated */ + 1, /* threadid_start */ &rtos_uCOS_III_Cortex_M_stacking, /* stacking_info */ - 0, /* num_threads */ + 0, /* num_threads */ }, }; @@ -159,10 +159,10 @@ static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t symbol_address_t thread_list_address = 0; retval = target_read_memory(rtos->target, - rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address, - params->pointer_width, - 1, - (void *)&thread_list_address); + rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address, + params->pointer_width, + 1, + (void *)&thread_list_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread list address"); return retval; @@ -173,10 +173,10 @@ static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address = thread_list_address; retval = target_read_memory(rtos->target, - thread_list_address + params->thread_next_offset, - params->pointer_width, - 1, - (void *)&thread_list_address); + thread_list_address + params->thread_next_offset, + params->pointer_width, + 1, + (void *)&thread_list_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read next thread address"); return retval; @@ -227,10 +227,10 @@ static int uCOS_III_update_thread_offsets(struct rtos *rtos) const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i]; int retval = target_read_memory(rtos->target, - rtos->symbols[thread_offset_map->symbol_value].address, - params->pointer_width, - 1, - (void *)thread_offset_map->thread_offset); + rtos->symbols[thread_offset_map->symbol_value].address, + params->pointer_width, + 1, + (void *)thread_offset_map->thread_offset); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread offset"); return retval; @@ -244,7 +244,7 @@ static int uCOS_III_update_thread_offsets(struct rtos *rtos) static int uCOS_III_detect_rtos(struct target *target) { return target->rtos->symbols != NULL && - target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0; + target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0; } static int uCOS_III_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv) @@ -263,8 +263,7 @@ static int uCOS_III_create(struct target *target) for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_params_list); i++) if (strcmp(uCOS_III_params_list[i].target_name, target->type->name) == 0) { - params = malloc(sizeof(*params) + - UCOS_III_MAX_THREADS * sizeof(*params->threads)); + params = malloc(sizeof(*params) + (UCOS_III_MAX_THREADS * sizeof(*params->threads))); if (params == NULL) { LOG_ERROR("uCOS-III: out of memory"); return ERROR_FAIL; @@ -294,8 +293,8 @@ static int uCOS_III_update_threads(struct rtos *rtos) uint8_t rtos_running; retval = target_read_u8(rtos->target, - rtos->symbols[uCOS_III_VAL_OSRunning].address, - &rtos_running); + rtos->symbols[uCOS_III_VAL_OSRunning].address, + &rtos_running); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read RTOS running"); return retval; @@ -327,10 +326,10 @@ static int uCOS_III_update_threads(struct rtos *rtos) symbol_address_t current_thread_address = 0; retval = target_read_memory(rtos->target, - rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address, - params->pointer_width, - 1, - (void *)¤t_thread_address); + rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address, + params->pointer_width, + 1, + (void *)¤t_thread_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read current thread address"); return retval; @@ -338,8 +337,8 @@ static int uCOS_III_update_threads(struct rtos *rtos) /* read number of tasks */ retval = target_read_u16(rtos->target, - rtos->symbols[uCOS_III_VAL_OSTaskQty].address, - (void *)&rtos->thread_count); + rtos->symbols[uCOS_III_VAL_OSTaskQty].address, + (void *)&rtos->thread_count); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread count"); return retval; @@ -368,9 +367,7 @@ static int uCOS_III_update_threads(struct rtos *rtos) char thread_str_buffer[UCOS_III_MAX_STRLEN + 1]; /* find or create new threadid */ - retval = uCOS_III_find_or_create_thread(rtos, - thread_address, - &thread_detail->threadid); + retval = uCOS_III_find_or_create_thread(rtos, thread_address, &thread_detail->threadid); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to find or create thread"); return retval; @@ -385,19 +382,19 @@ static int uCOS_III_update_threads(struct rtos *rtos) symbol_address_t thread_name_address = 0; retval = target_read_memory(rtos->target, - thread_address + params->thread_name_offset, - params->pointer_width, - 1, - (void *)&thread_name_address); + thread_address + params->thread_name_offset, + params->pointer_width, + 1, + (void *)&thread_name_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to name address"); return retval; } retval = target_read_buffer(rtos->target, - thread_name_address, - sizeof(thread_str_buffer), - (void *)thread_str_buffer); + thread_name_address, + sizeof(thread_str_buffer), + (void *)thread_str_buffer); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread name"); return retval; @@ -411,16 +408,16 @@ static int uCOS_III_update_threads(struct rtos *rtos) uint8_t thread_priority; retval = target_read_u8(rtos->target, - thread_address + params->thread_state_offset, - &thread_state); + thread_address + params->thread_state_offset, + &thread_state); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread state"); return retval; } retval = target_read_u8(rtos->target, - thread_address + params->thread_priority_offset, - &thread_priority); + thread_address + params->thread_priority_offset, + &thread_priority); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read thread priority"); return retval; @@ -434,15 +431,15 @@ static int uCOS_III_update_threads(struct rtos *rtos) thread_state_str = "Unknown"; snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d", - thread_state_str, thread_priority); + thread_state_str, thread_priority); thread_detail->extra_info_str = strdup(thread_str_buffer); /* read previous thread address */ retval = target_read_memory(rtos->target, - thread_address + params->thread_prev_offset, - params->pointer_width, - 1, - (void *)&thread_address); + thread_address + params->thread_prev_offset, + params->pointer_width, + 1, + (void *)&thread_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read previous thread address"); return retval; @@ -470,19 +467,19 @@ static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid, symbol_address_t stack_address = 0; retval = target_read_memory(rtos->target, - thread_address + params->thread_stack_offset, - params->pointer_width, - 1, - (void *)&stack_address); + thread_address + params->thread_stack_offset, + params->pointer_width, + 1, + (void *)&stack_address); if (retval != ERROR_OK) { LOG_ERROR("uCOS-III: failed to read stack address"); return retval; } return rtos_generic_stack_read(rtos->target, - params->stacking_info, - stack_address, - hex_reg_list); + params->stacking_info, + stack_address, + hex_reg_list); } static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) From 0e4fbfba03e7453846e75b2a54a8b8a6613dbb1e Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Wed, 21 Jun 2017 22:14:08 -0700 Subject: [PATCH 20/68] rtos: better sanity checking for uCOS-III This patch improves the OSRunning check. If the rtos_running check fails, update_threads will return an error rather than attempt to update the thread list using bad values. Change-Id: I8614c325504d3a9ab19aebb6862b1fe445a0c8e7 Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/4166 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/rtos/uCOS-III.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rtos/uCOS-III.c b/src/rtos/uCOS-III.c index 9021167db..0a0fb3e9e 100644 --- a/src/rtos/uCOS-III.c +++ b/src/rtos/uCOS-III.c @@ -300,6 +300,11 @@ static int uCOS_III_update_threads(struct rtos *rtos) return retval; } + if (rtos_running != 1 && rtos_running != 0) { + LOG_ERROR("uCOS-III: invalid RTOS running value"); + return ERROR_FAIL; + } + if (!rtos_running) { rtos->thread_details = calloc(1, sizeof(struct thread_detail)); if (rtos->thread_details == NULL) { From 29cfe9c5eede2cd2fb3a62f44bdaf4f58377b027 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Thu, 6 Jul 2017 09:51:40 +0200 Subject: [PATCH 21/68] mips32: inline functions in headers must be static Change-Id: If1d0fc6766cadc2db33408ae5c0968de6b7a1b94 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/4178 Tested-by: jenkins Reviewed-by: Salvador Arroyo Reviewed-by: Stian Skjelstad --- src/target/mips32_pracc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index b8b93c649..888c847c0 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -114,7 +114,7 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); -inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) +static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) { if (ejtag_info->isa && ejtag_info->endianness) for (int i = 0; i != count; i++) From dbd0d90af9ba12934eabd68d82aac9d7eb7e1e6a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 29 Jun 2017 23:06:55 +0200 Subject: [PATCH 22/68] flash Kinetis: fix devices with smallest program flash (8 and 16 kB) Change-Id: I2692b9877a7f877104528f279a69e8cc1cfbcdbf Reported-by: David Miller Lowe Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4173 Tested-by: jenkins Reviewed-by: Miller Lowe Reviewed-by: Paul Fertser --- src/flash/nor/kinetis.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 12efefbd9..f57579dda 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -2461,6 +2461,10 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) } switch (fcfg1_pfsize) { + case 0x00: + k_chip->pflash_size = 8192; + break; + case 0x01: case 0x03: case 0x05: case 0x07: @@ -2471,6 +2475,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) break; case 0x0f: /* a peculiar case: Freescale states different sizes for 0xf + * KL03P24M48SF0RM 32 KB .... duplicate of code 0x3 * K02P64M100SFARM 128 KB ... duplicate of code 0x7 * K22P121M120SF8RM 256 KB ... duplicate of code 0x9 * K22P121M120SF7RM 512 KB ... duplicate of code 0xb @@ -2562,7 +2567,7 @@ static int kinetis_probe(struct flash_bank *bank) * parts with more than 32K of PFlash. For parts with * less the protection unit is set to 1024 bytes */ k_bank->protection_size = MAX(k_chip->pflash_size / 32, 1024); - bank->num_prot_blocks = 32 / k_chip->num_pflash_blocks; + bank->num_prot_blocks = bank->size / k_bank->protection_size; k_bank->protection_block = bank->num_prot_blocks * k_bank->bank_number; size_k = bank->size / 1024; From 02bc718d1a49dd04bffa446f1dadd6b86d0d107c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 13 Jul 2017 21:35:22 +0200 Subject: [PATCH 23/68] flash Kinetis: fix probe for FlexNVM partitioned as EEPROM backup If a MCU has FlexNVM partitioned as EEPROM backup only (no data flash), kinetis_probe_chip() detects zero fcfg2_maxaddr1 and adjusts flash banks count to 1, what is obviously wrong. The change limits the test to devices without FlexNVM. Computation of program flash/FlexNVM blocks is now more robust. Missing case 0x07 is added to switch (fcfg1_depart) Change-Id: I0bd6030a0fe1ab62aeb0223bbdf2aee1505bf6a0 Reported-by: simon.haines@scalardata.com Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/4180 Tested-by: jenkins Reviewed-by: Simon Haines Reviewed-by: Paul Fertser --- src/flash/nor/kinetis.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index f57579dda..4ef438507 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -2387,7 +2387,9 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) if (num_blocks == 0) num_blocks = k_chip->fcfg2_maxaddr1_shifted ? 2 : 1; - else if (k_chip->fcfg2_maxaddr1_shifted == 0 && num_blocks >= 2) { + else if (k_chip->fcfg2_maxaddr1_shifted == 0 && num_blocks >= 2 && fcfg2_pflsh) { + /* fcfg2_maxaddr1 may be zero due to partitioning whole NVM as EEPROM backup + * Do not adjust block count in this case! */ num_blocks = 1; LOG_WARNING("MAXADDR1 is zero, number of flash banks adjusted to 1"); } else if (k_chip->fcfg2_maxaddr1_shifted != 0 && num_blocks == 1) { @@ -2444,6 +2446,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) case 0x06: k_chip->dflash_size = k_chip->nvm_size - (4096 << fcfg1_depart); break; + case 0x07: case 0x08: k_chip->dflash_size = 0; break; @@ -2502,8 +2505,13 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) /* Program section size is equal to sector size by default */ } - k_chip->num_pflash_blocks = num_blocks / (2 - fcfg2_pflsh); - k_chip->num_nvm_blocks = num_blocks - k_chip->num_pflash_blocks; + if (fcfg2_pflsh) { + k_chip->num_pflash_blocks = num_blocks; + k_chip->num_nvm_blocks = 0; + } else { + k_chip->num_pflash_blocks = (num_blocks + 1) / 2; + k_chip->num_nvm_blocks = num_blocks - k_chip->num_pflash_blocks; + } if (use_nvm_marking) { nvm_marking[0] = k_chip->num_nvm_blocks ? 'X' : 'N'; From 04b23ef5022bd0ebbcac7ceed5112d822bbd966d Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Wed, 9 Aug 2017 17:11:29 +0000 Subject: [PATCH 24/68] stm32l1: Devid 0x429 only has 8bit flash size register A footnote in RM0038r14. Change-Id: Ic31894d846fbbe917a7290b2b7ff8fb582bb65da Signed-off-by: Karl Palsson Reviewed-on: http://openocd.zylin.com/4198 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Spencer Oliver --- src/flash/nor/stm32lx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index e4f499d3c..0c2fddc92 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -790,6 +790,11 @@ static int stm32lx_probe(struct flash_bank *bank) flash_size_in_kb = 256; } + /* 0x429 devices only use the lowest 8 bits of the flash size register */ + if (retval == ERROR_OK && (device_id & 0xfff) == 0x429) { + flash_size_in_kb &= 0xff; + } + /* Failed reading flash size or flash size invalid (early silicon), * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { From 3ee81fd78760b2a7b6e70663f22045706bbcd65a Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 2 Apr 2017 12:54:43 +0200 Subject: [PATCH 25/68] log: Add a new debug level (4) for verbose I/O debug Change ftdi SWD driver and CMSIS-DAP to use it instead of LOG_DEBUG(). Change-Id: I17ba3de2086c7159209db61fba3faf067dfc5023 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3805 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 8 +++++--- src/helper/log.c | 12 +++++++----- src/helper/log.h | 12 +++++++++++- src/jtag/drivers/cmsis_dap_usb.c | 6 +++--- src/jtag/drivers/ftdi.c | 6 +++--- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 30d8aaeb4..959f71891 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -682,7 +682,8 @@ bash$ openocd --help --version | -v display OpenOCD version --file | -f use configuration file --search | -s dir to search for config files and scripts ---debug | -d set debug level <0-3> +--debug | -d set debug level to 3 + | -d set debug level to --log_output | -l redirect log output to file --command | -c run @end verbatim @@ -6849,12 +6850,13 @@ non-zero exit code to the parent process. @deffn Command debug_level [n] @cindex message level Display debug level. -If @var{n} (from 0..3) is provided, then set it to that level. +If @var{n} (from 0..4) is provided, then set it to that level. This affects the kind of messages sent to the server log. Level 0 is error messages only; level 1 adds warnings; level 2 adds informational messages; -and level 3 adds debugging messages. +level 3 adds debugging messages; +and level 4 adds verbose low-level debug messages. The default is level 2, but that can be overridden on the command line along with the location of that log file (which is normally the server's standard output). diff --git a/src/helper/log.c b/src/helper/log.c index 891613d31..49b9bd98f 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -50,11 +50,12 @@ static int64_t current_time; static int64_t start; -static const char * const log_strings[5] = { +static const char * const log_strings[6] = { "User : ", "Error: ", "Warn : ", /* want a space after each colon, all same width, colons aligned */ "Info : ", + "Debug: ", "Debug: " }; @@ -234,8 +235,8 @@ COMMAND_HANDLER(handle_debug_level_command) if (CMD_ARGC == 1) { int new_level; COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level); - if ((new_level > LOG_LVL_DEBUG) || (new_level < LOG_LVL_SILENT)) { - LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG); + if ((new_level > LOG_LVL_DEBUG_IO) || (new_level < LOG_LVL_SILENT)) { + LOG_ERROR("level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG_IO); return ERROR_COMMAND_SYNTAX_ERROR; } debug_level = new_level; @@ -279,7 +280,8 @@ static struct command_registration log_command_handlers[] = { .mode = COMMAND_ANY, .help = "Sets the verbosity level of debugging output. " "0 shows errors only; 1 adds warnings; " - "2 (default) adds other info; 3 adds debugging.", + "2 (default) adds other info; 3 adds debugging; " + "4 adds extra verbose debugging.", .usage = "number", }, COMMAND_REGISTRATION_DONE @@ -303,7 +305,7 @@ void log_init(void) int retval = parse_int(debug_env, &value); if (ERROR_OK == retval && debug_level >= LOG_LVL_SILENT && - debug_level <= LOG_LVL_DEBUG) + debug_level <= LOG_LVL_DEBUG_IO) debug_level = value; } diff --git a/src/helper/log.h b/src/helper/log.h index 6b938165b..512bcc512 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -46,6 +46,7 @@ * LOG_LVL_WARNING - non-fatal errors, that may be resolved later * LOG_LVL_INFO - state information, etc. * LOG_LVL_DEBUG - debug statements, execution trace + * LOG_LVL_DEBUG_IO - verbose debug, low-level I/O trace */ enum log_levels { LOG_LVL_SILENT = -3, @@ -54,7 +55,8 @@ enum log_levels { LOG_LVL_ERROR = 0, LOG_LVL_WARNING = 1, LOG_LVL_INFO = 2, - LOG_LVL_DEBUG = 3 + LOG_LVL_DEBUG = 3, + LOG_LVL_DEBUG_IO = 4, }; void log_printf(enum log_levels level, const char *file, unsigned line, @@ -102,6 +104,14 @@ extern int debug_level; #define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO)) +#define LOG_DEBUG_IO(expr ...) \ + do { \ + if (debug_level >= LOG_LVL_DEBUG_IO) \ + log_printf_lf(LOG_LVL_DEBUG, \ + __FILE__, __LINE__, __func__, \ + expr); \ + } while (0) + #define LOG_DEBUG(expr ...) \ do { \ if (debug_level >= LOG_LVL_DEBUG) \ diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index 86f796877..19c3b19c9 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -596,7 +596,7 @@ static int cmsis_dap_swd_run_queue(void) { uint8_t *buffer = cmsis_dap_handle->packet_buffer; - LOG_DEBUG("Executing %d queued transactions", pending_transfer_count); + LOG_DEBUG_IO("Executing %d queued transactions", pending_transfer_count); if (queued_retval != ERROR_OK) { LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); @@ -616,7 +616,7 @@ static int cmsis_dap_swd_run_queue(void) uint8_t cmd = pending_transfers[i].cmd; uint32_t data = pending_transfers[i].data; - LOG_DEBUG("%s %s reg %x %"PRIx32, + LOG_DEBUG_IO("%s %s reg %x %"PRIx32, cmd & SWD_CMD_APnDP ? "AP" : "DP", cmd & SWD_CMD_RnW ? "read" : "write", (cmd & SWD_CMD_A32) >> 1, data); @@ -674,7 +674,7 @@ static int cmsis_dap_swd_run_queue(void) uint32_t tmp = data; idx += 4; - LOG_DEBUG("Read result: %"PRIx32, data); + LOG_DEBUG_IO("Read result: %"PRIx32, data); /* Imitate posted AP reads */ if ((pending_transfers[i].cmd & SWD_CMD_APnDP) || diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 00fe37faf..342e32102 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -1074,12 +1074,12 @@ static void ftdi_swd_swdio_en(bool enable) */ static int ftdi_swd_run_queue(void) { - LOG_DEBUG("Executing %zu queued transactions", swd_cmd_queue_length); + LOG_DEBUG_IO("Executing %zu queued transactions", swd_cmd_queue_length); int retval; struct signal *led = find_signal_by_name("LED"); if (queued_retval != ERROR_OK) { - LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); + LOG_DEBUG_IO("Skipping due to previous errors: %d", queued_retval); goto skip; } @@ -1100,7 +1100,7 @@ static int ftdi_swd_run_queue(void) for (size_t i = 0; i < swd_cmd_queue_length; i++) { int ack = buf_get_u32(swd_cmd_queue[i].trn_ack_data_parity_trn, 1, 3); - LOG_DEBUG("%s %s %s reg %X = %08"PRIx32, + LOG_DEBUG_IO("%s %s %s reg %X = %08"PRIx32, ack == SWD_ACK_OK ? "OK" : ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK", swd_cmd_queue[i].cmd & SWD_CMD_APnDP ? "AP" : "DP", swd_cmd_queue[i].cmd & SWD_CMD_RnW ? "read" : "write", From 7719e9618e753ac41a46a2488dfba549ac578891 Mon Sep 17 00:00:00 2001 From: Andreas Bolsch Date: Sun, 5 Mar 2017 19:01:06 +0100 Subject: [PATCH 26/68] Support for STM32F722, F723, F413 and F423 IDs for STM32F722, F723, F413 and F423 added, handling of PCROP for F722/723 and additional nWPRT bits for F413/423 implemented. The additional protection bit positions for F413/423 conflict with other options bits for the F7xx variants, additionally the last two sectors share a common bit. Protection for F413 and F767/777 now use protection blocks rather sectors for dealing with protections bits. Checking for halted state in 'lock' and 'unlock' removed: When PCROP is activated in F723, halted state is not detected properly, but lock/unlock sequence is required to disable PCROP. Tested with STM32F723E-Disco, STM32F413ZH-Nucleo. Change-Id: Ie6ddab47a9ae8461087d369b4f289b7f9d1e031c Signed-off-by: Andreas Bolsch Reviewed-on: http://openocd.zylin.com/4045 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Paul Fertser --- doc/openocd.texi | 13 +- src/flash/nor/stm32f2x.c | 276 +++++++++++++++++++++++++++++++-------- 2 files changed, 229 insertions(+), 60 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 959f71891..89ee5eb45 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5989,16 +5989,21 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f2x options_read} num -Reads and displays user options and (where implemented) boot_addr0 and boot_addr1. +Reads and displays user options and (where implemented) boot_addr0, boot_addr1, optcr2. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn Command {stm32f2x options_write} num user_options boot_addr0 boot_addr1 Writes user options and (where implemented) boot_addr0 and boot_addr1 in raw format. Warning: The meaning of the various bits depends on the device, always check datasheet! -The @var{num} parameter is a value shown by @command{flash banks}, user_options a -12 bit value, consisting of bits 31-28 and 7-0 of FLASH_OPTCR, boot_addr0 and boot_addr1 -two halfwords (of FLASH_OPTCR1). +The @var{num} parameter is a value shown by @command{flash banks}, @var{user_options} a +12 bit value, consisting of bits 31-28 and 7-0 of FLASH_OPTCR, @var{boot_addr0} and +@var{boot_addr1} two halfwords (of FLASH_OPTCR1). +@end deffn + +@deffn Command {stm32f2x optcr2_write} num optcr2 +Writes FLASH_OPTCR2 options. Warning: Clearing PCROPi bits requires a full mass erase! +The @var{num} parameter is a value shown by @command{flash banks}, @var{optcr2} a 32-bit word. @end deffn @end deffn diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 4d750951c..0e4abb533 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -59,10 +59,14 @@ * * Sector sizes in kiBytes: * 1 MiByte part with 4 x 16, 1 x 64, 7 x 128. + * 1.5 MiByte part with 4 x 16, 1 x 64, 11 x 128. * 2 MiByte part with 4 x 16, 1 x 64, 7 x 128, 4 x 16, 1 x 64, 7 x 128. * 1 MiByte STM32F42x/43x part with DB1M Option set: * 4 x 16, 1 x 64, 3 x 128, 4 x 16, 1 x 64, 3 x 128. * + * STM32F7[2|3] + * 512 kiByte part with 4 x 16, 1 x 64, 3 x 128. + * * STM32F7[4|5] * 1 MiByte part with 4 x 32, 1 x 128, 3 x 256. * @@ -93,6 +97,12 @@ * RM0410 * http://www.st.com/resource/en/reference_manual/dm00224583.pdf * + * RM0430 + * http://www.st.com/resource/en/reference_manual/dm00305666.pdf + * + * RM0431 + * http://www.st.com/resource/en/reference_manual/dm00305990.pdf + * * STM32F1x series - notice that this code was copy, pasted and knocked * into a stm32f2x driver, so in case something has been converted or * bugs haven't been fixed, here are the original manuals: @@ -121,6 +131,7 @@ #define STM32_FLASH_CR 0x40023c10 #define STM32_FLASH_OPTCR 0x40023c14 #define STM32_FLASH_OPTCR1 0x40023c18 +#define STM32_FLASH_OPTCR2 0x40023c1c /* FLASH_CR register bits */ #define FLASH_PG (1 << 0) @@ -152,6 +163,10 @@ #define OPTCR_START (1 << 1) #define OPTCR_NDBANK (1 << 29) /* not dual bank mode */ #define OPTCR_DB1M (1 << 30) /* 1 MiB devices dual flash bank option */ +#define OPTCR_SPRMOD (1 << 31) /* switches PCROPi/nWPRi interpretation */ + +/* STM32_FLASH_OPTCR2 register bits */ +#define OPTCR2_PCROP_RDP (1 << 31) /* erase PCROP zone when decreasing RDP */ /* register unlock keys */ #define KEY1 0x45670123 @@ -166,14 +181,17 @@ struct stm32x_options { uint16_t user_options; /* bit 0-7 usual options, bit 8-11 extra options */ uint32_t protection; uint32_t boot_addr; + uint32_t optcr2_pcrop; }; struct stm32x_flash_bank { struct stm32x_options option_bytes; int probed; bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */ - bool has_boot_addr; /* F7xx */ bool has_extra_options; /* F42x/43x/469/479/7xx */ + bool has_boot_addr; /* F7xx */ + bool has_optcr2_pcrop; /* F72x/73x */ + int protection_bits; /* F413/423 */ uint32_t user_bank_size; }; @@ -328,11 +346,13 @@ static int stm32x_read_options(struct flash_bank *bank) * whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */ stm32x_info->option_bytes.user_options = optiondata & 0xfc; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; - stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff; + stm32x_info->option_bytes.protection = + (optiondata >> 16) & (~(0xffff << stm32x_info->protection_bits) & 0xffff); if (stm32x_info->has_extra_options) { /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */ - stm32x_info->option_bytes.user_options |= (optiondata >> 20) & 0xf00; + stm32x_info->option_bytes.user_options |= (optiondata >> 20) & + ((0xf00 << (stm32x_info->protection_bits - 12)) & 0xf00); } if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) { @@ -350,6 +370,20 @@ static int stm32x_read_options(struct flash_bank *bank) } } + if (stm32x_info->has_optcr2_pcrop) { + retval = target_read_u32(target, STM32_FLASH_OPTCR2, &optiondata); + if (retval != ERROR_OK) + return retval; + + stm32x_info->option_bytes.optcr2_pcrop = optiondata; + if (stm32x_info->has_optcr2_pcrop && + (stm32x_info->option_bytes.optcr2_pcrop & ~OPTCR2_PCROP_RDP)) { + LOG_INFO("PCROP Engaged"); + } + } else { + stm32x_info->option_bytes.optcr2_pcrop = 0x0; + } + if (stm32x_info->option_bytes.RDP != 0xAA) LOG_INFO("Device Security Bit Set"); @@ -371,11 +405,13 @@ static int stm32x_write_options(struct flash_bank *bank) /* rebuild option data */ optiondata = stm32x_info->option_bytes.user_options & 0xfc; optiondata |= stm32x_info->option_bytes.RDP << 8; - optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16; + optiondata |= (stm32x_info->option_bytes.protection & + (~(0xffff << stm32x_info->protection_bits))) << 16; if (stm32x_info->has_extra_options) { /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */ - optiondata |= (stm32x_info->option_bytes.user_options & 0xf00) << 20; + optiondata |= (stm32x_info->option_bytes.user_options & + ((0xf00 << (stm32x_info->protection_bits - 12)) & 0xf00)) << 20; } if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) { @@ -392,6 +428,14 @@ static int stm32x_write_options(struct flash_bank *bank) return retval; } + /* program extra pcrop register */ + if (stm32x_info->has_optcr2_pcrop) { + retval = target_write_u32(target, STM32_FLASH_OPTCR2, + stm32x_info->option_bytes.optcr2_pcrop); + if (retval != ERROR_OK) + return retval; + } + /* program options */ retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata); if (retval != ERROR_OK) @@ -418,6 +462,8 @@ static int stm32x_write_options(struct flash_bank *bank) static int stm32x_protect_check(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = bank->driver_priv; + struct flash_sector *prot_blocks; + int num_prot_blocks; /* read write protection settings */ int retval = stm32x_read_options(bank); @@ -426,27 +472,18 @@ static int stm32x_protect_check(struct flash_bank *bank) return retval; } - if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) { - /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */ - for (int i = 0; i < (bank->num_sectors >> 1); i++) { - if (stm32x_info->option_bytes.protection & (1 << i)) { - bank->sectors[i << 1].is_protected = 0; - bank->sectors[(i << 1) + 1].is_protected = 0; - } else { - bank->sectors[i << 1].is_protected = 1; - bank->sectors[(i << 1) + 1].is_protected = 1; - } - } + if (bank->prot_blocks) { + num_prot_blocks = bank->num_prot_blocks; + prot_blocks = bank->prot_blocks; } else { - /* one protection bit per sector */ - for (int i = 0; i < bank->num_sectors; i++) { - if (stm32x_info->option_bytes.protection & (1 << i)) - bank->sectors[i].is_protected = 0; - else - bank->sectors[i].is_protected = 1; - } + num_prot_blocks = bank->num_sectors; + prot_blocks = bank->sectors; } + for (int i = 0; i < num_prot_blocks; i++) + prot_blocks[i].is_protected = + ~(stm32x_info->option_bytes.protection >> i) & 1; + return ERROR_OK; } @@ -515,17 +552,6 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) return retval; } - if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) { - /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */ - if ((first & 1) != 0 || (last & 1) != 1) { - LOG_ERROR("sector protection must be double sector aligned"); - return ERROR_FAIL; - } else { - first >>= 1; - last >>= 1; - } - } - for (int i = first; i <= last; i++) { if (set) stm32x_info->option_bytes.protection &= ~(1 << i); @@ -829,7 +855,7 @@ static int stm32x_probe(struct flash_bank *bank) { struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = bank->driver_priv; - int i; + int i, num_prot_blocks; uint16_t flash_size_in_kb; uint32_t flash_size_reg = 0x1FFF7A22; uint16_t max_sector_size_in_kb = 128; @@ -841,15 +867,31 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->has_large_mem = false; stm32x_info->has_boot_addr = false; stm32x_info->has_extra_options = false; + stm32x_info->has_optcr2_pcrop = false; + stm32x_info->protection_bits = 12; /* max. number of nWRPi bits (in FLASH_OPTCR !!!) */ + num_prot_blocks = 0; + + if (bank->sectors) { + free(bank->sectors); + bank->num_sectors = 0; + bank->sectors = NULL; + } + + if (bank->prot_blocks) { + free(bank->prot_blocks); + bank->num_prot_blocks = 0; + bank->prot_blocks = NULL; + } /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); if (retval != ERROR_OK) return retval; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); + device_id &= 0xfff; /* only bits 0-11 are used further on */ /* set max flash size depending on family, id taken from AN2606 */ - switch (device_id & 0xfff) { + switch (device_id) { case 0x411: /* F20x/21x */ case 0x413: /* F40x/41x */ max_flash_size_in_kb = 1024; @@ -892,6 +934,21 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->has_boot_addr = true; break; + case 0x452: /* F72x/73x */ + max_flash_size_in_kb = 512; + flash_size_reg = 0x1FF07A22; /* yes, 0x1FF*0*7A22, not 0x1FF*F*7A22 */ + stm32x_info->has_extra_options = true; + stm32x_info->has_boot_addr = true; + stm32x_info->has_optcr2_pcrop = true; + break; + + case 0x463: /* F413x/423x */ + max_flash_size_in_kb = 1536; + stm32x_info->has_extra_options = true; + stm32x_info->protection_bits = 15; + num_prot_blocks = 15; + break; + default: LOG_WARNING("Cannot identify target as a STM32 family."); return ERROR_FAIL; @@ -920,12 +977,8 @@ static int stm32x_probe(struct flash_bank *bank) /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); - /* Devices with > 1024 kiByte always are dual-banked */ - if (flash_size_in_kb > 1024) - stm32x_info->has_large_mem = true; - /* F42x/43x/469/479 1024 kiByte devices have a dual bank option */ - if ((device_id & 0xfff) == 0x419 || (device_id & 0xfff) == 0x434) { + if ((device_id == 0x419) || (device_id == 0x434)) { uint32_t optiondata; retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) { @@ -942,7 +995,7 @@ static int stm32x_probe(struct flash_bank *bank) } /* F76x/77x devices have a dual bank option */ - if ((device_id & 0xfff) == 0x451) { + if (device_id == 0x451) { uint32_t optiondata; retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) { @@ -963,11 +1016,6 @@ static int stm32x_probe(struct flash_bank *bank) int num_pages = flash_size_in_kb / max_sector_size_in_kb + (stm32x_info->has_large_mem ? 8 : 4); - if (bank->sectors) { - free(bank->sectors); - bank->sectors = NULL; - } - bank->base = base_address; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); @@ -978,15 +1026,44 @@ static int stm32x_probe(struct flash_bank *bank) bank->size = 0; LOG_DEBUG("allocated %d sectors", num_pages); + /* F76x/77x in dual bank mode */ + if ((device_id == 0x451) && stm32x_info->has_large_mem) + num_prot_blocks = num_pages >> 1; + + if (num_prot_blocks) { + bank->prot_blocks = malloc(sizeof(struct flash_sector) * num_prot_blocks); + for (i = 0; i < num_prot_blocks; i++) + bank->prot_blocks[i].is_protected = 0; + LOG_DEBUG("allocated %d prot blocks", num_prot_blocks); + } + if (stm32x_info->has_large_mem) { /* dual-bank */ setup_bank(bank, 0, flash_size_in_kb >> 1, max_sector_size_in_kb); setup_bank(bank, num_pages >> 1, flash_size_in_kb >> 1, max_sector_size_in_kb); + + /* F767x/F77x in dual mode, one protection bit refers to two adjacent sectors */ + if (device_id == 0x451) { + for (i = 0; i < num_prot_blocks; i++) { + bank->prot_blocks[i].offset = bank->sectors[i << 1].offset; + bank->prot_blocks[i].size = bank->sectors[i << 1].size << 1; + } + } } else { /* single-bank */ setup_bank(bank, 0, flash_size_in_kb, max_sector_size_in_kb); + + /* F413/F423, sectors 14 and 15 share one common protection bit */ + if (device_id == 0x463) { + for (i = 0; i < num_prot_blocks; i++) { + bank->prot_blocks[i].offset = bank->sectors[i].offset; + bank->prot_blocks[i].size = bank->sectors[i].size; + } + bank->prot_blocks[num_prot_blocks - 1].size <<= 1; + } } + bank->num_prot_blocks = num_prot_blocks; assert((bank->size >> 10) == flash_size_in_kb); stm32x_info->probed = 1; @@ -1107,6 +1184,14 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) case 0x1001: rev_str = "Z"; break; + + case 0x2000: + rev_str = "B"; + break; + + case 0x3000: + rev_str = "C"; + break; } break; @@ -1134,6 +1219,26 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) } break; + case 0x452: + device_str = "STM32F7[2|3]x"; + + switch (rev_id) { + case 0x1000: + rev_str = "A"; + break; + } + break; + + case 0x463: + device_str = "STM32F4[1|2]3"; + + switch (rev_id) { + case 0x1000: + rev_str = "A"; + break; + } + break; + default: snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n"); return ERROR_FAIL; @@ -1164,8 +1269,8 @@ COMMAND_HANDLER(stm32x_handle_lock_command) target = bank->target; if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; + LOG_INFO("Target not halted"); + /* return ERROR_TARGET_NOT_HALTED; */ } if (stm32x_read_options(bank) != ERROR_OK) { @@ -1203,8 +1308,8 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) target = bank->target; if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; + LOG_INFO("Target not halted"); + /* return ERROR_TARGET_NOT_HALTED; */ } if (stm32x_read_options(bank) != ERROR_OK) { @@ -1215,6 +1320,9 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) /* clear readout protection and complementary option bytes * this will also force a device unlock if set */ stm32x_info->option_bytes.RDP = 0xAA; + if (stm32x_info->has_optcr2_pcrop) { + stm32x_info->option_bytes.optcr2_pcrop = OPTCR2_PCROP_RDP | (~1 << bank->num_sectors); + } if (stm32x_write_options(bank) != ERROR_OK) { command_print(CMD_CTX, "%s failed to unlock device", bank->driver->name); @@ -1327,8 +1435,12 @@ COMMAND_HANDLER(stm32f2x_handle_options_read_command) " boot_add0 0x%04X, boot_add1 0x%04X", stm32x_info->option_bytes.user_options, boot_addr & 0xffff, (boot_addr & 0xffff0000) >> 16); + if (stm32x_info->has_optcr2_pcrop) { + command_print(CMD_CTX, "stm32f2x optcr2_pcrop 0x%08X", + stm32x_info->option_bytes.optcr2_pcrop); + } } else { - command_print(CMD_CTX, "stm32f2x user_options 0x%03X,", + command_print(CMD_CTX, "stm32f2x user_options 0x%03X", stm32x_info->option_bytes.user_options); } } else { @@ -1345,7 +1457,7 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) int retval; struct flash_bank *bank; struct stm32x_flash_bank *stm32x_info = NULL; - uint16_t user_options, boot_addr0, boot_addr1; + uint16_t user_options, boot_addr0, boot_addr1, options_mask; if (CMD_ARGC < 1) { command_print(CMD_CTX, "stm32f2x options_write ..."); @@ -1378,9 +1490,11 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) } COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options); - if (user_options & (stm32x_info->has_extra_options ? ~0xffc : ~0xfc)) { + options_mask = !stm32x_info->has_extra_options ? ~0xfc : + ~(((0xf00 << (stm32x_info->protection_bits - 12)) | 0xff) & 0xffc); + if (user_options & options_mask) { command_print(CMD_CTX, "stm32f2x invalid user_options"); - return ERROR_COMMAND_SYNTAX_ERROR; + return ERROR_COMMAND_ARGUMENT_INVALID; } stm32x_info->option_bytes.user_options = user_options; @@ -1400,6 +1514,48 @@ COMMAND_HANDLER(stm32f2x_handle_options_write_command) return retval; } +COMMAND_HANDLER(stm32f2x_handle_optcr2_write_command) +{ + int retval; + struct flash_bank *bank; + struct stm32x_flash_bank *stm32x_info = NULL; + uint32_t optcr2_pcrop; + + if (CMD_ARGC != 2) { + command_print(CMD_CTX, "stm32f2x optcr2_write "); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + stm32x_info = bank->driver_priv; + if (!stm32x_info->has_optcr2_pcrop) { + command_print(CMD_CTX, "no optcr2 register"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + command_print(CMD_CTX, "INFO: To disable PCROP, set PCROP_RDP" + " with PCROPi bits STILL SET, then\nlock device and" + " finally unlock it. Clears PCROP and mass erases flash."); + + retval = stm32x_read_options(bank); + if (ERROR_OK != retval) + return retval; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], optcr2_pcrop); + stm32x_info->option_bytes.optcr2_pcrop = optcr2_pcrop; + + if (stm32x_write_options(bank) != ERROR_OK) { + command_print(CMD_CTX, "stm32f2x failed to write options"); + return ERROR_OK; + } + + command_print(CMD_CTX, "stm32f2x optcr2_write complete."); + return retval; +} + static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", @@ -1433,9 +1589,17 @@ static const struct command_registration stm32x_exec_command_handlers[] = { .name = "options_write", .handler = stm32f2x_handle_options_write_command, .mode = COMMAND_EXEC, - .usage = "bank_id user_options [ boot_add0 boot_add1]", + .usage = "bank_id user_options [ boot_add0 boot_add1 ]", .help = "Write option bytes", }, + { + .name = "optcr2_write", + .handler = stm32f2x_handle_optcr2_write_command, + .mode = COMMAND_EXEC, + .usage = "bank_id optcr2", + .help = "Write optcr2 word", + }, + COMMAND_REGISTRATION_DONE }; From 0d74c8689d96d1f04344b5bebc84ac9069c5ee70 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 14 Aug 2017 15:02:19 -0700 Subject: [PATCH 27/68] Fix block memory reads on slow targets. The interesting new code concerns ignore_prev_addr and this_is_last_read. Additionally, I tweaked some debug output, and optimized riscv_batch_run() when the batch is empty. --- src/target/riscv/batch.c | 5 +++++ src/target/riscv/riscv-013.c | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index cb5a10856..d6e8b7941 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -44,6 +44,11 @@ bool riscv_batch_full(struct riscv_batch *batch) void riscv_batch_run(struct riscv_batch *batch) { + if (batch->used_scans == 0) { + LOG_DEBUG("Ignoring empty batch."); + return; + } + LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans); riscv_batch_add_nop(batch); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 284f6a1ba..5fc3175ca 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1353,7 +1353,7 @@ static int read_memory(struct target *target, target_addr_t address, riscv_addr_t cur_addr = 0xbadbeef; riscv_addr_t fin_addr = address + (count * size); riscv_addr_t prev_addr = ((riscv_addr_t) address) - size; - bool first = true; + bool ignore_prev_addr = true; bool this_is_last_read = false; LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr); while (count > 1 && !this_is_last_read) { @@ -1361,9 +1361,9 @@ static int read_memory(struct target *target, target_addr_t address, LOG_DEBUG("transferring burst starting at address 0x%" TARGET_PRIxADDR " (previous burst was 0x%" TARGET_PRIxADDR ")", cur_addr, prev_addr); - assert(first || prev_addr < cur_addr); - first = false; + assert(ignore_prev_addr || prev_addr < cur_addr); prev_addr = cur_addr; + ignore_prev_addr = false; riscv_addr_t start = (cur_addr - address) / size; assert (cur_addr >= address); struct riscv_batch *batch = riscv_batch_alloc( @@ -1409,10 +1409,11 @@ static int read_memory(struct target *target, target_addr_t address, info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); switch (info->cmderr) { case CMDERR_NONE: - LOG_DEBUG("successful (partial?) memory write"); + LOG_DEBUG("successful (partial?) memory read"); break; case CMDERR_BUSY: - LOG_DEBUG("memory write resulted in busy response"); + LOG_DEBUG("memory read resulted in busy response; " + "this_is_last_read=%d", this_is_last_read); riscv013_clear_abstract_error(target); increase_ac_busy_delay(target); retry_batch_transaction = true; @@ -1427,7 +1428,11 @@ static int read_memory(struct target *target, target_addr_t address, riscv_batch_free(batch); return ERROR_FAIL; } - if (retry_batch_transaction) continue; + if (retry_batch_transaction) { + this_is_last_read = false; + ignore_prev_addr = true; + continue; + } for (size_t i = start; i < start + reads; ++i) { riscv_addr_t offset = size*i; @@ -1437,8 +1442,11 @@ static int read_memory(struct target *target, target_addr_t address, if (this_is_last_read && i == start + reads - 1) { riscv013_set_autoexec(target, d_data, 0); - // access debug buffer without executing a program - this address logic was taken from program.c - int const off = (r_data - riscv_debug_buffer_addr(program.target)) / sizeof(program.debug_buffer[0]); + // Access debug buffer without executing a program. This + // address logic was taken from program.c. + int const off = (r_data - + riscv_debug_buffer_addr(program.target)) / + sizeof(program.debug_buffer[0]); value = riscv_read_debug_buffer(target, off); } else { uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads); From 5092f961052d5f398834689f08c04280a496644a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 15 Aug 2017 13:31:06 -0700 Subject: [PATCH 28/68] Add some keep_alive()s for use with slow targets. --- src/target/riscv/batch.c | 2 ++ src/target/riscv/program.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index cb5a10856..155573da6 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -44,6 +44,8 @@ bool riscv_batch_full(struct riscv_batch *batch) void riscv_batch_run(struct riscv_batch *batch) { + keep_alive(); + LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans); riscv_batch_add_nop(batch); diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index 04edf6a09..efad623e4 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -41,6 +41,8 @@ int riscv_program_init(struct riscv_program *p, struct target *target) int riscv_program_exec(struct riscv_program *p, struct target *t) { + keep_alive(); + if (riscv_debug_buffer_leave(t, p) != ERROR_OK) { LOG_ERROR("unable to write program buffer exit code"); return ERROR_FAIL; From 0ff4103a2659de06b76bcc6d96fe82afa5fd44cd Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 15 Aug 2017 15:47:35 -0700 Subject: [PATCH 29/68] Reset address if target was busy during bust write Improve Issue #98. DebugCompareSections is still failing for me (with an instrumented sometimes-slow spike), but MemTestBlock now passes reliably. --- src/target/riscv/riscv-013.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 5fc3175ca..d4cb51ced 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1358,13 +1358,13 @@ static int read_memory(struct target *target, target_addr_t address, LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr); while (count > 1 && !this_is_last_read) { cur_addr = riscv_read_debug_buffer_x(target, d_addr); - LOG_DEBUG("transferring burst starting at address 0x%" TARGET_PRIxADDR - " (previous burst was 0x%" TARGET_PRIxADDR ")", cur_addr, - prev_addr); + riscv_addr_t start = (cur_addr - address) / size; + LOG_DEBUG("reading burst at address 0x%" TARGET_PRIxADDR + "; prev_addr=0x%" TARGET_PRIxADDR "; start=0x%" + TARGET_PRIxADDR, cur_addr, prev_addr, start); assert(ignore_prev_addr || prev_addr < cur_addr); prev_addr = cur_addr; ignore_prev_addr = false; - riscv_addr_t start = (cur_addr - address) / size; assert (cur_addr >= address); struct riscv_batch *batch = riscv_batch_alloc( target, @@ -1431,6 +1431,18 @@ static int read_memory(struct target *target, target_addr_t address, if (retry_batch_transaction) { this_is_last_read = false; ignore_prev_addr = true; + + switch (riscv_xlen(target)) { + case 64: + riscv013_write_debug_buffer(target, d_addr + 4, (cur_addr - size) >> 32); + case 32: + riscv013_write_debug_buffer(target, d_addr, (cur_addr - size)); + break; + default: + LOG_ERROR("unknown XLEN %d", riscv_xlen(target)); + return ERROR_FAIL; + } + continue; } From b42bc76e2ebe1525895440ffccffa59b5921cda2 Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Fri, 25 Aug 2017 14:53:45 +0300 Subject: [PATCH 30/68] server.c: fix clang warning /Users/ilg/Work/openocd/openocd.git/src/server/server.c:305:22: error: incompatible pointer types passing 'struct sockaddr_in *' to parameter of type 'struct sockaddr *' [-Werror,-Wincompatible-pointer-types] getsockname(c->fd, &addr_in, &addr_in_size); ^~~~~~~~ /usr/include/sys/socket.h:687:50: note: passing argument to parameter here int getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict) --- src/server/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/server.c b/src/server/server.c index 99bdc35ec..f3ae34ebe 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -302,7 +302,7 @@ int add_service(char *name, struct sockaddr_in addr_in; socklen_t addr_in_size = sizeof(addr_in); - getsockname(c->fd, &addr_in, &addr_in_size); + getsockname(c->fd, (struct sockaddr *)&addr_in, &addr_in_size); LOG_INFO("Listening on port %d for %s connections", ntohs(addr_in.sin_port), name); } else if (c->type == CONNECTION_STDINOUT) { From a9bcc48064010931ca316222e53aaddb82824d26 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 24 Aug 2017 14:24:40 -0700 Subject: [PATCH 31/68] Remove unnecessary newlines. --- src/target/riscv/riscv-013.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index f5fe37824..5cdf8b192 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -471,7 +471,7 @@ static uint64_t dmi_read(struct target *target, uint16_t address) } else if (status == DMI_STATUS_SUCCESS) { break; } else { - LOG_ERROR("failed read (NOP) at 0x%x, status=%d\n", address, status); + LOG_ERROR("failed read (NOP) at 0x%x, status=%d", address, status); break; } } @@ -500,13 +500,13 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value) } else if (status == DMI_STATUS_SUCCESS) { break; } else { - LOG_ERROR("failed write to 0x%x, status=%d\n", address, status); + LOG_ERROR("failed write to 0x%x, status=%d", address, status); break; } } if (status != DMI_STATUS_SUCCESS) { - LOG_ERROR("Failed write to 0x%x;, status=%d\n", + LOG_ERROR("Failed write to 0x%x;, status=%d", address, status); abort(); } @@ -521,12 +521,12 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value) } else if (status == DMI_STATUS_SUCCESS) { break; } else { - LOG_ERROR("failed write (NOP) at 0x%x, status=%d\n", address, status); + LOG_ERROR("failed write (NOP) at 0x%x, status=%d", address, status); break; } } if (status != DMI_STATUS_SUCCESS) { - LOG_ERROR("failed to write (NOP) 0x%" PRIx64 " to 0x%x; status=%d\n", value, address, status); + LOG_ERROR("failed to write (NOP) 0x%" PRIx64 " to 0x%x; status=%d", value, address, status); abort(); } } @@ -1146,7 +1146,7 @@ static int examine(struct target *target) r->xlen[i], r->debug_buffer_addr[i]); if (riscv_program_gah(&program64, r->debug_buffer_addr[i])) { - LOG_ERROR("This implementation will not work with hart %d with debug_buffer_addr of 0x%lx\n", i, + LOG_ERROR("This implementation will not work with hart %d with debug_buffer_addr of 0x%lx", i, (long)r->debug_buffer_addr[i]); abort(); } From 92ef3281613e6a33755ed6286802a677010d17ce Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 25 Aug 2017 12:00:06 -0700 Subject: [PATCH 32/68] Don't reset DMI when an abstract command is busy. --- src/target/riscv/riscv-013.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 5cdf8b192..093ae5625 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -364,17 +364,6 @@ static void increase_dmi_busy_delay(struct target *target) dtmcontrol_scan(target, DTM_DTMCS_DMIRESET); } -static void increase_ac_busy_delay(struct target *target) -{ - riscv013_info_t *info = get_info(target); - info->ac_busy_delay += info->ac_busy_delay / 10 + 1; - LOG_INFO("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", - info->dtmcontrol_idle, info->dmi_busy_delay, - info->ac_busy_delay); - - dtmcontrol_scan(target, DTM_DTMCS_DMIRESET); -} - /** * exec: If this is set, assume the scan results in an execution, so more * run-test/idle cycles may be required. @@ -531,6 +520,23 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value) } } +static void increase_ac_busy_delay(struct target *target) +{ + riscv013_info_t *info = get_info(target); + info->ac_busy_delay += info->ac_busy_delay / 10 + 1; + LOG_INFO("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", + info->dtmcontrol_idle, info->dmi_busy_delay, + info->ac_busy_delay); + + // Wait for busy to go away. + uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); + while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) { + abstractcs = dmi_read(target, DMI_ABSTRACTCS); + } + // Clear the error status. + dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); +} + uint32_t abstract_register_size(unsigned width) { switch (width) { @@ -1412,8 +1418,8 @@ static int read_memory(struct target *target, target_addr_t address, case CMDERR_BUSY: LOG_DEBUG("memory read resulted in busy response; " "this_is_last_read=%d", this_is_last_read); - riscv013_clear_abstract_error(target); increase_ac_busy_delay(target); + riscv013_clear_abstract_error(target); retry_batch_transaction = true; riscv_batch_free(batch); break; From 8bcec87cc1f0bb4b45d05977d2a1c69822806e0f Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 26 Aug 2017 16:53:00 -0700 Subject: [PATCH 33/68] Remove unnecessary \n --- src/target/riscv/riscv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 69aea1564..62628a179 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -629,7 +629,7 @@ static int riscv_examine(struct target *target) { LOG_DEBUG("riscv_examine()"); if (target_was_examined(target)) { - LOG_DEBUG("Target was already examined.\n"); + LOG_DEBUG("Target was already examined."); return ERROR_OK; } From 5bdee8bc669e5fdeb1c978726025a5c0ce2f188c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 26 Aug 2017 17:49:13 -0700 Subject: [PATCH 34/68] Fix off-by-3 error on 64-bit targets. This caused everything to fall apart when debugging slow 64-bit targets. --- src/target/riscv/riscv-013.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 093ae5625..6ea56ab83 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1438,7 +1438,7 @@ static int read_memory(struct target *target, target_addr_t address, switch (riscv_xlen(target)) { case 64: - riscv013_write_debug_buffer(target, d_addr + 4, (cur_addr - size) >> 32); + riscv013_write_debug_buffer(target, d_addr + 1, (cur_addr - size) >> 32); case 32: riscv013_write_debug_buffer(target, d_addr, (cur_addr - size)); break; From eef9442aa7f6e27efa64f4cde3f93c37a9c3178a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 26 Aug 2017 17:50:05 -0700 Subject: [PATCH 35/68] Remove redundant code. --- src/target/riscv/riscv-013.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6ea56ab83..e1f807d38 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -527,14 +527,6 @@ static void increase_ac_busy_delay(struct target *target) LOG_INFO("dtmcontrol_idle=%d, dmi_busy_delay=%d, ac_busy_delay=%d", info->dtmcontrol_idle, info->dmi_busy_delay, info->ac_busy_delay); - - // Wait for busy to go away. - uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); - while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) { - abstractcs = dmi_read(target, DMI_ABSTRACTCS); - } - // Clear the error status. - dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); } uint32_t abstract_register_size(unsigned width) @@ -2087,6 +2079,11 @@ int riscv013_debug_buffer_register(struct target *target, riscv_addr_t addr) void riscv013_clear_abstract_error(struct target *target) { - uint32_t acs = dmi_read(target, DMI_ABSTRACTCS); - dmi_write(target, DMI_ABSTRACTCS, acs); + // Wait for busy to go away. + uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); + while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) { + abstractcs = dmi_read(target, DMI_ABSTRACTCS); + } + // Clear the error status. + dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); } From 5f53655e658ee7ffce0ae24e692762321b233c04 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 26 Aug 2017 18:25:10 -0700 Subject: [PATCH 36/68] Fix off-by-one error. --- src/target/riscv/riscv-013.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index e1f807d38..e7efb9c79 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1430,9 +1430,9 @@ static int read_memory(struct target *target, target_addr_t address, switch (riscv_xlen(target)) { case 64: - riscv013_write_debug_buffer(target, d_addr + 1, (cur_addr - size) >> 32); + riscv013_write_debug_buffer(target, d_addr + 1, cur_addr >> 32); case 32: - riscv013_write_debug_buffer(target, d_addr, (cur_addr - size)); + riscv013_write_debug_buffer(target, d_addr, cur_addr); break; default: LOG_ERROR("unknown XLEN %d", riscv_xlen(target)); From 2efc415db47789e3d10c8be3d57855d190e36403 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sun, 27 Aug 2017 13:25:54 -0700 Subject: [PATCH 37/68] Finally nailed memory read on slow targets The downloaded program now post-increments, and there's no longer an attempt to read the current address from the target. This made it easier to fix the problem where at the start of the loop the current address was already read (in regular entry) or has not yet been read (when the first round through the loop encountered busy more than once, or busy was encountered at least once later on). --- src/target/riscv/riscv-013.c | 57 +++++++++++++----------------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index e7efb9c79..bd48fe9b0 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1273,7 +1273,6 @@ static int read_memory(struct target *target, target_addr_t address, riscv_addr_t r_addr = riscv_program_alloc_x(&program); riscv_program_fence(&program); riscv_program_lx(&program, GDB_REGNO_S0, r_addr); - riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); switch (size) { case 1: riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); @@ -1288,6 +1287,7 @@ static int read_memory(struct target *target, target_addr_t address, LOG_ERROR("Unsupported size: %d", size); return ERROR_FAIL; } + riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); riscv_program_sw(&program, GDB_REGNO_S1, r_data); riscv_program_sx(&program, GDB_REGNO_S0, r_addr); @@ -1295,9 +1295,9 @@ static int read_memory(struct target *target, target_addr_t address, * program execution mechanism. */ switch (riscv_xlen(target)) { case 64: - riscv_program_write_ram(&program, r_addr + 4, (((riscv_addr_t) address) - size) >> 32); + riscv_program_write_ram(&program, r_addr + 4, ((riscv_addr_t) address) >> 32); case 32: - riscv_program_write_ram(&program, r_addr, ((riscv_addr_t) address) - size); + riscv_program_write_ram(&program, r_addr, (riscv_addr_t) address); break; default: LOG_ERROR("unknown XLEN %d", riscv_xlen(target)); @@ -1314,27 +1314,6 @@ static int read_memory(struct target *target, target_addr_t address, return ERROR_FAIL; } - uint32_t value = riscv_program_read_ram(&program, r_data); - LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%08x", address, value); - switch (size) { - case 1: - buffer[0] = value; - break; - case 2: - buffer[0] = value; - buffer[1] = value >> 8; - break; - case 4: - buffer[0] = value; - buffer[1] = value >> 8; - buffer[2] = value >> 16; - buffer[3] = value >> 24; - break; - default: - LOG_ERROR("unsupported access size: %d", size); - return ERROR_FAIL; - } - /* The rest of this program is designed to be fast so it reads various * DMI registers directly. */ int d_data = (r_data - riscv_debug_buffer_addr(target)) / 4; @@ -1346,22 +1325,16 @@ static int read_memory(struct target *target, target_addr_t address, * case we need to back off a bit and try again. There's two * termination conditions to this loop: a non-BUSY error message, or * the data was all copied. */ - riscv_addr_t cur_addr = 0xbadbeef; + riscv_addr_t cur_addr = address; riscv_addr_t fin_addr = address + (count * size); - riscv_addr_t prev_addr = ((riscv_addr_t) address) - size; - bool ignore_prev_addr = true; bool this_is_last_read = false; LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr); - while (count > 1 && !this_is_last_read) { - cur_addr = riscv_read_debug_buffer_x(target, d_addr); + while (!this_is_last_read) { riscv_addr_t start = (cur_addr - address) / size; LOG_DEBUG("reading burst at address 0x%" TARGET_PRIxADDR - "; prev_addr=0x%" TARGET_PRIxADDR "; start=0x%" - TARGET_PRIxADDR, cur_addr, prev_addr, start); - assert(ignore_prev_addr || prev_addr < cur_addr); - prev_addr = cur_addr; - ignore_prev_addr = false; - assert (cur_addr >= address); + "; start=0x%" + TARGET_PRIxADDR, cur_addr, start); + assert(cur_addr >= address && cur_addr < fin_addr); struct riscv_batch *batch = riscv_batch_alloc( target, 32, @@ -1426,7 +1399,6 @@ static int read_memory(struct target *target, target_addr_t address, } if (retry_batch_transaction) { this_is_last_read = false; - ignore_prev_addr = true; switch (riscv_xlen(target)) { case 64: @@ -1439,6 +1411,16 @@ static int read_memory(struct target *target, target_addr_t address, return ERROR_FAIL; } + if (riscv013_execute_debug_buffer(target) != ERROR_OK) { + uint32_t acs = dmi_read(target, DMI_ABSTRACTCS); + LOG_ERROR("failed to execute program, abstractcs=0x%08x", acs); + riscv013_clear_abstract_error(target); + riscv_set_register(target, GDB_REGNO_S0, s0); + riscv_set_register(target, GDB_REGNO_S1, s1); + LOG_ERROR(" exiting with ERROR_FAIL"); + return ERROR_FAIL; + } + continue; } @@ -1446,6 +1428,7 @@ static int read_memory(struct target *target, target_addr_t address, riscv_addr_t offset = size*i; riscv_addr_t t_addr = address + offset; uint8_t *t_buffer = buffer + offset; + uint32_t value; if (this_is_last_read && i == start + reads - 1) { riscv013_set_autoexec(target, d_data, 0); @@ -1485,6 +1468,8 @@ static int read_memory(struct target *target, target_addr_t address, LOG_DEBUG("M[0x%08lx] reads 0x%08x", (long)t_addr, value); } riscv_batch_free(batch); + + cur_addr += reads * size; } riscv013_set_autoexec(target, d_data, 0); From 6721988ce373d0160dd4994e33d6c50584eac66b Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 29 Aug 2017 17:25:04 -0700 Subject: [PATCH 38/68] Ensure read_memory() only reads each address once. Previously it might read an address multiple times if an abstract command took longer to execute than expected. The new implementations reads from the target how far it has gotten along reading memory, and resumes from there if cmderr=busy. This ended up being a bigger change than I envisioned, but in the end it deleted more lines than it added, so I'm happy. :-) --- src/target/riscv/riscv-013.c | 168 +++++++++++++++-------------------- 1 file changed, 72 insertions(+), 96 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index bd48fe9b0..dbf2ce3db 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1248,6 +1248,31 @@ static int deassert_reset(struct target *target) return ERROR_OK; } +static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size) +{ + switch (size) { + case 8: + buffer[7] = value >> 56; + buffer[6] = value >> 48; + buffer[5] = value >> 40; + buffer[4] = value >> 32; + case 4: + buffer[3] = value >> 24; + buffer[2] = value >> 16; + case 2: + buffer[1] = value >> 8; + case 1: + buffer[0] = value; + break; + default: + assert(false); + } +} + +/** + * Read the requested memory, taking care to execute every read exactly once, + * even if cmderr=busy is encountered. + */ static int read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -1314,6 +1339,9 @@ static int read_memory(struct target *target, target_addr_t address, return ERROR_FAIL; } + // Program has been executed once. d_addr contains address+size, and d_data + // contains *address. + /* The rest of this program is designed to be fast so it reads various * DMI registers directly. */ int d_data = (r_data - riscv_debug_buffer_addr(target)) / 4; @@ -1325,15 +1353,17 @@ static int read_memory(struct target *target, target_addr_t address, * case we need to back off a bit and try again. There's two * termination conditions to this loop: a non-BUSY error message, or * the data was all copied. */ - riscv_addr_t cur_addr = address; + riscv_addr_t cur_addr = riscv_read_debug_buffer_x(target, d_addr); riscv_addr_t fin_addr = address + (count * size); - bool this_is_last_read = false; LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr); - while (!this_is_last_read) { - riscv_addr_t start = (cur_addr - address) / size; - LOG_DEBUG("reading burst at address 0x%" TARGET_PRIxADDR - "; start=0x%" - TARGET_PRIxADDR, cur_addr, start); + while (cur_addr < fin_addr) { + // Invariant: + // d_data contains *addr + // d_addr contains addr + size + + unsigned start = (cur_addr - address) / size; + LOG_DEBUG("creating burst to read address 0x%" TARGET_PRIxADDR + " up to 0x%" TARGET_PRIxADDR "; start=0x%d", cur_addr, fin_addr, start); assert(cur_addr >= address && cur_addr < fin_addr); struct riscv_batch *batch = riscv_batch_alloc( target, @@ -1341,23 +1371,12 @@ static int read_memory(struct target *target, target_addr_t address, info->dmi_busy_delay + info->ac_busy_delay); size_t reads = 0; - size_t rereads = reads; - for (riscv_addr_t i = start; i < count; ++i) { - if (i == count - 1) { - // don't do actual read in this batch, - // we will do it later after we disable autoexec - // - // this is done to avoid reading more memory than requested - // which in some special cases(like reading stack located - // at the very top of RAM) may cause an exception - this_is_last_read = true; - } else { - size_t const index = - riscv_batch_add_dmi_read( + for (riscv_addr_t addr = cur_addr; addr < fin_addr; addr += size) { + size_t const index = + riscv_batch_add_dmi_read( batch, riscv013_debug_buffer_register(target, r_data)); - assert(index == reads); - } + assert(index == reads); reads++; if (riscv_batch_full(batch)) @@ -1366,27 +1385,21 @@ static int read_memory(struct target *target, target_addr_t address, riscv_batch_run(batch); - // Note that if the scan resulted in a Busy DMI response, it - // is this read to abstractcs that will cause the dmi_busy_delay - // to be incremented if necessary. The loop condition above - // catches the case where no writes went through at all. - - bool retry_batch_transaction = false; + // Wait for the target to finish performing the last abstract command, + // and update our copy of cmderr. uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) abstractcs = dmi_read(target, DMI_ABSTRACTCS); info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR); + switch (info->cmderr) { case CMDERR_NONE: LOG_DEBUG("successful (partial?) memory read"); break; case CMDERR_BUSY: - LOG_DEBUG("memory read resulted in busy response; " - "this_is_last_read=%d", this_is_last_read); + LOG_DEBUG("memory read resulted in busy response"); increase_ac_busy_delay(target); riscv013_clear_abstract_error(target); - retry_batch_transaction = true; - riscv_batch_free(batch); break; default: LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); @@ -1397,82 +1410,45 @@ static int read_memory(struct target *target, target_addr_t address, riscv_batch_free(batch); return ERROR_FAIL; } - if (retry_batch_transaction) { - this_is_last_read = false; - switch (riscv_xlen(target)) { - case 64: - riscv013_write_debug_buffer(target, d_addr + 1, cur_addr >> 32); - case 32: - riscv013_write_debug_buffer(target, d_addr, cur_addr); - break; - default: - LOG_ERROR("unknown XLEN %d", riscv_xlen(target)); - return ERROR_FAIL; - } + // Figure out how far we managed to read. + riscv_addr_t next_addr = riscv_read_debug_buffer_x(target, d_addr); + LOG_DEBUG("Batch read [0x%" TARGET_PRIxADDR ", 0x%" TARGET_PRIxADDR + "); reads=%d", cur_addr, next_addr, (unsigned) reads); + assert(next_addr >= address && next_addr <= fin_addr); + assert(info->cmderr != CMDERR_NONE || + next_addr == cur_addr + reads * size); - if (riscv013_execute_debug_buffer(target) != ERROR_OK) { - uint32_t acs = dmi_read(target, DMI_ABSTRACTCS); - LOG_ERROR("failed to execute program, abstractcs=0x%08x", acs); - riscv013_clear_abstract_error(target); - riscv_set_register(target, GDB_REGNO_S0, s0); - riscv_set_register(target, GDB_REGNO_S1, s1); - LOG_ERROR(" exiting with ERROR_FAIL"); - return ERROR_FAIL; - } + // Now read whatever we got out of the batch. + unsigned rereads = 0; + for (riscv_addr_t addr = cur_addr - size; addr < next_addr - size; + addr += size) { + riscv_addr_t offset = addr - address; - continue; - } + uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads); + uint32_t value = get_field(dmi_out, DTM_DMI_DATA); + write_to_buf(buffer + offset, value, size); - for (size_t i = start; i < start + reads; ++i) { - riscv_addr_t offset = size*i; - riscv_addr_t t_addr = address + offset; - uint8_t *t_buffer = buffer + offset; - uint32_t value; - - if (this_is_last_read && i == start + reads - 1) { - riscv013_set_autoexec(target, d_data, 0); - - // Access debug buffer without executing a program. This - // address logic was taken from program.c. - int const off = (r_data - - riscv_debug_buffer_addr(program.target)) / - sizeof(program.debug_buffer[0]); - value = riscv_read_debug_buffer(target, off); - } else { - uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads); - value = get_field(dmi_out, DTM_DMI_DATA); - } - rereads++; - switch (size) { - case 1: - t_buffer[0] = value; - break; - case 2: - t_buffer[0] = value; - t_buffer[1] = value >> 8; - break; - case 4: - t_buffer[0] = value; - t_buffer[1] = value >> 8; - t_buffer[2] = value >> 16; - t_buffer[3] = value >> 24; - break; - default: - LOG_ERROR("unsupported access size: %d", size); - return ERROR_FAIL; - } - - LOG_DEBUG("M[0x%08lx] reads 0x%08x", (long)t_addr, value); + LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%08x", addr, value); } riscv_batch_free(batch); - cur_addr += reads * size; + cur_addr = next_addr; } riscv013_set_autoexec(target, d_data, 0); + + // Read the last word. + + // Access debug buffer without executing a program. This + // address logic was taken from program.c. + uint32_t value = riscv013_read_debug_buffer(target, d_data); + riscv_addr_t addr = cur_addr - size; + write_to_buf(buffer + addr - address, value, size); + LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%08x", addr, value); + riscv_set_register(target, GDB_REGNO_S0, s0); riscv_set_register(target, GDB_REGNO_S1, s1); return ERROR_OK; From ce740d02d6fdfcb1f403d41238d5322ab710c10c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 1 Sep 2017 11:29:15 -0700 Subject: [PATCH 39/68] Properly show XLEN for each thread. --- src/rtos/riscv_debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c index d6458e9da..3abdf74f0 100644 --- a/src/rtos/riscv_debug.c +++ b/src/rtos/riscv_debug.c @@ -30,7 +30,6 @@ static int riscv_create_rtos(struct target *target) target->rtos->current_threadid = 1; target->rtos->current_thread = 1; - riscv_update_threads(target->rtos); target->rtos->gdb_thread_packet = riscv_gdb_thread_packet; target->rtos->gdb_v_packet = riscv_gdb_v_packet; @@ -42,6 +41,8 @@ int riscv_update_threads(struct rtos *rtos) { LOG_DEBUG("Updating the RISC-V Hart List"); + struct target *target = rtos->target; + /* Figures out how many harts there are on the system. */ int hart_count = riscv_count_harts(rtos->target); if (rtos->thread_count != hart_count) { @@ -54,7 +55,8 @@ int riscv_update_threads(struct rtos *rtos) rtos->thread_details[i].exists = true; if (asprintf(&rtos->thread_details[i].thread_name_str, "Hart %d", i) < 0) LOG_ERROR("riscv_update_threads() failed asprintf"); - if (asprintf(&rtos->thread_details[i].extra_info_str, "RV64") < 0) + if (asprintf(&rtos->thread_details[i].extra_info_str, "RV%d", + riscv_xlen_of_hart(target, i)) < 0) LOG_ERROR("riscv_update_threads() failed asprintf"); } } From a6ec1a0e684ef0d6d3f12d7e2107af6ada15ac42 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 11 Sep 2017 11:35:47 -0700 Subject: [PATCH 40/68] Add timeout to another infinite loop. --- src/target/riscv/riscv-013.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index dbf2ce3db..3068fe0cd 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -574,7 +574,7 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs) errors[info->cmderr], *abstractcs); } - LOG_ERROR("Timed out after %ds waiting for busy to go low. (abstractcs=0x%x)" + LOG_ERROR("Timed out after %ds waiting for busy to go low (abstractcs=0x%x). " "Increase the timeout with riscv set_command_timeout_sec.", riscv_command_timeout_sec, *abstractcs); @@ -1897,7 +1897,7 @@ void riscv013_reset_current_hart(struct target *target) } if (time(NULL) - start > riscv_reset_timeout_sec) { LOG_ERROR("Hart didn't halt coming out of reset in %ds; " - "dmstatus=0x%x" + "dmstatus=0x%x; " "Increase the timeout with riscv set_reset_timeout_sec.", riscv_reset_timeout_sec, dmstatus); return; @@ -2041,9 +2041,17 @@ int riscv013_debug_buffer_register(struct target *target, riscv_addr_t addr) void riscv013_clear_abstract_error(struct target *target) { // Wait for busy to go away. + time_t start = time(NULL); uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) { abstractcs = dmi_read(target, DMI_ABSTRACTCS); + + if (time(NULL) - start > riscv_command_timeout_sec) { + LOG_ERROR("abstractcs.busy is not going low after %d seconds. " + "The target is either really slow, or broken. " + "abstractcs=0x%x", riscv_command_timeout_sec, abstractcs); + break; + } } // Clear the error status. dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); From f9b2549e202c045284d5b9e894e1e2163f6207b0 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 11 Sep 2017 12:11:24 -0700 Subject: [PATCH 41/68] Tell user how to increase timeout. --- src/target/riscv/riscv-013.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 3068fe0cd..4ed87bc5e 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2047,9 +2047,11 @@ void riscv013_clear_abstract_error(struct target *target) abstractcs = dmi_read(target, DMI_ABSTRACTCS); if (time(NULL) - start > riscv_command_timeout_sec) { - LOG_ERROR("abstractcs.busy is not going low after %d seconds. " - "The target is either really slow, or broken. " - "abstractcs=0x%x", riscv_command_timeout_sec, abstractcs); + LOG_ERROR("abstractcs.busy is not going low after %d seconds " + "(abstractcs=0x%x). The target is either really slow or " + "broken. You could increase the timeout with riscv " + "set_reset_timeout_sec.", + riscv_command_timeout_sec, abstractcs); break; } } From ce20be3d783882399047db1738e79b0a9ecdb1e8 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 14 Sep 2017 16:21:49 -0700 Subject: [PATCH 42/68] Add support for F extension. --- src/target/riscv/program.c | 31 +++++++++++++++++++++++++++---- src/target/riscv/program.h | 4 ++-- src/target/riscv/riscv-013.c | 4 ++-- src/target/riscv/riscv.c | 2 ++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index efad623e4..294e673ea 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -3,6 +3,7 @@ #endif #include "target/target.h" +#include "target/register.h" #include "riscv.h" #include "program.h" #include "helper/log.h" @@ -369,7 +370,7 @@ int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno return riscv_program_insert(p, addi(d, s, u)); } -int riscv_program_fsd(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) +int riscv_program_fsx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) { assert(d >= GDB_REGNO_FPR0); assert(d <= GDB_REGNO_FPR31); @@ -378,21 +379,43 @@ int riscv_program_fsd(struct riscv_program *p, enum gdb_regno d, riscv_addr_t ad : riscv_program_gettemp(p); if (riscv_program_lah(p, t, addr) != ERROR_OK) return ERROR_FAIL; - if (riscv_program_insert(p, fsd(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr))) != ERROR_OK) + uint32_t instruction; + switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) { + case 64: + instruction = fsd(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr)); + break; + case 32: + instruction = fsw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr)); + break; + default: + return ERROR_FAIL; + } + if (riscv_program_insert(p, instruction) != ERROR_OK) return ERROR_FAIL; riscv_program_puttemp(p, t); p->writes_memory = true; return ERROR_OK; } -int riscv_program_fld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) +int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) { assert(d >= GDB_REGNO_FPR0); assert(d <= GDB_REGNO_FPR31); enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d; if (riscv_program_lah(p, t, addr) != ERROR_OK) return ERROR_FAIL; - if (riscv_program_insert(p, fld(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr))) != ERROR_OK) + uint32_t instruction; + switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) { + case 64: + instruction = fld(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr)); + break; + case 32: + instruction = flw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr)); + break; + default: + return ERROR_FAIL; + } + if (riscv_program_insert(p, instruction) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; } diff --git a/src/target/riscv/program.h b/src/target/riscv/program.h index 1efdb125b..ac1127ed9 100644 --- a/src/target/riscv/program.h +++ b/src/target/riscv/program.h @@ -114,8 +114,8 @@ int riscv_program_ebreak(struct riscv_program *p); int riscv_program_lui(struct riscv_program *p, enum gdb_regno d, int32_t u); int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t i); -int riscv_program_fsd(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr); -int riscv_program_fld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr); +int riscv_program_fsx(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr); +int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr); /* Assembler macros. */ int riscv_program_li(struct riscv_program *p, enum gdb_regno d, riscv_reg_t c); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 4ed87bc5e..8809483ff 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -780,7 +780,7 @@ static int register_write_direct(struct target *target, unsigned number, if (number <= GDB_REGNO_XPR31) { riscv_program_lx(&program, number, input); } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - riscv_program_fld(&program, number, input); + riscv_program_flx(&program, number, input); } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { enum gdb_regno temp = riscv_program_gettemp(&program); riscv_program_lx(&program, temp, input); @@ -816,7 +816,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t if (number <= GDB_REGNO_XPR31) { riscv_program_sx(&program, number, output); } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { - riscv_program_fsd(&program, number, output); + riscv_program_fsx(&program, number, output); } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { LOG_DEBUG("reading CSR index=0x%03x", number - GDB_REGNO_CSR0); enum gdb_regno temp = riscv_program_gettemp(&program); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 62628a179..a502da5a6 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1715,6 +1715,8 @@ const char *gdb_regno_name(enum gdb_regno regno) sprintf(buf, "x%d", regno - GDB_REGNO_XPR0); } else if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) { sprintf(buf, "csr%d", regno - GDB_REGNO_CSR0); + } else if (regno >= GDB_REGNO_FPR0 && regno <= GDB_REGNO_FPR31) { + sprintf(buf, "f%d", regno - GDB_REGNO_FPR0); } else { sprintf(buf, "gdb_regno_%d", regno); } From 157a67a98ab17f88fca4e98e0c5fcc09843f825c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 11 Aug 2017 13:36:58 -0700 Subject: [PATCH 43/68] Be more clear in multi-core systems without -rtos Don't print out there's a hart with XLEN of 0. --- src/target/riscv/riscv-013.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 8809483ff..c474b9803 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1175,9 +1175,13 @@ static int examine(struct target *target) LOG_INFO("Examined RISC-V core; found %d harts", riscv_count_harts(target)); for (int i = 0; i < riscv_count_harts(target); ++i) { - LOG_INFO(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64 - ", %d triggers", i, r->xlen[i], r->debug_buffer_addr[i], - r->trigger_count[i]); + if (riscv_hart_enabled(target, i)) { + LOG_INFO(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64 + ", %d triggers", i, r->xlen[i], r->debug_buffer_addr[i], + r->trigger_count[i]); + } else { + LOG_INFO(" hart %d: currently disabled", i); + } } return ERROR_OK; } From 21bd5e7b68f80712d360ac88cf07ca9acef0a992 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 13:37:51 -0700 Subject: [PATCH 44/68] Try OSX build. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 320799516..5218de613 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,8 @@ matrix: packages: - gcc-multilib + - os: osx + script: - ./bootstrap && ./configure && make - file src/openocd From a715500912d3b3a3512873aaaa179fdfbf02d8a7 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 13:47:03 -0700 Subject: [PATCH 45/68] Try clang build. Travis takes a long time to start OSX builds. --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5218de613..6a5d067ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ matrix: - os: linux env: BUILD=x86_64-linux-gnu + - os: linux + compiler: clang + - os: linux env: BUILD=i686-linux-gnu CFLAGS=-m32 addons: From bf737b89855637d7e1bf288f9fa0febd31e9493a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 13:52:49 -0700 Subject: [PATCH 46/68] Remove osx, do 32/64 gcc/clang. --- .travis.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a5d067ae..ab5af76fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ language: c dist: trusty +compiler: + - gcc + - clang matrix: include: - os: linux env: BUILD=x86_64-linux-gnu - - os: linux - compiler: clang - - os: linux env: BUILD=i686-linux-gnu CFLAGS=-m32 addons: @@ -16,8 +16,6 @@ matrix: packages: - gcc-multilib - - os: osx - script: - ./bootstrap && ./configure && make - file src/openocd From 604dfa0dcc1c63f6b0959d5a10d838b5ddac4494 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 14:03:33 -0700 Subject: [PATCH 47/68] Try to fix some clang warnings. --- src/target/riscv/debug_defines.h | 2 +- src/target/riscv/riscv-013.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index c53cec7d5..fa2856020 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -926,7 +926,7 @@ */ #define DMI_COMMAND_CMDTYPE_OFFSET 24 #define DMI_COMMAND_CMDTYPE_LENGTH 8 -#define DMI_COMMAND_CMDTYPE (0xff << DMI_COMMAND_CMDTYPE_OFFSET) +#define DMI_COMMAND_CMDTYPE (0xffu << DMI_COMMAND_CMDTYPE_OFFSET) /* * This field is interpreted in a command-specific manner, * described for each abstract command. diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 8809483ff..1b3e39cd9 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -421,7 +421,6 @@ static uint64_t dmi_read(struct target *target, uint16_t address) { select_dmi(target); - uint64_t value; dmi_status_t status; uint16_t address_in; @@ -429,7 +428,7 @@ static uint64_t dmi_read(struct target *target, uint16_t address) // This first loop ensures that the read request was actually sent // to the target. Note that if for some reason this stays busy, - // it is actually due to the Previous dmi_read or dmi_write. + // it is actually due to the previous dmi_read or dmi_write. for (i = 0; i < 256; i++) { status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0, false); @@ -444,14 +443,14 @@ static uint64_t dmi_read(struct target *target, uint16_t address) } if (status != DMI_STATUS_SUCCESS) { - LOG_ERROR("Failed read from 0x%x; value=0x%" PRIx64 ", status=%d", - address, value, status); + LOG_ERROR("Failed read from 0x%x; status=%d", address, status); abort(); } // This second loop ensures that we got the read // data back. Note that NOP can result in a 'busy' result as well, but // that would be noticed on the next DMI access we do. + uint64_t value; for (i = 0; i < 256; i++) { status = dmi_scan(target, &address_in, &value, DMI_OP_NOP, address, 0, false); From 702cb0dd465591e43103b6a196e668fa7477981e Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 14:05:32 -0700 Subject: [PATCH 48/68] Another try at 32/64 gcc/clang --- .travis.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ab5af76fa..f721700f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,11 @@ language: c dist: trusty -compiler: - - gcc - - clang matrix: include: - os: linux env: BUILD=x86_64-linux-gnu + compiler: gcc - os: linux env: BUILD=i686-linux-gnu CFLAGS=-m32 @@ -15,6 +13,19 @@ matrix: apt: packages: - gcc-multilib + compiler: gcc + + - os: linux + env: BUILD=x86_64-linux-gnu + compiler: clang + + - os: linux + env: BUILD=i686-linux-gnu CFLAGS=-m32 + compiler: clang + addons: + apt: + packages: + - gcc-multilib script: - ./bootstrap && ./configure && make From 0abd94b50c6443f6ef9638fe6405a1153cef5759 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 14:23:59 -0700 Subject: [PATCH 49/68] Make constants unsigned for clang. --- src/target/riscv/debug_defines.h | 655 ++++++++++++++----------------- src/target/riscv/riscv-013.c | 2 +- 2 files changed, 287 insertions(+), 370 deletions(-) diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index fa2856020..6e88a55ec 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -4,13 +4,13 @@ */ #define DTM_IDCODE_VERSION_OFFSET 28 #define DTM_IDCODE_VERSION_LENGTH 4 -#define DTM_IDCODE_VERSION (0xf << DTM_IDCODE_VERSION_OFFSET) +#define DTM_IDCODE_VERSION (0xfU << DTM_IDCODE_VERSION_OFFSET) /* * Identifies the designer's part number of this part. */ #define DTM_IDCODE_PARTNUMBER_OFFSET 12 #define DTM_IDCODE_PARTNUMBER_LENGTH 16 -#define DTM_IDCODE_PARTNUMBER (0xffff << DTM_IDCODE_PARTNUMBER_OFFSET) +#define DTM_IDCODE_PARTNUMBER (0xffffU << DTM_IDCODE_PARTNUMBER_OFFSET) /* * Identifies the designer/manufacturer of this part. Bits 6:0 must be * bits 6:0 of the designer/manufacturer's Identification Code as @@ -20,10 +20,10 @@ */ #define DTM_IDCODE_MANUFID_OFFSET 1 #define DTM_IDCODE_MANUFID_LENGTH 11 -#define DTM_IDCODE_MANUFID (0x7ff << DTM_IDCODE_MANUFID_OFFSET) +#define DTM_IDCODE_MANUFID (0x7ffU << DTM_IDCODE_MANUFID_OFFSET) #define DTM_IDCODE_1_OFFSET 0 #define DTM_IDCODE_1_LENGTH 1 -#define DTM_IDCODE_1 (0x1 << DTM_IDCODE_1_OFFSET) +#define DTM_IDCODE_1 (0x1U << DTM_IDCODE_1_OFFSET) #define DTM_DTMCS 0x10 /* * Writing 1 to this bit does a hard reset of the DTM, @@ -35,7 +35,7 @@ */ #define DTM_DTMCS_DMIHARDRESET_OFFSET 17 #define DTM_DTMCS_DMIHARDRESET_LENGTH 1 -#define DTM_DTMCS_DMIHARDRESET (0x1 << DTM_DTMCS_DMIHARDRESET_OFFSET) +#define DTM_DTMCS_DMIHARDRESET (0x1U << DTM_DTMCS_DMIHARDRESET_OFFSET) /* * Writing 1 to this bit clears the sticky error state * and allows the DTM to retry or complete the previous @@ -43,7 +43,7 @@ */ #define DTM_DTMCS_DMIRESET_OFFSET 16 #define DTM_DTMCS_DMIRESET_LENGTH 1 -#define DTM_DTMCS_DMIRESET (0x1 << DTM_DTMCS_DMIRESET_OFFSET) +#define DTM_DTMCS_DMIRESET (0x1U << DTM_DTMCS_DMIRESET_OFFSET) /* * This is a hint to the debugger of the minimum number of * cycles a debugger should spend in @@ -61,7 +61,7 @@ */ #define DTM_DTMCS_IDLE_OFFSET 12 #define DTM_DTMCS_IDLE_LENGTH 3 -#define DTM_DTMCS_IDLE (0x7 << DTM_DTMCS_IDLE_OFFSET) +#define DTM_DTMCS_IDLE (0x7U << DTM_DTMCS_IDLE_OFFSET) /* * 0: No error. * @@ -74,24 +74,24 @@ */ #define DTM_DTMCS_DMISTAT_OFFSET 10 #define DTM_DTMCS_DMISTAT_LENGTH 2 -#define DTM_DTMCS_DMISTAT (0x3 << DTM_DTMCS_DMISTAT_OFFSET) +#define DTM_DTMCS_DMISTAT (0x3U << DTM_DTMCS_DMISTAT_OFFSET) /* * The size of \Faddress in \Rdmi. */ #define DTM_DTMCS_ABITS_OFFSET 4 #define DTM_DTMCS_ABITS_LENGTH 6 -#define DTM_DTMCS_ABITS (0x3f << DTM_DTMCS_ABITS_OFFSET) +#define DTM_DTMCS_ABITS (0x3fU << DTM_DTMCS_ABITS_OFFSET) /* * 0: Version described in spec version 0.11. * * 1: Version described in spec version 0.13 (and later?), which * reduces the DMI data width to 32 bits. * -* Other values are reserved for future use. +* 15: Version not described in any available version of this spec. */ #define DTM_DTMCS_VERSION_OFFSET 0 #define DTM_DTMCS_VERSION_LENGTH 4 -#define DTM_DTMCS_VERSION (0xf << DTM_DTMCS_VERSION_OFFSET) +#define DTM_DTMCS_VERSION (0xfU << DTM_DTMCS_VERSION_OFFSET) #define DTM_DMI 0x11 /* * Address used for DMI access. In Update-DR this value is used @@ -106,7 +106,7 @@ */ #define DTM_DMI_DATA_OFFSET 2 #define DTM_DMI_DATA_LENGTH 32 -#define DTM_DMI_DATA (0xffffffffLL << DTM_DMI_DATA_OFFSET) +#define DTM_DMI_DATA (0xffffffffULL << DTM_DMI_DATA_OFFSET) /* * When the debugger writes this field, it has the following meaning: * @@ -133,8 +133,10 @@ * this access will be ignored. This status is sticky and can be * cleared by writing \Fdmireset in \Rdtmcs. * -* This indicates that the DM itself responded with an error, e.g. -* in the System Bus and Serial Port overflow/underflow cases. +* This indicates that the DM itself responded with an error. +* Note: there are no specified cases in which the DM would +* respond with an error, and DMI is not required to support +* returning errors. * * 3: An operation was attempted while a DMI request is still in * progress. The data scanned into \Rdmi in this access will be @@ -151,41 +153,57 @@ */ #define DTM_DMI_OP_OFFSET 0 #define DTM_DMI_OP_LENGTH 2 -#define DTM_DMI_OP (0x3LL << DTM_DMI_OP_OFFSET) +#define DTM_DMI_OP (0x3ULL << DTM_DMI_OP_OFFSET) #define CSR_DCSR 0x7b0 /* * 0: There is no external debug support. * * 4: External debug support exists as it is described in this document. +* +* 15: There is external debug support, but it does not conform to any +* available version of this spec. */ #define CSR_DCSR_XDEBUGVER_OFFSET 28 #define CSR_DCSR_XDEBUGVER_LENGTH 4 -#define CSR_DCSR_XDEBUGVER (0xf << CSR_DCSR_XDEBUGVER_OFFSET) +#define CSR_DCSR_XDEBUGVER (0xfU << CSR_DCSR_XDEBUGVER_OFFSET) /* * When 1, {\tt ebreak} instructions in Machine Mode enter Debug Mode. */ #define CSR_DCSR_EBREAKM_OFFSET 15 #define CSR_DCSR_EBREAKM_LENGTH 1 -#define CSR_DCSR_EBREAKM (0x1 << CSR_DCSR_EBREAKM_OFFSET) +#define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET) /* * When 1, {\tt ebreak} instructions in Hypervisor Mode enter Debug Mode. */ #define CSR_DCSR_EBREAKH_OFFSET 14 #define CSR_DCSR_EBREAKH_LENGTH 1 -#define CSR_DCSR_EBREAKH (0x1 << CSR_DCSR_EBREAKH_OFFSET) +#define CSR_DCSR_EBREAKH (0x1U << CSR_DCSR_EBREAKH_OFFSET) /* * When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode. */ #define CSR_DCSR_EBREAKS_OFFSET 13 #define CSR_DCSR_EBREAKS_LENGTH 1 -#define CSR_DCSR_EBREAKS (0x1 << CSR_DCSR_EBREAKS_OFFSET) +#define CSR_DCSR_EBREAKS (0x1U << CSR_DCSR_EBREAKS_OFFSET) /* * When 1, {\tt ebreak} instructions in User/Application Mode enter * Debug Mode. */ #define CSR_DCSR_EBREAKU_OFFSET 12 #define CSR_DCSR_EBREAKU_LENGTH 1 -#define CSR_DCSR_EBREAKU (0x1 << CSR_DCSR_EBREAKU_OFFSET) +#define CSR_DCSR_EBREAKU (0x1U << CSR_DCSR_EBREAKU_OFFSET) +/* +* 0: Interrupts are disabled during single stepping. +* +* 1: Interrupts are enabled during single stepping. +* +* Implementations may hard wire this bit to 0. +* The debugger must read back the value it +* writes to check whether the feature is supported. If not +* supported, interrupt behavior can be emulated by the debugger. + */ +#define CSR_DCSR_STEPIE_OFFSET 11 +#define CSR_DCSR_STEPIE_LENGTH 1 +#define CSR_DCSR_STEPIE (0x1U << CSR_DCSR_STEPIE_OFFSET) /* * 0: Increment counters as usual. * @@ -199,7 +217,7 @@ */ #define CSR_DCSR_STOPCOUNT_OFFSET 10 #define CSR_DCSR_STOPCOUNT_LENGTH 1 -#define CSR_DCSR_STOPCOUNT (0x1 << CSR_DCSR_STOPCOUNT_OFFSET) +#define CSR_DCSR_STOPCOUNT (0x1U << CSR_DCSR_STOPCOUNT_OFFSET) /* * 0: Increment timers as usual. * @@ -211,7 +229,7 @@ */ #define CSR_DCSR_STOPTIME_OFFSET 9 #define CSR_DCSR_STOPTIME_LENGTH 1 -#define CSR_DCSR_STOPTIME (0x1 << CSR_DCSR_STOPTIME_OFFSET) +#define CSR_DCSR_STOPTIME (0x1U << CSR_DCSR_STOPTIME_OFFSET) /* * Explains why Debug Mode was entered. * @@ -220,9 +238,9 @@ * * 1: An {\tt ebreak} instruction was executed. (priority 3) * -* 2: The Trigger Module caused a halt. (priority 4) +* 2: The Trigger Module caused a breakpoint exception. (priority 4) * -* 3: \Fhaltreq was set. (priority 2) +* 3: The debugger requested entry to Debug Mode. (priority 2) * * 4: The hart single stepped because \Fstep was set. (priority 1) * @@ -230,18 +248,17 @@ */ #define CSR_DCSR_CAUSE_OFFSET 6 #define CSR_DCSR_CAUSE_LENGTH 3 -#define CSR_DCSR_CAUSE (0x7 << CSR_DCSR_CAUSE_OFFSET) +#define CSR_DCSR_CAUSE (0x7U << CSR_DCSR_CAUSE_OFFSET) /* * When set and not in Debug Mode, the hart will only execute a single * instruction and then enter Debug Mode. -* Interrupts are disabled when this bit is set. * If the instruction does not complete due to an exception, * the hart will immediately enter Debug Mode before executing * the trap handler, with appropriate exception registers set. */ #define CSR_DCSR_STEP_OFFSET 2 #define CSR_DCSR_STEP_LENGTH 1 -#define CSR_DCSR_STEP (0x1 << CSR_DCSR_STEP_OFFSET) +#define CSR_DCSR_STEP (0x1U << CSR_DCSR_STEP_OFFSET) /* * Contains the privilege level the hart was operating in when Debug * Mode was entered. The encoding is described in Table @@ -254,7 +271,7 @@ */ #define CSR_DCSR_PRV_OFFSET 0 #define CSR_DCSR_PRV_LENGTH 2 -#define CSR_DCSR_PRV (0x3 << CSR_DCSR_PRV_OFFSET) +#define CSR_DCSR_PRV (0x3U << CSR_DCSR_PRV_OFFSET) #define CSR_DPC 0x7b1 #define CSR_DPC_DPC_OFFSET 0 #define CSR_DPC_DPC_LENGTH XLEN @@ -285,7 +302,7 @@ */ #define CSR_TDATA1_TYPE_OFFSET XLEN-4 #define CSR_TDATA1_TYPE_LENGTH 4 -#define CSR_TDATA1_TYPE (0xfLL << CSR_TDATA1_TYPE_OFFSET) +#define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET) /* * 0: Both Debug and M Mode can write the {\tt tdata} registers at the * selected \Rtselect. @@ -297,7 +314,7 @@ */ #define CSR_TDATA1_HMODE_OFFSET XLEN-5 #define CSR_TDATA1_HMODE_LENGTH 1 -#define CSR_TDATA1_HMODE (0x1LL << CSR_TDATA1_HMODE_OFFSET) +#define CSR_TDATA1_HMODE (0x1ULL << CSR_TDATA1_HMODE_OFFSET) /* * Trigger-specific data. */ @@ -315,10 +332,10 @@ #define CSR_MCONTROL 0x7a1 #define CSR_MCONTROL_TYPE_OFFSET XLEN-4 #define CSR_MCONTROL_TYPE_LENGTH 4 -#define CSR_MCONTROL_TYPE (0xfLL << CSR_MCONTROL_TYPE_OFFSET) +#define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET) #define CSR_MCONTROL_DMODE_OFFSET XLEN-5 #define CSR_MCONTROL_DMODE_LENGTH 1 -#define CSR_MCONTROL_DMODE (0x1LL << CSR_MCONTROL_DMODE_OFFSET) +#define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET) /* * Specifies the largest naturally aligned powers-of-two (NAPOT) range * supported by the hardware. The value is the logarithm base 2 of the @@ -329,7 +346,7 @@ */ #define CSR_MCONTROL_MASKMAX_OFFSET XLEN-11 #define CSR_MCONTROL_MASKMAX_LENGTH 6 -#define CSR_MCONTROL_MASKMAX (0x3fLL << CSR_MCONTROL_MASKMAX_OFFSET) +#define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET) /* * 0: Perform a match on the virtual address. * @@ -338,7 +355,7 @@ */ #define CSR_MCONTROL_SELECT_OFFSET 19 #define CSR_MCONTROL_SELECT_LENGTH 1 -#define CSR_MCONTROL_SELECT (0x1LL << CSR_MCONTROL_SELECT_OFFSET) +#define CSR_MCONTROL_SELECT (0x1ULL << CSR_MCONTROL_SELECT_OFFSET) /* * 0: The action for this trigger will be taken just before the * instruction that triggered it is executed, but after all preceding @@ -366,7 +383,7 @@ */ #define CSR_MCONTROL_TIMING_OFFSET 18 #define CSR_MCONTROL_TIMING_LENGTH 1 -#define CSR_MCONTROL_TIMING (0x1LL << CSR_MCONTROL_TIMING_OFFSET) +#define CSR_MCONTROL_TIMING (0x1ULL << CSR_MCONTROL_TIMING_OFFSET) /* * Determines what happens when this trigger matches. * @@ -387,7 +404,7 @@ */ #define CSR_MCONTROL_ACTION_OFFSET 12 #define CSR_MCONTROL_ACTION_LENGTH 6 -#define CSR_MCONTROL_ACTION (0x3fLL << CSR_MCONTROL_ACTION_OFFSET) +#define CSR_MCONTROL_ACTION (0x3fULL << CSR_MCONTROL_ACTION_OFFSET) /* * 0: When this trigger matches, the configured action is taken. * @@ -396,7 +413,7 @@ */ #define CSR_MCONTROL_CHAIN_OFFSET 11 #define CSR_MCONTROL_CHAIN_LENGTH 1 -#define CSR_MCONTROL_CHAIN (0x1LL << CSR_MCONTROL_CHAIN_OFFSET) +#define CSR_MCONTROL_CHAIN (0x1ULL << CSR_MCONTROL_CHAIN_OFFSET) /* * 0: Matches when the value equals \Rtdatatwo. * @@ -404,9 +421,10 @@ * \Rtdatatwo. M is XLEN-1 minus the index of the least-significant * bit containing 0 in \Rtdatatwo. * -* 2: Matches when the value is greater than or equal to \Rtdatatwo. +* 2: Matches when the value is greater than (unsigned) or equal to +* \Rtdatatwo. * -* 3: Matches when the value is less than \Rtdatatwo. +* 3: Matches when the value is less than (unsigned) \Rtdatatwo. * * 4: Matches when the lower half of the value equals the lower half * of \Rtdatatwo after the lower half of the value is ANDed with the @@ -420,57 +438,57 @@ */ #define CSR_MCONTROL_MATCH_OFFSET 7 #define CSR_MCONTROL_MATCH_LENGTH 4 -#define CSR_MCONTROL_MATCH (0xfLL << CSR_MCONTROL_MATCH_OFFSET) +#define CSR_MCONTROL_MATCH (0xfULL << CSR_MCONTROL_MATCH_OFFSET) /* * When set, enable this trigger in M mode. */ #define CSR_MCONTROL_M_OFFSET 6 #define CSR_MCONTROL_M_LENGTH 1 -#define CSR_MCONTROL_M (0x1LL << CSR_MCONTROL_M_OFFSET) +#define CSR_MCONTROL_M (0x1ULL << CSR_MCONTROL_M_OFFSET) /* * When set, enable this trigger in H mode. */ #define CSR_MCONTROL_H_OFFSET 5 #define CSR_MCONTROL_H_LENGTH 1 -#define CSR_MCONTROL_H (0x1LL << CSR_MCONTROL_H_OFFSET) +#define CSR_MCONTROL_H (0x1ULL << CSR_MCONTROL_H_OFFSET) /* * When set, enable this trigger in S mode. */ #define CSR_MCONTROL_S_OFFSET 4 #define CSR_MCONTROL_S_LENGTH 1 -#define CSR_MCONTROL_S (0x1LL << CSR_MCONTROL_S_OFFSET) +#define CSR_MCONTROL_S (0x1ULL << CSR_MCONTROL_S_OFFSET) /* * When set, enable this trigger in U mode. */ #define CSR_MCONTROL_U_OFFSET 3 #define CSR_MCONTROL_U_LENGTH 1 -#define CSR_MCONTROL_U (0x1LL << CSR_MCONTROL_U_OFFSET) +#define CSR_MCONTROL_U (0x1ULL << CSR_MCONTROL_U_OFFSET) /* * When set, the trigger fires on the virtual address or opcode of an * instruction that is executed. */ #define CSR_MCONTROL_EXECUTE_OFFSET 2 #define CSR_MCONTROL_EXECUTE_LENGTH 1 -#define CSR_MCONTROL_EXECUTE (0x1LL << CSR_MCONTROL_EXECUTE_OFFSET) +#define CSR_MCONTROL_EXECUTE (0x1ULL << CSR_MCONTROL_EXECUTE_OFFSET) /* * When set, the trigger fires on the virtual address or data of a store. */ #define CSR_MCONTROL_STORE_OFFSET 1 #define CSR_MCONTROL_STORE_LENGTH 1 -#define CSR_MCONTROL_STORE (0x1LL << CSR_MCONTROL_STORE_OFFSET) +#define CSR_MCONTROL_STORE (0x1ULL << CSR_MCONTROL_STORE_OFFSET) /* * When set, the trigger fires on the virtual address or data of a load. */ #define CSR_MCONTROL_LOAD_OFFSET 0 #define CSR_MCONTROL_LOAD_LENGTH 1 -#define CSR_MCONTROL_LOAD (0x1LL << CSR_MCONTROL_LOAD_OFFSET) +#define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET) #define CSR_ICOUNT 0x7a1 #define CSR_ICOUNT_TYPE_OFFSET XLEN-4 #define CSR_ICOUNT_TYPE_LENGTH 4 -#define CSR_ICOUNT_TYPE (0xfLL << CSR_ICOUNT_TYPE_OFFSET) +#define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET) #define CSR_ICOUNT_DMODE_OFFSET XLEN-5 #define CSR_ICOUNT_DMODE_LENGTH 1 -#define CSR_ICOUNT_DMODE (0x1LL << CSR_ICOUNT_DMODE_OFFSET) +#define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET) /* * When count is decremented to 0, the trigger fires. Instead of * changing \Fcount from 1 to 0, it is also acceptable for hardware to @@ -479,35 +497,35 @@ */ #define CSR_ICOUNT_COUNT_OFFSET 10 #define CSR_ICOUNT_COUNT_LENGTH 14 -#define CSR_ICOUNT_COUNT (0x3fffLL << CSR_ICOUNT_COUNT_OFFSET) +#define CSR_ICOUNT_COUNT (0x3fffULL << CSR_ICOUNT_COUNT_OFFSET) /* * When set, every instruction completed or exception taken in M mode decrements \Fcount * by 1. */ #define CSR_ICOUNT_M_OFFSET 9 #define CSR_ICOUNT_M_LENGTH 1 -#define CSR_ICOUNT_M (0x1LL << CSR_ICOUNT_M_OFFSET) +#define CSR_ICOUNT_M (0x1ULL << CSR_ICOUNT_M_OFFSET) /* * When set, every instruction completed or exception taken in in H mode decrements \Fcount * by 1. */ #define CSR_ICOUNT_H_OFFSET 8 #define CSR_ICOUNT_H_LENGTH 1 -#define CSR_ICOUNT_H (0x1LL << CSR_ICOUNT_H_OFFSET) +#define CSR_ICOUNT_H (0x1ULL << CSR_ICOUNT_H_OFFSET) /* * When set, every instruction completed or exception taken in S mode decrements \Fcount * by 1. */ #define CSR_ICOUNT_S_OFFSET 7 #define CSR_ICOUNT_S_LENGTH 1 -#define CSR_ICOUNT_S (0x1LL << CSR_ICOUNT_S_OFFSET) +#define CSR_ICOUNT_S (0x1ULL << CSR_ICOUNT_S_OFFSET) /* * When set, every instruction completed or exception taken in U mode decrements \Fcount * by 1. */ #define CSR_ICOUNT_U_OFFSET 6 #define CSR_ICOUNT_U_LENGTH 1 -#define CSR_ICOUNT_U (0x1LL << CSR_ICOUNT_U_OFFSET) +#define CSR_ICOUNT_U (0x1ULL << CSR_ICOUNT_U_OFFSET) /* * Determines what happens when this trigger matches. * @@ -528,68 +546,68 @@ */ #define CSR_ICOUNT_ACTION_OFFSET 0 #define CSR_ICOUNT_ACTION_LENGTH 6 -#define CSR_ICOUNT_ACTION (0x3fLL << CSR_ICOUNT_ACTION_OFFSET) +#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET) #define DMI_DMSTATUS 0x11 /* * This field is 1 when all currently selected harts have acknowledged the previous \Fresumereq. */ #define DMI_DMSTATUS_ALLRESUMEACK_OFFSET 17 #define DMI_DMSTATUS_ALLRESUMEACK_LENGTH 1 -#define DMI_DMSTATUS_ALLRESUMEACK (0x1 << DMI_DMSTATUS_ALLRESUMEACK_OFFSET) +#define DMI_DMSTATUS_ALLRESUMEACK (0x1U << DMI_DMSTATUS_ALLRESUMEACK_OFFSET) /* * This field is 1 when any currently selected hart has acknowledged the previous \Fresumereq. */ #define DMI_DMSTATUS_ANYRESUMEACK_OFFSET 16 #define DMI_DMSTATUS_ANYRESUMEACK_LENGTH 1 -#define DMI_DMSTATUS_ANYRESUMEACK (0x1 << DMI_DMSTATUS_ANYRESUMEACK_OFFSET) +#define DMI_DMSTATUS_ANYRESUMEACK (0x1U << DMI_DMSTATUS_ANYRESUMEACK_OFFSET) /* * This field is 1 when all currently selected harts do not exist in this system. */ #define DMI_DMSTATUS_ALLNONEXISTENT_OFFSET 15 #define DMI_DMSTATUS_ALLNONEXISTENT_LENGTH 1 -#define DMI_DMSTATUS_ALLNONEXISTENT (0x1 << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET) +#define DMI_DMSTATUS_ALLNONEXISTENT (0x1U << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET) /* * This field is 1 when any currently selected hart does not exist in this system. */ #define DMI_DMSTATUS_ANYNONEXISTENT_OFFSET 14 #define DMI_DMSTATUS_ANYNONEXISTENT_LENGTH 1 -#define DMI_DMSTATUS_ANYNONEXISTENT (0x1 << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET) +#define DMI_DMSTATUS_ANYNONEXISTENT (0x1U << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET) /* * This field is 1 when all currently selected harts are unavailable. */ #define DMI_DMSTATUS_ALLUNAVAIL_OFFSET 13 #define DMI_DMSTATUS_ALLUNAVAIL_LENGTH 1 -#define DMI_DMSTATUS_ALLUNAVAIL (0x1 << DMI_DMSTATUS_ALLUNAVAIL_OFFSET) +#define DMI_DMSTATUS_ALLUNAVAIL (0x1U << DMI_DMSTATUS_ALLUNAVAIL_OFFSET) /* * This field is 1 when any currently selected hart is unavailable. */ #define DMI_DMSTATUS_ANYUNAVAIL_OFFSET 12 #define DMI_DMSTATUS_ANYUNAVAIL_LENGTH 1 -#define DMI_DMSTATUS_ANYUNAVAIL (0x1 << DMI_DMSTATUS_ANYUNAVAIL_OFFSET) +#define DMI_DMSTATUS_ANYUNAVAIL (0x1U << DMI_DMSTATUS_ANYUNAVAIL_OFFSET) /* * This field is 1 when all currently selected harts are running. */ #define DMI_DMSTATUS_ALLRUNNING_OFFSET 11 #define DMI_DMSTATUS_ALLRUNNING_LENGTH 1 -#define DMI_DMSTATUS_ALLRUNNING (0x1 << DMI_DMSTATUS_ALLRUNNING_OFFSET) +#define DMI_DMSTATUS_ALLRUNNING (0x1U << DMI_DMSTATUS_ALLRUNNING_OFFSET) /* * This field is 1 when any currently selected hart is running. */ #define DMI_DMSTATUS_ANYRUNNING_OFFSET 10 #define DMI_DMSTATUS_ANYRUNNING_LENGTH 1 -#define DMI_DMSTATUS_ANYRUNNING (0x1 << DMI_DMSTATUS_ANYRUNNING_OFFSET) +#define DMI_DMSTATUS_ANYRUNNING (0x1U << DMI_DMSTATUS_ANYRUNNING_OFFSET) /* * This field is 1 when all currently selected harts are halted. */ #define DMI_DMSTATUS_ALLHALTED_OFFSET 9 #define DMI_DMSTATUS_ALLHALTED_LENGTH 1 -#define DMI_DMSTATUS_ALLHALTED (0x1 << DMI_DMSTATUS_ALLHALTED_OFFSET) +#define DMI_DMSTATUS_ALLHALTED (0x1U << DMI_DMSTATUS_ALLHALTED_OFFSET) /* * This field is 1 when any currently selected hart is halted. */ #define DMI_DMSTATUS_ANYHALTED_OFFSET 8 #define DMI_DMSTATUS_ANYHALTED_LENGTH 1 -#define DMI_DMSTATUS_ANYHALTED (0x1 << DMI_DMSTATUS_ANYHALTED_OFFSET) +#define DMI_DMSTATUS_ANYHALTED (0x1U << DMI_DMSTATUS_ANYHALTED_OFFSET) /* * 0 when authentication is required before using the DM. 1 when the * authentication check has passed. On components that don't implement @@ -597,7 +615,7 @@ */ #define DMI_DMSTATUS_AUTHENTICATED_OFFSET 7 #define DMI_DMSTATUS_AUTHENTICATED_LENGTH 1 -#define DMI_DMSTATUS_AUTHENTICATED (0x1 << DMI_DMSTATUS_AUTHENTICATED_OFFSET) +#define DMI_DMSTATUS_AUTHENTICATED (0x1U << DMI_DMSTATUS_AUTHENTICATED_OFFSET) /* * 0: The authentication module is ready to process the next * read/write to \Rauthdata. @@ -610,10 +628,10 @@ */ #define DMI_DMSTATUS_AUTHBUSY_OFFSET 6 #define DMI_DMSTATUS_AUTHBUSY_LENGTH 1 -#define DMI_DMSTATUS_AUTHBUSY (0x1 << DMI_DMSTATUS_AUTHBUSY_OFFSET) -#define DMI_DMSTATUS_CFGSTRVALID_OFFSET 4 -#define DMI_DMSTATUS_CFGSTRVALID_LENGTH 1 -#define DMI_DMSTATUS_CFGSTRVALID (0x1 << DMI_DMSTATUS_CFGSTRVALID_OFFSET) +#define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET) +#define DMI_DMSTATUS_DEVTREEVALID_OFFSET 4 +#define DMI_DMSTATUS_DEVTREEVALID_LENGTH 1 +#define DMI_DMSTATUS_DEVTREEVALID (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET) /* * 0: There is no Debug Module present. * @@ -622,10 +640,13 @@ * * 2: There is a Debug Module and it conforms to version 0.13 of this * specification. +* +* 15: There is a Debug Module but it does not conform to any +* available version of this spec. */ #define DMI_DMSTATUS_VERSION_OFFSET 0 #define DMI_DMSTATUS_VERSION_LENGTH 4 -#define DMI_DMSTATUS_VERSION (0xf << DMI_DMSTATUS_VERSION_OFFSET) +#define DMI_DMSTATUS_VERSION (0xfU << DMI_DMSTATUS_VERSION_OFFSET) #define DMI_DMCONTROL 0x10 /* * Halt request signal for all currently selected harts. When set to @@ -639,7 +660,7 @@ */ #define DMI_DMCONTROL_HALTREQ_OFFSET 31 #define DMI_DMCONTROL_HALTREQ_LENGTH 1 -#define DMI_DMCONTROL_HALTREQ (0x1 << DMI_DMCONTROL_HALTREQ_OFFSET) +#define DMI_DMCONTROL_HALTREQ (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET) /* * Resume request signal for all currently selected harts. When set to 1, * each selected hart will resume if it is currently halted. @@ -649,7 +670,7 @@ */ #define DMI_DMCONTROL_RESUMEREQ_OFFSET 30 #define DMI_DMCONTROL_RESUMEREQ_LENGTH 1 -#define DMI_DMCONTROL_RESUMEREQ (0x1 << DMI_DMCONTROL_RESUMEREQ_OFFSET) +#define DMI_DMCONTROL_RESUMEREQ (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET) /* * This optional bit controls reset to all the currently selected harts. * To perform a reset the debugger writes 1, and then writes 0 to @@ -663,7 +684,7 @@ */ #define DMI_DMCONTROL_HARTRESET_OFFSET 29 #define DMI_DMCONTROL_HARTRESET_LENGTH 1 -#define DMI_DMCONTROL_HARTRESET (0x1 << DMI_DMCONTROL_HARTRESET_OFFSET) +#define DMI_DMCONTROL_HARTRESET (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET) /* * Selects the definition of currently selected harts. * @@ -679,14 +700,14 @@ */ #define DMI_DMCONTROL_HASEL_OFFSET 26 #define DMI_DMCONTROL_HASEL_LENGTH 1 -#define DMI_DMCONTROL_HASEL (0x1 << DMI_DMCONTROL_HASEL_OFFSET) +#define DMI_DMCONTROL_HASEL (0x1U << DMI_DMCONTROL_HASEL_OFFSET) /* * The DM-specific index of the hart to select. This hart is always part of the * currently selected harts. */ #define DMI_DMCONTROL_HARTSEL_OFFSET 16 #define DMI_DMCONTROL_HARTSEL_LENGTH 10 -#define DMI_DMCONTROL_HARTSEL (0x3ff << DMI_DMCONTROL_HARTSEL_OFFSET) +#define DMI_DMCONTROL_HARTSEL (0x3ffU << DMI_DMCONTROL_HARTSEL_OFFSET) /* * This bit controls the reset signal from the DM to the rest of the * system. To perform a system reset the debugger writes 1, @@ -697,7 +718,7 @@ */ #define DMI_DMCONTROL_NDMRESET_OFFSET 1 #define DMI_DMCONTROL_NDMRESET_LENGTH 1 -#define DMI_DMCONTROL_NDMRESET (0x1 << DMI_DMCONTROL_NDMRESET_OFFSET) +#define DMI_DMCONTROL_NDMRESET (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET) /* * This bit serves as a reset signal for the Debug Module itself. * @@ -720,7 +741,7 @@ */ #define DMI_DMCONTROL_DMACTIVE_OFFSET 0 #define DMI_DMCONTROL_DMACTIVE_LENGTH 1 -#define DMI_DMCONTROL_DMACTIVE (0x1 << DMI_DMCONTROL_DMACTIVE_OFFSET) +#define DMI_DMCONTROL_DMACTIVE (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET) #define DMI_HARTINFO 0x12 /* * Number of {\tt dscratch} registers available for the debugger @@ -730,7 +751,7 @@ */ #define DMI_HARTINFO_NSCRATCH_OFFSET 20 #define DMI_HARTINFO_NSCRATCH_LENGTH 4 -#define DMI_HARTINFO_NSCRATCH (0xf << DMI_HARTINFO_NSCRATCH_OFFSET) +#define DMI_HARTINFO_NSCRATCH (0xfU << DMI_HARTINFO_NSCRATCH_OFFSET) /* * 0: The {\tt data} registers are shadowed in the hart by CSR * registers. Each CSR register is XLEN bits in size, and corresponds @@ -741,7 +762,7 @@ */ #define DMI_HARTINFO_DATAACCESS_OFFSET 16 #define DMI_HARTINFO_DATAACCESS_LENGTH 1 -#define DMI_HARTINFO_DATAACCESS (0x1 << DMI_HARTINFO_DATAACCESS_OFFSET) +#define DMI_HARTINFO_DATAACCESS (0x1U << DMI_HARTINFO_DATAACCESS_OFFSET) /* * If \Fdataaccess is 0: Number of CSR registers dedicated to * shadowing the {\tt data} registers. @@ -751,7 +772,7 @@ */ #define DMI_HARTINFO_DATASIZE_OFFSET 12 #define DMI_HARTINFO_DATASIZE_LENGTH 4 -#define DMI_HARTINFO_DATASIZE (0xf << DMI_HARTINFO_DATASIZE_OFFSET) +#define DMI_HARTINFO_DATASIZE (0xfU << DMI_HARTINFO_DATASIZE_OFFSET) /* * If \Fdataaccess is 0: The number of the first CSR dedicated to * shadowing the {\tt data} registers. @@ -761,112 +782,112 @@ */ #define DMI_HARTINFO_DATAADDR_OFFSET 0 #define DMI_HARTINFO_DATAADDR_LENGTH 12 -#define DMI_HARTINFO_DATAADDR (0xfff << DMI_HARTINFO_DATAADDR_OFFSET) +#define DMI_HARTINFO_DATAADDR (0xfffU << DMI_HARTINFO_DATAADDR_OFFSET) #define DMI_HALTSUM 0x13 #define DMI_HALTSUM_HALT1023_992_OFFSET 31 #define DMI_HALTSUM_HALT1023_992_LENGTH 1 -#define DMI_HALTSUM_HALT1023_992 (0x1 << DMI_HALTSUM_HALT1023_992_OFFSET) +#define DMI_HALTSUM_HALT1023_992 (0x1U << DMI_HALTSUM_HALT1023_992_OFFSET) #define DMI_HALTSUM_HALT991_960_OFFSET 30 #define DMI_HALTSUM_HALT991_960_LENGTH 1 -#define DMI_HALTSUM_HALT991_960 (0x1 << DMI_HALTSUM_HALT991_960_OFFSET) +#define DMI_HALTSUM_HALT991_960 (0x1U << DMI_HALTSUM_HALT991_960_OFFSET) #define DMI_HALTSUM_HALT959_928_OFFSET 29 #define DMI_HALTSUM_HALT959_928_LENGTH 1 -#define DMI_HALTSUM_HALT959_928 (0x1 << DMI_HALTSUM_HALT959_928_OFFSET) +#define DMI_HALTSUM_HALT959_928 (0x1U << DMI_HALTSUM_HALT959_928_OFFSET) #define DMI_HALTSUM_HALT927_896_OFFSET 28 #define DMI_HALTSUM_HALT927_896_LENGTH 1 -#define DMI_HALTSUM_HALT927_896 (0x1 << DMI_HALTSUM_HALT927_896_OFFSET) +#define DMI_HALTSUM_HALT927_896 (0x1U << DMI_HALTSUM_HALT927_896_OFFSET) #define DMI_HALTSUM_HALT895_864_OFFSET 27 #define DMI_HALTSUM_HALT895_864_LENGTH 1 -#define DMI_HALTSUM_HALT895_864 (0x1 << DMI_HALTSUM_HALT895_864_OFFSET) +#define DMI_HALTSUM_HALT895_864 (0x1U << DMI_HALTSUM_HALT895_864_OFFSET) #define DMI_HALTSUM_HALT863_832_OFFSET 26 #define DMI_HALTSUM_HALT863_832_LENGTH 1 -#define DMI_HALTSUM_HALT863_832 (0x1 << DMI_HALTSUM_HALT863_832_OFFSET) +#define DMI_HALTSUM_HALT863_832 (0x1U << DMI_HALTSUM_HALT863_832_OFFSET) #define DMI_HALTSUM_HALT831_800_OFFSET 25 #define DMI_HALTSUM_HALT831_800_LENGTH 1 -#define DMI_HALTSUM_HALT831_800 (0x1 << DMI_HALTSUM_HALT831_800_OFFSET) +#define DMI_HALTSUM_HALT831_800 (0x1U << DMI_HALTSUM_HALT831_800_OFFSET) #define DMI_HALTSUM_HALT799_768_OFFSET 24 #define DMI_HALTSUM_HALT799_768_LENGTH 1 -#define DMI_HALTSUM_HALT799_768 (0x1 << DMI_HALTSUM_HALT799_768_OFFSET) +#define DMI_HALTSUM_HALT799_768 (0x1U << DMI_HALTSUM_HALT799_768_OFFSET) #define DMI_HALTSUM_HALT767_736_OFFSET 23 #define DMI_HALTSUM_HALT767_736_LENGTH 1 -#define DMI_HALTSUM_HALT767_736 (0x1 << DMI_HALTSUM_HALT767_736_OFFSET) +#define DMI_HALTSUM_HALT767_736 (0x1U << DMI_HALTSUM_HALT767_736_OFFSET) #define DMI_HALTSUM_HALT735_704_OFFSET 22 #define DMI_HALTSUM_HALT735_704_LENGTH 1 -#define DMI_HALTSUM_HALT735_704 (0x1 << DMI_HALTSUM_HALT735_704_OFFSET) +#define DMI_HALTSUM_HALT735_704 (0x1U << DMI_HALTSUM_HALT735_704_OFFSET) #define DMI_HALTSUM_HALT703_672_OFFSET 21 #define DMI_HALTSUM_HALT703_672_LENGTH 1 -#define DMI_HALTSUM_HALT703_672 (0x1 << DMI_HALTSUM_HALT703_672_OFFSET) +#define DMI_HALTSUM_HALT703_672 (0x1U << DMI_HALTSUM_HALT703_672_OFFSET) #define DMI_HALTSUM_HALT671_640_OFFSET 20 #define DMI_HALTSUM_HALT671_640_LENGTH 1 -#define DMI_HALTSUM_HALT671_640 (0x1 << DMI_HALTSUM_HALT671_640_OFFSET) +#define DMI_HALTSUM_HALT671_640 (0x1U << DMI_HALTSUM_HALT671_640_OFFSET) #define DMI_HALTSUM_HALT639_608_OFFSET 19 #define DMI_HALTSUM_HALT639_608_LENGTH 1 -#define DMI_HALTSUM_HALT639_608 (0x1 << DMI_HALTSUM_HALT639_608_OFFSET) +#define DMI_HALTSUM_HALT639_608 (0x1U << DMI_HALTSUM_HALT639_608_OFFSET) #define DMI_HALTSUM_HALT607_576_OFFSET 18 #define DMI_HALTSUM_HALT607_576_LENGTH 1 -#define DMI_HALTSUM_HALT607_576 (0x1 << DMI_HALTSUM_HALT607_576_OFFSET) +#define DMI_HALTSUM_HALT607_576 (0x1U << DMI_HALTSUM_HALT607_576_OFFSET) #define DMI_HALTSUM_HALT575_544_OFFSET 17 #define DMI_HALTSUM_HALT575_544_LENGTH 1 -#define DMI_HALTSUM_HALT575_544 (0x1 << DMI_HALTSUM_HALT575_544_OFFSET) +#define DMI_HALTSUM_HALT575_544 (0x1U << DMI_HALTSUM_HALT575_544_OFFSET) #define DMI_HALTSUM_HALT543_512_OFFSET 16 #define DMI_HALTSUM_HALT543_512_LENGTH 1 -#define DMI_HALTSUM_HALT543_512 (0x1 << DMI_HALTSUM_HALT543_512_OFFSET) +#define DMI_HALTSUM_HALT543_512 (0x1U << DMI_HALTSUM_HALT543_512_OFFSET) #define DMI_HALTSUM_HALT511_480_OFFSET 15 #define DMI_HALTSUM_HALT511_480_LENGTH 1 -#define DMI_HALTSUM_HALT511_480 (0x1 << DMI_HALTSUM_HALT511_480_OFFSET) +#define DMI_HALTSUM_HALT511_480 (0x1U << DMI_HALTSUM_HALT511_480_OFFSET) #define DMI_HALTSUM_HALT479_448_OFFSET 14 #define DMI_HALTSUM_HALT479_448_LENGTH 1 -#define DMI_HALTSUM_HALT479_448 (0x1 << DMI_HALTSUM_HALT479_448_OFFSET) +#define DMI_HALTSUM_HALT479_448 (0x1U << DMI_HALTSUM_HALT479_448_OFFSET) #define DMI_HALTSUM_HALT447_416_OFFSET 13 #define DMI_HALTSUM_HALT447_416_LENGTH 1 -#define DMI_HALTSUM_HALT447_416 (0x1 << DMI_HALTSUM_HALT447_416_OFFSET) +#define DMI_HALTSUM_HALT447_416 (0x1U << DMI_HALTSUM_HALT447_416_OFFSET) #define DMI_HALTSUM_HALT415_384_OFFSET 12 #define DMI_HALTSUM_HALT415_384_LENGTH 1 -#define DMI_HALTSUM_HALT415_384 (0x1 << DMI_HALTSUM_HALT415_384_OFFSET) +#define DMI_HALTSUM_HALT415_384 (0x1U << DMI_HALTSUM_HALT415_384_OFFSET) #define DMI_HALTSUM_HALT383_352_OFFSET 11 #define DMI_HALTSUM_HALT383_352_LENGTH 1 -#define DMI_HALTSUM_HALT383_352 (0x1 << DMI_HALTSUM_HALT383_352_OFFSET) +#define DMI_HALTSUM_HALT383_352 (0x1U << DMI_HALTSUM_HALT383_352_OFFSET) #define DMI_HALTSUM_HALT351_320_OFFSET 10 #define DMI_HALTSUM_HALT351_320_LENGTH 1 -#define DMI_HALTSUM_HALT351_320 (0x1 << DMI_HALTSUM_HALT351_320_OFFSET) +#define DMI_HALTSUM_HALT351_320 (0x1U << DMI_HALTSUM_HALT351_320_OFFSET) #define DMI_HALTSUM_HALT319_288_OFFSET 9 #define DMI_HALTSUM_HALT319_288_LENGTH 1 -#define DMI_HALTSUM_HALT319_288 (0x1 << DMI_HALTSUM_HALT319_288_OFFSET) +#define DMI_HALTSUM_HALT319_288 (0x1U << DMI_HALTSUM_HALT319_288_OFFSET) #define DMI_HALTSUM_HALT287_256_OFFSET 8 #define DMI_HALTSUM_HALT287_256_LENGTH 1 -#define DMI_HALTSUM_HALT287_256 (0x1 << DMI_HALTSUM_HALT287_256_OFFSET) +#define DMI_HALTSUM_HALT287_256 (0x1U << DMI_HALTSUM_HALT287_256_OFFSET) #define DMI_HALTSUM_HALT255_224_OFFSET 7 #define DMI_HALTSUM_HALT255_224_LENGTH 1 -#define DMI_HALTSUM_HALT255_224 (0x1 << DMI_HALTSUM_HALT255_224_OFFSET) +#define DMI_HALTSUM_HALT255_224 (0x1U << DMI_HALTSUM_HALT255_224_OFFSET) #define DMI_HALTSUM_HALT223_192_OFFSET 6 #define DMI_HALTSUM_HALT223_192_LENGTH 1 -#define DMI_HALTSUM_HALT223_192 (0x1 << DMI_HALTSUM_HALT223_192_OFFSET) +#define DMI_HALTSUM_HALT223_192 (0x1U << DMI_HALTSUM_HALT223_192_OFFSET) #define DMI_HALTSUM_HALT191_160_OFFSET 5 #define DMI_HALTSUM_HALT191_160_LENGTH 1 -#define DMI_HALTSUM_HALT191_160 (0x1 << DMI_HALTSUM_HALT191_160_OFFSET) +#define DMI_HALTSUM_HALT191_160 (0x1U << DMI_HALTSUM_HALT191_160_OFFSET) #define DMI_HALTSUM_HALT159_128_OFFSET 4 #define DMI_HALTSUM_HALT159_128_LENGTH 1 -#define DMI_HALTSUM_HALT159_128 (0x1 << DMI_HALTSUM_HALT159_128_OFFSET) +#define DMI_HALTSUM_HALT159_128 (0x1U << DMI_HALTSUM_HALT159_128_OFFSET) #define DMI_HALTSUM_HALT127_96_OFFSET 3 #define DMI_HALTSUM_HALT127_96_LENGTH 1 -#define DMI_HALTSUM_HALT127_96 (0x1 << DMI_HALTSUM_HALT127_96_OFFSET) +#define DMI_HALTSUM_HALT127_96 (0x1U << DMI_HALTSUM_HALT127_96_OFFSET) #define DMI_HALTSUM_HALT95_64_OFFSET 2 #define DMI_HALTSUM_HALT95_64_LENGTH 1 -#define DMI_HALTSUM_HALT95_64 (0x1 << DMI_HALTSUM_HALT95_64_OFFSET) +#define DMI_HALTSUM_HALT95_64 (0x1U << DMI_HALTSUM_HALT95_64_OFFSET) #define DMI_HALTSUM_HALT63_32_OFFSET 1 #define DMI_HALTSUM_HALT63_32_LENGTH 1 -#define DMI_HALTSUM_HALT63_32 (0x1 << DMI_HALTSUM_HALT63_32_OFFSET) +#define DMI_HALTSUM_HALT63_32 (0x1U << DMI_HALTSUM_HALT63_32_OFFSET) #define DMI_HALTSUM_HALT31_0_OFFSET 0 #define DMI_HALTSUM_HALT31_0_LENGTH 1 -#define DMI_HALTSUM_HALT31_0 (0x1 << DMI_HALTSUM_HALT31_0_OFFSET) +#define DMI_HALTSUM_HALT31_0 (0x1U << DMI_HALTSUM_HALT31_0_OFFSET) #define DMI_HAWINDOWSEL 0x14 #define DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET 0 #define DMI_HAWINDOWSEL_HAWINDOWSEL_LENGTH 5 -#define DMI_HAWINDOWSEL_HAWINDOWSEL (0x1f << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET) +#define DMI_HAWINDOWSEL_HAWINDOWSEL (0x1fU << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET) #define DMI_HAWINDOW 0x15 #define DMI_HAWINDOW_MASKDATA_OFFSET 0 #define DMI_HAWINDOW_MASKDATA_LENGTH 32 -#define DMI_HAWINDOW_MASKDATA (0xffffffff << DMI_HAWINDOW_MASKDATA_OFFSET) +#define DMI_HAWINDOW_MASKDATA (0xffffffffU << DMI_HAWINDOW_MASKDATA_OFFSET) #define DMI_ABSTRACTCS 0x16 /* * Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16. @@ -876,7 +897,7 @@ */ #define DMI_ABSTRACTCS_PROGSIZE_OFFSET 24 #define DMI_ABSTRACTCS_PROGSIZE_LENGTH 5 -#define DMI_ABSTRACTCS_PROGSIZE (0x1f << DMI_ABSTRACTCS_PROGSIZE_OFFSET) +#define DMI_ABSTRACTCS_PROGSIZE (0x1fU << DMI_ABSTRACTCS_PROGSIZE_OFFSET) /* * 1: An abstract command is currently being executed. * @@ -885,7 +906,7 @@ */ #define DMI_ABSTRACTCS_BUSY_OFFSET 12 #define DMI_ABSTRACTCS_BUSY_LENGTH 1 -#define DMI_ABSTRACTCS_BUSY (0x1 << DMI_ABSTRACTCS_BUSY_OFFSET) +#define DMI_ABSTRACTCS_BUSY (0x1U << DMI_ABSTRACTCS_BUSY_OFFSET) /* * Gets set if an abstract command fails. The bits in this field remain set until * they are cleared by writing 1 to them. No abstract command is @@ -911,14 +932,14 @@ */ #define DMI_ABSTRACTCS_CMDERR_OFFSET 8 #define DMI_ABSTRACTCS_CMDERR_LENGTH 3 -#define DMI_ABSTRACTCS_CMDERR (0x7 << DMI_ABSTRACTCS_CMDERR_OFFSET) +#define DMI_ABSTRACTCS_CMDERR (0x7U << DMI_ABSTRACTCS_CMDERR_OFFSET) /* * Number of {\tt data} registers that are implemented as part of the * abstract command interface. Valid sizes are 0 - 12. */ #define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0 #define DMI_ABSTRACTCS_DATACOUNT_LENGTH 5 -#define DMI_ABSTRACTCS_DATACOUNT (0x1f << DMI_ABSTRACTCS_DATACOUNT_OFFSET) +#define DMI_ABSTRACTCS_DATACOUNT (0x1fU << DMI_ABSTRACTCS_DATACOUNT_OFFSET) #define DMI_COMMAND 0x17 /* * The type determines the overall functionality of this @@ -926,14 +947,14 @@ */ #define DMI_COMMAND_CMDTYPE_OFFSET 24 #define DMI_COMMAND_CMDTYPE_LENGTH 8 -#define DMI_COMMAND_CMDTYPE (0xffu << DMI_COMMAND_CMDTYPE_OFFSET) +#define DMI_COMMAND_CMDTYPE (0xffU << DMI_COMMAND_CMDTYPE_OFFSET) /* * This field is interpreted in a command-specific manner, * described for each abstract command. */ #define DMI_COMMAND_CONTROL_OFFSET 0 #define DMI_COMMAND_CONTROL_LENGTH 24 -#define DMI_COMMAND_CONTROL (0xffffff << DMI_COMMAND_CONTROL_OFFSET) +#define DMI_COMMAND_CONTROL (0xffffffU << DMI_COMMAND_CONTROL_OFFSET) #define DMI_ABSTRACTAUTO 0x18 /* * When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word @@ -941,139 +962,35 @@ */ #define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16 #define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16 -#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffff << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET) +#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET) /* * When a bit in this field is 1, read or write accesses the corresponding {\tt data} word * cause the command in \Rcommand to be executed again. */ #define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0 #define DMI_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12 -#define DMI_ABSTRACTAUTO_AUTOEXECDATA (0xfff << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) -#define DMI_CFGSTRADDR0 0x19 -#define DMI_CFGSTRADDR0_ADDR_OFFSET 0 -#define DMI_CFGSTRADDR0_ADDR_LENGTH 32 -#define DMI_CFGSTRADDR0_ADDR (0xffffffff << DMI_CFGSTRADDR0_ADDR_OFFSET) -#define DMI_CFGSTRADDR1 0x1a -#define DMI_CFGSTRADDR2 0x1b -#define DMI_CFGSTRADDR3 0x1c +#define DMI_ABSTRACTAUTO_AUTOEXECDATA (0xfffU << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) +#define DMI_DEVTREEADDR0 0x19 +#define DMI_DEVTREEADDR0_ADDR_OFFSET 0 +#define DMI_DEVTREEADDR0_ADDR_LENGTH 32 +#define DMI_DEVTREEADDR0_ADDR (0xffffffffU << DMI_DEVTREEADDR0_ADDR_OFFSET) +#define DMI_DEVTREEADDR1 0x1a +#define DMI_DEVTREEADDR2 0x1b +#define DMI_DEVTREEADDR3 0x1c #define DMI_DATA0 0x04 #define DMI_DATA0_DATA_OFFSET 0 #define DMI_DATA0_DATA_LENGTH 32 -#define DMI_DATA0_DATA (0xffffffff << DMI_DATA0_DATA_OFFSET) +#define DMI_DATA0_DATA (0xffffffffU << DMI_DATA0_DATA_OFFSET) #define DMI_DATA11 0x0f #define DMI_PROGBUF0 0x20 #define DMI_PROGBUF0_DATA_OFFSET 0 #define DMI_PROGBUF0_DATA_LENGTH 32 -#define DMI_PROGBUF0_DATA (0xffffffff << DMI_PROGBUF0_DATA_OFFSET) +#define DMI_PROGBUF0_DATA (0xffffffffU << DMI_PROGBUF0_DATA_OFFSET) #define DMI_PROGBUF15 0x2f #define DMI_AUTHDATA 0x30 #define DMI_AUTHDATA_DATA_OFFSET 0 #define DMI_AUTHDATA_DATA_LENGTH 32 -#define DMI_AUTHDATA_DATA (0xffffffff << DMI_AUTHDATA_DATA_OFFSET) -#define DMI_SERCS 0x34 -/* -* Number of supported serial ports. - */ -#define DMI_SERCS_SERIALCOUNT_OFFSET 28 -#define DMI_SERCS_SERIALCOUNT_LENGTH 4 -#define DMI_SERCS_SERIALCOUNT (0xf << DMI_SERCS_SERIALCOUNT_OFFSET) -/* -* Select which serial port is accessed by \Rserrx and \Rsertx. - */ -#define DMI_SERCS_SERIAL_OFFSET 24 -#define DMI_SERCS_SERIAL_LENGTH 3 -#define DMI_SERCS_SERIAL (0x7 << DMI_SERCS_SERIAL_OFFSET) -#define DMI_SERCS_ERROR7_OFFSET 23 -#define DMI_SERCS_ERROR7_LENGTH 1 -#define DMI_SERCS_ERROR7 (0x1 << DMI_SERCS_ERROR7_OFFSET) -#define DMI_SERCS_VALID7_OFFSET 22 -#define DMI_SERCS_VALID7_LENGTH 1 -#define DMI_SERCS_VALID7 (0x1 << DMI_SERCS_VALID7_OFFSET) -#define DMI_SERCS_FULL7_OFFSET 21 -#define DMI_SERCS_FULL7_LENGTH 1 -#define DMI_SERCS_FULL7 (0x1 << DMI_SERCS_FULL7_OFFSET) -#define DMI_SERCS_ERROR6_OFFSET 20 -#define DMI_SERCS_ERROR6_LENGTH 1 -#define DMI_SERCS_ERROR6 (0x1 << DMI_SERCS_ERROR6_OFFSET) -#define DMI_SERCS_VALID6_OFFSET 19 -#define DMI_SERCS_VALID6_LENGTH 1 -#define DMI_SERCS_VALID6 (0x1 << DMI_SERCS_VALID6_OFFSET) -#define DMI_SERCS_FULL6_OFFSET 18 -#define DMI_SERCS_FULL6_LENGTH 1 -#define DMI_SERCS_FULL6 (0x1 << DMI_SERCS_FULL6_OFFSET) -#define DMI_SERCS_ERROR5_OFFSET 17 -#define DMI_SERCS_ERROR5_LENGTH 1 -#define DMI_SERCS_ERROR5 (0x1 << DMI_SERCS_ERROR5_OFFSET) -#define DMI_SERCS_VALID5_OFFSET 16 -#define DMI_SERCS_VALID5_LENGTH 1 -#define DMI_SERCS_VALID5 (0x1 << DMI_SERCS_VALID5_OFFSET) -#define DMI_SERCS_FULL5_OFFSET 15 -#define DMI_SERCS_FULL5_LENGTH 1 -#define DMI_SERCS_FULL5 (0x1 << DMI_SERCS_FULL5_OFFSET) -#define DMI_SERCS_ERROR4_OFFSET 14 -#define DMI_SERCS_ERROR4_LENGTH 1 -#define DMI_SERCS_ERROR4 (0x1 << DMI_SERCS_ERROR4_OFFSET) -#define DMI_SERCS_VALID4_OFFSET 13 -#define DMI_SERCS_VALID4_LENGTH 1 -#define DMI_SERCS_VALID4 (0x1 << DMI_SERCS_VALID4_OFFSET) -#define DMI_SERCS_FULL4_OFFSET 12 -#define DMI_SERCS_FULL4_LENGTH 1 -#define DMI_SERCS_FULL4 (0x1 << DMI_SERCS_FULL4_OFFSET) -#define DMI_SERCS_ERROR3_OFFSET 11 -#define DMI_SERCS_ERROR3_LENGTH 1 -#define DMI_SERCS_ERROR3 (0x1 << DMI_SERCS_ERROR3_OFFSET) -#define DMI_SERCS_VALID3_OFFSET 10 -#define DMI_SERCS_VALID3_LENGTH 1 -#define DMI_SERCS_VALID3 (0x1 << DMI_SERCS_VALID3_OFFSET) -#define DMI_SERCS_FULL3_OFFSET 9 -#define DMI_SERCS_FULL3_LENGTH 1 -#define DMI_SERCS_FULL3 (0x1 << DMI_SERCS_FULL3_OFFSET) -#define DMI_SERCS_ERROR2_OFFSET 8 -#define DMI_SERCS_ERROR2_LENGTH 1 -#define DMI_SERCS_ERROR2 (0x1 << DMI_SERCS_ERROR2_OFFSET) -#define DMI_SERCS_VALID2_OFFSET 7 -#define DMI_SERCS_VALID2_LENGTH 1 -#define DMI_SERCS_VALID2 (0x1 << DMI_SERCS_VALID2_OFFSET) -#define DMI_SERCS_FULL2_OFFSET 6 -#define DMI_SERCS_FULL2_LENGTH 1 -#define DMI_SERCS_FULL2 (0x1 << DMI_SERCS_FULL2_OFFSET) -#define DMI_SERCS_ERROR1_OFFSET 5 -#define DMI_SERCS_ERROR1_LENGTH 1 -#define DMI_SERCS_ERROR1 (0x1 << DMI_SERCS_ERROR1_OFFSET) -#define DMI_SERCS_VALID1_OFFSET 4 -#define DMI_SERCS_VALID1_LENGTH 1 -#define DMI_SERCS_VALID1 (0x1 << DMI_SERCS_VALID1_OFFSET) -#define DMI_SERCS_FULL1_OFFSET 3 -#define DMI_SERCS_FULL1_LENGTH 1 -#define DMI_SERCS_FULL1 (0x1 << DMI_SERCS_FULL1_OFFSET) -/* -* 1 when the debugger-to-core queue for serial port 0 has -* over or underflowed. This bit will remain set until it is reset by -* writing 1 to this bit. - */ -#define DMI_SERCS_ERROR0_OFFSET 2 -#define DMI_SERCS_ERROR0_LENGTH 1 -#define DMI_SERCS_ERROR0 (0x1 << DMI_SERCS_ERROR0_OFFSET) -/* -* 1 when the core-to-debugger queue for serial port 0 is not empty. - */ -#define DMI_SERCS_VALID0_OFFSET 1 -#define DMI_SERCS_VALID0_LENGTH 1 -#define DMI_SERCS_VALID0 (0x1 << DMI_SERCS_VALID0_OFFSET) -/* -* 1 when the debugger-to-core queue for serial port 0 is full. - */ -#define DMI_SERCS_FULL0_OFFSET 0 -#define DMI_SERCS_FULL0_LENGTH 1 -#define DMI_SERCS_FULL0 (0x1 << DMI_SERCS_FULL0_OFFSET) -#define DMI_SERTX 0x35 -#define DMI_SERTX_DATA_OFFSET 0 -#define DMI_SERTX_DATA_LENGTH 32 -#define DMI_SERTX_DATA (0xffffffff << DMI_SERTX_DATA_OFFSET) -#define DMI_SERRX 0x36 -#define DMI_SERRX_DATA_OFFSET 0 -#define DMI_SERRX_DATA_LENGTH 32 -#define DMI_SERRX_DATA (0xffffffff << DMI_SERRX_DATA_OFFSET) +#define DMI_AUTHDATA_DATA (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET) #define DMI_SBCS 0x38 /* * When a 1 is written here, triggers a read at the address in {\tt @@ -1081,7 +998,7 @@ */ #define DMI_SBCS_SBSINGLEREAD_OFFSET 20 #define DMI_SBCS_SBSINGLEREAD_LENGTH 1 -#define DMI_SBCS_SBSINGLEREAD (0x1 << DMI_SBCS_SBSINGLEREAD_OFFSET) +#define DMI_SBCS_SBSINGLEREAD (0x1U << DMI_SBCS_SBSINGLEREAD_OFFSET) /* * Select the access size to use for system bus accesses triggered by * writes to the {\tt sbaddress} registers or \Rsbdatazero. @@ -1102,7 +1019,7 @@ */ #define DMI_SBCS_SBACCESS_OFFSET 17 #define DMI_SBCS_SBACCESS_LENGTH 3 -#define DMI_SBCS_SBACCESS (0x7 << DMI_SBCS_SBACCESS_OFFSET) +#define DMI_SBCS_SBACCESS (0x7U << DMI_SBCS_SBACCESS_OFFSET) /* * When 1, the internal address value (used by the system bus master) * is incremented by the access size (in bytes) selected in \Fsbaccess @@ -1110,14 +1027,14 @@ */ #define DMI_SBCS_SBAUTOINCREMENT_OFFSET 16 #define DMI_SBCS_SBAUTOINCREMENT_LENGTH 1 -#define DMI_SBCS_SBAUTOINCREMENT (0x1 << DMI_SBCS_SBAUTOINCREMENT_OFFSET) +#define DMI_SBCS_SBAUTOINCREMENT (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET) /* * When 1, every read from \Rsbdatazero automatically triggers a system * bus read at the new address. */ #define DMI_SBCS_SBAUTOREAD_OFFSET 15 #define DMI_SBCS_SBAUTOREAD_LENGTH 1 -#define DMI_SBCS_SBAUTOREAD (0x1 << DMI_SBCS_SBAUTOREAD_OFFSET) +#define DMI_SBCS_SBAUTOREAD (0x1U << DMI_SBCS_SBAUTOREAD_OFFSET) /* * When the debug module's system bus * master causes a bus error, this field gets set. The bits in this @@ -1140,51 +1057,51 @@ */ #define DMI_SBCS_SBERROR_OFFSET 12 #define DMI_SBCS_SBERROR_LENGTH 3 -#define DMI_SBCS_SBERROR (0x7 << DMI_SBCS_SBERROR_OFFSET) +#define DMI_SBCS_SBERROR (0x7U << DMI_SBCS_SBERROR_OFFSET) /* * Width of system bus addresses in bits. (0 indicates there is no bus * access support.) */ #define DMI_SBCS_SBASIZE_OFFSET 5 #define DMI_SBCS_SBASIZE_LENGTH 7 -#define DMI_SBCS_SBASIZE (0x7f << DMI_SBCS_SBASIZE_OFFSET) +#define DMI_SBCS_SBASIZE (0x7fU << DMI_SBCS_SBASIZE_OFFSET) /* * 1 when 128-bit system bus accesses are supported. */ #define DMI_SBCS_SBACCESS128_OFFSET 4 #define DMI_SBCS_SBACCESS128_LENGTH 1 -#define DMI_SBCS_SBACCESS128 (0x1 << DMI_SBCS_SBACCESS128_OFFSET) +#define DMI_SBCS_SBACCESS128 (0x1U << DMI_SBCS_SBACCESS128_OFFSET) /* * 1 when 64-bit system bus accesses are supported. */ #define DMI_SBCS_SBACCESS64_OFFSET 3 #define DMI_SBCS_SBACCESS64_LENGTH 1 -#define DMI_SBCS_SBACCESS64 (0x1 << DMI_SBCS_SBACCESS64_OFFSET) +#define DMI_SBCS_SBACCESS64 (0x1U << DMI_SBCS_SBACCESS64_OFFSET) /* * 1 when 32-bit system bus accesses are supported. */ #define DMI_SBCS_SBACCESS32_OFFSET 2 #define DMI_SBCS_SBACCESS32_LENGTH 1 -#define DMI_SBCS_SBACCESS32 (0x1 << DMI_SBCS_SBACCESS32_OFFSET) +#define DMI_SBCS_SBACCESS32 (0x1U << DMI_SBCS_SBACCESS32_OFFSET) /* * 1 when 16-bit system bus accesses are supported. */ #define DMI_SBCS_SBACCESS16_OFFSET 1 #define DMI_SBCS_SBACCESS16_LENGTH 1 -#define DMI_SBCS_SBACCESS16 (0x1 << DMI_SBCS_SBACCESS16_OFFSET) +#define DMI_SBCS_SBACCESS16 (0x1U << DMI_SBCS_SBACCESS16_OFFSET) /* * 1 when 8-bit system bus accesses are supported. */ #define DMI_SBCS_SBACCESS8_OFFSET 0 #define DMI_SBCS_SBACCESS8_LENGTH 1 -#define DMI_SBCS_SBACCESS8 (0x1 << DMI_SBCS_SBACCESS8_OFFSET) +#define DMI_SBCS_SBACCESS8 (0x1U << DMI_SBCS_SBACCESS8_OFFSET) #define DMI_SBADDRESS0 0x39 /* * Accesses bits 31:0 of the internal address. */ #define DMI_SBADDRESS0_ADDRESS_OFFSET 0 #define DMI_SBADDRESS0_ADDRESS_LENGTH 32 -#define DMI_SBADDRESS0_ADDRESS (0xffffffff << DMI_SBADDRESS0_ADDRESS_OFFSET) +#define DMI_SBADDRESS0_ADDRESS (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET) #define DMI_SBADDRESS1 0x3a /* * Accesses bits 63:32 of the internal address (if the system address @@ -1192,7 +1109,7 @@ */ #define DMI_SBADDRESS1_ADDRESS_OFFSET 0 #define DMI_SBADDRESS1_ADDRESS_LENGTH 32 -#define DMI_SBADDRESS1_ADDRESS (0xffffffff << DMI_SBADDRESS1_ADDRESS_OFFSET) +#define DMI_SBADDRESS1_ADDRESS (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET) #define DMI_SBADDRESS2 0x3b /* * Accesses bits 95:64 of the internal address (if the system address @@ -1200,14 +1117,14 @@ */ #define DMI_SBADDRESS2_ADDRESS_OFFSET 0 #define DMI_SBADDRESS2_ADDRESS_LENGTH 32 -#define DMI_SBADDRESS2_ADDRESS (0xffffffff << DMI_SBADDRESS2_ADDRESS_OFFSET) +#define DMI_SBADDRESS2_ADDRESS (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET) #define DMI_SBDATA0 0x3c /* * Accesses bits 31:0 of the internal data. */ #define DMI_SBDATA0_DATA_OFFSET 0 #define DMI_SBDATA0_DATA_LENGTH 32 -#define DMI_SBDATA0_DATA (0xffffffff << DMI_SBDATA0_DATA_OFFSET) +#define DMI_SBDATA0_DATA (0xffffffffU << DMI_SBDATA0_DATA_OFFSET) #define DMI_SBDATA1 0x3d /* * Accesses bits 63:32 of the internal data (if the system bus is @@ -1215,7 +1132,7 @@ */ #define DMI_SBDATA1_DATA_OFFSET 0 #define DMI_SBDATA1_DATA_LENGTH 32 -#define DMI_SBDATA1_DATA (0xffffffff << DMI_SBDATA1_DATA_OFFSET) +#define DMI_SBDATA1_DATA (0xffffffffU << DMI_SBDATA1_DATA_OFFSET) #define DMI_SBDATA2 0x3e /* * Accesses bits 95:64 of the internal data (if the system bus is @@ -1223,7 +1140,7 @@ */ #define DMI_SBDATA2_DATA_OFFSET 0 #define DMI_SBDATA2_DATA_LENGTH 32 -#define DMI_SBDATA2_DATA (0xffffffff << DMI_SBDATA2_DATA_OFFSET) +#define DMI_SBDATA2_DATA (0xffffffffU << DMI_SBDATA2_DATA_OFFSET) #define DMI_SBDATA3 0x3f /* * Accesses bits 127:96 of the internal data (if the system bus is @@ -1231,125 +1148,21 @@ */ #define DMI_SBDATA3_DATA_OFFSET 0 #define DMI_SBDATA3_DATA_LENGTH 32 -#define DMI_SBDATA3_DATA (0xffffffff << DMI_SBDATA3_DATA_OFFSET) -#define TRACE 0x728 -/* -* 1 if the trace buffer has wrapped since the last time \Fdiscard was -* written. 0 otherwise. - */ -#define TRACE_WRAPPED_OFFSET 24 -#define TRACE_WRAPPED_LENGTH 1 -#define TRACE_WRAPPED (0x1 << TRACE_WRAPPED_OFFSET) -/* -* Emit Timestamp trace sequences. - */ -#define TRACE_EMITTIMESTAMP_OFFSET 23 -#define TRACE_EMITTIMESTAMP_LENGTH 1 -#define TRACE_EMITTIMESTAMP (0x1 << TRACE_EMITTIMESTAMP_OFFSET) -/* -* Emit Store Data trace sequences. - */ -#define TRACE_EMITSTOREDATA_OFFSET 22 -#define TRACE_EMITSTOREDATA_LENGTH 1 -#define TRACE_EMITSTOREDATA (0x1 << TRACE_EMITSTOREDATA_OFFSET) -/* -* Emit Load Data trace sequences. - */ -#define TRACE_EMITLOADDATA_OFFSET 21 -#define TRACE_EMITLOADDATA_LENGTH 1 -#define TRACE_EMITLOADDATA (0x1 << TRACE_EMITLOADDATA_OFFSET) -/* -* Emit Store Address trace sequences. - */ -#define TRACE_EMITSTOREADDR_OFFSET 20 -#define TRACE_EMITSTOREADDR_LENGTH 1 -#define TRACE_EMITSTOREADDR (0x1 << TRACE_EMITSTOREADDR_OFFSET) -/* -* Emit Load Address trace sequences. - */ -#define TRACE_EMITLOADADDR_OFFSET 19 -#define TRACE_EMITLOADADDR_LENGTH 1 -#define TRACE_EMITLOADADDR (0x1 << TRACE_EMITLOADADDR_OFFSET) -/* -* Emit Privilege Level trace sequences. - */ -#define TRACE_EMITPRIV_OFFSET 18 -#define TRACE_EMITPRIV_LENGTH 1 -#define TRACE_EMITPRIV (0x1 << TRACE_EMITPRIV_OFFSET) -/* -* Emit Branch Taken and Branch Not Taken trace sequences. - */ -#define TRACE_EMITBRANCH_OFFSET 17 -#define TRACE_EMITBRANCH_LENGTH 1 -#define TRACE_EMITBRANCH (0x1 << TRACE_EMITBRANCH_OFFSET) -/* -* Emit PC trace sequences. - */ -#define TRACE_EMITPC_OFFSET 16 -#define TRACE_EMITPC_LENGTH 1 -#define TRACE_EMITPC (0x1 << TRACE_EMITPC_OFFSET) -/* -* Determine what happens when the trace buffer is full. 0 means wrap -* and overwrite. 1 means turn off trace until \Fdiscard is written as 1. -* 2 means cause a trace full exception. 3 is reserved for future use. - */ -#define TRACE_FULLACTION_OFFSET 8 -#define TRACE_FULLACTION_LENGTH 2 -#define TRACE_FULLACTION (0x3 << TRACE_FULLACTION_OFFSET) -/* -* 0: Trace to a dedicated on-core RAM (which is not further defined in -* this spec). -* -* 1: Trace to RAM on the system bus. -* -* 2: Send trace data to a dedicated off-chip interface (which is not -* defined in this spec). This does not affect execution speed. -* -* 3: Reserved for future use. -* -* Options 0 and 1 slow down execution (eg. because of system bus -* contention). - */ -#define TRACE_DESTINATION_OFFSET 4 -#define TRACE_DESTINATION_LENGTH 2 -#define TRACE_DESTINATION (0x3 << TRACE_DESTINATION_OFFSET) -/* -* When 1, the trace logic may stall processor execution to ensure it -* can emit all the trace sequences required. When 0 individual trace -* sequences may be dropped. - */ -#define TRACE_STALL_OFFSET 2 -#define TRACE_STALL_LENGTH 1 -#define TRACE_STALL (0x1 << TRACE_STALL_OFFSET) -/* -* Writing 1 to this bit tells the trace logic that any trace -* collected is no longer required. When tracing to RAM, it resets the -* trace write pointer to the start of the memory, as well as -* \Fwrapped. - */ -#define TRACE_DISCARD_OFFSET 1 -#define TRACE_DISCARD_LENGTH 1 -#define TRACE_DISCARD (0x1 << TRACE_DISCARD_OFFSET) -#define TRACE_SUPPORTED_OFFSET 0 -#define TRACE_SUPPORTED_LENGTH 1 -#define TRACE_SUPPORTED (0x1 << TRACE_SUPPORTED_OFFSET) -#define TBUFSTART 0x729 -#define TBUFEND 0x72a -#define TBUFWRITE 0x72b +#define DMI_SBDATA3_DATA (0xffffffffU << DMI_SBDATA3_DATA_OFFSET) #define SHORTNAME 0x123 /* * Description of what this field is used for. */ #define SHORTNAME_FIELD_OFFSET 0 #define SHORTNAME_FIELD_LENGTH 8 -#define SHORTNAME_FIELD (0xff << SHORTNAME_FIELD_OFFSET) +#define SHORTNAME_FIELD (0xffU << SHORTNAME_FIELD_OFFSET) #define AC_ACCESS_REGISTER None /* * This is 0 to indicate Access Register Command. */ #define AC_ACCESS_REGISTER_CMDTYPE_OFFSET 24 #define AC_ACCESS_REGISTER_CMDTYPE_LENGTH 8 -#define AC_ACCESS_REGISTER_CMDTYPE (0xff << AC_ACCESS_REGISTER_CMDTYPE_OFFSET) +#define AC_ACCESS_REGISTER_CMDTYPE (0xffU << AC_ACCESS_REGISTER_CMDTYPE_OFFSET) /* * 2: Access the lowest 32 bits of the register. * @@ -1363,14 +1176,14 @@ */ #define AC_ACCESS_REGISTER_SIZE_OFFSET 20 #define AC_ACCESS_REGISTER_SIZE_LENGTH 3 -#define AC_ACCESS_REGISTER_SIZE (0x7 << AC_ACCESS_REGISTER_SIZE_OFFSET) +#define AC_ACCESS_REGISTER_SIZE (0x7U << AC_ACCESS_REGISTER_SIZE_OFFSET) /* * When 1, execute the program in the Program Buffer exactly once * after performing the transfer, if any. */ #define AC_ACCESS_REGISTER_POSTEXEC_OFFSET 18 #define AC_ACCESS_REGISTER_POSTEXEC_LENGTH 1 -#define AC_ACCESS_REGISTER_POSTEXEC (0x1 << AC_ACCESS_REGISTER_POSTEXEC_OFFSET) +#define AC_ACCESS_REGISTER_POSTEXEC (0x1U << AC_ACCESS_REGISTER_POSTEXEC_OFFSET) /* * 0: Don't do the operation specified by \Fwrite. * @@ -1378,7 +1191,7 @@ */ #define AC_ACCESS_REGISTER_TRANSFER_OFFSET 17 #define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1 -#define AC_ACCESS_REGISTER_TRANSFER (0x1 << AC_ACCESS_REGISTER_TRANSFER_OFFSET) +#define AC_ACCESS_REGISTER_TRANSFER (0x1U << AC_ACCESS_REGISTER_TRANSFER_OFFSET) /* * When \Ftransfer is set: * 0: Copy data from the specified register into {\tt arg0} portion @@ -1389,7 +1202,7 @@ */ #define AC_ACCESS_REGISTER_WRITE_OFFSET 16 #define AC_ACCESS_REGISTER_WRITE_LENGTH 1 -#define AC_ACCESS_REGISTER_WRITE (0x1 << AC_ACCESS_REGISTER_WRITE_OFFSET) +#define AC_ACCESS_REGISTER_WRITE (0x1U << AC_ACCESS_REGISTER_WRITE_OFFSET) /* * Number of the register to access, as described in * Table~\ref{tab:regno}. @@ -1398,14 +1211,14 @@ */ #define AC_ACCESS_REGISTER_REGNO_OFFSET 0 #define AC_ACCESS_REGISTER_REGNO_LENGTH 16 -#define AC_ACCESS_REGISTER_REGNO (0xffff << AC_ACCESS_REGISTER_REGNO_OFFSET) +#define AC_ACCESS_REGISTER_REGNO (0xffffU << AC_ACCESS_REGISTER_REGNO_OFFSET) #define AC_QUICK_ACCESS None /* * This is 1 to indicate Quick Access command. */ #define AC_QUICK_ACCESS_CMDTYPE_OFFSET 24 #define AC_QUICK_ACCESS_CMDTYPE_LENGTH 8 -#define AC_QUICK_ACCESS_CMDTYPE (0xff << AC_QUICK_ACCESS_CMDTYPE_OFFSET) +#define AC_QUICK_ACCESS_CMDTYPE (0xffU << AC_QUICK_ACCESS_CMDTYPE_OFFSET) #define VIRT_PRIV virtual /* * Contains the privilege level the hart was operating in when Debug @@ -1415,4 +1228,108 @@ */ #define VIRT_PRIV_PRV_OFFSET 0 #define VIRT_PRIV_PRV_LENGTH 2 -#define VIRT_PRIV_PRV (0x3 << VIRT_PRIV_PRV_OFFSET) +#define VIRT_PRIV_PRV (0x3U << VIRT_PRIV_PRV_OFFSET) +#define DMI_SERCS 0x34 +/* +* Number of supported serial ports. + */ +#define DMI_SERCS_SERIALCOUNT_OFFSET 28 +#define DMI_SERCS_SERIALCOUNT_LENGTH 4 +#define DMI_SERCS_SERIALCOUNT (0xfU << DMI_SERCS_SERIALCOUNT_OFFSET) +/* +* Select which serial port is accessed by \Rserrx and \Rsertx. + */ +#define DMI_SERCS_SERIAL_OFFSET 24 +#define DMI_SERCS_SERIAL_LENGTH 3 +#define DMI_SERCS_SERIAL (0x7U << DMI_SERCS_SERIAL_OFFSET) +#define DMI_SERCS_ERROR7_OFFSET 23 +#define DMI_SERCS_ERROR7_LENGTH 1 +#define DMI_SERCS_ERROR7 (0x1U << DMI_SERCS_ERROR7_OFFSET) +#define DMI_SERCS_VALID7_OFFSET 22 +#define DMI_SERCS_VALID7_LENGTH 1 +#define DMI_SERCS_VALID7 (0x1U << DMI_SERCS_VALID7_OFFSET) +#define DMI_SERCS_FULL7_OFFSET 21 +#define DMI_SERCS_FULL7_LENGTH 1 +#define DMI_SERCS_FULL7 (0x1U << DMI_SERCS_FULL7_OFFSET) +#define DMI_SERCS_ERROR6_OFFSET 20 +#define DMI_SERCS_ERROR6_LENGTH 1 +#define DMI_SERCS_ERROR6 (0x1U << DMI_SERCS_ERROR6_OFFSET) +#define DMI_SERCS_VALID6_OFFSET 19 +#define DMI_SERCS_VALID6_LENGTH 1 +#define DMI_SERCS_VALID6 (0x1U << DMI_SERCS_VALID6_OFFSET) +#define DMI_SERCS_FULL6_OFFSET 18 +#define DMI_SERCS_FULL6_LENGTH 1 +#define DMI_SERCS_FULL6 (0x1U << DMI_SERCS_FULL6_OFFSET) +#define DMI_SERCS_ERROR5_OFFSET 17 +#define DMI_SERCS_ERROR5_LENGTH 1 +#define DMI_SERCS_ERROR5 (0x1U << DMI_SERCS_ERROR5_OFFSET) +#define DMI_SERCS_VALID5_OFFSET 16 +#define DMI_SERCS_VALID5_LENGTH 1 +#define DMI_SERCS_VALID5 (0x1U << DMI_SERCS_VALID5_OFFSET) +#define DMI_SERCS_FULL5_OFFSET 15 +#define DMI_SERCS_FULL5_LENGTH 1 +#define DMI_SERCS_FULL5 (0x1U << DMI_SERCS_FULL5_OFFSET) +#define DMI_SERCS_ERROR4_OFFSET 14 +#define DMI_SERCS_ERROR4_LENGTH 1 +#define DMI_SERCS_ERROR4 (0x1U << DMI_SERCS_ERROR4_OFFSET) +#define DMI_SERCS_VALID4_OFFSET 13 +#define DMI_SERCS_VALID4_LENGTH 1 +#define DMI_SERCS_VALID4 (0x1U << DMI_SERCS_VALID4_OFFSET) +#define DMI_SERCS_FULL4_OFFSET 12 +#define DMI_SERCS_FULL4_LENGTH 1 +#define DMI_SERCS_FULL4 (0x1U << DMI_SERCS_FULL4_OFFSET) +#define DMI_SERCS_ERROR3_OFFSET 11 +#define DMI_SERCS_ERROR3_LENGTH 1 +#define DMI_SERCS_ERROR3 (0x1U << DMI_SERCS_ERROR3_OFFSET) +#define DMI_SERCS_VALID3_OFFSET 10 +#define DMI_SERCS_VALID3_LENGTH 1 +#define DMI_SERCS_VALID3 (0x1U << DMI_SERCS_VALID3_OFFSET) +#define DMI_SERCS_FULL3_OFFSET 9 +#define DMI_SERCS_FULL3_LENGTH 1 +#define DMI_SERCS_FULL3 (0x1U << DMI_SERCS_FULL3_OFFSET) +#define DMI_SERCS_ERROR2_OFFSET 8 +#define DMI_SERCS_ERROR2_LENGTH 1 +#define DMI_SERCS_ERROR2 (0x1U << DMI_SERCS_ERROR2_OFFSET) +#define DMI_SERCS_VALID2_OFFSET 7 +#define DMI_SERCS_VALID2_LENGTH 1 +#define DMI_SERCS_VALID2 (0x1U << DMI_SERCS_VALID2_OFFSET) +#define DMI_SERCS_FULL2_OFFSET 6 +#define DMI_SERCS_FULL2_LENGTH 1 +#define DMI_SERCS_FULL2 (0x1U << DMI_SERCS_FULL2_OFFSET) +#define DMI_SERCS_ERROR1_OFFSET 5 +#define DMI_SERCS_ERROR1_LENGTH 1 +#define DMI_SERCS_ERROR1 (0x1U << DMI_SERCS_ERROR1_OFFSET) +#define DMI_SERCS_VALID1_OFFSET 4 +#define DMI_SERCS_VALID1_LENGTH 1 +#define DMI_SERCS_VALID1 (0x1U << DMI_SERCS_VALID1_OFFSET) +#define DMI_SERCS_FULL1_OFFSET 3 +#define DMI_SERCS_FULL1_LENGTH 1 +#define DMI_SERCS_FULL1 (0x1U << DMI_SERCS_FULL1_OFFSET) +/* +* 1 when the debugger-to-core queue for serial port 0 has +* over or underflowed. This bit will remain set until it is reset by +* writing 1 to this bit. + */ +#define DMI_SERCS_ERROR0_OFFSET 2 +#define DMI_SERCS_ERROR0_LENGTH 1 +#define DMI_SERCS_ERROR0 (0x1U << DMI_SERCS_ERROR0_OFFSET) +/* +* 1 when the core-to-debugger queue for serial port 0 is not empty. + */ +#define DMI_SERCS_VALID0_OFFSET 1 +#define DMI_SERCS_VALID0_LENGTH 1 +#define DMI_SERCS_VALID0 (0x1U << DMI_SERCS_VALID0_OFFSET) +/* +* 1 when the debugger-to-core queue for serial port 0 is full. + */ +#define DMI_SERCS_FULL0_OFFSET 0 +#define DMI_SERCS_FULL0_LENGTH 1 +#define DMI_SERCS_FULL0 (0x1U << DMI_SERCS_FULL0_OFFSET) +#define DMI_SERTX 0x35 +#define DMI_SERTX_DATA_OFFSET 0 +#define DMI_SERTX_DATA_LENGTH 32 +#define DMI_SERTX_DATA (0xffffffffU << DMI_SERTX_DATA_OFFSET) +#define DMI_SERRX 0x36 +#define DMI_SERRX_DATA_OFFSET 0 +#define DMI_SERRX_DATA_LENGTH 32 +#define DMI_SERRX_DATA (0xffffffffU << DMI_SERRX_DATA_OFFSET) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 1b3e39cd9..9342a7dee 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -217,7 +217,7 @@ static void decode_dmi(char *text, unsigned address, unsigned data) { DMI_DMSTATUS, DMI_DMSTATUS_ANYHALTED, "anyhalted" }, { DMI_DMSTATUS, DMI_DMSTATUS_AUTHENTICATED, "authenticated" }, { DMI_DMSTATUS, DMI_DMSTATUS_AUTHBUSY, "authbusy" }, - { DMI_DMSTATUS, DMI_DMSTATUS_CFGSTRVALID, "cfgstrvalid" }, + { DMI_DMSTATUS, DMI_DMSTATUS_DEVTREEVALID, "devtreevalid" }, { DMI_DMSTATUS, DMI_DMSTATUS_VERSION, "version" }, { DMI_ABSTRACTCS, DMI_ABSTRACTCS_PROGSIZE, "progsize" }, From ed9a04bde9c7bf3cf8b20f51f842e7a0051b5556 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 14:35:47 -0700 Subject: [PATCH 50/68] Remove unnecessary abs(). --- src/target/riscv/program.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index 294e673ea..055bfdbaf 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -478,7 +478,7 @@ riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr) riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr) { - return ((addr > 0) ? 1 : 0) * (abs(addr) & 0x7FF); + return ((addr > 0) ? 1 : 0) * (addr & 0x7FF); } int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) From 60354cbea29c88884f3b99b40bfa257b047717b1 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 18 Sep 2017 14:56:46 -0700 Subject: [PATCH 51/68] clang fix, don't allow unaligned uint64_t pointers --- src/target/riscv/batch.c | 13 ++++++++++--- src/target/riscv/batch.h | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index 56d51a19c..1e6a4be92 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -103,7 +103,7 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) batch->read_keys[batch->read_keys_used] = batch->used_scans - 1; LOG_DEBUG("read key %u for batch 0x%p is %u (0x%p)", (unsigned) batch->read_keys_used, batch, (unsigned) (batch->used_scans - 1), - (uint64_t*)batch->data_in + (batch->used_scans + 1)); + batch->data_in + sizeof(uint64_t) * (batch->used_scans + 1)); return batch->read_keys_used++; } @@ -112,8 +112,15 @@ uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key) assert(key < batch->read_keys_used); size_t index = batch->read_keys[key]; assert(index <= batch->used_scans); - uint64_t *addr = ((uint64_t *)(batch->data_in) + index); - return *addr; + uint8_t *base = batch->data_in + 8 * index; + return base[0] | + ((uint64_t) base[1]) << 8 | + ((uint64_t) base[2]) << 16 | + ((uint64_t) base[3]) << 24 | + ((uint64_t) base[4]) << 32 | + ((uint64_t) base[5]) << 40 | + ((uint64_t) base[6]) << 48 | + ((uint64_t) base[7]) << 56; } void riscv_batch_add_nop(struct riscv_batch *batch) diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 776d93a79..835829b2b 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -23,8 +23,8 @@ struct riscv_batch { size_t idle_count; - char *data_out; - char *data_in; + uint8_t *data_out; + uint8_t *data_in; struct scan_field *fields; /* In JTAG we scan out the previous value's output when performing a From 848fe0ffcfbaace31f410f8699e1fe7590bacc10 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 19 Sep 2017 15:04:00 -0700 Subject: [PATCH 52/68] Cleaning up single-hart reset. --- src/target/riscv/riscv-013.c | 113 ++++++++++++++++------------------- src/target/riscv/riscv.c | 77 ++---------------------- src/target/riscv/riscv.h | 3 - 3 files changed, 54 insertions(+), 139 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 66d9602a1..c5a2420ba 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -63,7 +63,6 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); static int riscv013_dmi_write_u64_bits(struct target *target); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); -static void riscv013_reset_current_hart(struct target *target); /** * Since almost everything can be accomplish by scanning the dbus register, all @@ -904,7 +903,6 @@ static int init_target(struct command_context *cmd_ctx, generic_info->fill_dmi_read_u64 = &riscv013_fill_dmi_read_u64; generic_info->fill_dmi_nop_u64 = &riscv013_fill_dmi_nop_u64; generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits; - generic_info->reset_current_hart = &riscv013_reset_current_hart; generic_info->version_specific = calloc(1, sizeof(riscv013_info_t)); if (!generic_info->version_specific) return ERROR_FAIL; @@ -1192,19 +1190,19 @@ static int assert_reset(struct target *target) assert(r->current_hartid == 0); select_dmi(target); - LOG_DEBUG("ASSERTING NDRESET"); - uint32_t control = dmi_read(target, DMI_DMCONTROL); - control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); - if (target->reset_halt) { - LOG_DEBUG("TARGET RESET HALT SET, ensuring halt is set during reset."); - control = set_field(control, DMI_DMCONTROL_HALTREQ, 1); - } else { - LOG_DEBUG("TARGET RESET HALT NOT SET"); - control = set_field(control, DMI_DMCONTROL_HALTREQ, 0); - } + uint32_t control = 0; + control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); + control = set_field(control, DMI_DMCONTROL_HARTRESET, 1); + control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); + control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid); + control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1); + + LOG_DEBUG("write 0x%x to dmcontrol", control); dmi_write(target, DMI_DMCONTROL, control); + target->state = TARGET_RESET; + return ERROR_OK; } @@ -1219,33 +1217,53 @@ static int deassert_reset(struct target *target) /*FIXME -- is there bookkeeping we need to do here*/ - uint32_t control = dmi_read(target, DMI_DMCONTROL); - // Clear the reset, but make sure haltreq is still set - if (target->reset_halt) { - control = set_field(control, DMI_DMCONTROL_HALTREQ, 1); - } - - control = set_field(control, DMI_DMCONTROL_NDMRESET, 0); + uint32_t control = 0; + control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); + control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid); + control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1); dmi_write(target, DMI_DMCONTROL, control); - uint32_t status; + uint32_t dmstatus; int dmi_busy_delay = info->dmi_busy_delay; + time_t start = time(NULL); + if (target->reset_halt) { - LOG_DEBUG("DEASSERTING RESET, waiting for hart to be halted."); + LOG_DEBUG("Waiting for hart to be halted."); do { - status = dmi_read(target, DMI_DMSTATUS); - } while (get_field(status, DMI_DMSTATUS_ALLHALTED) == 0); - } else { - LOG_DEBUG("DEASSERTING RESET, waiting for hart to be running."); - do { - status = dmi_read(target, DMI_DMSTATUS); - if (get_field(status, DMI_DMSTATUS_ANYHALTED) || - get_field(status, DMI_DMSTATUS_ANYUNAVAIL)) { - LOG_ERROR("Unexpected hart status during reset."); - abort(); + dmstatus = dmi_read(target, DMI_DMSTATUS); + if (time(NULL) - start > riscv_reset_timeout_sec) { + LOG_ERROR("Hart didn't halt coming out of reset in %ds; " + "dmstatus=0x%x; " + "Increase the timeout with riscv set_reset_timeout_sec.", + riscv_reset_timeout_sec, dmstatus); + return ERROR_FAIL; } - } while (get_field(status, DMI_DMSTATUS_ALLRUNNING) == 0); + target->state = TARGET_HALTED; + } while (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0); + + control = set_field(control, DMI_DMCONTROL_HALTREQ, 0); + dmi_write(target, DMI_DMCONTROL, control); + + } else { + LOG_DEBUG("Waiting for hart to be running."); + do { + dmstatus = dmi_read(target, DMI_DMSTATUS); + if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) || + get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) { + LOG_ERROR("Unexpected hart status during reset. dmstatus=0x%x", + dmstatus); + return ERROR_FAIL; + } + if (time(NULL) - start > riscv_reset_timeout_sec) { + LOG_ERROR("Hart didn't run coming out of reset in %ds; " + "dmstatus=0x%x; " + "Increase the timeout with riscv set_reset_timeout_sec.", + riscv_reset_timeout_sec, dmstatus); + return ERROR_FAIL; + } + } while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0); + target->state = TARGET_RUNNING; } info->dmi_busy_delay = dmi_busy_delay; return ERROR_OK; @@ -1880,37 +1898,6 @@ int riscv013_dmi_write_u64_bits(struct target *target) return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH; } -void riscv013_reset_current_hart(struct target *target) -{ - select_dmi(target); - uint32_t control = dmi_read(target, DMI_DMCONTROL); - control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); - control = set_field(control, DMI_DMCONTROL_HALTREQ, 1); - dmi_write(target, DMI_DMCONTROL, control); - - control = set_field(control, DMI_DMCONTROL_NDMRESET, 0); - dmi_write(target, DMI_DMCONTROL, control); - - time_t start = time(NULL); - - while (1) { - uint32_t dmstatus = dmi_read(target, DMI_DMSTATUS); - if (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED)) { - break; - } - if (time(NULL) - start > riscv_reset_timeout_sec) { - LOG_ERROR("Hart didn't halt coming out of reset in %ds; " - "dmstatus=0x%x; " - "Increase the timeout with riscv set_reset_timeout_sec.", - riscv_reset_timeout_sec, dmstatus); - return; - } - } - - control = set_field(control, DMI_DMCONTROL_HALTREQ, 0); - dmi_write(target, DMI_DMCONTROL, control); -} - /* Helper Functions. */ static void riscv013_on_step_or_resume(struct target *target, bool step) { diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index a502da5a6..491996bf1 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -676,14 +676,13 @@ static int old_or_new_riscv_halt(struct target *target) return riscv_openocd_halt(target); } -static int oldriscv_assert_reset(struct target *target) +static int riscv_assert_reset(struct target *target) { - LOG_DEBUG("RISCV ASSERT RESET"); struct target_type *tt = get_target_type(target); return tt->assert_reset(target); } -static int oldriscv_deassert_reset(struct target *target) +static int riscv_deassert_reset(struct target *target) { LOG_DEBUG("RISCV DEASSERT RESET"); struct target_type *tt = get_target_type(target); @@ -691,24 +690,6 @@ static int oldriscv_deassert_reset(struct target *target) } -static int old_or_new_riscv_assert_reset(struct target *target) -{ - RISCV_INFO(r); - if (r->is_halted == NULL) - return oldriscv_assert_reset(target); - else - return riscv_openocd_assert_reset(target); -} - -static int old_or_new_riscv_deassert_reset(struct target *target) -{ - RISCV_INFO(r); - if (r->is_halted == NULL) - return oldriscv_deassert_reset(target); - else - return riscv_openocd_deassert_reset(target); -} - static int oldriscv_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { @@ -1115,29 +1096,6 @@ int riscv_openocd_step( return out; } -int riscv_openocd_assert_reset(struct target *target) -{ - LOG_DEBUG("asserting reset for all harts"); - int out = riscv_reset_all_harts(target); - if (out != ERROR_OK) { - LOG_ERROR("unable to reset all harts"); - return out; - } - - return out; -} - -int riscv_openocd_deassert_reset(struct target *target) -{ - LOG_DEBUG("deasserting reset for all harts"); - if (target->reset_halt) - riscv_halt_all_harts(target); - else - riscv_resume_all_harts(target); - return ERROR_OK; -} - - /* Command Handlers */ COMMAND_HANDLER(riscv_set_command_timeout_sec) { @@ -1217,8 +1175,8 @@ struct target_type riscv_target = .resume = old_or_new_riscv_resume, .step = old_or_new_riscv_step, - .assert_reset = old_or_new_riscv_assert_reset, - .deassert_reset = old_or_new_riscv_deassert_reset, + .assert_reset = riscv_assert_reset, + .deassert_reset = riscv_deassert_reset, .read_memory = riscv_read_memory, .write_memory = riscv_write_memory, @@ -1315,33 +1273,6 @@ int riscv_resume_one_hart(struct target *target, int hartid) return ERROR_OK; } -int riscv_reset_all_harts(struct target *target) -{ - for (int i = 0; i < riscv_count_harts(target); ++i) { - if (!riscv_hart_enabled(target, i)) - continue; - - riscv_reset_one_hart(target, i); - } - - riscv_invalidate_register_cache(target); - return ERROR_OK; -} - -int riscv_reset_one_hart(struct target *target, int hartid) -{ - RISCV_INFO(r); - LOG_DEBUG("resetting hart %d", hartid); - riscv_halt_one_hart(target, hartid); - riscv_set_current_hartid(target, hartid); - r->reset_current_hart(target); - /* At this point the hart must be halted. On platforms that support - * "reset halt" exactly we expect the hart to have been halted before - * executing any instructions, while on older cores it'll just have - * halted quickly. */ - return ERROR_OK; -} - int riscv_step_rtos_hart(struct target *target) { RISCV_INFO(r); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 391b1a69e..d84e51ceb 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -103,7 +103,6 @@ typedef struct { void (*fill_dmi_write_u64)(struct target *target, char *buf, int a, uint64_t d); void (*fill_dmi_read_u64)(struct target *target, char *buf, int a); void (*fill_dmi_nop_u64)(struct target *target, char *buf); - void (*reset_current_hart)(struct target *target); } riscv_info_t; /* Wall-clock timeout for a command/access. Settable via RISC-V Target commands.*/ @@ -161,8 +160,6 @@ int riscv_halt_all_harts(struct target *target); int riscv_halt_one_hart(struct target *target, int hartid); int riscv_resume_all_harts(struct target *target); int riscv_resume_one_hart(struct target *target, int hartid); -int riscv_reset_all_harts(struct target *target); -int riscv_reset_one_hart(struct target *target, int hartid); /* Steps the hart that's currently selected in the RTOS, or if there is no RTOS * then the only hart. */ From fe36097ff850f11e74af688bb5a853ede565f23b Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 21 Sep 2017 12:42:40 -0700 Subject: [PATCH 53/68] Fix reset for multicore. --- src/target/riscv/riscv-013.c | 46 +++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index c5a2420ba..1dd801d3d 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1185,21 +1185,42 @@ static int examine(struct target *target) static int assert_reset(struct target *target) { - /*FIXME -- this only works for single-hart.*/ RISCV_INFO(r); - assert(r->current_hartid == 0); select_dmi(target); - uint32_t control = 0; - control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); - control = set_field(control, DMI_DMCONTROL_HARTRESET, 1); - control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); - control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid); - control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1); + uint32_t control_base = set_field(0, DMI_DMCONTROL_DMACTIVE, 1); - LOG_DEBUG("write 0x%x to dmcontrol", control); - dmi_write(target, DMI_DMCONTROL, control); + if (target->rtos) { + // There's only one target, and OpenOCD thinks each hart is a thread. + // We must reset them all. + + // TODO: Try to use hasel in dmcontrol + + // Set haltreq/resumereq for each hart. + uint32_t control = control_base; + for (int i = 0; i < riscv_count_harts(target); ++i) { + if (!riscv_hart_enabled(target, i)) + continue; + + control = set_field(control_base, DMI_DMCONTROL_HARTSEL, i); + control = set_field(control, DMI_DMCONTROL_HALTREQ, + target->reset_halt ? 1 : 0); + dmi_write(target, DMI_DMCONTROL, control); + } + // Assert ndmreset + control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); + dmi_write(target, DMI_DMCONTROL, control); + + } else { + // Reset just this hart. + uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL, + r->current_hartid); + control = set_field(control, DMI_DMCONTROL_HALTREQ, + target->reset_halt ? 1 : 0); + control = set_field(control, DMI_DMCONTROL_HARTRESET, 1); + dmi_write(target, DMI_DMCONTROL, control); + } target->state = TARGET_RESET; @@ -1212,10 +1233,7 @@ static int deassert_reset(struct target *target) RISCV013_INFO(info); select_dmi(target); - /*FIXME -- this only works for Single Hart*/ - assert(r->current_hartid == 0); - - /*FIXME -- is there bookkeeping we need to do here*/ + LOG_DEBUG("%d", r->current_hartid); // Clear the reset, but make sure haltreq is still set uint32_t control = 0; From f0195868d3872d5acb4fbb834a4bbbcbd2d8281a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Thu, 21 Sep 2017 14:53:12 -0700 Subject: [PATCH 54/68] Fall back on ndmreset if hartreset is unsupported. --- src/target/riscv/riscv-013.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 1dd801d3d..9f2b9d5fe 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1220,6 +1220,16 @@ static int assert_reset(struct target *target) target->reset_halt ? 1 : 0); control = set_field(control, DMI_DMCONTROL_HARTRESET, 1); dmi_write(target, DMI_DMCONTROL, control); + + // Read back to check if hartreset is supported. + uint32_t rb = dmi_read(target, DMI_DMCONTROL); + if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) { + // Use ndmreset instead. That will reset the entire device, but + // that's probably what OpenOCD wants anyway. + control = set_field(control, DMI_DMCONTROL_HARTRESET, 0); + control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); + dmi_write(target, DMI_DMCONTROL, control); + } } target->state = TARGET_RESET; From 744894e9654625e4a190853f7c76966067484474 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 26 Sep 2017 15:40:41 -0700 Subject: [PATCH 55/68] Better debug messages. --- src/target/riscv/riscv-013.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 9f2b9d5fe..9d7d77b83 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1718,7 +1718,7 @@ struct target_type riscv013_target = /*** 0.13-specific implementations of various RISC-V helper functions. ***/ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid) { - LOG_DEBUG("reading register 0x%08x on hart %d", rid, hid); + LOG_DEBUG("reading register %s on hart %d", gdb_regno_name(rid), hid); riscv_set_current_hartid(target, hid); @@ -1750,7 +1750,8 @@ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid static void riscv013_set_register(struct target *target, int hid, int rid, uint64_t value) { - LOG_DEBUG("writing register 0x%08x on hart %d", rid, hid); + LOG_DEBUG("writing 0x%" PRIx64 " to register %s on hart %d", value, + gdb_regno_name(rid), hid); riscv_set_current_hartid(target, hid); From 51f73a67696d917549f1ade02999b450c04ca67d Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 26 Sep 2017 15:40:49 -0700 Subject: [PATCH 56/68] Fix triggers for multi-gdb mode. --- src/target/riscv/riscv.c | 43 ++++++++++++++++++++++++++++++---------- src/target/riscv/riscv.h | 4 +++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 491996bf1..a8fc4378c 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -394,31 +394,43 @@ static int add_trigger(struct target *target, struct trigger *trigger) { RISCV_INFO(r); + // In RTOS mode, we need to set the same trigger in the same slot on every + // hart, to keep up the illusion that each hart is a thread running on the + // same core. + + // Otherwise, we just set the trigger on the one hart this target deals + // with. + riscv_reg_t tselect[RISCV_MAX_HARTS]; + int first_hart = -1; for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; + if (first_hart < 0) + first_hart = hartid; tselect[hartid] = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT); } + assert(first_hart >= 0); unsigned int i; - for (i = 0; i < r->trigger_count[0]; i++) { + for (i = 0; i < r->trigger_count[first_hart]; i++) { if (r->trigger_unique_id[i] != -1) { continue; } - riscv_set_register_on_hart(target, 0, GDB_REGNO_TSELECT, i); + riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i); - uint64_t tdata1 = riscv_get_register_on_hart(target, 0, GDB_REGNO_TDATA1); + uint64_t tdata1 = riscv_get_register_on_hart(target, first_hart, GDB_REGNO_TDATA1); int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); int result = ERROR_OK; - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { + LOG_DEBUG(">>> hartid=%d", hartid); if (!riscv_hart_enabled(target, hartid)) continue; - if (hartid > 0) { + if (hartid > first_hart) { riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i); } switch (type) { @@ -448,14 +460,14 @@ static int add_trigger(struct target *target, struct trigger *trigger) break; } - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, tselect[hartid]); } - if (i >= r->trigger_count[0]) { + if (i >= r->trigger_count[first_hart]) { LOG_ERROR("Couldn't find an available hardware trigger."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -507,19 +519,30 @@ static int remove_trigger(struct target *target, struct trigger *trigger) { RISCV_INFO(r); + int first_hart = -1; + for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + if (!riscv_hart_enabled(target, hartid)) + continue; + if (first_hart < 0) { + first_hart = hartid; + break; + } + } + assert(first_hart >= 0); + unsigned int i; - for (i = 0; i < r->trigger_count[0]; i++) { + for (i = 0; i < r->trigger_count[first_hart]; i++) { if (r->trigger_unique_id[i] == trigger->unique_id) { break; } } - if (i >= r->trigger_count[0]) { + if (i >= r->trigger_count[first_hart]) { LOG_ERROR("Couldn't find the hardware resources used by hardware " "trigger."); return ERROR_FAIL; } LOG_DEBUG("Stop using resource %d for bp %d", i, trigger->unique_id); - for (int hartid = 0; hartid < riscv_count_harts(target); ++hartid) { + for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { if (!riscv_hart_enabled(target, hartid)) continue; riscv_reg_t tselect = riscv_get_register_on_hart(target, hartid, GDB_REGNO_TSELECT); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index d84e51ceb..1197cbfbc 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -67,7 +67,9 @@ typedef struct { unsigned trigger_count[RISCV_MAX_HARTS]; /* For each physical trigger, contains -1 if the hwbp is available, or the - * unique_id of the breakpoint/watchpoint that is using it. */ + * unique_id of the breakpoint/watchpoint that is using it. + * Note that in RTOS mode the triggers are the same across all harts the + * target controls, while otherwise only a single hart is controlled. */ int trigger_unique_id[RISCV_MAX_HWBPS]; /* The address of the debug RAM buffer. */ From 10833525762f93a9c6a3954b3bacd21f158c2676 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 30 Sep 2017 13:13:03 -0700 Subject: [PATCH 57/68] Share register numbers between 0.11 and 0.13. --- src/target/riscv/gdb_regs.h | 2 + src/target/riscv/riscv-011.c | 94 +++++++++++++++--------------------- 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index 0ad02e9ef..2952e10ab 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -1,6 +1,8 @@ #ifndef TARGET__RISCV__GDB_REGS_H #define TARGET__RISCV__GDB_REGS_H +// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in +// its source tree. We must interpret the numbers the same here. enum gdb_regno { GDB_REGNO_XPR0 = 0, GDB_REGNO_X0 = GDB_REGNO_XPR0 + 0, diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 6b6666b4d..978019fac 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -21,6 +21,7 @@ #include "helper/time_support.h" #include "riscv.h" #include "asm.h" +#include "gdb_regs.h" /** * Since almost everything can be accomplish by scanning the dbus register, all @@ -155,21 +156,6 @@ typedef enum slot { #define DBUS_ADDRESS_UNKNOWN 0xffff -// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in -// its source tree. We must interpret the numbers the same here. -enum { - REG_XPR0 = 0, - REG_XPR31 = 31, - REG_PC = 32, - REG_FPR0 = 33, - REG_FPR31 = 64, - REG_CSR0 = 65, - REG_MSTATUS = CSR_MSTATUS + REG_CSR0, - REG_CSR4095 = 4160, - REG_PRIV = 4161, - REG_COUNT -}; - #define DRAM_CACHE_SIZE 16 struct trigger { @@ -1117,7 +1103,7 @@ static int execute_resume(struct target *target, bool step) return ERROR_FAIL; } - struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS]; + struct reg *mstatus_reg = &target->reg_cache->reg_list[GDB_REGNO_MSTATUS]; if (mstatus_reg->valid) { uint64_t mstatus_user = buf_get_u64(mstatus_reg->value, 0, riscv_xlen(target)); if (mstatus_user != info->mstatus_actual) { @@ -1201,15 +1187,15 @@ static void update_reg_list(struct target *target) if (info->reg_values) { free(info->reg_values); } - info->reg_values = malloc(REG_COUNT * riscv_xlen(target) / 4); + info->reg_values = malloc(GDB_REGNO_COUNT * riscv_xlen(target) / 4); - for (unsigned int i = 0; i < REG_COUNT; i++) { + for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) { struct reg *r = &target->reg_cache->reg_list[i]; r->value = info->reg_values + i * riscv_xlen(target) / 4; if (r->dirty) { LOG_ERROR("Register %d was dirty. Its value is lost.", i); } - if (i == REG_PRIV) { + if (i == GDB_REGNO_PRIV) { r->size = 8; } else { r->size = riscv_xlen(target); @@ -1241,7 +1227,7 @@ static void reg_cache_set(struct target *target, unsigned int number, static int update_mstatus_actual(struct target *target) { - struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS]; + struct reg *mstatus_reg = &target->reg_cache->reg_list[GDB_REGNO_MSTATUS]; if (mstatus_reg->valid) { // We previously made it valid. return ERROR_OK; @@ -1249,7 +1235,7 @@ static int update_mstatus_actual(struct target *target) // Force reading the register. In that process mstatus_actual will be // updated. - return register_get(&target->reg_cache->reg_list[REG_MSTATUS]); + return register_get(&target->reg_cache->reg_list[GDB_REGNO_MSTATUS]); } /*** OpenOCD target functions. ***/ @@ -1257,8 +1243,8 @@ static int update_mstatus_actual(struct target *target) static int register_read(struct target *target, riscv_reg_t *value, int regnum) { riscv011_info_t *info = get_info(target); - if (regnum >= REG_CSR0 && regnum <= REG_CSR4095) { - cache_set32(target, 0, csrr(S0, regnum - REG_CSR0)); + if (regnum >= GDB_REGNO_CSR0 && regnum <= GDB_REGNO_CSR4095) { + cache_set32(target, 0, csrr(S0, regnum - GDB_REGNO_CSR0)); cache_set_store(target, 1, S0, SLOT0); cache_set_jump(target, 2); } else { @@ -1281,7 +1267,7 @@ static int register_read(struct target *target, riscv_reg_t *value, int regnum) *value = cache_get(target, SLOT0); LOG_DEBUG("reg[%d]=0x%" PRIx64, regnum, *value); - if (regnum == REG_MSTATUS) { + if (regnum == GDB_REGNO_MSTATUS) { info->mstatus_actual = *value; } @@ -1296,13 +1282,13 @@ static int register_get(struct reg *reg) maybe_write_tselect(target); riscv_reg_t value = ~0; - if (reg->number <= REG_XPR31) { + if (reg->number <= GDB_REGNO_XPR31) { value = reg_cache_get(target, reg->number); LOG_DEBUG("%s=0x%" PRIx64, reg->name, reg_cache_get(target, reg->number)); - } else if (reg->number == REG_PC) { + } else if (reg->number == GDB_REGNO_PC) { value = info->dpc; LOG_DEBUG("%s=0x%" PRIx64 " (cached)", reg->name, info->dpc); - } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) { + } else if (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) { int result = update_mstatus_actual(target); if (result != ERROR_OK) { return result; @@ -1316,9 +1302,9 @@ static int register_get(struct reg *reg) } if (riscv_xlen(target) == 32) { - cache_set32(target, i++, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fsw(reg->number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } else { - cache_set32(target, i++, fsd(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fsd(reg->number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } cache_set_jump(target, i++); @@ -1331,7 +1317,7 @@ static int register_get(struct reg *reg) } buf_set_u64(reg->value, 0, riscv_xlen(target), value); - if (reg->number == REG_MSTATUS) { + if (reg->number == GDB_REGNO_MSTATUS) { reg->valid = true; } @@ -1354,13 +1340,13 @@ static int register_write(struct target *target, unsigned int number, cache_set_load(target, 0, S0, SLOT0); cache_set_store(target, 1, S0, SLOT_LAST); cache_set_jump(target, 2); - } else if (number <= REG_XPR31) { - cache_set_load(target, 0, number - REG_XPR0, SLOT0); + } else if (number <= GDB_REGNO_XPR31) { + cache_set_load(target, 0, number - GDB_REGNO_XPR0, SLOT0); cache_set_jump(target, 1); - } else if (number == REG_PC) { + } else if (number == GDB_REGNO_PC) { info->dpc = value; return ERROR_OK; - } else if (number >= REG_FPR0 && number <= REG_FPR31) { + } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { int result = update_mstatus_actual(target); if (result != ERROR_OK) { return result; @@ -1374,20 +1360,20 @@ static int register_write(struct target *target, unsigned int number, } if (riscv_xlen(target) == 32) { - cache_set32(target, i++, flw(number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, flw(number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } else { - cache_set32(target, i++, fld(number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fld(number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } cache_set_jump(target, i++); - } else if (number >= REG_CSR0 && number <= REG_CSR4095) { + } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { cache_set_load(target, 0, S0, SLOT0); - cache_set32(target, 1, csrw(S0, number - REG_CSR0)); + cache_set32(target, 1, csrw(S0, number - GDB_REGNO_CSR0)); cache_set_jump(target, 2); - if (number == REG_MSTATUS) { + if (number == GDB_REGNO_MSTATUS) { info->mstatus_actual = value; } - } else if (number == REG_PRIV) { + } else if (number == GDB_REGNO_PRIV) { info->dcsr = set_field(info->dcsr, DCSR_PRV, value); return ERROR_OK; } else { @@ -1481,16 +1467,16 @@ static int init_target(struct command_context *cmd_ctx, target->reg_cache = calloc(1, sizeof(*target->reg_cache)); target->reg_cache->name = "RISC-V registers"; - target->reg_cache->num_regs = REG_COUNT; + target->reg_cache->num_regs = GDB_REGNO_COUNT; - target->reg_cache->reg_list = calloc(REG_COUNT, sizeof(struct reg)); + target->reg_cache->reg_list = calloc(GDB_REGNO_COUNT, sizeof(struct reg)); const unsigned int max_reg_name_len = 12; - info->reg_names = calloc(1, REG_COUNT * max_reg_name_len); + info->reg_names = calloc(1, GDB_REGNO_COUNT * max_reg_name_len); char *reg_name = info->reg_names; info->reg_values = NULL; - for (unsigned int i = 0; i < REG_COUNT; i++) { + for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) { struct reg *r = &target->reg_cache->reg_list[i]; r->number = i; r->caller_save = true; @@ -1499,22 +1485,22 @@ static int init_target(struct command_context *cmd_ctx, r->exist = true; r->type = &riscv_reg_arch_type; r->arch_info = target; - if (i <= REG_XPR31) { + if (i <= GDB_REGNO_XPR31) { sprintf(reg_name, "x%d", i); - } else if (i == REG_PC) { + } else if (i == GDB_REGNO_PC) { sprintf(reg_name, "pc"); - } else if (i >= REG_FPR0 && i <= REG_FPR31) { - sprintf(reg_name, "f%d", i - REG_FPR0); - } else if (i >= REG_CSR0 && i <= REG_CSR4095) { - sprintf(reg_name, "csr%d", i - REG_CSR0); - } else if (i == REG_PRIV) { + } else if (i >= GDB_REGNO_FPR0 && i <= GDB_REGNO_FPR31) { + sprintf(reg_name, "f%d", i - GDB_REGNO_FPR0); + } else if (i >= GDB_REGNO_CSR0 && i <= GDB_REGNO_CSR4095) { + sprintf(reg_name, "csr%d", i - GDB_REGNO_CSR0); + } else if (i == GDB_REGNO_PRIV) { sprintf(reg_name, "priv"); } if (reg_name[0]) { r->name = reg_name; } reg_name += strlen(reg_name) + 1; - assert(reg_name < info->reg_names + REG_COUNT * max_reg_name_len); + assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len); } return ERROR_OK; @@ -1579,7 +1565,7 @@ static int step(struct target *target, int current, target_addr_t address, LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.", riscv_xlen(target)); } - int result = register_write(target, REG_PC, address); + int result = register_write(target, GDB_REGNO_PC, address); if (result != ERROR_OK) return result; } @@ -2006,7 +1992,7 @@ static int riscv011_resume(struct target *target, int current, LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.", riscv_xlen(target)); } - int result = register_write(target, REG_PC, address); + int result = register_write(target, GDB_REGNO_PC, address); if (result != ERROR_OK) return result; } From 6795270a8ee21b8d231fdc7f3b6f7f8d823a580c Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 30 Sep 2017 13:31:57 -0700 Subject: [PATCH 58/68] Make priv readable in 0.11. --- src/target/riscv/riscv-011.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 978019fac..6073dbd6a 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1311,6 +1311,8 @@ static int register_get(struct reg *reg) if (cache_write(target, 4, true) != ERROR_OK) { return ERROR_FAIL; } + } else if (reg->number == GDB_REGNO_PRIV) { + value = get_field(info->dcsr, DCSR_PRV); } else { if (register_read(target, &value, reg->number) != ERROR_OK) return ERROR_FAIL; From e64bb8c44a6e2b6b9b39426c4c77e00edceac5aa Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 30 Sep 2017 14:15:37 -0700 Subject: [PATCH 59/68] Fix priv access on 0.13. --- src/target/riscv/riscv-013.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 9f2b9d5fe..e441d33b5 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1732,7 +1732,7 @@ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, out); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read_direct(target, &dcsr, CSR_DCSR); + register_read_direct(target, &dcsr, GDB_REGNO_DCSR); buf_set_u64((unsigned char *)&out, 0, 8, get_field(dcsr, CSR_DCSR_PRV)); } else { int result = register_read_direct(target, &out, rid); @@ -1765,9 +1765,9 @@ static void riscv013_set_register(struct target *target, int hid, int rid, uint6 assert(value == actual_value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read_direct(target, &dcsr, CSR_DCSR); + register_read_direct(target, &dcsr, GDB_REGNO_DCSR); dcsr = set_field(dcsr, CSR_DCSR_PRV, value); - register_write_direct(target, CSR_DCSR, dcsr); + register_write_direct(target, GDB_REGNO_DCSR, dcsr); } else { register_write_direct(target, rid, value); } From 728a617bd4e3363f9277d81e0f598e3911208233 Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Tue, 3 Oct 2017 00:17:57 +0300 Subject: [PATCH 60/68] target/riscv: Silence -Werror=return-type - clang compains about the functions not returning a value --- src/target/riscv/asm.h | 2 ++ src/target/riscv/riscv-011.c | 1 + 2 files changed, 3 insertions(+) diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h index 67ac14f84..8a2fd491c 100644 --- a/src/target/riscv/asm.h +++ b/src/target/riscv/asm.h @@ -17,6 +17,7 @@ static uint32_t load(const struct target *target, unsigned int rd, return ld(rd, base, offset); } assert(0); + return 0; // Silence -Werror=return-type } static uint32_t store(const struct target *target, unsigned int src, @@ -31,6 +32,7 @@ static uint32_t store(const struct target *target, unsigned int src, return sd(src, base, offset); } assert(0); + return 0; // Silence -Werror=return-type } #endif diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 6b6666b4d..4f2e3a618 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -269,6 +269,7 @@ static unsigned int slot_offset(const struct target *target, slot_t slot) LOG_ERROR("slot_offset called with xlen=%d, slot=%d", riscv_xlen(target), slot); assert(0); + return 0; // Silence -Werror=return-type } static uint32_t load_slot(const struct target *target, unsigned int dest, From f5a69e547f91a0eef47cf02f27f744020b6b427c Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Tue, 3 Oct 2017 00:23:14 +0300 Subject: [PATCH 61/68] target/riscv/program.c: fix clang warning - I'm not sure I understand the logic behind the original statement, but on macOS it fails to compile. --- src/target/riscv/program.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index 055bfdbaf..d052574d4 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -478,7 +478,11 @@ riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr) riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr) { - return ((addr > 0) ? 1 : 0) * (addr & 0x7FF); + if (addr > 0) { + return (addr & 0x7FF); + } else { + return 0; + } } int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr) From f9f303923e2ce16f9695efc8a4abf770d0122476 Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Tue, 3 Oct 2017 00:36:22 +0300 Subject: [PATCH 62/68] target/riscv/asm.h: use tab for indentation --- src/target/riscv/asm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h index 8a2fd491c..f976e2065 100644 --- a/src/target/riscv/asm.h +++ b/src/target/riscv/asm.h @@ -17,7 +17,7 @@ static uint32_t load(const struct target *target, unsigned int rd, return ld(rd, base, offset); } assert(0); - return 0; // Silence -Werror=return-type + return 0; // Silence -Werror=return-type } static uint32_t store(const struct target *target, unsigned int src, @@ -32,7 +32,7 @@ static uint32_t store(const struct target *target, unsigned int src, return sd(src, base, offset); } assert(0); - return 0; // Silence -Werror=return-type + return 0; // Silence -Werror=return-type } #endif From 066ce338d8d63fdcc6e40678acf1a20eb814c52b Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Tue, 3 Oct 2017 00:48:15 +0300 Subject: [PATCH 63/68] flash/nor/Makefile.am: lexicographical order --- src/flash/nor/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 759e98c4b..c647cbb60 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -22,8 +22,8 @@ NOR_DRIVERS = \ %D%/dsp5680xx_flash.c \ %D%/efm32.c \ %D%/em357.c \ - %D%/fespi.c \ %D%/faux.c \ + %D%/fespi.c \ %D%/fm3.c \ %D%/fm4.c \ %D%/jtagspi.c \ From 1b11d579eab1eff6248dfc41416c6a5aeca34e39 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 3 Oct 2017 14:21:27 -0700 Subject: [PATCH 64/68] Add read buffer to bitbang, improving performance. This reduces the time for one testcase where OpenOCD connects to a simulator from 12.30s to 5.35s! Running all our tests went from 13m13s to 3m55s. Change-Id: I7dc774e1e0f5752905ac4318fd9b85b930374a05 --- src/jtag/drivers/bitbang.c | 21 +++++-- src/jtag/drivers/bitbang.h | 14 +++++ src/jtag/drivers/remote_bitbang.c | 100 ++++++++++++++++++++++++------ 3 files changed, 111 insertions(+), 24 deletions(-) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index c9ec9c9d6..bde48e0dc 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -203,7 +203,6 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int } for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { - int val = 0; int tms = (bit_cnt == scan_size-1) ? 1 : 0; int tdi; int bytec = bit_cnt/8; @@ -219,12 +218,26 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int bitbang_interface->write(0, tms, tdi); - if (type != SCAN_OUT) - val = bitbang_interface->read(); + if (type != SCAN_OUT) { + if (bitbang_interface->sample) { + bitbang_interface->sample(); + } else { + int val = bitbang_interface->read(); + if (val) + buffer[bytec] |= bcval; + else + buffer[bytec] &= ~bcval; + } + } bitbang_interface->write(1, tms, tdi); + } - if (type != SCAN_OUT) { + if (type != SCAN_OUT && bitbang_interface->sample) { + for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { + int bytec = bit_cnt/8; + int bcval = 1 << (bit_cnt % 8); + int val = bitbang_interface->read_sample(); if (val) buffer[bytec] |= bcval; else diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index c5b44bfd5..563ea104c 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -27,7 +27,21 @@ struct bitbang_interface { /* low level callbacks (for bitbang) */ + + /* Either read() or sample()/read_sample() must be implemented. */ + + /* Sample TDO and return 0 or 1. */ int (*read)(void); + + /* The sample functions allow an interface to batch a number of writes and + * sample requests together. Not waiting for a value to come back can + * greatly increase throughput. */ + /* Sample TDO and put the result in a buffer. */ + void (*sample)(void); + /* Return the next unread value from the buffer. */ + int (*read_sample)(void); + + /* Set TCK, TMS, and TDI to the given values. */ void (*write)(int tck, int tms, int tdi); void (*reset)(int trst, int srst); void (*blink)(int on); diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index b898e957d..3907a077a 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -40,11 +40,44 @@ static char *remote_bitbang_host; static char *remote_bitbang_port; -FILE *remote_bitbang_in; -FILE *remote_bitbang_out; +static FILE *remote_bitbang_in; +static FILE *remote_bitbang_out; +static int remote_bitbang_fd; + +static char remote_bitbang_buf[64]; +static unsigned remote_bitbang_start; +static unsigned remote_bitbang_end; + +/* Read any incoming data, placing it into the buffer. */ +static void remote_bitbang_fill_buf(void) +{ + fcntl(remote_bitbang_fd, F_SETFL, O_NONBLOCK); + while (1) { + ssize_t count = read(remote_bitbang_fd, + remote_bitbang_buf + remote_bitbang_end, + sizeof(remote_bitbang_buf) - remote_bitbang_end); + if (count > 0) { + remote_bitbang_end += count; + // TODO: check for overflow. + if (remote_bitbang_end == sizeof(remote_bitbang_buf)) { + remote_bitbang_end = 0; + } + } else if (count == 0) { + return; + } else if (count < 0) { + if (errno == EAGAIN) { + return; + } else { + REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_fill_buf: %s (%d)", + strerror(errno), errno); + } + } + } +} static void remote_bitbang_putc(int c) { + remote_bitbang_fill_buf(); if (EOF == fputc(c, remote_bitbang_out)) REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); } @@ -75,15 +108,8 @@ static int remote_bitbang_quit(void) return ERROR_OK; } -/* Get the next read response. */ -static int remote_bitbang_rread(void) +static int char_to_int(int c) { - if (EOF == fflush(remote_bitbang_out)) { - remote_bitbang_quit(); - REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno)); - } - - int c = fgetc(remote_bitbang_in); switch (c) { case '0': return 0; @@ -96,9 +122,40 @@ static int remote_bitbang_rread(void) } } -static int remote_bitbang_read(void) +/* Get the next read response. */ +static int remote_bitbang_rread(void) +{ + if (EOF == fflush(remote_bitbang_out)) { + remote_bitbang_quit(); + REMOTE_BITBANG_RAISE_ERROR("fflush: %s", strerror(errno)); + } + + /* Enable blocking access. */ + fcntl(remote_bitbang_fd, F_SETFL, 0); + char c; + ssize_t count = read(remote_bitbang_fd, &c, 1); + if (count == 1) { + return char_to_int(c); + } else { + remote_bitbang_quit(); + REMOTE_BITBANG_RAISE_ERROR("read: count=%d, error=%s", (int) count, + strerror(errno)); + } +} + +static void remote_bitbang_sample(void) { remote_bitbang_putc('R'); +} + +static int remote_bitbang_read_sample(void) +{ + if (remote_bitbang_start != remote_bitbang_end) { + int c = remote_bitbang_buf[remote_bitbang_start]; + remote_bitbang_start = + (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf); + return char_to_int(c); + } return remote_bitbang_rread(); } @@ -121,7 +178,8 @@ static void remote_bitbang_blink(int on) } static struct bitbang_interface remote_bitbang_bitbang = { - .read = &remote_bitbang_read, + .sample = &remote_bitbang_sample, + .read_sample = &remote_bitbang_read_sample, .write = &remote_bitbang_write, .reset = &remote_bitbang_reset, .blink = &remote_bitbang_blink, @@ -199,26 +257,28 @@ static int remote_bitbang_init_unix(void) static int remote_bitbang_init(void) { - int fd; bitbang_interface = &remote_bitbang_bitbang; + remote_bitbang_start = 0; + remote_bitbang_end = 0; + LOG_INFO("Initializing remote_bitbang driver"); if (remote_bitbang_port == NULL) - fd = remote_bitbang_init_unix(); + remote_bitbang_fd = remote_bitbang_init_unix(); else - fd = remote_bitbang_init_tcp(); + remote_bitbang_fd = remote_bitbang_init_tcp(); - if (fd < 0) - return fd; + if (remote_bitbang_fd < 0) + return remote_bitbang_fd; - remote_bitbang_in = fdopen(fd, "r"); + remote_bitbang_in = fdopen(remote_bitbang_fd, "r"); if (remote_bitbang_in == NULL) { LOG_ERROR("fdopen: failed to open read stream"); - close(fd); + close(remote_bitbang_fd); return ERROR_FAIL; } - remote_bitbang_out = fdopen(fd, "w"); + remote_bitbang_out = fdopen(remote_bitbang_fd, "w"); if (remote_bitbang_out == NULL) { LOG_ERROR("fdopen: failed to open write stream"); fclose(remote_bitbang_in); From 28eb10f43d513770224967fe7a73e98b498aa1a9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 4 Oct 2017 15:23:14 -0700 Subject: [PATCH 65/68] Ensure the buffer doesn't overflow. Tested with a variety of prime buffer sizes. Change-Id: I2b4835d46adf4c971111da88e8de4b46eb8dad41 --- src/jtag/drivers/bitbang.c | 40 +++++++++++++++++-------------- src/jtag/drivers/bitbang.h | 3 +++ src/jtag/drivers/remote_bitbang.c | 26 +++++++++++++++++--- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index bde48e0dc..4fdca7980 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -185,10 +185,11 @@ static void bitbang_stableclocks(int num_cycles) } } -static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) +static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, + unsigned scan_size) { tap_state_t saved_end_state = tap_get_end_state(); - int bit_cnt; + unsigned bit_cnt; if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) || @@ -202,6 +203,7 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int bitbang_end_state(saved_end_state); } + size_t buffered = 0; for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { int tms = (bit_cnt == scan_size-1) ? 1 : 0; int tdi; @@ -219,8 +221,9 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int bitbang_interface->write(0, tms, tdi); if (type != SCAN_OUT) { - if (bitbang_interface->sample) { + if (bitbang_interface->buf_size) { bitbang_interface->sample(); + buffered++; } else { int val = bitbang_interface->read(); if (val) @@ -231,17 +234,17 @@ static void bitbang_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int } bitbang_interface->write(1, tms, tdi); - } - if (type != SCAN_OUT && bitbang_interface->sample) { - for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++) { - int bytec = bit_cnt/8; - int bcval = 1 << (bit_cnt % 8); - int val = bitbang_interface->read_sample(); - if (val) - buffer[bytec] |= bcval; - else - buffer[bytec] &= ~bcval; + if (type != SCAN_OUT && bitbang_interface->buf_size && + (buffered == bitbang_interface->buf_size || + bit_cnt == scan_size - 1)) { + for (unsigned i = bit_cnt + 1 - buffered; i <= bit_cnt; i++) { + if (bitbang_interface->read_sample()) + buffer[i/8] |= 1 << (i % 8); + else + buffer[i/8] &= ~(1 << (i % 8)); + } + buffered = 0; } } @@ -322,13 +325,14 @@ int bitbang_execute_queue(void) bitbang_path_move(cmd->cmd.pathmove); break; case JTAG_SCAN: -#ifdef _DEBUG_JTAG_IO_ - LOG_DEBUG("%s scan end in %s", - (cmd->cmd.scan->ir_scan) ? "IR" : "DR", - tap_state_name(cmd->cmd.scan->end_state)); -#endif bitbang_end_state(cmd->cmd.scan->end_state); scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); +#ifdef _DEBUG_JTAG_IO_ + LOG_DEBUG("%s scan %d bits; end in %s", + (cmd->cmd.scan->ir_scan) ? "IR" : "DR", + scan_size, + tap_state_name(cmd->cmd.scan->end_state)); +#endif type = jtag_scan_type(cmd->cmd.scan); bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 563ea104c..f0b9263c1 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -36,6 +36,9 @@ struct bitbang_interface { /* The sample functions allow an interface to batch a number of writes and * sample requests together. Not waiting for a value to come back can * greatly increase throughput. */ + /* The number of TDO samples that can be buffered up before the caller has + * to call read_sample. */ + size_t buf_size; /* Sample TDO and put the result in a buffer. */ void (*sample)(void); /* Return the next unread value from the buffer. */ diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index 3907a077a..5e78ccb45 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -44,18 +44,36 @@ static FILE *remote_bitbang_in; static FILE *remote_bitbang_out; static int remote_bitbang_fd; +/* Circular buffer. When start == end, the buffer is empty. */ static char remote_bitbang_buf[64]; static unsigned remote_bitbang_start; static unsigned remote_bitbang_end; +static int remote_bitbang_buf_full(void) +{ + return remote_bitbang_end == + ((remote_bitbang_start + sizeof(remote_bitbang_buf) - 1) % + sizeof(remote_bitbang_buf)); +} + /* Read any incoming data, placing it into the buffer. */ static void remote_bitbang_fill_buf(void) { fcntl(remote_bitbang_fd, F_SETFL, O_NONBLOCK); - while (1) { + while (!remote_bitbang_buf_full()) { + unsigned contiguous_available_space; + if (remote_bitbang_end >= remote_bitbang_start) { + contiguous_available_space = sizeof(remote_bitbang_buf) - + remote_bitbang_end; + if (remote_bitbang_start == 0) + contiguous_available_space -= 1; + } else { + contiguous_available_space = remote_bitbang_start - + remote_bitbang_end - 1; + } ssize_t count = read(remote_bitbang_fd, remote_bitbang_buf + remote_bitbang_end, - sizeof(remote_bitbang_buf) - remote_bitbang_end); + contiguous_available_space); if (count > 0) { remote_bitbang_end += count; // TODO: check for overflow. @@ -77,7 +95,6 @@ static void remote_bitbang_fill_buf(void) static void remote_bitbang_putc(int c) { - remote_bitbang_fill_buf(); if (EOF == fputc(c, remote_bitbang_out)) REMOTE_BITBANG_RAISE_ERROR("remote_bitbang_putc: %s", strerror(errno)); } @@ -145,6 +162,8 @@ static int remote_bitbang_rread(void) static void remote_bitbang_sample(void) { + remote_bitbang_fill_buf(); + assert(!remote_bitbang_buf_full()); remote_bitbang_putc('R'); } @@ -178,6 +197,7 @@ static void remote_bitbang_blink(int on) } static struct bitbang_interface remote_bitbang_bitbang = { + .buf_size = sizeof(remote_bitbang_buf) - 1, .sample = &remote_bitbang_sample, .read_sample = &remote_bitbang_read_sample, .write = &remote_bitbang_write, From 916759e0de712f806aa5cdbfc23128ee8bdf6def Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 4 Oct 2017 15:44:07 -0700 Subject: [PATCH 66/68] Revert ae74097f (extra ftdi debug). Instead it makes more sense to push the debug changes to jtag/core.c. Change-Id: I73bafa2a054e1f72b7752cfbce9ffc14303fc4c4 --- src/jtag/drivers/ftdi.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index 883cd24c8..342e32102 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -430,40 +430,10 @@ static void ftdi_execute_pathmove(struct jtag_command *cmd) tap_set_end_state(tap_get_state()); } -#ifdef _DEBUG_JTAG_IO_ -static void debug_jtag_io_value(const char *prefix, const uint8_t *value, - unsigned int num_bits) -{ - if (!value) { - return; - } - - char buf[33]; - char *bufp = buf; - unsigned int chars = (num_bits + 3) / 4; - for (unsigned int i = 0; i < chars; i++) { - if (i && (i % 32) == 0) { - DEBUG_JTAG_IO(" %s%s", prefix, buf); - bufp = buf; - } - int start_bit = 4 * (chars - i - 1); - sprintf(bufp, "%01x", buf_get_u32(value, start_bit, 4)); - bufp++; - } - if (bufp != buf) { - DEBUG_JTAG_IO(" %s%s", prefix, buf); - } -} -#endif - static void ftdi_execute_scan(struct jtag_command *cmd) { DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", jtag_scan_type(cmd->cmd.scan)); -#ifdef _DEBUG_JTAG_IO_ - debug_jtag_io_value(" out=", cmd->cmd.scan->fields->out_value, - cmd->cmd.scan->fields->num_bits); -#endif /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ while (cmd->cmd.scan->num_fields > 0 @@ -545,11 +515,6 @@ static void ftdi_execute_scan(struct jtag_command *cmd) DEBUG_JTAG_IO("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, tap_state_name(tap_get_end_state())); - -#ifdef _DEBUG_JTAG_IO_ - debug_jtag_io_value(" in=", cmd->cmd.scan->fields->in_value, - cmd->cmd.scan->fields->num_bits); -#endif } static void ftdi_execute_reset(struct jtag_command *cmd) From 24658db50ea86d08d8b8bbbd306cb12490074335 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 4 Oct 2017 16:02:30 -0700 Subject: [PATCH 67/68] Fix compile warnings. Partly fixes #124. Change-Id: I3a7fd65c643e40b142709806cb9fb4cc62bb955f --- src/target/riscv/riscv-011.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 7ac856118..6e576fef9 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -2080,7 +2080,7 @@ static int read_memory(struct target *target, target_addr_t address, cache_write(target, CACHE_NO_READ, false); riscv011_info_t *info = get_info(target); - const int max_batch_size = 256; + const unsigned max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); uint32_t result_value = 0x777; @@ -2241,7 +2241,7 @@ static int write_memory(struct target *target, target_addr_t address, return ERROR_FAIL; } - const int max_batch_size = 256; + const unsigned max_batch_size = 256; scans_t *scans = scans_new(target, max_batch_size); uint32_t result_value = 0x777; From 2da7820833abf82564b1afb778ac40cea60728e2 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sun, 8 Oct 2017 11:37:39 -0700 Subject: [PATCH 68/68] Revert this LOG_INFO to LOG_DEBUG. Change-Id: I75dd7667a542aa1c6ea10f97fe1e00dd1ecba69d --- src/rtos/rtos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 5e8ce485c..a37f44a1a 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -434,7 +434,7 @@ int rtos_get_gdb_reg_list(struct connection *connection) (target->smp))) { /* in smp several current thread are possible */ char *hex_reg_list; - LOG_INFO("RTOS: getting register list for thread 0x%" PRIx64 + LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64 ", target->rtos->current_thread=0x%" PRIx64 "\r\n", current_threadid, target->rtos->current_thread);