1 /*!
2 \file gd32vf103_gpio.c
3 \brief GPIO driver
4
5 \version 2019-06-05, V1.0.0, firmware for GD32VF103
6 \version 2020-08-04, V1.1.0, firmware for GD32VF103
7 */
8
9 /*
10 Copyright (c) 2020, GigaDevice Semiconductor Inc.
11
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14
15 1. Redistributions of source code must retain the above copyright notice, this
16 list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright notice,
18 this list of conditions and the following disclaimer in the documentation
19 and/or other materials provided with the distribution.
20 3. Neither the name of the copyright holder nor the names of its contributors
21 may be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35
36 #include "gd32vf103_gpio.h"
37
38 #define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/
39 #define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */
40 #define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */
41 #define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */
42 #define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */
43 #define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */
44 #define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */
45 #define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */
46 #define GPIO_OUTPUT_PORT_OFFSET ((uint32_t)4U) /*!< GPIO event output port offset*/
47
48 /*!
49 \brief reset GPIO port
50 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
51 \param[out] none
52 \retval none
53 */
gpio_deinit(uint32_t gpio_periph)54 void gpio_deinit(uint32_t gpio_periph)
55 {
56 switch (gpio_periph) {
57 case GPIOA:
58 /* reset GPIOA */
59 rcu_periph_reset_enable(RCU_GPIOARST);
60 rcu_periph_reset_disable(RCU_GPIOARST);
61 break;
62 case GPIOB:
63 /* reset GPIOB */
64 rcu_periph_reset_enable(RCU_GPIOBRST);
65 rcu_periph_reset_disable(RCU_GPIOBRST);
66 break;
67 case GPIOC:
68 /* reset GPIOC */
69 rcu_periph_reset_enable(RCU_GPIOCRST);
70 rcu_periph_reset_disable(RCU_GPIOCRST);
71 break;
72 case GPIOD:
73 /* reset GPIOD */
74 rcu_periph_reset_enable(RCU_GPIODRST);
75 rcu_periph_reset_disable(RCU_GPIODRST);
76 break;
77 case GPIOE:
78 /* reset GPIOE */
79 rcu_periph_reset_enable(RCU_GPIOERST);
80 rcu_periph_reset_disable(RCU_GPIOERST);
81 break;
82 default:
83 break;
84 }
85 }
86
87 /*!
88 \brief reset alternate function I/O(AFIO)
89 \param[in] none
90 \param[out] none
91 \retval none
92 */
gpio_afio_deinit(void)93 void gpio_afio_deinit(void)
94 {
95 rcu_periph_reset_enable(RCU_AFRST);
96 rcu_periph_reset_disable(RCU_AFRST);
97 }
98
99 /*!
100 \brief GPIO parameter initialization
101 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
102 \param[in] mode: gpio pin mode
103 only one parameter can be selected which is shown as below:
104 \arg GPIO_MODE_AIN: analog input mode
105 \arg GPIO_MODE_IN_FLOATING: floating input mode
106 \arg GPIO_MODE_IPD: pull-down input mode
107 \arg GPIO_MODE_IPU: pull-up input mode
108 \arg GPIO_MODE_OUT_OD: GPIO output with open-drain
109 \arg GPIO_MODE_OUT_PP: GPIO output with push-pull
110 \arg GPIO_MODE_AF_OD: AFIO output with open-drain
111 \arg GPIO_MODE_AF_PP: AFIO output with push-pull
112 \param[in] speed: gpio output max speed value
113 only one parameter can be selected which is shown as below:
114 \arg GPIO_OSPEED_10MHZ: output max speed 10MHz
115 \arg GPIO_OSPEED_2MHZ: output max speed 2MHz
116 \arg GPIO_OSPEED_50MHZ: output max speed 50MHz
117 \param[in] pin: GPIO pin
118 one or more parameters can be selected which are shown as below:
119 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
120
121 \param[out] none
122 \retval none
123 */
gpio_init(uint32_t gpio_periph,uint32_t mode,uint32_t speed,uint32_t pin)124 void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed,
125 uint32_t pin)
126 {
127 uint16_t i;
128 uint32_t temp_mode = 0U;
129 uint32_t reg = 0U;
130
131 /* GPIO mode configuration */
132 temp_mode = (uint32_t) (mode & ((uint32_t) 0x0FU));
133
134 /* GPIO speed configuration */
135 if (((uint32_t) 0x00U) != ((uint32_t) mode & ((uint32_t) 0x10U))) {
136 /* output mode max speed:10MHz,2MHz,50MHz */
137 temp_mode |= (uint32_t) speed;
138 }
139
140 /* configure the eight low port pins with GPIO_CTL0 */
141 for (i = 0U; i < 8U; i++) {
142 if ((1U << i) & pin) {
143 reg = GPIO_CTL0(gpio_periph);
144
145 /* clear the specified pin mode bits */
146 reg &= ~GPIO_MODE_MASK(i);
147 /* set the specified pin mode bits */
148 reg |= GPIO_MODE_SET(i, temp_mode);
149
150 /* set IPD or IPU */
151 if (GPIO_MODE_IPD == mode) {
152 /* reset the corresponding OCTL bit */
153 GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin);
154 } else {
155 /* set the corresponding OCTL bit */
156 if (GPIO_MODE_IPU == mode) {
157 GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin);
158 }
159 }
160 /* set GPIO_CTL0 register */
161 GPIO_CTL0(gpio_periph) = reg;
162 }
163 }
164 /* configure the eight high port pins with GPIO_CTL1 */
165 for (i = 8U; i < 16U; i++) {
166 if ((1U << i) & pin) {
167 reg = GPIO_CTL1(gpio_periph);
168
169 /* clear the specified pin mode bits */
170 reg &= ~GPIO_MODE_MASK(i - 8U);
171 /* set the specified pin mode bits */
172 reg |= GPIO_MODE_SET(i - 8U, temp_mode);
173
174 /* set IPD or IPU */
175 if (GPIO_MODE_IPD == mode) {
176 /* reset the corresponding OCTL bit */
177 GPIO_BC(gpio_periph) = (uint32_t) ((1U << i) & pin);
178 } else {
179 /* set the corresponding OCTL bit */
180 if (GPIO_MODE_IPU == mode) {
181 GPIO_BOP(gpio_periph) = (uint32_t) ((1U << i) & pin);
182 }
183 }
184 /* set GPIO_CTL1 register */
185 GPIO_CTL1(gpio_periph) = reg;
186 }
187 }
188 }
189
190 /*!
191 \brief set GPIO pin
192 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
193 \param[in] pin: GPIO pin
194 one or more parameters can be selected which are shown as below:
195 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
196 \param[out] none
197 \retval none
198 */
gpio_bit_set(uint32_t gpio_periph,uint32_t pin)199 void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
200 {
201 GPIO_BOP(gpio_periph) = (uint32_t) pin;
202 }
203
204 /*!
205 \brief reset GPIO pin
206 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
207 \param[in] pin: GPIO pin
208 one or more parameters can be selected which are shown as below:
209 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
210 \param[out] none
211 \retval none
212 */
gpio_bit_reset(uint32_t gpio_periph,uint32_t pin)213 void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
214 {
215 GPIO_BC(gpio_periph) = (uint32_t) pin;
216 }
217
218 /*!
219 \brief write data to the specified GPIO pin
220 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
221 \param[in] pin: GPIO pin
222 one or more parameters can be selected which are shown as below:
223 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
224 \param[in] bit_value: SET or RESET
225 only one parameter can be selected which is shown as below:
226 \arg RESET: clear the port pin
227 \arg SET: set the port pin
228 \param[out] none
229 \retval none
230 */
gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value)231 void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
232 {
233 if (RESET != bit_value) {
234 GPIO_BOP(gpio_periph) = (uint32_t) pin;
235 } else {
236 GPIO_BC(gpio_periph) = (uint32_t) pin;
237 }
238 }
239
240 /*!
241 \brief write data to the specified GPIO port
242 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
243 \param[in] data: specify the value to be written to the port output data register
244 \param[out] none
245 \retval none
246 */
gpio_port_write(uint32_t gpio_periph,uint16_t data)247 void gpio_port_write(uint32_t gpio_periph, uint16_t data)
248 {
249 GPIO_OCTL(gpio_periph) = (uint32_t) data;
250 }
251
252 /*!
253 \brief get GPIO pin input status
254 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
255 \param[in] pin: GPIO pin
256 only one parameter can be selected which are shown as below:
257 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
258 \param[out] none
259 \retval input status of gpio pin: SET or RESET
260 */
gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)261 FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
262 {
263 if ((uint32_t) RESET != (GPIO_ISTAT(gpio_periph) & (pin))) {
264 return SET;
265 } else {
266 return RESET;
267 }
268 }
269
270 /*!
271 \brief get GPIO port input status
272 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
273 \param[out] none
274 \retval input status of gpio all pins
275 */
gpio_input_port_get(uint32_t gpio_periph)276 uint16_t gpio_input_port_get(uint32_t gpio_periph)
277 {
278 return (uint16_t) (GPIO_ISTAT(gpio_periph));
279 }
280
281 /*!
282 \brief get GPIO pin output status
283 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
284 \param[in] pin: GPIO pin
285 only one parameter can be selected which are shown as below:
286 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
287 \param[out] none
288 \retval output status of gpio pin: SET or RESET
289 */
gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin)290 FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
291 {
292 if ((uint32_t) RESET != (GPIO_OCTL(gpio_periph) & (pin))) {
293 return SET;
294 } else {
295 return RESET;
296 }
297 }
298
299 /*!
300 \brief get GPIO port output status
301 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
302 \param[out] none
303 \retval output status of gpio all pins
304 */
gpio_output_port_get(uint32_t gpio_periph)305 uint16_t gpio_output_port_get(uint32_t gpio_periph)
306 {
307 return ((uint16_t) GPIO_OCTL(gpio_periph));
308 }
309
310 /*!
311 \brief configure GPIO pin remap
312 \param[in] gpio_remap: select the pin to remap
313 only one parameter can be selected which are shown as below:
314 \arg GPIO_SPI0_REMAP: SPI0 remapping
315 \arg GPIO_I2C0_REMAP: I2C0 remapping
316 \arg GPIO_USART0_REMAP: USART0 remapping
317 \arg GPIO_USART1_REMAP: USART1 remapping
318 \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping
319 \arg GPIO_USART2_FULL_REMAP: USART2 full remapping
320 \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping
321 \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping
322 \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping
323 \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping
324 \arg GPIO_TIMER1_FULL_REMAP: TIMER1 full remapping
325 \arg GPIO_TIMER2_PARTIAL_REMAP: TIMER2 partial remapping
326 \arg GPIO_TIMER2_FULL_REMAP: TIMER2 full remapping
327 \arg GPIO_TIMER3_REMAP: TIMER3 remapping
328 \arg GPIO_CAN0_PARTIAL_REMAP: CAN0 partial remapping
329 \arg GPIO_CAN0_FULL_REMAP: CAN0 full remapping
330 \arg GPIO_PD01_REMAP: PD01 remapping
331 \arg GPIO_TIMER4CH3_IREMAP: TIMER4 channel3 internal remapping
332 \arg GPIO_CAN1_REMAP: CAN1 remapping
333 \arg GPIO_SWJ_NONJTRST_REMAP: JTAG-DP,but without NJTRST
334 \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled
335 \arg GPIO_SPI2_REMAP: SPI2 remapping
336 \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping
337 \arg GPIO_EXMC_NADV_REMAP: EXMC_NADV connect/disconnect
338 \param[in] newvalue: ENABLE or DISABLE
339 \param[out] none
340 \retval none
341 */
gpio_pin_remap_config(uint32_t remap,ControlStatus newvalue)342 void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue)
343 {
344 uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U;
345
346 if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
347 /* get AFIO_PCF1 regiter value */
348 temp_reg = AFIO_PCF1;
349 } else {
350 /* get AFIO_PCF0 regiter value */
351 temp_reg = AFIO_PCF0;
352 }
353
354 temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U;
355 remap1 = remap & LSB_16BIT_MASK;
356
357 /* judge pin remap type */
358 if ((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK)
359 == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))) {
360 temp_reg &= PCF_SWJCFG_MASK;
361 AFIO_PCF0 &= PCF_SWJCFG_MASK;
362 } else if (PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)) {
363 remap2 = ((uint32_t) 0x03U) << temp_mask;
364 temp_reg &= ~remap2;
365 temp_reg |= ~PCF_SWJCFG_MASK;
366 } else {
367 temp_reg &= ~(remap1 << ((remap >> 0x15U) * 0x10U));
368 temp_reg |= ~PCF_SWJCFG_MASK;
369 }
370
371 /* set pin remap value */
372 if (DISABLE != newvalue) {
373 temp_reg |= (remap1 << ((remap >> 0x15U) * 0x10U));
374 }
375
376 if (AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) {
377 /* set AFIO_PCF1 regiter value */
378 AFIO_PCF1 = temp_reg;
379 } else {
380 /* set AFIO_PCF0 regiter value */
381 AFIO_PCF0 = temp_reg;
382 }
383 }
384
385 /*!
386 \brief select GPIO pin exti sources
387 \param[in] gpio_outputport: gpio event output port
388 only one parameter can be selected which are shown as below:
389 \arg GPIO_PORT_SOURCE_GPIOA: output port source A
390 \arg GPIO_PORT_SOURCE_GPIOB: output port source B
391 \arg GPIO_PORT_SOURCE_GPIOC: output port source C
392 \arg GPIO_PORT_SOURCE_GPIOD: output port source D
393 \arg GPIO_PORT_SOURCE_GPIOE: output port source E
394 \param[in] gpio_outputpin: GPIO_PIN_SOURCE_x(x=0..15)
395 \param[out] none
396 \retval none
397 */
gpio_exti_source_select(uint8_t output_port,uint8_t output_pin)398 void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin)
399 {
400 uint32_t source = 0U;
401 source = ((uint32_t) 0x0FU)
402 << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK));
403
404 /* select EXTI sources */
405 if (GPIO_PIN_SOURCE_4 > output_pin) {
406 /* select EXTI0/EXTI1/EXTI2/EXTI3 */
407 AFIO_EXTISS0 &= ~source;
408 AFIO_EXTISS0 |= (((uint32_t) output_port)
409 << (AFIO_EXTI_SOURCE_FIELDS
410 * (output_pin & AFIO_EXTI_SOURCE_MASK)));
411 } else if (GPIO_PIN_SOURCE_8 > output_pin) {
412 /* select EXTI4/EXTI5/EXTI6/EXTI7 */
413 AFIO_EXTISS1 &= ~source;
414 AFIO_EXTISS1 |= (((uint32_t) output_port)
415 << (AFIO_EXTI_SOURCE_FIELDS
416 * (output_pin & AFIO_EXTI_SOURCE_MASK)));
417 } else if (GPIO_PIN_SOURCE_12 > output_pin) {
418 /* select EXTI8/EXTI9/EXTI10/EXTI11 */
419 AFIO_EXTISS2 &= ~source;
420 AFIO_EXTISS2 |= (((uint32_t) output_port)
421 << (AFIO_EXTI_SOURCE_FIELDS
422 * (output_pin & AFIO_EXTI_SOURCE_MASK)));
423 } else {
424 /* select EXTI12/EXTI13/EXTI14/EXTI15 */
425 AFIO_EXTISS3 &= ~source;
426 AFIO_EXTISS3 |= (((uint32_t) output_port)
427 << (AFIO_EXTI_SOURCE_FIELDS
428 * (output_pin & AFIO_EXTI_SOURCE_MASK)));
429 }
430 }
431
432 /*!
433 \brief configure GPIO pin event output
434 \param[in] output_port: gpio event output port
435 only one parameter can be selected which are shown as below:
436 \arg GPIO_EVENT_PORT_GPIOA: event output port A
437 \arg GPIO_EVENT_PORT_GPIOB: event output port B
438 \arg GPIO_EVENT_PORT_GPIOC: event output port C
439 \arg GPIO_EVENT_PORT_GPIOD: event output port D
440 \arg GPIO_EVENT_PORT_GPIOE: event output port E
441 \param[in] output_pin:
442 only one parameter can be selected which are shown as below:
443 \arg GPIO_EVENT_PIN_x(x=0..15)
444 \param[out] none
445 \retval none
446 */
gpio_event_output_config(uint8_t output_port,uint8_t output_pin)447 void gpio_event_output_config(uint8_t output_port, uint8_t output_pin)
448 {
449 uint32_t reg = 0U;
450 reg = AFIO_EC;
451
452 /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */
453 reg &= (uint32_t) (~(AFIO_EC_PORT | AFIO_EC_PIN));
454
455 reg |= (uint32_t) ((uint32_t) output_port << GPIO_OUTPUT_PORT_OFFSET);
456 reg |= (uint32_t) output_pin;
457
458 AFIO_EC = reg;
459 }
460
461 /*!
462 \brief enable GPIO pin event output
463 \param[in] none
464 \param[out] none
465 \retval none
466 */
gpio_event_output_enable(void)467 void gpio_event_output_enable(void)
468 {
469 AFIO_EC |= AFIO_EC_EOE;
470 }
471
472 /*!
473 \brief disable GPIO pin event output
474 \param[in] none
475 \param[out] none
476 \retval none
477 */
gpio_event_output_disable(void)478 void gpio_event_output_disable(void)
479 {
480 AFIO_EC &= (uint32_t) (~AFIO_EC_EOE);
481 }
482
483 /*!
484 \brief lock GPIO pin
485 \param[in] gpio_periph: GPIOx(x = A,B,C,D,E)
486 \param[in] pin: GPIO pin
487 one or more parameters can be selected which are shown as below:
488 \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
489 \param[out] none
490 \retval none
491 */
gpio_pin_lock(uint32_t gpio_periph,uint32_t pin)492 void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
493 {
494 uint32_t lock = 0x00010000U;
495 lock |= pin;
496
497 /* lock key writing sequence: write 1 -> write 0 -> write 1 -> read 0 -> read 1 */
498 GPIO_LOCK(gpio_periph) = (uint32_t) lock;
499 GPIO_LOCK(gpio_periph) = (uint32_t) pin;
500 GPIO_LOCK(gpio_periph) = (uint32_t) lock;
501 lock = GPIO_LOCK(gpio_periph);
502 lock = GPIO_LOCK(gpio_periph);
503 }
504