forked from Archive/PX4-Autopilot
Fix logic in STM32 SPI driver that leaves interrupts disabled; back out earlier change to irqsave()
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@5158 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
3364b55f86
commit
fd63baf0fa
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue