1 /*!
2 * @file apm32f10x_gpio.c
3 *
4 * @brief This file provides all the GPIO firmware functions
5 *
6 * @version V1.0.4
7 *
8 * @date 2022-12-01
9 *
10 * @attention
11 *
12 * Copyright (C) 2020-2022 Geehy Semiconductor
13 *
14 * You may not use this file except in compliance with the
15 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16 *
17 * The program is only for reference, which is distributed in the hope
18 * that it will be useful and instructional for customers to develop
19 * their software. Unless required by applicable law or agreed to in
20 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23 * and limitations under the License.
24 */
25
26 /* Includes */
27 #include "apm32f10x_gpio.h"
28 #include "apm32f10x_rcm.h"
29
30 /** @addtogroup APM32F10x_StdPeriphDriver
31 @{
32 */
33
34 /** @addtogroup GPIO_Driver GPIO Driver
35 @{
36 */
37
38 /** @defgroup GPIO_Functions Functions
39 @{
40 */
41
42 /*!
43 * @brief Reset GPIO peripheral registers to their default reset values
44 *
45 * @param port: Select the GPIO port.
46 * This parameter can be one of GPIOx( x can be from A to G).
47 *
48 * @retval None
49 */
GPIO_Reset(GPIO_T * port)50 void GPIO_Reset(GPIO_T* port)
51 {
52 RCM_APB2_PERIPH_T APB2Periph;
53
54 if (port == GPIOA)
55 {
56 APB2Periph = RCM_APB2_PERIPH_GPIOA;
57 }
58 else if (port == GPIOB)
59 {
60 APB2Periph = RCM_APB2_PERIPH_GPIOB;
61 }
62 else if (port == GPIOC)
63 {
64 APB2Periph = RCM_APB2_PERIPH_GPIOC;
65 }
66 else if (port == GPIOD)
67 {
68 APB2Periph = RCM_APB2_PERIPH_GPIOD;
69 }
70 else if (port == GPIOE)
71 {
72 APB2Periph = RCM_APB2_PERIPH_GPIOE;
73 }
74 else if (port == GPIOF)
75 {
76 APB2Periph = RCM_APB2_PERIPH_GPIOF;
77 }
78 else if (port == GPIOG)
79 {
80 APB2Periph = RCM_APB2_PERIPH_GPIOG;
81 }
82
83 RCM_EnableAPB2PeriphReset(APB2Periph);
84 RCM_DisableAPB2PeriphReset(APB2Periph);
85 }
86
87 /*!
88 * @brief Reset Alternate Functions registers to their default reset values
89 *
90 * @param None
91 *
92 * @retval None
93 */
GPIO_AFIOReset(void)94 void GPIO_AFIOReset(void)
95 {
96 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO);
97 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO);
98 }
99
100 /*!
101 * @brief Config the GPIO peripheral according to the specified parameters in the gpioConfig
102 *
103 * @param port: Select the GPIO port.
104 * This parameter can be one of GPIOx( x can be from A to G).
105 *
106 * @param gpioConfig: pointer to a GPIO_Config_T structure
107 *
108 * @retval None
109 */
GPIO_Config(GPIO_T * port,GPIO_Config_T * gpioConfig)110 void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig)
111 {
112 uint8_t i;
113 uint32_t mode;
114 uint32_t CR;
115 uint32_t temp;
116 uint32_t shift;
117
118 mode = gpioConfig->mode & 0x0f;
119
120 if (gpioConfig->mode & 0x80)
121 {
122 mode |= gpioConfig->speed;
123 }
124
125 if (gpioConfig->pin & 0xff)
126 {
127 CR = port->CFGLOW;
128
129 for (i = 0, shift = 0x01; i < 8; i++, shift <<= 1)
130 {
131 if (gpioConfig->pin & shift)
132 {
133 temp = i << 2;
134 CR &= (uint32_t)~(0x0f << temp);
135 CR |= mode << temp;
136
137 if (gpioConfig->mode == GPIO_MODE_IN_PD)
138 {
139 port->BC = shift;
140 }
141 else if (gpioConfig->mode == GPIO_MODE_IN_PU)
142 {
143 port->BSC = shift;
144 }
145 }
146 }
147
148 port->CFGLOW = CR;
149 }
150
151 if (gpioConfig->pin & 0xff00)
152 {
153 CR = port->CFGHIG;
154
155 for (i = 8, shift = 0x100; i < 16; i++, shift <<= 1)
156 {
157 if (gpioConfig->pin & shift)
158 {
159 temp = (i - 8) << 2;
160 CR &= (uint32_t)~(0x0f << temp);
161 CR |= mode << temp;
162
163 if (gpioConfig->mode == GPIO_MODE_IN_PD)
164 {
165 port->BC = shift;
166 }
167 else if (gpioConfig->mode == GPIO_MODE_IN_PU)
168 {
169 port->BSC = shift;
170 }
171 }
172 }
173
174 port->CFGHIG = CR;
175 }
176 }
177
178 /*!
179 * @brief Fills each gpioConfig member with its default value.
180 *
181 * @param gpioConfig : pointer to a GPIO_Config_T structure which will be initialized.
182 *
183 * @retval None
184 */
GPIO_ConfigStructInit(GPIO_Config_T * gpioConfig)185 void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig)
186 {
187 gpioConfig->pin = GPIO_PIN_ALL;
188 gpioConfig->speed = GPIO_SPEED_2MHz;
189 gpioConfig->mode = GPIO_MODE_IN_FLOATING;
190 }
191
192 /*!
193 * @brief Reads the specified input port pin
194 *
195 * @param port: Select the GPIO port.
196 * This parameter can be one of GPIOx( x can be from A to G).
197 *
198 * @param pin : specifies pin to read.
199 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
200 *
201 * @retval The input port pin value
202 */
GPIO_ReadInputBit(GPIO_T * port,uint16_t pin)203 uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin)
204 {
205 uint8_t ret;
206
207 ret = (port->IDATA & pin) ? BIT_SET : BIT_RESET;
208
209 return ret;
210 }
211
212 /*!
213 * @brief Reads the specified GPIO input data port
214 *
215 * @param port: Select the GPIO port.
216 * This parameter can be one of GPIOx( x can be from A to G).
217 *
218 * @retval GPIO input data port value
219 */
GPIO_ReadInputPort(GPIO_T * port)220 uint16_t GPIO_ReadInputPort(GPIO_T* port)
221 {
222 return ((uint16_t)port->IDATA);
223 }
224
225 /*!
226 * @brief Reads the specified output data port bit
227 *
228 * @param port: Select the GPIO port.
229 * This parameter can be one of GPIOx( x can be from A to G).
230 *
231 * @param pin : specifies pin to read.
232 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
233 *
234 * @retval The output port pin value
235 */
GPIO_ReadOutputBit(GPIO_T * port,uint16_t pin)236 uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin)
237 {
238
239 uint8_t ret;
240
241 ret = (port->ODATA & pin) ? BIT_SET : BIT_RESET;
242
243 return ret;
244 }
245
246 /*!
247 * @brief Reads the specified GPIO output data port
248 *
249 * @param port: Select the GPIO port.
250 * This parameter can be one of GPIOx( x can be from A to G).
251 *
252 * @retval output data port value
253 */
GPIO_ReadOutputPort(GPIO_T * port)254 uint16_t GPIO_ReadOutputPort(GPIO_T* port)
255 {
256 return ((uint16_t)port->ODATA);
257 }
258
259 /*!
260 * @brief Sets the selected data port bits
261 *
262 * @param port: Select the GPIO port.
263 * This parameter can be one of GPIOx( x can be from A to G).
264 *
265 * @param pin : specifies pin to be written.
266 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
267 *
268 * @retval None
269 */
GPIO_SetBit(GPIO_T * port,uint16_t pin)270 void GPIO_SetBit(GPIO_T* port, uint16_t pin)
271 {
272 port->BSC = (uint32_t)pin;
273 }
274
275 /*!
276 * @brief Clears the selected data port bits
277 *
278 * @param port: Select the GPIO port.
279 * This parameter can be one of GPIOx( x can be from A to G).
280 *
281 * @param pin : specifies pin to be cleared.
282 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
283 *
284 * @retval None
285 */
GPIO_ResetBit(GPIO_T * port,uint16_t pin)286 void GPIO_ResetBit(GPIO_T* port, uint16_t pin)
287 {
288 port->BC = (uint32_t)pin;
289 }
290
291 /*!
292 * @brief Writes data to the specified GPIO data port bit
293 *
294 * @param port: Select the GPIO port.
295 * This parameter can be one of GPIOx( x can be from A to G).
296 *
297 * @param pin : Select specifies pin.
298 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
299 *
300 *
301 * @param bitVal : specifies the value to be written to the port output data register
302 * This parameter can be one of the following values:
303 * @arg BIT_RESET: Reset the port pin
304 * @arg BIT_SET : Set the port pin
305 *
306 * @retval None
307 */
GPIO_WriteBitValue(GPIO_T * port,uint16_t pin,uint8_t bitVal)308 void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, uint8_t bitVal)
309 {
310 if (bitVal != BIT_RESET)
311 {
312 port->BSC = pin;
313 }
314 else
315 {
316 port->BC = pin ;
317 }
318 }
319
320 /*!
321 * @brief Writes data to the specified GPIO data port
322 *
323 * @param port: Select the GPIO port.
324 * This parameter can be one of GPIOx( x can be from A to G).
325 *
326 * @param portValue : specifies the value to be written to the port output data register.
327 *
328 * @retval None
329 */
GPIO_WriteOutputPort(GPIO_T * port,uint16_t portValue)330 void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue)
331 {
332 port->ODATA = (uint32_t)portValue;
333 }
334
335 /*!
336 * @brief Locks GPIO Pins configuration registers
337 *
338 * @param port: Select the GPIO port.
339 * This parameter can be one of GPIOx( x can be from A to G).
340 *
341 * @param pin : Select specifies pin.
342 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
343 *
344 * @retval None
345 */
GPIO_ConfigPinLock(GPIO_T * port,uint16_t pin)346 void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin)
347 {
348 uint32_t val = 0x00010000;
349
350 val |= pin;
351 /* Set LCKK bit */
352 port->LOCK = val ;
353 /* Reset LCKK bit */
354 port->LOCK = pin;
355 /* Set LCKK bit */
356 port->LOCK = val;
357 /* Read LCKK bit*/
358 val = port->LOCK;
359 /* Read LCKK bit*/
360 val = port->LOCK;
361 }
362
363 /*!
364 * @brief Selects the GPIO pin used as Event output
365 *
366 * @param portSource : selects the GPIO port to be used as source for Event output.
367 * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to E).
368 *
369 * @param pinSource specifies the pin for the Event output
370 * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15).
371 *
372 * @retval None
373 */
GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource,GPIO_PIN_SOURCE_T pinSource)374 void GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource)
375 {
376 AFIO->EVCTRL_B.PORTSEL = portSource;
377 AFIO->EVCTRL_B.PINSEL = pinSource;
378 }
379
380 /*!
381 * @brief Enables the Event Output
382 *
383 * @param None
384 *
385 * @retval None
386 */
GPIO_EnableEventOutput(void)387 void GPIO_EnableEventOutput(void)
388 {
389 AFIO->EVCTRL_B.EVOEN = BIT_SET;
390 }
391
392 /*!
393 * @brief Disable the Event Output
394 *
395 * @param None
396 *
397 * @retval None
398 */
GPIO_DisableEventOutput(void)399 void GPIO_DisableEventOutput(void)
400 {
401 AFIO->EVCTRL_B.EVOEN = BIT_RESET;
402 }
403
404 /*!
405 * @brief Changes the mapping of the specified pin
406 *
407 * @param remap : selects the pin to remap
408 * This parameter can be one of the following values:
409 * @arg GPIO_NO_REMAP_SPI1 : No SPI1 Alternate Function mapping
410 * @arg GPIO_REMAP_SPI1 : SPI1 Alternate Function mapping
411 * @arg GPIO_NO_REMAP_I2C1 : No I2C1 Alternate Function mapping
412 * @arg GPIO_REMAP_I2C1 : I2C1 Alternate Function mapping
413 * @arg GPIO_NO_REMAP_USART1 : No USART1 Alternate Function mapping
414 * @arg GPIO_REMAP_USART1 : USART1 Alternate Function mapping
415 * @arg GPIO_NO_REMAP_USART2 : No USART2 Alternate Function mapping
416 * @arg GPIO_REMAP_USART2 : USART2 Alternate Function mapping
417 * @arg GPIO_NO_REMAP_USART3 : No USART3 Partial Alternate Function mapping
418 * @arg GPIO_PARTIAL_REMAP_USART3 : USART3 Partial Alternate Function mapping
419 * @arg GPIO_FULL_REMAP_USART3 : USART3 Full Alternate Function mapping
420 * @arg GPIO_NO_REMAP_TMR1 : No TIM1 Partial Alternate Function mapping
421 * @arg GPIO_PARTIAL_REMAP_TMR1 : TIM1 Partial Alternate Function mapping
422 * @arg GPIO_FULL_REMAP_TMR1 : TIM1 Full Alternate Function mapping
423 * @arg GPIO_NO_REMAP1_TMR2 : No TIM2 Partial1 Alternate Function mapping
424 * @arg GPIO_PARTIAL_REMAP1_TMR2 : TIM2 Partial1 Alternate Function mapping
425 * @arg GPIO_PARTIAL_REMAP2_TMR2 : TIM2 Partial2 Alternate Function mapping
426 * @arg GPIO_FULL_REMAP_TMR2 : TIM2 Full Alternate Function mapping
427 * @arg GPIO_NO_REMAP_TMR3 : No TIM3 Partial Alternate Function mapping
428 * @arg GPIO_PARTIAL_REMAP_TMR3 : TIM3 Partial Alternate Function mapping
429 * @arg GPIO_FULL_REMAP_TMR3 : TIM3 Full Alternate Function mapping
430 * @arg GPIO_NO_REMAP_TMR4 : No TIM4 Alternate Function mapping
431 * @arg GPIO_REMAP_TMR4 : TIM4 Alternate Function mapping
432 * @arg GPIO_NO_REMAP_CAN1 : No CAN1 Alternate Function mapping
433 * @arg GPIO_REMAP1_CAN1 : CAN1 Alternate Function mapping
434 * @arg GPIO_REMAP2_CAN1 : CAN1 Alternate Function mapping
435 * @arg GPIO_NO_REMAP_PD01 : No PD01 Alternate Function mapping
436 * @arg GPIO_REMAP_PD01 : PD01 Alternate Function mapping
437 * @arg GPIO_NO_REMAP_TMR5CH4_LSI : No LSI connected to TIM5 Channel4 input capture for calibration
438 * @arg GPIO_REMAP_TMR5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration
439 * Only For APM32F10X_CL devices(APM32F107xx and APM32F105xx):
440 * @arg GPIO_NO_REMAP_ETH_MAC : No Ethernet MAC Alternate remapping
441 * @arg GPIO_REMAP_ETH_MAC : Ethernet MAC Alternate remapping
442 * @arg GPIO_NO_REMAP_CAN2 : No CAN2 Alternate Function mapping
443 * @arg GPIO_REMAP_CAN2 : CAN2 Alternate Function mapping
444 * @arg GPIO_REMAP_MACEISEL_MII : Ethernet MAC External Interface Select MII Interface
445 * @arg GPIO_REMAP_MACEISEL_RMII : Ethernet MAC External Interface Select RMII Interface
446 * @arg GPIO_NO_REMAP_SPI3 : No SPI3 Alternate Function mapping
447 * @arg GPIO_REMAP_SPI3 : SPI3 Alternate Function mapping
448 * @arg GPIO_NO_REMAP_SWJ : Full SWJ Enabled (JTAG-DP + SW-DP)
449 * @arg GPIO_REMAP_SWJ_NOJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
450 * @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled
451 * @arg GPIO_REMAP_SWJ_DISABLE : Full SWJ Disabled (JTAG-DP + SW-DP)
452 * @arg GPIO_NO_REMAP_TMR2ITR1 : No TMR2 ITR1 Alternate Function mapping
453 * @arg GPIO_REMAP_TMR2ITR1 : TMR2 ITR1 Alternate Function mapping
454 * @arg GPIO_NO_REMAP_PTP_PPS : No Ethernet MAC PTP_PPS Alternate Function mapping
455 * @arg GPIO_REMAP_PTP_PPS : Ethernet MAC PTP_PPS Alternate Function mapping
456 * For Other APM32F10X_HD/MD/LD devices:
457 * @arg GPIO_NO_REMAP_ADC1_ETRGINJ : No ADC1 External Trigger Injected Conversion remapping
458 * @arg GPIO_REMAP_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping
459 * @arg GPIO_NO_REMAP_ADC1_ETRGREG : No ADC1 External Trigger Regular Conversion remapping
460 * @arg GPIO_REMAP_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping
461 * @arg GPIO_NO_REMAP_ADC2_ETRGINJ : No ADC2 External Trigger Injected Conversion remapping
462 * @arg GPIO_REMAP_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping
463 * @arg GPIO_NO_REMAP_ADC2_ETRGREG : No ADC2 External Trigger Regular Conversion remapping
464 * @arg GPIO_REMAP_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping
465 * @arg GPIO_NO_REMAP_CAN2 : No CAN2 Alternate Function mapping
466 * @arg GPIO_REMAP_CAN2 : CAN2 Alternate Function mapping
467 * @arg GPIO_NO_REMAP_SWJ : Full SWJ Enabled (JTAG-DP + SW-DP)
468 * @arg GPIO_REMAP_SWJ_NOJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
469 * @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled
470 * @arg GPIO_REMAP_SWJ_DISABLE : Full SWJ Disabled (JTAG-DP + SW-DP)
471 *
472 * @retval When you use GPIO_REMAP_CAN2, you must put this function last of all other ConfigPinRemap Function.
473 */
GPIO_ConfigPinRemap(GPIO_REMAP_T remap)474 void GPIO_ConfigPinRemap(GPIO_REMAP_T remap)
475 {
476 uint32_t val, mask, bitOffset, regOffset;
477 uint32_t regVal;
478
479 val = remap & 0x0f;
480 mask = (remap >> 4) & 0x0f;
481 bitOffset = (remap >> 8) & 0xff;
482 regOffset = (remap >> 16) & 0x0f;
483
484 if (regOffset)
485 {
486 regVal = AFIO->REMAP2;
487 }
488 else
489 {
490 regVal = AFIO->REMAP1;
491 }
492
493 if (remap >> 8 == 0x18)
494 {
495 regVal &= 0xF0FFFFFF;
496 AFIO->REMAP1 &= 0xF0FFFFFF;
497 }
498 else
499 {
500 regVal |= 0x0F000000;
501 }
502
503 mask <<= bitOffset;
504 regVal &= (uint32_t)~mask;
505 val <<= bitOffset;
506 regVal |= val;
507
508 if (regOffset)
509 {
510 AFIO->REMAP2 = regVal;
511 }
512 else
513 {
514 AFIO->REMAP1 = regVal;
515 }
516 }
517
518 /*!
519 * @brief Selects the GPIO pin used as EINT Line
520 *
521 * @param portSource : selects the GPIO port to be used as source for EINT line.
522 * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to G).
523 *
524 * @param pinSource : Specifies the EINT line to be configured.
525 * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15).
526 *
527 * @retval None
528 */
GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource,GPIO_PIN_SOURCE_T pinSource)529 void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource)
530 {
531 uint32_t shift;
532
533 if (pinSource <= GPIO_PIN_SOURCE_3)
534 {
535 shift = pinSource << 2;
536 AFIO->EINTSEL1 &= (uint32_t)~(0x0f << shift);
537 AFIO->EINTSEL1 |= portSource << shift;
538 }
539
540 else if (pinSource <= GPIO_PIN_SOURCE_7)
541 {
542 shift = (pinSource - GPIO_PIN_SOURCE_4) << 2;
543 AFIO->EINTSEL2 &= (uint32_t)~(0x0f << shift);
544 AFIO->EINTSEL2 |= portSource << shift;
545 }
546
547 else if (pinSource <= GPIO_PIN_SOURCE_11)
548 {
549 shift = (pinSource - GPIO_PIN_SOURCE_8) << 2;
550 AFIO->EINTSEL3 &= (uint32_t)~(0x0f << shift);
551 AFIO->EINTSEL3 |= portSource << shift;
552 }
553
554 else if (pinSource <= GPIO_PIN_SOURCE_15)
555 {
556 shift = (pinSource - GPIO_PIN_SOURCE_12) << 2;
557 AFIO->EINTSEL4 &= (uint32_t)~(0x0f << shift);
558 AFIO->EINTSEL4 |= portSource << shift;
559 }
560 }
561
562 /**@} end of group GPIO_Functions*/
563 /**@} end of group GPIO_Driver*/
564 /**@} end of group APM32F10x_StdPeriphDriver*/
565