From 24ed65d6b6319dea654cb7a2253e953e75c4908a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 8 Feb 2017 13:47:57 +0100 Subject: [PATCH 1/7] src/target/stm32f4.c: Declare CCMRAM only for devices with CCMRAM. --- src/target/stm32f4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index c530183..1dcb5c9 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -164,13 +164,14 @@ bool stm32f4_probe(target *t) /* Fall through for stuff common to F40x/F41x */ case 0x411: /* F205 */ case 0x413: /* F405 */ + if (!f2) + target_add_ram(t, 0x10000000, 0x10000); + /* Fall through for devices w/o CCMRAM */ case 0x421: /* F446 */ case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x431: /* F411 RM0383 Rev.4 */ case 0x433: /* F401 D/E RM0368 Rev.3 */ t->driver = f2 ? stm32f2_driver_str : stm32f4_driver_str; - if (!f2) - target_add_ram(t, 0x10000000, 0x10000); target_add_ram(t, 0x20000000, 0x30000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); From e43017d0a62e941e75bb47856d7bd3ac54907813 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 8 Feb 2017 13:57:17 +0100 Subject: [PATCH 2/7] src/target/stm32f4.c: Add STM32F412 and F413. F413 needs its own clause, as there is memory > 1 MB but no second bank. --- src/target/stm32f4.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 1dcb5c9..e9a3c84 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -170,15 +170,24 @@ bool stm32f4_probe(target *t) case 0x421: /* F446 */ case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x431: /* F411 RM0383 Rev.4 */ + case 0x441: /* F412 RM0402 Rev.4, 256 kB Ram */ case 0x433: /* F401 D/E RM0368 Rev.3 */ t->driver = f2 ? stm32f2_driver_str : stm32f4_driver_str; - target_add_ram(t, 0x20000000, 0x30000); + target_add_ram(t, 0x20000000, 0x40000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); stm32f4_add_flash(t, 0x8020000, 0xE0000, 0x20000, 5); target_add_commands(t, stm32f4_cmd_list, f2 ? "STM32F2" : "STM32F4"); break; + case 0x463: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ + t->driver = stm32f4_driver_str; + target_add_ram(t, 0x20000000, 0x50000); + stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); + stm32f4_add_flash(t, 0x8010000, 0x10000, 0x10000, 4); + stm32f4_add_flash(t, 0x8020000, 0x160000, 0x20000, 5); + target_add_commands(t, stm32f4_cmd_list, "STM32F413"); + break; case 0x449: /* F7x6 RM0385 Rev.2 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x4000); From dc1c7611a9f9a8ba242d2b36a575eda8b111d2ef Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 8 Feb 2017 14:08:30 +0100 Subject: [PATCH 3/7] src/target/stm32f4.c: All STM32F7 devs have option bytes at 0x1fff0000. --- src/target/stm32f4.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index e9a3c84..0f54347 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -338,7 +338,8 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) uint32_t start, val; int len; - if (t->idcode == 0x449) { + if ((t->idcode == 0x449) || (t->idcode == 0x451)){ + /* F7 Devices have option bytes at 0x1FFF0000. */ start = 0x1FFF0000; len = 0x20; } From 2216587b39a67387e0606c2c815c682a5aef154c Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 8 Feb 2017 14:32:43 +0100 Subject: [PATCH 4/7] src/target/stm32f4.c: Remove missleading DTCM comment. Use different command string for F74x and F76x. --- src/target/stm32f4.c | 10 +++++----- src/target/stm32l0.c | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 0f54347..5a3d5d0 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -188,7 +188,7 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x8020000, 0x160000, 0x20000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F413"); break; - case 0x449: /* F7x6 RM0385 Rev.2 */ + case 0x449: /* F74x RM0385 Rev.4 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x4000); target_add_ram(t, 0x20000000, 0x50000); @@ -196,11 +196,11 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x8000000, 0x20000, 0x8000, 0); stm32f4_add_flash(t, 0x8020000, 0x20000, 0x20000, 4); stm32f4_add_flash(t, 0x8040000, 0xC0000, 0x40000, 5); - /* ITCM */ + /* Flash aliased as ITCM */ stm32f4_add_flash(t, 0x0200000, 0x20000, 0x8000, 0); stm32f4_add_flash(t, 0x0220000, 0x20000, 0x20000, 4); stm32f4_add_flash(t, 0x0240000, 0xC0000, 0x40000, 5); - target_add_commands(t, stm32f4_cmd_list, "STM32F7"); + target_add_commands(t, stm32f4_cmd_list, "STM32F4x"); break; case 0x451: /* F76x F77x RM0410 */ t->driver = stm32f7_driver_str; @@ -210,11 +210,11 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x8000000, 0x020000, 0x8000, 0); stm32f4_add_flash(t, 0x8020000, 0x020000, 0x20000, 4); stm32f4_add_flash(t, 0x8040000, 0x1C0000, 0x40000, 5); - /* ITCM */ + /* Flash aliased as ITCM */ stm32f4_add_flash(t, 0x200000, 0x020000, 0x8000, 0); stm32f4_add_flash(t, 0x220000, 0x020000, 0x20000, 4); stm32f4_add_flash(t, 0x240000, 0x1C0000, 0x40000, 5); - target_add_commands(t, stm32f4_cmd_list, "STM32F7"); + target_add_commands(t, stm32f4_cmd_list, "STM32F76x"); break; default: return false; diff --git a/src/target/stm32l0.c b/src/target/stm32l0.c index 967f0f9..ea22cb9 100644 --- a/src/target/stm32l0.c +++ b/src/target/stm32l0.c @@ -287,9 +287,11 @@ bool stm32l0_probe(target* t) case 0x447: /* STM32L0xx Cat5 */ t->idcode = idcode; t->driver = "STM32L0x"; - target_add_ram(t, 0x20000000, 0x2000); + target_add_ram(t, 0x20000000, 0x5000); stm32l_add_flash(t, 0x8000000, 0x10000, 0x80); - stm32l_add_eeprom(t, 0x8080000, 0x800); + stm32l_add_flash(t, 0x8010000, 0x10000, 0x80); + stm32l_add_flash(t, 0x8020000, 0x10000, 0x80); + stm32l_add_eeprom(t, 0x8080000, 0x1800); target_add_commands(t, stm32lx_cmd_list, "STM32L0x"); return true; } From 84e036a80498d3e899e4e2c0717edf8891ca2960 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 27 Feb 2017 12:18:42 +0100 Subject: [PATCH 5/7] target/stm32f4: Document FLASH_OPTCR(1|2) registers. --- src/target/stm32f4.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 5a3d5d0..221b094 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -313,6 +313,28 @@ static bool stm32f4_cmd_erase_mass(target *t) return true; } +/* Dev | DOC |Rev|ID |OPTCR |OPTCR |OPTCR1 |OPTCR1 | OPTCR2 + |hex|default |reserved|default |resvd | default|resvd + * F20x |pm0059|5.1|411|0FFFAAED |F0000010| + * F40x |rm0090|11 |413|0FFFAAED |F0000010| + * F42x |rm0090|11 |419|0FFFAAED |30000000|0FFF0000 |F000FFFF + * F446 |rm0390| 2 |421|0FFFAAED |7F000010| + * F401BC|rm0368| 3 |423|0FFFAAED |7FC00010| + * F411 |rm0383| 2 |431|0FFFAAED |7F000010| + * F401DE|rm0368| 3 |433|0FFFAAED |7F000010| + * F46x |rm0386| 2 |434|0FFFAAED |30000000|0FFF0000 |F000FFFF + * F412 |rm0402| 4 |441|0FFFAAED*|70000010| + * F74x |rm0385| 4 |449|C0FFAAFD |3F000000|00400080*|00000000 + * F76x |rm0410| 2 |451|FFFFAAFD*|00000000|00400080*|00000000 + * F72x |rm0431| 1 |452|C0FFAAFD |3F000000|00400080*|00000000|00000000|800000FF + * F410 |rm0401| 2 |458|0FFFAAED*|7FE00010| + * F413 |rm0430| 2 |463|7FFFAAED*|00000010| + * + * * Documentation for F7 with OPTCR1 default = 0fff7f0080 seems wrong! + * * Documentation for F412 with OPTCR default = 0ffffffed seems wrong! + * * Documentation for F413 with OPTCR default = 0ffffffed seems wrong! + */ + static bool stm32f4_option_write(target *t, uint32_t value) { target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); From 8a7455f63ef014bf72f0cb0f35bb2a752e14150f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 27 Feb 2017 16:04:25 +0100 Subject: [PATCH 6/7] src/target/stm32f4.c: Add STM32F7[2|3]x. --- src/target/stm32f4.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 221b094..6ece675 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -216,6 +216,15 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x240000, 0x1C0000, 0x40000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F76x"); break; + case 0x452: /* F72x F73x RM0431 */ + t->driver = stm32f7_driver_str; + target_add_ram(t, 0x00000000, 0x2000); + target_add_ram(t, 0x20000000, 0x40000); + stm32f4_add_flash(t, 0x8000000, 0x010000, 0x4000, 0); + stm32f4_add_flash(t, 0x8010000, 0x010000, 0x10000, 4); + stm32f4_add_flash(t, 0x8020000, 0x060000, 0x20000, 3); + target_add_commands(t, stm32f4_cmd_list, "STM32F76x"); + break; default: return false; } @@ -360,7 +369,7 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) uint32_t start, val; int len; - if ((t->idcode == 0x449) || (t->idcode == 0x451)){ + if ((t->idcode == 0x449) || (t->idcode == 0x451) || (t->idcode == 0x452)) { /* F7 Devices have option bytes at 0x1FFF0000. */ start = 0x1FFF0000; len = 0x20; From 408c5a9df2c3425377d6e8f90b95e7e32b30287a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 27 Feb 2017 17:57:29 +0100 Subject: [PATCH 7/7] stm32f4: Try to handle option bytes for more devices. Correct the table for the OPTCRx values from errors in documentation and error when entering the values. --- src/target/stm32f4.c | 210 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 173 insertions(+), 37 deletions(-) diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 6ece675..5762e19 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -79,7 +79,6 @@ static const char stm32f2_driver_str[] = "STM32F2xx"; #define FLASH_OPTCR_OPTLOCK (1 << 0) #define FLASH_OPTCR_OPTSTRT (1 << 1) -#define FLASH_OPTCR_RESERVED 0xf0000013 #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -118,6 +117,23 @@ struct stm32f4_flash { uint8_t base_sector; }; +enum ID_STM32F47 { + ID_STM32F20X = 0x411, + ID_STM32F40X = 0x413, + ID_STM32F42X = 0x419, + ID_STM32F446 = 0x421, + ID_STM32F401C = 0x423, + ID_STM32F411 = 0x431, + ID_STM32F401E = 0x433, + ID_STM32F46X = 0x434, + ID_STM32F412 = 0x441, + ID_STM32F74X = 0x449, + ID_STM32F76X = 0x451, + ID_STM32F72X = 0x452, + ID_STM32F410 = 0x458, + ID_STM32F413 = 0x463 +}; + static void stm32f4_add_flash(target *t, uint32_t addr, size_t length, size_t blocksize, uint8_t base_sector) @@ -143,35 +159,35 @@ bool stm32f4_probe(target *t) idcode = target_mem_read32(t, DBGMCU_IDCODE); idcode &= 0xFFF; - if (idcode == 0x411) + if (idcode == ID_STM32F20X) { /* F405 revision A have a wrong IDCODE, use ARM_CPUID to make the * distinction with F205. Revision is also wrong (0x2000 instead * of 0x1000). See F40x/F41x errata. */ uint32_t cpuid = target_mem_read32(t, ARM_CPUID); if ((cpuid & 0xFFF0) == 0xC240) - idcode = 0x413; + idcode = ID_STM32F40X; else f2 = true; } switch(idcode) { - case 0x419: /* 427/437 */ + case ID_STM32F42X: /* 427/437 */ /* Second bank for 2M parts. */ stm32f4_add_flash(t, 0x8100000, 0x10000, 0x4000, 12); stm32f4_add_flash(t, 0x8110000, 0x10000, 0x10000, 16); stm32f4_add_flash(t, 0x8120000, 0xE0000, 0x20000, 17); /* Fall through for stuff common to F40x/F41x */ - case 0x411: /* F205 */ - case 0x413: /* F405 */ + case ID_STM32F20X: /* F205 */ + case ID_STM32F40X: /* F405 */ if (!f2) target_add_ram(t, 0x10000000, 0x10000); /* Fall through for devices w/o CCMRAM */ - case 0x421: /* F446 */ - case 0x423: /* F401 B/C RM0368 Rev.3 */ - case 0x431: /* F411 RM0383 Rev.4 */ - case 0x441: /* F412 RM0402 Rev.4, 256 kB Ram */ - case 0x433: /* F401 D/E RM0368 Rev.3 */ + case ID_STM32F446: /* F446 */ + case ID_STM32F401C: /* F401 B/C RM0368 Rev.3 */ + case ID_STM32F411: /* F411 RM0383 Rev.4 */ + case ID_STM32F412: /* F412 RM0402 Rev.4, 256 kB Ram */ + case ID_STM32F401E: /* F401 D/E RM0368 Rev.3 */ t->driver = f2 ? stm32f2_driver_str : stm32f4_driver_str; target_add_ram(t, 0x20000000, 0x40000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); @@ -180,7 +196,7 @@ bool stm32f4_probe(target *t) target_add_commands(t, stm32f4_cmd_list, f2 ? "STM32F2" : "STM32F4"); break; - case 0x463: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ + case ID_STM32F413: /* F413 RM0430 Rev.2, 320 kB Ram, 1.5 MB flash. */ t->driver = stm32f4_driver_str; target_add_ram(t, 0x20000000, 0x50000); stm32f4_add_flash(t, 0x8000000, 0x10000, 0x4000, 0); @@ -188,7 +204,7 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x8020000, 0x160000, 0x20000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F413"); break; - case 0x449: /* F74x RM0385 Rev.4 */ + case ID_STM32F74X: /* F74x RM0385 Rev.4 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x4000); target_add_ram(t, 0x20000000, 0x50000); @@ -202,7 +218,7 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x0240000, 0xC0000, 0x40000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F4x"); break; - case 0x451: /* F76x F77x RM0410 */ + case ID_STM32F76X: /* F76x F77x RM0410 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x4000); target_add_ram(t, 0x20000000, 0x80000); @@ -216,7 +232,7 @@ bool stm32f4_probe(target *t) stm32f4_add_flash(t, 0x240000, 0x1C0000, 0x40000, 5); target_add_commands(t, stm32f4_cmd_list, "STM32F76x"); break; - case 0x452: /* F72x F73x RM0431 */ + case ID_STM32F72X: /* F72x F73x RM0431 */ t->driver = stm32f7_driver_str; target_add_ram(t, 0x00000000, 0x2000); target_add_ram(t, 0x20000000, 0x40000); @@ -344,56 +360,176 @@ static bool stm32f4_cmd_erase_mass(target *t) * * Documentation for F413 with OPTCR default = 0ffffffed seems wrong! */ -static bool stm32f4_option_write(target *t, uint32_t value) +bool optcr_mask(target *t, uint32_t *val) +{ + switch (t->idcode) { + case ID_STM32F20X: + case ID_STM32F40X: + val[0] &= ~0xF0000010; + break; + case ID_STM32F46X: + case ID_STM32F42X: + val[0] &= ~0x30000000; + val[1] &= 0x0fff0000; + break; + case ID_STM32F401C: + val[0] &= ~0x7FC00010; + break; + case ID_STM32F446: + case ID_STM32F411: + case ID_STM32F401E: + val[0] &= ~0x7F000010; + break; + case ID_STM32F410: + val[0] &= ~0x7FE00010; + break; + case ID_STM32F412: + val[0] &= ~0x70000010; + break; + case ID_STM32F413: + val[0] &= ~0x00000010; + break; + case ID_STM32F72X: + val[2] &= ~0x800000ff; + /* Fall through*/ + case ID_STM32F74X: + val[0] &= ~0x3F000000; + break; + case ID_STM32F76X: + break; + default: + return false; + } + return true; +} + +static bool stm32f4_option_write(target *t, uint32_t *val, int count) { target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); - value &= ~FLASH_OPTCR_RESERVED; while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; /* WRITE option bytes instruction */ - target_mem_write32(t, FLASH_OPTCR, value); - target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); + if (((t->idcode == ID_STM32F42X) || (t->idcode == ID_STM32F46X) || + (t->idcode == ID_STM32F72X) || (t->idcode == ID_STM32F74X) || + (t->idcode == ID_STM32F76X)) && (count > 1)) + /* Checkme: Do we need to read old value and then set it? */ + target_mem_write32(t, FLASH_OPTCR + 4, val[1]); + if ((t->idcode == ID_STM32F72X) && (count > 2)) + target_mem_write32(t, FLASH_OPTCR + 8, val[2]); + + target_mem_write32(t, FLASH_OPTCR, val[0]); + target_mem_write32(t, FLASH_OPTCR, val[0] | FLASH_OPTCR_OPTSTRT); /* Read FLASH_SR to poll for BSY bit */ while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; - target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK); + target_mem_write32(t, FLASH_OPTCR, FLASH_OPTCR_OPTLOCK); return true; } +static bool stm32f4_option_write_default(target *t) +{ + uint32_t val[3]; + switch (t->idcode) { + case ID_STM32F42X: + case ID_STM32F46X: + val[0] = 0x0FFFAAED; + val[1] = 0x0FFF0000; + return stm32f4_option_write(t, val, 2); + case ID_STM32F72X: + val[0] = 0xC0FFAAFD; + val[1] = 0x00400080; + val[2] = 0; + return stm32f4_option_write(t, val, 3); + case ID_STM32F74X: + val[0] = 0xC0FFAAFD; + val[1] = 0x00400080; + return stm32f4_option_write(t, val, 2); + case ID_STM32F76X: + val[0] = 0xFFFFAAFD; + val[1] = 0x00400080; + return stm32f4_option_write(t, val, 2); + case ID_STM32F413: + val[0] = 0x7FFFAAFD; + return stm32f4_option_write(t, val, 1); + default: + val[0] = 0x0FFFAAED; + return stm32f4_option_write(t, val, 1); + } +} + static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { - uint32_t start, val; - int len; + uint32_t start = 0x1FFFC000, val[3]; + int count = 0, readcount = 1; - if ((t->idcode == 0x449) || (t->idcode == 0x451) || (t->idcode == 0x452)) { + switch (t->idcode) { + case ID_STM32F72X: /* STM32F72|3 */ + readcount++; + /* fall through.*/ + case ID_STM32F74X: + case ID_STM32F76X: /* F7 Devices have option bytes at 0x1FFF0000. */ start = 0x1FFF0000; - len = 0x20; - } - else { - start = 0x1FFFC000; - len = 0x10; + readcount++; + break; + case ID_STM32F42X: + case ID_STM32F46X: + readcount++; } if ((argc == 2) && !strcmp(argv[1], "erase")) { - stm32f4_option_write(t, 0x0fffaaed); + stm32f4_option_write_default(t); } - else if ((argc == 3) && !strcmp(argv[1], "write")) { - val = strtoul(argv[2], NULL, 0); - stm32f4_option_write(t, val); + else if ((argc > 1) && !strcmp(argv[1], "write")) { + val[0] = strtoul(argv[2], NULL, 0); + count++; + if (argc > 2) { + val[1] = strtoul(argv[3], NULL, 0); + count ++; + } + if (argc > 3) { + val[2] = strtoul(argv[4], NULL, 0); + count ++; + } + if (optcr_mask(t, val)) + stm32f4_option_write(t, val, count); + else + tc_printf(t, "error\n"); } else { tc_printf(t, "usage: monitor option erase\n"); - tc_printf(t, "usage: monitor option write \n"); + tc_printf(t, "usage: monitor option write "); + if (readcount > 1) + tc_printf(t, " "); + if (readcount > 2) + tc_printf(t, " "); + tc_printf(t, "\n"); } - for (int i = 0; i < len; i += 8) { - uint32_t addr = start + i; - val = target_mem_read32(t, addr); - tc_printf(t, "0x%08X: 0x%04X\n", addr, val & 0xFFFF); + val[0] = (target_mem_read32(t, start + 8) & 0xffff) << 16; + val[0] |= (target_mem_read32(t, start ) & 0xffff); + if (readcount > 1) { + if (start == 0x1FFFC000) /* F4 */ { + val[1] = target_mem_read32(t, start + 8 - 0x10000); + val[1] &= 0xffff; + } else { + val[1] = (target_mem_read32(t, start + 0x18) & 0xffff) << 16; + val[1] |= (target_mem_read32(t, start + 0x10) & 0xffff); + } } + if (readcount > 2) { + val[2] = (target_mem_read32(t, start + 0x28) & 0xffff) << 16; + val[2] |= (target_mem_read32(t, start + 0x20) & 0xffff); + } + optcr_mask(t, val); + tc_printf(t, "OPTCR: 0x%08X ", val[0]); + if (readcount > 1) + tc_printf(t, "OPTCR1: 0x%08X ", val[1]); + if (readcount > 2) + tc_printf(t, "OPTCR2: 0x%08X" , val[2]); + tc_printf(t, "\n"); return true; }