• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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