Skip to content

Commit dfd58cd

Browse files
committed
Draft of initial nRF91 support.
1 parent 6c193f0 commit dfd58cd

File tree

6 files changed

+114
-0
lines changed

6 files changed

+114
-0
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ SRC = \
5757
morse.c \
5858
msp432.c \
5959
nrf51.c \
60+
nrf91.c \
6061
nxpke04.c \
6162
platform.c \
6263
remote.c \

src/target/adiv5.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,11 @@ adiv5_access_port_s *adiv5_new_ap(adiv5_debug_port_s *dp, uint8_t apsel)
687687
return NULL;
688688
}
689689

690+
if (tmpap.idr == 0x84770001) {
691+
// Clear HNONSEC bit to enable secure accesses.
692+
tmpap.csw &= ~(1U << 30U);
693+
}
694+
690695
/* It's valid to so create a heap copy */
691696
adiv5_access_port_s *ap = malloc(sizeof(*ap));
692697
if (!ap) { /* malloc failed: heap exhaustion */

src/target/cortexm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@ bool cortexm_probe(adiv5_access_port_s *ap)
683683
break;
684684
case JEP106_MANUFACTURER_NORDIC:
685685
PROBE(nrf51_probe);
686+
PROBE(nrf91_probe);
686687
break;
687688
case JEP106_MANUFACTURER_ATMEL:
688689
PROBE(samx7x_probe);

src/target/nrf91.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include "general.h"
2+
#include "target.h"
3+
#include "target_internal.h"
4+
#include "cortexm.h"
5+
#include "adiv5.h"
6+
7+
/* Non-Volatile Memory Controller (NVMC) Registers */
8+
#define NRF91_NVMC 0x50039000U
9+
#define NRF91_NVMC_READY (NRF91_NVMC + 0x400U)
10+
#define NRF91_NVMC_CONFIG (NRF91_NVMC + 0x504U)
11+
#define NRF91_NVMC_ERASEALL (NRF91_NVMC + 0x50cU)
12+
13+
#define NRF91_NVMC_CONFIG_REN 0x0U // Read only access
14+
#define NRF91_NVMC_CONFIG_WEN 0x1U // Write enable
15+
#define NRF91_NVMC_CONFIG_EEN 0x2U // Erase enable
16+
#define NRF91_NVMC_CONFIG_PEEN 0x3U // Partial erase enable
17+
18+
static bool nrf91_wait_ready(target_s *const t, platform_timeout_s *const timeout)
19+
{
20+
/* Poll for NVMC_READY */
21+
while (target_mem_read32(t, NRF91_NVMC_READY) == 0) {
22+
if (target_check_error(t))
23+
return false;
24+
if (timeout)
25+
target_print_progress(timeout);
26+
}
27+
return true;
28+
}
29+
30+
static bool nrf91_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
31+
{
32+
target_s *t = f->t;
33+
34+
/* Enable erase */
35+
target_mem_write32(t, NRF91_NVMC_CONFIG, NRF91_NVMC_CONFIG_EEN);
36+
if (!nrf91_wait_ready(t, NULL))
37+
return false;
38+
39+
for (size_t offset = 0; offset < len; offset += f->blocksize) {
40+
/* Write all ones to first word in page to erase it */
41+
target_mem_write32(t, addr + offset, 0xffffffffU);
42+
43+
if (!nrf91_wait_ready(t, NULL))
44+
return false;
45+
}
46+
47+
/* Return to read-only */
48+
target_mem_write32(t, NRF91_NVMC_CONFIG, NRF91_NVMC_CONFIG_REN);
49+
return nrf91_wait_ready(t, NULL);
50+
}
51+
52+
static bool nrf91_flash_write(target_flash_s *f, target_addr_t dest, const void *src, size_t len)
53+
{
54+
target_s *t = f->t;
55+
56+
/* Enable write */
57+
target_mem_write32(t, NRF91_NVMC_CONFIG, NRF91_NVMC_CONFIG_WEN);
58+
if (!nrf91_wait_ready(t, NULL))
59+
return false;
60+
/* Write the data */
61+
target_mem_write(t, dest, src, len);
62+
if (!nrf91_wait_ready(t, NULL))
63+
return false;
64+
/* Return to read-only */
65+
target_mem_write32(t, NRF91_NVMC_CONFIG, NRF91_NVMC_CONFIG_REN);
66+
return true;
67+
}
68+
69+
static void nrf91_add_flash(target_s *t, uint32_t addr, size_t length, size_t erasesize)
70+
{
71+
target_flash_s *f = calloc(1, sizeof(*f));
72+
if (!f) { /* calloc failed: heap exhaustion */
73+
DEBUG_WARN("calloc: failed in %s\n", __func__);
74+
return;
75+
}
76+
77+
f->start = addr;
78+
f->length = length;
79+
f->blocksize = erasesize;
80+
f->erase = nrf91_flash_erase;
81+
f->write = nrf91_flash_write;
82+
f->erased = 0xff;
83+
target_add_flash(t, f);
84+
}
85+
86+
bool nrf91_probe(target_s *t) {
87+
adiv5_access_port_s *ap = cortexm_ap(t);
88+
89+
if (ap->dp->version < 2U) {
90+
return false;
91+
}
92+
93+
switch (ap->dp->target_partno) {
94+
case 0x90:
95+
t->driver = "Nordic nRF9160";
96+
t->target_options |= CORTEXM_TOPT_INHIBIT_NRST;
97+
target_add_ram(t, 0x20000000, 256U * 1024U);
98+
nrf91_add_flash(t, 0, 4096U * 256U, 4096U);
99+
break;
100+
default:
101+
return false;
102+
}
103+
104+
return true;
105+
}

src/target/target_probe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ TARGET_PROBE_WEAK_NOP(samx7x_probe)
104104
TARGET_PROBE_WEAK_NOP(sam3x_probe)
105105
TARGET_PROBE_WEAK_NOP(sam4l_probe)
106106
TARGET_PROBE_WEAK_NOP(nrf51_probe)
107+
TARGET_PROBE_WEAK_NOP(nrf91_probe)
107108
TARGET_PROBE_WEAK_NOP(samd_probe)
108109
TARGET_PROBE_WEAK_NOP(samx5x_probe)
109110
TARGET_PROBE_WEAK_NOP(kinetis_probe)

src/target/target_probe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ bool samx7x_probe(target_s *target);
6363
bool sam3x_probe(target_s *target);
6464
bool sam4l_probe(target_s *target);
6565
bool nrf51_probe(target_s *target);
66+
bool nrf91_probe(target_s *target);
6667
bool samd_probe(target_s *target);
6768
bool samx5x_probe(target_s *target);
6869
bool kinetis_probe(target_s *target);

0 commit comments

Comments
 (0)