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