From a336ac20847b6f2059a8f77f774362699cfbd32b Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 19 Dec 2018 14:20:06 +0100 Subject: [PATCH 1/5] NRF5: New detection scheme. --- src/target/nrf51.c | 107 ++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 75 deletions(-) diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 95c5f0d5789..182bf026201 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -74,6 +74,8 @@ const struct command_s nrf51_read_cmd_list[] = { #define NRF51_FICR_DEVICEADDRTYPE (NRF51_FICR + 0x0A0) #define NRF51_FICR_DEVICEADDR_LOW (NRF51_FICR + 0x0A4) #define NRF51_FICR_DEVICEADDR_HIGH (NRF51_FICR + 0x0A8) +#define NRF52_PART_INFO (NRF51_FICR + 0x100) +#define NRF52_INFO_RAM (NRF51_FICR + 0x10C) /* User Information Configuration Registers (UICR) */ #define NRF51_UICR 0x10001000 @@ -103,87 +105,42 @@ static void nrf51_add_flash(target *t, bool nrf51_probe(target *t) { - t->idcode = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF; - - switch (t->idcode) { - case 0x001D: /* nRF51822 (rev 1) QFAA CA/C0 */ - case 0x001E: /* nRF51422 (rev 1) QFAA CA */ - case 0x0020: /* nRF51822 (rev 1) CEAA BA */ - case 0x0024: /* nRF51422 (rev 1) QFAA C0 */ - case 0x002A: /* nRF51822 (rev 2) QFAA FA0 */ - case 0x004A: /* nRF51822 (rev 3) QFAA G1 */ - case 0x002D: /* nRF51422 (rev 2) QFAA DAA */ - case 0x002E: /* nRF51422 (rev 2) QFAA E0 */ - case 0x002F: /* nRF51822 (rev 1) CEAA B0 */ - case 0x0031: /* nRF51422 (rev 1) CEAA A0A */ - case 0x003C: /* nRF51822 (rev 2) QFAA G0 */ - case 0x0057: /* nRF51422 (rev 2) QFAA G2 */ - case 0x0040: /* nRF51822 (rev 2) CEAA CA0 */ - case 0x0044: /* nRF51822 (rev 2) QFAA GC0 */ - case 0x0047: /* nRF51822 (rev 2) CEAA DA0 */ - case 0x004D: /* nRF51822 (rev 2) CEAA D00 */ - case 0x0050: /* nRF51422 (rev 2) CEAA B0 */ - case 0x0072: /* nRF51822 (rev 3) QFAA H0 */ - case 0x0073: /* nRF51422 (rev 3) QFAA F0 */ - case 0x0079: /* nRF51822 (rev 3) CEAA E0 */ - case 0x007A: /* nRF51422 (rev 3) CEAA C0 */ - case 0x008F: /* nRF51822 (rev 3) QFAA H1 See https://devzone.nordicsemi.com/question/97769/can-someone-conform-the-config-id-code-for-the-nrf51822qfaah1/ */ - case 0x00D1: /* nRF51822 (rev 3) QFAA H2 */ - case 0x0114: /* nRF51802 (rev ?) QFAA A1 */ - t->driver = "Nordic nRF51"; - target_add_ram(t, 0x20000000, 0x4000); - nrf51_add_flash(t, 0x00000000, 0x40000, NRF51_PAGE_SIZE); - nrf51_add_flash(t, NRF51_UICR, 0x100, 0x100); - target_add_commands(t, nrf51_cmd_list, "nRF51"); - return true; - case 0x0026: /* nRF51822 (rev 1) QFAB AA */ - case 0x0027: /* nRF51822 (rev 1) QFAB A0 */ - case 0x004C: /* nRF51822 (rev 2) QFAB B0 */ - case 0x0061: /* nRF51422 (rev 2) QFAB A00 */ - case 0x007B: /* nRF51822 (rev 3) QFAB C0 */ - case 0x007C: /* nRF51422 (rev 3) QFAB B0 */ - case 0x007D: /* nRF51822 (rev 3) CDAB A0 */ - case 0x007E: /* nRF51422 (rev 3) CDAB A0 */ - t->driver = "Nordic nRF51"; - target_add_ram(t, 0x20000000, 0x4000); - nrf51_add_flash(t, 0x00000000, 0x20000, NRF51_PAGE_SIZE); - nrf51_add_flash(t, NRF51_UICR, 0x100, 0x100); - target_add_commands(t, nrf51_cmd_list, "nRF51"); + uint32_t page_size = target_mem_read32(t, NRF51_FICR_CODEPAGESIZE); + uint32_t code_size = target_mem_read32(t, NRF51_FICR_CODESIZE); + /* Check that page_size and code_size makes sense */ + if ((page_size == 0xffffffff) || (code_size == 0xffffffff) || + (page_size == 0) || (code_size == 0) || + (page_size > 0x10000) || (code_size > 0x10000)) + return false; + /* Check that device identifier makes sense */ + uint32_t uid0 = target_mem_read32(t, NRF51_FICR_DEVICEID_LOW); + uint32_t uid1 = target_mem_read32(t, NRF51_FICR_DEVICEID_HIGH); + if ((uid0 == 0xffffffff) || (uid1 == 0xffffffff) || + (uid0 == 0) || (uid1 == 0)) + return false; + /* Test for NRF52 device*/ + uint32_t info_part = target_mem_read32(t, NRF52_PART_INFO); + if ((info_part != 0xffffffff) && (info_part != 0) && + ((info_part & 0x00ff000) == 0x52000)) { + uint32_t ram_size = target_mem_read32(t, NRF52_INFO_RAM); + t->idcode = info_part; + t->driver = "Nordic nRF52"; + target_add_ram(t, 0x20000000, ram_size * 1024); + nrf51_add_flash(t, 0, page_size * code_size, page_size); + nrf51_add_flash(t, NRF51_UICR, page_size, page_size); + target_add_commands(t, nrf51_cmd_list, "nRF52"); return true; - case 0x0071: /* nRF51422 (rev 3) QFAC AB */ - case 0x0083: /* nRF51822 (rev 3) QFAC A0 */ - case 0x0084: /* nRF51422 (rev 3) QFAC A1 */ - case 0x0085: /* nRF51422 (rev 3) QFAC A0 */ - case 0x0086: /* nRF51422 (rev 3) QFAC A1 */ - case 0x0087: /* nRF51822 (rev 3) CFAC A0 */ - case 0x0088: /* nRF51422 (rev 3) CFAC A0 */ + } else { t->driver = "Nordic nRF51"; + /* Use the biggest RAM size seen in NRF51 fammily. + * IDCODE is kept as '0', as deciphering is hard and + * there is later no usage.*/ target_add_ram(t, 0x20000000, 0x8000); - nrf51_add_flash(t, 0x00000000, 0x40000, NRF51_PAGE_SIZE); - nrf51_add_flash(t, NRF51_UICR, 0x100, 0x100); + nrf51_add_flash(t, 0, page_size * code_size, page_size); + nrf51_add_flash(t, NRF51_UICR, page_size, page_size); target_add_commands(t, nrf51_cmd_list, "nRF51"); return true; - case 0x00AC: /* nRF52832 Preview QFAA BA0 */ - case 0x00C7: /* nRF52832 (rev 1) QFAA B00 */ - case 0x00E3: /* nRF52832 (rev 1) CIAA B?? */ - case 0x0139: /* nRF52832 (rev 2) ??AA B?0 */ - case 0x014F: /* nRF52832 (rev 2) CIAA E1 */ - t->driver = "Nordic nRF52"; - target_add_ram(t, 0x20000000, 64*1024); - nrf51_add_flash(t, 0x00000000, 512*1024, NRF52_PAGE_SIZE); - nrf51_add_flash(t, NRF51_UICR, 0x100, 0x100); - target_add_commands(t, nrf51_cmd_list, "nRF52"); - return true; - case 0x00EB: /* nRF52840 Preview QIAA AA0 */ - case 0x0150: /* nRF52840 QIAA C0 */ - t->driver = "Nordic nRF52"; - target_add_ram(t, 0x20000000, 256*1024); - nrf51_add_flash(t, 0x00000000, 1024*1024, NRF52_PAGE_SIZE); - nrf51_add_flash(t, NRF51_UICR, 0x100, 0x100); - target_add_commands(t, nrf51_cmd_list, "nRF52"); - return true; } - return false; } From db2f4034178110f7a7547abd54a48f0b9110f4dd Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 20 Dec 2018 19:35:40 +0100 Subject: [PATCH 2/5] sam4l: Remove noisy debug message. --- src/target/sam4l.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/sam4l.c b/src/target/sam4l.c index 54bcc52dfc6..1db37ba389d 100644 --- a/src/target/sam4l.c +++ b/src/target/sam4l.c @@ -223,7 +223,6 @@ bool sam4l_probe(target *t) { size_t ram_size, flash_size; - DEBUG("\nSAM4L: Probe function called\n"); t->idcode = target_mem_read32(t, SAM4L_CHIPID_CIDR); if (((t->idcode >> CHIPID_CIDR_ARCH_SHIFT) & CHIPID_CIDR_ARCH_MASK) == SAM4L_ARCH) { t->driver = "Atmel SAM4L"; From 4ecd13a9a3facb93f715b568222d5e88c0c29627 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 22 Dec 2018 20:47:38 +0100 Subject: [PATCH 3/5] nrf51: Fix crash with not argument given to "mon read". --- src/target/nrf51.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 182bf026201..4b5da81ca61 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -283,15 +283,15 @@ static bool nrf51_cmd_read_help(target *t) static bool nrf51_cmd_read(target *t, int argc, const char *argv[]) { const struct command_s *c; - - for(c = nrf51_read_cmd_list; c->cmd; c++) { - /* Accept a partial match as GDB does. - * So 'mon ver' will match 'monitor version' - */ - if(!strncmp(argv[1], c->cmd, strlen(argv[1]))) - return !c->handler(t, argc - 1, &argv[1]); + if (argc > 1) { + for(c = nrf51_read_cmd_list; c->cmd; c++) { + /* Accept a partial match as GDB does. + * So 'mon ver' will match 'monitor version' + */ + if(!strncmp(argv[1], c->cmd, strlen(argv[1]))) + return !c->handler(t, argc - 1, &argv[1]); + } } - return nrf51_cmd_read_help(t); } From 3f89fed32ea73caba5e8205e40f084251f08e172 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 22 Dec 2018 21:17:33 +0100 Subject: [PATCH 4/5] nrf51: Use buffered direct write to flash. --- src/target/flashstub/Makefile | 2 +- src/target/flashstub/nrf51.c | 37 ----------------------------------- src/target/nrf51.c | 23 ++++++---------------- 3 files changed, 7 insertions(+), 55 deletions(-) delete mode 100644 src/target/flashstub/nrf51.c diff --git a/src/target/flashstub/Makefile b/src/target/flashstub/Makefile index abc03a4e39f..4eb42a1d4ee 100644 --- a/src/target/flashstub/Makefile +++ b/src/target/flashstub/Makefile @@ -11,7 +11,7 @@ endif CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../../../libopencm3/include ASFLAGS=-mcpu=cortex-m3 -mthumb -all: lmi.stub stm32l4.stub nrf51.stub efm32.stub +all: lmi.stub stm32l4.stub efm32.stub %.o: %.c $(Q)echo " CC $<" diff --git a/src/target/flashstub/nrf51.c b/src/target/flashstub/nrf51.c deleted file mode 100644 index d2915925945..00000000000 --- a/src/target/flashstub/nrf51.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2017 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * 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 3 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, see . - */ -#include -#include "stub.h" - -/* Non-Volatile Memory Controller (NVMC) Registers */ -#define NVMC ((volatile uint32_t *)0x4001E000) -#define NVMC_READY NVMC[0x100] - -void __attribute__((naked)) -nrf51_flash_write_stub(volatile uint32_t *dest, uint32_t *src, uint32_t size) -{ - for (int i; i < size; i += 4) { - *dest++ = *src++; - while (!(NVMC_READY & 1)) - ; - } - - stub_exit(0); -} diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 4b5da81ca61..1bbe0346a8c 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -83,13 +83,6 @@ const struct command_s nrf51_read_cmd_list[] = { #define NRF51_PAGE_SIZE 1024 #define NRF52_PAGE_SIZE 4096 -#define SRAM_BASE 0x20000000 -#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(nrf51_flash_write_stub), 4) - -static const uint16_t nrf51_flash_write_stub[] = { -#include "flashstub/nrf51.stub" -}; - static void nrf51_add_flash(target *t, uint32_t addr, size_t length, size_t erasesize) { @@ -192,22 +185,18 @@ static int nrf51_flash_write(struct target_flash *f, /* Enable write */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); - /* Poll for NVMC_READY */ while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return -1; - - /* Write stub and data to target ram and call stub */ - target_mem_write(t, SRAM_BASE, nrf51_flash_write_stub, - sizeof(nrf51_flash_write_stub)); - target_mem_write(t, STUB_BUFFER_BASE, src, len); - int ret = cortexm_run_stub(t, SRAM_BASE, dest, - STUB_BUFFER_BASE, len, 0); + target_mem_write(t, dest, src, len); + /* Poll for NVMC_READY */ + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) + return -1; /* Return to read-only */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); - - return ret; + return 0; } static bool nrf51_cmd_erase_all(target *t) From 691ada17e995b99ddc80101410f661a721c5cd98 Mon Sep 17 00:00:00 2001 From: Boris Sorochkin Date: Wed, 19 Dec 2018 22:57:07 +0200 Subject: [PATCH 5/5] Implement read device info for NRF5x --- src/target/nrf51.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 1bbe0346a8c..ad1b55448fe 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -35,6 +35,7 @@ static bool nrf51_cmd_read_hwid(target *t); static bool nrf51_cmd_read_fwid(target *t); static bool nrf51_cmd_read_deviceid(target *t); static bool nrf51_cmd_read_deviceaddr(target *t); +static bool nrf51_cmd_read_deviceinfo(target *t); static bool nrf51_cmd_read_help(target *t); static bool nrf51_cmd_read(target *t, int argc, const char *argv[]); @@ -49,6 +50,7 @@ const struct command_s nrf51_read_cmd_list[] = { {"fwid", (cmd_handler)nrf51_cmd_read_fwid, "Read pre-loaded firmware ID"}, {"deviceid", (cmd_handler)nrf51_cmd_read_deviceid, "Read unique device ID"}, {"deviceaddr", (cmd_handler)nrf51_cmd_read_deviceaddr, "Read device address"}, + {"deviceinfo", (cmd_handler)nrf51_cmd_read_deviceinfo, "Read device information"}, {NULL, NULL, NULL} }; @@ -76,6 +78,15 @@ const struct command_s nrf51_read_cmd_list[] = { #define NRF51_FICR_DEVICEADDR_HIGH (NRF51_FICR + 0x0A8) #define NRF52_PART_INFO (NRF51_FICR + 0x100) #define NRF52_INFO_RAM (NRF51_FICR + 0x10C) +/* Device Info Registers */ +#define NRF51_FICR_DEVICE_INFO_BASE (NRF51_FICR + 0x100) +#define NRF51_FICR_DEVICE_INFO_PART NRF51_FICR_DEVICE_INFO_BASE +#define NRF51_FICR_DEVICE_INFO_VARIANT (NRF51_FICR_DEVICE_INFO_BASE + 4) +#define NRF51_FICR_DEVICE_INFO_PACKAGE (NRF51_FICR_DEVICE_INFO_BASE + 8) +#define NRF51_FICR_DEVICE_INFO_RAM (NRF51_FICR_DEVICE_INFO_BASE + 12) +#define NRF51_FICR_DEVICE_INFO_FLASH (NRF51_FICR_DEVICE_INFO_BASE + 16) + +#define NRF51_FIELD_UNSPECIFIED (0xFFFFFFFF) /* User Information Configuration Registers (UICR) */ #define NRF51_UICR 0x10001000 @@ -245,6 +256,56 @@ static bool nrf51_cmd_read_deviceid(target *t) return true; } + +static bool nrf51_cmd_read_deviceinfo(target *t) +{ + struct deviceinfo{ + uint32_t part; + union{ + char c[4]; + uint32_t f; + } variant; + uint32_t package; + uint32_t ram; + uint32_t flash; + } di; + di.package = target_mem_read32(t, NRF51_FICR_DEVICE_INFO_PACKAGE); + di.part = target_mem_read32(t, NRF51_FICR_DEVICE_INFO_PART); + di.ram = target_mem_read32(t, NRF51_FICR_DEVICE_INFO_RAM); + di.flash = target_mem_read32(t, NRF51_FICR_DEVICE_INFO_FLASH); + di.variant.f = target_mem_read32(t, NRF51_FICR_DEVICE_INFO_VARIANT); + + tc_printf(t, "Part:\t\tNRF%X\n",di.part); + tc_printf(t, "Variant:\t%c%c%c%c\n", + di.variant.c[3], + di.variant.c[2], + di.variant.c[1], + di.variant.c[0]); + tc_printf(t, "Package:\t"); + switch (di.package) + { + case NRF51_FIELD_UNSPECIFIED: + tc_printf(t,"Unspecified\n"); + break; + case 0x2000: + tc_printf(t,"QF\n"); + break; + case 0x2001: + tc_printf(t,"CI\n"); + break; + case 0x2004: + tc_printf(t,"QIxx\n"); + break; + default: + tc_printf(t,"Unknown (Code %X)\n",di.package); + break; + } + + tc_printf(t, "Ram:\t\t%uK\n", di.ram); + tc_printf(t, "Flash:\t\t%uK\n", di.flash); + return true; +} + static bool nrf51_cmd_read_deviceaddr(target *t) { uint32_t addr_type = target_mem_read32(t, NRF51_FICR_DEVICEADDRTYPE);