Browse Source

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
sbg
patacongo 13 years ago
parent
commit
4070ce05fe
  1. 30
      NxWidgets/UnitTests/README.txt
  2. 9
      nuttx/TODO
  3. 86
      nuttx/arch/arm/include/armv7-m/irq.h
  4. 7
      nuttx/configs/fire-stm32v2/src/fire-internal.h
  5. 4
      nuttx/drivers/net/enc28j60.c

30
NxWidgets/UnitTests/README.txt

@ -74,7 +74,7 @@ Installing and Building the Unit Tests
writing *ONLY* the sim/nsh2 and stm321-e-eval configurations have C++ support writing *ONLY* the sim/nsh2 and stm321-e-eval configurations have C++ support
pre-enabled). pre-enabled).
c) Enable Debug Options d) Enable Debug Options
If you are running on a simulated target, then you might also want to If you are running on a simulated target, then you might also want to
enable debug symbols: 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 Then you can run the simulation using GDB or DDD which is a very powerful
debugging environment! debugging environment!
d) Special configuration requirements for the nxwm unit test: e) Special configuration requirements for the nxwm unit test:
CONFIG_NXCONSOLE=y CONFIG_NXCONSOLE=y
CONFIG_NX_MULTIUSER=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 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 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 to change anything further in the nuttx/.config file if you are using either
of these configurations. 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 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 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. 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) 3. Install the CButton C++ application (for example)
Where: <nxwidgets-directory>/tool Where: <nxwidgets-directory>/tool

9
nuttx/TODO

@ -6,7 +6,7 @@ standards, things that could be improved, and ideas for enhancements.
nuttx/ nuttx/
(5) Task/Scheduler (sched/) (6) Task/Scheduler (sched/)
(1) On-demand paging (sched/) (1) On-demand paging (sched/)
(1) Memory Managment (mm/) (1) Memory Managment (mm/)
(2) Signals (sched/, arch/) (2) Signals (sched/, arch/)
@ -110,6 +110,13 @@ o Task/Scheduler (sched/)
Status: Open Status: Open
Priority: Low 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/) o On-demand paging (sched/)
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^

86
nuttx/arch/arm/include/armv7-m/irq.h

@ -129,8 +129,25 @@ struct xcptcontext
#ifndef __ASSEMBLY__ #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 */ /* Disable IRQs */
static inline void irqdisable(void) __attribute__((always_inline));
static inline void irqdisable(void) static inline void irqdisable(void)
{ {
__asm__ __volatile__ ("\tcpsid i\n"); __asm__ __volatile__ ("\tcpsid i\n");
@ -138,26 +155,22 @@ static inline void irqdisable(void)
/* Save the current primask state & disable IRQs */ /* Save the current primask state & disable IRQs */
static inline irqstate_t irqsave(void) __attribute__((always_inline));
static inline irqstate_t irqsave(void) 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 uint8_t primask = getprimask();
* bit 0 of the primask register to disable interrupts
*/
__asm__ __volatile__ /* Then set bit 0 of the primask register to disable interrupts */
(
"\tmrs %0, primask\n" irqdisable();
"\tcpsid i\n"
: "=r" (primask)
:
: "memory");
return primask; return primask;
} }
/* Enable IRQs */ /* Enable IRQs */
static inline void irqenable(void) __attribute__((always_inline));
static inline void irqenable(void) static inline void irqenable(void)
{ {
__asm__ __volatile__ ("\tcpsie i\n"); __asm__ __volatile__ ("\tcpsie i\n");
@ -165,61 +178,48 @@ static inline void irqenable(void)
/* Restore saved primask state */ /* 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__ __asm__ __volatile__
( (
"\ttst %0, #1\n" "\tmsr primask, %0\n"
"\tbne 1f\n"
"\tcpsie i\n"
"1:\n"
: :
: "r" (primask) : "r" (primask)
: "memory"); : "memory");
} }
/* Get/set the primask register */ static inline void irqrestore(irqstate_t primask) __attribute__((always_inline));
static inline void irqrestore(irqstate_t primask)
static inline uint8_t getprimask(void)
{ {
uint32_t primask; /* If bit 0 of the primask is 0, then we need to restore
__asm__ __volatile__ * interrupts.
( */
"\tmrs %0, primask\n"
: "=r" (primask)
:
: "memory");
return (uint8_t)primask;
}
static inline void setprimask(uint32_t primask) if ((primask & 1) == 0)
{ {
__asm__ __volatile__ setprimask(primask);
( }
"\tmsr primask, %0\n"
:
: "r" (primask)
: "memory");
} }
/* Get/set the basepri register */ /* Get/set the basepri register */
static inline uint8_t getbasepri(void) __attribute__((always_inline));
static inline uint8_t getbasepri(void) static inline uint8_t getbasepri(void)
{ {
uint32_t basepri; uint32_t basepri;
__asm__ __volatile__ __asm__ __volatile__
( (
"\tmrs %0, basepri\n" "\tmrs %0, basepri\n"
: "=r" (basepri) : "=r" (basepri)
: :
: "memory"); : "memory");
return (uint8_t)basepri; return (uint8_t)basepri;
} }
static inline void setbasepri(uint32_t basepri) __attribute__((always_inline));
static inline void setbasepri(uint32_t basepri) static inline void setbasepri(uint32_t basepri)
{ {
__asm__ __volatile__ __asm__ __volatile__
@ -232,6 +232,7 @@ static inline void setbasepri(uint32_t basepri)
/* Get/set IPSR */ /* Get/set IPSR */
static inline uint32_t getipsr(void) __attribute__((always_inline));
static inline uint32_t getipsr(void) static inline uint32_t getipsr(void)
{ {
uint32_t ipsr; uint32_t ipsr;
@ -241,9 +242,11 @@ static inline uint32_t getipsr(void)
: "=r" (ipsr) : "=r" (ipsr)
: :
: "memory"); : "memory");
return ipsr; return ipsr;
} }
static inline void setipsr(uint32_t ipsr) __attribute__((always_inline));
static inline void setipsr(uint32_t ipsr) static inline void setipsr(uint32_t ipsr)
{ {
__asm__ __volatile__ __asm__ __volatile__
@ -256,6 +259,7 @@ static inline void setipsr(uint32_t ipsr)
/* Get/set CONTROL */ /* Get/set CONTROL */
static inline uint32_t getcontrol(void) __attribute__((always_inline));
static inline uint32_t getcontrol(void) static inline uint32_t getcontrol(void)
{ {
uint32_t control; uint32_t control;
@ -265,9 +269,11 @@ static inline uint32_t getcontrol(void)
: "=r" (control) : "=r" (control)
: :
: "memory"); : "memory");
return control; return control;
} }
static inline void setcontrol(uint32_t control) __attribute__((always_inline));
static inline void setcontrol(uint32_t control) static inline void setcontrol(uint32_t control)
{ {
__asm__ __volatile__ __asm__ __volatile__

7
nuttx/configs/fire-stm32v2/src/fire-internal.h

@ -214,15 +214,16 @@
# warning "TFT LCD and ENCJ2860 shared PE1" # warning "TFT LCD and ENCJ2860 shared PE1"
#endif #endif
/* CS and Reset are active low. Initial states are not selected and not in /* CS and Reset are active low. Initial states are not selected and in
* reset (driver does a soft reset). * reset. The ENC28J60 is taken out of reset when the driver is
* initialized (thedriver does a soft reset too).
*/ */
#ifdef CONFIG_ENC28J60 #ifdef CONFIG_ENC28J60
# define GPIO_ENC28J60_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ # define GPIO_ENC28J60_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\
GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4) GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN4)
# define GPIO_ENC28J60_RESET (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ # 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|\ # define GPIO_ENC28J60_INTR (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|\
GPIO_EXTI|GPIO_PORTE|GPIO_PIN5) GPIO_EXTI|GPIO_PORTE|GPIO_PIN5)
#endif #endif

4
nuttx/drivers/net/enc28j60.c

@ -171,7 +171,7 @@
enum enc_state_e 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_DOWN, /* The interface is down */
ENCSTATE_UP /* The interface is up */ ENCSTATE_UP /* The interface is up */
}; };
@ -2265,7 +2265,7 @@ int enc_initialize(FAR struct spi_dev_s *spi,
* bringing the interface up. * bringing the interface up.
*/ */
priv->ifstate = ENCSTATE_UNIT; priv->ifstate = ENCSTATE_UNINIT;
/* Attach the interrupt to the driver (but don't enable it yet) */ /* Attach the interrupt to the driver (but don't enable it yet) */

Loading…
Cancel
Save