From 4070ce05feae09331156c64b882bead55831f5e3 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 15 Sep 2012 16:02:58 +0000 Subject: 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 --- nuttx/TODO | 9 ++- nuttx/arch/arm/include/armv7-m/irq.h | 86 ++++++++++++++------------ nuttx/arch/arm/src/stm32/stm32_spi.c | 26 ++++---- nuttx/configs/fire-stm32v2/src/fire-internal.h | 7 ++- nuttx/drivers/net/enc28j60.c | 4 +- 5 files changed, 73 insertions(+), 59 deletions(-) (limited to 'nuttx') diff --git a/nuttx/TODO b/nuttx/TODO index 543d15f70..ae42d6c1c 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -6,7 +6,7 @@ standards, things that could be improved, and ideas for enhancements. nuttx/ - (5) Task/Scheduler (sched/) + (6) Task/Scheduler (sched/) (1) On-demand paging (sched/) (1) Memory Managment (mm/) (2) Signals (sched/, arch/) @@ -110,6 +110,13 @@ o Task/Scheduler (sched/) Status: Open Priority: Low + Title: posix_spawn() + Description: This would be a good interface to add to NuttX. It is really + just a re-packaging of the existing, non-standard NuttX exec() + function. + Status: Open + Priority: Medium low. + o On-demand paging (sched/) ^^^^^^^^^^^^^^^^^^^^^^^^^ 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) { diff --git a/nuttx/configs/fire-stm32v2/src/fire-internal.h b/nuttx/configs/fire-stm32v2/src/fire-internal.h index 801fb127e..0260d8e33 100644 --- a/nuttx/configs/fire-stm32v2/src/fire-internal.h +++ b/nuttx/configs/fire-stm32v2/src/fire-internal.h @@ -214,15 +214,16 @@ # warning "TFT LCD and ENCJ2860 shared PE1" #endif -/* CS and Reset are active low. Initial states are not selected and not in - * reset (driver does a soft reset). +/* CS and Reset are active low. Initial states are not selected and in + * reset. The ENC28J60 is taken out of reset when the driver is + * initialized (thedriver does a soft reset too). */ #ifdef CONFIG_ENC28J60 # define GPIO_ENC28J60_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) # define GPIO_ENC28J60_RESET (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ - GPIO_OUTPUT_SET|GPIO_PORTE|GPIO_PIN1) + GPIO_OUTPUT_CLEAR|GPIO_PORTE|GPIO_PIN1) # define GPIO_ENC28J60_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|\ GPIO_EXTI|GPIO_PORTE|GPIO_PIN5) #endif diff --git a/nuttx/drivers/net/enc28j60.c b/nuttx/drivers/net/enc28j60.c index 47a84ec9f..df4353b9d 100644 --- a/nuttx/drivers/net/enc28j60.c +++ b/nuttx/drivers/net/enc28j60.c @@ -171,7 +171,7 @@ enum enc_state_e { - ENCSTATE_UNIT = 0, /* The interface is in an unknown state */ + ENCSTATE_UNINIT = 0, /* The interface is in an uninitialized state */ ENCSTATE_DOWN, /* The interface is down */ ENCSTATE_UP /* The interface is up */ }; @@ -2265,7 +2265,7 @@ int enc_initialize(FAR struct spi_dev_s *spi, * bringing the interface up. */ - priv->ifstate = ENCSTATE_UNIT; + priv->ifstate = ENCSTATE_UNINIT; /* Attach the interrupt to the driver (but don't enable it yet) */ -- cgit v1.2.3