You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ut...@apache.org on 2018/02/26 10:22:57 UTC
[mynewt-core] 12/17: Added support for gpio_irq_...
This is an automated email from the ASF dual-hosted git repository.
utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 65781b1d2f8ac68d96f922868238a717c209286a
Author: Markus Lampert <ma...@bibi.ca>
AuthorDate: Fri Jan 19 20:32:49 2018 -0800
Added support for gpio_irq_...
---
hw/mcu/stm/stm32f3xx/src/hal_gpio.c | 313 ++++++++++++++++++++++++++++++++----
1 file changed, 285 insertions(+), 28 deletions(-)
diff --git a/hw/mcu/stm/stm32f3xx/src/hal_gpio.c b/hw/mcu/stm/stm32f3xx/src/hal_gpio.c
index c34337e..020e769 100644
--- a/hw/mcu/stm/stm32f3xx/src/hal_gpio.c
+++ b/hw/mcu/stm/stm32f3xx/src/hal_gpio.c
@@ -27,11 +27,33 @@
#include "hal/hal_gpio.h"
#include "bsp/cmsis_nvic.h"
#include "stm32f3xx.h"
+#include "stm32f3xx_hal_cortex.h"
#include "stm32f3xx_hal_gpio.h"
#include "stm32f3xx_hal_rcc.h"
#include "mcu/stm32f3xx_mynewt_hal.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
+ * 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.
+ * "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
*
@@ -59,6 +81,90 @@ static GPIO_TypeDef * const portmap[HAL_GPIO_PORT_COUNT] =
HAL_GPIO_PORT_LIST
};
+/* Storage for GPIO ISRS. */
+struct hal_gpio_irq_isr_t
+{
+ hal_gpio_irq_handler_t isr;
+ void *arg;
+ volatile uint32_t invoked;
+ volatile uint32_t dropped;
+};
+struct hal_gpio_irq_isr_t hal_gpio_irq[16];
+
+void hal_gpio_ext_irq_handler(uint16_t index)
+{
+ uint32_t mask;
+
+ mask = HAL_GPIO_PIN(index);
+ if (__HAL_GPIO_EXTI_GET_IT(mask) != RESET) {
+ __HAL_GPIO_EXTI_CLEAR_IT(mask);
+ if (hal_gpio_irq[index].isr) {
+ ++hal_gpio_irq[index].invoked;
+ hal_gpio_irq[index].isr(hal_gpio_irq[index].arg);
+ } else {
+ ++hal_gpio_irq[index].dropped;
+ }
+ }
+}
+
+
+/* External interrupt 0 */
+static void
+hal_gpio_ext_irq0(void)
+{
+ hal_gpio_ext_irq_handler(0);
+}
+
+/* External interrupt 1 */
+static void
+hal_gpio_ext_irq1(void)
+{
+ hal_gpio_ext_irq_handler(1);
+}
+
+/* External interrupt 2 */
+static void
+hal_gpio_ext_irq2(void)
+{
+ hal_gpio_ext_irq_handler(2);
+}
+
+/* External interrupt 3 */
+static void
+hal_gpio_ext_irq3(void)
+{
+ hal_gpio_ext_irq_handler(3);
+}
+
+/* External interrupt 4 */
+static void
+hal_gpio_ext_irq4(void)
+{
+ hal_gpio_ext_irq_handler(4);
+}
+
+/* External interrupt 9 through 5 */
+static void
+hal_gpio_ext_irq9_5(void)
+{
+ int index;
+
+ for (index = 5; index <= 9; ++index) {
+ hal_gpio_ext_irq_handler(index);
+ }
+}
+
+/* External interrupt 15 through 10 */
+static void
+hal_gpio_ext_irq15_10(void)
+{
+ int index;
+
+ for (index = 10; index <= 15; ++index) {
+ hal_gpio_ext_irq_handler(index);
+ }
+}
+
/**
* hal gpio clk enable
*
@@ -151,19 +257,76 @@ hal_gpio_clk_enable(uint32_t port_idx)
}
}
-
/**
- * hal gpio init
+ * hal gpio pin to irq
*
- * Called to initialize a gpio.
+ * Converts the logical pin number to the IRQ number associated with the
+ * external interrupt for that particular GPIO.
*
* @param pin
- * @param cfg
*
- * @return int
+ * @return IRQn_Type
*/
-int
-hal_gpio_init_stm(int pin, GPIO_InitTypeDef *cfg)
+static IRQn_Type
+hal_gpio_pin_to_irq(int pin)
+{
+ int index;
+ IRQn_Type irqn;
+
+ index = HAL_GPIO_PIN_NUM(pin);
+ if (index <= 4) {
+ irqn = EXTI0_IRQn + index;
+ } else if (index <= 9) {
+ irqn = EXTI9_5_IRQn;
+ } else {
+ irqn = EXTI15_10_IRQn;
+ }
+
+ return irqn;
+}
+
+static void
+hal_gpio_set_nvic(IRQn_Type irqn)
+{
+ void (*isr)(void);
+
+ switch (irqn) {
+ case EXTI0_IRQn:
+ isr = hal_gpio_ext_irq0;
+ break;
+ case EXTI1_IRQn:
+ isr = hal_gpio_ext_irq1;
+ break;
+ case EXTI2_TSC_IRQn:
+ isr = hal_gpio_ext_irq2;
+ break;
+ case EXTI3_IRQn:
+ isr = hal_gpio_ext_irq3;
+ break;
+ case EXTI4_IRQn:
+ isr = hal_gpio_ext_irq4;
+ break;
+ case EXTI9_5_IRQn:
+ isr = hal_gpio_ext_irq9_5;
+ break;
+ case EXTI15_10_IRQn:
+ isr = hal_gpio_ext_irq15_10;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* Set isr in vector table if not yet set */
+ if (NVIC_GetVector(irqn) != (uint32_t)isr) {
+ NVIC_SetVector(irqn, (uint32_t)isr);
+ NVIC_EnableIRQ(irqn);
+ }
+}
+
+
+static int
+hal_gpio_init_stm32_int(int pin, GPIO_InitTypeDef *cfg, GPIO_PinState *state)
{
int port;
uint32_t mcu_gpio_pin;
@@ -180,13 +343,33 @@ hal_gpio_init_stm(int pin, GPIO_InitTypeDef *cfg)
/* Enable the GPIO clock */
hal_gpio_clk_enable(port);
- /* Initialize pin as an input, setting proper mode */
+ /* Write initial state if required */
+ if (NULL != state) {
+ HAL_GPIO_WritePin(portmap[port], mcu_gpio_pin, *state);
+ }
+
+ /* Initialize pin setting proper mode */
HAL_GPIO_Init(portmap[port], cfg);
return 0;
}
/**
+ * hal gpio init
+ *
+ * Called to initialize a gpio.
+ *
+ * @param pin
+ * @param cfg
+ *
+ * @return int
+ */
+int
+hal_gpio_init_stm(int pin, GPIO_InitTypeDef *cfg)
+{
+ return hal_gpio_init_stm32_int(pin, cfg, NULL);
+}
+/**
* hal gpio deinit
*
* Called to deinitialize a gpio.
@@ -253,19 +436,16 @@ hal_gpio_init_in(int pin, hal_gpio_pull_t pull)
*/
int hal_gpio_init_out(int pin, int val)
{
- int rc;
GPIO_InitTypeDef cfg;
+ GPIO_PinState state;
cfg.Mode = GPIO_MODE_OUTPUT_PP;
cfg.Pull = GPIO_NOPULL;
cfg.Speed = GPIO_SPEED_FREQ_HIGH;
- rc = hal_gpio_init_stm(pin, &cfg);
- if (HAL_OK == rc) {
- hal_gpio_write(pin, val);
- }
+ state = val ? GPIO_PIN_SET : GPIO_PIN_RESET;
- return rc;
+ return hal_gpio_init_stm32_int(pin, &cfg, &state);
}
/**
@@ -368,8 +548,6 @@ int hal_gpio_toggle(int pin)
*
* Initialize an external interrupt on a gpio pin
*
- * irq support not implemented yet.
- *
* @param pin Pin number to enable gpio.
* @param handler Interrupt handler
* @param arg Argument to pass to interrupt handler
@@ -382,50 +560,129 @@ int
hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg,
hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull)
{
- (void)pin;
- (void)handler;
- (void)arg;
- (void)trig;
- (void)pull;
+ int rc;
+ int irqn;
+ int index;
+ uint32_t pin_mask;
+ uint32_t mode;
+ GPIO_InitTypeDef cfg;
+
+ /* Configure the gpio for an external interrupt */
+ rc = 0;
+ switch (trig) {
+ case HAL_GPIO_TRIG_NONE:
+ rc = -1;
+ break;
+ case HAL_GPIO_TRIG_RISING:
+ mode = GPIO_MODE_IT_RISING;
+ break;
+ case HAL_GPIO_TRIG_FALLING:
+ mode = GPIO_MODE_IT_FALLING;
+ break;
+ case HAL_GPIO_TRIG_BOTH:
+ mode = GPIO_MODE_IT_RISING_FALLING;
+ break;
+ case HAL_GPIO_TRIG_LOW:
+ rc = -1;
+ break;
+ case HAL_GPIO_TRIG_HIGH:
+ rc = -1;
+ break;
+ default:
+ rc = -1;
+ break;
+ }
- return -1;
+ /* Check to make sure no error has occurred */
+ if (!rc) {
+ /* Disable interrupt and clear any pending */
+ hal_gpio_irq_disable(pin);
+ pin_mask = HAL_GPIO_PIN(pin);
+ __HAL_GPIO_EXTI_CLEAR_FLAG(pin_mask);
+
+ /* Set the gpio irq handler */
+ index = HAL_GPIO_PIN_NUM(pin);
+ hal_gpio_irq[index].isr = handler;
+ hal_gpio_irq[index].arg = arg;
+ hal_gpio_irq[index].invoked = 0;
+
+ /* Configure the GPIO */
+ cfg.Mode = mode;
+ cfg.Pull = pull;
+ rc = hal_gpio_init_stm(pin, &cfg);
+ if (!rc) {
+ /* Enable interrupt vector in NVIC */
+ irqn = hal_gpio_pin_to_irq(pin);
+ hal_gpio_set_nvic(irqn);
+ }
+ }
+
+ return rc;
}
/**
* gpio irq release
*
- * irq support not implemented yet.
+ * 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.
*
* @param pin
*/
void
hal_gpio_irq_release(int pin)
{
- (void)pin;
+ int index;
+ uint32_t pin_mask;
+
+ /* Disable the interrupt */
+ hal_gpio_irq_disable(pin);
+
+ /* Clear any pending interrupts */
+ pin_mask = HAL_GPIO_PIN(pin);
+ __HAL_GPIO_EXTI_CLEAR_FLAG(pin_mask);
+
+ /* Clear out the irq handler */
+ index = HAL_GPIO_PIN_NUM(pin);
+ hal_gpio_irq[index].arg = NULL;
+ hal_gpio_irq[index].isr = NULL;
}
/**
* gpio irq enable
*
- * irq support not implemented yet.
+ * Enable the irq on the specified pin
*
* @param pin
*/
void
hal_gpio_irq_enable(int pin)
{
- (void)pin;
+ uint32_t ctx;
+ uint32_t mask;
+
+ mask = HAL_GPIO_PIN(pin);
+
+ __HAL_DISABLE_INTERRUPTS(ctx);
+ EXTI->IMR |= mask;
+ __HAL_ENABLE_INTERRUPTS(ctx);
}
/**
* gpio irq disable
*
- * irq support not implemented yet.
*
* @param pin
*/
void
hal_gpio_irq_disable(int pin)
{
- (void)pin;
+ uint32_t ctx;
+ uint32_t mask;
+
+ mask = HAL_GPIO_PIN(pin);
+ __HAL_DISABLE_INTERRUPTS(ctx);
+ EXTI->IMR &= ~mask;
+ __HAL_ENABLE_INTERRUPTS(ctx);
}
--
To stop receiving notification emails like this one, please contact
utzig@apache.org.