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:
Abdelatif Guettouche 2019-04-03 17:26:22 -06:00 committed by Gregory Nutt
parent 6f408b87bf
commit e5f84dca39
5 changed files with 365 additions and 100 deletions

View File

@ -1,7 +1,7 @@
/********************************************************************************************
* 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>
*
* 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_CNENINV_OFFSET 0x008c /* Change Notice Interrupt Enable invert register */
#define PIC32MZ_IOPORT_CNSTAT_OFFSET 0x0080 /* Change Notice Control register */
#define PIC32MZ_IOPORT_CNSTATCLR_OFFSET 0x0084 /* Change Notice Control clear register*/
#define PIC32MZ_IOPORT_CNSTATSET_OFFSET 0x0088 /* Change Notice Control set register */
#define PIC32MZ_IOPORT_CNSTATINV_OFFSET 0x008c /* Change Notice Control invert register */
#define PIC32MZ_IOPORT_CNSTAT_OFFSET 0x0090 /* Change Notice Status register */
#define PIC32MZ_IOPORT_CNSTATCLR_OFFSET 0x0094 /* Change Notice Status clear register*/
#define PIC32MZ_IOPORT_CNSTATSET_OFFSET 0x0098 /* Change Notice Status set 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 **************************************************************/
@ -823,7 +843,8 @@
/* 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 */
/* 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_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
********************************************************************************************/

View File

@ -507,7 +507,7 @@
#undef CONFIG_PIC32MZ_FWDTEN
#ifdef CONFIG_PIC32MZ_WDTENABLE
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_ENSABLED
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_ENABLED
#else
# define CONFIG_PIC32MZ_FWDTEN DEVCFG1_FWDT_DISABLED
#endif

View File

@ -113,7 +113,7 @@ static inline bool pic32mz_output(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)
@ -141,6 +141,21 @@ static inline unsigned int pic32mz_analog(pinset_t pinset)
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
****************************************************************************/
@ -172,9 +187,24 @@ int pic32mz_configgpio(pinset_t cfgset)
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? */
sched_lock();
if (pic32mz_output(cfgset))
{
/* Not analog */
@ -308,7 +338,7 @@ bool pic32mz_gpioread(pinset_t pinset)
****************************************************************************/
#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);
irqstate_t flags;

View File

@ -51,58 +51,119 @@
/* GPIO settings used in the configport, readport, writeport, etc.
*
* 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 */
#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* 00 Normal input */
# define GPIO_OUTPUT (2 << GPIO_MODE_SHIFT) /* 10 Normal output */
# define GPIO_OPENDRAN (3 << GPIO_MODE_SHIFT) /* 11 Open drain output */
/* Slew Rate Control.
*
* .... .... .... .SS. .... .... .... ....
*/
#define GPIO_ANALOG_MASK (1 << 13) /* Bit 13: Analog */
# define GPIO_ANALOG (1 << 13)
# define GPIO_DIGITAL (0)
#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)
#define GPIO_VALUE_MASK (1 << 12) /* Bit 12: Initial output value */
# define GPIO_VALUE_ONE (1 << 12)
# define GPIO_VALUE_ZERO (0)
/* Input/Output mode:
*
* .... .... .... ...M M... .... .... ....
*/
#define GPIO_INTERRUPT (1 << 11) /* Bit 11: Change notification enable */
#define GPIO_PULLUP (1 << 10) /* Bit 10: Change notification pull-up */
#define GPIO_PULLDOWN (1 << 9) /* Bit 9: Change notification pull-down */
#define GPIO_MODE_SHIFT (15) /* Bits 15-16: I/O mode */
#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT)
# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* 00 Normal input */
# define GPIO_OUTPUT (2 << GPIO_MODE_SHIFT) /* 10 Normal output */
# define GPIO_OPENDRAIN (3 << GPIO_MODE_SHIFT) /* 11 Open drain output */
#define GPIO_PORT_SHIFT (5) /* Bits 5-8: Port number */
#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT)
# define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
# define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
# define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
# define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
# define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
# define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
# define GPIO_PORTG (6 << GPIO_PORT_SHIFT)
# define GPIO_PORTH (7 << GPIO_PORT_SHIFT)
# define GPIO_PORTJ (8 << GPIO_PORT_SHIFT)
# define GPIO_PORTK (9 << GPIO_PORT_SHIFT)
/* Analog mode.
*
* .... .... .... .... .A.. .... .... ....
*/
#define GPIO_PIN_SHIFT 0 /* Bits 0-3: GPIO number: 0-15 */
#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
#define GPIO_PIN1 (1 << GPIO_PIN_SHIFT)
#define GPIO_PIN2 (2 << GPIO_PIN_SHIFT)
#define GPIO_PIN3 (3 << GPIO_PIN_SHIFT)
#define GPIO_PIN4 (4 << GPIO_PIN_SHIFT)
#define GPIO_PIN5 (5 << GPIO_PIN_SHIFT)
#define GPIO_PIN6 (6 << GPIO_PIN_SHIFT)
#define GPIO_PIN7 (7 << GPIO_PIN_SHIFT)
#define GPIO_PIN8 (8 << GPIO_PIN_SHIFT)
#define GPIO_PIN9 (9 << GPIO_PIN_SHIFT)
#define GPIO_PIN10 (10 << GPIO_PIN_SHIFT)
#define GPIO_PIN11 (11 << GPIO_PIN_SHIFT)
#define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
#define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
#define GPIO_PIN14 (14 << GPIO_PIN_SHIFT)
#define GPIO_PIN15 (15 << GPIO_PIN_SHIFT)
#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)
/* Pin Value.
*
* .... .... .... .... ..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)
/* Change Notification config.
*
* .... .... .... .... ...I IIII .... ....
*/
#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_PORTA (0 << GPIO_PORT_SHIFT)
# define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
# define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
# define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
# define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
# define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
# define GPIO_PORTG (6 << GPIO_PORT_SHIFT)
# define GPIO_PORTH (7 << GPIO_PORT_SHIFT)
# define GPIO_PORTJ (8 << 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_MASK (15 << GPIO_PIN_SHIFT)
#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
#define GPIO_PIN1 (1 << GPIO_PIN_SHIFT)
#define GPIO_PIN2 (2 << GPIO_PIN_SHIFT)
#define GPIO_PIN3 (3 << GPIO_PIN_SHIFT)
#define GPIO_PIN4 (4 << GPIO_PIN_SHIFT)
#define GPIO_PIN5 (5 << GPIO_PIN_SHIFT)
#define GPIO_PIN6 (6 << GPIO_PIN_SHIFT)
#define GPIO_PIN7 (7 << GPIO_PIN_SHIFT)
#define GPIO_PIN8 (8 << GPIO_PIN_SHIFT)
#define GPIO_PIN9 (9 << GPIO_PIN_SHIFT)
#define GPIO_PIN10 (10 << GPIO_PIN_SHIFT)
#define GPIO_PIN11 (11 << GPIO_PIN_SHIFT)
#define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
#define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
#define GPIO_PIN14 (14 << GPIO_PIN_SHIFT)
#define GPIO_PIN15 (15 << GPIO_PIN_SHIFT)
/************************************************************************************
* Public Types
@ -110,7 +171,7 @@
#ifndef __ASSEMBLY__
typedef uint16_t pinset_t;
typedef uint32_t pinset_t;
/************************************************************************************
* Public Data
@ -210,7 +271,7 @@ void pic32mz_gpioirqinitialize(void);
****************************************************************************/
#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
# define pic32mz_gpioattach(p,h,a) (0)
#endif
@ -252,7 +313,7 @@ void pic32mz_gpioirqdisable(pinset_t pinset);
************************************************************************************/
#ifdef CONFIG_DEBUG_GPIO_INFO
void pic32mz_dumpgpio(uint32_t pinset, const char *msg);
void pic32mz_dumpgpio(pinset_t pinset, const char *msg);
#else
# define pic32mz_dumpgpio(p,m)
#endif

View File

@ -70,6 +70,8 @@ static inline unsigned int pic32mz_ioport(pinset_t pinset);
static inline unsigned int pic32mz_pin(pinset_t pinset);
static inline bool pic32mz_input(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_pulldown(pinset_t pinset);
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)
{
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)
@ -182,6 +184,16 @@ static inline bool pic32mz_interrupt(pinset_t pinset)
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)
{
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;
xcpt_t handler;
uintptr_t base;
uint32_t cnstat;
uint32_t cncon;
uint32_t cnen;
uint32_t cnne;
uint32_t cnstat;
uint32_t cnf;
uint32_t pending;
uint32_t regval;
int ioport;
@ -240,50 +255,105 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
base = g_gpiobase[ioport];
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)
{
/* Get the interrupt status associated with this interrupt */
/* Mismatch mode selected? */
cnstat = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
cnen = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
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 */
for (i = 0; i < 16; i++)
if ((cncon & IOPORT_CNCON_EDGEDETECT) == 0)
{
/* Is this interrupt pending */
/* Get the interrupt status associated with this interrupt */
if ((pending & (1 << IOPORT_CNSTAT(i))) != 0)
cnstat = getreg32(base + PIC32MZ_IOPORT_CNSTAT_OFFSET);
cnen = getreg32(base + PIC32MZ_IOPORT_CNEN_OFFSET);
pending = cnstat & cnen;
/* Call all attached handlers for each pending interrupt */
for (i = 0; i < 16; i++)
{
/* Yes.. Has the user attached a handler? */
/* Is this interrupt pending */
handler = handlers->handler[i].entry;
if (handler)
if ((pending & (IOPORT_CNSTAT(i))) != 0)
{
/* Yes.. call the attached handler */
/* Yes.. Has the user attached a handler? */
status = handler(irq, context, handlers->handler[i].arg);
/* Keep track of the status of the last handler that
* failed.
*/
if (status < 0)
handler = handlers->handler[i].entry;
if (handler)
{
ret = status;
/* 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. */
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 */
@ -309,6 +379,7 @@ static int pic32mz_cninterrupt(int irq, FAR void *context, FAR void *arg)
void pic32mz_gpioirqinitialize(void)
{
uintptr_t base;
uint32_t regval;
int ret;
int i;
@ -327,6 +398,7 @@ void pic32mz_gpioirqinitialize(void)
/* Reset all registers and disable the CN module */
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_CNPD_ALL, base + PIC32MZ_IOPORT_CNPDCLR_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);
/* 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(uint32_t pinset, xcpt_t handler, void *arg)
int pic32mz_gpioattach(pinset_t pinset, xcpt_t handler, void *arg)
{
struct ioport_level2_s *handlers;
irqstate_t flags;
@ -391,8 +467,6 @@ int pic32mz_gpioattach(uint32_t pinset, xcpt_t handler, void *arg)
int ioport;
int pin;
DEBUGASSERT(pin < IOPORT_NUMCN);
/* First verify that the pinset is configured as an interrupting input */
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_CNNECLR_OFFSET);
/* Set the new handler (perhaps NULLifying the current handler) */
@ -506,12 +581,43 @@ void pic32mz_gpioirqenable(pinset_t pinset)
DEBUGASSERT(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
* should do nothing.
*/
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENSET_OFFSET);
if (!pic32mz_edgedetect(pinset))
{
/* If Edge detect is not selected, then CNEN
* controls the interrupt.
*/
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,12 +647,39 @@ void pic32mz_gpioirqdisable(pinset_t pinset)
DEBUGASSERT(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
* should do nothing.
*/
putreg32(1 << pin, base + PIC32MZ_IOPORT_CNENCLR_OFFSET);
if (!pic32mz_edgedetect(pinset))
{
/* If Edge detect is not selected, then CNEN
* controls the interrupt.
*/
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);
}
}
}
}