1 /*!
2 * @file apm32s10x_gpio.c
3 *
4 * @brief This file provides all the GPIO firmware functions
5 *
6 * @version V1.0.1
7 *
8 * @date 2022-12-31
9 *
10 * @attention
11 *
12 * Copyright (C) 2022-2023 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 usefull 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 "apm32s10x_gpio.h"
28 #include "apm32s10x_rcm.h"
29
30 /** @addtogroup APM32S10x_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 E).
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
75 RCM_EnableAPB2PeriphReset(APB2Periph);
76 RCM_DisableAPB2PeriphReset(APB2Periph);
77 }
78
79 /*!
80 * @brief Reset Alternate Functions registers to their default reset values
81 *
82 * @param None
83 *
84 * @retval None
85 */
GPIO_AFIOReset(void)86 void GPIO_AFIOReset(void)
87 {
88 RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO);
89 RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_AFIO);
90 }
91
92 /*!
93 * @brief Configure the GPIO peripheral according to the specified parameters in the gpioConfig
94 *
95 * @param port: Select the GPIO port.
96 * This parameter can be one of GPIOx( x can be from A to E).
97 *
98 * @param gpioConfig: pointer to a GPIO_Config_T structure
99 *
100 * @retval None
101 */
GPIO_Config(GPIO_T * port,GPIO_Config_T * gpioConfig)102 void GPIO_Config(GPIO_T* port, GPIO_Config_T* gpioConfig)
103 {
104 uint8_t i;
105 uint32_t mode;
106 uint32_t CR;
107 uint32_t temp;
108 uint32_t shift;
109
110 mode = gpioConfig->mode & 0x0f;
111
112 if (gpioConfig->mode & 0x80)
113 {
114 mode |= gpioConfig->speed;
115 }
116
117 if (gpioConfig->pin & 0xff)
118 {
119 CR = port->CFGLOW;
120
121 for (i = 0, shift = 0x01; i < 8; i++, shift <<= 1)
122 {
123 if (gpioConfig->pin & shift)
124 {
125 temp = i << 2;
126 CR &= (uint32_t)~(0x0f << temp);
127 CR |= mode << temp;
128
129 if (gpioConfig->mode == GPIO_MODE_IN_PD)
130 {
131 port->BC = shift;
132 }
133 else if (gpioConfig->mode == GPIO_MODE_IN_PU)
134 {
135 port->BSC = shift;
136 }
137 }
138 }
139
140 port->CFGLOW = CR;
141 }
142
143 if (gpioConfig->pin & 0xff00)
144 {
145 CR = port->CFGHIG;
146
147 for (i = 8, shift = 0x100; i < 16; i++, shift <<= 1)
148 {
149 if (gpioConfig->pin & shift)
150 {
151 temp = (i - 8) << 2;
152 CR &= (uint32_t)~(0x0f << temp);
153 CR |= mode << temp;
154
155 if (gpioConfig->mode == GPIO_MODE_IN_PD)
156 {
157 port->BC = shift;
158 }
159 else if (gpioConfig->mode == GPIO_MODE_IN_PU)
160 {
161 port->BSC = shift;
162 }
163 }
164 }
165
166 port->CFGHIG = CR;
167 }
168 }
169
170 /*!
171 * @brief Fill each gpioConfig member with its default value.
172 *
173 * @param gpioConfig : pointer to a GPIO_Config_T structure which will be initialized.
174 *
175 * @retval None
176 */
GPIO_ConfigStructInit(GPIO_Config_T * gpioConfig)177 void GPIO_ConfigStructInit(GPIO_Config_T* gpioConfig)
178 {
179 gpioConfig->pin = GPIO_PIN_ALL;
180 gpioConfig->speed = GPIO_SPEED_2MHz;
181 gpioConfig->mode = GPIO_MODE_IN_FLOATING;
182 }
183
184 /*!
185 * @brief Read the specified input port pin
186 *
187 * @param port: Select the GPIO port.
188 * This parameter can be one of GPIOx( x can be from A to E).
189 *
190 * @param pin : specify pin to read.
191 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
192 *
193 * @retval The input port pin value
194 */
GPIO_ReadInputBit(GPIO_T * port,uint16_t pin)195 uint8_t GPIO_ReadInputBit(GPIO_T* port, uint16_t pin)
196 {
197 uint8_t ret;
198
199 ret = (port->IDATA & pin) ? BIT_SET : BIT_RESET;
200
201 return ret;
202 }
203
204 /*!
205 * @brief Read the specified GPIO input data port
206 *
207 * @param port: Select the GPIO port.
208 * This parameter can be one of GPIOx( x can be from A to E).
209 *
210 * @retval GPIO input data port value
211 */
GPIO_ReadInputPort(GPIO_T * port)212 uint16_t GPIO_ReadInputPort(GPIO_T* port)
213 {
214 return (uint16_t)port->IDATA;
215 }
216
217 /*!
218 * @brief Read the specified output data port bit
219 *
220 * @param port: Select the GPIO port.
221 * This parameter can be one of GPIOx( x can be from A to E).
222 *
223 * @param pin : specify pin to read.
224 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
225 *
226 * @retval The output port pin value
227 */
GPIO_ReadOutputBit(GPIO_T * port,uint16_t pin)228 uint8_t GPIO_ReadOutputBit(GPIO_T* port, uint16_t pin)
229 {
230
231 uint8_t ret;
232
233 ret = (port->ODATA & pin) ? BIT_SET : BIT_RESET;
234
235 return ret;
236 }
237
238 /*!
239 * @brief Read the specified GPIO output data port
240 *
241 * @param port: Select the GPIO port.
242 * This parameter can be one of GPIOx( x can be from A to E).
243 *
244 * @retval output data port value
245 */
GPIO_ReadOutputPort(GPIO_T * port)246 uint16_t GPIO_ReadOutputPort(GPIO_T* port)
247 {
248 return (uint16_t)port->ODATA;
249 }
250
251 /*!
252 * @brief Set the selected data port bits
253 *
254 * @param port: Select the GPIO port.
255 * This parameter can be one of GPIOx( x can be from A to E).
256 *
257 * @param pin : specify pin to be written.
258 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
259 *
260 * @retval None
261 */
GPIO_SetBit(GPIO_T * port,uint16_t pin)262 void GPIO_SetBit(GPIO_T* port, uint16_t pin)
263 {
264 port->BSC = (uint32_t)pin;
265 }
266
267 /*!
268 * @brief Clear the selected data port bits
269 *
270 * @param port: Select the GPIO port.
271 * This parameter can be one of GPIOx( x can be from A to E).
272 *
273 * @param pin : specify pin to be cleared.
274 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
275 *
276 * @retval None
277 */
GPIO_ResetBit(GPIO_T * port,uint16_t pin)278 void GPIO_ResetBit(GPIO_T* port, uint16_t pin)
279 {
280 port->BC = (uint32_t)pin;
281 }
282
283 /*!
284 * @brief Write data to the specified GPIO data port bit
285 *
286 * @param port: Select the GPIO port.
287 * This parameter can be one of GPIOx( x can be from A to E).
288 *
289 * @param pin : Select specifies pin.
290 * This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
291 *
292 * @param bitVal : specify the value to be written to the port output data register
293 * This parameter can be one of the following values:
294 * @arg BIT_RESET: Reset the port pin
295 * @arg BIT_SET : Set the port pin
296 *
297 * @retval None
298 */
GPIO_WriteBitValue(GPIO_T * port,uint16_t pin,uint8_t bitVal)299 void GPIO_WriteBitValue(GPIO_T* port, uint16_t pin, uint8_t bitVal)
300 {
301 if (bitVal != BIT_RESET)
302 {
303 port->BSC = pin;
304 }
305 else
306 {
307 port->BC = pin ;
308 }
309 }
310
311 /*!
312 * @brief Write data to the specified GPIO data port
313 *
314 * @param port: Select the GPIO port.
315 * This parameter can be one of GPIOx( x can be from A to E).
316 *
317 * @param portValue : specify the value to be written to the port output data register.
318 *
319 * @retval None
320 */
GPIO_WriteOutputPort(GPIO_T * port,uint16_t portValue)321 void GPIO_WriteOutputPort(GPIO_T* port, uint16_t portValue)
322 {
323 port->ODATA = (uint32_t)portValue;
324 }
325
326 /*!
327 * @brief Lock GPIO Pins configuration registers
328 *
329 * @param port: Select the GPIO port.
330 * This parameter can be one of GPIOx( x can be from A to E).
331 *
332 * @param pin : Select specifies pin.
333 * This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
334 *
335 * @retval None
336 */
GPIO_ConfigPinLock(GPIO_T * port,uint16_t pin)337 void GPIO_ConfigPinLock(GPIO_T* port, uint16_t pin)
338 {
339 uint32_t val = 0x00010000;
340
341 val |= pin;
342 /* Set LCKK bit */
343 port->LOCK = val ;
344 /* Reset LCKK bit */
345 port->LOCK = pin;
346 /* Set LCKK bit */
347 port->LOCK = val;
348 /* Read LCKK bit */
349 val = port->LOCK;
350 /* Read LCKK bit */
351 val = port->LOCK;
352 }
353
354 /*!
355 * @brief Select the GPIO pin used as Event output
356 *
357 * @param portSource: select the GPIO port to be used as source for Event output.
358 * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to E).
359 *
360 * @param pinSource : specify the pin for the Event output
361 * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15).
362 *
363 * @retval None
364 */
GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource,GPIO_PIN_SOURCE_T pinSource)365 void GPIO_ConfigEventOutput(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource)
366 {
367 AFIO->EVCTRL_B.PORTSEL = portSource;
368 AFIO->EVCTRL_B.PINSEL = pinSource;
369 }
370
371 /*!
372 * @brief Enable the Event Output
373 *
374 * @param None
375 *
376 * @retval None
377 */
GPIO_EnableEventOutput(void)378 void GPIO_EnableEventOutput(void)
379 {
380 AFIO->EVCTRL_B.EVOEN = BIT_SET;
381 }
382
383 /*!
384 * @brief Disable the Event Output
385 *
386 * @param None
387 *
388 * @retval None
389 */
GPIO_DisableEventOutput(void)390 void GPIO_DisableEventOutput(void)
391 {
392 AFIO->EVCTRL_B.EVOEN = BIT_RESET;
393 }
394
395 /*!
396 * @brief Change the mapping of the specified pin
397 *
398 * @param remap : select the pin to remap
399 * This parameter can be one of the following values:
400 * @arg GPIO_NO_REMAP_SPI1 : No SPI1 Alternate Function mapping
401 * @arg GPIO_REMAP_SPI1 : SPI1 Alternate Function mapping
402 * @arg GPIO_NO_REMAP_I2C1 : No I2C1 Alternate Function mapping
403 * @arg GPIO_REMAP_I2C1 : I2C1 Alternate Function mapping
404 * @arg GPIO_NO_REMAP_USART1 : No USART1 Alternate Function mapping
405 * @arg GPIO_REMAP_USART1 : USART1 Alternate Function mapping
406 * @arg GPIO_NO_REMAP_USART2 : No USART2 Alternate Function mapping
407 * @arg GPIO_REMAP_USART2 : USART2 Alternate Function mapping
408 * @arg GPIO_NO_REMAP_USART3 : No USART3 Partial Alternate Function mapping
409 * @arg GPIO_PARTIAL_REMAP_USART3 : USART3 Partial Alternate Function mapping
410 * @arg GPIO_FULL_REMAP_USART3 : USART3 Full Alternate Function mapping
411 * @arg GPIO_NO_REMAP_TMR1 : No TIM1 Partial Alternate Function mapping
412 * @arg GPIO_PARTIAL_REMAP_TMR1 : TIM1 Partial Alternate Function mapping
413 * @arg GPIO_FULL_REMAP_TMR1 : TIM1 Full Alternate Function mapping
414 * @arg GPIO_NO_REMAP1_TMR2 : No TIM2 Partial1 Alternate Function mapping
415 * @arg GPIO_PARTIAL_REMAP1_TMR2 : TIM2 Partial1 Alternate Function mapping
416 * @arg GPIO_PARTIAL_REMAP2_TMR2 : TIM2 Partial2 Alternate Function mapping
417 * @arg GPIO_FULL_REMAP_TMR2 : TIM2 Full Alternate Function mapping
418 * @arg GPIO_NO_REMAP_TMR3 : No TIM3 Partial Alternate Function mapping
419 * @arg GPIO_PARTIAL_REMAP_TMR3 : TIM3 Partial Alternate Function mapping
420 * @arg GPIO_FULL_REMAP_TMR3 : TIM3 Full Alternate Function mapping
421 * @arg GPIO_NO_REMAP_TMR4 : No TIM4 Alternate Function mapping
422 * @arg GPIO_REMAP_TMR4 : TIM4 Alternate Function mapping
423 * @arg GPIO_NO_REMAP_CAN1 : No CAN1 Alternate Function mapping
424 * @arg GPIO_REMAP1_CAN1 : CAN1 Alternate Function mapping
425 * @arg GPIO_REMAP2_CAN1 : CAN1 Alternate Function mapping
426 * @arg GPIO_NO_REMAP_PD01 : No PD01 Alternate Function mapping
427 * @arg GPIO_REMAP_PD01 : PD01 Alternate Function mapping
428 * @arg GPIO_NO_REMAP_ADC1_ETRGINJ : No ADC1 External Trigger Injected Conversion remapping
429 * @arg GPIO_REMAP_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping
430 * @arg GPIO_NO_REMAP_ADC1_ETRGREG : No ADC1 External Trigger Regular Conversion remapping
431 * @arg GPIO_REMAP_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping
432 * @arg GPIO_NO_REMAP_ADC2_ETRGINJ : No ADC2 External Trigger Injected Conversion remapping
433 * @arg GPIO_REMAP_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping
434 * @arg GPIO_NO_REMAP_ADC2_ETRGREG : No ADC2 External Trigger Regular Conversion remapping
435 * @arg GPIO_REMAP_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping
436 * @arg GPIO_NO_REMAP_CAN2 : No CAN2 Alternate Function mapping
437 * @arg GPIO_REMAP_CAN2 : CAN2 Alternate Function mapping
438 * @arg GPIO_NO_REMAP_SWJ : Full SWJ Enabled (JTAG-DP + SW-DP)
439 * @arg GPIO_REMAP_SWJ_NOJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
440 * @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled
441 * @arg GPIO_REMAP_SWJ_DISABLE : Full SWJ Disabled (JTAG-DP + SW-DP)
442 *
443 * @retval When you use GPIO_REMAP_CAN2, you must put this function last of all other ConfigPinRemap Function.
444 */
GPIO_ConfigPinRemap(GPIO_REMAP_T remap)445 void GPIO_ConfigPinRemap(GPIO_REMAP_T remap)
446 {
447 uint32_t val, mask, bitOffset;
448 uint32_t regVal;
449
450 val = remap & 0x0f;
451 mask = (remap >> 4) & 0x0f;
452 bitOffset = (remap >> 8) & 0xff;
453 regVal = AFIO->REMAP1;
454
455 if (remap >> 8 == 0x18)
456 {
457 regVal &= 0xF0FFFFFF;
458 AFIO->REMAP1 &= 0xF0FFFFFF;
459 }
460 else
461 {
462 regVal |= 0x0F000000;
463 }
464
465 mask <<= bitOffset;
466 regVal &= (uint32_t)~mask;
467 val <<= bitOffset;
468 regVal |= val;
469 AFIO->REMAP1 = regVal;
470 }
471
472 /*!
473 * @brief Select the GPIO pin used as EINT Line
474 *
475 * @param portSource : select the GPIO port to be used as source for EINT line.
476 * This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to E).
477 *
478 * @param pinSource : Specify the EINT line to be configured.
479 * This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15).
480 *
481 * @retval None
482 */
GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource,GPIO_PIN_SOURCE_T pinSource)483 void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource)
484 {
485 uint32_t shift;
486
487 if (pinSource <= GPIO_PIN_SOURCE_3)
488 {
489 shift = pinSource << 2;
490 AFIO->EINTSEL1 &= (uint32_t)~(0x0f << shift);
491 AFIO->EINTSEL1 |= portSource << shift;
492 }
493
494 else if (pinSource <= GPIO_PIN_SOURCE_7)
495 {
496 shift = (pinSource - GPIO_PIN_SOURCE_4) << 2;
497 AFIO->EINTSEL2 &= (uint32_t)~(0x0f << shift);
498 AFIO->EINTSEL2 |= portSource << shift;
499 }
500
501 else if (pinSource <= GPIO_PIN_SOURCE_11)
502 {
503 shift = (pinSource - GPIO_PIN_SOURCE_8) << 2;
504 AFIO->EINTSEL3 &= (uint32_t)~(0x0f << shift);
505 AFIO->EINTSEL3 |= portSource << shift;
506 }
507
508 else if (pinSource <= GPIO_PIN_SOURCE_15)
509 {
510 shift = (pinSource - GPIO_PIN_SOURCE_12) << 2;
511 AFIO->EINTSEL4 &= (uint32_t)~(0x0f << shift);
512 AFIO->EINTSEL4 |= portSource << shift;
513 }
514 }
515
516 /**@} end of group GPIO_Functions */
517 /**@} end of group GPIO_Driver */
518 /**@} end of group APM32S10x_StdPeriphDriver */
519