Skip to content

Commit 9612f9d

Browse files
cybertalegalak
authored andcommitted
soc: arm: st_stm32: Cleanup gpio function code.
All series STM32 have mostly the same GPIO architecture and can share the same code for GPIO manipulation. Functions of the external interrupt line control are also the same. This patch extracts common code from them and put them into the 'common' folder. Functions of control GPIO of these series scattered in soc/arm/st_stm32/stm32xx/ folders contain these functions: stm32_gpio_flags_to_conf(), stm32_gpio_configure(), stm32_gpio_set(), stm32_gpio_get, stm32_gpio_enable_int(). This patch merges them into the gpio_stm32.c file. Signed-off-by: Song Qiang <[email protected]>
1 parent d4ef80e commit 9612f9d

36 files changed

+376
-1478
lines changed

drivers/gpio/gpio_stm32.c

Lines changed: 220 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,17 @@
1919
#include "gpio_stm32.h"
2020
#include "gpio_utils.h"
2121

22+
/* F1 series STM32 use AFIO register to configure interrupt generation
23+
* and pinmux.
24+
*/
25+
#ifdef CONFIG_SOC_SERIES_STM32F1X
26+
#include "afio_registers.h"
27+
#else
28+
#include "syscfg_registers.h"
29+
#endif
30+
2231
/**
23-
* @brief Common GPIO driver for STM32 MCUs. Each SoC must implement a
24-
* SoC specific integration glue
32+
* @brief Common GPIO driver for STM32 MCUs.
2533
*/
2634

2735
/**
@@ -37,6 +45,202 @@ static void gpio_stm32_isr(int line, void *arg)
3745
}
3846
}
3947

48+
/**
49+
* @brief Common gpio flags to custom flags
50+
*/
51+
const int gpio_stm32_flags_to_conf(int flags, int *pincfg)
52+
{
53+
int direction = flags & GPIO_DIR_MASK;
54+
int pud = flags & GPIO_PUD_MASK;
55+
56+
if (pincfg == NULL) {
57+
return -EINVAL;
58+
}
59+
60+
if (direction == GPIO_DIR_OUT) {
61+
*pincfg = STM32_PINCFG_MODE_OUTPUT;
62+
} else {
63+
/* pull-{up,down} maybe? */
64+
*pincfg = STM32_PINCFG_MODE_INPUT;
65+
if (pud == GPIO_PUD_PULL_UP) {
66+
*pincfg |= STM32_PINCFG_PULL_UP;
67+
} else if (pud == GPIO_PUD_PULL_DOWN) {
68+
*pincfg |= STM32_PINCFG_PULL_DOWN;
69+
} else {
70+
/* floating */
71+
*pincfg |= STM32_PINCFG_FLOATING;
72+
}
73+
}
74+
75+
return 0;
76+
}
77+
78+
/**
79+
* @brief Configure the hardware.
80+
*/
81+
int gpio_stm32_configure(u32_t *base_addr, int pin, int conf, int altf)
82+
{
83+
volatile struct stm32_gpio *gpio =
84+
(struct stm32_gpio *)(base_addr);
85+
#ifdef CONFIG_SOC_SERIES_STM32F1X
86+
int cnf, mode, mode_io;
87+
int crpin = pin;
88+
89+
/* pins are configured in CRL (0-7) and CRH (8-15)
90+
* registers
91+
*/
92+
volatile u32_t *reg = &gpio->crl;
93+
94+
ARG_UNUSED(altf);
95+
96+
if (crpin > 7) {
97+
reg = &gpio->crh;
98+
crpin -= 8;
99+
}
100+
101+
/* each port is configured by 2 registers:
102+
* CNFy[1:0]: Port x configuration bits
103+
* MODEy[1:0]: Port x mode bits
104+
*
105+
* memory layout is repeated for every port:
106+
* | CNF | MODE |
107+
* | [0:1] | [0:1] |
108+
*/
109+
110+
mode_io = (conf >> STM32_MODE_INOUT_SHIFT) & STM32_MODE_INOUT_MASK;
111+
112+
if (mode_io == STM32_MODE_INPUT) {
113+
int in_pudpd = conf & (STM32_PUPD_MASK << STM32_PUPD_SHIFT);
114+
115+
/* Pin configured in input mode */
116+
/* Mode: 00 */
117+
mode = mode_io;
118+
/* Configuration values: */
119+
/* 00: Analog mode */
120+
/* 01: Floating input */
121+
/* 10: Pull-up/Pull-Down */
122+
cnf = (conf >> STM32_CNF_IN_SHIFT) & STM32_CNF_IN_MASK;
123+
124+
if (in_pudpd == STM32_PUPD_PULL_UP) {
125+
/* enable pull up */
126+
gpio->odr |= 1 << pin;
127+
} else if (in_pudpd == STM32_PUPD_PULL_DOWN) {
128+
/* or pull down */
129+
gpio->odr &= ~(1 << pin);
130+
}
131+
} else {
132+
/* Pin configured in output mode */
133+
int mode_speed = ((conf >> STM32_MODE_OSPEED_SHIFT) &
134+
STM32_MODE_OSPEED_MASK);
135+
/* Mode output possible values */
136+
/* 01: Max speed 10MHz (default value) */
137+
/* 10: Max speed 2MHz */
138+
/* 11: Max speed 50MHz */
139+
mode = mode_speed + mode_io;
140+
/* Configuration possible values */
141+
/* x0: Push-pull */
142+
/* x1: Open-drain */
143+
/* 0x: General Purpose Output */
144+
/* 1x: Alternate Function Output */
145+
cnf = ((conf >> STM32_CNF_OUT_0_SHIFT) & STM32_CNF_OUT_0_MASK) |
146+
(((conf >> STM32_CNF_OUT_1_SHIFT) & STM32_CNF_OUT_1_MASK)
147+
<< 1);
148+
}
149+
150+
/* clear bits */
151+
*reg &= ~(0xf << (crpin * 4));
152+
/* set bits */
153+
*reg |= (cnf << (crpin * 4 + 2) | mode << (crpin * 4));
154+
#else
155+
unsigned int mode, otype, ospeed, pupd;
156+
unsigned int pin_shift = pin << 1;
157+
unsigned int afr_bank = pin / 8;
158+
unsigned int afr_shift = (pin % 8) << 2;
159+
u32_t scratch;
160+
161+
mode = (conf >> STM32_MODER_SHIFT) & STM32_MODER_MASK;
162+
otype = (conf >> STM32_OTYPER_SHIFT) & STM32_OTYPER_MASK;
163+
ospeed = (conf >> STM32_OSPEEDR_SHIFT) & STM32_OSPEEDR_MASK;
164+
pupd = (conf >> STM32_PUPDR_SHIFT) & STM32_PUPDR_MASK;
165+
166+
scratch = gpio->moder & ~(STM32_MODER_MASK << pin_shift);
167+
gpio->moder = scratch | (mode << pin_shift);
168+
169+
scratch = gpio->ospeedr & ~(STM32_OSPEEDR_MASK << pin_shift);
170+
gpio->ospeedr = scratch | (ospeed << pin_shift);
171+
172+
scratch = gpio->otyper & ~(STM32_OTYPER_MASK << pin);
173+
gpio->otyper = scratch | (otype << pin);
174+
175+
scratch = gpio->pupdr & ~(STM32_PUPDR_MASK << pin_shift);
176+
gpio->pupdr = scratch | (pupd << pin_shift);
177+
178+
scratch = gpio->afr[afr_bank] & ~(STM32_AFR_MASK << afr_shift);
179+
gpio->afr[afr_bank] = scratch | (altf << afr_shift);
180+
#endif
181+
return 0;
182+
}
183+
184+
/**
185+
* @brief Enable EXTI of the specific line
186+
*/
187+
const int gpio_stm32_enable_int(int port, int pin)
188+
{
189+
#ifdef CONFIG_SOC_SERIES_STM32F1X
190+
volatile struct stm32_afio *syscfg =
191+
(struct stm32_afio *)AFIO_BASE;
192+
#else
193+
volatile struct stm32_syscfg *syscfg =
194+
(struct stm32_syscfg *)SYSCFG_BASE;
195+
#endif
196+
volatile union syscfg_exticr *exticr;
197+
198+
#if defined(CONFIG_SOC_SERIES_STM32F2X) || \
199+
defined(CONFIG_SOC_SERIES_STM32F3X) || \
200+
defined(CONFIG_SOC_SERIES_STM32F4X) || \
201+
defined(CONFIG_SOC_SERIES_STM32F7X) || \
202+
defined(CONFIG_SOC_SERIES_STM32L4X)
203+
struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
204+
struct stm32_pclken pclken = {
205+
.bus = STM32_CLOCK_BUS_APB2,
206+
.enr = LL_APB2_GRP1_PERIPH_SYSCFG
207+
};
208+
/* Enable SYSCFG clock */
209+
clock_control_on(clk, (clock_control_subsys_t *) &pclken);
210+
#endif
211+
int shift = 0;
212+
213+
if (pin <= 3) {
214+
exticr = &syscfg->exticr1;
215+
} else if (pin <= 7) {
216+
exticr = &syscfg->exticr2;
217+
} else if (pin <= 11) {
218+
exticr = &syscfg->exticr3;
219+
} else if (pin <= 15) {
220+
exticr = &syscfg->exticr4;
221+
} else {
222+
return -EINVAL;
223+
}
224+
225+
#ifdef CONFIG_SOC_SERIES_STM32L0X
226+
/*
227+
* Ports F and G are not present on some STM32L0 parts, so
228+
* for these parts port H external interrupt should be enabled
229+
* by writing value 0x5 instead of 0x7.
230+
*/
231+
if (port == STM32_PORTH) {
232+
port = LL_SYSCFG_EXTI_PORTH;
233+
}
234+
#endif
235+
236+
shift = 4 * (pin % 4);
237+
238+
exticr->val &= ~(0xf << shift);
239+
exticr->val |= port << shift;
240+
241+
return 0;
242+
}
243+
40244
/**
41245
* @brief Configure pin or port
42246
*/
@@ -54,12 +258,12 @@ static int gpio_stm32_config(struct device *dev, int access_op,
54258
/* figure out if we can map the requested GPIO
55259
* configuration
56260
*/
57-
map_res = stm32_gpio_flags_to_conf(flags, &pincfg);
261+
map_res = gpio_stm32_flags_to_conf(flags, &pincfg);
58262
if (map_res) {
59263
return map_res;
60264
}
61265

62-
if (stm32_gpio_configure(cfg->base, pin, pincfg, 0)) {
266+
if (gpio_stm32_configure(cfg->base, pin, pincfg, 0)) {
63267
return -EIO;
64268
}
65269

@@ -70,7 +274,7 @@ static int gpio_stm32_config(struct device *dev, int access_op,
70274
return -EBUSY;
71275
}
72276

73-
stm32_gpio_enable_int(cfg->port, pin);
277+
gpio_stm32_enable_int(cfg->port, pin);
74278

75279
if (flags & GPIO_INT_EDGE) {
76280
int edge = 0;
@@ -100,12 +304,20 @@ static int gpio_stm32_write(struct device *dev, int access_op,
100304
u32_t pin, u32_t value)
101305
{
102306
const struct gpio_stm32_config *cfg = dev->config->config_info;
307+
struct stm32_gpio *gpio = (struct stm32_gpio *)cfg->base;
308+
int pval = 1 << (pin & 0xf);
103309

104310
if (access_op != GPIO_ACCESS_BY_PIN) {
105311
return -ENOTSUP;
106312
}
107313

108-
return stm32_gpio_set(cfg->base, pin, value);
314+
if (value != 0) {
315+
gpio->odr |= pval;
316+
} else {
317+
gpio->odr &= ~pval;
318+
}
319+
320+
return 0;
109321
}
110322

111323
/**
@@ -115,12 +327,13 @@ static int gpio_stm32_read(struct device *dev, int access_op,
115327
u32_t pin, u32_t *value)
116328
{
117329
const struct gpio_stm32_config *cfg = dev->config->config_info;
330+
struct stm32_gpio *gpio = (struct stm32_gpio *)cfg->base;
118331

119332
if (access_op != GPIO_ACCESS_BY_PIN) {
120333
return -ENOTSUP;
121334
}
122335

123-
*value = stm32_gpio_get(cfg->base, pin);
336+
*value = (gpio->idr >> pin) & 0x1;
124337

125338
return 0;
126339
}

drivers/gpio/gpio_stm32.h

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@
104104
#define STM32_PERIPH_GPIOI LL_AHB2_GRP1_PERIPH_GPIOI
105105
#endif /* CONFIG_SOC_SERIES_.. */
106106

107+
#ifdef CONFIG_SOC_SERIES_STM32F1X
108+
#define STM32_PINCFG_MODE_OUTPUT STM32_MODE_OUTPUT | STM32_CNF_GP_OUTPUT | STM32_CNF_PUSH_PULL
109+
#define STM32_PINCFG_MODE_INPUT STM32_MODE_INPUT
110+
#define STM32_PINCFG_PULL_UP STM32_CNF_IN_PUPD | STM32_PUPD_PULL_UP
111+
#define STM32_PINCFG_PULL_DOWN STM32_CNF_IN_PUPD | STM32_PUPD_PULL_DOWN
112+
#define STM32_PINCFG_FLOATING STM32_CNF_IN_FLOAT | STM32_PUPD_NO_PULL
113+
#else
114+
#define STM32_PINCFG_MODE_OUTPUT STM32_MODER_OUTPUT_MODE
115+
#define STM32_PINCFG_MODE_INPUT STM32_MODER_INPUT_MODE
116+
#define STM32_PINCFG_PULL_UP STM32_PUPDR_PULL_UP
117+
#define STM32_PINCFG_PULL_DOWN STM32_PUPDR_PULL_DOWN
118+
#define STM32_PINCFG_FLOATING STM32_PUPDR_NO_PULL
119+
#endif /* CONFIG_SOC_SERIES_STM32F1X */
120+
107121
/**
108122
* @brief configuration of GPIO device
109123
*/
@@ -126,14 +140,39 @@ struct gpio_stm32_data {
126140
};
127141

128142
/**
129-
* @brief helper for mapping of GPIO flags to SoC specific config
130-
*
131-
* @param flags GPIO encoded flags
132-
* @param out conf SoC specific pin config
133-
*
134-
* @return 0 if flags were mapped to SoC pin config
143+
* @brief layout of stm32 gpio registers
135144
*/
136-
int stm32_gpio_flags_to_conf(int flags, int *conf);
145+
struct stm32_gpio {
146+
#ifdef CONFIG_SOC_SERIES_STM32F1X
147+
u32_t crl;
148+
u32_t crh;
149+
u32_t idr;
150+
u32_t odr;
151+
u32_t bsrr;
152+
u32_t brr;
153+
u32_t lckr;
154+
#else
155+
u32_t moder;
156+
u32_t otyper;
157+
u32_t ospeedr;
158+
u32_t pupdr;
159+
u32_t idr;
160+
u32_t odr;
161+
u32_t bsrr;
162+
u32_t lckr;
163+
u32_t afr[2];
164+
#if defined(CONFIG_SOC_SERIES_STM32F0X) || \
165+
defined(CONFIG_SOC_SERIES_STM32F3X) || \
166+
defined(CONFIG_SOC_SERIES_STM32F7X) || \
167+
defined(CONFIG_SOC_SERIES_STM32L0X) || \
168+
defined(CONFIG_SOC_SERIES_STM32L4X)
169+
u32_t brr;
170+
#endif
171+
#ifdef CONFIG_SOC_SERIES_STM32L4X
172+
u32_t ascr;
173+
#endif
174+
#endif /* CONFIG_SOC_SERIES_STM32F1X */
175+
};
137176

138177
/**
139178
* @brief helper for configuration of GPIO pin
@@ -143,32 +182,6 @@ int stm32_gpio_flags_to_conf(int flags, int *conf);
143182
* @param func GPIO mode
144183
* @param altf Alternate function
145184
*/
146-
int stm32_gpio_configure(u32_t *base_addr, int pin, int func, int altf);
147-
148-
/**
149-
* @brief helper for setting of GPIO pin output
150-
*
151-
* @param base_addr GPIO port base address
152-
* @param pin IO pin
153-
* @param value 1, 0
154-
*/
155-
int stm32_gpio_set(u32_t *base, int pin, int value);
156-
157-
/**
158-
* @brief helper for reading of GPIO pin value
159-
*
160-
* @param base_addr GPIO port base address
161-
* @param pin IO pin
162-
* @return pin value
163-
*/
164-
int stm32_gpio_get(u32_t *base, int pin);
165-
166-
/**
167-
* @brief enable interrupt source for GPIO pin
168-
* @param port
169-
* @param pin
170-
*/
171-
int stm32_gpio_enable_int(int port, int pin);
185+
int gpio_stm32_configure(u32_t *base_addr, int pin, int conf, int altf);
172186

173187
#endif /* ZEPHYR_DRIVERS_GPIO_GPIO_STM32_H_ */
174-

drivers/pinmux/stm32/pinmux_stm32.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static int stm32_pin_configure(int pin, int func, int altf)
105105
/* not much here, on STM32F10x the alternate function is
106106
* controller by setting up GPIO pins in specific mode.
107107
*/
108-
return stm32_gpio_configure((u32_t *)port_base,
108+
return gpio_stm32_configure((u32_t *)port_base,
109109
STM32_PIN(pin), func, altf);
110110
}
111111

0 commit comments

Comments
 (0)