mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
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...
This commit is contained in:
parent
b4664a5bd3
commit
0ca02de0a2
24
dist/tools/nrf52_resetpin_cfg/Makefile
vendored
Normal file
24
dist/tools/nrf52_resetpin_cfg/Makefile
vendored
Normal file
@ -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
|
||||
18
dist/tools/nrf52_resetpin_cfg/README.md
vendored
Normal file
18
dist/tools/nrf52_resetpin_cfg/README.md
vendored
Normal file
@ -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.
|
||||
131
dist/tools/nrf52_resetpin_cfg/main.c
vendored
Normal file
131
dist/tools/nrf52_resetpin_cfg/main.c
vendored
Normal file
@ -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 <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user