From 0ca02de0a2f52097e43b20fce6d5b425aac73f99 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 28 Sep 2018 16:49:35 +0200 Subject: [PATCH 1/2] tools: add nrf52_resetpin_cfg tool This new tool allows configuring the reset pin for nRF52-based boards. As the reset pin configuration is persistent, it does not make sense to include it into the board code... --- dist/tools/nrf52_resetpin_cfg/Makefile | 24 +++++ dist/tools/nrf52_resetpin_cfg/README.md | 18 ++++ dist/tools/nrf52_resetpin_cfg/main.c | 131 ++++++++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 dist/tools/nrf52_resetpin_cfg/Makefile create mode 100644 dist/tools/nrf52_resetpin_cfg/README.md create mode 100644 dist/tools/nrf52_resetpin_cfg/main.c diff --git a/dist/tools/nrf52_resetpin_cfg/Makefile b/dist/tools/nrf52_resetpin_cfg/Makefile new file mode 100644 index 000000000000..23c5e784169c --- /dev/null +++ b/dist/tools/nrf52_resetpin_cfg/Makefile @@ -0,0 +1,24 @@ +# name of your application +APPLICATION = nrf52_resetpin_cfg + +# configure RIOT basics +BOARD ?= nrf52dk +RIOTBASE ?= $(CURDIR)/../../.. + +# the RESET_PIN environment variable allows for manually specifying the reset +# pin that is programmed. Below this Makefile already contains the specific pins +# for some known platforms +ifeq (nrf52dk,$(BOARD)) + RESET_PIN ?= 21 +endif +ifeq (nrf52840dk,$(BOARD)) + RESET_PIN ?= 18 +endif +ifeq (,$(RESET_PIN)) + $(error Please specify the target reset pin using the RESET_PIN env variable) +else + CFLAGS += -DRESET_PIN=$(RESET_PIN) +endif + + +include $(RIOTBASE)/Makefile.include diff --git a/dist/tools/nrf52_resetpin_cfg/README.md b/dist/tools/nrf52_resetpin_cfg/README.md new file mode 100644 index 000000000000..e7634c924ee8 --- /dev/null +++ b/dist/tools/nrf52_resetpin_cfg/README.md @@ -0,0 +1,18 @@ +Program the reset pin for nRF52x CPUs +===================================== + +Simply compile, flash, and run this tool on your nRF52x-based board. It will +program the given `RESET_PIN` into the NRF_UICR->PSELRESET registers, hence +allowing for hardware resets using a button connected to that pin. + + +Context +======= +For nRF52x CPUs, the reset pin is programmable. The reset pin configuration is +store in two persistent registers, that are programmed in the same way as the +CPUs flash memory. + +In most cases, these values should be readily programmed when you get your +board, and thus do not need to be touched. However, we have seen however a +number of nrf52xxxdk boards, where this was not the case and the on-board reset +button did have no effect. Running this tool on those boards solves the issue. diff --git a/dist/tools/nrf52_resetpin_cfg/main.c b/dist/tools/nrf52_resetpin_cfg/main.c new file mode 100644 index 000000000000..fd7a72141019 --- /dev/null +++ b/dist/tools/nrf52_resetpin_cfg/main.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tools + * @{ + * + * @file + * @brief Tool for programming the reset pin on nRF52x-based boards + * + * @author Hauke Petersen + * + * @} + */ + +#include +#include + +#include "cpu.h" +#include "periph/pm.h" + +/* guard against bad usage: only allow building for nRF52x CPUs */ +#ifndef CPU_NRF52 +#error This tool is only usable for nRF52x-based platforms +#endif + +#ifndef RESET_PIN +#error RESET_PIN not specified +#endif + +#define PORT_BIT (0x00000020) +#define PORT_POS (5U) +#define PIN_MASK (0x0000001f) + +#define RESET_VAL (0xffffffff) + +#define REG_NUM (sizeof(NRF_UICR_Type) / 4) + +/* allocate a copy of the registers in RAM */ +static NRF_UICR_Type _buf; + +static void _print_pin(uint32_t p) +{ + printf("P%i.%2i", (int)((p & PORT_BIT) >> PORT_POS), (int)(p & PIN_MASK)); +} + +static void _copy(volatile uint32_t *dst, volatile uint32_t *src, unsigned num) +{ + for (unsigned i = 0; i < num; i++) { + *dst++ = *src++; + } +} + +static void _save_uicr(void) +{ + memcpy(&_buf, (void *)NRF_UICR, sizeof(NRF_UICR_Type)); +} + +static void _restore_uicr(void) +{ + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {} + + /* we copy the values back selectively, skipping the PSELRESET fields */ + _copy(NRF_UICR->NRFFW, _buf.NRFFW, 15); + _copy(NRF_UICR->NRFHW, _buf.NRFHW, 12); + _copy(NRF_UICR->CUSTOMER, _buf.CUSTOMER, 32); + NRF_UICR->APPROTECT = _buf.APPROTECT; + NRF_UICR->NFCPINS = _buf.NFCPINS; +#ifdef CPU_MODEL_NRF52840XXAA + NRF_UICR->EXTSUPPLY = _buf.EXTSUPPLY; + NRF_UICR->REGOUT0 = _buf.REGOUT0; +#endif + + /* we can leave the NVMC in write enable mode when leaving... */ +} + +int main(void) +{ + uint32_t target = (uint32_t)RESET_PIN; + + if ((NRF_UICR->PSELRESET[0] == target) && + (NRF_UICR->PSELRESET[1] == target)) { + puts("\nAll good!"); + _print_pin(target); + puts(" programmed as reset pin\n"); + puts("Now press the reset button to confirm its function!"); + } + else { + puts("\nReset pin is not programmed properly"); + printf("Will now program it to "); + _print_pin(target); + puts("\n\nPress any key (meaning send any char) to continue"); + getchar(); + + puts("Progamming the pin now..."); + if ((NRF_UICR->PSELRESET[0] != RESET_VAL) || + (NRF_UICR->PSELRESET[1] != RESET_VAL)) { + /* we can only erase all UICR registers at once, so we need to save + * and restore there values for clearing the PSELRESET registers */ + puts("save uicr"); + _save_uicr(); + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {} + NRF_NVMC->ERASEUICR = 1; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {} + puts("restore"); + _restore_uicr(); + } + + puts("promming new value to PSELRESET"); + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {} + NRF_UICR->PSELRESET[0] = target; + NRF_UICR->PSELRESET[1] = target; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {} + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren; + + /* verify result */ + puts("The changes will only take effect after reboot.\n" + "Doing a reboot now...\n"); + pm_reboot(); + } + + return 0; +} From 19d0da08f99db03f5c4499b2a569cf5d35b672be Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 28 Sep 2018 16:58:38 +0200 Subject: [PATCH 2/2] boards/nrf52xdk: add doc for reset pin config --- boards/nrf52840dk/doc.txt | 11 +++++++++++ boards/nrf52dk/doc.txt | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/boards/nrf52840dk/doc.txt b/boards/nrf52840dk/doc.txt index 119e425d3028..3129f874825b 100644 --- a/boards/nrf52840dk/doc.txt +++ b/boards/nrf52840dk/doc.txt @@ -2,4 +2,15 @@ @defgroup boards_nrf52840dk nRF52840 DK @ingroup boards @brief Support for the nRF52840 DK + + +### RESET pin configuration + +On many (all?) nrf52840dk boards, the reset pin is not configured out-of-the box. +This means, that simply nothing happens if the RESET pin is pressed. To change +this, RIOT provides a little tool in `dist/tools/nrf52_resetpin_cfg`. + +Simply compile, flash, and run that tool on your board, and the reset pin should +work for the time being. + */ diff --git a/boards/nrf52dk/doc.txt b/boards/nrf52dk/doc.txt index ffec7d364f34..b32c08d7e5e4 100644 --- a/boards/nrf52dk/doc.txt +++ b/boards/nrf52dk/doc.txt @@ -90,6 +90,15 @@ board](https://github.com/d00616/temp/raw/master/nrf52-minidev.jpg) **Caution**: NFC is not usable with this board. +### RESET pin configuration + +On many (all?) nrf52dk boards, the reset pin is not configured out-of-the box. +This means, that simply nothing happens if the RESET pin is pressed. To change +this, RIOT provides a little tool in `dist/tools/nrf52_resetpin_cfg`. + +Simply compile, flash, and run that tool on your board, and the reset pin should +work for the time being. + ## Current measurement: There are two pins for current measurement on board. Don't connect these pins