1 /*!
2  * @file       apm32e10x_gpio.c
3  *
4  * @brief      This file provides all the GPIO firmware functions
5  *
6  * @version     V1.0.2
7  *
8  * @date        2022-12-31
9  *
10  * @attention
11  *
12  *  Copyright (C) 2021-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 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 #include "apm32e10x_gpio.h"
27 #include "apm32e10x_rcm.h"
28 
29 /** @addtogroup APM32E10x_StdPeriphDriver
30   @{
31 */
32 
33 /** @addtogroup GPIO_Driver
34   * @brief GPIO driver modules
35   @{
36 */
37 
38 /** @defgroup GPIO_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  *                    @arg GPIO_NO_REMAP_ADC1_ETRGINJ : No ADC1 External Trigger Injected Conversion remapping
440  *                    @arg GPIO_REMAP_ADC1_ETRGINJ    : ADC1 External Trigger Injected Conversion remapping
441  *                    @arg GPIO_NO_REMAP_ADC1_ETRGREG : No ADC1 External Trigger Regular Conversion remapping
442  *                    @arg GPIO_REMAP_ADC1_ETRGREG    : ADC1 External Trigger Regular Conversion remapping
443  *                    @arg GPIO_NO_REMAP_ADC2_ETRGINJ : No ADC2 External Trigger Injected Conversion remapping
444  *                    @arg GPIO_REMAP_ADC2_ETRGINJ    : ADC2 External Trigger Injected Conversion remapping
445  *                    @arg GPIO_NO_REMAP_ADC2_ETRGREG : No ADC2 External Trigger Regular Conversion remapping
446  *                    @arg GPIO_REMAP_ADC2_ETRGREG    : ADC2 External Trigger Regular Conversion remapping
447  *                    @arg GPIO_NO_REMAP_CAN2         : No CAN2 Alternate Function mapping
448  *                    @arg GPIO_REMAP_CAN2            : CAN2 Alternate Function mapping
449  *                    @arg GPIO_NO_REMAP_SWJ          : Full SWJ Enabled (JTAG-DP + SW-DP)
450  *                    @arg GPIO_REMAP_SWJ_NOJTRST     : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
451  *                    @arg GPIO_REMAP_SWJ_JTAGDISABLE : JTAG-DP Disabled and SW-DP Enabled
452  *                    @arg GPIO_REMAP_SWJ_DISABLE     : Full SWJ Disabled (JTAG-DP + SW-DP)
453  *
454  * @retval    When you use GPIO_REMAP_CAN2, you must put this function last of all other ConfigPinRemap Function.
455  */
GPIO_ConfigPinRemap(GPIO_REMAP_T remap)456 void GPIO_ConfigPinRemap(GPIO_REMAP_T remap)
457 {
458     uint32_t val, mask, bitOffset, regOffset;
459     uint32_t regVal;
460 
461     val = remap & 0x0f;
462     mask = (remap >> 4) & 0x0f;
463     bitOffset = (remap >> 8) & 0xff;
464     regOffset = (remap >> 16) & 0x0f;
465 
466     if (regOffset)
467     {
468         regVal = AFIO->REMAP2;
469     }
470     else
471     {
472         regVal = AFIO->REMAP1;
473     }
474 
475     if(remap >> 8 == 0x18)
476     {
477         regVal &= 0xF0FFFFFF;
478         AFIO->REMAP1 &= 0xF0FFFFFF;
479     }
480     else
481     {
482         regVal |= 0x0F000000;
483     }
484 
485     mask <<= bitOffset;
486     regVal &= (uint32_t)~mask;
487     val <<= bitOffset;
488     regVal |= val;
489 
490     if (regOffset)
491     {
492         AFIO->REMAP2 = regVal;
493     }
494     else
495     {
496         AFIO->REMAP1 = regVal;
497     }
498 }
499 
500 /*!
501  * @brief     Selects the GPIO pin used as EINT Line
502  *
503  * @param     portSource : selects the GPIO port to be used as source for EINT line.
504  *                         This parameter can be one of GPIO_PORT_SOURCE_x( x can be from A to G).
505  *
506  * @param     pinSource : Specifies the EINT line to be configured.
507  *                        This parameter can be GPIO_PIN_SOURCE_x( x can be from 0 to 15).
508  *
509  * @retval    None
510  */
GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource,GPIO_PIN_SOURCE_T pinSource)511 void GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_T portSource, GPIO_PIN_SOURCE_T pinSource)
512 {
513     uint32_t shift;
514 
515     if (pinSource <= GPIO_PIN_SOURCE_3)
516     {
517         shift = pinSource << 2;
518         AFIO->EINTSEL1 &= (uint32_t )~(0x0f << shift);
519         AFIO->EINTSEL1 |=  portSource << shift;
520     }
521 
522     else if (pinSource <= GPIO_PIN_SOURCE_7)
523     {
524         shift = (pinSource - GPIO_PIN_SOURCE_4) << 2;
525         AFIO->EINTSEL2 &= (uint32_t )~(0x0f << shift);
526         AFIO->EINTSEL2 |=  portSource << shift;
527     }
528 
529     else if (pinSource <= GPIO_PIN_SOURCE_11)
530     {
531         shift = (pinSource - GPIO_PIN_SOURCE_8) << 2;
532         AFIO->EINTSEL3 &= (uint32_t )~(0x0f << shift);
533         AFIO->EINTSEL3 |=  portSource << shift;
534     }
535 
536     else if (pinSource <= GPIO_PIN_SOURCE_15)
537     {
538         shift = (pinSource - GPIO_PIN_SOURCE_12) << 2;
539         AFIO->EINTSEL4 &= (uint32_t )~(0x0f << shift);
540         AFIO->EINTSEL4 |=  portSource << shift;
541     }
542 }
543 
544 /**@} end of group GPIO_Functions */
545 /**@} end of group GPIO_Driver */
546 /**@} end of group APM32E10x_StdPeriphDriver */
547