Skip to content

Commit 3dc71c8

Browse files
lemreycarlescufi
authored andcommitted
boards: arm: nrf52840_pca10090: add a GPIO reset line
Let one of the MCU interface pins be configured to act as a reset line. This mitigates the lack of a connection between the nRF9160 and nRF52840 PINRESET. Minor refactoring and updated comments. Signed-off-by: Emanuele Di Santo <[email protected]>
1 parent 0604e21 commit 3dc71c8

File tree

3 files changed

+227
-20
lines changed

3 files changed

+227
-20
lines changed

boards/arm/nrf52840_pca10090/Kconfig

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,65 @@ config BOARD_PCA10090_INTERFACE2_MCU
192192

193193
endchoice
194194

195+
config BOARD_PCA10090_NRF52840_RESET
196+
bool "Enable GPIO reset line"
197+
help
198+
Let the nRF52840 be reset from the nRF9160 via a GPIO line.
199+
The GPIO line may only be one of the first 6 MCU interface pins.
200+
The line is active high.
201+
202+
if BOARD_PCA10090_NRF52840_RESET
203+
204+
choice
205+
prompt "Pin used for reset"
206+
207+
comment "nRF52840 pins"
208+
209+
config BOARD_PCA10090_NRF52840_RESET_P0_17
210+
bool "P0.17"
211+
depends on BOARD_PCA10090_INTERFACE0_MCU
212+
help
213+
Pin P0.17 on nRF52840,
214+
connected to P0.17 on the nRF9160.
215+
216+
config BOARD_PCA10090_NRF52840_RESET_P0_20
217+
bool "P0.20"
218+
depends on BOARD_PCA10090_INTERFACE0_MCU
219+
help
220+
Pin P0.20 on nRF52840,
221+
connected to P0.18 on the nRF9160.
222+
223+
config BOARD_PCA10090_NRF52840_RESET_P0_15
224+
bool "P0.15"
225+
depends on BOARD_PCA10090_INTERFACE0_MCU
226+
help
227+
Pin P0.15 on nRF52840,
228+
connected to P0.19 on the nRF9160.
229+
230+
config BOARD_PCA10090_NRF52840_RESET_P0_22
231+
bool "P0.22"
232+
depends on BOARD_PCA10090_INTERFACE1_MCU
233+
help
234+
Pin P0.22 on nRF52840,
235+
connected to P0.21 on the nRF9160.
236+
237+
config BOARD_PCA10090_NRF52840_RESET_P1_04
238+
bool "P1.04"
239+
depends on BOARD_PCA10090_INTERFACE1_MCU
240+
help
241+
Pin P1.04 on nRF52840,
242+
connected to P0.22 on the nRF9160.
243+
244+
config BOARD_PCA10090_NRF52840_RESET_P1_02
245+
bool "P1.02"
246+
depends on BOARD_PCA10090_INTERFACE1_MCU
247+
help
248+
Pin P1.02 on nRF52840,
249+
connected to P0.23 on the nRF9160.
250+
251+
endchoice
252+
253+
endif # BOARD_PCA10090_NRF52840_RESET
195254

196255
module = BOARD_PCA10090
197256
module-str = Board Control

boards/arm/nrf52840_pca10090/board.c

Lines changed: 159 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_PCA10090_LOG_LEVEL);
2121
*/
2222

2323
/* GPIO pins on Port 0 */
24+
2425
#define INTERFACE0_U5 13 /* MCU interface pins 0 - 2 */
2526
#define INTERFACE1_U6 24 /* MCU interface pins 3 - 5 */
2627
#define UART1_VCOM_U7 12 /* Route nRF9160 UART1 to VCOM2 */
@@ -29,6 +30,7 @@ LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_PCA10090_LOG_LEVEL);
2930
#define SWITCH2_U9 8
3031

3132
/* GPIO pins on Port 1 */
33+
3234
#define INTERFACE2_U21 10 /* COEX interface pins 6 - 8 */
3335
#define UART0_VCOM_U14 14 /* Route nRF9160 UART0 to VCOM0 */
3436
#define UART1_VCOM_U7 12 /* Route nRF9160 UART1 to VCOM2 */
@@ -53,12 +55,18 @@ LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_PCA10090_LOG_LEVEL);
5355
* | COEX2 | -- MCU Interface Pin 8 -- | P1.15 | COEX2_PH |
5456
*/
5557

56-
/* The following tables specify the -default- values for each pin.
57-
* Thus, when configuring the pins if there is a one in this table,
58-
* pull the pin to zero instead.
58+
__packed struct pin_config {
59+
u8_t pin;
60+
u8_t val;
61+
};
62+
63+
/* The following tables specify the configuration of each pin based on the
64+
* Kconfig options that drive it.
65+
* The switches have active-low logic, so when writing to the port we will
66+
* need to invert the value to match the IS_ENABLED() logic.
5967
*/
6068

61-
static const u8_t pins_on_p0[][2] = {
69+
static const struct pin_config pins_on_p0[] = {
6270
{ INTERFACE0_U5, IS_ENABLED(CONFIG_BOARD_PCA10090_INTERFACE0_ARDUINO) },
6371
{ INTERFACE1_U6, IS_ENABLED(CONFIG_BOARD_PCA10090_INTERFACE1_TRACE) },
6472
{ UART1_VCOM_U7, IS_ENABLED(CONFIG_BOARD_PCA10090_UART1_ARDUINO) },
@@ -67,7 +75,7 @@ static const u8_t pins_on_p0[][2] = {
6775
{ SWITCH2_U9, IS_ENABLED(CONFIG_BOARD_PCA10090_SWITCH1_PHY) },
6876
};
6977

70-
static const u8_t pins_on_p1[][2] = {
78+
static const struct pin_config pins_on_p1[] = {
7179
{ INTERFACE2_U21, IS_ENABLED(CONFIG_BOARD_PCA10090_INTERFACE2_COEX) },
7280
{ UART0_VCOM_U14, IS_ENABLED(CONFIG_BOARD_PCA10090_UART0_VCOM) },
7381
{ UART1_VCOM_U7, IS_ENABLED(CONFIG_BOARD_PCA10090_UART1_ARDUINO) },
@@ -163,40 +171,171 @@ static void config_print(void)
163171
IS_ENABLED(CONFIG_BOARD_PCA10090_SWITCH1_ARDUINO));
164172
}
165173

166-
static void configure_pins(struct device *port, const u8_t pins[][2],
167-
size_t size)
174+
static int pins_configure(struct device *port, const struct pin_config cfg[],
175+
size_t pins)
168176
{
169177
int err;
170178

171-
for (size_t i = 0; i < size; i++) {
172-
err = gpio_pin_configure(port, pins[i][0], GPIO_DIR_OUT);
173-
__ASSERT(err == 0, "Unable to configure pin %u", pins[i][0]);
174-
175-
/* The pin tables contain the default values for each pin.
176-
* Thus, if there is a one in the table, pull the pin to zero.
179+
/* Write to the pins before configuring them as output,
180+
* to make sure we are driving them to the correct level
181+
* right after they are configured.
182+
*/
183+
for (size_t i = 0; i < pins; i++) {
184+
/* The swiches on the board are active low, so we need
185+
* to negate the IS_ENABLED() value from the tables.
177186
*/
178-
err = gpio_pin_write(port, pins[i][0], !pins[i][1]);
179-
__ASSERT(err == 0, "Unable to set pin %u to %u", pins[i][0],
180-
!pins[i][1]);
187+
err = gpio_pin_write(port, cfg[i].pin, !cfg[i].val);
188+
if (err) {
189+
return cfg[i].pin;
190+
}
191+
192+
err = gpio_pin_configure(port, cfg[i].pin, GPIO_DIR_OUT);
193+
if (err) {
194+
return cfg[i].pin;
195+
}
196+
197+
LOG_DBG("port %p, pin %u -> %u",
198+
port, cfg[i].pin, !cfg[i].val);
199+
}
200+
201+
return 0;
202+
}
203+
204+
static void chip_reset(struct device *gpio,
205+
struct gpio_callback *cb, u32_t pins)
206+
{
207+
const u32_t stamp = k_cycle_get_32();
208+
209+
printk("GPIO reset line asserted, device reset.\n");
210+
printk("Bye @ cycle32 %u\n", stamp);
211+
212+
NVIC_SystemReset();
213+
}
214+
215+
static void reset_pin_wait_low(struct device *port, u32_t pin)
216+
{
217+
int err;
218+
u32_t val;
219+
220+
/* Wait until the pin is pulled low */
221+
do {
222+
err = gpio_pin_read(port, pin, &val);
223+
} while (err == 0 && val != 0);
224+
}
225+
226+
static int reset_pin_configure(struct device *p0, struct device *p1)
227+
{
228+
int err;
229+
u32_t pin;
230+
struct device *port = NULL;
231+
232+
static struct gpio_callback gpio_ctx;
233+
234+
/* MCU interface pins 0-2 */
235+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_17)) {
236+
port = p0;
237+
pin = 17;
181238
}
239+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_20)) {
240+
port = p0;
241+
pin = 20;
242+
}
243+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_15)) {
244+
port = p0;
245+
pin = 15;
246+
}
247+
/* MCU interface pins 3-6 */
248+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_22)) {
249+
port = p0;
250+
pin = 22;
251+
}
252+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P1_04)) {
253+
port = p1;
254+
pin = 4;
255+
}
256+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P1_02)) {
257+
port = p1;
258+
pin = 2;
259+
}
260+
261+
if (port == NULL) {
262+
return -EINVAL;
263+
}
264+
265+
err = gpio_pin_configure(port, pin,
266+
GPIO_DIR_IN | GPIO_INT | GPIO_PUD_PULL_DOWN |
267+
GPIO_INT_ACTIVE_HIGH | GPIO_INT_EDGE);
268+
if (err) {
269+
return err;
270+
}
271+
272+
gpio_init_callback(&gpio_ctx, chip_reset, BIT(pin));
273+
274+
err = gpio_add_callback(port, &gpio_ctx);
275+
if (err) {
276+
return err;
277+
}
278+
279+
err = gpio_pin_enable_callback(port, pin);
280+
if (err) {
281+
return err;
282+
}
283+
284+
/* Wait until the pin is pulled low before continuing.
285+
* This lets the other side ensure that they are ready.
286+
*/
287+
LOG_INF("GPIO reset line enabled on pin %s.%02u, holding..",
288+
port == p0 ? "P0" : "P1", pin);
289+
290+
reset_pin_wait_low(port, pin);
291+
292+
return 0;
182293
}
183294

184295
static int init(struct device *dev)
185296
{
297+
int rc;
186298
struct device *p0;
187299
struct device *p1;
188300

189301
p0 = device_get_binding(DT_GPIO_P0_DEV_NAME);
190-
__ASSERT(p0, "Unable to find GPIO %s", DT_GPIO_P0_DEV_NAME);
302+
if (!p0) {
303+
LOG_ERR("GPIO device " DT_GPIO_P0_DEV_NAME "not found!");
304+
return -EIO;
305+
}
191306

192307
p1 = device_get_binding(DT_GPIO_P1_DEV_NAME);
193-
__ASSERT(p1, "Unable to find GPIO %s", DT_GPIO_P1_DEV_NAME);
308+
if (!p1) {
309+
LOG_ERR("GPIO device " DT_GPIO_P1_DEV_NAME " not found!");
310+
return -EIO;
311+
}
194312

195-
configure_pins(p0, pins_on_p0, ARRAY_SIZE(pins_on_p0));
196-
configure_pins(p1, pins_on_p1, ARRAY_SIZE(pins_on_p1));
313+
/* Configure pins on each port */
314+
rc = pins_configure(p0, pins_on_p0, ARRAY_SIZE(pins_on_p0));
315+
if (rc) {
316+
LOG_ERR("Error while configuring pin P0.%02d", rc);
317+
return -EIO;
318+
}
319+
rc = pins_configure(p1, pins_on_p1, ARRAY_SIZE(pins_on_p1));
320+
if (rc) {
321+
LOG_ERR("Error while configuring pin P1.%02d", rc);
322+
return -EIO;
323+
}
197324

198325
config_print();
199326

327+
/* Make sure to configure the switches before initializing
328+
* the GPIO reset pin, so that we are connected to
329+
* the nRF9160 before enabling our interrupt.
330+
*/
331+
if (IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET)) {
332+
rc = reset_pin_configure(p0, p1);
333+
if (rc) {
334+
LOG_ERR("Unable to configure reset pin, err %d", rc);
335+
return -EIO;
336+
}
337+
}
338+
200339
LOG_INF("Board configured.");
201340

202341
return 0;

boards/arm/nrf52840_pca10090/integrity.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,12 @@ BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_BOARD_PCA10090_SWITCH0_PHY) ||
4949
BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_BOARD_PCA10090_SWITCH1_PHY) ||
5050
IS_ENABLED(CONFIG_BOARD_PCA10090_SWITCH1_ARDUINO),
5151
"Invalid switch 2 routing");
52+
53+
BUILD_ASSERT_MSG(!IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET) ||
54+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_17) ||
55+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_20) ||
56+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_15) ||
57+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P0_22) ||
58+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P1_04) ||
59+
IS_ENABLED(CONFIG_BOARD_PCA10090_NRF52840_RESET_P1_02),
60+
"No reset line selected, please check Kconfig macros");

0 commit comments

Comments
 (0)