19
19
#include "gpio_stm32.h"
20
20
#include "gpio_utils.h"
21
21
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
+
22
31
/**
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.
25
33
*/
26
34
27
35
/**
@@ -37,6 +45,202 @@ static void gpio_stm32_isr(int line, void *arg)
37
45
}
38
46
}
39
47
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
+
40
244
/**
41
245
* @brief Configure pin or port
42
246
*/
@@ -54,12 +258,12 @@ static int gpio_stm32_config(struct device *dev, int access_op,
54
258
/* figure out if we can map the requested GPIO
55
259
* configuration
56
260
*/
57
- map_res = stm32_gpio_flags_to_conf (flags , & pincfg );
261
+ map_res = gpio_stm32_flags_to_conf (flags , & pincfg );
58
262
if (map_res ) {
59
263
return map_res ;
60
264
}
61
265
62
- if (stm32_gpio_configure (cfg -> base , pin , pincfg , 0 )) {
266
+ if (gpio_stm32_configure (cfg -> base , pin , pincfg , 0 )) {
63
267
return - EIO ;
64
268
}
65
269
@@ -70,7 +274,7 @@ static int gpio_stm32_config(struct device *dev, int access_op,
70
274
return - EBUSY ;
71
275
}
72
276
73
- stm32_gpio_enable_int (cfg -> port , pin );
277
+ gpio_stm32_enable_int (cfg -> port , pin );
74
278
75
279
if (flags & GPIO_INT_EDGE ) {
76
280
int edge = 0 ;
@@ -100,12 +304,20 @@ static int gpio_stm32_write(struct device *dev, int access_op,
100
304
u32_t pin , u32_t value )
101
305
{
102
306
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 );
103
309
104
310
if (access_op != GPIO_ACCESS_BY_PIN ) {
105
311
return - ENOTSUP ;
106
312
}
107
313
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 ;
109
321
}
110
322
111
323
/**
@@ -115,12 +327,13 @@ static int gpio_stm32_read(struct device *dev, int access_op,
115
327
u32_t pin , u32_t * value )
116
328
{
117
329
const struct gpio_stm32_config * cfg = dev -> config -> config_info ;
330
+ struct stm32_gpio * gpio = (struct stm32_gpio * )cfg -> base ;
118
331
119
332
if (access_op != GPIO_ACCESS_BY_PIN ) {
120
333
return - ENOTSUP ;
121
334
}
122
335
123
- * value = stm32_gpio_get ( cfg -> base , pin );
336
+ * value = ( gpio -> idr >> pin ) & 0x1 ;
124
337
125
338
return 0 ;
126
339
}
0 commit comments