summaryrefslogtreecommitdiff
path: root/hw/mcu/nordic/nrf52xxx
diff options
context:
space:
mode:
authorChristopher Collins <ccollins@apache.org>2016-08-23 17:35:28 -0700
committerChristopher Collins <ccollins@apache.org>2016-08-23 17:35:28 -0700
commit70987f7d2e3c791132509f08566fe77de34142ac (patch)
tree269ca9b857f65c22b8f2b93560466984f96091e5 /hw/mcu/nordic/nrf52xxx
parent0d9c8f30efbe2dba00b21d9185e9db8e36cd579e (diff)
parent665e22f5722d6348c1b260192e27f69d855b58fd (diff)
Merge branch 'develop' - in preparation for
backwards-compatibility-breaking changes to develop. * develop: (290 commits) sim compiler - replace objsize with size Fix warnings reported by clang. MYNEWT-329 MYNEWT-354 STM32f407 discovery board BSP mbedtls; use smaller version of SHA256. boot; boot loader does not need to call os_init() anymore, as bsp_init() has been exported. boot; app does not need the dependency to mbedtls slinky; time-based waits must use OS_TICKS_PER_SEC. bootutil; adjust unit tests to work with status upkeep outside sys/config. bootutil; was returning wrong image header in response when swithing images. Add boot_set_req() routine for unit test use. boot/bootutil; remove debug console use from bootloader. bootutil/imgmgr; output of boot now shows the fallback image. imgmgr; automatically confirm image as good for now. bootutil; add 'confirm' step, telling that image was confirmed as good. Otherwise next restart we'll go back to old image. bootutil; make status element size depend on flash alignment restrictions. boot, imgmgr; return the slot number for test image. bootutil; move routines reading boot-copy-status from loader.c to bootutil_misc.c. boot; return full flash location of status bytes, instead of just offset. boot; don't use NFFS or FCB for keeping status. Interim commit. ...
Diffstat (limited to 'hw/mcu/nordic/nrf52xxx')
-rw-r--r--hw/mcu/nordic/nrf52xxx/src/hal_gpio.c503
-rw-r--r--hw/mcu/nordic/nrf52xxx/src/hal_uart.c33
2 files changed, 171 insertions, 365 deletions
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c b/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
index d803ec0b..490b8a3f 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
@@ -21,289 +21,35 @@
#include "bsp/cmsis_nvic.h"
#include "mcu/nrf52.h"
#include "mcu/nrf52_bitfields.h"
+#include <stdlib.h>
#include <assert.h>
- /* XXX: Notes
- * 1) Right now, we are not disabling the NVIC interrupt source; we only
- * disable the external interrupt from occurring. Dont think either way
- * to do it is an issue... when we release we may want to disable the NVIC
- *
- * 2) investigate how thread safe these routines are. HAL_GPIO_Init, for
- * example. Looks like if it gets interrupted while doing config an error
- * may occur. Read/modify write could cause screw-ups.
- *
- * 3) Currently, this code does not change the interrupt priority of the
+/*
+ * 1) Currently, this code does not change the interrupt priority of the
* external interrupt vectors in the NVIC. The application developer must
* decide on the priority level for each external interrupt and program that
* by using the CMSIS NVIC API (NVIC_SetPriority and NVIC_SetPriorityGrouping)
*
- * 4) The code probably does not handle "re-purposing" gpio very well.
+ * 2) The code probably does not handle "re-purposing" gpio very well.
* "Re-purposing" means changing a gpio from input to output, or calling
* gpio_init_in and expecting previously enabled interrupts to be stopped.
*
- * 5) Possbily add access to HAL_GPIO_DeInit.
*/
/*
* GPIO pin mapping
*
*/
-#define GPIO_INDEX(pin) (pin)
-#define GPIO_MASK(pin) (1 << GPIO_INDEX(pin))
+#define HAL_GPIO_MAX_IRQ 8
+#define HAL_GPIO_MASK(pin) (1 << pin)
/* Storage for GPIO callbacks. */
-struct gpio_irq_obj
-{
+struct hal_gpio_irq {
+ gpio_irq_handler_t func;
void *arg;
- gpio_irq_handler_t isr;
-};
-
-#if 0
-static struct gpio_irq_obj gpio_irq_handlers[16];
-#endif
-
-struct ext_irqs
-{
- volatile uint32_t irq0;
- volatile uint32_t irq1;
- volatile uint32_t irq2;
- volatile uint32_t irq3;
- volatile uint32_t irq4;
- volatile uint32_t irq9_5;
- volatile uint32_t irq15_10;
};
-struct ext_irqs ext_irq_counts;
-
-#if 0
-/**
- * ext irq handler
- *
- * Handles the gpio interrupt attached to a gpio pin.
- *
- * @param index
- */
-static void
-ext_irq_handler(int index)
-{
- uint32_t mask;
-
- mask = 1 << index;
- if (__HAL_GPIO_EXTI_GET_IT(mask) != RESET) {
- __HAL_GPIO_EXTI_CLEAR_IT(mask);
- gpio_irq_handlers[index].isr(gpio_irq_handlers[index].arg);
- }
-}
-/* External interrupt 0 */
-static void
-ext_irq0(void)
-{
- ++ext_irq_counts.irq0;
- ext_irq_handler(0);
-}
-
-/* External interrupt 1 */
-static void
-ext_irq1(void)
-{
- ++ext_irq_counts.irq1;
- ext_irq_handler(1);
-}
-
-/* External interrupt 2 */
-static void
-ext_irq2(void)
-{
- ++ext_irq_counts.irq2;
- ext_irq_handler(2);
-}
-
-/* External interrupt 3 */
-static void
-ext_irq3(void)
-{
- ++ext_irq_counts.irq3;
- ext_irq_handler(3);
-}
-
-/**
- * ext irq4
- *
- * External interrupt handler for external interrupt 4.
- *
- */
-static void
-ext_irq4(void)
-{
- ++ext_irq_counts.irq4;
- ext_irq_handler(4);
-}
-
-/**
- * ext irq9_5
- *
- * External interrupt handler for irqs 9 through 5.
- *
- */
-static void
-ext_irq9_5(void)
-{
- int index;
-
- ++ext_irq_counts.irq9_5;
- for (index = 5; index <= 9; ++index) {
- ext_irq_handler(index);
- }
-}
-
-/**
- * ext irq15_10
- *
- * External interrupt handler for irqs 15 through 10.
- *
- */
-static void
-ext_irq15_10(void)
-{
- int index;
-
- ++ext_irq_counts.irq15_10;
- for (index = 10; index <= 15; ++index) {
- ext_irq_handler(index);
- }
-}
-
-/**
- * hal gpio clk enable
- *
- * Enable the port peripheral clock
- *
- * @param port_idx
- */
-static void
-hal_gpio_clk_enable(uint32_t port_idx)
-{
- switch (port_idx) {
- case 0:
- __HAL_RCC_GPIOA_CLK_ENABLE();
- break;
- case 1:
- __HAL_RCC_GPIOB_CLK_ENABLE();
- break;
- case 2:
- __HAL_RCC_GPIOC_CLK_ENABLE();
- break;
- case 3:
- __HAL_RCC_GPIOD_CLK_ENABLE();
- break;
- case 4:
- __HAL_RCC_GPIOE_CLK_ENABLE();
- break;
-#if defined GPIOF_BASE
- case 5:
- __HAL_RCC_GPIOF_CLK_ENABLE();
- break;
-#endif
-#if defined GPIOG_BASE
- case 6:
- __HAL_RCC_GPIOG_CLK_ENABLE();
- break;
-#endif
-#if defined GPIOH_BASE
- case 7:
- __HAL_RCC_GPIOH_CLK_ENABLE();
- break;
-#endif
-#if defined GPIOI_BASE
- case 8:
- __HAL_RCC_GPIOI_CLK_ENABLE();
- break;
-#endif
-#if defined GPIOJ_BASE
- case 9:
- __HAL_RCC_GPIOJ_CLK_ENABLE();
- break;
-#endif
-#if defined GPIOK_BASE
- case 10:
- __HAL_RCC_GPIOK_CLK_ENABLE();
- break;
-#endif
- default:
- assert(0);
- break;
- }
-}
-
-/**
- * hal gpio pin to irq
- *
- * Converts the logical pin number to the IRQ number associated with the
- * external interrupt for that particular GPIO.
- *
- * @param pin
- *
- * @return IRQn_Type
- */
-static IRQn_Type
-hal_gpio_pin_to_irq(int pin)
-{
- int index;
- IRQn_Type irqn;
-
- index = GPIO_INDEX(pin);
- if (index <= 4) {
- irqn = GPIOTE_IRQn + index;
- } else if (index <= 9) {
- irqn = EXTI9_5_IRQn;
- } else {
- irqn = EXTI15_10_IRQn;
- }
-
- return irqn;
-}
-#endif
-
-static void
-hal_gpio_set_nvic(IRQn_Type irqn)
-{
-#if 0
- uint32_t isr;
-
- switch (irqn) {
- case EXTI0_IRQn:
- isr = (uint32_t)&ext_irq0;
- break;
- case EXTI1_IRQn:
- isr = (uint32_t)&ext_irq1;
- break;
- case EXTI2_IRQn:
- isr = (uint32_t)&ext_irq2;
- break;
- case EXTI3_IRQn:
- isr = (uint32_t)&ext_irq3;
- break;
- case EXTI4_IRQn:
- isr = (uint32_t)&ext_irq4;
- break;
- case EXTI9_5_IRQn:
- isr = (uint32_t)&ext_irq9_5;
- break;
- case EXTI15_10_IRQn:
- isr = (uint32_t)&ext_irq15_10;
- break;
- default:
- assert(0);
- break;
- }
-
- /* Set isr in vector table if not yet set */
- if (NVIC_GetVector(irqn) != isr) {
- NVIC_SetVector(irqn, isr);
- NVIC_EnableIRQ(irqn);
- }
-#endif
-}
+static struct hal_gpio_irq hal_gpio_irqs[HAL_GPIO_MAX_IRQ];
/**
* gpio init in
@@ -334,7 +80,7 @@ hal_gpio_init_in(int pin, gpio_pull_t pull)
}
NRF_P0->PIN_CNF[pin] = conf;
- NRF_P0->DIRCLR = GPIO_MASK(pin);
+ NRF_P0->DIRCLR = HAL_GPIO_MASK(pin);
return 0;
}
@@ -353,12 +99,12 @@ hal_gpio_init_in(int pin, gpio_pull_t pull)
int hal_gpio_init_out(int pin, int val)
{
if (val) {
- NRF_P0->OUTSET = GPIO_MASK(pin);
+ NRF_P0->OUTSET = HAL_GPIO_MASK(pin);
} else {
- NRF_P0->OUTCLR = GPIO_MASK(pin);
+ NRF_P0->OUTCLR = HAL_GPIO_MASK(pin);
}
NRF_P0->PIN_CNF[pin] = GPIO_PIN_CNF_DIR_Output;
- NRF_P0->DIRSET = GPIO_MASK(pin);
+ NRF_P0->DIRSET = HAL_GPIO_MASK(pin);
return 0;
}
@@ -371,7 +117,7 @@ int hal_gpio_init_out(int pin, int val)
*/
void hal_gpio_set(int pin)
{
- NRF_P0->OUTSET = GPIO_MASK(pin);
+ NRF_P0->OUTSET = HAL_GPIO_MASK(pin);
}
/**
@@ -383,7 +129,7 @@ void hal_gpio_set(int pin)
*/
void hal_gpio_clear(int pin)
{
- NRF_P0->OUTCLR = GPIO_MASK(pin);
+ NRF_P0->OUTCLR = HAL_GPIO_MASK(pin);
}
/**
@@ -414,7 +160,7 @@ void hal_gpio_write(int pin, int val)
*/
int hal_gpio_read(int pin)
{
- return (NRF_P0->IN & GPIO_MASK(pin));
+ return (NRF_P0->IN & HAL_GPIO_MASK(pin));
}
/**
@@ -433,6 +179,79 @@ int hal_gpio_toggle(int pin)
return pin_state;
}
+/*
+ * GPIO irq handler
+ *
+ * Handles the gpio interrupt attached to a gpio pin.
+ *
+ * @param index
+ */
+static void
+hal_gpio_irq_handler(void)
+{
+ int i;
+
+ for (i = 0; i < HAL_GPIO_MAX_IRQ; i++) {
+ if (NRF_GPIOTE->EVENTS_IN[i]) {
+ NRF_GPIOTE->EVENTS_IN[i] = 0;
+ if (hal_gpio_irqs[i].func) {
+ hal_gpio_irqs[i].func(hal_gpio_irqs[i].arg);
+ }
+ }
+ }
+}
+
+/*
+ * Register IRQ handler for GPIOTE, and enable it.
+ * Only executed once, during first registration.
+ */
+static void
+hal_gpio_irq_setup(void)
+{
+ static uint8_t irq_setup = 0;
+
+ if (!irq_setup) {
+ NVIC_SetVector(GPIOTE_IRQn, (uint32_t)hal_gpio_irq_handler);
+ NVIC_EnableIRQ(GPIOTE_IRQn);
+ irq_setup = 1;
+ }
+}
+
+/*
+ * Find out whether we have an GPIOTE pin event to use.
+ */
+static int
+hal_gpio_find_empty_slot(void)
+{
+ int i;
+
+ for (i = 0; i < HAL_GPIO_MAX_IRQ; i++) {
+ if (hal_gpio_irqs[i].func == NULL) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Find the GPIOTE event which handles this pin.
+ */
+static int
+hal_gpio_find_pin(int pin)
+{
+ int i;
+
+ pin = pin << GPIOTE_CONFIG_PSEL_Pos;
+
+ for (i = 0; i < HAL_GPIO_MAX_IRQ; i++) {
+ if (hal_gpio_irqs[i].func &&
+ (NRF_GPIOTE->CONFIG[i] & GPIOTE_CONFIG_PSEL_Msk) == pin) {
+ return i;
+ }
+ }
+ return -1;
+}
+
/**
* gpio irq init
*
@@ -450,101 +269,65 @@ int
hal_gpio_irq_init(int pin, gpio_irq_handler_t handler, void *arg,
gpio_irq_trig_t trig, gpio_pull_t pull)
{
-#if 0
- int rc;
- int irqn;
- int index;
- uint32_t pin_mask;
- uint32_t mode;
- GPIO_InitTypeDef init_cfg;
-
- /* Configure the gpio for an external interrupt */
- rc = 0;
+ uint32_t conf;
+ int i;
+
+ hal_gpio_irq_setup();
+ i = hal_gpio_find_empty_slot();
+ if (i < 0) {
+ return -1;
+ }
+ hal_gpio_init_in(pin, pull);
+
switch (trig) {
- case GPIO_TRIG_NONE:
- rc = -1;
- break;
case GPIO_TRIG_RISING:
- mode = GPIO_MODE_IT_RISING;
+ conf = GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos;
break;
case GPIO_TRIG_FALLING:
- mode = GPIO_MODE_IT_FALLING;
+ conf = GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos;
break;
case GPIO_TRIG_BOTH:
- mode = GPIO_MODE_IT_RISING_FALLING;
- break;
- case GPIO_TRIG_LOW:
- rc = -1;
- break;
- case GPIO_TRIG_HIGH:
- rc = -1;
+ conf = GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos;
break;
default:
- rc = -1;
- break;
+ return -1;
}
+ conf |= pin << GPIOTE_CONFIG_PSEL_Pos;
+ conf |= GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos;
- /* Check to make sure no error has occurred */
- if (!rc) {
- /* Disable interrupt and clear any pending */
- gpio_irq_disable(pin);
- pin_mask = GPIO_MASK(pin);
- __HAL_GPIO_EXTI_CLEAR_FLAG(pin_mask);
-
- /* Set the gpio irq handler */
- index = GPIO_INDEX(pin);
- gpio_irq_handlers[index].isr = handler;
- gpio_irq_handlers[index].arg = arg;
-
- /* Configure the GPIO */
- init_cfg.Mode = mode;
- init_cfg.Pull = pull;
- rc = hal_gpio_init(pin, &init_cfg);
- if (!rc) {
- /* Enable interrupt vector in NVIC */
- irqn = hal_gpio_pin_to_irq(pin);
- hal_gpio_set_nvic(irqn);
- }
- }
+ NRF_GPIOTE->CONFIG[i] = conf;
+
+ hal_gpio_irqs[i].func = handler;
+ hal_gpio_irqs[i].arg = arg;
- return rc;
-#else
- hal_gpio_set_nvic(0);
return 0;
-#endif
}
/**
* gpio irq release
*
* No longer interrupt when something occurs on the pin. NOTE: this function
- * does not change the GPIO push/pull setting nor does it change the
- * SYSCFG EXTICR registers. It also does not disable the NVIC interrupt enable
- * setting for the irq.
+ * does not change the GPIO push/pull setting.
+ * It also does not disable the NVIC interrupt enable setting for the irq.
*
* @param pin
*/
void
hal_gpio_irq_release(int pin)
{
-#if 0
- int index;
- uint32_t pin_mask;
-
- /* Disable the interrupt */
- gpio_irq_disable(pin);
-
- /* Clear any pending interrupts */
- pin_mask = GPIO_MASK(pin);
- __HAL_GPIO_EXTI_CLEAR_FLAG(pin_mask);
-
- /* Clear out the irq handler */
- index = GPIO_INDEX(pin);
- gpio_irq_handlers[index].arg = NULL;
- gpio_irq_handlers[index].isr = NULL;
-#else
- return;
-#endif
+ int i;
+
+ i = hal_gpio_find_pin(pin);
+ if (i < 0) {
+ return;
+ }
+ hal_gpio_irq_disable(i);
+
+ NRF_GPIOTE->CONFIG[i] = 0;
+ NRF_GPIOTE->EVENTS_IN[i] = 0;
+
+ hal_gpio_irqs[i].arg = NULL;
+ hal_gpio_irqs[i].func = NULL;
}
/**
@@ -557,18 +340,14 @@ hal_gpio_irq_release(int pin)
void
hal_gpio_irq_enable(int pin)
{
-#if 0
- uint32_t ctx;
- uint32_t mask;
-
- mask = GPIO_MASK(pin);
-
- __HAL_DISABLE_INTERRUPTS(ctx);
- EXTI->IMR |= mask;
- __HAL_ENABLE_INTERRUPTS(ctx);
-#else
- return;
-#endif
+ int i;
+
+ i = hal_gpio_find_pin(pin);
+ if (i < 0) {
+ return;
+ }
+ NRF_GPIOTE->EVENTS_IN[i] = 0;
+ NRF_GPIOTE->INTENSET = 1 << i;
}
/**
@@ -580,15 +359,11 @@ hal_gpio_irq_enable(int pin)
void
hal_gpio_irq_disable(int pin)
{
-#if 0
- uint32_t ctx;
- uint32_t mask;
-
- mask = GPIO_MASK(pin);
- __HAL_DISABLE_INTERRUPTS(ctx);
- EXTI->IMR &= ~mask;
- __HAL_ENABLE_INTERRUPTS(ctx);
-#else
- return;
-#endif
+ int i;
+
+ i = hal_gpio_find_pin(pin);
+ if (i < 0) {
+ return;
+ }
+ NRF_GPIOTE->INTENCLR = 1 << i;
}
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_uart.c b/hw/mcu/nordic/nrf52xxx/src/hal_uart.c
index 49861003..eb9cc32b 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_uart.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_uart.c
@@ -6,7 +6,7 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
@@ -31,6 +31,7 @@
#define UARTE_CONFIG_PARITY UARTE_CONFIG_PARITY_Msk
#define UARTE_CONFIG_HWFC UARTE_CONFIG_HWFC_Msk
#define UARTE_ENABLE UARTE_ENABLE_ENABLE_Enabled
+#define UARTE_DISABLE UARTE_ENABLE_ENABLE_Disabled
/*
* Only one UART on NRF 52832.
@@ -91,6 +92,9 @@ hal_uart_start_tx(int port)
int sr;
int rc;
+ if (port != 0) {
+ return;
+ }
u = &uart;
__HAL_DISABLE_INTERRUPTS(sr);
if (u->u_tx_started == 0) {
@@ -113,6 +117,9 @@ hal_uart_start_rx(int port)
int sr;
int rc;
+ if (port != 0) {
+ return;
+ }
u = &uart;
if (u->u_rx_stall) {
__HAL_DISABLE_INTERRUPTS(sr);
@@ -131,6 +138,10 @@ hal_uart_blocking_tx(int port, uint8_t data)
{
struct hal_uart *u;
+ if (port != 0) {
+ return;
+ }
+
u = &uart;
if (!u->u_open) {
return;
@@ -202,6 +213,8 @@ hal_uart_baudrate(int baudrate)
return UARTE_BAUDRATE_BAUDRATE_Baud38400;
case 57600:
return UARTE_BAUDRATE_BAUDRATE_Baud57600;
+ case 76800:
+ return UARTE_BAUDRATE_BAUDRATE_Baud76800;
case 115200:
return UARTE_BAUDRATE_BAUDRATE_Baud115200;
case 230400:
@@ -303,7 +316,25 @@ hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits,
NRF_UARTE0->RXD.MAXCNT = sizeof(u->u_rx_buf);
NRF_UARTE0->TASKS_STARTRX = 1;
+ u->u_rx_stall = 0;
+ u->u_tx_started = 0;
u->u_open = 1;
return 0;
}
+
+int
+hal_uart_close(int port)
+{
+ struct hal_uart *u;
+
+ u = &uart;
+
+ if (port == 0) {
+ u->u_open = 0;
+ NRF_UARTE0->ENABLE = 0;
+ NRF_UARTE0->INTENCLR = 0xffffffff;
+ return 0;
+ }
+ return -1;
+}