diff --git a/arch/arm/include/max326xx/chip.h b/arch/arm/include/max326xx/chip.h index 09036769a5f..668df0ec02b 100644 --- a/arch/arm/include/max326xx/chip.h +++ b/arch/arm/include/max326xx/chip.h @@ -200,6 +200,55 @@ #define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ #define NVIC_SYSH_PRIORITY_STEP 0x20 /* Eight priority levels in steps 0x20 */ +/* If CONFIG_ARMV7M_USEBASEPRI is selected, then interrupts will be disabled + * by setting the BASEPRI register to NVIC_SYSH_DISABLE_PRIORITY so that most + * interrupts will not have execution priority. SVCall must have execution + * priority in all cases. + * + * In the normal cases, interrupts are not nest-able and all interrupts run + * at an execution priority between NVIC_SYSH_PRIORITY_MIN and + * NVIC_SYSH_PRIORITY_MAX (with NVIC_SYSH_PRIORITY_MAX reserved for SVCall). + * + * If, in addition, CONFIG_ARCH_HIPRI_INTERRUPT is defined, then special + * high priority interrupts are supported. These are not "nested" in the + * normal sense of the word. These high priority interrupts can interrupt + * normal processing but execute outside of OS (although they can "get back + * into the game" via a PendSV interrupt). + * + * In the normal course of things, interrupts must occasionally be disabled + * using the up_irq_save() inline function to prevent contention in use of + * resources that may be shared between interrupt level and non-interrupt + * level logic. Now the question arises, if CONFIG_ARCH_HIPRI_INTERRUPT, + * do we disable all interrupts (except SVCall), or do we only disable the + * "normal" interrupts. Since the high priority interrupts cannot interact + * with the OS, you may want to permit the high priority interrupts even if + * interrupts are disabled. The setting CONFIG_ARCH_INT_DISABLEALL can be + * used to select either behavior: + * + * ----------------------------+--------------+---------------------------- + * CONFIG_ARCH_HIPRI_INTERRUPT | NO | YES + * ----------------------------+--------------+--------------+------------- + * CONFIG_ARCH_INT_DISABLEALL | N/A | YES | NO + * ----------------------------+--------------+--------------+------------- + * | | | SVCall + * | SVCall | SVCall | HIGH + * Disable here and below --------> MAXNORMAL ---> HIGH --------> MAXNORMAL + * | | MAXNORMAL | + * ----------------------------+--------------+--------------+------------- + */ + +#if defined(CONFIG_ARCH_HIPRI_INTERRUPT) && defined(CONFIG_ARCH_INT_DISABLEALL) +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + 2*NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_HIGH_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#else +# define NVIC_SYSH_MAXNORMAL_PRIORITY (NVIC_SYSH_PRIORITY_MAX + NVIC_SYSH_PRIORITY_STEP) +# define NVIC_SYSH_HIGH_PRIORITY NVIC_SYSH_PRIORITY_MAX +# define NVIC_SYSH_DISABLE_PRIORITY NVIC_SYSH_MAXNORMAL_PRIORITY +# define NVIC_SYSH_SVCALL_PRIORITY NVIC_SYSH_PRIORITY_MAX +#endif + /************************************************************************************ * Public Types ************************************************************************************/ diff --git a/arch/arm/src/max326xx/common/max326_idle.c b/arch/arm/src/max326xx/common/max326_idle.c index af4c103c893..d57ce64fbdd 100644 --- a/arch/arm/src/max326xx/common/max326_idle.c +++ b/arch/arm/src/max326xx/common/max326_idle.c @@ -176,10 +176,12 @@ void up_idle(void) up_idlepm(); +#if 0 /* REVISIT: "wfi" causes instability */ /* Sleep until an interrupt occurs to save power */ BEGIN_IDLE(); asm("WFI"); END_IDLE(); #endif +#endif } diff --git a/arch/arm/src/max326xx/common/max326_irq.c b/arch/arm/src/max326xx/common/max326_irq.c index e98637d7bce..fb2c9153b64 100644 --- a/arch/arm/src/max326xx/common/max326_irq.c +++ b/arch/arm/src/max326xx/common/max326_irq.c @@ -312,9 +312,8 @@ void up_irqinitialize(void) /* Make sure that we are using the correct vector table. The default * vector address is 0x0000:0000 but if we are executing code that is - * positioned in SRAM or in external FLASH, then we may need to reset - * the interrupt vector so that it refers to the table in SRAM or in - * external FLASH. + * positioned in SRAM, then we need to reset the interrupt vector so + * that it refers to the table in SRAM. */ putreg32((uint32_t)_vectors, NVIC_VECTAB); @@ -385,7 +384,7 @@ void up_irqinitialize(void) up_enable_irq(MAX326_IRQ_MEMFAULT); #endif - /* Attach all other processor exceptions (except reset and sys tick) */ + /* Attach all other processor exceptions (except reset and SysTick) */ #ifdef CONFIG_DEBUG_FEATURES irq_attach(MAX326_IRQ_NMI, max326_nmi, NULL); diff --git a/arch/arm/src/max326xx/max32660/max32660_gpio.c b/arch/arm/src/max326xx/max32660/max32660_gpio.c index 24e4a7ae1a3..63bc6203cba 100644 --- a/arch/arm/src/max326xx/max32660/max32660_gpio.c +++ b/arch/arm/src/max326xx/max32660/max32660_gpio.c @@ -244,6 +244,7 @@ void max326_default(uint32_t pinmask) int max326_gpio_config(max326_pinset_t pinset) { irqstate_t flags; + max326_pinset_t subset; unsigned int pin; uint32_t pinmask; uint32_t regval; @@ -284,20 +285,33 @@ int max326_gpio_config(max326_pinset_t pinset) /* Enable pull up and pull down */ - if ((pinset & GPIO_MODE_MASK) != GPIO_FLOAT) + subset = pinset & GPIO_MODE_MASK; + if (subset != GPIO_FLOAT) { - /* Enable pull-down resistor */ + bool upcap; /* True: GPIO_PULLUP supported */ - if ((PULLUP_SET & pinmask) != 0 || - (pinset & GPIO_MODE_MASK) == GPIO_PULLDOWN) + /* Enable pull-down resistor. All pins support pull down resisters, + * but it works differently: + * + * - For pins that support only pull-down, the PULLEN register + * selects the pull down resister. + * - For pins that support both pull-up and pull down, the PULLEN + * enables the feature but the PULLSEL registers selects the pull + * up or down direction. + */ + + upcap = ((PULLUP_SET & pinmask) != 0); + + if (upcap || subset == GPIO_PULLDOWN) { regval = getreg32(MAX326_GPIO0_PULLEN); regval |= pinmask; putreg32(regval, MAX326_GPIO0_PULLEN); } - if ((PULLUP_SET & pinmask) != 0 && - (pinset & GPIO_MODE_MASK) == GPIO_PULLUP) + /* Enable pull-ups (only certain pins support pull up resistors) */ + + if (upcap && subset == GPIO_PULLUP) { /* Enable pull-up resistor */ @@ -309,12 +323,12 @@ int max326_gpio_config(max326_pinset_t pinset) /* Set drive strength */ + subset = pinset & GPIO_DRIVE_MASK; if ((DS1_SET & pinmask) == 0) { /* Only two levels of drive strength */ - if ((pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_MEDHI || - (pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_HI) + if (subset == GPIO_DRIVE_MEDHI || subset == GPIO_DRIVE_HI) { regval = getreg32(MAX326_GPIO0_DS0SEL); regval |= pinmask; @@ -331,16 +345,14 @@ int max326_gpio_config(max326_pinset_t pinset) * HI DS0=1 DS1=1 */ - if ((pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_MEDLO || - (pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_HI) + if (subset == GPIO_DRIVE_MEDLO || subset == GPIO_DRIVE_HI) { regval = getreg32(MAX326_GPIO0_DS0SEL); regval |= pinmask; putreg32(regval, MAX326_GPIO0_DS0SEL); } - if ((pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_MEDHI || - (pinset & GPIO_DRIVE_MASK) != GPIO_DRIVE_HI) + if (subset == GPIO_DRIVE_MEDHI || subset == GPIO_DRIVE_HI) { regval = getreg32(MAX326_GPIO0_DS1SEL); regval |= pinmask; @@ -363,6 +375,7 @@ int max326_gpio_config(max326_pinset_t pinset) regval = getreg32(MAX326_GPIO0_OUTEN); /* Enable output drivers */ regval |= pinmask; putreg32(regval, MAX326_GPIO0_OUTEN); + break; case GPIO_ALT1: max326_altfunc(pinmask, AF_FUNC1); @@ -427,14 +440,14 @@ void max326_gpio_write(max326_pinset_t pinset, bool value) /* Modification of registers must be atomic */ flags = spin_lock_irqsave(); - regval = getreg32(MAX326_GPIO0_OUT); /* Set output high */ + regval = getreg32(MAX326_GPIO0_OUT); if (value) { - regval |= (1 << pin); + regval |= (1 << pin); /* Set output high */ } else { - regval &= ~(1 << pin); + regval &= ~(1 << pin); /* Set output low */ } putreg32(regval, MAX326_GPIO0_OUT); @@ -494,33 +507,33 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); * Alternate Function 3 1 1 */ - regval = getre32(MAX326_GPIO0_AF0SEL); + regval = getreg32(MAX326_GPIO0_AF0SEL); afmode = (regval & pinmask) != 0 ? 1 : 0; - regval = getre32(MAX326_GPIO0_AF1SEL); + regval = getreg32(MAX326_GPIO0_AF1SEL); afmode |= (regval & pinmask) != 0 ? 2 : 0; gpioinfo(" Mode: %d\n", g_afmode[afmode]); - regval = getre32(MAX326_GPIO0_OUTEN); + regval = getreg32(MAX326_GPIO0_OUTEN); gpioinfo(" Output Enable: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); - regval = getre32(MAX326_GPIO0_OUT); + regval = getreg32(MAX326_GPIO0_OUT); gpioinfo(" Output Value: %s\n", (regval & pinmask) != 0 ? "High" : "Low"); - regval = getre32(MAX326_GPIO0_IN); + regval = getreg32(MAX326_GPIO0_IN); gpioinfo(" Input Value: %s\n", (regval & pinmask) != 0 ? "High" : "Low"); - regval = getre32(MAX326_GPIO0_INTMODE); + regval = getreg32(MAX326_GPIO0_INTMODE); edge = (regval & pinmask) != 0 gpioinfo(" Intr Mode: %s\n", edge ? "Yes" : "No"); - regval = getre32(MAX326_GPIO0_INTPOL); + regval = getreg32(MAX326_GPIO0_INTPOL); if (edge) { - uint32_t dualedge = getre32(MAX326_GPIO0_INTDUALEDGE); + uint32_t dualedge = getreg32(MAX326_GPIO0_INTDUALEDGE); if ((dualedge & pinmask) != 0) { gpioinfo(" Intr Edge: Both edges\n"); @@ -537,20 +550,20 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); (regval & pinmask) != 0 ? "High" : "Low"); } - regval = getre32(MAX326_GPIO0_INTEN); + regval = getreg32(MAX326_GPIO0_INTEN); gpioinfo(" Intr Enabled: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); - regval = getre32(MAX326_GPIO0_INTFL); + regval = getreg32(MAX326_GPIO0_INTFL); gpioinfo(" Intr Pending: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); - regval = getre32(MAX326_GPIO0_WAKEEN); + regval = getreg32(MAX326_GPIO0_WAKEEN); gpioinfo(" Wakeup Enabled: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); pullmode = 0 - regval = getre32(MAX326_GPIO0_PULLEN); + regval = getreg32(MAX326_GPIO0_PULLEN); if ((regval & pinmask) != 0) { if ((PULLUP_SET & pinmask) == 0) @@ -559,7 +572,7 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); } else { - regval = getre32(MAX326_GPIO0_PULLSEL); + regval = getreg32(MAX326_GPIO0_PULLSEL); pullmode = (regval & pinmask) != 0 ? 2 : 1; } } @@ -567,7 +580,7 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); gpioinfo(" Resister Mode: %s\n", g_pullmode[pullmode]); dsmode = (PULLUP_SET & pinmask) == 0 ? 1 : 0; - regval = getre32(MAX326_GPIO0_DS0SEL); + regval = getreg32(MAX326_GPIO0_DS0SEL); if ((regval & pinmask) != 0) { if (PULLUP_SET & pinmask) == 0) @@ -576,13 +589,13 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); } else { - regval = getre32(MAX326_GPIO0_DS1SEL); + regval = getreg32(MAX326_GPIO0_DS1SEL); dsmode = (regval & pinmask) != 0 ? 3 : 1; } } else if (PULLUP_SET & pinmask) != 0) { - regval = getre32(MAX326_GPIO0_DS1SEL); + regval = getreg32(MAX326_GPIO0_DS1SEL); if (regval & pinmask) != 0) { dsmode = 2; @@ -591,11 +604,11 @@ int max326_gpio_dump(max326_pinset_t pinset, const char *msg); gpioinfo(" Drive Strength: %s\n", g_dsmode[dsmode]); - regval = getre32(MAX326_GPIO0_INHYSEN); + regval = getreg32(MAX326_GPIO0_INHYSEN); gpioinfo(" Hysteresis: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); - regval = getre32(MAX326_GPIO0_SRSEL); + regval = getreg32(MAX326_GPIO0_SRSEL); gpioinfo(" Slew Enabled: %s\n", (regval & pinmask) != 0 ? "Yes" : "No"); } diff --git a/configs/max32660-evsys/README.txt b/configs/max32660-evsys/README.txt index a00eef51ab4..60e12574a35 100644 --- a/configs/max32660-evsys/README.txt +++ b/configs/max32660-evsys/README.txt @@ -45,7 +45,7 @@ Status up the board on bad configurations. The rest of the bring-up will use this SRAM configuration. - Some successby the end of the day: + Some success the end of the day: ACFH @@ -57,6 +57,10 @@ Status issues. I comes up with 'NuttShell' then stops. I hit enter and " (NSH) NuttX" comes out etc. So it looks like Rx input is driving the Tx output. + 2018-11-28: Found that the WFI instruction in the IDLE loop was causing + instability. System ran OK until it was in IDLE then it became + unstable. Commenting out the WIF restores stability. Also fixed the + on-board LED which now currently reflects the state. Serial Console ============== @@ -150,7 +154,7 @@ Debugging from FLASH: $ arm-none-eabi-gdb (gdb) target remote localhost:3333 (gdb) mon reset - (gdb) mon reg pc 0x11c # Set PC to __start entry point + (gdb) mon reg pc __start # Set PC to __start entry point (gdb) file nuttx (gdb) b os_start (gdb) c @@ -159,7 +163,17 @@ Debugging from FLASH: Debugging from SRAM: - Same except that the __start entry point is 0x2000011c, not 0x11c. + Same except (1) that the __start entry point is 0x2000011c, not 0x11c, and + the code needs to be reloaded into SRAM each time: + + (gdb) target remote localhost:3333 + (gdb) mon reset + (gdb) mon halt + (gdb) load nuttx # Re-load code into SRAM + (gdb) mon reg pc __start # Set PC to __start entry point + (gdb) file nuttx + (gdb) b os_start + (gdb) c Recovering from bad code in FLASH: diff --git a/configs/max32660-evsys/nsh/defconfig b/configs/max32660-evsys/nsh/defconfig index a10000d48aa..c2562e16769 100644 --- a/configs/max32660-evsys/nsh/defconfig +++ b/configs/max32660-evsys/nsh/defconfig @@ -9,6 +9,7 @@ CONFIG_ARCH_INTERRUPTSTACK=2048 CONFIG_ARCH_IRQBUTTONS=y CONFIG_ARCH_STACKDUMP=y CONFIG_ARMV7M_LAZYFPU=y +CONFIG_ARMV7M_USEBASEPRI=y CONFIG_BOARD_LOOPSPERMSEC=8192 CONFIG_BUILTIN=y CONFIG_DISABLE_POLL=y diff --git a/configs/max32660-evsys/src/max32660-evsys.h b/configs/max32660-evsys/src/max32660-evsys.h index b4738315f12..42e2e907efb 100644 --- a/configs/max32660-evsys/src/max32660-evsys.h +++ b/configs/max32660-evsys/src/max32660-evsys.h @@ -46,13 +46,17 @@ * Pre-processor Definitions ****************************************************************************/ -/* A single red LED is available driven by GPIO P0.13. */ +/* A single red LED is available driven by GPIO P0.13. + * High illuminates, initial output is Low. + */ -#define GPIO_LED (GPIO_OUTPUT | GPIO_PORT0 | GPIO_PIN13) +#define GPIO_LED (GPIO_OUTPUT | GPIO_VALUE_ZERO | GPIO_PORT0 | GPIO_PIN13) -/* An single button is available on GPIO P0.12 for use by software. */ +/* An single button is available on GPIO P0.12 for use by software. + * Interrupts are available on both edges. + */ -#define GPIO_BUTTON (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN12) +#define GPIO_BUTTON (GPIO_INTBOTH | GPIO_PORT0 | GPIO_PIN12) #define BUTTON_IRQ MAX326_IRQ_P0_12 /**************************************************************************** diff --git a/configs/max32660-evsys/src/max326_autoleds.c b/configs/max32660-evsys/src/max326_autoleds.c index 0b1b1254fcf..c63708de73c 100644 --- a/configs/max32660-evsys/src/max326_autoleds.c +++ b/configs/max32660-evsys/src/max326_autoleds.c @@ -101,7 +101,7 @@ void board_autoled_on(int led) { if (led == 1 || led == 3) { - max326_gpio_write(GPIO_LED, false); /* Low illuminates */ + max326_gpio_write(GPIO_LED, true); /* High illuminates */ } } @@ -113,7 +113,7 @@ void board_autoled_off(int led) { if (led == 3) { - max326_gpio_write(GPIO_LED, true); /* High extinguishes */ + max326_gpio_write(GPIO_LED, false); /* Low extinguishes */ } }