The commit corrects the gpioirq when mismatch mode is selected and adds support for edge detect mode. Slew Rate was also added for completeness.
This commit is contained in:
parent
6f408b87bf
commit
e5f84dca39
@ -1,7 +1,7 @@
|
|||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* arch/mips/src/pic32mz/pic32mz-ioport.h
|
* arch/mips/src/pic32mz/pic32mz-ioport.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2015, 2019 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -121,10 +121,30 @@
|
|||||||
#define PIC32MZ_IOPORT_CNENSET_OFFSET 0x0088 /* Change Notice Interrupt Enable set register */
|
#define PIC32MZ_IOPORT_CNENSET_OFFSET 0x0088 /* Change Notice Interrupt Enable set register */
|
||||||
#define PIC32MZ_IOPORT_CNENINV_OFFSET 0x008c /* Change Notice Interrupt Enable invert register */
|
#define PIC32MZ_IOPORT_CNENINV_OFFSET 0x008c /* Change Notice Interrupt Enable invert register */
|
||||||
|
|
||||||
#define PIC32MZ_IOPORT_CNSTAT_OFFSET 0x0080 /* Change Notice Control register */
|
#define PIC32MZ_IOPORT_CNSTAT_OFFSET 0x0090 /* Change Notice Status register */
|
||||||
#define PIC32MZ_IOPORT_CNSTATCLR_OFFSET 0x0084 /* Change Notice Control clear register*/
|
#define PIC32MZ_IOPORT_CNSTATCLR_OFFSET 0x0094 /* Change Notice Status clear register*/
|
||||||
#define PIC32MZ_IOPORT_CNSTATSET_OFFSET 0x0088 /* Change Notice Control set register */
|
#define PIC32MZ_IOPORT_CNSTATSET_OFFSET 0x0098 /* Change Notice Status set register */
|
||||||
#define PIC32MZ_IOPORT_CNSTATINV_OFFSET 0x008c /* Change Notice Control invert register */
|
#define PIC32MZ_IOPORT_CNSTATINV_OFFSET 0x009c /* Change Notice Status invert register */
|
||||||
|
|
||||||
|
#define PIC32MZ_IOPORT_CNNE_OFFSET 0x00a0 /* Change Notice Interrupt Enable register */
|
||||||
|
#define PIC32MZ_IOPORT_CNNECLR_OFFSET 0x00a4 /* Change Notice Interrupt Enable clear register */
|
||||||
|
#define PIC32MZ_IOPORT_CNNESET_OFFSET 0x00a8 /* Change Notice Interrupt Enable set register */
|
||||||
|
#define PIC32MZ_IOPORT_CNNEINV_OFFSET 0x00ac /* Change Notice Interrupt Enable invert register */
|
||||||
|
|
||||||
|
#define PIC32MZ_IOPORT_CNF_OFFSET 0x00b0 /* Change Notice Status register */
|
||||||
|
#define PIC32MZ_IOPORT_CNFCLR_OFFSET 0x00b4 /* Change Notice Status clear register */
|
||||||
|
#define PIC32MZ_IOPORT_CNFSET_OFFSET 0x00b8 /* Change Notice Status set register */
|
||||||
|
#define PIC32MZ_IOPORT_CNFINV_OFFSET 0x00bc /* Change Notice Status invert register */
|
||||||
|
|
||||||
|
#define PIC32MZ_IOPORT_SRCON0_OFFSET 0x00c0 /* Slew Rate Control0 register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON0CLR_OFFSET 0x00c4 /* Slew Rate Control0 clear register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON0SET_OFFSET 0x00c8 /* Slew Rate Control0 set register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON0INV_OFFSET 0x00cc /* Slew Rate Control0 invert register */
|
||||||
|
|
||||||
|
#define PIC32MZ_IOPORT_SRCON1_OFFSET 0x00d0 /* Slew Rate Control1 register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON1CLR_OFFSET 0x00d4 /* Slew Rate Control1 clear register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON1SET_OFFSET 0x00d8 /* Slew Rate Control1 set register */
|
||||||
|
#define PIC32MZ_IOPORT_SRCON1INV_OFFSET 0x00dc /* Slew Rate Control1 invert register */
|
||||||
|
|
||||||
/* IOPort Peripheral Addresses **************************************************************/
|
/* IOPort Peripheral Addresses **************************************************************/
|
||||||
|
|
||||||
@ -823,7 +843,8 @@
|
|||||||
|
|
||||||
/* Change Notice Control register */
|
/* Change Notice Control register */
|
||||||
|
|
||||||
#define IOPORT_CNCON_SIDL (1 << 13) /* Bit 13: Stop in idle mode */
|
#define IOPORT_CNCON_EDGEDETECT (1 << 11) /* Bit 11: Change Notification Style bit */
|
||||||
|
#define IOPORT_CNCON_SIDL (1 << 13) /* Bit 13: Stop in Idle Control bit */
|
||||||
#define IOPORT_CNCON_ON (1 << 15) /* Bit 15: Change notice module enable */
|
#define IOPORT_CNCON_ON (1 << 15) /* Bit 15: Change notice module enable */
|
||||||
|
|
||||||
/* Change Notice Interrupt Enable register */
|
/* Change Notice Interrupt Enable register */
|
||||||
@ -836,6 +857,26 @@
|
|||||||
#define IOPORT_CNSTAT(n) (1 << (n)) /* Bits 0-15: Change notice control pin n */
|
#define IOPORT_CNSTAT(n) (1 << (n)) /* Bits 0-15: Change notice control pin n */
|
||||||
#define IOPORT_CNSTAT_ALL 0x0000ffff
|
#define IOPORT_CNSTAT_ALL 0x0000ffff
|
||||||
|
|
||||||
|
/* Change Notice Interrupt Enable register (Negative edge) */
|
||||||
|
|
||||||
|
#define IOPORT_CNNE(n) (1 << (n)) /* Bits 0-15: 1=Interrupt enabled */
|
||||||
|
#define IOPORT_CNNE_ALL 0x0000ffff
|
||||||
|
|
||||||
|
/* Change Notice Status register */
|
||||||
|
|
||||||
|
#define IOPORT_CNF(n) (1 << (n)) /* Bits 0-15: Change notice control pin n */
|
||||||
|
#define IOPORT_CNF_ALL 0x0000ffff
|
||||||
|
|
||||||
|
/* Slew Rate Control0 register */
|
||||||
|
|
||||||
|
#define IOPORT_SRCON0(n) (1 << (n)) /* Bits 0-15: Slew Rate control pin n */
|
||||||
|
#define IOPORT_SRCON0_ALL 0x0000ffff
|
||||||
|
|
||||||
|
/* Slew Rate Control1 register */
|
||||||
|
|
||||||
|
#define IOPORT_SRCON1(n) (1 << (n)) /* Bits 0-15: Slew Rate control pin n */
|
||||||
|
#define IOPORT_SRCON1_ALL 0x0000ffff
|
||||||
|
|
||||||
/********************************************************************************************
|
/********************************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
@ -507,7 +507,7 @@
|
|||||||
|
|
||||||
#undef CONFIG_PIC32MZ_FWDTEN
|
#undef CONFIG_PIC32MZ_FWDTEN
|
||||||
#ifdef CONFIG_PIC32MZ_WDTENABLE
|
#ifdef CONFIG_PIC32MZ_WDTENABLE
|
||||||
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_ENSABLED
|
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_ENABLED
|
||||||
#else
|
#else
|
||||||
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_DISABLED
|
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_DISABLED
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,7 +113,7 @@ static inline bool pic32mz_output(pinset_t pinset)
|
|||||||
|
|
||||||
static inline bool pic32mz_opendrain(pinset_t pinset)
|
static inline bool pic32mz_opendrain(pinset_t pinset)
|
||||||
{
|
{
|
||||||
return ((pinset & GPIO_MODE_MASK) == GPIO_OPENDRAN);
|
return ((pinset & GPIO_MODE_MASK) == GPIO_OPENDRAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool pic32mz_outputhigh(pinset_t pinset)
|
static inline bool pic32mz_outputhigh(pinset_t pinset)
|
||||||
@ -141,6 +141,21 @@ static inline unsigned int pic32mz_analog(pinset_t pinset)
|
|||||||
return ((pinset & GPIO_ANALOG_MASK) != 0);
|
return ((pinset & GPIO_ANALOG_MASK) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int pic32mz_slewrate(pinset_t pinset)
|
||||||
|
{
|
||||||
|
return ((pinset & GPIO_SR_MASK) >> GPIO_SR_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int pic32mz_slewratecon0(pinset_t pinset)
|
||||||
|
{
|
||||||
|
return (pic32mz_slewrate(pinset) & GPIO_SR_CON0_MASK) >> GPIO_SR_CON0_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int pic32mz_slewratecon1(pinset_t pinset)
|
||||||
|
{
|
||||||
|
return (pic32mz_slewrate(pinset) & GPIO_SR_CON1_MASK) >> GPIO_SR_CON1_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -172,9 +187,24 @@ int pic32mz_configgpio(pinset_t cfgset)
|
|||||||
|
|
||||||
base = g_gpiobase[port];
|
base = g_gpiobase[port];
|
||||||
|
|
||||||
|
sched_lock();
|
||||||
|
|
||||||
|
/* Is Slew Rate control enabled? */
|
||||||
|
|
||||||
|
if (pic32mz_slewrate(cfgset) != GPIO_FASTEST)
|
||||||
|
{
|
||||||
|
/* Note: not every port nor every pin has the Slew Rate feature.
|
||||||
|
* Writing to an unimplemented port/pin will have no effect.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(pic32mz_slewratecon0(cfgset),
|
||||||
|
base + PIC32MZ_IOPORT_SRCON0_OFFSET);
|
||||||
|
putreg32(pic32mz_slewratecon1(cfgset),
|
||||||
|
base + PIC32MZ_IOPORT_SRCON1_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
/* Is this an input or an output? */
|
/* Is this an input or an output? */
|
||||||
|
|
||||||
sched_lock();
|
|
||||||
if (pic32mz_output(cfgset))
|
if (pic32mz_output(cfgset))
|
||||||
{
|
{
|
||||||
/* Not analog */
|
/* Not analog */
|
||||||
@ -308,7 +338,7 @@ bool pic32mz_gpioread(pinset_t pinset)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_GPIO_INFO
|
#ifdef CONFIG_DEBUG_GPIO_INFO
|
||||||
void pic32mz_dumpgpio(uint32_t pinset, const char *msg)
|
void pic32mz_dumpgpio(pinset_t pinset, const char *msg)
|
||||||
{
|
{
|
||||||
unsigned int port = pic32mz_portno(pinset);
|
unsigned int port = pic32mz_portno(pinset);
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
@ -51,28 +51,84 @@
|
|||||||
/* GPIO settings used in the configport, readport, writeport, etc.
|
/* GPIO settings used in the configport, readport, writeport, etc.
|
||||||
*
|
*
|
||||||
* General encoding:
|
* General encoding:
|
||||||
* MMAV IIDR RRRx PPPP
|
* xxxx xxxx xxxx xSSM MAVI IIII RRRR PPPP
|
||||||
|
*
|
||||||
|
* x = Not implemented
|
||||||
|
* S = Slew Rate
|
||||||
|
* M = Mode (input/output)
|
||||||
|
* I = Interrupt
|
||||||
|
* R = Register
|
||||||
|
* P = Pin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GPIO_MODE_SHIFT (14) /* Bits 14-15: I/O mode */
|
/* Slew Rate Control.
|
||||||
|
*
|
||||||
|
* .... .... .... .SS. .... .... .... ....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GPIO_SR_SHIFT (17) /* Bits 17-18: Slew Rate Control */
|
||||||
|
#define GPIO_SR_MASK (3 << GPIO_SR_SHIFT)
|
||||||
|
# define GPIO_FASTEST (0 << GPIO_SR_SHIFT) /* 00: Disabled and set to fastest */
|
||||||
|
# define GPIO_MEDIUM (1 << GPIO_SR_SHIFT) /* 01: Enabled and set to medium */
|
||||||
|
# define GPIO_SLOW (2 << GPIO_SR_SHIFT) /* 10: Enabled and set to slow */
|
||||||
|
# define GPIO_SLOWEST (3 << GPIO_SR_SHIFT) /* 11: Enabled and set to slowest */
|
||||||
|
#define GPIO_SR_CON0_SHIFT (0) /* Bit 0: SRCON0x */
|
||||||
|
#define GPIO_SR_CON0_MASK (1 << GPIO_SR_CON0_SHIFT)
|
||||||
|
#define GPIO_SR_CON1_SHIFT (1) /* Bit 1: SRCON1x */
|
||||||
|
#define GPIO_SR_CON1_MASK (1 << GPIO_SR_CON1_SHIFT)
|
||||||
|
|
||||||
|
/* Input/Output mode:
|
||||||
|
*
|
||||||
|
* .... .... .... ...M M... .... .... ....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GPIO_MODE_SHIFT (15) /* Bits 15-16: I/O mode */
|
||||||
#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
|
#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
|
||||||
# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* 00 Normal input */
|
# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* 00 Normal input */
|
||||||
# define GPIO_OUTPUT (2 << GPIO_MODE_SHIFT) /* 10 Normal output */
|
# define GPIO_OUTPUT (2 << GPIO_MODE_SHIFT) /* 10 Normal output */
|
||||||
# define GPIO_OPENDRAN (3 << GPIO_MODE_SHIFT) /* 11 Open drain output */
|
# define GPIO_OPENDRAIN (3 << GPIO_MODE_SHIFT) /* 11 Open drain output */
|
||||||
|
|
||||||
#define GPIO_ANALOG_MASK (1 << 13) /* Bit 13: Analog */
|
/* Analog mode.
|
||||||
# define GPIO_ANALOG (1 << 13)
|
*
|
||||||
|
* .... .... .... .... .A.. .... .... ....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GPIO_ANALOG_SHIFT (14) /* Bit 14: Analog */
|
||||||
|
#define GPIO_ANALOG_MASK (1 << GPIO_ANALOG_SHIFT)
|
||||||
|
# define GPIO_ANALOG (1 << GPIO_ANALOG_SHIFT)
|
||||||
# define GPIO_DIGITAL (0)
|
# define GPIO_DIGITAL (0)
|
||||||
|
|
||||||
#define GPIO_VALUE_MASK (1 << 12) /* Bit 12: Initial output value */
|
/* Pin Value.
|
||||||
# define GPIO_VALUE_ONE (1 << 12)
|
*
|
||||||
|
* .... .... .... .... ..V. .... .... ....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GPIO_VALUE_SHIFT (13) /* Bit 13: Initializetial output value */
|
||||||
|
#define GPIO_VALUE_MASK (1 << GPIO_VALUE_SHIFT)
|
||||||
|
# define GPIO_VALUE_ONE (1 << GPIO_VALUE_SHIFT)
|
||||||
# define GPIO_VALUE_ZERO (0)
|
# define GPIO_VALUE_ZERO (0)
|
||||||
|
|
||||||
#define GPIO_INTERRUPT (1 << 11) /* Bit 11: Change notification enable */
|
/* Change Notification config.
|
||||||
#define GPIO_PULLUP (1 << 10) /* Bit 10: Change notification pull-up */
|
*
|
||||||
#define GPIO_PULLDOWN (1 << 9) /* Bit 9: Change notification pull-down */
|
* .... .... .... .... ...I IIII .... ....
|
||||||
|
*/
|
||||||
|
|
||||||
#define GPIO_PORT_SHIFT (5) /* Bits 5-8: Port number */
|
#define GPIO_CN_SHIFT (8) /* Bit 8 - 12: Change notification bits */
|
||||||
|
#define GPIO_CN_MASK (31 << GPIO_CN_SHIFT)
|
||||||
|
# define GPIO_INTERRUPT (1 << GPIO_CN_SHIFT) /* Bit 8: Change notification enable bit */
|
||||||
|
# define GPIO_PULLUP (2 << GPIO_CN_SHIFT) /* Bit 9: Change notification pull-up */
|
||||||
|
# define GPIO_PULLDOWN (4 << GPIO_CN_SHIFT) /* Bit 10: Change notification pull-down */
|
||||||
|
# define GPIO_EDGE_DETECT (8 << GPIO_CN_SHIFT) /* Bit 11: Change notification interrupt mode */
|
||||||
|
# define GPIO_MISMATCH (0)
|
||||||
|
# define GPIO_EDGE_RISING (12 << GPIO_CN_SHIFT) /* Bit 12: Change notification edge type */
|
||||||
|
# define GPIO_EDGE_FALLING (0)
|
||||||
|
|
||||||
|
/* GPIO Port.
|
||||||
|
*
|
||||||
|
* .... .... .... .... .... .... RRRR ....
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GPIO_PORT_SHIFT (4) /* Bits 4-7: Port number */
|
||||||
#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT)
|
#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT)
|
||||||
# define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
|
# define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
|
||||||
# define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
|
# define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
|
||||||
@ -85,6 +141,11 @@
|
|||||||
# define GPIO_PORTJ (8 << GPIO_PORT_SHIFT)
|
# define GPIO_PORTJ (8 << GPIO_PORT_SHIFT)
|
||||||
# define GPIO_PORTK (9 << GPIO_PORT_SHIFT)
|
# define GPIO_PORTK (9 << GPIO_PORT_SHIFT)
|
||||||
|
|
||||||
|
/* GPIO Pin.
|
||||||
|
*
|
||||||
|
* .... .... .... .... .... .... .... PPPP
|
||||||
|
*/
|
||||||
|
|
||||||
#define GPIO_PIN_SHIFT 0 /* Bits 0-3: GPIO number: 0-15 */
|
#define GPIO_PIN_SHIFT 0 /* Bits 0-3: GPIO number: 0-15 */
|
||||||
#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
|
#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
|
||||||
#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
|
#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
|
||||||
@ -110,7 +171,7 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
typedef uint16_t pinset_t;
|
typedef uint32_t pinset_t;
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
@ -210,7 +271,7 @@ void pic32mz_gpioirqinitialize(void);
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_PIC32MZ_GPIOIRQ
|
#ifdef CONFIG_PIC32MZ_GPIOIRQ
|
||||||
int pic32mz_gpioattach(uint32_t pinset, xcpt_t handler, void *arg);
|
int pic32mz_gpioattach(pinset_t pinset, xcpt_t handler, void *arg);
|
||||||
#else
|
#else
|
||||||
# define pic32mz_gpioattach(p,h,a) (0)
|
# define pic32mz_gpioattach(p,h,a) (0)
|
||||||
#endif
|
#endif
|
||||||
@ -252,7 +313,7 @@ void pic32mz_gpioirqdisable(pinset_t pinset);
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_GPIO_INFO
|
#ifdef CONFIG_DEBUG_GPIO_INFO
|
||||||
void pic32mz_dumpgpio(uint32_t pinset, const char *msg);
|
void pic32mz_dumpgpio(pinset_t pinset, const char *msg);
|
||||||
#else
|
#else
|
||||||
# define pic32mz_dumpgpio(p,m)
|
# define pic32mz_dumpgpio(p,m)
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,6 +70,8 @@ static inline unsigned int pic32mz_ioport(pinset_t pinset);
|
|||||||
static inline unsigned int pic32mz_pin(pinset_t pinset);
|
static inline unsigned int pic32mz_pin(pinset_t pinset);
|
||||||
static inline bool pic32mz_input(pinset_t pinset);
|
static inline bool pic32mz_input(pinset_t pinset);
|
||||||
static inline bool pic32mz_interrupt(pinset_t pinset);
|
static inline bool pic32mz_interrupt(pinset_t pinset);
|
||||||
|
static inline bool pic32mz_edgedetect(pinset_t pinset);
|
||||||
|
static inline unsigned int pic32mz_edgemode(pinset_t pinset);
|
||||||
static inline bool pic32mz_pullup(pinset_t pinset);
|
static inline bool pic32mz_pullup(pinset_t pinset);
|
||||||
static inline bool pic32mz_pulldown(pinset_t pinset);
|
static inline bool pic32mz_pulldown(pinset_t pinset);
|
||||||
static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg);
|
static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg);
|
||||||
@ -174,7 +176,7 @@ static struct ioport_level2_s * const g_level2_handlers[CHIP_NPORTS] =
|
|||||||
|
|
||||||
static inline bool pic32mz_input(pinset_t pinset)
|
static inline bool pic32mz_input(pinset_t pinset)
|
||||||
{
|
{
|
||||||
return ((pinset & GPIO_MODE_MASK) != GPIO_INPUT);
|
return (((pinset & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT) == GPIO_INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool pic32mz_interrupt(pinset_t pinset)
|
static inline bool pic32mz_interrupt(pinset_t pinset)
|
||||||
@ -182,6 +184,16 @@ static inline bool pic32mz_interrupt(pinset_t pinset)
|
|||||||
return ((pinset & GPIO_INTERRUPT) != 0);
|
return ((pinset & GPIO_INTERRUPT) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool pic32mz_edgedetect(pinset_t pinset)
|
||||||
|
{
|
||||||
|
return ((pinset & GPIO_EDGE_DETECT) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int pic32mz_edgemode(pinset_t pinset)
|
||||||
|
{
|
||||||
|
return ((pinset & GPIO_EDGE_RISING));
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool pic32mz_pullup(pinset_t pinset)
|
static inline bool pic32mz_pullup(pinset_t pinset)
|
||||||
{
|
{
|
||||||
return ((pinset & GPIO_PULLUP) != 0);
|
return ((pinset & GPIO_PULLUP) != 0);
|
||||||
@ -215,8 +227,11 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
|
|||||||
struct ioport_level2_s *handlers;
|
struct ioport_level2_s *handlers;
|
||||||
xcpt_t handler;
|
xcpt_t handler;
|
||||||
uintptr_t base;
|
uintptr_t base;
|
||||||
uint32_t cnstat;
|
uint32_t cncon;
|
||||||
uint32_t cnen;
|
uint32_t cnen;
|
||||||
|
uint32_t cnne;
|
||||||
|
uint32_t cnstat;
|
||||||
|
uint32_t cnf;
|
||||||
uint32_t pending;
|
uint32_t pending;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
int ioport;
|
int ioport;
|
||||||
@ -240,29 +255,29 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
|
|||||||
base = g_gpiobase[ioport];
|
base = g_gpiobase[ioport];
|
||||||
DEBUGASSERT(handlers && base);
|
DEBUGASSERT(handlers && base);
|
||||||
|
|
||||||
|
/* Get the control registers. It will be used to get the interrupt type. */
|
||||||
|
|
||||||
|
cncon = getreg32(base + PIC32MZ_IOPORT_CNCON_OFFSET);
|
||||||
|
|
||||||
if (handlers && base)
|
if (handlers && base)
|
||||||
|
{
|
||||||
|
/* Mismatch mode selected? */
|
||||||
|
|
||||||
|
if ((cncon & IOPORT_CNCON_EDGEDETECT) == 0)
|
||||||
{
|
{
|
||||||
/* Get the interrupt status associated with this interrupt */
|
/* Get the interrupt status associated with this interrupt */
|
||||||
|
|
||||||
cnstat = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
|
cnstat = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
|
||||||
cnen = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
|
cnen = getreg32(base + PIC32MZ_IOPORT_CNEN_OFFSET);
|
||||||
pending = cnstat & cnen;
|
pending = cnstat & cnen;
|
||||||
|
|
||||||
/* Hmmm.. the data sheet implies that the status will pend
|
|
||||||
* until the corresponding PORTx registers is read? Clear
|
|
||||||
* pending status.
|
|
||||||
*/
|
|
||||||
|
|
||||||
regval = getreg32(base + PIC32MZ_IOPORT_PORT_OFFSET);
|
|
||||||
UNUSED(regval);
|
|
||||||
|
|
||||||
/* Call all attached handlers for each pending interrupt */
|
/* Call all attached handlers for each pending interrupt */
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
/* Is this interrupt pending */
|
/* Is this interrupt pending */
|
||||||
|
|
||||||
if ((pending & (1 << IOPORT_CNSTAT(i))) != 0)
|
if ((pending & (IOPORT_CNSTAT(i))) != 0)
|
||||||
{
|
{
|
||||||
/* Yes.. Has the user attached a handler? */
|
/* Yes.. Has the user attached a handler? */
|
||||||
|
|
||||||
@ -284,6 +299,61 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear pending status. */
|
||||||
|
|
||||||
|
regval = getreg32(base + PIC32MZ_IOPORT_PORT_OFFSET);
|
||||||
|
UNUSED(regval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Edge detect mode selected. */
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Get the interrupt status associated with this interrupt.
|
||||||
|
* The interrupt is controlled by either CNEN (positive edge)
|
||||||
|
* or CNNE (negative edge).
|
||||||
|
*/
|
||||||
|
|
||||||
|
cnen = getreg32(base + PIC32MZ_IOPORT_CNEN_OFFSET);
|
||||||
|
cnne = getreg32(base + PIC32MZ_IOPORT_CNNE_OFFSET);
|
||||||
|
cnf = getreg32(base + PIC32MZ_IOPORT_CNF_OFFSET);
|
||||||
|
pending = cnf & (cnen | cnne);
|
||||||
|
|
||||||
|
/* Call all attached handlers for each pending interrupt */
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
/* Is this interrupt pending */
|
||||||
|
|
||||||
|
if ((pending & (IOPORT_CNF(i))) != 0)
|
||||||
|
{
|
||||||
|
/* Yes.. Has the user attached a handler? */
|
||||||
|
|
||||||
|
handler = handlers->handler[i].entry;
|
||||||
|
if (handler)
|
||||||
|
{
|
||||||
|
/* Yes.. call the attached handler */
|
||||||
|
|
||||||
|
status = handler(irq, context, handlers->handler[i].arg);
|
||||||
|
|
||||||
|
/* Keep track of the status of the last handler that
|
||||||
|
* failed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
ret = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending status. */
|
||||||
|
|
||||||
|
putreg32(pending, base + PIC32MZ_IOPORT_CNFCLR_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the pending interrupt */
|
/* Clear the pending interrupt */
|
||||||
@ -309,6 +379,7 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
|
|||||||
void pic32mz_gpioirqinitialize(void)
|
void pic32mz_gpioirqinitialize(void)
|
||||||
{
|
{
|
||||||
uintptr_t base;
|
uintptr_t base;
|
||||||
|
uint32_t regval;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -327,6 +398,7 @@ void pic32mz_gpioirqinitialize(void)
|
|||||||
/* Reset all registers and disable the CN module */
|
/* Reset all registers and disable the CN module */
|
||||||
|
|
||||||
putreg32(IOPORT_CNEN_ALL, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
putreg32(IOPORT_CNEN_ALL, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
||||||
|
putreg32(IOPORT_CNNE_ALL, base + PIC32MZ_IOPORT_CNNECLR_OFFSET);
|
||||||
putreg32(IOPORT_CNPU_ALL, base + PIC32MZ_IOPORT_CNPUCLR_OFFSET);
|
putreg32(IOPORT_CNPU_ALL, base + PIC32MZ_IOPORT_CNPUCLR_OFFSET);
|
||||||
putreg32(IOPORT_CNPD_ALL, base + PIC32MZ_IOPORT_CNPDCLR_OFFSET);
|
putreg32(IOPORT_CNPD_ALL, base + PIC32MZ_IOPORT_CNPDCLR_OFFSET);
|
||||||
putreg32(0, base + PIC32MZ_IOPORT_CNCON_OFFSET);
|
putreg32(0, base + PIC32MZ_IOPORT_CNCON_OFFSET);
|
||||||
@ -350,9 +422,14 @@ void pic32mz_gpioirqinitialize(void)
|
|||||||
|
|
||||||
putreg32(IOPORT_CNCON_ON, base + PIC32MZ_IOPORT_CNCON_OFFSET);
|
putreg32(IOPORT_CNCON_ON, base + PIC32MZ_IOPORT_CNCON_OFFSET);
|
||||||
|
|
||||||
/* And enable the GPIO interrupt. Same assumption as above. */
|
/* Read the port to clear the interrupt. */
|
||||||
|
|
||||||
up_enable_irq(PIC32MZ_IRQ_PORTA + i);
|
regval = getreg32(base + PIC32MZ_IOPORT_PORT_OFFSET);
|
||||||
|
UNUSED(regval);
|
||||||
|
|
||||||
|
/* Clear the CN interrupt flag. Same assumption as above. */
|
||||||
|
|
||||||
|
up_clrpend_irq(PIC32MZ_IRQ_PORTA + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,8 +459,7 @@ void pic32mz_gpioirqinitialize(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_PIC32MZ_GPIOIRQ
|
int pic32mz_gpioattach(pinset_t pinset, xcpt_t handler, void *arg)
|
||||||
int pic32mz_gpioattach(uint32_t pinset, xcpt_t handler, void *arg)
|
|
||||||
{
|
{
|
||||||
struct ioport_level2_s *handlers;
|
struct ioport_level2_s *handlers;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
@ -391,8 +467,6 @@ int pic32mz_gpioattach(uint32_t pinset, xcpt_t handler, void *arg)
|
|||||||
int ioport;
|
int ioport;
|
||||||
int pin;
|
int pin;
|
||||||
|
|
||||||
DEBUGASSERT(pin < IOPORT_NUMCN);
|
|
||||||
|
|
||||||
/* First verify that the pinset is configured as an interrupting input */
|
/* First verify that the pinset is configured as an interrupting input */
|
||||||
|
|
||||||
if (pic32mz_input(pinset) && pic32mz_interrupt(pinset))
|
if (pic32mz_input(pinset) && pic32mz_interrupt(pinset))
|
||||||
@ -468,6 +542,7 @@ int pic32mz_gpioattach(uint32_t pinset, xcpt_t handler, void *arg)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
||||||
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNNECLR_OFFSET);
|
||||||
|
|
||||||
/* Set the new handler (perhaps NULLifying the current handler) */
|
/* Set the new handler (perhaps NULLifying the current handler) */
|
||||||
|
|
||||||
@ -506,13 +581,44 @@ void pic32mz_gpioirqenable(pinset_t pinset)
|
|||||||
DEBUGASSERT(base);
|
DEBUGASSERT(base);
|
||||||
if (base)
|
if (base)
|
||||||
{
|
{
|
||||||
/* And enable the interrupt. NOTE that we don't actually check if
|
/* Enable the correct CN interrupt.
|
||||||
|
* NOTE that we don't actually check if
|
||||||
* interrupts are configured for this IO port. If not, this operation
|
* interrupts are configured for this IO port. If not, this operation
|
||||||
* should do nothing.
|
* should do nothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (!pic32mz_edgedetect(pinset))
|
||||||
|
{
|
||||||
|
/* If Edge detect is not selected, then CNEN
|
||||||
|
* controls the interrupt.
|
||||||
|
*/
|
||||||
|
|
||||||
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENSET_OFFSET);
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENSET_OFFSET);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Enable edge detect. */
|
||||||
|
|
||||||
|
putreg32(IOPORT_CNCON_EDGEDETECT, base + PIC32MZ_IOPORT_CNCONSET_OFFSET);
|
||||||
|
|
||||||
|
if (pic32mz_edgemode(pinset) == GPIO_EDGE_RISING)
|
||||||
|
{
|
||||||
|
/* Rising edge selected. CNEN controls the interrupt. */
|
||||||
|
|
||||||
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENSET_OFFSET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Falling edge selected. CNNE controls the interrupt. */
|
||||||
|
|
||||||
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNNESET_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And enable the interrupt. */
|
||||||
|
|
||||||
|
up_enable_irq(ioport + PIC32MZ_IRQ_PORTA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -541,13 +647,40 @@ void pic32mz_gpioirqdisable(pinset_t pinset)
|
|||||||
DEBUGASSERT(base);
|
DEBUGASSERT(base);
|
||||||
if (base)
|
if (base)
|
||||||
{
|
{
|
||||||
/* And disable the interrupt. NOTE that we don't actually check if
|
/* And disable the correct interrupt.
|
||||||
|
* NOTE that we don't actually check if
|
||||||
* interrupts are configured for this IO port. If not, this operation
|
* interrupts are configured for this IO port. If not, this operation
|
||||||
* should do nothing.
|
* should do nothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (!pic32mz_edgedetect(pinset))
|
||||||
|
{
|
||||||
|
/* If Edge detect is not selected, then CNEN
|
||||||
|
* controls the interrupt.
|
||||||
|
*/
|
||||||
|
|
||||||
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pic32mz_edgemode(pinset) == GPIO_EDGE_RISING)
|
||||||
|
{
|
||||||
|
/* Rising edge selected.
|
||||||
|
* CNEN controls the interrupt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Falling edge selected.
|
||||||
|
* CNNE controls the interrupt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNNECLR_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_PIC32MZ_GPIOIRQ */
|
#endif /* CONFIG_PIC32MZ_GPIOIRQ */
|
||||||
|
Loading…
Reference in New Issue
Block a user