Skip to content

Commit

Permalink
drivers: gpio: stm32: STM32F7 GPIO support
Browse files Browse the repository at this point in the history
This patch adds GPIO support for STM32F7 family microcontrollers.

Signed-off-by: Yurii Hamann <[email protected]>
  • Loading branch information
Yurii Hamann authored and galak committed Jun 28, 2018
1 parent cfb25c7 commit a229500
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/arm/soc/st_stm32/stm32f7/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers)
zephyr_sources(
soc.c
)
zephyr_sources_ifdef(CONFIG_GPIO soc_gpio.c)
16 changes: 16 additions & 0 deletions arch/arm/soc/st_stm32/stm32f7/Kconfig.defconfig.series
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,20 @@ gsource "arch/arm/soc/st_stm32/stm32f7/Kconfig.defconfig.stm32f7*"
config SOC_SERIES
default "stm32f7"

if GPIO_STM32

config GPIO_STM32_PORTD
default y

config GPIO_STM32_PORTE
default y

config GPIO_STM32_PORTH
default y

config GPIO_STM32_PORTI
default y

endif # GPIO_STM32

endif # SOC_SERIES_STM32F7X
10 changes: 10 additions & 0 deletions arch/arm/soc/st_stm32/stm32f7/Kconfig.defconfig.stm32f746xg
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ config SOC
string
default "stm32f746xx"

if GPIO_STM32

config GPIO_STM32_PORTJ
default y

config GPIO_STM32_PORTK
default y

endif # GPIO_STM32

config NUM_IRQS
int
default 98
Expand Down
53 changes: 53 additions & 0 deletions arch/arm/soc/st_stm32/stm32f7/gpio_registers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2018 Yurii Hamann
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef _STM32F7X_GPIO_REGISTERS_H_
#define _STM32F7X_GPIO_REGISTERS_H_

/**
* @brief Driver for GPIO of STM32F7X family processor.
*
* Based on reference manual:
* RM0385 Reference manual STM32F75xxx and STM32F74xxx
* advanced ARM(r)-based 32-bit MCUs
*
* Chapter 6: General-purpose I/Os (GPIOs)
*/

/* 6.4 GPIO registers - each GPIO port controls 16 pins */
struct stm32f7x_gpio {
u32_t moder;
u32_t otyper;
u32_t ospeedr;
u32_t pupdr;
u32_t idr;
u32_t odr;
u32_t bsrr;
u32_t lckr;
u32_t afr[2];
u32_t brr;
};

union syscfg_exticr {
u32_t val;
struct {
u16_t rsvd__16_31;
u16_t exti;
} bit;
};

/* 7.2 SYSCFG registers */
struct stm32f7x_syscfg {
u32_t memrmp;
u32_t pmc;
union syscfg_exticr exticr1;
union syscfg_exticr exticr2;
union syscfg_exticr exticr3;
union syscfg_exticr exticr4;
u32_t cmpcr;
};

#endif /* _STM32F7X_GPIO_REGISTERS_H_ */
4 changes: 4 additions & 0 deletions arch/arm/soc/st_stm32/stm32f7/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
#ifndef _STM32F7_SOC_H_
#define _STM32F7_SOC_H_

#define GPIO_REG_SIZE 0x400
/* base address for where GPIO registers start */
#define GPIO_PORTS_BASE (GPIOA_BASE)

#ifndef _ASMLANGUAGE

#include <device.h>
Expand Down
142 changes: 142 additions & 0 deletions arch/arm/soc/st_stm32/stm32f7/soc_gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2018 Yurii Hamann
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @brief
*
* Based on reference manual:
* RM0385 Reference manual STM32F75xxx and STM32F74xxx
* advanced ARM ® -based 32-bit MCUs
*
* Chapter 6: General-purpose I/Os (GPIOs)
*/

#include <errno.h>

#include <device.h>
#include "soc.h"
#include "soc_registers.h"
#include <gpio.h>
#include <gpio/gpio_stm32.h>


int stm32_gpio_flags_to_conf(int flags, int *pincfg)
{
int direction = flags & GPIO_DIR_MASK;
int pud = flags & GPIO_PUD_MASK;

if (!pincfg) {
return -EINVAL;
}

if (direction == GPIO_DIR_OUT) {
*pincfg = STM32_MODER_OUTPUT_MODE;
} else {
/* pull-{up,down} maybe? */
*pincfg = STM32_MODER_INPUT_MODE;

if (pud == GPIO_PUD_PULL_UP) {
*pincfg = *pincfg | STM32_PUPDR_PULL_UP;
} else if (pud == GPIO_PUD_PULL_DOWN) {
*pincfg = *pincfg | STM32_PUPDR_PULL_DOWN;
} else {
/* floating */
*pincfg = *pincfg | STM32_PUPDR_NO_PULL;
}
}

return 0;
}

int stm32_gpio_configure(u32_t *base_addr, int pin, int conf, int altf)
{
volatile struct stm32f7x_gpio *gpio =
(struct stm32f7x_gpio *)(base_addr);
unsigned int mode, otype, ospeed, pupd;
unsigned int pin_shift = pin << 1;
unsigned int afr_bank = pin / 8;
unsigned int afr_shift = (pin % 8) << 2;
u32_t scratch;

mode = (conf >> STM32_MODER_SHIFT) & STM32_MODER_MASK;
otype = (conf >> STM32_OTYPER_SHIFT) & STM32_OTYPER_MASK;
ospeed = (conf >> STM32_OSPEEDR_SHIFT) & STM32_OSPEEDR_MASK;
pupd = (conf >> STM32_PUPDR_SHIFT) & STM32_PUPDR_MASK;

scratch = gpio->moder & ~(STM32_MODER_MASK << pin_shift);
gpio->moder = scratch | (mode << pin_shift);

scratch = gpio->ospeedr & ~(STM32_OSPEEDR_MASK << pin_shift);
gpio->ospeedr = scratch | (ospeed << pin_shift);

scratch = gpio->otyper & ~(STM32_OTYPER_MASK << pin);
gpio->otyper = scratch | (otype << pin);

scratch = gpio->pupdr & ~(STM32_PUPDR_MASK << pin_shift);
gpio->pupdr = scratch | (pupd << pin_shift);

scratch = gpio->afr[afr_bank] & ~(STM32_AFR_MASK << afr_shift);
gpio->afr[afr_bank] = scratch | (altf << afr_shift);

return 0;
}

int stm32_gpio_set(u32_t *base, int pin, int value)
{
struct stm32f7x_gpio *gpio = (struct stm32f7x_gpio *)base;

if (value) {
/* atomic set */
gpio->bsrr = (1 << (pin & 0x0f));
} else {
/* atomic reset */
gpio->bsrr = (1 << ((pin & 0x0f) + 0x10));
}

return 0;
}

int stm32_gpio_get(u32_t *base, int pin)
{
struct stm32f7x_gpio *gpio = (struct stm32f7x_gpio *)base;

return (gpio->idr >> pin) & 0x1;
}

int stm32_gpio_enable_int(int port, int pin)
{
volatile struct stm32f7x_syscfg *syscfg =
(struct stm32f7x_syscfg *)SYSCFG_BASE;
volatile union syscfg_exticr *exticr;
struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
struct stm32_pclken pclken = {
.bus = STM32_CLOCK_BUS_APB2,
.enr = LL_APB2_GRP1_PERIPH_SYSCFG
};
int shift = 0;

/* Enable SYSCFG clock */
clock_control_on(clk, (clock_control_subsys_t *) &pclken);

if (pin <= 3) {
exticr = &syscfg->exticr1;
} else if (pin <= 7) {
exticr = &syscfg->exticr2;
} else if (pin <= 11) {
exticr = &syscfg->exticr3;
} else if (pin <= 15) {
exticr = &syscfg->exticr4;
} else {
return -EINVAL;
}

shift = 4 * (pin % 4);

exticr->val &= ~(0xf << shift);
exticr->val |= port << shift;

return 0;
}
1 change: 1 addition & 0 deletions arch/arm/soc/st_stm32/stm32f7/soc_registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@

/* include register mapping headers */
#include "flash_registers.h"
#include "gpio_registers.h"

#endif /* _STM32F7_SOC_REGISTERS_H_ */
13 changes: 13 additions & 0 deletions drivers/gpio/gpio_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@
#define STM32_PERIPH_GPIOI LL_AHB1_GRP1_PERIPH_GPIOI
#define STM32_PERIPH_GPIOJ LL_AHB1_GRP1_PERIPH_GPIOJ
#define STM32_PERIPH_GPIOK LL_AHB1_GRP1_PERIPH_GPIOK
#elif CONFIG_SOC_SERIES_STM32F7X
#define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_AHB1
#define STM32_PERIPH_GPIOA LL_AHB1_GRP1_PERIPH_GPIOA
#define STM32_PERIPH_GPIOB LL_AHB1_GRP1_PERIPH_GPIOB
#define STM32_PERIPH_GPIOC LL_AHB1_GRP1_PERIPH_GPIOC
#define STM32_PERIPH_GPIOD LL_AHB1_GRP1_PERIPH_GPIOD
#define STM32_PERIPH_GPIOE LL_AHB1_GRP1_PERIPH_GPIOE
#define STM32_PERIPH_GPIOF LL_AHB1_GRP1_PERIPH_GPIOF
#define STM32_PERIPH_GPIOG LL_AHB1_GRP1_PERIPH_GPIOG
#define STM32_PERIPH_GPIOH LL_AHB1_GRP1_PERIPH_GPIOH
#define STM32_PERIPH_GPIOI LL_AHB1_GRP1_PERIPH_GPIOI
#define STM32_PERIPH_GPIOJ LL_AHB1_GRP1_PERIPH_GPIOJ
#define STM32_PERIPH_GPIOK LL_AHB1_GRP1_PERIPH_GPIOK
#elif CONFIG_SOC_SERIES_STM32L0X
#define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_IOP
#define STM32_PERIPH_GPIOA LL_IOP_GRP1_PERIPH_GPIOA
Expand Down

0 comments on commit a229500

Please sign in to comment.