1 /*
2 * Copyright 2017-2020 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_gpio.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.gpio_1"
17 #endif
18
19 #define PORT_NUMBERS_EACH_GPIO (4U)
20 #define PIN_NUMBERS_EACH_PORT (8UL)
21 /*******************************************************************************
22 * Variables
23 ******************************************************************************/
24 #if defined(FSL_FEATURE_SOC_GPIO_COUNT) && FSL_FEATURE_SOC_GPIO_COUNT
25 static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
26 #endif
27
28 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
29 static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
30 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
31
32 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
33 /*! @brief Array to map FGPIO instance number to clock name. */
34 static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
35 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
36
37 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
38
39 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
40
41 /*******************************************************************************
42 * Prototypes
43 ******************************************************************************/
44
45 /*******************************************************************************
46 * Code
47 ******************************************************************************/
48
49 /*!
50 * brief Initializes a GPIO pin used by the board.
51 *
52 * To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
53 * Then, call the GPIO_PinInit() function.
54 *
55 * This is an example to define an input pin or an output pin configuration.
56 * code
57 * Define a digital input pin configuration,
58 * gpio_pin_config_t config =
59 * {
60 * kGPIO_DigitalInput,
61 * 0,
62 * }
63 * Define a digital output pin configuration,
64 * gpio_pin_config_t config =
65 * {
66 * kGPIO_DigitalOutput,
67 * 0,
68 * }
69 * endcode
70 *
71 * param port GPIO PORT number, see "gpio_port_num_t".
72 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
73 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
74 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
75 * ...
76 * param pin GPIO port pin number
77 * param config GPIO pin configuration pointer
78 */
GPIO_PinInit(gpio_port_num_t port,uint8_t pin,const gpio_pin_config_t * config)79 void GPIO_PinInit(gpio_port_num_t port, uint8_t pin, const gpio_pin_config_t *config)
80 {
81 assert(config);
82
83 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
84 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
85 GPIO_Type *base = s_gpioBases[instance];
86
87 if (config->pinDirection == kGPIO_DigitalInput)
88 {
89 base->PDDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
90 base->PIDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
91 }
92 else
93 {
94 GPIO_PinWrite(port, pin, config->outputLogic);
95 base->PDDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
96 base->PIDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
97 }
98 }
99
100 /*!
101 * brief Sets the output level of the multiple GPIO pins to the logic 1 or 0.
102 *
103 * param port GPIO PORT number, see "gpio_port_num_t".
104 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
105 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
106 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
107 * ...
108 * param pin GPIO pin number
109 * param output GPIO pin output logic level.
110 * - 0: corresponding pin output low-logic level.
111 * - 1: corresponding pin output high-logic level.
112 */
GPIO_PinWrite(gpio_port_num_t port,uint8_t pin,uint8_t output)113 void GPIO_PinWrite(gpio_port_num_t port, uint8_t pin, uint8_t output)
114 {
115 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
116 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
117 GPIO_Type *base = s_gpioBases[instance];
118
119 if (output == 0U)
120 {
121 base->PCOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
122 }
123 else
124 {
125 base->PSOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
126 }
127 }
128
129 /*!
130 * brief Sets the output level of the multiple GPIO pins to the logic 1.
131 *
132 * param port GPIO PORT number, see "gpio_port_num_t".
133 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
134 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
135 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
136 * ...
137 * param mask GPIO pin number macro
138 */
GPIO_PortSet(gpio_port_num_t port,uint8_t mask)139 void GPIO_PortSet(gpio_port_num_t port, uint8_t mask)
140 {
141 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
142 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
143 GPIO_Type *base = s_gpioBases[instance];
144
145 base->PSOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
146 }
147
148 /*!
149 * brief Sets the output level of the multiple GPIO pins to the logic 0.
150 *
151 * param port GPIO PORT number, see "gpio_port_num_t".
152 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
153 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
154 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
155 * ...
156 * param mask GPIO pin number macro
157 */
GPIO_PortClear(gpio_port_num_t port,uint8_t mask)158 void GPIO_PortClear(gpio_port_num_t port, uint8_t mask)
159 {
160 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
161 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
162 GPIO_Type *base = s_gpioBases[instance];
163
164 base->PCOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
165 }
166
167 /*!
168 * brief Reverses the current output logic of the multiple GPIO pins.
169 *
170 * param port GPIO PORT number, see "gpio_port_num_t".
171 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
172 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
173 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
174 * ...
175 * param mask GPIO pin number macro
176 */
GPIO_PortToggle(gpio_port_num_t port,uint8_t mask)177 void GPIO_PortToggle(gpio_port_num_t port, uint8_t mask)
178 {
179 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
180 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
181 GPIO_Type *base = s_gpioBases[instance];
182
183 base->PTOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
184 }
185
186 /*!
187 * brief Reads the current input value of the GPIO port.
188 *
189 * param port GPIO PORT number, see "gpio_port_num_t".
190 * For each group GPIO (GPIOA, GPIOB,etc) control registers, they handles four PORT number controls.
191 * GPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
192 * GPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
193 * ...
194 * param pin GPIO pin number
195 * retval GPIO port input value
196 * - 0: corresponding pin input low-logic level.
197 * - 1: corresponding pin input high-logic level.
198 */
GPIO_PinRead(gpio_port_num_t port,uint8_t pin)199 uint32_t GPIO_PinRead(gpio_port_num_t port, uint8_t pin)
200 {
201 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
202 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
203 GPIO_Type *base = s_gpioBases[instance];
204
205 return (((base->PDIR) >> ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT))) & 0x01UL);
206 }
207
208 #if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
209
210 /*******************************************************************************
211 * Variables
212 ******************************************************************************/
213
214 /*******************************************************************************
215 * Prototypes
216 ******************************************************************************/
217 /*!
218 * @brief Enable the FGPIO clock.
219 *
220 * @param port FGPIO PORT number.
221 */
222 static void FGPIO_EnableClock(gpio_port_num_t port);
223
224 /*******************************************************************************
225 * Code
226 ******************************************************************************/
FGPIO_EnableClock(gpio_port_num_t port)227 static void FGPIO_EnableClock(gpio_port_num_t port)
228 {
229 #if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
230 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
231 FGPIO_Type *base = s_fgpioBases[instance];
232
233 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
234 /* Ungate FGPIO periphral clock */
235 CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
236 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
237 #endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
238 }
239
FGPIO_PortInit(gpio_port_num_t port)240 void FGPIO_PortInit(gpio_port_num_t port)
241 {
242 FGPIO_EnableClock(port);
243 }
244
245 /*!
246 * brief Initializes a FGPIO pin used by the board.
247 *
248 * To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
249 * Then, call the FGPIO_PinInit() function.
250 *
251 * This is an example to define an input pin or an output pin configuration:
252 * code
253 * Define a digital input pin configuration,
254 * gpio_pin_config_t config =
255 * {
256 * kGPIO_DigitalInput,
257 * 0,
258 * }
259 * Define a digital output pin configuration,
260 * gpio_pin_config_t config =
261 * {
262 * kGPIO_DigitalOutput,
263 * 0,
264 * }
265 * endcode
266 *
267 * param port FGPIO PORT number, see "gpio_port_num_t".
268 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
269 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
270 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
271 * ...
272 * param pin FGPIO port pin number
273 * param config FGPIO pin configuration pointer
274 */
FGPIO_PinInit(gpio_port_num_t port,uint8_t pin,const gpio_pin_config_t * config)275 void FGPIO_PinInit(gpio_port_num_t port, uint8_t pin, const gpio_pin_config_t *config)
276 {
277 assert(config);
278
279 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
280 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
281 FGPIO_Type *base = s_fgpioBases[instance];
282
283 FGPIO_EnableClock(port);
284
285 if (config->pinDirection == kGPIO_DigitalInput)
286 {
287 base->PDDR &= ~(1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
288 }
289 else
290 {
291 FGPIO_PinWrite(port, pin, config->outputLogic);
292 base->PDDR |= (1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT)));
293 }
294 }
295
296 /*!
297 * brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0.
298 *
299 * param port FGPIO PORT number, see "gpio_port_num_t".
300 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
301 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
302 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
303 * ...
304 * param pin FGPIO pin number
305 * param output FGPIOpin output logic level.
306 * - 0: corresponding pin output low-logic level.
307 * - 1: corresponding pin output high-logic level.
308 */
FGPIO_PinWrite(gpio_port_num_t port,uint8_t pin,uint8_t output)309 void FGPIO_PinWrite(gpio_port_num_t port, uint8_t pin, uint8_t output)
310 {
311 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
312 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
313 FGPIO_Type *base = s_fgpioBases[instance];
314
315 if (output == 0U)
316 {
317 base->PCOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
318 }
319 else
320 {
321 base->PSOR = 1UL << ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT));
322 }
323 }
324
325 /*!
326 * brief Sets the output level of the multiple FGPIO pins to the logic 1.
327 *
328 * param port FGPIO PORT number, see "gpio_port_num_t".
329 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
330 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
331 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
332 * ...
333 * param mask FGPIO pin number macro
334 */
FGPIO_PortSet(gpio_port_num_t port,uint8_t mask)335 void FGPIO_PortSet(gpio_port_num_t port, uint8_t mask)
336 {
337 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
338 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
339 FGPIO_Type *base = s_fgpioBases[instance];
340
341 base->PSOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
342 }
343
344 /*!
345 * brief Sets the output level of the multiple FGPIO pins to the logic 0.
346 *
347 * param port FGPIO PORT number, see "gpio_port_num_t".
348 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
349 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
350 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
351 * ...
352 * param mask FGPIO pin number macro
353 */
FGPIO_PortClear(gpio_port_num_t port,uint8_t mask)354 void FGPIO_PortClear(gpio_port_num_t port, uint8_t mask)
355 {
356 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
357 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
358 FGPIO_Type *base = s_fgpioBases[instance];
359
360 base->PCOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
361 }
362
363 /*!
364 * brief Reverses the current output logic of the multiple FGPIO pins.
365 *
366 * param port FGPIO PORT number, see "gpio_port_num_t".
367 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
368 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
369 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
370 * ...
371 * param mask FGPIO pin number macro
372 */
FGPIO_PortToggle(gpio_port_num_t port,uint8_t mask)373 void FGPIO_PortToggle(gpio_port_num_t port, uint8_t mask)
374 {
375 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
376 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
377 FGPIO_Type *base = s_fgpioBases[instance];
378
379 base->PTOR = ((uint32_t)mask << (shift * PIN_NUMBERS_EACH_PORT));
380 }
381
382 /*!
383 * brief Reads the current input value of the FGPIO port.
384 *
385 * param port FGPIO PORT number, see "gpio_port_num_t".
386 * For each group FGPIO (FGPIOA, FGPIOB,etc) control registers, they handles four PORT number controls.
387 * FGPIOA serial registers ----- PTA 0 ~ 7, PTB 0 ~7 ... PTD 0 ~ 7.
388 * FGPIOB serial registers ----- PTE 0 ~ 7, PTF 0 ~7 ... PTH 0 ~ 7.
389 * ...
390 * param pin FGPIO pin number
391 * retval FGPIO port input value
392 * - 0: corresponding pin input low-logic level.
393 * - 1: corresponding pin input high-logic level.
394 */
FGPIO_PinRead(gpio_port_num_t port,uint8_t pin)395 uint32_t FGPIO_PinRead(gpio_port_num_t port, uint8_t pin)
396 {
397 uint8_t instance = (uint8_t)port / PORT_NUMBERS_EACH_GPIO;
398 uint8_t shift = (uint8_t)port % PORT_NUMBERS_EACH_GPIO;
399 FGPIO_Type *base = s_fgpioBases[instance];
400
401 return (((base->PDIR) >> ((uint32_t)pin + (shift * PIN_NUMBERS_EACH_PORT))) & 0x01UL);
402 }
403
404 #endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
405