aboutsummaryrefslogtreecommitdiff
path: root/nuttx/arch
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-09-15 16:02:58 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2012-09-15 16:02:58 +0000
commit4070ce05feae09331156c64b882bead55831f5e3 (patch)
treef5f057626312c87f0089041fbc93eeb960dba3cd /nuttx/arch
parentcfa24e37d6f153dbb5c7e2e0de6484719ea4a9b0 (diff)
downloadpx4-firmware-4070ce05feae09331156c64b882bead55831f5e3.tar.gz
px4-firmware-4070ce05feae09331156c64b882bead55831f5e3.tar.bz2
px4-firmware-4070ce05feae09331156c64b882bead55831f5e3.zip
Fix a ARMv7-M interrupt disable/optimization bug
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@5155 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'nuttx/arch')
-rw-r--r--nuttx/arch/arm/include/armv7-m/irq.h86
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_spi.c26
2 files changed, 59 insertions, 53 deletions
diff --git a/nuttx/arch/arm/include/armv7-m/irq.h b/nuttx/arch/arm/include/armv7-m/irq.h
index 6cef85c02..950ce80ca 100644
--- a/nuttx/arch/arm/include/armv7-m/irq.h
+++ b/nuttx/arch/arm/include/armv7-m/irq.h
@@ -129,8 +129,25 @@ struct xcptcontext
#ifndef __ASSEMBLY__
+/* Get/set the primask register */
+
+static inline uint8_t getprimask(void) __attribute__((always_inline));
+static inline uint8_t getprimask(void)
+{
+ uint32_t primask;
+ __asm__ __volatile__
+ (
+ "\tmrs %0, primask\n"
+ : "=r" (primask)
+ :
+ : "memory");
+
+ return (uint8_t)primask;
+}
+
/* Disable IRQs */
+static inline void irqdisable(void) __attribute__((always_inline));
static inline void irqdisable(void)
{
__asm__ __volatile__ ("\tcpsid i\n");
@@ -138,26 +155,22 @@ static inline void irqdisable(void)
/* 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 (before disabling) */
- /* Return the current value of primask register and set
- * bit 0 of the primask register to disable interrupts
- */
+ uint8_t primask = getprimask();
- __asm__ __volatile__
- (
- "\tmrs %0, primask\n"
- "\tcpsid i\n"
- : "=r" (primask)
- :
- : "memory");
+ /* 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");
@@ -165,61 +178,48 @@ static inline void irqenable(void)
/* Restore saved primask state */
-static inline void irqrestore(irqstate_t primask)
+static inline void setprimask(uint32_t primask) __attribute__((always_inline));
+static inline void setprimask(uint32_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"
+ "\tmsr primask, %0\n"
:
: "r" (primask)
: "memory");
}
-/* Get/set the primask register */
-
-static inline uint8_t getprimask(void)
+static inline void irqrestore(irqstate_t primask) __attribute__((always_inline));
+static inline void irqrestore(irqstate_t primask)
{
- uint32_t primask;
- __asm__ __volatile__
- (
- "\tmrs %0, primask\n"
- : "=r" (primask)
- :
- : "memory");
- return (uint8_t)primask;
-}
+ /* If bit 0 of the primask is 0, then we need to restore
+ * interrupts.
+ */
-static inline void setprimask(uint32_t primask)
-{
- __asm__ __volatile__
- (
- "\tmsr primask, %0\n"
- :
- : "r" (primask)
- : "memory");
+ if ((primask & 1) == 0)
+ {
+ setprimask(primask);
+ }
}
/* Get/set the basepri register */
+static inline uint8_t getbasepri(void) __attribute__((always_inline));
static inline uint8_t getbasepri(void)
{
uint32_t basepri;
+
__asm__ __volatile__
(
"\tmrs %0, basepri\n"
: "=r" (basepri)
:
: "memory");
+
return (uint8_t)basepri;
}
+static inline void setbasepri(uint32_t basepri) __attribute__((always_inline));
static inline void setbasepri(uint32_t basepri)
{
__asm__ __volatile__
@@ -232,6 +232,7 @@ static inline void setbasepri(uint32_t basepri)
/* Get/set IPSR */
+static inline uint32_t getipsr(void) __attribute__((always_inline));
static inline uint32_t getipsr(void)
{
uint32_t ipsr;
@@ -241,9 +242,11 @@ static inline uint32_t getipsr(void)
: "=r" (ipsr)
:
: "memory");
+
return ipsr;
}
+static inline void setipsr(uint32_t ipsr) __attribute__((always_inline));
static inline void setipsr(uint32_t ipsr)
{
__asm__ __volatile__
@@ -256,6 +259,7 @@ static inline void setipsr(uint32_t ipsr)
/* Get/set CONTROL */
+static inline uint32_t getcontrol(void) __attribute__((always_inline));
static inline uint32_t getcontrol(void)
{
uint32_t control;
@@ -265,9 +269,11 @@ static inline uint32_t getcontrol(void)
: "=r" (control)
:
: "memory");
+
return control;
}
+static inline void setcontrol(uint32_t control) __attribute__((always_inline));
static inline void setcontrol(uint32_t control)
{
__asm__ __volatile__
diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c
index 40b1a29a0..2d907bfca 100644
--- a/nuttx/arch/arm/src/stm32/stm32_spi.c
+++ b/nuttx/arch/arm/src/stm32/stm32_spi.c
@@ -49,7 +49,7 @@
* 3. Add a calls to up_spiinitialize() in your low level application
* initialization logic
* 4. The handle returned by up_spiinitialize() may then be used to bind the
- * SPI driver to higher level logic (e.g., calling
+ * SPI driver to higher level logic (e.g., calling
* mmcsd_spislotinitialize(), for example, will bind the SPI driver to
* the SPI MMC/SD driver).
*
@@ -881,7 +881,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
else
{
/* Less than fPCLK/128. This is as slow as we can go */
-
+
setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
actual = priv->spiclock >> 8;
}
@@ -941,22 +941,22 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
setbits = 0;
clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
break;
-
+
case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
setbits = SPI_CR1_CPHA;
clrbits = SPI_CR1_CPOL;
break;
-
+
case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
setbits = SPI_CR1_CPOL;
clrbits = SPI_CR1_CPHA;
break;
-
+
case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
clrbits = 0;
break;
-
+
default:
return;
}
@@ -1008,7 +1008,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
setbits = 0;
clrbits = SPI_CR1_DFF;
break;
-
+
case 16:
setbits = SPI_CR1_DFF;
clrbits = 0;
@@ -1111,7 +1111,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
}
/* Exchange one word */
-
+
word = spi_send(dev, word);
/* Is there a buffer to receive the return value? */
@@ -1120,7 +1120,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
{
*dest++ = word;
}
- }
+ }
}
else
{
@@ -1144,7 +1144,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
}
/* Exchange one word */
-
+
word = (uint8_t)spi_send(dev, (uint16_t)word);
/* Is there a buffer to receive the return value? */
@@ -1152,7 +1152,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
if (dest)
{
*dest++ = word;
- }
+ }
}
}
}
@@ -1331,7 +1331,7 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv)
priv->txdma = stm32_dmachannel(priv->txch);
DEBUGASSERT(priv->rxdma && priv->txdma);
#endif
-
+
/* Enable spi */
spi_modifycr1(priv, SPI_CR1_SPE, 0);
@@ -1360,7 +1360,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
FAR struct stm32_spidev_s *priv = NULL;
irqstate_t flags = irqsave();
-
+
#ifdef CONFIG_STM32_SPI1
if (port == 1)
{