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