diff --git a/arch/arm/src/stm32/stm32_gpio.c b/arch/arm/src/stm32/stm32_gpio.c index 2e323f906e1..66186f11673 100755 --- a/arch/arm/src/stm32/stm32_gpio.c +++ b/arch/arm/src/stm32/stm32_gpio.c @@ -122,136 +122,123 @@ int stm32_configgpio(uint32_t cfgset) /* Verify that this hardware supports the select GPIO port */ port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; - if (port < STM32_NGPIO_PORTS) + if (port >= STM32_NGPIO_PORTS) { - /* Get the port base address */ - - base = g_gpiobase[port]; - - /* Get the pin number and select the port configuration register for that pin */ - - pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; - if (pin < 8) - { - cr = base + STM32_GPIO_CRL_OFFSET; - pos = pin; - } - else - { - cr = base + STM32_GPIO_CRH_OFFSET; - pos = pin - 8; - } - - /* Input or output? */ - - input = ((cfgset & GPIO_INPUT) != 0); - - /* Decode the mode and configuration */ - - if (input) - { - /* Input.. force mode = INPUT */ - - modecnf = 0; - } - else - { - /* Output or alternate function */ - - modecnf = (cfgset & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT; - } - - modecnf |= ((cfgset & GPIO_CNF_MASK) >> GPIO_CNF_SHIFT) << 2; - - /* Set the port configuration register */ - - regval = getreg32(cr); - regval &= ~(GPIO_CR_MODECNF_MASK(pos)); - regval |= (modecnf << GPIO_CR_MODECNF_SHIFT(pos)); - putreg32(regval, cr); - - /* Set or reset the corresponding BRR/BSRR bit */ - - if (!input) - { - /* It is an output or an alternate function. We have to look at the CNF - * bits to know which. - */ - - unsigned int cnf = (cfgset & GPIO_CNF_MASK); - if (cnf == GPIO_CNF_OUTPP || cnf == GPIO_CNF_OUTOD) - { - - /* Its an output... set the pin to the correct initial state */ - - if ((cfgset & GPIO_OUTPUT_SET) != 0) - { - /* Use the BSRR register to set the output */ - - regaddr = base + STM32_GPIO_BSRR_OFFSET; - } - else - { - /* Use the BRR register to clear */ - - regaddr = base + STM32_GPIO_BRR_OFFSET; - } - } - else - { - /* Its an alternate function pin... we can return early */ - - return OK; - } - } - else - { - /* It is an input pin... Should it configured as an EXTI interrupt? */ - - if ((cfgset & GPIO_EXTI) != 0) - { - int shift; - - /* Yes.. Set the bits in the EXTI CR register */ - - regaddr = STM32_AFIO_EXTICR(pin); - regval = getreg32(regaddr); - shift = AFIO_EXTICR_EXTI_SHIFT(pin); - regval &= ~(AFIO_EXTICR_PORT_MASK << shift); - regval |= (((uint32_t)port) << shift); - putreg32(regval, regaddr); - } - - /* If it is pull-down or pull up, then we need to set the ODR - * appropriately for that function. - */ - - if ((cfgset & GPIO_CNF_MASK) == GPIO_CNF_INPULLUP) - { - /* Set the ODR bit (using BSRR) to one for the PULL-UP functionality */ - - regaddr = base + STM32_GPIO_BSRR_OFFSET; - } - else if ((cfgset & GPIO_CNF_MASK) == GPIO_CNF_INPULLDWN) - { - /* Clear the ODR bit (using BRR) to zero for the PULL-DOWN functionality */ - - regaddr = base + STM32_GPIO_BRR_OFFSET; - } - else - { - /* Neither... we can return early */ - - return OK; - } - } - - regval = getreg32(regaddr); - regval |= (1 << pin); - putreg32(regval, regaddr); - return OK; + return ERROR; } - return ERROR; + + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and select the port configuration register for that + * pin + */ + + pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + if (pin < 8) + { + cr = base + STM32_GPIO_CRL_OFFSET; + pos = pin; + } + else + { + cr = base + STM32_GPIO_CRH_OFFSET; + pos = pin - 8; + } + + /* Input or output? */ + + input = ((cfgset & GPIO_INPUT) != 0); + + /* Decode the mode and configuration */ + + if (input) + { + /* Input.. force mode = INPUT */ + + modecnf = 0; + } + else + { + /* Output or alternate function */ + + modecnf = (cfgset & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT; + } + + modecnf |= ((cfgset & GPIO_CNF_MASK) >> GPIO_CNF_SHIFT) << 2; + + /* Set the port configuration register */ + + regval = getreg32(cr); + regval &= ~(GPIO_CR_MODECNF_MASK(pos)); + regval |= (modecnf << GPIO_CR_MODECNF_SHIFT(pos)); + putreg32(regval, cr); + + /* Set or reset the corresponding BRR/BSRR bit */ + + if (!input) + { + /* It is an output or an alternate function. We have to look at the CNF + * bits to know which. + */ + + unsigned int cnf = (cfgset & GPIO_CNF_MASK); + if (cnf != GPIO_CNF_OUTPP && cnf != GPIO_CNF_OUTOD) + { + /* Its an alternate function pin... we can return early */ + + return OK; + } + } + else + { + /* It is an input pin... Should it configured as an EXTI interrupt? */ + + if ((cfgset & GPIO_EXTI) != 0) + { + int shift; + + /* Yes.. Set the bits in the EXTI CR register */ + + regaddr = STM32_AFIO_EXTICR(pin); + regval = getreg32(regaddr); + shift = AFIO_EXTICR_EXTI_SHIFT(pin); + regval &= ~(AFIO_EXTICR_PORT_MASK << shift); + regval |= (((uint32_t)port) << shift); + putreg32(regval, regaddr); + } + + if ((cfgset & GPIO_CNF_MASK) != GPIO_CNF_INPULLUD) + { + /* Neither... we can return early */ + + return OK; + } + } + + /* If it is an output... set the pin to the correct initial state. + * If it is pull-down or pull up, then we need to set the ODR + * appropriately for that function. + */ + + if ((cfgset & GPIO_OUTPUT_SET) != 0) + { + /* Use the BSRR register to set the output */ + + regaddr = base + STM32_GPIO_BSRR_OFFSET; + } + else + { + /* Use the BRR register to clear */ + + regaddr = base + STM32_GPIO_BRR_OFFSET; + } + + regval = getreg32(regaddr); + regval |= (1 << pin); + putreg32(regval, regaddr); + return OK; } /**************************************************************************** diff --git a/arch/arm/src/stm32/stm32_gpio.h b/arch/arm/src/stm32/stm32_gpio.h index 43377fce5bd..3061b6b8171 100644 --- a/arch/arm/src/stm32/stm32_gpio.h +++ b/arch/arm/src/stm32/stm32_gpio.h @@ -199,8 +199,8 @@ #define GPIO_CR_CNF_OUTPP (0) /* 00: General purpose output push-pull */ #define GPIO_CR_CNF_OUTOD (1) /* 01: General purpose output Open-drain */ -#define GPIO_CR_CNF_ALTPP (3) /* 10: Alternate function output Push-pull */ -#define GPIO_CR_CNF_ALTOD (6) /* 11: Alternate function output Open-drain */ +#define GPIO_CR_CNF_ALTPP (2) /* 10: Alternate function output Push-pull */ +#define GPIO_CR_CNF_ALTOD (3) /* 11: Alternate function output Open-drain */ #define GPIO_CR_MODE_INRST (0) /* 00: Input mode (reset state) */ #define GPIO_CR_MODE_OUT10MHz (1) /* 01: Output mode, max speed 10 MHz */ diff --git a/arch/arm/src/stm32/stm32_internal.h b/arch/arm/src/stm32/stm32_internal.h index f5094d50a85..1af627a710a 100755 --- a/arch/arm/src/stm32/stm32_internal.h +++ b/arch/arm/src/stm32/stm32_internal.h @@ -80,6 +80,16 @@ #define GPIO_OUTPUT (0) /* 0=Output or alternate function */ #define GPIO_ALT (0) +/* If the pin is a GPIO digital output, then this identifies the initial output value. + * If the pin is an input, this bit is overloaded to provide the qualifier to\ + * distinquish input pull-up and -down: + * + * .... .... V... .... + */ + +#define GPIO_OUTPUT_SET (1 << 7) /* Bit 7: If output, inital value of output */ +#define GPIO_OUTPUT_CLEAR (0) + /* These bits set the primary function of the pin: * .FF. .... .... .... */ @@ -89,8 +99,9 @@ # define GPIO_CNF_ANALOGIN (0 << GPIO_CNF_SHIFT) /* Analog input */ # define GPIO_CNF_INFLOAT (1 << GPIO_CNF_SHIFT) /* Input floating */ -# define GPIO_CNF_INPULLUP (2 << GPIO_CNF_SHIFT) /* Input pull-up */ -# define GPIO_CNF_INPULLDWN (3 << GPIO_CNF_SHIFT) /* Input pull-down */ +# define GPIO_CNF_INPULLUD (2 << GPIO_CNF_SHIFT) /* Input pull-up/down general bit, since up is composed of two parts */ +# define GPIO_CNF_INPULLDWN (2 << GPIO_CNF_SHIFT) /* Input pull-down */ +# define GPIO_CNF_INPULLUP ((2 << GPIO_CNF_SHIFT) | GPIO_OUTPUT_SET) /* Input pull-up */ # define GPIO_CNF_OUTPP (0 << GPIO_CNF_SHIFT) /* Output push-pull */ # define GPIO_CNF_OUTOD (1 << GPIO_CNF_SHIFT) /* Output open-drain */ @@ -114,13 +125,6 @@ #define GPIO_EXTI (1 << 10) /* Bit 10: Configure as EXTI interrupt */ -/* If the pin is an GPIO digital output, then this identifies the initial output value: - * .... .... V... .... - */ - -#define GPIO_OUTPUT_SET (1 << 7) /* Bit 7: If output, inital value of output */ -#define GPIO_OUTPUT_CLEAR (0) - /* This identifies the GPIO port: * .... .... .PPP .... */