mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 09:18:00 +08:00
arch/arm/src/max326xx/max32660: Add GPIO driver and GPIO interrupt support.
This commit is contained in:
@@ -104,7 +104,20 @@
|
||||
/* Number of external interrupts and total number of vectors */
|
||||
|
||||
#define MAX326_IRQ_NEXTINT 50
|
||||
#define NR_IRQS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
|
||||
|
||||
#define MAX326_IRQ_NVECTORS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
|
||||
|
||||
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
#warning Missing logic
|
||||
#else
|
||||
# define MAX326_IRQ_NPININT 0
|
||||
#endif
|
||||
|
||||
/* Total number of interrupts handled by the OS */
|
||||
|
||||
#define NR_IRQS (MAX326_IRQ_NVECTORS + MAX326_IRQ_NPININT)
|
||||
|
||||
/************************************************************************************************
|
||||
* Public Types
|
||||
|
||||
@@ -86,10 +86,41 @@
|
||||
/* 46-48 Reserved */
|
||||
#define MAX326_IRQ_SPIS (MAX326_IRQ_EXTINT + 49) /* 49 SPI Slave */
|
||||
|
||||
/* Number of external interrupts and total number of vectors */
|
||||
/* Number of external interrupts and number of true interrupt vectors */
|
||||
|
||||
#define MAX326_IRQ_NEXTINT 50
|
||||
#define NR_IRQS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
|
||||
#define MAX326_IRQ_NVECTORS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
|
||||
|
||||
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
/* Up to 14 pins are available as interrupt sources, depending on the MAX32660 package */
|
||||
|
||||
# define MAX326_IRQ_P0_0 (MAX326_IRQ_NEXTINT + 0)
|
||||
# define MAX326_IRQ_P0_1 (MAX326_IRQ_NEXTINT + 1)
|
||||
# define MAX326_IRQ_P0_2 (MAX326_IRQ_NEXTINT + 2)
|
||||
# define MAX326_IRQ_P0_3 (MAX326_IRQ_NEXTINT + 3)
|
||||
# define MAX326_IRQ_P0_4 (MAX326_IRQ_NEXTINT + 4)
|
||||
# define MAX326_IRQ_P0_5 (MAX326_IRQ_NEXTINT + 5)
|
||||
# define MAX326_IRQ_P0_6 (MAX326_IRQ_NEXTINT + 6)
|
||||
# define MAX326_IRQ_P0_7 (MAX326_IRQ_NEXTINT + 7)
|
||||
# define MAX326_IRQ_P0_8 (MAX326_IRQ_NEXTINT + 8)
|
||||
# define MAX326_IRQ_P0_9 (MAX326_IRQ_NEXTINT + 9)
|
||||
# define MAX326_IRQ_P0_10 (MAX326_IRQ_NEXTINT + 10)
|
||||
# define MAX326_IRQ_P0_11 (MAX326_IRQ_NEXTINT + 11)
|
||||
# define MAX326_IRQ_P0_12 (MAX326_IRQ_NEXTINT + 12)
|
||||
# define MAX326_IRQ_P0_13 (MAX326_IRQ_NEXTINT + 13)
|
||||
|
||||
# define MAX326_IRQ_GPIO1ST MAX326_IRQ_P0_0
|
||||
# define MAX326_IRQ_GPIOLAST MAX326_IRQ_P0_13
|
||||
# define MAX326_IRQ_NPININT 14
|
||||
#else
|
||||
# define MAX326_IRQ_NPININT 0
|
||||
#endif
|
||||
|
||||
/* Total number of interrupts handled by the OS */
|
||||
|
||||
#define NR_IRQS (MAX326_IRQ_NVECTORS + MAX326_IRQ_NPININT)
|
||||
|
||||
/************************************************************************************************
|
||||
* Public Types
|
||||
|
||||
@@ -439,6 +439,15 @@ void up_disable_irq(int irq)
|
||||
uint32_t regval;
|
||||
uint32_t bit;
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
/* Handle "fake" GPIO irq */
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
{
|
||||
max326_gpio_irqdisable(irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (max326_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0)
|
||||
{
|
||||
/* Modify the appropriate bit in the register to disable the interrupt.
|
||||
@@ -476,6 +485,15 @@ void up_enable_irq(int irq)
|
||||
uint32_t regval;
|
||||
uint32_t bit;
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
/* Handle "fake" GPIO irq */
|
||||
|
||||
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
|
||||
{
|
||||
max326_gpio_irqensable(irq);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (max326_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0)
|
||||
{
|
||||
/* Modify the appropriate bit in the register to enable the interrupt.
|
||||
@@ -542,13 +560,20 @@ int up_prioritize_irq(int irq, int priority)
|
||||
regaddr = NVIC_SYSH_PRIORITY(irq);
|
||||
irq -= 4;
|
||||
}
|
||||
else
|
||||
else if (irq < MAX326_IRQ_NVECTORS)
|
||||
{
|
||||
/* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */
|
||||
|
||||
irq -= MAX326_IRQ_EXTINT;
|
||||
regaddr = NVIC_IRQ_PRIORITY(irq);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef CONFIG_MAX326_GPIOIRQ
|
||||
DEBUGPANIC();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
regval = getreg32(regaddr);
|
||||
shift = ((irq & 3) << 3);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -69,10 +69,9 @@
|
||||
#define GPIO_FUNC_MASK (15 << GPIO_FUNC_SHIFT)
|
||||
# define GPIO_INPUT (0 << GPIO_FUNC_SHIFT) /* 0000 GPIO input pin */
|
||||
# define GPIO_OUTPUT (1 << GPIO_FUNC_SHIFT) /* 0001 GPIO output pin */
|
||||
# define GPIO_ALT0 (4 << GPIO_FUNC_SHIFT) /* 0100 GPIO Alternate function 0 */
|
||||
# define GPIO_ALT1 (5 << GPIO_FUNC_SHIFT) /* 0101 GPIO Alternate function 1 */
|
||||
# define GPIO_ALT2 (6 << GPIO_FUNC_SHIFT) /* 0110 GPIO Alternate function 2 */
|
||||
# define GPIO_ALT3 (7 << GPIO_FUNC_SHIFT) /* 0111 GPIO Alternate function 3 */
|
||||
# define GPIO_ALT1 (5 << GPIO_FUNC_SHIFT) /* 0100 GPIO Alternate function 1 */
|
||||
# define GPIO_ALT2 (6 << GPIO_FUNC_SHIFT) /* 0101 GPIO Alternate function 2 */
|
||||
# define GPIO_ALT3 (7 << GPIO_FUNC_SHIFT) /* 0110 GPIO Alternate function 3 */
|
||||
# define GPIO_INTFE (9 << GPIO_FUNC_SHIFT) /* 1001 GPIO interrupt falling edge */
|
||||
# define GPIO_INTRE (10 << GPIO_FUNC_SHIFT) /* 1010 GPIO interrupt rising edge */
|
||||
# define GPIO_INTBOTH (11 << GPIO_FUNC_SHIFT) /* 1011 GPIO interrupt both edges */
|
||||
@@ -94,7 +93,7 @@
|
||||
|
||||
#define GPIO_IS_GPIO(ps) (((uint16_t)(ps) & GPIO_GPIO_MASK) == GPIO_GPIO_CODE)
|
||||
#define GPIO_IS_ALT(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_ALT_CODE)
|
||||
#define GPIO_IS_INTR(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_ALT_CODE)
|
||||
#define GPIO_IS_INTR(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_INTR_CODE)
|
||||
#define GPIO_IS_INTEDGE(ps) (((uint16_t)(ps) & GPIO_INTEDGE_MASK) == GPIO_INTEDGE_CODE)
|
||||
#define GPIO_IS_INTLVL(ps) (((uint16_t)(ps) & GPIO_INTLVL_MASK) == GPIO_INTLVL_CODE)
|
||||
|
||||
@@ -180,6 +179,9 @@
|
||||
# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
|
||||
# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
|
||||
|
||||
# define GPIO_PINMIN 0
|
||||
# define GPIO_PINMAX 13
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/max32660/max326_gpioirq.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
|
||||
#include "max326_gpio.h"
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_gpio_irqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support interrupting GPIO pins. This function is
|
||||
* called by the OS initialization logic and is not a user interface.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called early in the boot-up sequence
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void max326_gpio_irqinitialize(void);
|
||||
{
|
||||
/* Attach the GPIO0 interrupt handler and enable interrupts */
|
||||
|
||||
DEBUGVERIFY(irq_attach, MAX326_IRQ_GPIO0, NULL);
|
||||
up_enable_irq(MAX326_IRQ_GPIO0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: max326_gpio_irqconfig
|
||||
*
|
||||
* Description:
|
||||
* Configure a pin for interrupt operation. This function should not be
|
||||
* called directory but, rather, indirectly through max326_gpio_config().
|
||||
*
|
||||
* Assumptions:
|
||||
* - The pin interrupt has been disabled and all interrupt related bits
|
||||
* have been set to zero by max436_gpio_config().
|
||||
* - We are called in a critical section.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void max326_gpio_irqconfig(max326_pinset_t cfgset)
|
||||
{
|
||||
unsigned int pin;
|
||||
uint32_t pinmask;
|
||||
uint32_t intmode;
|
||||
uint32_t intpol;
|
||||
uint32_t intdual;
|
||||
uint32_t regval;
|
||||
|
||||
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
|
||||
DEBUGASSERT(pin <= GPIO_PINMAX);
|
||||
pinmask = 1 << pin;
|
||||
|
||||
intmode = 0;
|
||||
intpol = 0;
|
||||
intdual = 0;
|
||||
|
||||
switch (cfgset & GPIO_FUNC_MASK)
|
||||
{
|
||||
default:
|
||||
case GPIO_INPUT:
|
||||
case GPIO_OUTPUT:
|
||||
case GPIO_ALT1:
|
||||
case GPIO_ALT2:
|
||||
case GPIO_ALT3:
|
||||
DEBUGPANIC();
|
||||
return;
|
||||
|
||||
case GPIO_INTFE: /* Edge triggered, falling edge */
|
||||
intmode = pinmask; /* Edge triggered */
|
||||
break;
|
||||
|
||||
case GPIO_INTRE: /* Edge triggered, rising edge */
|
||||
intmode = pinmask; /* Edge triggered */
|
||||
intpol = pinmask; /* Rising edge */
|
||||
break;
|
||||
|
||||
case GPIO_INTBOTH: /* Edge triggered, both edges */
|
||||
intmode = pinmask; /* Edge triggered */
|
||||
intdual = pinmask; /* Both edges */
|
||||
break;
|
||||
|
||||
case GPIO_INTLOW: /* Level triggered, low level */
|
||||
break;
|
||||
|
||||
case GPIO_INTHIGH: /* Level triggered, high level */
|
||||
intpol = pinmask; /* High level */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure the interrupt */
|
||||
|
||||
regval = getreg32(MAX326_GPIO0_INTMODE);
|
||||
regval &= ~pinmask;
|
||||
regval |= intmode;
|
||||
putreg32(regval, MAX326_GPIO0_INTMODE)
|
||||
|
||||
regval = getreg32(MAX326_GPIO0_INTPOL);
|
||||
regval &= ~pinmask;
|
||||
regval |= intpol;
|
||||
putreg32(regval, MAX326_GPIO0_INTPOL)
|
||||
|
||||
regval = getreg32(MAX326_GPIO0_INTDUALEDGE);
|
||||
regval &= ~pinmask;
|
||||
regval |= intdual;
|
||||
putreg32(regval, MAX326_GPIO0_INTDUALEDGE)
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_irqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable a GPIO pin interrupt. This function should not be called directly but,
|
||||
* rather through up_disable_irq();
|
||||
*
|
||||
* Assumptions:
|
||||
* We are in a critical section.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void max326_gpio_irqdisable(int irq)
|
||||
{
|
||||
unsigned int pin;
|
||||
uint32_t pinmask;
|
||||
uint32_t regval;
|
||||
irqset_t flags;
|
||||
|
||||
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
|
||||
DEBUGASSERT(pin <= GPIO_PINMAX);
|
||||
pinmask = 1 << pin;
|
||||
|
||||
/* Modification of registers must be atomic */
|
||||
|
||||
flags = spin_lock_irqsave();
|
||||
regval = getreg32(MAX326_GPIO0_INTEN);
|
||||
regval &= ~pinmask;
|
||||
putreg32(regval, MAX326_GPIO0_INTEN)
|
||||
spin_unlock_restore(flags);
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_irqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable a GPIO pin interrupt. This function should not be called directly but,
|
||||
* rather through up_enable_irq();
|
||||
*
|
||||
* Assumptions:
|
||||
* We are in a critical section.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void max326_gpio_irqenable(int irq)
|
||||
{
|
||||
unsigned int pin;
|
||||
uint32_t pinmask;
|
||||
uint32_t regval;
|
||||
irqset_t flags;
|
||||
|
||||
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
|
||||
DEBUGASSERT(pin <= GPIO_PINMAX);
|
||||
pinmask = 1 << pin;
|
||||
|
||||
/* Modification of registers must be atomic */
|
||||
|
||||
flags = spin_lock_irqsave();
|
||||
regval = getreg32(MAX326_GPIO0_INTEN);
|
||||
regval |= pinmask;
|
||||
putreg32(regval, MAX326_GPIO0_INTEN)
|
||||
spin_unlock_restore(flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MAX326_GPIOIRQ */
|
||||
@@ -86,12 +86,13 @@ extern "C"
|
||||
* Initialize logic to support interrupting GPIO pins. This function is called by
|
||||
* the OS initialization logic and is not a user interface.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called early in the boot-up sequence
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
void max326_gpio_irqinitialize(void);
|
||||
#else
|
||||
# define max326_gpio_irqinitialize()
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
@@ -100,10 +101,28 @@ void max326_gpio_irqinitialize(void);
|
||||
* Description:
|
||||
* Configure a GPIO pin based on bit-encoded description of the pin.
|
||||
*
|
||||
* Assumptions:
|
||||
* - The pin interrupt has been disabled and all interrupt related bits
|
||||
* have been set to zero by max436_gpio_config().
|
||||
* - We are called in a critical section.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int max326_gpio_config(max326_pinset_t cfgset);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_irqconfig
|
||||
*
|
||||
* Description:
|
||||
* Configure a pin for interrupt operation. This function should not be called
|
||||
* directory but, rather, indirectly through max326_gpio_config().
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
void max326_gpio_irqconfig(max326_pinset_t cfgset);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_write
|
||||
*
|
||||
@@ -124,11 +143,44 @@ void max326_gpio_write(max326_pinset_t pinset, bool value);
|
||||
|
||||
bool max326_gpio_read(max326_pinset_t pinset);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_irqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable a GPIO pin interrupt. This function should not be called directly but,
|
||||
* rather through up_disable_irq();
|
||||
*
|
||||
* Assumptions:
|
||||
* We are in a critical section.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
void max326_gpio_irqdisable(int irq);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: max326_gpio_irqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable a GPIO pin interrupt. This function should not be called directly but,
|
||||
* rather through up_enable_irq();
|
||||
*
|
||||
* Assumptions:
|
||||
* We are in a critical section.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MAX326_GPIOIRQ
|
||||
void max326_gpio_irqenable(int irq);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Function: max326_gpio_dump
|
||||
*
|
||||
* Description:
|
||||
* Dump all GPIO registers associated with the base address of the provided pinset.
|
||||
* Decode and dump all GPIO registers associated with the port and pin
|
||||
* numbers in the provided pinset.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user