1 /**
2 *********************************************************************************
3 *
4 * @file ald_gpio.c
5 * @brief GPIO module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the General Purpose Input/Output (GPIO) peripheral:
8 * + Initialization functions
9 * + IO operation functions
10 * + Control functions
11 *
12 * @version V1.0
13 * @date 07 Nov 2017
14 * @author AE Team
15 * @note
16 *
17 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
18 *
19 * SPDX-License-Identifier: Apache-2.0
20 *
21 * Licensed under the Apache License, Version 2.0 (the License); you may
22 * not use this file except in compliance with the License.
23 * You may obtain a copy of the License at
24 *
25 * www.apache.org/licenses/LICENSE-2.0
26 *
27 * Unless required by applicable law or agreed to in writing, software
28 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
29 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30 * See the License for the specific language governing permissions and
31 * limitations under the License.
32 *
33 *********************************************************************************
34 * @verbatim
35 ==============================================================================
36 ##### GPIO Peripheral features #####
37 ==============================================================================
38 [..]
39 Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each
40 port bit of the General Purpose IO (GPIO) Ports, can be individually configured by software
41 in several modes:
42 (+) Input mode
43 (+) Analog mode
44 (+) Output mode
45 (+) External interrupt/event lines
46
47 [..]
48 During and just after reset, the external interrupt lines are not active and
49 the I/O ports are configured Analog mode.
50
51 [..]
52 All GPIO pins have weak internal pull-up and pull-down resistors, which can be
53 activated or not.
54
55 [..]
56 In Output mode, each IO can be configured on open-drain or push-pull
57 type and the Output driver can be selected depending on ODRV register.
58
59 [..]
60 In Input mode, each IO can select filter function.
61
62 [..]
63 Each IO can select TTL or SMIT type.
64
65 [..]
66 Each IO have up to eight functions, user can configure the functions depend
67 on the user's environment.
68
69 [..]
70 Each IO can be locked. Once locked, uesr can only change the output data.
71 Only when the CPU reset to unlock the GPIO port.
72
73 [..]
74 All ports have external interrupt/event capability. To use external interrupt
75 lines, the port must be configured in input mode. All available GPIO pins are
76 connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
77
78 [..]
79 Each input line can be independently configured to select the type (event or interrupt) and
80 the corresponding trigger event (rising or falling). Each line can also masked
81 independently. A pending register maintains the status line of the interrupt requests.
82
83 ==============================================================================
84 ##### How to use this driver #####
85 ==============================================================================
86 [..]
87 (#) Enable the GPIO clock.
88
89 (#) Configure the GPIO pin(s) using ald_gpio_init().
90 (++) Configure the IO mode using "mode" member from gpio_init_t structure
91 (++) Activate Pull-up, Pull-down resistor using "pupd" member from gpio_init_t
92 structure.
93 (++) In Output mode, configured on open-drain or push-pull using "odos"
94 member from gpio_init_t structure.
95 (++) In Output mode, configured output driver using "odrv" member
96 from gpio_init_t structure.
97 (++) In Input mode, configured filter function using "flt" member
98 from gpio_init_t structure.
99 (++) Configured type using "type" member from gpio_init_t structure.
100 (++) Configured functions using "func" member from gpio_init_t structure.
101 (++) Analog mode is required when a pin is to be used as ADC channel
102 or DAC output.
103
104 (#) Configure the GPIO pin(s) using ald_gpio_init_default().
105 (++) Configure GPIO pin using default param:
106 init.mode = GPIO_MODE_OUTPUT;
107 init.odos = GPIO_PUSH_PULL;
108 init.pupd = GPIO_PUSH_UP;
109 init.odrv = GPIO_OUT_DRIVE_NORMAL;
110 init.flt = GPIO_FILTER_DISABLE;
111 init.type = GPIO_TYPE_TTL;
112 init.func = GPIO_FUNC_1;
113
114 (#) In case of external interrupt/event mode selection, user need invoke
115 ald_gpio_exti_init() to configure some param. And then invoke
116 ald_gpio_exti_interrupt_config() to enable/disable external interrupt/event.
117
118 (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
119 mapped to the EXTI line using NVIC_SetPriority() and enable it using
120 NVIC_EnableIRQ().
121
122 (#) To get the level of a pin configured in input mode use GPIO_read_pin().
123
124 (#) To set/reset the level of a pin configured in output mode use
125 ald_gpio_write_pin()/ald_gpio_toggle_pin().
126
127 (#) To lock pin configuration until next reset use ald_gpio_lock_pin().
128
129 (#) Configure external interrupt mode and enable/disable using
130 ald_gpio_exti_interrupt_config().
131
132 (#) Get external interrupt flag status using ald_gpio_exti_get_flag_status().
133
134 (#) Clear pending external interrupt flag status using
135 ald_gpio_exti_clear_flag_status().
136
137 @endverbatim
138 */
139
140 #include "ald_conf.h"
141 #include "ald_gpio.h"
142
143
144 /** @addtogroup ES32FXXX_ALD
145 * @{
146 */
147
148 /** @defgroup GPIO GPIO
149 * @brief GPIO module driver
150 * @{
151 */
152
153 #ifdef ALD_GPIO
154
155 /** @defgroup GPIO_Public_Functions GPIO Public Functions
156 * @{
157 */
158
159 /** @defgroup GPIO_Public_Functions_Group1 Initialization functions
160 * @brief Initialization and Configuration functions
161 *
162 @verbatim
163 ===============================================================================
164 ##### Initialization functions #####
165 ===============================================================================
166 [..]
167 This section provides functions allowing to initialize the GPIOs or external
168 interrupt to be ready for use.
169
170 @endverbatim
171 * @{
172 */
173
174 /**
175 * @brief Initialize the GPIOx peripheral according to the specified
176 * parameters in the gpio_init_t.
177 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
178 * @param pin: The pin which need to initialize.
179 * @param init: Pointer to a gpio_init_t structure that can contains
180 * the configuration information for the specified parameters.
181 * @retval None
182 */
ald_gpio_init(GPIO_TypeDef * GPIOx,uint16_t pin,gpio_init_t * init)183 void ald_gpio_init(GPIO_TypeDef *GPIOx, uint16_t pin, gpio_init_t *init)
184 {
185 uint32_t i, pos, mask, tmp;
186
187 assert_param(IS_GPIO_PORT(GPIOx));
188 assert_param(IS_GPIO_PIN(pin));
189 assert_param(IS_GPIO_MODE(init->mode));
190 assert_param(IS_GPIO_ODOS(init->odos));
191 assert_param(IS_GPIO_PUPD(init->pupd));
192 assert_param(IS_GPIO_ODRV(init->odrv));
193 assert_param(IS_GPIO_FLT(init->flt));
194 assert_param(IS_GPIO_TYPE(init->type));
195 assert_param(IS_GPIO_FUNC(init->func));
196
197 for (i = 0; i < 16; ++i) {
198 if (((pin >> i) & 0x1) == 0)
199 continue;
200
201 /* Get position and 2-bits mask */
202 pos = i << 1;
203 mask = 0x3 << pos;
204
205 /* Set PIN mode */
206 tmp = READ_REG(GPIOx->MODE);
207 tmp &= ~mask;
208 tmp |= (init->mode << pos);
209 WRITE_REG(GPIOx->MODE, tmp);
210
211 /* Set PIN open-drain or push-pull */
212 tmp = READ_REG(GPIOx->ODOS);
213 tmp &= ~mask;
214 tmp |= (init->odos << pos);
215 WRITE_REG(GPIOx->ODOS, tmp);
216
217 /* Set PIN push-up or/and push-down */
218 tmp = READ_REG(GPIOx->PUPD);
219 tmp &= ~mask;
220 tmp |= (init->pupd << pos);
221 WRITE_REG(GPIOx->PUPD, tmp);
222
223 /* Set PIN output driver */
224 tmp = READ_REG(GPIOx->ODRV);
225 tmp &= ~mask;
226 tmp |= (init->odrv << pos);
227 WRITE_REG(GPIOx->ODRV, tmp);
228
229 /* Get position and 1-bit mask */
230 pos = i;
231 mask = 0x1 << pos;
232
233 /* Set PIN filter enable or disable */
234 tmp = READ_REG(GPIOx->FLT);
235 tmp &= ~mask;
236 tmp |= (init->flt << pos);
237 WRITE_REG(GPIOx->FLT, tmp);
238
239 /* Set PIN type ttl or smit */
240 tmp = READ_REG(GPIOx->TYPE);
241 tmp &= ~mask;
242 tmp |= (init->type << pos);
243 WRITE_REG(GPIOx->TYPE, tmp);
244
245 /* Configure PIN function */
246 pos = i < 8 ? (i << 2) : ((i - 8) << 2);
247 mask = 0xF << pos;
248 tmp = i < 8 ? READ_REG(GPIOx->FUNC0) : READ_REG(GPIOx->FUNC1);
249 tmp &= ~mask;
250 tmp |= (init->func << pos);
251 i < 8 ? WRITE_REG(GPIOx->FUNC0, tmp) : WRITE_REG(GPIOx->FUNC1, tmp);
252 }
253
254 return;
255 }
256
257 /**
258 * @brief Initialize the GPIOx peripheral using the default parameters.
259 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
260 * @param pin: The pin which need to initialize.
261 * @retval None
262 */
ald_gpio_init_default(GPIO_TypeDef * GPIOx,uint16_t pin)263 void ald_gpio_init_default(GPIO_TypeDef *GPIOx, uint16_t pin)
264 {
265 gpio_init_t init;
266
267 /* Fill GPIO_init_t structure with default parameter */
268 init.mode = GPIO_MODE_OUTPUT;
269 init.odos = GPIO_PUSH_PULL;
270 init.pupd = GPIO_PUSH_UP;
271 init.odrv = GPIO_OUT_DRIVE_NORMAL;
272 init.flt = GPIO_FILTER_DISABLE;
273 init.type = GPIO_TYPE_CMOS;
274 init.func = GPIO_FUNC_1;
275
276 ald_gpio_init(GPIOx, pin, &init);
277 return;
278 }
279
280 /**
281 * @brief Sets GPIO function to default(func0).
282 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
283 * @retval None
284 */
ald_gpio_func_default(GPIO_TypeDef * GPIOx)285 void ald_gpio_func_default(GPIO_TypeDef *GPIOx)
286 {
287 WRITE_REG(GPIOx->FUNC0, 0x00);
288 WRITE_REG(GPIOx->FUNC1, 0x00);
289
290 return;
291 }
292
293 /**
294 * @brief Initialize the external interrupt according to the specified
295 * parameters in the exti_init_t.
296 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
297 * @param pin: The pin which need to initialize.
298 * @param init: Pointer to a exti_init_t structure that can contains
299 * the configuration information for the specified parameters.
300 * @retval None
301 */
ald_gpio_exti_init(GPIO_TypeDef * GPIOx,uint16_t pin,exti_init_t * init)302 void ald_gpio_exti_init(GPIO_TypeDef *GPIOx, uint16_t pin, exti_init_t *init)
303 {
304 uint8_t i;
305 uint8_t port;
306
307 assert_param(IS_GPIO_PORT(GPIOx));
308 assert_param(IS_GPIO_PIN(pin));
309 assert_param(IS_FUNC_STATE(init->filter));
310 assert_param(IS_EXTI_FLTCKS_TYPE(init->cks));
311
312 /* Get GPIO port */
313 if (GPIOx == GPIOA)
314 port = 0x0;
315 else if (GPIOx == GPIOB)
316 port = 0x1;
317 else if (GPIOx == GPIOC)
318 port = 2;
319 else if (GPIOx == GPIOD)
320 port = 3;
321 else if (GPIOx == GPIOE)
322 port = 4;
323 else if (GPIOx == GPIOF)
324 port = 5;
325 else if (GPIOx == GPIOG)
326 port = 6;
327 else if (GPIOx == GPIOH)
328 port = 7;
329 else
330 port = 0;
331
332 /* Get Pin index */
333 for (i = 0; i < 16; ++i) {
334 if (((pin >> i) & 0x1) == 0x1)
335 break;
336 }
337
338 /* Select external interrupt line */
339 if (i <= 7) {
340 EXTI->EXTIPSR0 &= ~(0x7U << (i * 4));
341 EXTI->EXTIPSR0 |= (port << (i * 4));
342 }
343 else {
344 i -= 8;
345 EXTI->EXTIPSR1 &= ~(0x7U << (i * 4));
346 EXTI->EXTIPSR1 |= (port << (i * 4));
347 }
348
349 /* Configure filter parameter */
350 if (init->filter == ENABLE) {
351 SET_BIT(EXTI->EXTIFLTCR, pin);
352 MODIFY_REG(EXTI->EXTIFLTCR, GPIO_EXTIFLTCR_FLTCKS_MSK, init->cks << GPIO_EXTIFLTCR_FLTCKS_POSS);
353 MODIFY_REG(EXTI->EXTIFLTCR, GPIO_EXTIFLTCR_FLTSEL_MSK, init->filter_time << GPIO_EXTIFLTCR_FLTSEL_POSS);
354 }
355 else {
356 CLEAR_BIT(EXTI->EXTIFLTCR, pin);
357 }
358
359 return;
360 }
361 /**
362 * @}
363 */
364
365 /** @defgroup GPIO_Public_Functions_Group2 IO operation functions
366 * @brief GPIO Read and Write
367 *
368 @verbatim
369 ===============================================================================
370 ##### IO operation functions #####
371 ===============================================================================
372 [..]
373 This subsection provides a set of functions allowing to manage the GPIOs.
374
375 @endverbatim
376 * @{
377 */
378
379 /**
380 * @brief Read the specified input port pin.
381 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
382 * @param pin: Specifies the pin to read.
383 * @retval The input pin value
384 */
ald_gpio_read_pin(GPIO_TypeDef * GPIOx,uint16_t pin)385 uint8_t ald_gpio_read_pin(GPIO_TypeDef *GPIOx, uint16_t pin)
386 {
387 assert_param(IS_GPIO_PORT(GPIOx));
388 assert_param(IS_GPIO_PIN(pin));
389
390 if (READ_BIT(GPIOx->DIN, pin))
391 return 1;
392 else
393 return 0;
394 }
395
396 /**
397 * @brief Set or clear the select Pin data.
398 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
399 * @param pin: The specified pin to be written.
400 * @param val: The specifies value to be written.
401 * @retval None
402 */
ald_gpio_write_pin(GPIO_TypeDef * GPIOx,uint16_t pin,uint8_t val)403 void ald_gpio_write_pin(GPIO_TypeDef *GPIOx, uint16_t pin, uint8_t val)
404 {
405 assert_param(IS_GPIO_PORT(GPIOx));
406 assert_param(IS_GPIO_PIN(pin));
407
408 if ((val & (0x01)) == 0x00)
409 CLEAR_BIT(GPIOx->DOUT, pin);
410 else
411 SET_BIT(GPIOx->DOUT, pin);
412
413 return;
414 }
415
416 /**
417 * @brief Turn over the select data.
418 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
419 * @param pin: Specifies the pin to turn over.
420 * @retval None
421 */
ald_gpio_toggle_pin(GPIO_TypeDef * GPIOx,uint16_t pin)422 void ald_gpio_toggle_pin(GPIO_TypeDef *GPIOx, uint16_t pin)
423 {
424 assert_param(IS_GPIO_PORT(GPIOx));
425 assert_param(IS_GPIO_PIN(pin));
426
427 WRITE_REG(GPIOx->BIR, pin);
428 return;
429 }
430
431 /**
432 * @brief Turn over the direction.
433 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
434 * @param pin: Specifies the pin to turn over.
435 * @retval None
436 */
ald_gpio_toggle_dir(GPIO_TypeDef * GPIOx,uint16_t pin)437 void ald_gpio_toggle_dir(GPIO_TypeDef *GPIOx, uint16_t pin)
438 {
439 uint32_t i, pos, mask, tmp, value;
440
441 assert_param(IS_GPIO_PORT(GPIOx));
442 assert_param(IS_GPIO_PIN(pin));
443
444 for (i = 0; i < 16; ++i) {
445 if (((pin >> i) & 0x1) == 0)
446 continue;
447
448 /* Get position and 2-bits mask */
449 pos = i << 1;
450 mask = 0x3 << pos;
451
452 /* Get the new direction */
453 tmp = READ_REG(GPIOx->MODE);
454 value = (tmp >> pos) & 0x3;
455
456 if ((value == 2) || (value == 3))
457 value = 1;
458 else if (value == 1) {
459 value = 2;
460 }
461 else {
462 continue; /* do nothing */
463 }
464
465 /* Set PIN mode */
466 tmp &= ~mask;
467 tmp |= (value << pos);
468 WRITE_REG(GPIOx->MODE, tmp);
469 }
470
471 return;
472 }
473
474 /**
475 * @brief Lock the GPIO prot. Once locked, can
476 * only change the output data. Only when the CPU
477 * reset to unlock the GPIO port.
478 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
479 * @param pin: The specified Pin to be written.
480 * @retval None
481 */
ald_gpio_lock_pin(GPIO_TypeDef * GPIOx,uint16_t pin)482 void ald_gpio_lock_pin(GPIO_TypeDef *GPIOx, uint16_t pin)
483 {
484 assert_param(IS_GPIO_PORT(GPIOx));
485 assert_param(IS_GPIO_PIN(pin));
486
487 MODIFY_REG(GPIOx->LOCK, GPIO_LOCK_KEY_MSK, UNLOCK_KEY << GPIO_LOCK_KEY_POSS);
488 WRITE_REG(GPIOx->LOCK, pin);
489
490 return;
491 }
492
493 /**
494 * @brief Read the specified input port pin.
495 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
496 * @retval The value;
497 */
ald_gpio_read_port(GPIO_TypeDef * GPIOx)498 uint16_t ald_gpio_read_port(GPIO_TypeDef *GPIOx)
499 {
500 assert_param(IS_GPIO_PORT(GPIOx));
501
502 return READ_REG(GPIOx->DIN);
503 }
504
505 /**
506 * @brief Set or clear the select Pin data.
507 * @param GPIOx: Where x can be (A--H) to select the GPIO peripheral.
508 * @param val: The specifies value to be written.
509 * @retval None
510 */
ald_gpio_write_port(GPIO_TypeDef * GPIOx,uint16_t val)511 void ald_gpio_write_port(GPIO_TypeDef *GPIOx, uint16_t val)
512 {
513 assert_param(IS_GPIO_PORT(GPIOx));
514
515 WRITE_REG(GPIOx->DOUT, val);
516 return;
517 }
518
519
520 /**
521 * @}
522 */
523
524 /** @defgroup GPIO_Public_Functions_Group3 Control functions
525 * @brief EXTI Control functions
526 *
527 @verbatim
528 ===============================================================================
529 ##### Control functions #####
530 ===============================================================================
531 [..]
532 This subsection provides a set of functions allowing to
533 control external interrupt.
534
535 @endverbatim
536 * @{
537 */
538
539 /**
540 * @brief Configure the interrupt according to the specified parameter.
541 * @param pin: The Pin which need to configure.
542 * @param style: External interrupt trigger style.
543 * @param status:
544 * @arg ENABLE
545 * @arg DISABLE
546 * @retval None
547 */
ald_gpio_exti_interrupt_config(uint16_t pin,exti_trigger_style_t style,type_func_t status)548 void ald_gpio_exti_interrupt_config(uint16_t pin, exti_trigger_style_t style, type_func_t status)
549 {
550 assert_param(IS_GPIO_PIN(pin));
551 assert_param(IS_TRIGGER_STYLE(style));
552 assert_param(IS_FUNC_STATE(status));
553
554 if (status == ENABLE) {
555 if (style == EXTI_TRIGGER_RISING_EDGE) {
556 SET_BIT(EXTI->EXTIRER, pin);
557 }
558 else if (style == EXTI_TRIGGER_TRAILING_EDGE) {
559 SET_BIT(EXTI->EXTIFER, pin);
560 }
561 else if (style == EXTI_TRIGGER_BOTH_EDGE) {
562 SET_BIT(EXTI->EXTIRER, pin);
563 SET_BIT(EXTI->EXTIFER, pin);
564 }
565 else {
566 ; /* do nothing */
567 }
568
569 WRITE_REG(EXTI->EXTICFR, 0xffff);
570 SET_BIT(EXTI->EXTIEN, pin);
571 }
572 else {
573 if (style == EXTI_TRIGGER_RISING_EDGE) {
574 CLEAR_BIT(EXTI->EXTIRER, pin);
575 }
576 else if (style == EXTI_TRIGGER_TRAILING_EDGE) {
577 CLEAR_BIT(EXTI->EXTIFER, pin);
578 }
579 else if (style == EXTI_TRIGGER_BOTH_EDGE) {
580 CLEAR_BIT(EXTI->EXTIRER, pin);
581 CLEAR_BIT(EXTI->EXTIFER, pin);
582 }
583 else {
584 ; /* do nothing */
585 }
586
587 CLEAR_BIT(EXTI->EXTIEN, pin);
588 }
589
590 return;
591 }
592
593 /**
594 * @brief Get the Flag about external interrupt.
595 * @param pin: The pin which belong to external interrupt.
596 * @retval Flag status
597 * - SET
598 * - RESET
599 */
ald_gpio_exti_get_flag_status(uint16_t pin)600 flag_status_t ald_gpio_exti_get_flag_status(uint16_t pin)
601 {
602 assert_param(IS_GPIO_PIN(pin));
603
604 if (READ_BIT(EXTI->EXTIFLAG, pin))
605 return SET;
606
607 return RESET;
608 }
609
610 /**
611 * @brief Clear the external interrupt flag.
612 * @param pin: The pin which belong to external interrupt.
613 * @retval None
614 */
ald_gpio_exti_clear_flag_status(uint16_t pin)615 void ald_gpio_exti_clear_flag_status(uint16_t pin)
616 {
617 assert_param(IS_GPIO_PIN(pin));
618
619 WRITE_REG(EXTI->EXTICFR, pin);
620 return;
621 }
622 /**
623 * @}
624 */
625
626 /**
627 * @}
628 */
629
630 #endif /* ALD_GPIO */
631 /**
632 * @}
633 */
634
635 /**
636 * @}
637 */
638