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