1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #ifndef _FSL_PORT_H_
9 #define _FSL_PORT_H_
10
11 #include "fsl_common.h"
12
13 /*!
14 * @addtogroup port
15 * @{
16 */
17
18 /*******************************************************************************
19 * Definitions
20 ******************************************************************************/
21
22 /*! @name Driver version */
23 /*@{*/
24 /*! Version 2.0.2. */
25 #define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
26 /*@}*/
27
28 #if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
29 /*! @brief Internal resistor pull feature selection */
30 enum _port_pull
31 {
32 kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */
33 kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */
34 kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */
35 };
36 #endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
37
38 #if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
39 /*! @brief Slew rate selection */
40 enum _port_slew_rate
41 {
42 kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */
43 kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */
44 };
45 #endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
46
47 #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
48 /*! @brief Open Drain feature enable/disable */
49 enum _port_open_drain_enable
50 {
51 kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */
52 kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */
53 };
54 #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
55
56 #if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
57 /*! @brief Passive filter feature enable/disable */
58 enum _port_passive_filter_enable
59 {
60 kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */
61 kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */
62 };
63 #endif
64
65 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
66 /*! @brief Configures the drive strength. */
67 enum _port_drive_strength
68 {
69 kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */
70 kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */
71 };
72 #endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
73
74 #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
75 /*! @brief Unlock/lock the pin control register field[15:0] */
76 enum _port_lock_register
77 {
78 kPORT_UnlockRegister = 0U, /*!< Pin Control Register fields [15:0] are not locked. */
79 kPORT_LockRegister = 1U, /*!< Pin Control Register fields [15:0] are locked. */
80 };
81 #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
82
83 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
84 /*! @brief Pin mux selection */
85 typedef enum _port_mux
86 {
87 kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */
88 kPORT_MuxAsGpio = 1U, /*!< Corresponding pin is configured as GPIO. */
89 kPORT_MuxAlt2 = 2U, /*!< Chip-specific */
90 kPORT_MuxAlt3 = 3U, /*!< Chip-specific */
91 kPORT_MuxAlt4 = 4U, /*!< Chip-specific */
92 kPORT_MuxAlt5 = 5U, /*!< Chip-specific */
93 kPORT_MuxAlt6 = 6U, /*!< Chip-specific */
94 kPORT_MuxAlt7 = 7U, /*!< Chip-specific */
95 kPORT_MuxAlt8 = 8U, /*!< Chip-specific */
96 kPORT_MuxAlt9 = 9U, /*!< Chip-specific */
97 kPORT_MuxAlt10 = 10U, /*!< Chip-specific */
98 kPORT_MuxAlt11 = 11U, /*!< Chip-specific */
99 kPORT_MuxAlt12 = 12U, /*!< Chip-specific */
100 kPORT_MuxAlt13 = 13U, /*!< Chip-specific */
101 kPORT_MuxAlt14 = 14U, /*!< Chip-specific */
102 kPORT_MuxAlt15 = 15U, /*!< Chip-specific */
103 } port_mux_t;
104 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
105
106 /*! @brief Configures the interrupt generation condition. */
107 typedef enum _port_interrupt
108 {
109 kPORT_InterruptOrDMADisabled = 0x0U, /*!< Interrupt/DMA request is disabled. */
110 #if defined(FSL_FEATURE_PORT_HAS_DMA_REQUEST) && FSL_FEATURE_PORT_HAS_DMA_REQUEST
111 kPORT_DMARisingEdge = 0x1U, /*!< DMA request on rising edge. */
112 kPORT_DMAFallingEdge = 0x2U, /*!< DMA request on falling edge. */
113 kPORT_DMAEitherEdge = 0x3U, /*!< DMA request on either edge. */
114 #endif
115 #if defined(FSL_FEATURE_PORT_HAS_IRQC_FLAG) && FSL_FEATURE_PORT_HAS_IRQC_FLAG
116 kPORT_FlagRisingEdge = 0x05U, /*!< Flag sets on rising edge. */
117 kPORT_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
118 kPORT_FlagEitherEdge = 0x07U, /*!< Flag sets on either edge. */
119 #endif
120 kPORT_InterruptLogicZero = 0x8U, /*!< Interrupt when logic zero. */
121 kPORT_InterruptRisingEdge = 0x9U, /*!< Interrupt on rising edge. */
122 kPORT_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
123 kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */
124 kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */
125 #if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER
126 kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */
127 kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */
128 #endif
129 } port_interrupt_t;
130
131 #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
132 /*! @brief Digital filter clock source selection */
133 typedef enum _port_digital_filter_clock_source
134 {
135 kPORT_BusClock = 0U, /*!< Digital filters are clocked by the bus clock. */
136 kPORT_LpoClock = 1U, /*!< Digital filters are clocked by the 1 kHz LPO clock. */
137 } port_digital_filter_clock_source_t;
138
139 /*! @brief PORT digital filter feature configuration definition */
140 typedef struct _port_digital_filter_config
141 {
142 uint32_t digitalFilterWidth; /*!< Set digital filter width */
143 port_digital_filter_clock_source_t clockSource; /*!< Set digital filter clockSource */
144 } port_digital_filter_config_t;
145 #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
146
147 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
148 /*! @brief PORT pin configuration structure */
149 typedef struct _port_pin_config
150 {
151 #if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
152 uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */
153 #else
154 uint16_t : 2;
155 #endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
156
157 #if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
158 uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */
159 #else
160 uint16_t : 1;
161 #endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
162
163 uint16_t : 1;
164
165 #if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
166 uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */
167 #else
168 uint16_t : 1;
169 #endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */
170
171 #if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
172 uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */
173 #else
174 uint16_t : 1;
175 #endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
176
177 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
178 uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */
179 #else
180 uint16_t : 1;
181 #endif
182
183 uint16_t : 1;
184
185 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 3)
186 uint16_t mux : 3; /*!< Pin mux Configure */
187 uint16_t : 4;
188 #elif defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 4)
189 uint16_t mux : 4; /*!< Pin mux Configure */
190 uint16_t : 3;
191 #else
192 uint16_t : 7,
193 #endif
194
195 #if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
196 uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */
197 #else
198 uint16_t : 1;
199 #endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
200 } port_pin_config_t;
201 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
202
203 /*******************************************************************************
204 * API
205 ******************************************************************************/
206
207 #if defined(__cplusplus)
208 extern "C" {
209 #endif
210
211 #if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
212 /*! @name Configuration */
213 /*@{*/
214
215 /*!
216 * @brief Sets the port PCR register.
217 *
218 * This is an example to define an input pin or output pin PCR configuration.
219 * @code
220 * // Define a digital input pin PCR configuration
221 * port_pin_config_t config = {
222 * kPORT_PullUp,
223 * kPORT_FastSlewRate,
224 * kPORT_PassiveFilterDisable,
225 * kPORT_OpenDrainDisable,
226 * kPORT_LowDriveStrength,
227 * kPORT_MuxAsGpio,
228 * kPORT_UnLockRegister,
229 * };
230 * @endcode
231 *
232 * @param base PORT peripheral base pointer.
233 * @param pin PORT pin number.
234 * @param config PORT PCR register configuration structure.
235 */
PORT_SetPinConfig(PORT_Type * base,uint32_t pin,const port_pin_config_t * config)236 static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
237 {
238 assert(config);
239 uint32_t addr = (uint32_t)&base->PCR[pin];
240 *(volatile uint16_t *)(addr) = *((const uint16_t *)config);
241 }
242
243 /*!
244 * @brief Sets the port PCR register for multiple pins.
245 *
246 * This is an example to define input pins or output pins PCR configuration.
247 * @code
248 * // Define a digital input pin PCR configuration
249 * port_pin_config_t config = {
250 * kPORT_PullUp ,
251 * kPORT_PullEnable,
252 * kPORT_FastSlewRate,
253 * kPORT_PassiveFilterDisable,
254 * kPORT_OpenDrainDisable,
255 * kPORT_LowDriveStrength,
256 * kPORT_MuxAsGpio,
257 * kPORT_UnlockRegister,
258 * };
259 * @endcode
260 *
261 * @param base PORT peripheral base pointer.
262 * @param mask PORT pin number macro.
263 * @param config PORT PCR register configuration structure.
264 */
PORT_SetMultiplePinsConfig(PORT_Type * base,uint32_t mask,const port_pin_config_t * config)265 static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config)
266 {
267 assert(config);
268
269 uint16_t pcrl = *((const uint16_t *)config);
270
271 if (mask & 0xffffU)
272 {
273 base->GPCLR = ((mask & 0xffffU) << 16) | pcrl;
274 }
275 if (mask >> 16)
276 {
277 base->GPCHR = (mask & 0xffff0000U) | pcrl;
278 }
279 }
280
281 #if defined(FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG) && FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG
282 /*!
283 * @brief Sets the port interrupt configuration in PCR register for multiple pins.
284 *
285 * @param base PORT peripheral base pointer.
286 * @param mask PORT pin number macro.
287 * @param config PORT pin interrupt configuration.
288 * - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
289 * - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
290 * - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
291 * - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
292 * - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
293 * - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
294 * - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
295 * - #kPORT_InterruptLogicZero : Interrupt when logic zero.
296 * - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
297 * - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
298 * - #kPORT_InterruptEitherEdge : Interrupt on either edge.
299 * - #kPORT_InterruptLogicOne : Interrupt when logic one.
300 * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
301 * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit)..
302 */
PORT_SetMultipleInterruptPinsConfig(PORT_Type * base,uint32_t mask,port_interrupt_t config)303 static inline void PORT_SetMultipleInterruptPinsConfig(PORT_Type *base, uint32_t mask, port_interrupt_t config)
304 {
305 assert(config);
306
307 if (mask & 0xffffU)
308 {
309 base->GICLR = (config << 16) | (mask & 0xffffU);
310 }
311 if (mask >> 16)
312 {
313 base->GICHR = (config << 16) | (mask & 0xffff0000U);
314 }
315 }
316 #endif
317
318 /*!
319 * @brief Configures the pin muxing.
320 *
321 * @param base PORT peripheral base pointer.
322 * @param pin PORT pin number.
323 * @param mux pin muxing slot selection.
324 * - #kPORT_PinDisabledOrAnalog: Pin disabled or work in analog function.
325 * - #kPORT_MuxAsGpio : Set as GPIO.
326 * - #kPORT_MuxAlt2 : chip-specific.
327 * - #kPORT_MuxAlt3 : chip-specific.
328 * - #kPORT_MuxAlt4 : chip-specific.
329 * - #kPORT_MuxAlt5 : chip-specific.
330 * - #kPORT_MuxAlt6 : chip-specific.
331 * - #kPORT_MuxAlt7 : chip-specific.
332 * @Note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because
333 * the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is
334 * reset to zero : kPORT_PinDisabledOrAnalog).
335 * This function is recommended to use to reset the pin mux
336 *
337 */
PORT_SetPinMux(PORT_Type * base,uint32_t pin,port_mux_t mux)338 static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
339 {
340 base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux);
341 }
342 #endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
343
344 #if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
345
346 /*!
347 * @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin.
348 *
349 * @param base PORT peripheral base pointer.
350 * @param mask PORT pin number macro.
351 */
PORT_EnablePinsDigitalFilter(PORT_Type * base,uint32_t mask,bool enable)352 static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable)
353 {
354 if (enable == true)
355 {
356 base->DFER |= mask;
357 }
358 else
359 {
360 base->DFER &= ~mask;
361 }
362 }
363
364 /*!
365 * @brief Sets the digital filter in one port, each bit of the 32-bit register represents one pin.
366 *
367 * @param base PORT peripheral base pointer.
368 * @param config PORT digital filter configuration structure.
369 */
PORT_SetDigitalFilterConfig(PORT_Type * base,const port_digital_filter_config_t * config)370 static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digital_filter_config_t *config)
371 {
372 assert(config);
373
374 base->DFCR = PORT_DFCR_CS(config->clockSource);
375 base->DFWR = PORT_DFWR_FILT(config->digitalFilterWidth);
376 }
377
378 #endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
379
380 /*@}*/
381
382 /*! @name Interrupt */
383 /*@{*/
384
385 /*!
386 * @brief Configures the port pin interrupt/DMA request.
387 *
388 * @param base PORT peripheral base pointer.
389 * @param pin PORT pin number.
390 * @param config PORT pin interrupt configuration.
391 * - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
392 * - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
393 * - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
394 * - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
395 * - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
396 * - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
397 * - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
398 * - #kPORT_InterruptLogicZero : Interrupt when logic zero.
399 * - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
400 * - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
401 * - #kPORT_InterruptEitherEdge : Interrupt on either edge.
402 * - #kPORT_InterruptLogicOne : Interrupt when logic one.
403 * - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
404 * - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit).
405 */
PORT_SetPinInterruptConfig(PORT_Type * base,uint32_t pin,port_interrupt_t config)406 static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
407 {
408 base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
409 }
410
411 #if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
412 /*!
413 * @brief Configures the port pin drive strength.
414 *
415 * @param base PORT peripheral base pointer.
416 * @param pin PORT pin number.
417 * @param config PORT pin drive strength
418 * - #kPORT_LowDriveStrength = 0U - Low-drive strength is configured.
419 * - #kPORT_HighDriveStrength = 1U - High-drive strength is configured.
420 */
PORT_SetPinDriveStrength(PORT_Type * base,uint32_t pin,uint8_t strength)421 static inline void PORT_SetPinDriveStrength(PORT_Type* base, uint32_t pin, uint8_t strength)
422 {
423 base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_DSE_MASK) | PORT_PCR_DSE(strength);
424 }
425 #endif
426
427 /*!
428 * @brief Reads the whole port status flag.
429 *
430 * If a pin is configured to generate the DMA request, the corresponding flag
431 * is cleared automatically at the completion of the requested DMA transfer.
432 * Otherwise, the flag remains set until a logic one is written to that flag.
433 * If configured for a level sensitive interrupt that remains asserted, the flag
434 * is set again immediately.
435 *
436 * @param base PORT peripheral base pointer.
437 * @return Current port interrupt status flags, for example, 0x00010001 means the
438 * pin 0 and 16 have the interrupt.
439 */
PORT_GetPinsInterruptFlags(PORT_Type * base)440 static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
441 {
442 return base->ISFR;
443 }
444
445 /*!
446 * @brief Clears the multiple pin interrupt status flag.
447 *
448 * @param base PORT peripheral base pointer.
449 * @param mask PORT pin number macro.
450 */
PORT_ClearPinsInterruptFlags(PORT_Type * base,uint32_t mask)451 static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
452 {
453 base->ISFR = mask;
454 }
455
456 /*@}*/
457
458 #if defined(__cplusplus)
459 }
460 #endif
461
462 /*! @}*/
463
464 #endif /* _FSL_PORT_H_ */
465