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