1 /*!
2     \file    gd32a50x_gpio.c
3     \brief   GPIO driver
4 
5     \version 2022-01-30, V1.0.0, firmware for GD32A50x
6 */
7 
8 /*
9     Copyright (c) 2022, 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 "gd32a50x_gpio.h"
36 
37 /*!
38     \brief      reset GPIO port
39     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
40                 only one parameter can be selected which is shown as below:
41       \arg        GPIOx(x = A,B,C,D,E,F)
42     \param[out] none
43     \retval     none
44 */
gpio_deinit(uint32_t gpio_periph)45 void gpio_deinit(uint32_t gpio_periph)
46 {
47     switch(gpio_periph){
48     case GPIOA:
49         /* reset GPIOA */
50         rcu_periph_reset_enable(RCU_GPIOARST);
51         rcu_periph_reset_disable(RCU_GPIOARST);
52         break;
53     case GPIOB:
54         /* reset GPIOB */
55         rcu_periph_reset_enable(RCU_GPIOBRST);
56         rcu_periph_reset_disable(RCU_GPIOBRST);
57         break;
58     case GPIOC:
59         /* reset GPIOC */
60         rcu_periph_reset_enable(RCU_GPIOCRST);
61         rcu_periph_reset_disable(RCU_GPIOCRST);
62         break;
63     case GPIOD:
64         /* reset GPIOD */
65         rcu_periph_reset_enable(RCU_GPIODRST);
66         rcu_periph_reset_disable(RCU_GPIODRST);
67         break;
68     case GPIOE:
69         /* reset GPIOE */
70         rcu_periph_reset_enable(RCU_GPIOERST);
71         rcu_periph_reset_disable(RCU_GPIOERST);
72         break;
73     case GPIOF:
74         /* reset GPIOF */
75         rcu_periph_reset_enable(RCU_GPIOFRST);
76         rcu_periph_reset_disable(RCU_GPIOFRST);
77         break;
78     default:
79         break;
80     }
81 }
82 
83 /*!
84     \brief      set GPIO mode
85     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
86                 only one parameter can be selected which is shown as below:
87       \arg        GPIOx(x = A,B,C,D,E,F)
88     \param[in]  mode: gpio pin mode
89                 only one parameter can be selected which is shown as below:
90       \arg        GPIO_MODE_INPUT: input mode
91       \arg        GPIO_MODE_OUTPUT: output mode
92       \arg        GPIO_MODE_AF: alternate function mode
93       \arg        GPIO_MODE_ANALOG: analog mode
94     \param[in]  pull_up_down: gpio pin with pull-up or pull-down resistor
95                 only one parameter can be selected which is shown as below:
96       \arg        GPIO_PUPD_NONE: floating mode, no pull-up and pull-down resistors
97       \arg        GPIO_PUPD_PULLUP: with pull-up resistor
98       \arg        GPIO_PUPD_PULLDOWN:with pull-down resistor
99     \param[in]  pin: GPIO pin
100                 one or more parameters can be selected which are shown as below:
101       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
102     \param[out] none
103     \retval     none
104 */
gpio_mode_set(uint32_t gpio_periph,uint32_t mode,uint32_t pull_up_down,uint32_t pin)105 void gpio_mode_set(uint32_t gpio_periph, uint32_t mode, uint32_t pull_up_down, uint32_t pin)
106 {
107     uint16_t i;
108     uint32_t ctl, pupd;
109 
110     ctl = GPIO_CTL(gpio_periph);
111     pupd = GPIO_PUD(gpio_periph);
112 
113     for(i = 0U;i < 16U;i++){
114         if((((uint32_t)1U << i)) & pin){
115             /* clear the specified pin mode bits */
116             ctl &= ~GPIO_MODE_MASK(i);
117             /* set the specified pin mode bits */
118             ctl |= GPIO_MODE_SET(i, mode);
119 
120             /* clear the specified pin pupd bits */
121             pupd &= ~GPIO_PUPD_MASK(i);
122             /* set the specified pin pupd bits */
123             pupd |= GPIO_PUPD_SET(i, pull_up_down);
124         }
125     }
126 
127     GPIO_CTL(gpio_periph) = ctl;
128     GPIO_PUD(gpio_periph) = pupd;
129 }
130 
131 /*!
132     \brief      set GPIO output type and speed
133     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
134                 only one parameter can be selected which is shown as below:
135       \arg        GPIOx(x = A,B,C,D,E,F)
136     \param[in]  otype: gpio pin output mode
137                 only one parameter can be selected which is shown as below:
138       \arg        GPIO_OTYPE_PP: push pull mode
139       \arg        GPIO_OTYPE_OD: open drain mode
140     \param[in]  speed: gpio pin output max speed
141                 only one parameter can be selected which is shown as below:
142       \arg        GPIO_OSPEED_2MHZ: output max speed 2MHz
143       \arg        GPIO_OSPEED_10MHZ: output max speed 10MHz
144       \arg        GPIO_OSPEED_50MHZ: output max speed 50MHz
145     \param[in]  pin: GPIO pin
146                 one or more parameters can be selected which are shown as below:
147       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
148     \param[out] none
149     \retval     none
150 */
gpio_output_options_set(uint32_t gpio_periph,uint8_t otype,uint32_t speed,uint32_t pin)151 void gpio_output_options_set(uint32_t gpio_periph, uint8_t otype, uint32_t speed, uint32_t pin)
152 {
153     uint16_t i;
154     uint32_t ospeed;
155 
156     if(GPIO_OTYPE_OD == otype){
157         GPIO_OMODE(gpio_periph) |= (uint32_t)pin;
158     }else{
159         GPIO_OMODE(gpio_periph) &= (uint32_t)(~pin);
160     }
161 
162     /* get the specified pin output speed bits value */
163     ospeed = GPIO_OSPD(gpio_periph);
164 
165     for(i = 0U;i < 16U;i++){
166         if(((uint32_t)1U << i) & pin){
167             /* clear the specified pin output speed bits */
168             ospeed &= ~GPIO_OSPEED_MASK(i);
169             /* set the specified pin output speed bits */
170             ospeed |= GPIO_OSPEED_SET(i,speed);
171         }
172     }
173     GPIO_OSPD(gpio_periph) = ospeed;
174 }
175 
176 /*!
177     \brief      set GPIO pin bit
178     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
179                 only one parameter can be selected which is shown as below:
180       \arg        GPIOx(x = A,B,C,D,E,F)
181     \param[in]  pin: GPIO pin
182                 one or more parameters can be selected which are shown as below:
183       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
184     \param[out] none
185     \retval     none
186 */
gpio_bit_set(uint32_t gpio_periph,uint32_t pin)187 void gpio_bit_set(uint32_t gpio_periph, uint32_t pin)
188 {
189     GPIO_BOP(gpio_periph) = (uint32_t)pin;
190 }
191 
192 /*!
193     \brief      reset GPIO pin bit
194     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
195                 only one parameter can be selected which is shown as below:
196       \arg        GPIOx(x = A,B,C,D,E,F)
197     \param[in]  pin: GPIO pin
198                 one or more parameters can be selected which are shown as below:
199       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
200     \param[out] none
201     \retval     none
202 */
gpio_bit_reset(uint32_t gpio_periph,uint32_t pin)203 void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin)
204 {
205     GPIO_BC(gpio_periph) = (uint32_t)pin;
206 }
207 
208 /*!
209     \brief      write data to the specified GPIO pin
210     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
211                 only one parameter can be selected which is shown as below:
212       \arg        GPIOx(x = A,B,C,D,E,F)
213     \param[in]  pin: GPIO pin
214                 one or more parameters can be selected which are shown as below:
215       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
216     \param[in]  bit_value: SET or RESET
217                 only one parameter can be selected which is shown as below:
218       \arg        RESET: clear the port pin
219       \arg        SET: set the port pin
220     \param[out] none
221     \retval     none
222 */
gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value)223 void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value)
224 {
225     if(RESET != bit_value){
226         GPIO_BOP(gpio_periph) = (uint32_t)pin;
227     }else{
228         GPIO_BC(gpio_periph) = (uint32_t)pin;
229     }
230 }
231 
232 /*!
233     \brief      write data to the specified GPIO port
234     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
235                 only one parameter can be selected which is shown as below:
236       \arg        GPIOx(x = A,B,C,D,E,F)
237     \param[in]  data: specify the value to be written to the port output control register
238     \param[out] none
239     \retval     none
240 */
gpio_port_write(uint32_t gpio_periph,uint16_t data)241 void gpio_port_write(uint32_t gpio_periph, uint16_t data)
242 {
243     GPIO_OCTL(gpio_periph) = (uint32_t)data;
244 }
245 
246 /*!
247     \brief      get GPIO pin input status
248     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
249                 only one parameter can be selected which is shown as below:
250       \arg        GPIOx(x = A,B,C,D,E,F)
251     \param[in]  pin: GPIO pin
252                 one or more parameters can be selected which are shown as below:
253       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
254     \param[out] none
255     \retval     SET or RESET
256 */
gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin)257 FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin)
258 {
259     if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){
260         return SET;
261     }else{
262         return RESET;
263     }
264 }
265 
266 /*!
267     \brief      get GPIO port input status
268     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
269                 only one parameter can be selected which is shown as below:
270       \arg        GPIOx(x = A,B,C,D,E,F)
271     \param[out] none
272     \retval     state of GPIO all pins
273 */
gpio_input_port_get(uint32_t gpio_periph)274 uint16_t gpio_input_port_get(uint32_t gpio_periph)
275 {
276     return ((uint16_t)GPIO_ISTAT(gpio_periph));
277 }
278 
279 /*!
280     \brief      get GPIO pin output status
281     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
282                 only one parameter can be selected which is shown as below:
283       \arg        GPIOx(x = A,B,C,D,E,F)
284     \param[in]  pin: GPIO pin
285                 one or more parameters 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     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,F)
302                 only one parameter can be selected which is shown as below:
303       \arg        GPIOx(x = A,B,C,D,E,F)
304     \param[out] none
305     \retval     state of GPIO all pins
306 */
gpio_output_port_get(uint32_t gpio_periph)307 uint16_t gpio_output_port_get(uint32_t gpio_periph)
308 {
309     return ((uint16_t)GPIO_OCTL(gpio_periph));
310 }
311 
312 /*!
313     \brief      set GPIO alternate function
314     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
315                 only one parameter can be selected which is shown as below:
316       \arg        GPIOx(x = A,B,C,D,E,F)
317     \param[in]  alt_func_num: GPIO pin af function, please refer to specific device datasheet
318                 only one parameter can be selected which is shown as below:
319       \arg        GPIO_AF_0: SYSTEM
320       \arg        GPIO_AF_1: TIMER0, TIMER1, TIMER7, TIMER19, TIMER20
321       \arg        GPIO_AF_2: TIMER0, TIMER1, TIMER7, TIMER19, TIMER20
322       \arg        GPIO_AF_3: TIMER7, TIMER19, I2C0
323       \arg        GPIO_AF_4: SPI0, SPI1, I2S1, USART1
324       \arg        GPIO_AF_5: USART0, USART2, MFCOM, SPI1, I2C1
325       \arg        GPIO_AF_6: CAN0, CAN1, MFCOM, TRIGSEL
326       \arg        GPIO_AF_7: TRIGSEL, CMP, MFCOM
327       \arg        GPIO_AF_8:
328       \arg        GPIO_AF_9: EVENTOUT
329     \param[in]  pin: GPIO pin
330                 one or more parameters can be selected which are shown as below:
331       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
332     \param[out] none
333     \retval     none
334 */
gpio_af_set(uint32_t gpio_periph,uint32_t alt_func_num,uint32_t pin)335 void gpio_af_set(uint32_t gpio_periph, uint32_t alt_func_num, uint32_t pin)
336 {
337     uint16_t i;
338     uint32_t afrl, afrh;
339 
340     afrl = GPIO_AFSEL0(gpio_periph);
341     afrh = GPIO_AFSEL1(gpio_periph);
342 
343     for(i = 0U;i < 8U;i++){
344         if(((uint32_t)1U << i) & pin){
345             /* clear the specified pin alternate function bits */
346             afrl &= ~GPIO_AFR_MASK(i);
347             afrl |= GPIO_AFR_SET(i,alt_func_num);
348         }
349     }
350 
351     for(i = 8U;i < 16U;i++){
352         if(((uint32_t)1U << i) & pin){
353             /* clear the specified pin alternate function bits */
354             afrh &= ~GPIO_AFR_MASK(i - 8U);
355             afrh |= GPIO_AFR_SET(i - 8U,alt_func_num);
356         }
357     }
358 
359     GPIO_AFSEL0(gpio_periph) = afrl;
360     GPIO_AFSEL1(gpio_periph) = afrh;
361 }
362 
363 /*!
364     \brief      lock GPIO pin bit
365     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
366                 only one parameter can be selected which is shown as below:
367       \arg        GPIOx(x = A,B,C,D,E,F)
368     \param[in]  pin: GPIO pin
369                 one or more parameters can be selected which are shown as below:
370       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
371     \param[out] none
372     \retval     none
373 */
gpio_pin_lock(uint32_t gpio_periph,uint32_t pin)374 void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin)
375 {
376     uint32_t lock = 0x00010000U;
377     lock |= pin;
378 
379     /* lock key writing sequence: write 1->write 0->write 1->read 0->read 1 */
380     GPIO_LOCK(gpio_periph) = (uint32_t)lock;
381     GPIO_LOCK(gpio_periph) = (uint32_t)pin;
382     GPIO_LOCK(gpio_periph) = (uint32_t)lock;
383     lock = GPIO_LOCK(gpio_periph);
384     lock = GPIO_LOCK(gpio_periph);
385 }
386 
387 /*!
388     \brief      toggle GPIO pin status
389     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
390                 only one parameter can be selected which is shown as below:
391       \arg        GPIOx(x = A,B,C,D,E,F)
392     \param[in]  pin: GPIO pin
393                 one or more parameters can be selected which are shown as below:
394       \arg        GPIO_PIN_x(x=0..15), GPIO_PIN_ALL
395     \param[out] none
396     \retval     none
397 */
gpio_bit_toggle(uint32_t gpio_periph,uint32_t pin)398 void gpio_bit_toggle(uint32_t gpio_periph, uint32_t pin)
399 {
400     GPIO_TG(gpio_periph) = (uint32_t)pin;
401 }
402 
403 /*!
404     \brief      toggle GPIO port status
405     \param[in]  gpio_periph: GPIOx(x = A,B,C,D,E,F)
406                 only one parameter can be selected which is shown as below:
407       \arg        GPIOx(x = A,B,C,D,E,F)
408     \param[out] none
409     \retval     none
410 */
gpio_port_toggle(uint32_t gpio_periph)411 void gpio_port_toggle(uint32_t gpio_periph)
412 {
413     GPIO_TG(gpio_periph) = 0x0000FFFFU;
414 }
415