1 /*!
2     \file    gd32f4xx_gpio.c
3     \brief   GPIO driver
4 
5     \version 2016-08-15, V1.0.0, firmware for GD32F4xx
6     \version 2018-12-12, V2.0.0, firmware for GD32F4xx
7     \version 2020-09-30, V2.1.0, firmware for GD32F4xx
8     \version 2022-03-09, V3.0.0, firmware for GD32F4xx
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 #include "gd32f4xx_gpio.h"
39 
40 /*!
41     \brief      reset GPIO port
42     \param[in]  gpio_periph: GPIO port
43                 only one parameter can be selected which is shown as below:
44       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
45     \param[out] none
46     \retval     none
47 */
gpio_deinit(uint32_t gpio_periph)48 void gpio_deinit(uint32_t gpio_periph)
49 {
50     switch(gpio_periph) {
51     case GPIOA:
52         /* reset GPIOA */
53         rcu_periph_reset_enable(RCU_GPIOARST);
54         rcu_periph_reset_disable(RCU_GPIOARST);
55         break;
56     case GPIOB:
57         /* reset GPIOB */
58         rcu_periph_reset_enable(RCU_GPIOBRST);
59         rcu_periph_reset_disable(RCU_GPIOBRST);
60         break;
61     case GPIOC:
62         /* reset GPIOC */
63         rcu_periph_reset_enable(RCU_GPIOCRST);
64         rcu_periph_reset_disable(RCU_GPIOCRST);
65         break;
66     case GPIOD:
67         /* reset GPIOD */
68         rcu_periph_reset_enable(RCU_GPIODRST);
69         rcu_periph_reset_disable(RCU_GPIODRST);
70         break;
71     case GPIOE:
72         /* reset GPIOE */
73         rcu_periph_reset_enable(RCU_GPIOERST);
74         rcu_periph_reset_disable(RCU_GPIOERST);
75         break;
76     case GPIOF:
77         /* reset GPIOF */
78         rcu_periph_reset_enable(RCU_GPIOFRST);
79         rcu_periph_reset_disable(RCU_GPIOFRST);
80         break;
81     case GPIOG:
82         /* reset GPIOG */
83         rcu_periph_reset_enable(RCU_GPIOGRST);
84         rcu_periph_reset_disable(RCU_GPIOGRST);
85         break;
86     case GPIOH:
87         /* reset GPIOH */
88         rcu_periph_reset_enable(RCU_GPIOHRST);
89         rcu_periph_reset_disable(RCU_GPIOHRST);
90         break;
91     case GPIOI:
92         /* reset GPIOI */
93         rcu_periph_reset_enable(RCU_GPIOIRST);
94         rcu_periph_reset_disable(RCU_GPIOIRST);
95         break;
96     default:
97         break;
98     }
99 }
100 
101 /*!
102     \brief      set GPIO mode
103     \param[in]  gpio_periph: GPIO port
104                 only one parameter can be selected which is shown as below:
105       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
106     \param[in]  mode: GPIO pin mode
107       \arg        GPIO_MODE_INPUT: input mode
108       \arg        GPIO_MODE_OUTPUT: output mode
109       \arg        GPIO_MODE_AF: alternate function mode
110       \arg        GPIO_MODE_ANALOG: analog mode
111     \param[in]  pull_up_down: GPIO pin with pull-up or pull-down resistor
112       \arg        GPIO_PUPD_NONE: floating mode, no pull-up and pull-down resistors
113       \arg        GPIO_PUPD_PULLUP: with pull-up resistor
114       \arg        GPIO_PUPD_PULLDOWN:with pull-down resistor
115     \param[in]  pin: GPIO pin
116                 one or more parameters can be selected which are shown as below:
117       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
118     \param[out] none
119     \retval     none
120 */
gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint32_t pin)121 void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin)
122 {
123     uint16_t i;
124     uint32_t ctl, pupd;
125 
126     ctl = GPIO_CTL(gpio_periph);
127     pupd = GPIO_PUD(gpio_periph);
128 
129     for(i = 0U; i < 16U; i++) {
130         if((1U << i) & pin) {
131             /* clear the specified pin mode bits */
132             ctl &= ~GPIO_MODE_MASK(i);
133             /* set the specified pin mode bits */
134             ctl |= GPIO_MODE_SET(i, mode);
135 
136             /* clear the specified pin pupd bits */
137             pupd &= ~GPIO_PUPD_MASK(i);
138             /* set the specified pin pupd bits */
139             pupd |= GPIO_PUPD_SET(i, pull_up_down);
140         }
141     }
142 
143     GPIO_CTL(gpio_periph) = ctl;
144     GPIO_PUD(gpio_periph) = pupd;
145 }
146 
147 /*!
148     \brief      set GPIO output type and speed
149     \param[in]  gpio_periph: GPIO port
150                 only one parameter can be selected which is shown as below:
151       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
152     \param[in]  otype: GPIO pin output mode
153       \arg        GPIO_OTYPE_PP: push pull mode
154       \arg        GPIO_OTYPE_OD: open drain mode
155     \param[in]  speed: GPIO pin output max speed
156       \arg        GPIO_OSPEED_2MHZ: output max speed 2MHz
157       \arg        GPIO_OSPEED_25MHZ: output max speed 25MHz
158       \arg        GPIO_OSPEED_50MHZ: output max speed 50MHz
159       \arg        GPIO_OSPEED_MAX: output max speed more than 50MHz
160     \param[in]  pin: GPIO pin
161                 one or more parameters can be selected which are shown as below:
162       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
163     \param[out] none
164     \retval     none
165 */
gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,uint32_t pin)166 void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)
167 {
168     uint16_t i;
169     uint32_t ospeedr;
170 
171     if(GPIO_OTYPE_OD == otype) {
172         GPIO_OMODE(gpio_periph) |= (uint32_t)pin;
173     } else {
174         GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin);
175     }
176 
177     /* get the specified pin output speed bits value */
178     ospeedr = GPIO_OSPD(gpio_periph);
179 
180     for(i = 0U; i < 16U; i++) {
181         if((1U << i) & pin) {
182             /* clear the specified pin output speed bits */
183             ospeedr &= ~GPIO_OSPEED_MASK(i);
184             /* set the specified pin output speed bits */
185             ospeedr |= GPIO_OSPEED_SET(i, speed);
186         }
187     }
188     GPIO_OSPD(gpio_periph) = ospeedr;
189 }
190 
191 /*!
192     \brief    set GPIO pin bit
193     \param[in]  gpio_periph: GPIO port
194                 only one parameter can be selected which is shown as below:
195       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
196     \param[in]  pin: GPIO pin
197                 one or more parameters can be selected which are shown as below:
198       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
199     \param[out] none
200     \retval     none
201 */
gpio_bit_set(uint32_t gpio_periph,uint32_t pin)202 void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
203 {
204     GPIO_BOP(gpio_periph) = (uint32_t)pin;
205 }
206 
207 /*!
208     \brief      reset GPIO pin bit
209     \param[in]  gpio_periph: GPIO port
210                 only one parameter can be selected which is shown as below:
211       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
212     \param[in]  pin: GPIO pin
213                 one or more parameters can be selected which are shown as below:
214       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
215     \param[out] none
216     \retval     none
217 */
gpio_bit_reset(uint32_t gpio_periph,uint32_t pin)218 void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
219 {
220     GPIO_BC(gpio_periph) = (uint32_t)pin;
221 }
222 
223 /*!
224     \brief      write data to the specified GPIO pin
225     \param[in]  gpio_periph: GPIO port
226                 only one parameter can be selected which is shown as below:
227       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
228     \param[in]  pin: GPIO pin
229                 one or more parameters can be selected which are shown as below:
230       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
231     \param[in]  bit_value: SET or RESET
232       \arg        RESET: clear the port pin
233       \arg        SET: set the port pin
234     \param[out] none
235     \retval     none
236 */
gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value)237 void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
238 {
239     if(RESET != bit_value) {
240         GPIO_BOP(gpio_periph) = (uint32_t)pin;
241     } else {
242         GPIO_BC(gpio_periph) = (uint32_t)pin;
243     }
244 }
245 
246 /*!
247     \brief      write data to the specified GPIO port
248     \param[in]  gpio_periph: GPIO port
249                 only one parameter can be selected which is shown as below:
250       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
251     \param[in]  data: specify the value to be written to the port output control register
252     \param[out] none
253     \retval     none
254 */
gpio_port_write(uint32_t gpio_periph,uint16_t data)255 void gpio_port_write(uint32_t gpio_periph, uint16_t data)
256 {
257     GPIO_OCTL(gpio_periph) = (uint32_t)data;
258 }
259 
260 /*!
261     \brief      get GPIO pin input status
262     \param[in]  gpio_periph: GPIO port
263                 only one parameter can be selected which is shown as below:
264       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
265     \param[in]  pin: GPIO pin
266                 one or more parameters can be selected which are shown as below:
267       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
268     \param[out] none
269     \retval     input status of GPIO pin: SET or RESET
270 */
gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)271 FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
272 {
273     if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph) & (pin))) {
274         return SET;
275     } else {
276         return RESET;
277     }
278 }
279 
280 /*!
281     \brief      get GPIO all pins input status
282     \param[in]  gpio_periph: GPIO port
283                 only one parameter can be selected which is shown as below:
284       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
285     \param[out] none
286     \retval     input status of GPIO all pins
287 */
gpio_input_port_get(uint32_t gpio_periph)288 uint16_t gpio_input_port_get(uint32_t gpio_periph)
289 {
290     return ((uint16_t)GPIO_ISTAT(gpio_periph));
291 }
292 
293 /*!
294     \brief      get GPIO pin output status
295     \param[in]  gpio_periph: GPIO port
296                 only one parameter can be selected which is shown as below:
297       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
298     \param[in]  pin: GPIO pin
299                 one or more parameters can be selected which are shown as below:
300       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
301     \param[out] none
302     \retval     output status of GPIO pin: SET or RESET
303 */
gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin)304 FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin)
305 {
306     if((uint32_t)RESET != (GPIO_OCTL(gpio_periph) & (pin))) {
307         return SET;
308     } else {
309         return RESET;
310     }
311 }
312 
313 /*!
314     \brief      get GPIO port output status
315     \param[in]  gpio_periph: GPIO port
316                 only one parameter can be selected which is shown as below:
317       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
318     \param[out] none
319     \retval     output status of GPIO all pins
320 */
gpio_output_port_get(uint32_t gpio_periph)321 uint16_t gpio_output_port_get(uint32_t gpio_periph)
322 {
323     return ((uint16_t)GPIO_OCTL(gpio_periph));
324 }
325 
326 /*!
327     \brief      set GPIO alternate function
328     \param[in]  gpio_periph: GPIO port
329                 only one parameter can be selected which is shown as below:
330       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
331     \param[in]  alt_func_num: GPIO pin af function
332       \arg        GPIO_AF_0: SYSTEM
333       \arg        GPIO_AF_1: TIMER0, TIMER1
334       \arg        GPIO_AF_2: TIMER2, TIMER3, TIMER4
335       \arg        GPIO_AF_3: TIMER7, TIMER8, TIMER9, TIMER10
336       \arg        GPIO_AF_4: I2C0, I2C1, I2C2
337       \arg        GPIO_AF_5: SPI0, SPI1, SPI2, SPI3, SPI4, SPI5
338       \arg        GPIO_AF_6: SPI2, SPI3, SPI4
339       \arg        GPIO_AF_7: USART0, USART1, USART2, SPI1, SPI2
340       \arg        GPIO_AF_8: UART3, UART4, USART5, UART6, UART7
341       \arg        GPIO_AF_9: CAN0, CAN1, TLI, TIMER11, TIMER12, TIMER13, I2C1, I2C2, CTC
342       \arg        GPIO_AF_10: USB_FS, USB_HS
343       \arg        GPIO_AF_11: ENET
344       \arg        GPIO_AF_12: EXMC, SDIO, USB_HS
345       \arg        GPIO_AF_13: DCI
346       \arg        GPIO_AF_14: TLI
347       \arg        GPIO_AF_15: EVENTOUT
348     \param[in]  pin: GPIO pin
349                 one or more parameters can be selected which are shown as below:
350       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
351     \param[out] none
352     \retval     none
353 */
gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin)354 void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin)
355 {
356     uint16_t i;
357     uint32_t afrl, afrh;
358 
359     afrl = GPIO_AFSEL0(gpio_periph);
360     afrh = GPIO_AFSEL1(gpio_periph);
361 
362     for(i = 0U; i < 8U; i++) {
363         if((1U << i) & pin) {
364             /* clear the specified pin alternate function bits */
365             afrl &= ~GPIO_AFR_MASK(i);
366             afrl |= GPIO_AFR_SET(i, alt_func_num);
367         }
368     }
369 
370     for(i = 8U; i < 16U; i++) {
371         if((1U << i) & pin) {
372             /* clear the specified pin alternate function bits */
373             afrh &= ~GPIO_AFR_MASK(i - 8U);
374             afrh |= GPIO_AFR_SET(i - 8U, alt_func_num);
375         }
376     }
377 
378     GPIO_AFSEL0(gpio_periph) = afrl;
379     GPIO_AFSEL1(gpio_periph) = afrh;
380 }
381 
382 /*!
383     \brief      lock GPIO pin bit
384     \param[in]  gpio_periph: GPIO port
385                 only one parameter can be selected which is shown as below:
386       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
387     \param[in]  pin: GPIO pin
388                 one or more parameters can be selected which are shown as below:
389       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
390     \param[out] none
391     \retval     none
392 */
gpio_pin_lock(uint32_t gpio_periph,uint32_t pin)393 void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
394 {
395     uint32_t lock = 0x00010000U;
396     lock |= pin;
397 
398     /* lock key writing sequence: write 1->write 0->write 1->read 0->read 1 */
399     GPIO_LOCK(gpio_periph) = (uint32_t)lock;
400     GPIO_LOCK(gpio_periph) = (uint32_t)pin;
401     GPIO_LOCK(gpio_periph) = (uint32_t)lock;
402     lock = GPIO_LOCK(gpio_periph);
403     lock = GPIO_LOCK(gpio_periph);
404 }
405 
406 /*!
407     \brief      toggle GPIO pin status
408     \param[in]  gpio_periph: GPIO port
409                 only one parameter can be selected which is shown as below:
410       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
411     \param[in]  pin: GPIO pin
412                 one or more parameters can be selected which are shown as below:
413       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
414     \param[out] none
415     \retval     none
416 */
gpio_bit_toggle(uint32_t gpio_periph,uint32_t pin)417 void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin)
418 {
419     GPIO_TG(gpio_periph) = (uint32_t)pin;
420 }
421 
422 /*!
423     \brief      toggle GPIO port status
424     \param[in]  gpio_periph: GPIO port
425                 only one parameter can be selected which is shown as below:
426       \arg        GPIOx(x = A,B,C,D,E,F,G,H,I)
427 
428     \param[out] none
429     \retval     none
430 */
gpio_port_toggle(uint32_t gpio_periph)431 void gpio_port_toggle(uint32_t gpio_periph)
432 {
433     GPIO_TG(gpio_periph) = 0x0000FFFFU;
434 }
435