1 /*!
2  * @file        apm32f4xx_gpio.c
3  *
4  * @brief       This file provides all the GPIO firmware functions
5  *
6  * @version     V1.0.2
7  *
8  * @date        2022-06-23
9  *
10  * @attention
11  *
12  *  Copyright (C) 2021-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 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 #include "apm32f4xx_gpio.h"
27 #include "apm32f4xx_rcm.h"
28 
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30   @{
31 */
32 
33 /** @defgroup GPIO_Driver
34   * @brief GPIO driver modules
35   @{
36 */
37 
38 /** @defgroup GPIO_Functions
39   @{
40 */
41 
42 /*!
43  * @brief  Reset the GPIOx peripheral registers to their default reset values.
44  *
45  * @param  port: Select the GPIO port.
46  *               This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
47  *               for APM32F405xx/407xx and APM32F415xx/417xx devices
48  * @retval None
49  *
50  * @note   By reset, The GPIO pins are configured in input floating mode (except the JTAG pins).
51  */
GPIO_Reset(GPIO_T * port)52 void GPIO_Reset(GPIO_T *port)
53 {
54     RCM_AHB1_PERIPH_T AHB1Periph;
55 
56     if (port == GPIOA)
57     {
58         AHB1Periph = RCM_AHB1_PERIPH_GPIOA;
59     }
60     else if (port == GPIOB)
61     {
62         AHB1Periph = RCM_AHB1_PERIPH_GPIOB;
63     }
64     else if (port == GPIOC)
65     {
66         AHB1Periph = RCM_AHB1_PERIPH_GPIOC;
67     }
68     else if (port == GPIOD)
69     {
70         AHB1Periph = RCM_AHB1_PERIPH_GPIOD;
71     }
72     else if (port == GPIOE)
73     {
74         AHB1Periph = RCM_AHB1_PERIPH_GPIOE;
75     }
76     else if (port == GPIOF)
77     {
78         AHB1Periph = RCM_AHB1_PERIPH_GPIOF;
79     }
80     else if (port == GPIOG)
81     {
82         AHB1Periph = RCM_AHB1_PERIPH_GPIOG;
83     }
84     else if (port == GPIOH)
85     {
86         AHB1Periph = RCM_AHB1_PERIPH_GPIOH;
87     }
88     else if (port == GPIOI)
89     {
90         AHB1Periph = RCM_AHB1_PERIPH_GPIOI;
91     }
92     else if (port == GPIOJ)
93     {
94         AHB1Periph = RCM_AHB1_PERIPH_GPIOJ;
95     }
96     else if (port == GPIOK)
97     {
98         AHB1Periph = RCM_AHB1_PERIPH_GPIOK;
99     }
100 
101     RCM_EnableAHB1PeriphReset(AHB1Periph);
102     RCM_DisableAHB1PeriphReset(AHB1Periph);
103 }
104 
105 /*!
106  * @brief        Config the GPIO peripheral according to the specified parameters in the gpioConfig
107  *
108  * @param        port: Select the GPIO port.
109  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
110  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
111  *
112  * @param       gpioConfig: pointer to a GPIO_Config_T structure
113  *
114  * @retval      None
115  */
GPIO_Config(GPIO_T * port,GPIO_Config_T * gpioConfig)116 void GPIO_Config(GPIO_T *port, GPIO_Config_T *gpioConfig)
117 {
118     uint32_t i = 0x00;
119     uint32_t pos = 0x00;
120     uint32_t temp = 0x00;
121 
122     for (i = 0; i < 16; i++)
123     {
124         pos = ((uint32_t)0x01) << i;
125         temp = (gpioConfig->pin) & pos;
126 
127         if (temp == pos)
128         {
129             port->MODE  &= ~(0x03 << (i * 2));
130             port->MODE |= (((uint32_t)gpioConfig->mode) << (i * 2));
131 
132             if ((gpioConfig->mode == GPIO_MODE_OUT) || (gpioConfig->mode == GPIO_MODE_AF))
133             {
134                 port->OSSEL &= ~(0x03 << (i * 2));
135                 port->OSSEL |= ((uint32_t)(gpioConfig->speed) << (i * 2));
136 
137                 port->OMODE  &= ~(0x01 << ((uint16_t)i)) ;
138                 port->OMODE |= (uint16_t)(((uint16_t)gpioConfig->otype) << ((uint16_t)i));
139             }
140 
141             port->PUPD &= ~(0x03 << ((uint16_t)i * 2));
142             port->PUPD |= (((uint32_t)gpioConfig->pupd) << (i * 2));
143         }
144     }
145 }
146 
147 /*!
148  * @brief       Fills every gpioConfig member with its default value.
149  *
150  * @param       gpioConfig : pointer to a GPIO_Config_T structure which will be initialized.
151  *
152  * @retval      None
153  */
GPIO_ConfigStructInit(GPIO_Config_T * gpioConfig)154 void GPIO_ConfigStructInit(GPIO_Config_T *gpioConfig)
155 {
156     gpioConfig->pin  = GPIO_PIN_ALL;
157     gpioConfig->mode = GPIO_MODE_IN;
158     gpioConfig->speed = GPIO_SPEED_2MHz;
159     gpioConfig->otype = GPIO_OTYPE_PP;
160     gpioConfig->pupd = GPIO_PUPD_NOPULL;
161 }
162 
163 /*!
164  * @brief        Lock GPIO Pins config registers.
165  *
166  * @param        port: Select the GPIO port.
167  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
168  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
169  *
170  * @param        pin: specifies the pin bit to be locked.
171  *                    This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
172  *
173  * @retval       None
174  *
175  * @note         Locked registers are GPIOx_MODER, GPIOx_OMODER, GPIOx_OOSSELR,
176  *               GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH,until the next reset the
177  *               configuration of the locked GPIO pins can no longer be config.
178  *
179  */
GPIO_ConfigPinLock(GPIO_T * port,uint16_t pin)180 void GPIO_ConfigPinLock(GPIO_T *port, uint16_t pin)
181 {
182     __IOM uint32_t temp = 0x00010000;
183 
184     temp |= pin;
185 
186     port->LOCK = temp;
187 
188     port->LOCK = pin;
189 
190     port->LOCK = temp;
191 
192     temp = port->LOCK;
193 }
194 
195 /*!
196  * @brief        Reads the specified input port pin.
197  *
198  * @param        port :Select the GPIO port.
199  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
200  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
201  *
202  * @param        pin: specifies the port bit to read.
203  *                    This parameter can be GPIO_Pin_x where x can be (0..15).
204  *
205  * @retval The input port pin value.
206  */
GPIO_ReadInputBit(GPIO_T * port,uint16_t pin)207 uint8_t GPIO_ReadInputBit(GPIO_T *port, uint16_t pin)
208 {
209     uint8_t readBit = 0x00;
210 
211     readBit = (port->IDATA & pin) ?  BIT_SET : BIT_RESET;
212 
213     return readBit;
214 }
215 
216 /*!
217  * @brief        Reads the specified GPIO input data port.
218  *
219  * @param        port :Select the GPIO port.
220  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
221  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
222  *
223  * @retval      GPIO input data port value.
224  */
GPIO_ReadInputPort(GPIO_T * port)225 uint16_t GPIO_ReadInputPort(GPIO_T *port)
226 {
227     return ((uint16_t)port->IDATA);
228 }
229 
230 /*!
231  * @brief        Reads the specified output data port bit.
232  *
233  * @param        port :Select the GPIO port.
234  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
235  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
236  *
237  * @param        pin: specifies the port bit to read.
238  *                    This parameter can be one of GPIO_Pin_x where x can be (0..15).
239  *
240  * @retval       The output port pin value.
241  */
GPIO_ReadOutputBit(GPIO_T * port,uint16_t pin)242 uint8_t GPIO_ReadOutputBit(GPIO_T *port, uint16_t pin)
243 {
244     uint8_t readBit = 0x00;
245 
246     readBit = (port->ODATA & pin) ? BIT_SET : BIT_RESET;
247 
248     return readBit;
249 }
250 
251 /*!
252  * @brief        Reads the specified GPIO output data port
253  *
254  * @param        port: Select the GPIO port.
255  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
256  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
257  *
258  * @retval       output data port value
259  */
GPIO_ReadOutputPort(GPIO_T * port)260 uint16_t GPIO_ReadOutputPort(GPIO_T *port)
261 {
262     return ((uint16_t)port->ODATA);
263 }
264 
265 /*!
266  * @brief        Sets the selected data port bits
267  *
268  * @param        port: Select the GPIO port.
269  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
270  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
271  *
272  * @param        pin : specifies pin to be written.
273  *                  This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
274  *
275  * @retval       None
276  */
GPIO_SetBit(GPIO_T * port,uint16_t pin)277 void GPIO_SetBit(GPIO_T *port, uint16_t pin)
278 {
279     port->BSCL = pin;
280 }
281 
282 /*!
283  * @brief     Clears the selected data port bits
284  *
285  * @param        port: Select the GPIO port.
286  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
287  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
288  *
289  * @param     pin : specifies pin to be cleared.
290  *                  This parameter can be any combination of GPIO_PIN_x( x can be from 0 to 15).
291  *
292  * @retval    None
293  */
GPIO_ResetBit(GPIO_T * port,uint16_t pin)294 void GPIO_ResetBit(GPIO_T *port, uint16_t pin)
295 {
296     port->BSCH = pin;
297 }
298 
299 /*!
300  * @brief        Writes data to the specified GPIO data port bit
301  *
302  * @param        port: Select the GPIO port.
303  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
304  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
305  *
306  * @param        pin : Select specifies pin.
307  *                  This parameter can be one of GPIO_PIN_x( x can be from 0 to 15).
308  *
309  * @param       bitVal : specifies the value to be written to the port output data register
310  *                       This parameter can be one of the following values:
311  *                       @arg BIT_RESET : Reset the port pin
312  *                       @arg BIT_SET   : Set the port pin
313  *
314  * @retval       None
315  */
GPIO_WriteBitValue(GPIO_T * port,uint16_t pin,uint8_t bitVal)316 void GPIO_WriteBitValue(GPIO_T *port, uint16_t pin, uint8_t bitVal)
317 {
318     if (bitVal != BIT_RESET)
319     {
320         port->BSCL = pin;
321     }
322     else
323     {
324         port->BSCH = pin ;
325     }
326 }
327 
328 /*!
329  * @brief        Writes data to the specified GPIO data port
330  *
331  * @param        port: Select the GPIO port.
332  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral
333  *                     for APM32F405xx/407xx and APM32F415xx/417xx devices
334  *
335  * @param        portValue : specifies the value to be written to the port output data register.
336  *
337  * @retval       None
338  */
GPIO_WriteOutputPort(GPIO_T * port,uint16_t portValue)339 void GPIO_WriteOutputPort(GPIO_T *port, uint16_t portValue)
340 {
341     port->ODATA = (uint16_t)portValue;
342 }
343 
344 /*!
345  * @brief       Toggles the specified GPIO pins.
346  *
347  * @param       port: Select the GPIO port.
348  *                    This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral.
349  *
350  * @param       pin: Specifies the pins to be toggled.
351  *
352  * @retval      None
353  */
GPIO_ToggleBit(GPIO_T * port,uint16_t pin)354 void GPIO_ToggleBit(GPIO_T *port, uint16_t pin)
355 {
356     port->ODATA ^= pin;
357 }
358 
359 /*!
360  * @brief        Changes the mapping of the specified pin.
361  *
362  * @param        port: Select the GPIO port.
363  *                     This parameter can be one of GPIOx(x=A..K) to select the GPIO peripheral.
364  *
365  * @param        gpioPinSource: specifies the pin for the Alternate function.
366  *                              This parameter can be GPIO_PinSourcex where x can be (0..15).
367  *
368  * @param        gpioAf: selects the pin to used as Alternate function.
369  *                       This parameter can be one of the following values:
370  *                       @arg GPIO_AF_RTC_50Hz: Connect RTC_50Hz pin to AF0 (default after reset)
371  *                       @arg GPIO_AF_MCO: Connect MCO pin (MCO1 and MCO2) to AF0 (default after reset)
372  *                       @arg GPIO_AF_TAMPER: Connect TAMPER pins (TAMPER_1 and TAMPER_2) to AF0 (default after reset)
373  *                       @arg GPIO_AF_SWJ: Connect SWJ pins (SWD and JTAG)to AF0 (default after reset)
374  *                       @arg GPIO_AF_TRACE: Connect TRACE pins to AF0 (default after reset)
375  *                       @arg GPIO_AF_TMR1: Connect TMR1 pins to AF1
376  *                       @arg GPIO_AF_TMR2: Connect TMR2 pins to AF1
377  *                       @arg GPIO_AF_TMR3: Connect TMR3 pins to AF2
378  *                       @arg GPIO_AF_TMR4: Connect TMR4 pins to AF2
379  *                       @arg GPIO_AF_TMR5: Connect TMR5 pins to AF2
380  *                       @arg GPIO_AF_TMR8: Connect TMR8 pins to AF3
381  *                       @arg GPIO_AF_TMR9: Connect TMR9 pins to AF3
382  *                       @arg GPIO_AF_TMR10: Connect TMR10 pins to AF3
383  *                       @arg GPIO_AF_TMR11: Connect TMR11 pins to AF3
384  *                       @arg GPIO_AF_I2C1: Connect I2C1 pins to AF4
385  *                       @arg GPIO_AF_I2C2: Connect I2C2 pins to AF4
386  *                       @arg GPIO_AF_I2C3: Connect I2C3 pins to AF4
387  *                       @arg GPIO_AF_SPI1: Connect SPI1 pins to AF5
388  *                       @arg GPIO_AF_SPI2: Connect SPI2/I2S2 pins to AF5
389  *                       @arg GPIO_AF_SPI4: Connect SPI4 pins to AF5
390  *                       @arg GPIO_AF_SPI5: Connect SPI5 pins to AF5
391  *                       @arg GPIO_AF_SPI6: Connect SPI6 pins to AF5
392  *                       @arg GPIO_AF_SAI1: Connect SAI1 pins to AF6
393  *                       @arg GPIO_AF_SPI3: Connect SPI3/I2S3 pins to AF6
394  *                       @arg GPIO_AF_I2S3ext: Connect I2S3ext pins to AF7
395  *                       @arg GPIO_AF_USART1: Connect USART1 pins to AF7
396  *                       @arg GPIO_AF_USART2: Connect USART2 pins to AF7
397  *                       @arg GPIO_AF_USART3: Connect USART3 pins to AF7
398  *                       @arg GPIO_AF_UART4: Connect UART4 pins to AF8
399  *                       @arg GPIO_AF_UART5: Connect UART5 pins to AF8
400  *                       @arg GPIO_AF_USART6: Connect USART6 pins to AF8
401  *                       @arg GPIO_AF_UART7: Connect UART7 pins to AF8
402  *                       @arg GPIO_AF_UART8: Connect UART8 pins to AF8
403  *                       @arg GPIO_AF_CAN1: Connect CAN1 pins to AF9
404  *                       @arg GPIO_AF_CAN2: Connect CAN2 pins to AF9
405  *                       @arg GPIO_AF_TMR12: Connect TMR12 pins to AF9
406  *                       @arg GPIO_AF_TMR13: Connect TMR13 pins to AF9
407  *                       @arg GPIO_AF_TMR14: Connect TMR14 pins to AF9
408  *                       @arg GPIO_AF_OTG_FS: Connect OTG_FS pins to AF10
409  *                       @arg GPIO_AF_OTG_HS: Connect OTG_HS pins to AF10
410  *                       @arg GPIO_AF_ETH: Connect ETHERNET pins to AF11
411  *                       @arg GPIO_AF_FSMC: Connect FSMC pins to AF12
412  *                       @arg GPIO_AF_OTG_HS_FS: Connect OTG HS (configured in FS) pins to AF12
413  *                       @arg GPIO_AF_SDIO: Connect SDIO pins to AF12
414  *                       @arg GPIO_AF_DCMI: Connect DCMI pins to AF13
415  *                       @arg GPIO_AF_EVENTOUT: Connect EVENTOUT pins to AF15
416  *
417  * @retval    None
418  */
GPIO_ConfigPinAF(GPIO_T * port,GPIO_PIN_SOURCE_T gpioPinSource,GPIO_AF_T gpioAf)419 void GPIO_ConfigPinAF(GPIO_T *port, GPIO_PIN_SOURCE_T gpioPinSource, GPIO_AF_T gpioAf)
420 {
421     uint32_t val = 0x00;
422     uint32_t val_2 = 0x00;
423 
424     if (gpioPinSource >> 0x03 == 0)
425     {
426         val = (uint32_t)(gpioAf) << (((uint32_t)gpioPinSource & (uint32_t)0x07) * 4);
427         port->ALFL &= ~((uint32_t)0xF << (((uint32_t)gpioPinSource & (uint32_t)0x07) * 4)) ;
428         val_2 = port->ALFL | val;
429         port->ALFL = val_2;
430     }
431     else
432     {
433         val = (uint32_t)(gpioAf) << (((uint32_t)gpioPinSource & (uint32_t)0x07) * 4);
434         port->ALFH &= ~((uint32_t)0xF << (((uint32_t)gpioPinSource & (uint32_t)0x07) * 4)) ;
435         val_2 = port->ALFH | val;
436         port->ALFH = val_2;
437     }
438 }
439 
440 /**@} end of group GPIO_Functions */
441 /**@} end of group GPIO_Driver */
442 /**@} end of group APM32F4xx_StdPeriphDriver */
443