Finish port of GPIO driver for STM3240
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4122 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
67eb344218
commit
5bcaa4dfb8
@ -53,20 +53,26 @@
|
||||
|
||||
#define STM32_SYSCFG_MEMRMP_OFFSET 0x0000 /* SYSCFG memory remap register */
|
||||
#define STM32_SYSCFG_PMC_OFFSET 0x0004 /* SYSCFG peripheral mode configuration register */
|
||||
|
||||
#define STM32_SYSCFG_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */
|
||||
#define STM32_SYSCFG_EXTICR1_OFFSET 0x0008 /* SYSCFG external interrupt configuration register 1 */
|
||||
#define STM32_SYSCFG_EXTICR2_OFFSET 0x000c /* SYSCFG external interrupt configuration register 2 */
|
||||
#define STM32_SYSCFG_EXTICR3_OFFSET 0x0010 /* SYSCFG external interrupt configuration register 3 */
|
||||
#define STM32_SYSCFG_EXTICR4_OFFSET 0x0014 /* SYSCFG external interrupt configuration register 4 */
|
||||
|
||||
#define STM32_SYSCFG_CMPCR_OFFSET 0x0020 /* Compensation cell control register */
|
||||
|
||||
/* Register Addresses *******************************************************************************/
|
||||
|
||||
#define STM32_SYSCFG_MEMRMP (STM32_SYSCFG_BASE+STM32_SYSCFG_MEMRMP_OFFSET)
|
||||
#define STM32_SYSCFG_PMC (STM32_SYSCFG_BASE+STM32_SYSCFG_PMC_OFFSET)
|
||||
|
||||
#define STM32_SYSCFG_EXTICR(p) (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR_OFFSET(p))
|
||||
#define STM32_SYSCFG_EXTICR1 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR1_OFFSET)
|
||||
#define STM32_SYSCFG_EXTICR2 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR2_OFFSET)
|
||||
#define STM32_SYSCFG_EXTICR3 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR3_OFFSET)
|
||||
#define STM32_SYSCFG_EXTICR4 (STM32_SYSCFG_BASE+STM32_SYSCFG_EXTICR4_OFFSET)
|
||||
|
||||
#define STM32_SYSCFG_CMPCR (STM32_SYSCFG_BASE+STM32_SYSCFG_CMPCR_OFFSET)
|
||||
|
||||
/* Register Bitfield Definitions ********************************************************************/
|
||||
@ -75,10 +81,10 @@
|
||||
|
||||
#define SYSCFG_MEMRMP_SHIFT (0) /* Bits 1:0 MEM_MODE: Memory mapping selection */
|
||||
#define SYSCFG_MEMRMP_MASK (3 << SYSCFG_MEMRMP_SHIFT)
|
||||
# define SYSCFG_MEMRMP _MASK (0 << SYSCFG_MEMRMP_SHIFT) /* 00: Main Flash memory mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP _MASK (1 << SYSCFG_MEMRMP_SHIFT) /* 01: System Flash memory mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP _MASK (2 << SYSCFG_MEMRMP_SHIFT) /* 10: FSMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP _MASK (3 << SYSCFG_MEMRMP_SHIFT) /* 11: Embedded SRAM (112kB) mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP_FLASH (0 << SYSCFG_MEMRMP_SHIFT) /* 00: Main Flash memory mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP_SYSTEM (1 << SYSCFG_MEMRMP_SHIFT) /* 01: System Flash memory mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP_FSMC (2 << SYSCFG_MEMRMP_SHIFT) /* 10: FSMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x0000 0000 */
|
||||
# define SYSCFG_MEMRMP_SRAM (3 << SYSCFG_MEMRMP_SHIFT) /* 11: Embedded SRAM (112kB) mapped at 0x0000 0000 */
|
||||
|
||||
/* SYSCFG peripheral mode configuration register */
|
||||
|
||||
@ -96,41 +102,45 @@
|
||||
#define SYSCFG_EXTICR_PORTH (7) /* 0111: PH[x] pin */
|
||||
#define SYSCFG_EXTICR_PORTI (8) /* 1000: PI[x] pin */
|
||||
|
||||
#define SYSCFG_EXTICR1_EXTI0_SHIFT (0) /* Bits 0-3: EXIT 0 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI0_MASK (15 << SYSCFG_EXTICR1_EXTI0_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI1_SHIFT (0) /* Bits 4-7: EXIT 1 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI1_MASK (15 << SYSCFG_EXTICR1_EXTI1_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI2_SHIFT (0) /* Bits 8-11: EXIT 2 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI2_MASK (15 << SYSCFG_EXTICR1_EXTI2_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI3_SHIFT (0) /* Bits 12-15: EXIT 3 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI3_MASK (15 << SYSCFG_EXTICR1_EXTI3_SHIFT)
|
||||
#define SYSCFG_EXTICR_PORT_MASK (15)
|
||||
#define SYSCFG_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2)
|
||||
#define SYSCFG_EXTICR_EXTI_MASK(g) (SYSCFG_EXTICR_PORT_MASK << (SYSCFG_EXTICR_EXTI_SHIFT(g)))
|
||||
|
||||
#define SYSCFG_EXTICR2_EXTI4_SHIFT (0) /* Bits 0-3: EXIT 4 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI4_MASK (15 << SYSCFG_EXTICR2_EXTI4_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI5_SHIFT (0) /* Bits 4-7: EXIT 5 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI5_MASK (15 << SYSCFG_EXTICR2_EXTI5_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI6_SHIFT (0) /* Bits 8-11: EXIT 6 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI6_MASK (15 << SYSCFG_EXTICR2_EXTI6_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI7_SHIFT (0) /* Bits 12-15: EXIT 7 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI7_MASK (15 << SYSCFG_EXTICR2_EXTI7_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI0_SHIFT (0) /* Bits 0-3: EXTI 0 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI0_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI0_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI1_SHIFT (4) /* Bits 4-7: EXTI 1 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI1_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI1_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI2_SHIFT (8) /* Bits 8-11: EXTI 2 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI2_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI2_SHIFT)
|
||||
#define SYSCFG_EXTICR1_EXTI3_SHIFT (12) /* Bits 12-15: EXTI 3 coinfiguration */
|
||||
#define SYSCFG_EXTICR1_EXTI3_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI3_SHIFT)
|
||||
|
||||
#define SYSCFG_EXTICR3_EXTI8_SHIFT (0) /* Bits 0-3: EXIT 8 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI8_MASK (15 << SYSCFG_EXTICR3_EXTI8_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI9_SHIFT (0) /* Bits 4-7: EXIT 9 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI9_MASK (15 << SYSCFG_EXTICR3_EXTI9_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI10_SHIFT (0) /* Bits 8-11: EXIT 10 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI10_MASK (15 << SYSCFG_EXTICR3_EXTI10_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI11_SHIFT (0) /* Bits 12-15: EXIT 11 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI11_MASK (15 << SYSCFG_EXTICR3_EXTI11_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI4_SHIFT (0) /* Bits 0-3: EXTI 4 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI4_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI4_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI5_SHIFT (4) /* Bits 4-7: EXTI 5 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI5_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI5_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI6_SHIFT (8) /* Bits 8-11: EXTI 6 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI6_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI6_SHIFT)
|
||||
#define SYSCFG_EXTICR2_EXTI7_SHIFT (12) /* Bits 12-15: EXTI 7 coinfiguration */
|
||||
#define SYSCFG_EXTICR2_EXTI7_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI7_SHIFT)
|
||||
|
||||
#define SYSCFG_EXTICR4_EXTI12_SHIFT (0) /* Bits 0-3: EXIT 12 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI12_MASK (15 << SYSCFG_EXTICR4_EXTI12_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI13_SHIFT (0) /* Bits 4-7: EXIT 13 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI13_MASK (15 << SYSCFG_EXTICR4_EXTI13_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI14_SHIFT (0) /* Bits 8-11: EXIT 14 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI14_MASK (15 << SYSCFG_EXTICR4_EXTI14_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI15_SHIFT (0) /* Bits 12-15: EXIT 15 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI15_MASK (15 << SYSCFG_EXTICR4_EXTI15_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI8_SHIFT (0) /* Bits 0-3: EXTI 8 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI8_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI8_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI9_SHIFT (4) /* Bits 4-7: EXTI 9 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI9_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI9_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI10_SHIFT (8) /* Bits 8-11: EXTI 10 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI10_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI10_SHIFT)
|
||||
#define SYSCFG_EXTICR3_EXTI11_SHIFT (12) /* Bits 12-15: EXTI 11 coinfiguration */
|
||||
#define SYSCFG_EXTICR3_EXTI11_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI11_SHIFT)
|
||||
|
||||
#define SYSCFG_EXTICR4_EXTI12_SHIFT (0) /* Bits 0-3: EXTI 12 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI12_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI12_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI13_SHIFT (4) /* Bits 4-7: EXTI 13 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI13_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI13_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI14_SHIFT (8) /* Bits 8-11: EXTI 14 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI14_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI14_SHIFT)
|
||||
#define SYSCFG_EXTICR4_EXTI15_SHIFT (12) /* Bits 12-15: EXTI 15 coinfiguration */
|
||||
#define SYSCFG_EXTICR4_EXTI15_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI15_SHIFT)
|
||||
|
||||
/* Compensation cell control register */
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
|
||||
#define STM32_AFIO_EVCR_OFFSET 0x0000 /* Event control register */
|
||||
#define STM32_AFIO_MAPR_OFFSET 0x0004 /* AF remap and debug I/O configuration register */
|
||||
#define STM32_AFIO_EXTICR_OFFSET(p) (0x0008 + ((p) & 0xC)) /* Registers are displaced by 4! */
|
||||
#define STM32_AFIO_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */
|
||||
#define STM32_AFIO_EXTICR1_OFFSET 0x0008 /* External interrupt configuration register 1 */
|
||||
#define STM32_AFIO_EXTICR2_OFFSET 0x000c /* External interrupt configuration register 2 */
|
||||
#define STM32_AFIO_EXTICR3_OFFSET 0x0010 /* External interrupt configuration register 3 */
|
||||
|
@ -52,6 +52,14 @@
|
||||
#include "chip.h"
|
||||
#include "stm32_gpio.h"
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F40XX)
|
||||
# include "chip/stm32_syscfg.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
@ -96,179 +104,6 @@ const uint32_t g_gpiobase[STM32_NGPIO_PORTS] =
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_gpio_configlock (for the STM32F10xxx family
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F10XX)
|
||||
static int stm32_gpio_configlock(uint32_t cfgset, bool altlock)
|
||||
{
|
||||
uint32_t base;
|
||||
uint32_t cr;
|
||||
uint32_t regval;
|
||||
uint32_t regaddr;
|
||||
unsigned int port;
|
||||
unsigned int pin;
|
||||
unsigned int pos;
|
||||
unsigned int modecnf;
|
||||
bool input;
|
||||
|
||||
/* Verify that this hardware supports the select GPIO port */
|
||||
|
||||
port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
|
||||
if (port >= STM32_NGPIO_PORTS)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
regval = getreg32(cr);
|
||||
|
||||
/* Is present (old) config already in GPIO_ALT? and we got request to
|
||||
* lock the alternative configuration. If so we allow the following
|
||||
* changes only:
|
||||
* - to HiZ (unlocking the configuration)
|
||||
* - AFPP
|
||||
* - AFOD
|
||||
*/
|
||||
|
||||
uint32_t oldmode = (regval >> GPIO_CR_MODECNF_SHIFT(pos));
|
||||
|
||||
if (altlock &&
|
||||
(oldmode & (GPIO_MODE_MASK >> GPIO_MODE_SHIFT)) && /* previous state was output? */
|
||||
((oldmode>>2) & GPIO_CR_CNF_ALTOD) > GPIO_CR_CNF_OUTOD && /* previous state is ALT? */
|
||||
( ((cfgset & GPIO_CNF_MASK) >> GPIO_CNF_SHIFT) < GPIO_CR_CNF_ALTPP || /* new state is not output ALT? */
|
||||
input ) ) /* or it is input */
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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 &= ~(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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_gpio_configlock (for the STM32F40xxx family
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F40XX)
|
||||
static int stm32_gpio_configlock(uint32_t cfgset, bool altlock)
|
||||
{
|
||||
# warning "Missing logic"
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: stm32_gpioremap
|
||||
*
|
||||
@ -394,10 +229,352 @@ void stm32_gpioinit(void)
|
||||
* To-Do: Auto Power Enable
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_configgpio (for the STM32F10xxx family)
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F10XX)
|
||||
int stm32_configgpio(uint32_t cfgset)
|
||||
{
|
||||
return stm32_gpio_configlock(cfgset, true);
|
||||
uint32_t base;
|
||||
uint32_t cr;
|
||||
uint32_t regval;
|
||||
uint32_t regaddr;
|
||||
unsigned int port;
|
||||
unsigned int pin;
|
||||
unsigned int pos;
|
||||
unsigned int modecnf;
|
||||
bool input;
|
||||
|
||||
/* Verify that this hardware supports the select GPIO port */
|
||||
|
||||
port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
|
||||
if (port >= STM32_NGPIO_PORTS)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
regval = getreg32(cr);
|
||||
|
||||
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 &= ~(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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_configgpio (for the STM32F40xxx family)
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32_STM32F40XX)
|
||||
int stm32_configgpio(uint32_t cfgset)
|
||||
{
|
||||
uintptr_t base;
|
||||
uint32_t regval;
|
||||
uint32_t setting;
|
||||
unsigned int regoffset;
|
||||
unsigned int port;
|
||||
unsigned int pin;
|
||||
unsigned int pos;
|
||||
unsigned int pinmode;
|
||||
|
||||
/* Verify that this hardware supports the select GPIO port */
|
||||
|
||||
port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
|
||||
if (port >= STM32_NGPIO_PORTS)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Set up the mode register (and remember whether the pin mode) */
|
||||
|
||||
switch (cfgset & GPIO_MODE_MASK)
|
||||
{
|
||||
default:
|
||||
case GPIO_INPUT: /* Input mode */
|
||||
pinmode = GPIO_MODER_INPUT;
|
||||
break;
|
||||
|
||||
case GPIO_OUTPUT: /* General purpose output mode */
|
||||
pinmode = GPIO_MODER_OUTPUT;
|
||||
break;
|
||||
|
||||
case GPIO_ALT: /* Alternate function mode */
|
||||
pinmode = GPIO_MODER_ALT;
|
||||
break;
|
||||
|
||||
case GPIO_ANALOG: /* Analog mode */
|
||||
pinmode = GPIO_MODER_ANALOG;
|
||||
break;
|
||||
}
|
||||
|
||||
regval = getreg32(base + STM32_GPIO_MODER_OFFSET);
|
||||
regval &= ~GPIO_MODER_MASK(pin);
|
||||
regval |= ((uint32_t)pinmode << GPIO_MODER_SHIFT(pin));
|
||||
putreg32(regval, base + STM32_GPIO_MODER_OFFSET);
|
||||
|
||||
/* Set up the pull-up/pull-down configuration (all but analog pins) */
|
||||
|
||||
setting = GPIO_PUPDR_NONE;
|
||||
if (pinmode != GPIO_MODER_ANALOG)
|
||||
{
|
||||
switch (cfgset & GPIO_PUPD_MASK)
|
||||
{
|
||||
default:
|
||||
case GPIO_FLOAT: /* No pull-up, pull-down */
|
||||
break;
|
||||
|
||||
case GPIO_PULLUP: /* Pull-up */
|
||||
setting = GPIO_PUPDR_PULLUP;
|
||||
break;
|
||||
|
||||
case GPIO_PULLDOWN: /* Pull-down */
|
||||
setting = GPIO_PUPDR_PULLDOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
regval = getreg32(base + STM32_GPIO_PUPDR_OFFSET);
|
||||
regval &= ~GPIO_PUPDR_MASK(pin);
|
||||
regval |= (setting << GPIO_PUPDR_SHIFT(pin));
|
||||
putreg32(regval, base + STM32_GPIO_PUPDR_OFFSET);
|
||||
|
||||
/* Set the alternate function (Only alternate function pins) */
|
||||
|
||||
if (pinmode == GPIO_MODER_ALT)
|
||||
{
|
||||
setting = (cfgset & GPIO_AF_MASK) >> GPIO_AF_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
setting = 0;
|
||||
}
|
||||
|
||||
if (pin < 8)
|
||||
{
|
||||
regoffset = STM32_GPIO_AFRL_OFFSET;
|
||||
pos = pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
regoffset = STM32_GPIO_ARFH_OFFSET;
|
||||
pos = pin - 8;
|
||||
}
|
||||
|
||||
regval = getreg32(base + regoffset);
|
||||
regval &= ~GPIO_AFR_MASK(pos);
|
||||
regval |= (setting << GPIO_AFR_SHIFT(pos));
|
||||
putreg32(regval, base + regoffset);
|
||||
|
||||
/* Set speed (Only outputs and alternate function pins) */
|
||||
|
||||
if (pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT)
|
||||
{
|
||||
switch (cfgset & GPIO_SPEED_MASK)
|
||||
{
|
||||
default:
|
||||
case GPIO_SPEED_2MHz: /* 2 MHz Low speed output */
|
||||
setting = GPIO_OSPEED_2MHz;
|
||||
break;
|
||||
|
||||
case GPIO_SPEED_25MHz: /* 25 MHz Medium speed output */
|
||||
setting = GPIO_OSPEED_25MHz;
|
||||
break;
|
||||
|
||||
case GPIO_SPEED_20MHz: /* 50 MHz Fast speed output */
|
||||
setting = GPIO_OSPEED_50MHz;
|
||||
break;
|
||||
|
||||
case GPIO_SPEED_100MHz: /* 100 MHz High speed output */
|
||||
setting = GPIO_OSPEED_100MHz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setting = 0;
|
||||
}
|
||||
|
||||
regval = getreg32(base + STM32_GPIO_OSPEED_OFFSET);
|
||||
regval &= ~GPIO_OSPEED_MASK(pos);
|
||||
regval |= (setting << GPIO_OSPEED_SHIFT(pos));
|
||||
putreg32(regval, base + STM32_GPIO_OSPEED_OFFSET);
|
||||
|
||||
/* Set push-pull/open-drain (Only outputs and alternate function pins) */
|
||||
|
||||
regval = getreg32(base + STM32_GPIO_OTYPER_OFFSET);
|
||||
setting = GPIO_OTYPER_OD(pin);
|
||||
|
||||
if ((pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) &&
|
||||
(cfgset & GPIO_OPENDRAIN) != 0)
|
||||
{
|
||||
regval |= setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
regval &= ~setting;
|
||||
}
|
||||
|
||||
putreg32(regval, base + STM32_GPIO_OTYPER_OFFSET);
|
||||
|
||||
/* If it is an input pin, hould it configured as an EXTI interrupt? */
|
||||
|
||||
if ((cfgset & GPIO_EXTI) != 0)
|
||||
{
|
||||
/* "In STM32 F1 the selection of the EXTI line source is performed through
|
||||
* the EXTIx bits in the AFIO_EXTICRx registers, while in F2 series this
|
||||
* selection is done through the EXTIx bits in the SYSCFG_EXTICRx registers.
|
||||
*
|
||||
* "Only the mapping of the EXTICRx registers has been changed, without any
|
||||
* changes to the meaning of the EXTIx bits. However, the range of EXTI
|
||||
* bits values has been extended to 0b1000 to support the two ports added
|
||||
* in F2, port H and I (in F1 series the maximum value is 0b0110)."
|
||||
*/
|
||||
|
||||
uint32_t regaddr;
|
||||
int shift;
|
||||
|
||||
/* Set the bits in the SYSCFG EXTICR register */
|
||||
|
||||
regaddr = STM32_SYSCFG_EXTICR(pin);
|
||||
regval = getreg32(regaddr);
|
||||
shift = SYSCFG_EXTICR_EXTI_SHIFT(pin);
|
||||
regval &= ~(SYSCFG_EXTICR_PORT_MASK << shift);
|
||||
regval |= (((uint32_t)port) << shift);
|
||||
|
||||
putreg32(regval, regaddr);
|
||||
}
|
||||
|
||||
/* If it is an output... set the pin to the correct initial state. */
|
||||
|
||||
else if (pinmode == GPIO_MODER_OUTPUT)
|
||||
{
|
||||
bool value = ((cfgset & GPIO_OUTPUT_SET) != 0);
|
||||
stm32_gpiowrite(cfgset, value);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_unconfiggpio
|
||||
@ -434,7 +611,7 @@ int stm32_unconfiggpio(uint32_t cfgset)
|
||||
|
||||
/* To-Do: Mark its unuse for automatic power saving options */
|
||||
|
||||
return stm32_gpio_configlock(cfgset, false);
|
||||
return stm32_configgpio(cfgset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -307,7 +307,7 @@ extern "C" {
|
||||
* .... .... ..O. .... ....
|
||||
*/
|
||||
|
||||
#define GPIO_OPENDRAM (1 << 9) /* Bit9: 1=Open-drain output */
|
||||
#define GPIO_OPENDRAIN (1 << 9) /* Bit9: 1=Open-drain output */
|
||||
#define GPIO_PUSHPULL (0) /* Bit9: 0=Push-pull output */
|
||||
|
||||
/* If the pin is a GPIO digital output, then this identifies the initial output value.
|
||||
|
Loading…
Reference in New Issue
Block a user