diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index b6817eab23..309fd05966 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3349,3 +3349,15 @@ * configs/*/nxwm/defconfig and sched/task_exithook.c: Fixes for bugs that crept in during recent changes. (Submitted by Max Holtzberg). + * arch/arm/include/armv7-m/irq.h: Fix a critical bug in irqsave(). + It looks like sometimes the compile will re-order some instructions + inapproapriately. This end result is that interrupts will get + stuff off. + * drivers/mtd/w25.c: Beginning of a driver for the Windbond SPI + FLASH family (W25x16, W25x32, and W25x64). The initial check-in + is basically just the SST25 driver with some name changes. + * arch/arm/include/armv7-m/irq.h and arch/arm/src/stm32/stm32_spi.c: + Back out the last change in irq.h. It is (most likely) fine the + way it was. The really interrupt related problem was in stm32_spi.c: + When SPI3 is not enabled, then the irqrestore() falls in the + else clause. diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h index 950ce80ca4..b6306d3390 100644 --- a/nuttx/arch/arm/include/armv7-m/irq.h +++ b/nuttx/arch/arm/include/armv7-m/irq.h @@ -129,6 +129,64 @@ struct xcptcontext #ifndef __ASSEMBLY__ +/* Disable IRQs */ + +static inline void irqdisable(void) __attribute__((always_inline)); +static inline void irqdisable(void) +{ + __asm__ __volatile__ ("\tcpsid i\n"); +} + +/* Save the current primask state & disable IRQs */ + +static inline irqstate_t irqsave(void) __attribute__((always_inline)); +static inline irqstate_t irqsave(void) +{ + unsigned short primask; + + /* Return the current value of primask register and set + * bit 0 of the primask register to disable interrupts + */ + + __asm__ __volatile__ + ( + "\tmrs %0, primask\n" + "\tcpsid i\n" + : "=r" (primask) + : + : "memory"); + + return primask; +} + +/* Enable IRQs */ + +static inline void irqenable(void) __attribute__((always_inline)); +static inline void irqenable(void) +{ + __asm__ __volatile__ ("\tcpsie i\n"); +} + +/* Restore saved primask state */ + +static inline void irqrestore(irqstate_t primask) __attribute__((always_inline)); +static inline void irqrestore(irqstate_t primask) +{ + /* If bit 0 of the primask is 0, then we need to restore + * interupts. + */ + + __asm__ __volatile__ + ( + "\ttst %0, #1\n" + "\tbne 1f\n" + "\tcpsie i\n" + "1:\n" + : + : "r" (primask) + : "memory"); +} + /* Get/set the primask register */ static inline uint8_t getprimask(void) __attribute__((always_inline)); @@ -145,39 +203,6 @@ static inline uint8_t getprimask(void) return (uint8_t)primask; } -/* Disable IRQs */ - -static inline void irqdisable(void) __attribute__((always_inline)); -static inline void irqdisable(void) -{ - __asm__ __volatile__ ("\tcpsid i\n"); -} - -/* Save the current primask state & disable IRQs */ - -static inline irqstate_t irqsave(void) __attribute__((always_inline)); -static inline irqstate_t irqsave(void) -{ - /* Return the current value of primask register (before disabling) */ - - uint8_t primask = getprimask(); - - /* Then set bit 0 of the primask register to disable interrupts */ - - irqdisable(); - return primask; -} - -/* Enable IRQs */ - -static inline void irqenable(void) __attribute__((always_inline)); -static inline void irqenable(void) -{ - __asm__ __volatile__ ("\tcpsie i\n"); -} - -/* Restore saved primask state */ - static inline void setprimask(uint32_t primask) __attribute__((always_inline)); static inline void setprimask(uint32_t primask) { @@ -189,19 +214,6 @@ static inline void setprimask(uint32_t primask) : "memory"); } -static inline void irqrestore(irqstate_t primask) __attribute__((always_inline)); -static inline void irqrestore(irqstate_t primask) -{ - /* If bit 0 of the primask is 0, then we need to restore - * interrupts. - */ - - if ((primask & 1) == 0) - { - setprimask(primask); - } -} - /* Get/set the basepri register */ static inline uint8_t getbasepri(void) __attribute__((always_inline)); diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c index 2d907bfca7..8de698cd5a 100644 --- a/nuttx/arch/arm/src/stm32/stm32_spi.c +++ b/nuttx/arch/arm/src/stm32/stm32_spi.c @@ -1431,7 +1431,12 @@ FAR struct spi_dev_s *up_spiinitialize(int port) spi_portinitialize(priv); } } + else #endif + { + spidbg("ERROR: Unsupported SPI port: %d\n", port); + return NULL; + } irqrestore(flags); return (FAR struct spi_dev_s *)priv;