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