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