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
This commit is contained in:
patacongo 2012-09-15 16:02:58 +00:00
parent cfa24e37d6
commit 4070ce05fe
6 changed files with 112 additions and 76 deletions

View File

@ -74,7 +74,7 @@ Installing and Building the Unit Tests
writing *ONLY* the sim/nsh2 and stm321-e-eval configurations have C++ support
pre-enabled).
c) Enable Debug Options
d) Enable Debug Options
If you are running on a simulated target, then you might also want to
enable debug symbols:
@ -84,12 +84,12 @@ Installing and Building the Unit Tests
Then you can run the simulation using GDB or DDD which is a very powerful
debugging environment!
d) Special configuration requirements for the nxwm unit test:
e) Special configuration requirements for the nxwm unit test:
CONFIG_NXCONSOLE=y
CONFIG_NX_MULTIUSER=y
e) Other nuttx/.config changes -- NSH configurations only.
f) Other nuttx/.config changes -- NSH configurations only.
If the configuration that you are using supports NSH and NSH built-in tasks
then all is well. If it is an NSH configuration, then you will have to define
@ -101,7 +101,26 @@ Installing and Building the Unit Tests
to change anything further in the nuttx/.config file if you are using either
of these configurations.
f) Other apps/.config changes -- NON-NSH configurations only.
g) Other apps/.config changes -- NON-NSH configurations only.
Entry Point. You will need to set the entry point in the .config file.
For NSH configurations, the entry point will always be "nsh_main" and you
will see that setting like:
CONFIG_USER_ENTRYPOINT="nsh_main"
If you are not using in NSH, then each unit test has a unique entry point.
That entry point is the name of the unit test directory in all lower case
plus the suffix "_main". So, for example, the correct entry for the
UnitTests/CButton would be:
CONFIG_USER_ENTRYPOINT="cbutton_main"
And the correct entry point for UnitTests/nxwm would be:
CONFIG_USER_ENTRYPOINT="nxwm_main"
etc.
For non-NSH configurations (such as the sim/touchscreen) you will have to
remove the CONFIGURED_APPS seting that contains the user_start function so
@ -306,6 +325,9 @@ Example
Do nothing... sim/nsh2 already has C++ support enabled.
Since this is an NSH configuration, the entry point does not need to be
changed.
3. Install the CButton C++ application (for example)
Where: <nxwidgets-directory>/tool

View File

@ -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/)
^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -129,61 +129,9 @@ struct xcptcontext
#ifndef __ASSEMBLY__
/* Disable IRQs */
static inline void irqdisable(void)
{
__asm__ __volatile__ ("\tcpsid i\n");
}
/* Save the current primask state & disable IRQs */
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)
{
__asm__ __volatile__ ("\tcpsie i\n");
}
/* Restore saved primask state */
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));
static inline uint8_t getprimask(void)
{
uint32_t primask;
@ -193,9 +141,44 @@ static inline uint8_t getprimask(void)
: "=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");
}
/* 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)
{
__asm__ __volatile__
@ -206,20 +189,37 @@ 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));
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__

View File

@ -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)
{

View File

@ -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

View File

@ -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) */