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