LPC17xx GPIO interrupt fixes: lpc17_setintedge() must be atomic. Can't disable interrupts from interrupt handlers because they are automatically re-enabled. Try re-configuring pin instead.

This commit is contained in:
Gregory Nutt 2013-04-07 13:46:05 -06:00
parent a3906f2f72
commit 141fb6a32b
7 changed files with 94 additions and 32 deletions

View File

@ -4523,4 +4523,10 @@
* arch/arm/src/lpc17_gpiodbg.c: Updated so that it correctly
reports LPC177x/8x GPIO registers when GPIO debug is enabled
(2013-4-05).
* arch/arm/src/Makefile: The variable NUTTX already includes
the extension $(EXEEXT). So remove the second extension
$(NUTTX)$(EXEEXT) in two places (2013-4-7).
* arch/arm/src/lpc17xx/lpc17_gpioint.c: Disable interrrupts in
lpc17_setintedge(). This logic must be atomic because it can be
re-entered before it completes enabled interrupts, sometimes
leaving the interrupts in a strange state (2013-4-7).

2
TODO
View File

@ -364,8 +364,6 @@ o Kernel Build
A similar issue exists in NSH that uses some internal OS
interfaces that would not be available in a kernel build
(such as foreach_task, foreach_mountpoint, etc.).
See also "Memory Management" for another kernel build issue.
Status: Open
Priority: Low -- the kernel build configuration is not fully fielded
yet.

View File

@ -99,7 +99,7 @@
#define GPIO_SSP1_MISO_1 (GPIO_ALT2 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN8)
#define GPIO_MAT2p2_1 (GPIO_ALT3 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN8)
#define GPIO_RTC_EV1_1 (GPIO_ALT4 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN8)
#define GPIO_LCD_VD16 (GPIO_ALT7 | GPIO_FLOA | GPIO_HYSTERESIST | GPIO_PORT0 | GPIO_PIN8)
#define GPIO_LCD_VD16 (GPIO_ALT7 | GPIO_FLOAT | GPIO_HYSTERESIS | GPIO_PORT0 | GPIO_PIN8)
#define GPIO_I2S_TXSDA_1 (GPIO_ALT1 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN9)
#define GPIO_SSP1_MOSI_1 (GPIO_ALT2 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN9)

View File

@ -116,8 +116,13 @@ static unsigned int lpc17_getintedge(unsigned int port, unsigned int pin)
static void lpc17_setintedge(uint32_t intbase, unsigned int pin,
unsigned int edges)
{
irqstate_t flags;
int regval;
/* These must be atomic */
flags = irqsave();
/* Set/clear the rising edge enable bit */
regval = getreg32(intbase + LPC17_GPIOINT_INTENR_OFFSET);
@ -145,6 +150,7 @@ static void lpc17_setintedge(uint32_t intbase, unsigned int pin,
}
putreg32(regval, intbase + LPC17_GPIOINT_INTENF_OFFSET);
irqrestore(flags);
}
/****************************************************************************
@ -389,9 +395,10 @@ static void lpc17_gpiodemux(uint32_t intbase, uint32_t intmask,
* Name: lpc17_gpiointerrupt
*
* Description:
* Handle the EINT3 interrupt that also indicates that a GPIO interrupt has
* occurred. NOTE: This logic will have to be extended if EINT3 is
* actually used for External Interrupt 3.
* Handle the GPIO interrupt. For the LPC176x family, that interrupt could
* also that also indicates that an EINT3 interrupt has occurred. NOTE:
* This logic would have to be extended if EINT3 is actually used for
* External Interrupt 3 on an LPC176x platform.
*
****************************************************************************/

View File

@ -12,6 +12,7 @@ CONTENTS
o Buttons
o FPU
o Using OpenOCD with the Olimex ARM-USB-OCD
o Loading Code with the ISP Board
o Configuration
LEDs
@ -245,27 +246,53 @@ Using OpenOCD with the Olimex ARM-USB-OCD
(gdb) monitor halt
NOTES:
1. The MCU must be halted using 'monitor halt' prior to loading code.
2. 'monitor reset' will restart the processor after loading code.
3. The 'monitor' command can be abbreviated as just 'mon'.
After starting GDB, you can load the NuttX ELF file:
After starting GDB, you can load the NuttX ELF file like this:
(gdb) mon halt
(gdb) load nuttx
NOTES:
1. NuttX should have been built so that it has debugging symbols
(by setting CONFIG_DEBUG_SYMBOLS=y in the .config file).
2. The MCU must be halted prior to loading code.
3. I find that there are often undetected write failures. I usually
load nuttx twice to assure good FLASH contents:
3. I find that there are often undetected write failures when using
the Olimex ARM-USB-OCD debugber and that if you start the program
with a bad FLASH failure, it will lock up OpenOCD. I usually
oad nuttx twice, restarting OpenOCD in between in order to assure
good FLASH contents:
(gdb) mon halt
(gdb) load nuttx
(gdb) mon reset
Exit GDB, kill the OpenOCD server, recycle power on the board,
restart the OpenOCD server and GDB, then:
(gdb) mon halt
(gdb) load nuttx
(gdb) mon reset
Other debuggers may not have these issues and such drastic steps may
not be necessary.
Loading Code with the ISP Board
===============================
Use can also load code onto the board using the WaveShare and the UART0
ISP/VCOM board. I use the FlashMagic program for Windows available here:
http://www.flashmagictool.com/ . It is so easy to use that no further
explanation should be necessary: Just select the LPC1788, the ISP COM
port, and the NuttX .hex file and program it.
CONFIGURATION
=============
@ -452,13 +479,18 @@ CONFIGURATION
on the 4.3" LCD module by modifying the configuration in the
following ways:
Drivers:
CONFIG_INPUT=y : Enable support for input devices
CONFIG_INPUT_ADS7843E=y : Enable support for the XPT2048
CONFIG_ADS7843E_SPIDEV=1 : Use SSP1 for communication
CONFIG_SPI=y : Enable SPI support
CONFIG_SPI_EXCHANGE=n : exchange() method is not supported
System Type:
CONFIG_GPIO_IRQ=y : GPIO interrupt support
CONFIG_LPC17_SSP1=y : Enable support for SSP1
Applicaton Configuration:
CONFIG_EXAMPLES_TOUCHSCREEN=y : Enable the touchscreen built-int test
CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN=y
@ -470,15 +502,21 @@ CONFIGURATION
There is a jumper on board that enables the CD pin. OR, you can simply
remove the SD module so that it does not drive the CD pin.
Drivers:
CONFIG_MMCSD=n : No MMC/SD driver support
System Type:
CONFIG_LPC17_GPDMA=n : No DMA
CONFIG_ARCH_DMA=n
CONFIG_LPC17_SDCARD=n : No SD card driver
CONFIG_SDIO_DMA=n : No SD card DMA
CONFIG_MMCSD=n : No MMC/SD driver support
CONFIG_ARCH_DMA=n
File Systems:
CONFIG_FS_FAT=n : No FAT file system support
For touchscreen debug output:
Build Setup:
CONFIG_DEBUG=y
CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_INPUT=y

View File

@ -178,11 +178,21 @@ static void tsc_enable(FAR struct ads7843e_config_s *state, bool enable)
ivdbg("enable:%d\n", enable);
if (enable)
{
/* Configure the PENIRQ GPIO as an interrupting enable and enable the interrupt */
(void)lpc17_configgpio(GPIO_TC_PENIRQ);
up_enable_irq(LPC17_IRQ_PENIRQ);
}
else
{
/* Disable PENIRQ interrupts and reconfigure the pin as a normal input pin.
* We have to do this because the PENIRQ interrupt will be disabled from
* interrupt handling logic and, in that case, will be automatically re-enabled
* when the interrupt returns.
*/
up_disable_irq(LPC17_IRQ_PENIRQ);
(void)lpc17_configgpio(GPIO_TC_PEN);
}
}
@ -278,9 +288,12 @@ int arch_tcinitialize(int minor)
if (!initialized)
{
/* Configure and enable the XPT2046 PENIRQ pin as an interrupting input. */
/* Configure and enable the XPT2046 PENIRQ pin as a normal input. It
* will be reconfigured as an interrupting input when tsc_enable is
* called to enable the PENIRQ interrupt.
*/
(void)lpc17_configgpio(GPIO_TC_PENIRQ);
(void)lpc17_configgpio(GPIO_TC_PEN);
/* Configure the XPT2046 BUSY pin as a normal input. */
@ -336,4 +349,3 @@ void arch_tcuninitialize(void)
}
#endif /* CONFIG_INPUT_ADS7843E */

View File

@ -132,6 +132,7 @@
* Pins are configured as floating because there are pullups on the module.
*/
#define GPIO_TC_PEN (GPIO_INPUT | GPIO_FLOAT | GPIO_PORT2 | GPIO_PIN15)
#define GPIO_TC_PENIRQ (GPIO_INTBOTH | GPIO_FLOAT | GPIO_PORT2 | GPIO_PIN15)
#define GPIO_TC_BUSY (GPIO_INPUT | GPIO_FLOAT | GPIO_PORT2 | GPIO_PIN14)
#define GPIO_TC_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT1 | GPIO_PIN8)