[bsp][nxp]support FRDM-MCXA156 (#9971)

support FRDM-MCXA156

Co-authored-by: shannon <xxlong1999@163.com>
This commit is contained in:
Rbb666 2025-02-07 09:45:56 +08:00 committed by GitHub
parent 8629c9572a
commit a63b97e316
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
146 changed files with 135645 additions and 0 deletions

View File

@ -234,6 +234,7 @@ jobs:
- "nxp/mcx/mcxn/frdm-mcxn947"
- "nxp/mcx/mcxn/frdm-mcxn236"
- "nxp/mcx/mcxa/frdm-mcxa153"
- "nxp/mcx/mcxa/frdm-mcxa156"
- "renesas/ebf_qi_min_6m5"
- "renesas/ra6m4-cpk"
- "renesas/ra6m4-iot"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,793 @@
/*
** ###################################################################
** Version: rev. 1.0, 2022-03-29
** Build: b240411
**
** Abstract:
** Chip specific module features.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2024 NXP
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2022-03-29)
** Initial version based on v0.1UM
**
** ###################################################################
*/
#ifndef _MCXA156_FEATURES_H_
#define _MCXA156_FEATURES_H_
/* SOC module features */
/* @brief AOI availability on the SoC. */
#define FSL_FEATURE_SOC_AOI_COUNT (2)
/* @brief CDOG availability on the SoC. */
#define FSL_FEATURE_SOC_CDOG_COUNT (1)
/* @brief CMC availability on the SoC. */
#define FSL_FEATURE_SOC_CMC_COUNT (1)
/* @brief CRC availability on the SoC. */
#define FSL_FEATURE_SOC_CRC_COUNT (1)
/* @brief CTIMER availability on the SoC. */
#define FSL_FEATURE_SOC_CTIMER_COUNT (5)
/* @brief EDMA availability on the SoC. */
#define FSL_FEATURE_SOC_EDMA_COUNT (1)
/* @brief EIM availability on the SoC. */
#define FSL_FEATURE_SOC_EIM_COUNT (1)
/* @brief EQDC availability on the SoC. */
#define FSL_FEATURE_SOC_EQDC_COUNT (2)
/* @brief FLEXCAN availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCAN_COUNT (1)
/* @brief FLEXIO availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXIO_COUNT (1)
/* @brief FMC availability on the SoC. */
#define FSL_FEATURE_SOC_FMC_COUNT (1)
/* @brief FREQME availability on the SoC. */
#define FSL_FEATURE_SOC_FREQME_COUNT (1)
/* @brief GPIO availability on the SoC. */
#define FSL_FEATURE_SOC_GPIO_COUNT (5)
/* @brief SPC availability on the SoC. */
#define FSL_FEATURE_SOC_SPC_COUNT (1)
/* @brief I3C availability on the SoC. */
#define FSL_FEATURE_SOC_I3C_COUNT (1)
/* @brief INPUTMUX availability on the SoC. */
#define FSL_FEATURE_SOC_INPUTMUX_COUNT (1)
/* @brief LPADC availability on the SoC. */
#define FSL_FEATURE_SOC_LPADC_COUNT (2)
/* @brief LPCMP availability on the SoC. */
#define FSL_FEATURE_SOC_LPCMP_COUNT (2)
/* @brief LPDAC availability on the SoC. */
#define FSL_FEATURE_SOC_LPDAC_COUNT (1)
/* @brief LPI2C availability on the SoC. */
#define FSL_FEATURE_SOC_LPI2C_COUNT (4)
/* @brief LPSPI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSPI_COUNT (2)
/* @brief LPTMR availability on the SoC. */
#define FSL_FEATURE_SOC_LPTMR_COUNT (1)
/* @brief LPUART availability on the SoC. */
#define FSL_FEATURE_SOC_LPUART_COUNT (5)
/* @brief OPAMP availability on the SoC. */
#define FSL_FEATURE_SOC_OPAMP_COUNT (1)
/* @brief OSTIMER availability on the SoC. */
#define FSL_FEATURE_SOC_OSTIMER_COUNT (1)
/* @brief PORT availability on the SoC. */
#define FSL_FEATURE_SOC_PORT_COUNT (5)
/* @brief PWM availability on the SoC. */
#define FSL_FEATURE_SOC_PWM_COUNT (2)
/* @brief SCG availability on the SoC. */
#define FSL_FEATURE_SOC_SCG_COUNT (1)
/* @brief SYSCON availability on the SoC. */
#define FSL_FEATURE_SOC_SYSCON_COUNT (1)
/* @brief USB availability on the SoC. */
#define FSL_FEATURE_SOC_USB_COUNT (1)
/* @brief UTICK availability on the SoC. */
#define FSL_FEATURE_SOC_UTICK_COUNT (1)
/* @brief WAKETIMER availability on the SoC. */
#define FSL_FEATURE_SOC_WAKETIMER_COUNT (1)
/* @brief WWDT availability on the SoC. */
#define FSL_FEATURE_SOC_WWDT_COUNT (1)
/* @brief WUU availability on the SoC. */
#define FSL_FEATURE_SOC_WUU_COUNT (1)
/* LPADC module features */
/* @brief FIFO availability on the SoC. */
#define FSL_FEATURE_LPADC_FIFO_COUNT (1)
/* @brief Has subsequent trigger priority (bitfield CFG[TPRICTRL]). */
#define FSL_FEATURE_LPADC_HAS_CFG_SUBSEQUENT_PRIORITY (1)
/* @brief Has differential mode (bitfield CMDLn[DIFF]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_DIFF (0)
/* @brief Has channel scale (bitfield CMDLn[CSCALE]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_CSCALE (0)
/* @brief Has conversion type select (bitfield CMDLn[CTYPE]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_CTYPE (1)
/* @brief Has conversion resolution select (bitfield CMDLn[MODE]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_MODE (1)
/* @brief Has compare function enable (bitfield CMDHn[CMPEN]). */
#define FSL_FEATURE_LPADC_HAS_CMDH_CMPEN (1)
/* @brief Has Wait for trigger assertion before execution (bitfield CMDHn[WAIT_TRIG]). */
#define FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG (1)
/* @brief Has offset calibration (bitfield CTRL[CALOFS]). */
#define FSL_FEATURE_LPADC_HAS_CTRL_CALOFS (1)
/* @brief Has gain calibration (bitfield CTRL[CAL_REQ]). */
#define FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ (1)
/* @brief Has calibration average (bitfield CTRL[CAL_AVGS]). */
#define FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS (1)
/* @brief Has internal clock (bitfield CFG[ADCKEN]). */
#define FSL_FEATURE_LPADC_HAS_CFG_ADCKEN (0)
/* @brief Enable support for low voltage reference on option 1 reference (bitfield CFG[VREF1RNG]). */
#define FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG (0)
/* @brief Has calibration (bitfield CFG[CALOFS]). */
#define FSL_FEATURE_LPADC_HAS_CFG_CALOFS (0)
/* @brief Has offset trim (register OFSTRIM). */
#define FSL_FEATURE_LPADC_HAS_OFSTRIM (1)
/* @brief OFSTRIM availability on the SoC. */
#define FSL_FEATURE_LPADC_OFSTRIM_COUNT (1)
/* @brief Has Trigger status register. */
#define FSL_FEATURE_LPADC_HAS_TSTAT (1)
/* @brief Has power select (bitfield CFG[PWRSEL]). */
#define FSL_FEATURE_LPADC_HAS_CFG_PWRSEL (1)
/* @brief Has alternate channel B scale (bitfield CMDLn[ALTB_CSCALE]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE (0)
/* @brief Has alternate channel B select enable (bitfield CMDLn[ALTBEN]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN (0)
/* @brief Has alternate channel input (bitfield CMDLn[ALTB_ADCH]). */
#define FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH (0)
/* @brief Has offset calibration mode (bitfield CTRL[CALOFSMODE]). */
#define FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE (0)
/* @brief Conversion averaged bitfiled width. */
#define FSL_FEATURE_LPADC_CONVERSIONS_AVERAGED_BITFIELD_WIDTH (4)
/* @brief Has B side channels. */
#define FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS (0)
/* @brief Indicate whether the LPADC STAT register has trigger exception interrupt function (bitfield STAT[TEXC_INT]). */
#define FSL_FEATURE_LPADC_HAS_STAT_TEXC_INT (1)
/* @brief Indicate whether the LPADC STAT register has trigger completion interrupt function (bitfield STAT[TCOMP_INT]). */
#define FSL_FEATURE_LPADC_HAS_STAT_TCOMP_INT (1)
/* @brief Indicate whether the LPADC STAT register has calibration ready function (bitfield STAT[CAL_RDY]). */
#define FSL_FEATURE_LPADC_HAS_STAT_CAL_RDY (1)
/* @brief Indicate whether the LPADC STAT register has ADC active function (bitfield STAT[ADC_ACTIVE]). */
#define FSL_FEATURE_LPADC_HAS_STAT_ADC_ACTIVE (1)
/* @brief Indicate whether the LPADC IE register has trigger exception interrupt enable function (bitfield IE[TEXC_IE]). */
#define FSL_FEATURE_LPADC_HAS_IE_TEXC_IE (1)
/* @brief Indicate whether the LPADC IE register has trigger completion interrupt enable function (bitfield IE[TCOMP_IE]). */
#define FSL_FEATURE_LPADC_HAS_IE_TCOMP_IE (1)
/* @brief Indicate whether the LPADC CFG register has trigger resume/restart enable function (bitfield CFG[TRES]). */
#define FSL_FEATURE_LPADC_HAS_CFG_TRES (1)
/* @brief Indicate whether the LPADC CFG register has trigger command resume/restart enable function (bitfield CFG[TCMDRES]). */
#define FSL_FEATURE_LPADC_HAS_CFG_TCMDRES (1)
/* @brief Indicate whether the LPADC CFG register has high priority trigger exception disable function (bitfield CFG[HPT_EXDI]). */
#define FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI (1)
/* @brief Indicate LPADC CFG register TPRICTRL bitfield width. */
#define FSL_FEATURE_LPADC_CFG_TPRICTRL_BITFIELD_WIDTH (2)
/* @brief Has internal temperature sensor. */
#define FSL_FEATURE_LPADC_HAS_INTERNAL_TEMP_SENSOR (1)
/* @brief Temperature sensor parameter A (slope). */
#define FSL_FEATURE_LPADC_TEMP_PARAMETER_A (738.0f)
/* @brief Temperature sensor parameter B (offset). */
#define FSL_FEATURE_LPADC_TEMP_PARAMETER_B (287.5f)
/* @brief Temperature sensor parameter Alpha. */
#define FSL_FEATURE_LPADC_TEMP_PARAMETER_ALPHA (10.06f)
/* @brief The buffer size of temperature sensor. */
#define FSL_FEATURE_LPADC_TEMP_SENS_BUFFER_SIZE (2U)
/* AOI module features */
/* @brief Maximum value of input mux. */
#define FSL_FEATURE_AOI_MODULE_INPUTS (4)
/* @brief Number of events related to number of registers AOIx_BFCRT01n/AOIx_BFCRT23n. */
#define FSL_FEATURE_AOI_EVENT_COUNT (4)
/* FLEXCAN module features */
/* @brief Has more than 64 MBs. */
#define FSL_FEATURE_FLEXCAN_HAS_MORE_THAN_64_MB (0)
/* @brief Message buffer size */
#define FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(x) (32)
/* @brief Has doze mode support (register bit field MCR[DOZE]). */
#define FSL_FEATURE_FLEXCAN_HAS_DOZE_MODE_SUPPORT (1)
/* @brief Insatnce has doze mode support (register bit field MCR[DOZE]). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_DOZE_MODE_SUPPORTn(x) (1)
/* @brief Has a glitch filter on the receive pin (register bit field MCR[WAKSRC]). */
#define FSL_FEATURE_FLEXCAN_HAS_GLITCH_FILTER (1)
/* @brief Has extended interrupt mask and flag register (register IMASK2, IFLAG2). */
#define FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER (0)
/* @brief Instance has extended bit timing register (register CBT). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_EXTENDED_TIMING_REGISTERn(x) (1)
/* @brief Has a receive FIFO DMA feature (register bit field MCR[DMA]). */
#define FSL_FEATURE_FLEXCAN_HAS_RX_FIFO_DMA (1)
/* @brief Instance has a receive FIFO DMA feature (register bit field MCR[DMA]). */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_RX_FIFO_DMAn(x) (1)
/* @brief Remove CAN Engine Clock Source Selection from unsupported part. */
#define FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE (1)
/* @brief Instance remove CAN Engine Clock Source Selection from unsupported part. */
#define FSL_FEATURE_FLEXCAN_INSTANCE_SUPPORT_ENGINE_CLK_SEL_REMOVEn(x) (1)
/* @brief Is affected by errata with ID 5641 (Module does not transmit a message that is enabled to be transmitted at a specific moment during the arbitration process). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641 (0)
/* @brief Is affected by errata with ID 5829 (FlexCAN: FlexCAN does not transmit a message that is enabled to be transmitted in a specific moment during the arbitration process). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829 (0)
/* @brief Is affected by errata with ID 6032 (FlexCAN: A frame with wrong ID or payload is transmitted into the CAN bus when the Message Buffer under transmission is either aborted or deactivated while the CAN bus is in the Bus Idle state). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_6032 (0)
/* @brief Is affected by errata with ID 9595 (FlexCAN: Corrupt frame possible if the Freeze Mode or the Low-Power Mode are entered during a Bus-Off state). */
#define FSL_FEATURE_FLEXCAN_HAS_ERRATA_9595 (0)
/* @brief Has CAN with Flexible Data rate (CAN FD) protocol. */
#define FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE (1)
/* @brief CAN instance support Flexible Data rate (CAN FD) protocol. */
#define FSL_FEATURE_FLEXCAN_INSTANCE_HAS_FLEXIBLE_DATA_RATEn(x) (1)
/* @brief Has memory error control (register MECR). */
#define FSL_FEATURE_FLEXCAN_HAS_MEMORY_ERROR_CONTROL (0)
/* @brief Has enhanced bit timing register (register EPRS, ENCBT, EDCBT and ETDC). */
#define FSL_FEATURE_FLEXCAN_HAS_ENHANCED_BIT_TIMING_REG (1)
/* @brief Has Pretended Networking mode support. */
#define FSL_FEATURE_FLEXCAN_HAS_PN_MODE (1)
/* @brief Has Enhanced Rx FIFO. */
#define FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO (1)
/* @brief Enhanced Rx FIFO size (Indicates how many CAN FD messages can be stored). */
#define FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_SIZE (12)
/* @brief The number of enhanced Rx FIFO filter element registers. */
#define FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO_FILTER_MAX_NUMBER (32)
/* @brief Does not support Supervisor Mode (bitfield MCR[SUPV]. */
#define FSL_FEATURE_FLEXCAN_HAS_NO_SUPV_SUPPORT (1)
/* CDOG module features */
/* @brief CDOG Has No Reset */
#define FSL_FEATURE_CDOG_HAS_NO_RESET (1)
/* CMC module features */
/* @brief Has SRAM_DIS register */
#define FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG (0)
/* @brief Has BSR register */
#define FSL_FEATURE_MCX_CMC_HAS_BSR_REG (0)
/* @brief Has RSTCNT register */
#define FSL_FEATURE_MCX_CMC_HAS_RSTCNT_REG (1)
/* @brief Has BLR register */
#define FSL_FEATURE_MCX_CMC_HAS_BLR_REG (0)
/* LPCMP module features */
/* @brief Has CCR1 FUNC_CLK_SEL bitfield. */
#define FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL (1)
/* @brief Has IER RRF_IE bitfield. */
#define FSL_FEATURE_LPCMP_HAS_IER_RRF_IE (1)
/* @brief Has CSR RRF bitfield. */
#define FSL_FEATURE_LPCMP_HAS_CSR_RRF (1)
/* @brief Has Round Robin mode (related to existence of registers RRCR0). */
#define FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE (1)
/* @brief Has window mode (related to existence of CCR1.WINDOW_CLS). */
#define FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL (1)
/* CTIMER module features */
/* @brief CTIMER has no capture channel. */
#define FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE (0)
/* @brief CTIMER has no capture 2 interrupt. */
#define FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT (0)
/* @brief CTIMER capture 3 interrupt. */
#define FSL_FEATURE_CTIMER_HAS_IR_CR3INT (1)
/* @brief Has CTIMER CCR_CAP2 (register bits CCR[CAP2RE][CAP2FE][CAP2I]. */
#define FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 (0)
/* @brief Has CTIMER CCR_CAP3 (register bits CCR[CAP3RE][CAP3FE][CAP3I]). */
#define FSL_FEATURE_CTIMER_HAS_CCR_CAP3 (1)
/* @brief CTIMER Has register MSR */
#define FSL_FEATURE_CTIMER_HAS_MSR (1)
/* LPDAC module features */
/* @brief FIFO size. */
#define FSL_FEATURE_LPDAC_FIFO_SIZE (16)
/* @brief Has OPAMP as buffer, speed control signal (bitfield GCR[BUF_SPD_CTRL]). */
#define FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL (1)
/* @brief Buffer Enable(bitfield GCR[BUF_EN]). */
#define FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN (1)
/* @brief RCLK cycles before data latch(bitfield GCR[LATCH_CYC]). */
#define FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC (1)
/* @brief VREF source number. */
#define FSL_FEATURE_ANALOG_NUM_OF_VREF_SRC (3)
/* @brief Has internal reference current options. */
#define FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT (1)
/* EDMA module features */
/* @brief Number of DMA channels (related to number of registers TCD, DCHPRI, bit fields ERQ[ERQn], EEI[EEIn], INT[INTn], ERR[ERRn], HRS[HRSn] and bit field widths ES[ERRCHN], CEEI[CEEI], SEEI[SEEI], CERQ[CERQ], SERQ[SERQ], CDNE[CDNE], SSRT[SSRT], CERR[CERR], CINT[CINT], TCDn_CITER_ELINKYES[LINKCH], TCDn_CSR[MAJORLINKCH], TCDn_BITER_ELINKYES[LINKCH]). (Valid only for eDMA modules.) */
#define FSL_FEATURE_EDMA_MODULE_CHANNEL (8)
/* @brief If 8 bytes transfer supported. */
#define FSL_FEATURE_EDMA_SUPPORT_8_BYTES_TRANSFER (1)
/* @brief Number of DMA channel groups (register bit fields CR[ERGA], CR[GRPnPRI], ES[GPE], DCHPRIn[GRPPRI]). (Valid only for eDMA modules.) */
#define FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT (1)
/* @brief If 16 bytes transfer supported. */
#define FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER (1)
/* @brief Has DMA_Error interrupt vector. */
#define FSL_FEATURE_EDMA_HAS_ERROR_IRQ (1)
/* @brief If 64 bytes transfer supported. */
#define FSL_FEATURE_EDMA_SUPPORT_64_BYTES_TRANSFER (1)
/* @brief If channel clock controlled independently */
#define FSL_FEATURE_EDMA_CHANNEL_HAS_OWN_CLOCK_GATE (1)
/* @brief If 128 bytes transfer supported. */
#define FSL_FEATURE_EDMA_SUPPORT_128_BYTES_TRANSFER (1)
/* @brief Number of channel for each EDMA instance, (only defined for soc with different channel numbers for difference instance) */
#define FSL_FEATURE_EDMA_INSTANCE_CHANNELn(x) (8)
/* @brief If 128 bytes transfer supported. */
#define FSL_FEATURE_EDMA_INSTANCE_SUPPORT_128_BYTES_TRANSFERn(x) (1)
/* @brief Has no register bit fields MP_CSR[EBW]. */
#define FSL_FEATURE_EDMA_HAS_NO_MP_CSR_EBW (1)
/* @brief Has register CH_CSR. */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG (1)
/* @brief If dma has common clock gate */
#define FSL_FEATURE_EDMA_HAS_COMMON_CLOCK_GATE (0)
/* @brief Has channel mux */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_MUX (1)
/* @brief If dma channel IRQ support parameter */
#define FSL_FEATURE_EDMA_MODULE_CHANNEL_IRQ_ENTRY_SUPPORT_PARAMETER (0)
/* @brief Instance has channel mux */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_MUXn(x) (1)
/* @brief NBYTES must be multiple of 8 when using scatter gather. */
#define FSL_FEATURE_EDMA_HAS_ERRATA_51327 (0)
/* @brief Has register CH_SBR. */
#define FSL_FEATURE_EDMA_HAS_SBR (1)
/* @brief NBYTES must be multiple of 8 when using scatter gather. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_ERRATA_51327n(x) (0)
/* @brief Has no register bit fields CH_SBR[ATTR]. */
#define FSL_FEATURE_EDMA_HAS_NO_CH_SBR_ATTR (1)
/* @brief Has register bit fields MP_CSR[GMRC]. */
#define FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION (1)
/* @brief Has register bit field CH_CSR[SWAP]. */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_SWAP_SIZE (0)
/* @brief Instance has register bit field CH_CSR[SWAP]. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_SWAP_SIZEn(x) (0)
/* @brief Has register bit field CH_SBR[INSTR]. */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_ACCESS_TYPE (0)
/* @brief Instance has register bit field CH_SBR[INSTR]. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_ACCESS_TYPEn(x) (0)
/* @brief Has register bit fields CH_MATTR[WCACHE], CH_MATTR[RCACHE]. */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_MEMORY_ATTRIBUTE (0)
/* @brief Instance has register CH_MATTR. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_MEMORY_ATTRIBUTEn(x) (0)
/* @brief Has register bit field CH_CSR[SIGNEXT]. */
#define FSL_FEATURE_EDMA_HAS_CHANNEL_SIGN_EXTENSION (0)
/* @brief Instance Has register bit field CH_CSR[SIGNEXT]. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_CHANNEL_SIGN_EXTENSIONn(x) (0)
/* @brief Has register bit field TCD_CSR[BWC]. */
#define FSL_FEATURE_EDMA_HAS_BANDWIDTH (1)
/* @brief Instance has register bit field TCD_CSR[BWC]. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_BANDWIDTHn(x) (1)
/* @brief Has register bit fields TCD_CSR[TMC]. */
#define FSL_FEATURE_EDMA_HAS_TRANSFER_MODE (0)
/* @brief Instance has register bit fields TCD_CSR[TMC]. */
#define FSL_FEATURE_EDMA_INSTANCE_HAS_TRANSFER_MODEn(x) (0)
/* @brief Has no register bit fields CH_SBR[SEC]. */
#define FSL_FEATURE_EDMA_HAS_NO_CH_SBR_SEC (1)
/* FLEXIO module features */
/* @brief Has Shifter Status Register (FLEXIO_SHIFTSTAT) */
#define FSL_FEATURE_FLEXIO_HAS_SHIFTER_STATUS (1)
/* @brief Has Pin Data Input Register (FLEXIO_PIN) */
#define FSL_FEATURE_FLEXIO_HAS_PIN_STATUS (1)
/* @brief Has pin input output related registers */
#define FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER (1)
/* @brief Has Shifter Buffer N Nibble Byte Swapped Register (FLEXIO_SHIFTBUFNBSn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP (1)
/* @brief Has Shifter Buffer N Half Word Swapped Register (FLEXIO_SHIFTBUFHWSn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP (1)
/* @brief Has Shifter Buffer N Nibble Swapped Register (FLEXIO_SHIFTBUFNISn) */
#define FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP (1)
/* @brief Supports Shifter State Mode (FLEXIO_SHIFTCTLn[SMOD]) */
#define FSL_FEATURE_FLEXIO_HAS_STATE_MODE (1)
/* @brief Supports Shifter Logic Mode (FLEXIO_SHIFTCTLn[SMOD]) */
#define FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE (1)
/* @brief Supports paralle width (FLEXIO_SHIFTCFGn[PWIDTH]) */
#define FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH (1)
/* @brief Reset value of the FLEXIO_VERID register */
#define FSL_FEATURE_FLEXIO_VERID_RESET_VALUE (0x2010003)
/* @brief Reset value of the FLEXIO_PARAM register */
#define FSL_FEATURE_FLEXIO_PARAM_RESET_VALUE (0x4200404)
/* @brief Represent the bit width of the TIMDCE field (FLEXIO_TIMCFGLn[TIMDEC]) */
#define FSL_FEATURE_FLEXIO_TIMCFG_TIMDCE_FIELD_WIDTH (3)
/* PWM module features */
/* @brief If (e)FlexPWM has module A channels (outputs). */
#define FSL_FEATURE_PWM_HAS_CHANNELA (1)
/* @brief If (e)FlexPWM has module B channels (outputs). */
#define FSL_FEATURE_PWM_HAS_CHANNELB (1)
/* @brief If (e)FlexPWM has module X channels (outputs). */
#define FSL_FEATURE_PWM_HAS_CHANNELX (1)
/* @brief If (e)FlexPWM has fractional feature. */
#define FSL_FEATURE_PWM_HAS_FRACTIONAL (0)
/* @brief If (e)FlexPWM has mux trigger source select bit field. */
#define FSL_FEATURE_PWM_HAS_MUX_TRIGGER_SOURCE_SEL (1)
/* @brief Number of submodules in each (e)FlexPWM module. */
#define FSL_FEATURE_PWM_SUBMODULE_COUNT (3)
/* @brief Number of fault channel in each (e)FlexPWM module. */
#define FSL_FEATURE_PWM_FAULT_CH_COUNT (1)
/* @brief (e)FlexPWM has no WAITEN Bitfield In CTRL2 Register. */
#define FSL_FEATURE_PWM_HAS_NO_WAITEN (1)
/* @brief If (e)FlexPWM has phase delay feature. */
#define FSL_FEATURE_PWM_HAS_PHASE_DELAY (1)
/* @brief If (e)FlexPWM has input filter capture feature. */
#define FSL_FEATURE_PWM_HAS_INPUT_FILTER_CAPTURE (1)
/* @brief If (e)FlexPWM has module capture functionality on A channels (inputs). */
#define FSL_FEATURE_PWM_HAS_CAPTURE_ON_CHANNELA (0)
/* @brief If (e)FlexPWM has module capture functionality on B channels (inputs). */
#define FSL_FEATURE_PWM_HAS_CAPTURE_ON_CHANNELB (0)
/* @brief If (e)FlexPWM has module capture functionality on X channels (inputs). */
#define FSL_FEATURE_PWM_HAS_CAPTURE_ON_CHANNELX (1)
/* FMU module features */
/* @brief Is the flash module msf1? */
#define FSL_FEATURE_FSL_FEATURE_FLASH_IS_MSF1 (1)
/* @brief P-Flash block count. */
#define FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT (1)
/* @brief P-Flash block0 start address. */
#define FSL_FEATURE_FLASH_PFLASH_START_ADDRESS (0x00000000U)
/* @brief P-Flash block0 size. */
#define FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE (0x100000U)
/* @brief P-Flash sector size. */
#define FSL_FEATURE_FLASH_PFLASH_SECTOR_SIZE (0x2000U)
/* @brief P-Flash page size. */
#define FSL_FEATURE_FLASH_PFLASH_PAGE_SIZE (128)
/* @brief P-Flash phrase size. */
#define FSL_FEATURE_FLASH_PFLASH_PHRASE_SIZE (16)
/* @brief Has IFR memory. */
#define FSL_FEATURE_FLASH_HAS_IFR (1)
/* @brief flash BLOCK0 IFR0 start address. */
#define FSL_FEATURE_FLASH_IFR0_START_ADDRESS (0x01000000u)
/* @brief flash BLOCK0 IFR1 start address. */
#define FSL_FEATURE_FLASH_IFR1_START_ADDRESS (0x02100000U)
/* @brief flash block IFR0 size. */
#define FSL_FEATURE_FLASH_IFR0_SIZE (0x8000U)
/* @brief flash block IFR1 size. */
#define FSL_FEATURE_FLASH_IFR1_SIZE (0x2000U)
/* @brief IFR sector size. */
#define FSL_FEATURE_FLASH_IFR_SECTOR_SIZE (0x2000U)
/* @brief IFR page size. */
#define FSL_FEATURE_FLASH_IFR_PAGE_SIZE (128)
/* GLIKEY module features */
/* @brief GLIKEY has 8 step FSM configuration */
#define FSL_FEATURE_GLIKEY_HAS_EIGHT_STEPS (1)
/* GPIO module features */
/* @brief Has GPIO attribute checker register (GACR). */
#define FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER (0)
/* @brief Has GPIO version ID register (VERID). */
#define FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER (1)
/* @brief Has secure/non-secure access protection registers (LOCK, PCNS, PCNP, ICNS, ICNP). */
#define FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL (0)
/* @brief Has GPIO port input disable register (PIDR). */
#define FSL_FEATURE_GPIO_HAS_PORT_INPUT_CONTROL (1)
/* @brief Has GPIO interrupt/DMA request/trigger output selection. */
#define FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT (0)
/* I3C module features */
/* @brief Has TERM bitfile in MERRWARN register. */
#define FSL_FEATURE_I3C_HAS_NO_MERRWARN_TERM (0)
/* @brief SOC has no reset driver. */
#define FSL_FEATURE_I3C_HAS_NO_RESET (0)
/* @brief Use fixed BAMATCH count, do not provide editable BAMATCH. */
#define FSL_FEATURE_I3C_HAS_NO_SCONFIG_BAMATCH (0)
/* @brief Register SCONFIG do not have IDRAND bitfield. */
#define FSL_FEATURE_I3C_HAS_NO_SCONFIG_IDRAND (1)
/* @brief Register SCONFIG has HDROK bitfield. */
#define FSL_FEATURE_I3C_HAS_HDROK (1)
/* @brief SOC doesn't support slave IBI/MR/HJ. */
#define FSL_FEATURE_I3C_HAS_NO_SLAVE_IBI_MR_HJ (0)
/* @brief Has SCL delay after START. */
#define FSL_FEATURE_I3C_HAS_START_SCL_DELAY (1)
/* LPI2C module features */
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPI2C_FIFO_SIZEn(x) (4)
/* LPSPI module features */
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPSPI_FIFO_SIZEn(x) (4)
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPSPI_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1)
/* @brief Has CCR1 (related to existence of registers CCR1). */
#define FSL_FEATURE_LPSPI_HAS_CCR1 (1)
/* @brief Has no PCSCFG bit in CFGR1 register */
#define FSL_FEATURE_LPSPI_HAS_NO_PCSCFG (0)
/* @brief Has no WIDTH bits in TCR register */
#define FSL_FEATURE_LPSPI_HAS_NO_MULTI_WIDTH (0)
/* LPTMR module features */
/* @brief Has shared interrupt handler with another LPTMR module. */
#define FSL_FEATURE_LPTMR_HAS_SHARED_IRQ_HANDLER (0)
/* @brief Whether LPTMR counter is 32 bits width. */
#define FSL_FEATURE_LPTMR_CNR_WIDTH_IS_32B (1)
/* @brief Has timer DMA request enable (register bit CSR[TDRE]). */
#define FSL_FEATURE_LPTMR_HAS_CSR_TDRE (1)
/* @brief Do not has prescaler clock source 0. */
#define FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_0_SUPPORT (1)
/* @brief Do not has prescaler clock source 1. */
#define FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT (0)
/* @brief Do not has prescaler clock source 2. */
#define FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_2_SUPPORT (1)
/* @brief Do not has prescaler clock source 3. */
#define FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT (0)
/* LPUART module features */
/* @brief Has receive FIFO overflow detection (bit field CFIFO[RXOFE]). */
#define FSL_FEATURE_LPUART_HAS_IRQ_EXTENDED_FUNCTIONS (0)
/* @brief Has low power features (can be enabled in wait mode via register bit C1[DOZEEN] or CTRL[DOZEEN] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_LOW_POWER_UART_SUPPORT (1)
/* @brief Has extended data register ED (or extra flags in the DATA register if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_EXTENDED_DATA_REGISTER_FLAGS (1)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPUART_HAS_FIFO (1)
/* @brief Has 32-bit register MODIR */
#define FSL_FEATURE_LPUART_HAS_MODIR (1)
/* @brief Hardware flow control (RTS, CTS) is supported. */
#define FSL_FEATURE_LPUART_HAS_MODEM_SUPPORT (1)
/* @brief Infrared (modulation) is supported. */
#define FSL_FEATURE_LPUART_HAS_IR_SUPPORT (1)
/* @brief 2 bits long stop bit is available. */
#define FSL_FEATURE_LPUART_HAS_STOP_BIT_CONFIG_SUPPORT (1)
/* @brief If 10-bit mode is supported. */
#define FSL_FEATURE_LPUART_HAS_10BIT_DATA_SUPPORT (1)
/* @brief If 7-bit mode is supported. */
#define FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT (1)
/* @brief Baud rate fine adjustment is available. */
#define FSL_FEATURE_LPUART_HAS_BAUD_RATE_FINE_ADJUST_SUPPORT (0)
/* @brief Baud rate oversampling is available (has bit fields C4[OSR], C5[BOTHEDGE], C5[RESYNCDIS] or BAUD[OSR], BAUD[BOTHEDGE], BAUD[RESYNCDIS] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_BAUD_RATE_OVER_SAMPLING_SUPPORT (1)
/* @brief Baud rate oversampling is available. */
#define FSL_FEATURE_LPUART_HAS_RX_RESYNC_SUPPORT (1)
/* @brief Baud rate oversampling is available. */
#define FSL_FEATURE_LPUART_HAS_BOTH_EDGE_SAMPLING_SUPPORT (1)
/* @brief Peripheral type. */
#define FSL_FEATURE_LPUART_IS_SCI (1)
/* @brief Capacity (number of entries) of the transmit/receive FIFO (or zero if no FIFO is available). */
#define FSL_FEATURE_LPUART_FIFO_SIZEn(x) (4)
/* @brief Supports two match addresses to filter incoming frames. */
#define FSL_FEATURE_LPUART_HAS_ADDRESS_MATCHING (1)
/* @brief Has transmitter/receiver DMA enable bits C5[TDMAE]/C5[RDMAE] (or BAUD[TDMAE]/BAUD[RDMAE] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_DMA_ENABLE (1)
/* @brief Has transmitter/receiver DMA select bits C4[TDMAS]/C4[RDMAS], resp. C5[TDMAS]/C5[RDMAS] if IS_SCI = 0. */
#define FSL_FEATURE_LPUART_HAS_DMA_SELECT (0)
/* @brief Data character bit order selection is supported (bit field S2[MSBF] or STAT[MSBF] if the registers are 32-bit wide). */
#define FSL_FEATURE_LPUART_HAS_BIT_ORDER_SELECT (1)
/* @brief Has smart card (ISO7816 protocol) support and no improved smart card support. */
#define FSL_FEATURE_LPUART_HAS_SMART_CARD_SUPPORT (0)
/* @brief Has improved smart card (ISO7816 protocol) support. */
#define FSL_FEATURE_LPUART_HAS_IMPROVED_SMART_CARD_SUPPORT (0)
/* @brief Has local operation network (CEA709.1-B protocol) support. */
#define FSL_FEATURE_LPUART_HAS_LOCAL_OPERATION_NETWORK_SUPPORT (0)
/* @brief Has 32-bit registers (BAUD, STAT, CTRL, DATA, MATCH, MODIR) instead of 8-bit (BDH, BDL, C1, S1, D, etc.). */
#define FSL_FEATURE_LPUART_HAS_32BIT_REGISTERS (1)
/* @brief Lin break detect available (has bit BAUD[LBKDIE]). */
#define FSL_FEATURE_LPUART_HAS_LIN_BREAK_DETECT (1)
/* @brief UART stops in Wait mode available (has bit C1[UARTSWAI]). */
#define FSL_FEATURE_LPUART_HAS_WAIT_MODE_OPERATION (0)
/* @brief Has separate DMA RX and TX requests. */
#define FSL_FEATURE_LPUART_HAS_SEPARATE_DMA_RX_TX_REQn(x) (1)
/* @brief Has separate RX and TX interrupts. */
#define FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ (0)
/* @brief Has LPAURT_PARAM. */
#define FSL_FEATURE_LPUART_HAS_PARAM (1)
/* @brief Has LPUART_VERID. */
#define FSL_FEATURE_LPUART_HAS_VERID (1)
/* @brief Has LPUART_GLOBAL. */
#define FSL_FEATURE_LPUART_HAS_GLOBAL (1)
/* @brief Has LPUART_PINCFG. */
#define FSL_FEATURE_LPUART_HAS_PINCFG (1)
/* @brief Has register MODEM Control. */
#define FSL_FEATURE_LPUART_HAS_MCR (0)
/* @brief Has register Half Duplex Control. */
#define FSL_FEATURE_LPUART_HAS_HDCR (0)
/* @brief Has register Timeout. */
#define FSL_FEATURE_LPUART_HAS_TIMEOUT (0)
/* TRDC module features */
/* @brief Process master count. */
#define FSL_FEATURE_TRDC_PROCESSOR_MASTER_COUNT (2)
/* @brief TRDC instance has PID configuration or not. */
#define FSL_FEATURE_TRDC_INSTANCE_HAS_PID_CONFIGURATIONn(x) (0)
/* @brief TRDC instance has MBC. */
#define FSL_FEATURE_TRDC_HAS_MBC (1)
/* @brief TRDC instance has MRC. */
#define FSL_FEATURE_TRDC_HAS_MRC (0)
/* @brief TRDC instance has TRDC_CR. */
#define FSL_FEATURE_TRDC_HAS_GENERAL_CONFIG (0)
/* @brief TRDC instance has MDA_Wx_y_DFMT. */
#define FSL_FEATURE_TRDC_HAS_DOMAIN_ASSIGNMENT (0)
/* @brief TRDC instance has TRDC_FDID. */
#define FSL_FEATURE_TRDC_HAS_DOMAIN_ERROR (0)
/* @brief TRDC instance has TRDC_FLW_CTL. */
#define FSL_FEATURE_TRDC_HAS_FLW (0)
/* OPAMP module features */
/* @brief Opamp has OPAMP_CTR OUTSW bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW (1)
/* @brief Opamp has OPAMP_CTR ADCSW1 bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 (1)
/* @brief Opamp has OPAMP_CTR ADCSW2 bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 (1)
/* @brief Opamp has OPAMP_CTR BUFEN bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN (1)
/* @brief Opamp has OPAMP_CTR INPSEL bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL (1)
/* @brief Opamp has OPAMP_CTR TRIGMD bit */
#define FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD (1)
/* @brief OPAMP support reference buffer */
#define FSL_FEATURE_OPAMP_HAS_SUPPORT_REFERENCE_BUFFER (1U)
/* PORT module features */
/* @brief Has control lock (register bit PCR[LK]). */
#define FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK (1)
/* @brief Has open drain control (register bit PCR[ODE]). */
#define FSL_FEATURE_PORT_HAS_OPEN_DRAIN (1)
/* @brief Has digital filter (registers DFER, DFCR and DFWR). */
#define FSL_FEATURE_PORT_HAS_DIGITAL_FILTER (0)
/* @brief Has DMA request (register bit field PCR[IRQC] or ICR[IRQC] values). */
#define FSL_FEATURE_PORT_HAS_DMA_REQUEST (0)
/* @brief Has pull resistor selection available. */
#define FSL_FEATURE_PORT_HAS_PULL_SELECTION (1)
/* @brief Has pull resistor enable (register bit PCR[PE]). */
#define FSL_FEATURE_PORT_HAS_PULL_ENABLE (1)
/* @brief Has slew rate control (register bit PCR[SRE]). */
#define FSL_FEATURE_PORT_HAS_SLEW_RATE (1)
/* @brief Has passive filter (register bit field PCR[PFE]). */
#define FSL_FEATURE_PORT_HAS_PASSIVE_FILTER (1)
/* @brief Do not has interrupt control (register ISFR). */
#define FSL_FEATURE_PORT_HAS_NO_INTERRUPT (1)
/* @brief Has pull value (register bit field PCR[PV]). */
#define FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE (1)
/* @brief Has drive strength1 control (register bit PCR[DSE1]). */
#define FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 (1)
/* @brief Has version ID register (register VERID). */
#define FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER (1)
/* @brief Has voltage range control (register bit CONFIG[RANGE]). */
#define FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE (1)
/* @brief Has EFT detect (registers EDFR, EDIER and EDCR). */
#define FSL_FEATURE_PORT_SUPPORT_EFT (0)
/* @brief Function 0 is GPIO. */
#define FSL_FEATURE_PORT_PCR_MUX_GPIO (0)
/* @brief Has drive strength control (register bit PCR[DSE]). */
#define FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH (1)
/* @brief Defines width of PCR[MUX] field. */
#define FSL_FEATURE_PORT_PCR_MUX_WIDTH (4)
/* @brief Has dedicated interrupt vector. */
#define FSL_FEATURE_PORT_HAS_INTERRUPT_VECTOR (1)
/* @brief Has independent interrupt control(register ICR). */
#define FSL_FEATURE_PORT_HAS_INDEPENDENT_INTERRUPT_CONTROL (0)
/* @brief Has multiple pin IRQ configuration (register GICLR and GICHR). */
#define FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG (0)
/* @brief Has Input Buffer Enable (register bit field PCR[IBE]). */
#define FSL_FEATURE_PORT_HAS_INPUT_BUFFER (1)
/* @brief Has Invert Input (register bit field PCR[INV]). */
#define FSL_FEATURE_PORT_HAS_INVERT_INPUT (1)
/* @brief Defines whether PCR[IRQC] bit-field has flag states. */
#define FSL_FEATURE_PORT_HAS_IRQC_FLAG (0)
/* @brief Defines whether PCR[IRQC] bit-field has trigger states. */
#define FSL_FEATURE_PORT_HAS_IRQC_TRIGGER (0)
/* EQDC module features */
/* @brief If EQDC CTRL2 register has EMIP bit field. */
#define FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD (1)
/* SPC module features */
/* @brief Has DCDC */
#define FSL_FEATURE_MCX_SPC_HAS_DCDC (0)
/* @brief Has SYS LDO */
#define FSL_FEATURE_MCX_SPC_HAS_SYS_LDO (0)
/* @brief Has IOVDD_LVDF */
#define FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD (0)
/* @brief Has COREVDD_HVDF */
#define FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD (0)
/* @brief Has CORELDO_VDD_DS */
#define FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS (1)
/* @brief Has LPBUFF_EN */
#define FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT (0)
/* @brief Has COREVDD_IVS_EN */
#define FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT (0)
/* @brief Has SWITCH_STATE */
#define FSL_FEATURE_MCX_SPC_HAS_SWITCH_STATE_BIT (0)
/* @brief Has SRAMRETLDO */
#define FSL_FEATURE_MCX_SPC_HAS_SRAMRETLDO_REG (1)
/* @brief Has CFG register */
#define FSL_FEATURE_MCX_SPC_HAS_CFG_REG (0)
/* @brief Has SRAMLDO_DPD_ON */
#define FSL_FEATURE_MCX_SPC_HAS_SRAMLDO_DPD_ON_BIT (1)
/* @brief Has CNTRL register */
#define FSL_FEATURE_MCX_SPC_HAS_CNTRL_REG (0)
/* @brief Has DPDOWN_PULLDOWN_DISABLE */
#define FSL_FEATURE_MCX_SPC_HAS_DPDOWN_PULLDOWN_DISABLE_BIT (0)
/* @brief Not have glitch detect */
#define FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT (1)
/* @brief Has BLEED_EN */
#define FSL_FEATURE_MCX_SPC_HAS_DCDC_CFG_BLEED_EN (0)
/* SYSCON module features */
/* @brief Flash page size in bytes */
#define FSL_FEATURE_SYSCON_FLASH_PAGE_SIZE_BYTES (128)
/* @brief Flash sector size in bytes */
#define FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES (8192)
/* @brief Flash size in bytes */
#define FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES (1048576)
/* @brief Support ROMAPI */
#define FSL_FEATURE_SYSCON_ROMAPI (1)
/* @brief Powerlib API is different with other series devices */
#define FSL_FEATURE_POWERLIB_EXTEND (1)
/* @brief No OSTIMER register in PMC */
#define FSL_FEATURE_PMC_HAS_NO_OSTIMER_REG (1)
/* @brief Starter register discontinuous. */
#define FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS (1)
/* USB module features */
/* @brief KHCI module instance count */
#define FSL_FEATURE_USB_KHCI_COUNT (1)
/* @brief HOST mode enabled */
#define FSL_FEATURE_USB_KHCI_HOST_ENABLED (0)
/* @brief OTG mode enabled */
#define FSL_FEATURE_USB_KHCI_OTG_ENABLED (0)
/* @brief Size of the USB dedicated RAM */
#define FSL_FEATURE_USB_KHCI_USB_RAM (0)
/* @brief Has KEEP_ALIVE_CTRL register */
#define FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED (0)
/* @brief Has the Dynamic SOF threshold compare support */
#define FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED (0)
/* @brief Has the VBUS detect support */
#define FSL_FEATURE_USB_KHCI_VBUS_DETECT_ENABLED (1)
/* @brief Has the IRC48M module clock support */
#define FSL_FEATURE_USB_KHCI_IRC48M_MODULE_CLOCK_ENABLED (1)
/* @brief Number of endpoints supported */
#define FSL_FEATURE_USB_ENDPT_COUNT (16)
/* @brief Has STALL_IL/OL_DIS registers */
#define FSL_FEATURE_USB_KHCI_HAS_STALL_LOW (1)
/* @brief Has STALL_IH/OH_DIS registers */
#define FSL_FEATURE_USB_KHCI_HAS_STALL_HIGH (1)
/* UTICK module features */
/* @brief UTICK does not support PD configure. */
#define FSL_FEATURE_UTICK_HAS_NO_PDCFG (1)
/* VBAT module features */
/* @brief Has STATUS register */
#define FSL_FEATURE_MCX_VBAT_HAS_STATUS_REG (0)
/* @brief Has TAMPER register */
#define FSL_FEATURE_MCX_VBAT_HAS_TAMPER_REG (0)
/* @brief Has BANDGAP register */
#define FSL_FEATURE_MCX_VBAT_HAS_BANDGAP_TIMER (0)
/* @brief Has LDOCTL register */
#define FSL_FEATURE_MCX_VBAT_HAS_LDOCTL_REG (0)
/* @brief Has OSCCTL register */
#define FSL_FEATURE_MCX_VBAT_HAS_OSCCTL_REG (0)
/* @brief Has SWICTL register */
#define FSL_FEATURE_MCX_VBAT_HAS_SWICTL_REG (0)
/* @brief Has CLKMON register */
#define FSL_FEATURE_MCX_VBAT_HAS_CLKMON_REG (0)
/* WWDT module features */
/* @brief Has no RESET register. */
#define FSL_FEATURE_WWDT_HAS_NO_RESET (1)
#endif /* _MCXA156_FEATURES_H_ */

View File

@ -0,0 +1,71 @@
#!armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -x c
/*
** ###################################################################
** Processors: MCXA156VLL
** MCXA156VMP
** MCXA156VPJ
**
** Compiler: Keil ARM C/C++ Compiler
** Reference manual: MCXA18 User manual
** Version: rev. 1.0, 2022-03-29
** Build: b240104
**
** Abstract:
** Linker file for the Keil ARM C/C++ Compiler
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2024 NXP
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
/* Sizes */
#if (defined(__stack_size__))
#define Stack_Size __stack_size__
#else
#define Stack_Size 0x0400
#endif
#if (defined(__heap_size__))
#define Heap_Size __heap_size__
#else
#define Heap_Size 0x0400
#endif
#define m_interrupts_start 0x00000000
#define m_interrupts_size 0x00000200
#define m_text_start 0x00000200
#define m_text_size 0x000FFE00
#define m_data_start 0x20000000
#define m_data_size 0x0001E000
#define m_sramx0_start 0x04000000;
#define m_sramx0_size 0x00002000;
LR_m_text m_interrupts_start m_interrupts_size+m_text_size { ; load region size_region
VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address
* (.isr_vector,+FIRST)
}
ER_m_text m_text_start FIXED m_text_size { ; load address = execution address
* (InRoot$$Sections)
.ANY (+RO)
}
RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data
.ANY (+RW +ZI)
}
ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up
}
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
}
}

View File

@ -0,0 +1,68 @@
#!armclang --target=arm-arm-none-eabi -march=armv8-m.main -E -x c
/*
** ###################################################################
** Processors: MCXA156VLL
** MCXA156VMP
** MCXA156VPJ
**
** Compiler: Keil ARM C/C++ Compiler
** Reference manual: MCXA18 User manual
** Version: rev. 1.0, 2022-03-29
** Build: b240104
**
** Abstract:
** Linker file for the Keil ARM C/C++ Compiler
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2024 NXP
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** ###################################################################
*/
/* Sizes */
#if (defined(__stack_size__))
#define Stack_Size __stack_size__
#else
#define Stack_Size 0x0400
#endif
#if (defined(__heap_size__))
#define Heap_Size __heap_size__
#else
#define Heap_Size 0x0400
#endif
#define m_interrupts_start 0x20000000
#define m_interrupts_size 0x00000200
#define m_text_start 0x20000200
#define m_text_size 0x00005E00
#define m_data_start 0x20006000
#define m_data_size 0x00018000
LR_m_text m_interrupts_start m_interrupts_size+m_text_size { ; load region size_region
VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address
* (.isr_vector,+FIRST)
}
ER_m_text m_text_start FIXED m_text_size { ; load address = execution address
* (InRoot$$Sections)
.ANY (+RO)
}
RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data
.ANY (+RW +ZI)
}
ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up
}
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
}
}

View File

@ -0,0 +1,18 @@
// <<< Use Configuration Wizard in Context Menu >>>
// <o0> SWO pin
// <i> The SWO (Serial Wire Output) pin optionally provides data from the ITM
// <i> for an external debug tool to evaluate.
// <0=> PIO0_10
// <1=> PIO0_8
SWO_Pin = 0;
//
// <h>Debug Configuration
// <o.0> StopAfterBootloader <i> Stop after Bootloader
// </h>
Dbg_CR = 0x00000001;
//
// <<< end of configuration section >>>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_aoi.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.aoi"
#endif
#if defined(AOI_RSTS)
#define AOI_RESETS_ARRAY AOI_RSTS
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to aoi bases for each instance. */
static AOI_Type *const s_aoiBases[] = AOI_BASE_PTRS;
#if defined(AOI_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_aoiResets[] = AOI_RESETS_ARRAY;
#endif
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to aoi clocks for each instance. */
static const clock_ip_name_t s_aoiClocks[] = AOI_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for AOI module.
*
* @param base AOI peripheral base address
*
* @return The AOI instance
*/
static uint32_t AOI_GetInstance(AOI_Type *base);
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t AOI_GetInstance(AOI_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_aoiBases); instance++)
{
if (s_aoiBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_aoiBases));
return instance;
}
/*!
* brief Initializes an AOI instance for operation.
*
* This function un-gates the AOI clock.
*
* param base AOI peripheral address.
*/
void AOI_Init(AOI_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock gate from clock manager. */
CLOCK_EnableClock(s_aoiClocks[AOI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(AOI_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_aoiResets[AOI_GetInstance(base)]);
#endif
}
/*!
* brief Deinitializes an AOI instance for operation.
*
* This function shutdowns AOI module.
*
* param base AOI peripheral address.
*/
void AOI_Deinit(AOI_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock gate from clock manager */
CLOCK_DisableClock(s_aoiClocks[AOI_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* brief Gets the Boolean evaluation associated.
*
* This function returns the Boolean evaluation associated.
*
* Example:
code
aoi_event_config_t demoEventLogicStruct;
AOI_GetEventLogicConfig(AOI, kAOI_Event0, &demoEventLogicStruct);
endcode
*
* param base AOI peripheral address.
* param event Index of the event which will be set of type aoi_event_t.
* param config Selected input configuration .
*/
void AOI_GetEventLogicConfig(AOI_Type *base, aoi_event_t event, aoi_event_config_t *config)
{
assert((uint32_t)event < (uint32_t)FSL_FEATURE_AOI_EVENT_COUNT);
assert(config != NULL);
uint16_t value;
uint16_t temp;
/* Read BFCRT01 register at event index. */
value = base->BFCRT[event].BFCRT01;
temp = (value & AOI_BFCRT01_PT0_AC_MASK) >> AOI_BFCRT01_PT0_AC_SHIFT;
config->PT0AC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT0_BC_MASK) >> AOI_BFCRT01_PT0_BC_SHIFT;
config->PT0BC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT0_CC_MASK) >> AOI_BFCRT01_PT0_CC_SHIFT;
config->PT0CC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT0_DC_MASK) >> AOI_BFCRT01_PT0_DC_SHIFT;
config->PT0DC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT1_AC_MASK) >> AOI_BFCRT01_PT1_AC_SHIFT;
config->PT1AC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT1_BC_MASK) >> AOI_BFCRT01_PT1_BC_SHIFT;
config->PT1BC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT1_CC_MASK) >> AOI_BFCRT01_PT1_CC_SHIFT;
config->PT1CC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT01_PT1_DC_MASK) >> AOI_BFCRT01_PT1_DC_SHIFT;
config->PT1DC = (aoi_input_config_t)temp;
/* Read BFCRT23 register at event index. */
value = base->BFCRT[event].BFCRT23;
temp = (value & AOI_BFCRT23_PT2_AC_MASK) >> AOI_BFCRT23_PT2_AC_SHIFT;
config->PT2AC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT2_BC_MASK) >> AOI_BFCRT23_PT2_BC_SHIFT;
config->PT2BC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT2_CC_MASK) >> AOI_BFCRT23_PT2_CC_SHIFT;
config->PT2CC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT2_DC_MASK) >> AOI_BFCRT23_PT2_DC_SHIFT;
config->PT2DC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT3_AC_MASK) >> AOI_BFCRT23_PT3_AC_SHIFT;
config->PT3AC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT3_BC_MASK) >> AOI_BFCRT23_PT3_BC_SHIFT;
config->PT3BC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT3_CC_MASK) >> AOI_BFCRT23_PT3_CC_SHIFT;
config->PT3CC = (aoi_input_config_t)temp;
temp = (value & AOI_BFCRT23_PT3_DC_MASK) >> AOI_BFCRT23_PT3_DC_SHIFT;
config->PT3DC = (aoi_input_config_t)temp;
}
/*!
* brief Configures an AOI event.
*
* This function configures an AOI event according
* to the aoiEventConfig structure. This function configures all inputs (A, B, C, and D)
* of all product terms (0, 1, 2, and 3) of a desired event.
*
* Example:
code
aoi_event_config_t demoEventLogicStruct;
demoEventLogicStruct.PT0AC = kAOI_InvInputSignal;
demoEventLogicStruct.PT0BC = kAOI_InputSignal;
demoEventLogicStruct.PT0CC = kAOI_LogicOne;
demoEventLogicStruct.PT0DC = kAOI_LogicOne;
demoEventLogicStruct.PT1AC = kAOI_LogicZero;
demoEventLogicStruct.PT1BC = kAOI_LogicOne;
demoEventLogicStruct.PT1CC = kAOI_LogicOne;
demoEventLogicStruct.PT1DC = kAOI_LogicOne;
demoEventLogicStruct.PT2AC = kAOI_LogicZero;
demoEventLogicStruct.PT2BC = kAOI_LogicOne;
demoEventLogicStruct.PT2CC = kAOI_LogicOne;
demoEventLogicStruct.PT2DC = kAOI_LogicOne;
demoEventLogicStruct.PT3AC = kAOI_LogicZero;
demoEventLogicStruct.PT3BC = kAOI_LogicOne;
demoEventLogicStruct.PT3CC = kAOI_LogicOne;
demoEventLogicStruct.PT3DC = kAOI_LogicOne;
AOI_SetEventLogicConfig(AOI, kAOI_Event0, demoEventLogicStruct);
endcode
*
* param base AOI peripheral address.
* param event Event which will be configured of type aoi_event_t.
* param eventConfig Pointer to type aoi_event_config_t structure. The user is responsible for
* filling out the members of this structure and passing the pointer to this function.
*/
void AOI_SetEventLogicConfig(AOI_Type *base, aoi_event_t event, const aoi_event_config_t *eventConfig)
{
assert(eventConfig != NULL);
assert((uint32_t)event < (uint32_t)FSL_FEATURE_AOI_EVENT_COUNT);
uint16_t value;
/* Calculate value to configure product term 0, 1 */
value = AOI_BFCRT01_PT0_AC(eventConfig->PT0AC) | AOI_BFCRT01_PT0_BC(eventConfig->PT0BC) |
AOI_BFCRT01_PT0_CC(eventConfig->PT0CC) | AOI_BFCRT01_PT0_DC(eventConfig->PT0DC) |
AOI_BFCRT01_PT1_AC(eventConfig->PT1AC) | AOI_BFCRT01_PT1_BC(eventConfig->PT1BC) |
AOI_BFCRT01_PT1_CC(eventConfig->PT1CC) | AOI_BFCRT01_PT1_DC(eventConfig->PT1DC);
/* Write value to register */
base->BFCRT[event].BFCRT01 = value;
/* Reset and calculate value to configure product term 2, 3 */
value = AOI_BFCRT23_PT2_AC(eventConfig->PT2AC) | AOI_BFCRT23_PT2_BC(eventConfig->PT2BC) |
AOI_BFCRT23_PT2_CC(eventConfig->PT2CC) | AOI_BFCRT23_PT2_DC(eventConfig->PT2DC) |
AOI_BFCRT23_PT3_AC(eventConfig->PT3AC) | AOI_BFCRT23_PT3_BC(eventConfig->PT3BC) |
AOI_BFCRT23_PT3_CC(eventConfig->PT3CC) | AOI_BFCRT23_PT3_DC(eventConfig->PT3DC);
/* Write value to register */
base->BFCRT[event].BFCRT23 = value;
}

View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_AOI_H_
#define FSL_AOI_H_
#include "fsl_common.h"
/*!
* @addtogroup aoi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#ifndef AOI
#define AOI AOI0 /*!< AOI peripheral address */
#endif
/*! @name Driver version */
/*! @{ */
#define FSL_AOI_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) /*!< Version 2.0.2. */
/*! @} */
/*!
* @brief AOI input configurations.
*
* The selection item represents the Boolean evaluations.
*/
typedef enum _aoi_input_config
{
kAOI_LogicZero = 0x0U, /*!< Forces the input to logical zero. */
kAOI_InputSignal = 0x1U, /*!< Passes the input signal. */
kAOI_InvInputSignal = 0x2U, /*!< Inverts the input signal. */
kAOI_LogicOne = 0x3U /*!< Forces the input to logical one. */
} aoi_input_config_t;
/*!
* @brief AOI event indexes, where an event is the collection of the four product
* terms (0, 1, 2, and 3) and the four signal inputs (A, B, C, and D).
*/
typedef enum _aoi_event
{
kAOI_Event0 = 0x0U, /*!< Event 0 index */
kAOI_Event1 = 0x1U, /*!< Event 1 index */
kAOI_Event2 = 0x2U, /*!< Event 2 index */
kAOI_Event3 = 0x3U /*!< Event 3 index */
} aoi_event_t;
/*!
* @brief AOI event configuration structure
*
* Defines structure _aoi_event_config and use the AOI_SetEventLogicConfig() function to make
* whole event configuration.
*/
typedef struct _aoi_event_config
{
aoi_input_config_t PT0AC; /*!< Product term 0 input A */
aoi_input_config_t PT0BC; /*!< Product term 0 input B */
aoi_input_config_t PT0CC; /*!< Product term 0 input C */
aoi_input_config_t PT0DC; /*!< Product term 0 input D */
aoi_input_config_t PT1AC; /*!< Product term 1 input A */
aoi_input_config_t PT1BC; /*!< Product term 1 input B */
aoi_input_config_t PT1CC; /*!< Product term 1 input C */
aoi_input_config_t PT1DC; /*!< Product term 1 input D */
aoi_input_config_t PT2AC; /*!< Product term 2 input A */
aoi_input_config_t PT2BC; /*!< Product term 2 input B */
aoi_input_config_t PT2CC; /*!< Product term 2 input C */
aoi_input_config_t PT2DC; /*!< Product term 2 input D */
aoi_input_config_t PT3AC; /*!< Product term 3 input A */
aoi_input_config_t PT3BC; /*!< Product term 3 input B */
aoi_input_config_t PT3CC; /*!< Product term 3 input C */
aoi_input_config_t PT3DC; /*!< Product term 3 input D */
} aoi_event_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @name AOI Initialization
* @{
*/
/*!
* @brief Initializes an AOI instance for operation.
*
* This function un-gates the AOI clock.
*
* @param base AOI peripheral address.
*/
void AOI_Init(AOI_Type *base);
/*!
* @brief Deinitializes an AOI instance for operation.
*
* This function shutdowns AOI module.
*
* @param base AOI peripheral address.
*/
void AOI_Deinit(AOI_Type *base);
/*! @} */
/*!
* @name AOI Get Set Operation
* @{
*/
/*!
* @brief Gets the Boolean evaluation associated.
*
* This function returns the Boolean evaluation associated.
*
* Example:
@code
aoi_event_config_t demoEventLogicStruct;
AOI_GetEventLogicConfig(AOI, kAOI_Event0, &demoEventLogicStruct);
@endcode
*
* @param base AOI peripheral address.
* @param event Index of the event which will be set of type aoi_event_t.
* @param config Selected input configuration .
*/
void AOI_GetEventLogicConfig(AOI_Type *base, aoi_event_t event, aoi_event_config_t *config);
/*!
* @brief Configures an AOI event.
*
* This function configures an AOI event according
* to the aoiEventConfig structure. This function configures all inputs (A, B, C, and D)
* of all product terms (0, 1, 2, and 3) of a desired event.
*
* Example:
@code
aoi_event_config_t demoEventLogicStruct;
demoEventLogicStruct.PT0AC = kAOI_InvInputSignal;
demoEventLogicStruct.PT0BC = kAOI_InputSignal;
demoEventLogicStruct.PT0CC = kAOI_LogicOne;
demoEventLogicStruct.PT0DC = kAOI_LogicOne;
demoEventLogicStruct.PT1AC = kAOI_LogicZero;
demoEventLogicStruct.PT1BC = kAOI_LogicOne;
demoEventLogicStruct.PT1CC = kAOI_LogicOne;
demoEventLogicStruct.PT1DC = kAOI_LogicOne;
demoEventLogicStruct.PT2AC = kAOI_LogicZero;
demoEventLogicStruct.PT2BC = kAOI_LogicOne;
demoEventLogicStruct.PT2CC = kAOI_LogicOne;
demoEventLogicStruct.PT2DC = kAOI_LogicOne;
demoEventLogicStruct.PT3AC = kAOI_LogicZero;
demoEventLogicStruct.PT3BC = kAOI_LogicOne;
demoEventLogicStruct.PT3CC = kAOI_LogicOne;
demoEventLogicStruct.PT3DC = kAOI_LogicOne;
AOI_SetEventLogicConfig(AOI, kAOI_Event0, demoEventLogicStruct);
@endcode
*
* @param base AOI peripheral address.
* @param event Event which will be configured of type aoi_event_t.
* @param eventConfig Pointer to type aoi_event_config_t structure. The user is responsible for
* filling out the members of this structure and passing the pointer to this function.
*/
void AOI_SetEventLogicConfig(AOI_Type *base, aoi_event_t event, const aoi_event_config_t *eventConfig);
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @} */
/*!* @} */
#endif /* FSL_AOI_H_*/

View File

@ -0,0 +1,378 @@
/*
* Copyright 2020-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_cdog.h"
/*******************************************************************************
* Definitions
*******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.cdog"
#endif
/* Reset CONTROL mask */
#define RESERVED_CTRL_MASK 0x800u
#if defined(CDOG_IRQS)
/* Array of IRQs */
static const IRQn_Type s_CdogIrqs[] = CDOG_IRQS;
#endif /* CDOG_IRQS */
#ifdef CDOG_CLOCKS
static const clock_ip_name_t s_CdogClocks[] = CDOG_CLOCKS;
#endif /* CDOG_CLOCKS */
#ifdef CDOG_BASE_PTRS
static const CDOG_Type* s_cdogBases[] = CDOG_BASE_PTRS;
#endif /* CDOG_BASE_PTRS */
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t CDOG_GetInstance(CDOG_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_cdogBases); instance++)
{
if (s_cdogBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_cdogBases));
return instance;
}
/*!
* brief Sets the default configuration of CDOG
*
* This function initialize CDOG config structure to default values.
*
* param conf CDOG configuration structure
*/
void CDOG_GetDefaultConfig(cdog_config_t *conf)
{
/* Default configuration after reset */
conf->lock = (uint8_t)kCDOG_LockCtrl_Unlock; /* Lock control */
conf->timeout = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Timeout control */
conf->miscompare = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Miscompare control */
conf->sequence = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Sequence control */
conf->state = (uint8_t)kCDOG_FaultCtrl_NoAction; /* State control */
conf->address = (uint8_t)kCDOG_FaultCtrl_NoAction; /* Address control */
conf->irq_pause = (uint8_t)kCDOG_IrqPauseCtrl_Run; /* IRQ pause control */
conf->debug_halt = (uint8_t)kCDOG_DebugHaltCtrl_Run; /* Debug halt control */
return;
}
/*!
* brief Sets secure counter and instruction timer values
*
* This function sets value in RELOAD and START registers for instruction timer.
*
* param base CDOG peripheral base address
* param reload reload value
* param start start value
*/
void CDOG_Start(CDOG_Type *base, uint32_t reload, uint32_t start)
{
base->RELOAD = reload;
base->START = start;
}
/*!
* brief Stops secure counter and instruction timer
*
* This function stops instruction timer and secure counter.
* This also change state of CDOG to IDLE.
*
* param base CDOG peripheral base address
* param stop expected value which will be compared with value of secure counter
*/
void CDOG_Stop(CDOG_Type *base, uint32_t stop)
{
base->STOP = stop;
}
/*!
* brief Sets secure counter and instruction timer values
*
* This function sets value in STOP, RELOAD and START registers
* for instruction timer and secure counter.
*
* param base CDOG peripheral base address
* param stop expected value which will be compared with value of secure counter
* param reload reload value for instruction timer
* param start start value for secure timer
*/
void CDOG_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start)
{
base->STOP = stop;
base->RELOAD = reload;
base->START = start;
}
/*!
* brief Add value to secure counter
*
* This function add specified value to secure counter.
*
* param base CDOG peripheral base address.
* param add Value to be added.
*/
void CDOG_Add(CDOG_Type *base, uint32_t add)
{
base->ADD = (secure_counter_t)add;
}
/*!
* brief Add 1 to secure counter
*
* This function add 1 to secure counter.
*
* param base CDOG peripheral base address.
* param add Value to be added.
*/
void CDOG_Add1(CDOG_Type *base)
{
base->ADD1 = (secure_counter_t)0x1U;
}
/*!
* brief Add 16 to secure counter
*
* This function add 16 to secure counter.
*
* param base CDOG peripheral base address.
* param add Value to be added.
*/
void CDOG_Add16(CDOG_Type *base)
{
base->ADD16 = (secure_counter_t)0x1U;
}
/*!
* brief Add 256 to secure counter
*
* This function add 256 to secure counter.
*
* param base CDOG peripheral base address.
* param add Value to be added.
*/
void CDOG_Add256(CDOG_Type *base)
{
base->ADD256 = (secure_counter_t)0x1U;
}
/*!
* brief Substract value to secure counter
*
* This function substract specified value to secure counter.
*
* param base CDOG peripheral base address.
* param sub Value to be substracted.
*/
void CDOG_Sub(CDOG_Type *base, uint32_t sub)
{
base->SUB = (secure_counter_t)sub;
}
/*!
* brief Substract 1 from secure counter
*
* This function substract specified 1 from secure counter.
*
* param base CDOG peripheral base address.
*/
void CDOG_Sub1(CDOG_Type *base)
{
base->SUB1 = (secure_counter_t)0x1U;
}
/*!
* brief Substract 16 from secure counter
*
* This function substract specified 16 from secure counter.
*
* param base CDOG peripheral base address.
*/
void CDOG_Sub16(CDOG_Type *base)
{
base->SUB16 = (secure_counter_t)0x1U;
}
/*!
* brief Substract 256 from secure counter
*
* This function substract specified 256 from secure counter.
*
* param base CDOG peripheral base address.
*/
void CDOG_Sub256(CDOG_Type *base)
{
base->SUB256 = (secure_counter_t)0x1U;
}
/*!
* brief Checks secure counter.
*
* This function compares stop value with secure counter value
* by writting to RELOAD refister.
*
* param base CDOG peripheral base address
* param check expected (stop) value.
*/
void CDOG_Check(CDOG_Type *base, uint32_t check)
{
#if defined(FLS_FEATURE_CDOG_USE_RESTART)
base->RESTART = check;
#else
base->STOP = check;
base->RELOAD = base->RELOAD;
base->START= check;
#endif
}
/*!
* brief Set the CDOG persistent word.
*
* param base CDOG peripheral base address.
* param value The value to be written.
*/
void CDOG_WritePersistent(CDOG_Type *base, uint32_t value)
{
base->PERSISTENT = value;
}
/*!
* brief Get the CDOG persistent word.
*
* param base CDOG peripheral base address.
* return The persistent word.
*/
uint32_t CDOG_ReadPersistent(CDOG_Type *base)
{
return base->PERSISTENT;
}
/*!
* brief Initialize CDOG
*
* This function initializes CDOG setting and enable all interrupts.
*
* param base CDOG peripheral base address
* param conf CDOG configuration structure
* return Status of the init operation
*/
status_t CDOG_Init(CDOG_Type *base, cdog_config_t *conf)
{
/* Ungate clock to CDOG engine and reset it */
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#ifdef CDOG_CLOCKS
CLOCK_EnableClock(s_CdogClocks[CDOG_GetInstance(base)]);
#endif /* CDOG_CLOCKS */
#endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
RESET_PeripheralReset(kCDOG_RST_SHIFT_RSTn);
#endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
if (base->CONTROL == 0x0U)
{
/* CDOG is not in IDLE mode, which may be cause after SW reset. */
/* Writing to CONTROL register will trigger fault. */
return kStatus_Fail;
}
/* Clear pending errors, otherwise the device will reset */
/* itself immediately after enable Code Watchdog */
if ((uint32_t)kCDOG_LockCtrl_Lock ==
((base->CONTROL & CDOG_CONTROL_LOCK_CTRL_MASK) >> CDOG_CONTROL_LOCK_CTRL_SHIFT))
{
base->FLAGS = CDOG_FLAGS_TO_FLAG(1U) | CDOG_FLAGS_MISCOM_FLAG(1U) | CDOG_FLAGS_SEQ_FLAG(1U) |
CDOG_FLAGS_CNT_FLAG(1U) | CDOG_FLAGS_STATE_FLAG(1U) | CDOG_FLAGS_ADDR_FLAG(1U) |
CDOG_FLAGS_POR_FLAG(1U);
}
else
{
/* load default values for CDOG->CONTROL before flags clear */
#if defined(FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF) && (FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF > 0)
cdog_config_t default_conf;
/* Initialize CDOG */
CDOG_GetDefaultConfig(&default_conf);
/* Write default value to CDOG->CONTROL*/
base->CONTROL =
CDOG_CONTROL_TIMEOUT_CTRL(default_conf.timeout) | /* Action if the timeout event is triggered */
CDOG_CONTROL_MISCOMPARE_CTRL(default_conf.miscompare) | /* Action if the miscompare error event is triggered */
CDOG_CONTROL_SEQUENCE_CTRL(default_conf.sequence) | /* Action if the sequence error event is triggered */
CDOG_CONTROL_STATE_CTRL(default_conf.state) | /* Action if the state error event is triggered */
CDOG_CONTROL_ADDRESS_CTRL(default_conf.address) | /* Action if the address error event is triggered */
CDOG_CONTROL_IRQ_PAUSE(default_conf.irq_pause) | /* Pause running during interrupts setup */
CDOG_CONTROL_DEBUG_HALT_CTRL(default_conf.debug_halt) | /* Halt CDOG timer during debug */
CDOG_CONTROL_LOCK_CTRL(default_conf.lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
#endif /* FSL_FEATURE_CDOG_NEED_LOAD_DEFAULT_CONF */
base->FLAGS = CDOG_FLAGS_TO_FLAG(0U) | CDOG_FLAGS_MISCOM_FLAG(0U) | CDOG_FLAGS_SEQ_FLAG(0U) |
CDOG_FLAGS_CNT_FLAG(0U) | CDOG_FLAGS_STATE_FLAG(0U) | CDOG_FLAGS_ADDR_FLAG(0U) |
CDOG_FLAGS_POR_FLAG(0U);
}
base->CONTROL =
CDOG_CONTROL_TIMEOUT_CTRL(conf->timeout) | /* Action if the timeout event is triggered */
CDOG_CONTROL_MISCOMPARE_CTRL(conf->miscompare) | /* Action if the miscompare error event is triggered */
CDOG_CONTROL_SEQUENCE_CTRL(conf->sequence) | /* Action if the sequence error event is triggered */
CDOG_CONTROL_STATE_CTRL(conf->state) | /* Action if the state error event is triggered */
CDOG_CONTROL_ADDRESS_CTRL(conf->address) | /* Action if the address error event is triggered */
CDOG_CONTROL_IRQ_PAUSE(conf->irq_pause) | /* Pause running during interrupts setup */
CDOG_CONTROL_DEBUG_HALT_CTRL(conf->debug_halt) | /* Halt CDOG timer during debug */
CDOG_CONTROL_LOCK_CTRL(conf->lock) | RESERVED_CTRL_MASK; /* Lock control register, RESERVED */
#if defined(CDOG_IRQS)
/* Enable peripheral IRQ */
NVIC_EnableIRQ(s_CdogIrqs[CDOG_GetInstance(base)]);
#endif /* CDOG_IRQS */
return kStatus_Success;
}
/*!
* brief Deinitialize CDOG
*
* This function stops CDOG secure counter.
*
* param base CDOG peripheral base address
*/
void CDOG_Deinit(CDOG_Type *base)
{
#if defined(CDOG_IRQS)
/* Disable peripheral IRQ */
NVIC_DisableIRQ(s_CdogIrqs[CDOG_GetInstance(base)]);
#endif /* CDOG_IRQS */
#if !(defined(FSL_FEATURE_CDOG_HAS_NO_RESET) && FSL_FEATURE_CDOG_HAS_NO_RESET)
RESET_SetPeripheralReset(kCDOG_RST_SHIFT_RSTn);
#endif /* !FSL_FEATURE_CDOG_HAS_NO_RESET */
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#ifdef CDOG_CLOCKS
CLOCK_DisableClock(s_CdogClocks[CDOG_GetInstance(base)]);
#endif /* CDOG_CLOCKS */
#endif /* !FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

View File

@ -0,0 +1,329 @@
/*
* Copyright 2020-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_CDOG_H_
#define FSL_CDOG_H_
#include "fsl_common.h"
/*!
* @addtogroup CDOG
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief Defines CDOG driver version 2.1.3.
*
* Change log:
* - Version 2.1.3
* - Re-design multiple instance IRQs and Clocks
* - Add fix for RESTART command errata
* - Version 2.1.2
* - Support multiple IRQs
* - Fix default CONTROL values
* - Version 2.1.1
* - Remove bit CONTROL[CONTROL_CTRL]
* - Version 2.1.0
* - Rename CWT to CDOG
* - Version 2.0.2
* - Fix MISRA-2012 issues
* - Version 2.0.1
* - Fix doxygen issues
* - Version 2.0.0
* - initial version
*/
#define FSL_CDOG_DRIVER_VERSION (MAKE_VERSION(2, 1, 3))
/*! @} */
typedef struct
{
uint8_t lock : 2;
uint8_t timeout : 3;
uint8_t miscompare : 3;
uint8_t sequence : 3;
uint8_t state : 3;
uint8_t address : 3;
uint8_t reserved : 8;
uint8_t irq_pause : 2;
uint8_t debug_halt : 2;
} cdog_config_t;
enum __cdog_debug_Action_ctrl_enum
{
kCDOG_DebugHaltCtrl_Run = 0x1,
kCDOG_DebugHaltCtrl_Pause = 0x2,
};
enum __cdog_irq_pause_ctrl_enum
{
kCDOG_IrqPauseCtrl_Run = 0x1,
kCDOG_IrqPauseCtrl_Pause = 0x2,
};
enum __cdog_fault_ctrl_enum
{
kCDOG_FaultCtrl_EnableReset = 0x1U,
kCDOG_FaultCtrl_EnableInterrupt = 0x2U,
kCDOG_FaultCtrl_NoAction = 0x4U,
};
enum __code_lock_ctrl_enum
{
kCDOG_LockCtrl_Lock = 0x1,
kCDOG_LockCtrl_Unlock = 0x2,
};
typedef uint32_t secure_counter_t;
#define SC_ADD(add) \
do \
{ \
CDOG->ADD = (secure_counter_t)(add); \
} while (0)
#define SC_ADD1 \
do \
{ \
CDOG->ADD1 = (secure_counter_t)0x1U; \
} while (0)
#define SC_ADD16 \
do \
{ \
CDOG->ADD16 = (secure_counter_t)0x1U; \
} while (0)
#define SC_ADD256 \
do \
{ \
CDOG->ADD256 = (secure_counter_t)0x1U; \
} while (0)
#define SC_SUB(sub) \
do \
{ \
CDOG->SUB = (secure_counter_t)(sub); \
} while (0)
#define SC_SUB1 \
do \
{ \
CDOG->SUB1 = (secure_counter_t)0x1U; \
} while (0)
#define SC_SUB16 \
do \
{ \
CDOG->SUB16 = (secure_counter_t)0x1U; \
} while (0)
#define SC_SUB256 \
do \
{ \
CDOG->SUB256 = (secure_counter_t)0x1U; \
} while (0)
#define SC_CHECK(val) \
do \
{ \
CDOG->RESTART = (secure_counter_t)val; \
} while (0)
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name CDOG Functional Operation
* @{
*/
/*!
* @brief Initialize CDOG
*
* This function initializes CDOG block and setting.
*
* @param base CDOG peripheral base address
* @param conf CDOG configuration structure
* @return Status of the init operation
*/
status_t CDOG_Init(CDOG_Type *base, cdog_config_t *conf);
/*!
* @brief Deinitialize CDOG
*
* This function deinitializes CDOG secure counter.
*
* @param base CDOG peripheral base address
*/
void CDOG_Deinit(CDOG_Type *base);
/*!
* @brief Sets the default configuration of CDOG
*
* This function initialize CDOG config structure to default values.
*
* @param conf CDOG configuration structure
*/
void CDOG_GetDefaultConfig(cdog_config_t *conf);
/*!
* @brief Stops secure counter and instruction timer
*
* This function stops instruction timer and secure counter.
* This also change state od CDOG to IDLE.
*
* @param base CDOG peripheral base address
* @param stop expected value which will be compared with value of secure counter
*/
void CDOG_Stop(CDOG_Type *base, uint32_t stop);
/*!
* @brief Sets secure counter and instruction timer values
*
* This function sets value in RELOAD and START registers
* for instruction timer and secure counter
*
* @param base CDOG peripheral base address
* @param reload reload value
* @param start start value
*/
void CDOG_Start(CDOG_Type *base, uint32_t reload, uint32_t start);
/*!
* @brief Checks secure counter.
*
* This function compares stop value in handler with secure counter value
* by writting to RELOAD refister.
*
* @param base CDOG peripheral base address
* @param check expected (stop) value
*/
void CDOG_Check(CDOG_Type *base, uint32_t check);
/*!
* @brief Sets secure counter and instruction timer values
*
* This function sets value in STOP, RELOAD and START registers
* for instruction timer and secure counter.
*
* @param base CDOG peripheral base address
* @param stop expected value which will be compared with value of secure counter
* @param reload reload value for instruction timer
* @param start start value for secure timer
*/
void CDOG_Set(CDOG_Type *base, uint32_t stop, uint32_t reload, uint32_t start);
/*!
* @brief Add value to secure counter
*
* This function add specified value to secure counter.
*
* @param base CDOG peripheral base address.
* @param add Value to be added.
*/
void CDOG_Add(CDOG_Type *base, uint32_t add);
/*!
* @brief Add 1 to secure counter
*
* This function add 1 to secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Add1(CDOG_Type *base);
/*!
* @brief Add 16 to secure counter
*
* This function add 16 to secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Add16(CDOG_Type *base);
/*!
* @brief Add 256 to secure counter
*
* This function add 256 to secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Add256(CDOG_Type *base);
/*!
* brief Substract value to secure counter
*
* This function substract specified value to secure counter.
*
* param base CDOG peripheral base address.
* param sub Value to be substracted.
*/
void CDOG_Sub(CDOG_Type *base, uint32_t sub);
/*!
* @brief Substract 1 from secure counter
*
* This function substract specified 1 from secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Sub1(CDOG_Type *base);
/*!
* @brief Substract 16 from secure counter
*
* This function substract specified 16 from secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Sub16(CDOG_Type *base);
/*!
* @brief Substract 256 from secure counter
*
* This function substract specified 256 from secure counter.
*
* @param base CDOG peripheral base address.
*/
void CDOG_Sub256(CDOG_Type *base);
/*!
* @brief Set the CDOG persistent word.
*
* @param base CDOG peripheral base address.
* @param value The value to be written.
*/
void CDOG_WritePersistent(CDOG_Type *base, uint32_t value);
/*!
* @brief Get the CDOG persistent word.
*
* @param base CDOG peripheral base address.
* @return The persistent word.
*/
uint32_t CDOG_ReadPersistent(CDOG_Type *base);
/*! @}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/ /* end of group cdog */
#endif /* FSL_CDOG_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,983 @@
/*
* Copyright 2023, NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_CLOCK_H_
#define _FSL_CLOCK_H_
#include "fsl_common.h"
/*! @addtogroup clock */
/*! @{ */
/*! @file */
/*******************************************************************************
* Definitions
*****************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief CLOCK driver version 1.0.0. */
#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(1, 0, 0))
/*@}*/
/*! @brief Configure whether driver controls clock
*
* When set to 0, peripheral drivers will enable clock in initialize function
* and disable clock in de-initialize function. When set to 1, peripheral
* driver will not control the clock, application could control the clock out of
* the driver.
*
* @note All drivers share this feature switcher. If it is set to 1, application
* should handle clock enable and disable for all drivers.
*/
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0U
#endif
/* Definition for delay API in clock driver, users can redefine it to the real application. */
#ifndef SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY
#define SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY (96000000U)
#endif
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
/*------------------------------------------------------------------------------
clock_ip_name_t definition:
------------------------------------------------------------------------------*/
#define CLK_GATE_REG_OFFSET(value) (((uint32_t)(value)) >> 16U)
#define CLK_GATE_BIT_SHIFT(value) (((uint32_t)(value)) & 0x0000FFFFU)
#define REG_PWM0SUBCTL (250U)
#define REG_PWM1SUBCTL (240U)
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
typedef enum _clock_ip_name
{
kCLOCK_InputMux = (0x0000U | (0U)), /*!< Clock gate name: INPUTMUX0 */
kCLOCK_GateINPUTMUX0 = (0x0000U | (0U)), /*!< Clock gate name: INPUTMUX0 */
kCLOCK_GateI3C0 = (0x0000U | (1U)), /*!< Clock gate name: I3C0 */
kCLOCK_GateCTIMER0 = (0x0000U | (2U)), /*!< Clock gate name: CTIMER0 */
kCLOCK_GateCTIMER1 = (0x0000U | (3U)), /*!< Clock gate name: CTIMER1 */
kCLOCK_GateCTIMER2 = (0x0000U | (4U)), /*!< Clock gate name: CTIMER2 */
kCLOCK_GateCTIMER3 = (0x0000U | (5U)), /*!< Clock gate name: CTIMER3 */
kCLOCK_GateCTIMER4 = (0x0000U | (6U)), /*!< Clock gate name: CTIMER4 */
kCLOCK_GateFREQME = (0x0000U | (7U)), /*!< Clock gate name: FREQME */
kCLOCK_GateUTICK0 = (0x0000U | (8U)), /*!< Clock gate name: UTICK0 */
kCLOCK_GateWWDT0 = (0x0000U | (9U)), /*!< Clock gate name: WWDT0 */
kCLOCK_GateDMA = (0x0000U | (10U)), /*!< Clock gate name: DMA */
kCLOCK_GateAOI0 = (0x0000U | (11U)), /*!< Clock gate name: AOI0 */
kCLOCK_GateCRC0 = (0x0000U | (12U)), /*!< Clock gate name: CRC0 */
kCLOCK_Crc0 = (0x0000U | (12U)), /*!< Clock gate name: CRC0 */
kCLOCK_GateEIM0 = (0x0000U | (13U)), /*!< Clock gate name: EIM0 */
kCLOCK_GateERM0 = (0x0000U | (14U)), /*!< Clock gate name: ERM0 */
kCLOCK_GateFMC = (0x0000U | (15U)), /*!< Clock gate name: FMC */
kCLOCK_GateAOI1 = (0x0000U | (16U)), /*!< Clock gate name: AOI1 */
kCLOCK_GateFLEXIO0 = (0x0000U | (17U)), /*!< Clock gate name: FLEXIO0 */
kCLOCK_GateLPI2C0 = (0x0000U | (18U)), /*!< Clock gate name: LPI2C0 */
kCLOCK_GateLPI2C1 = (0x0000U | (19U)), /*!< Clock gate name: LPI2C1 */
kCLOCK_GateLPSPI0 = (0x0000U | (20U)), /*!< Clock gate name: LPSPI0 */
kCLOCK_GateLPSPI1 = (0x0000U | (21U)), /*!< Clock gate name: LPSPI1 */
kCLOCK_GateLPUART0 = (0x0000U | (22U)), /*!< Clock gate name: LPUART0 */
kCLOCK_GateLPUART1 = (0x0000U | (23U)), /*!< Clock gate name: LPUART1 */
kCLOCK_GateLPUART2 = (0x0000U | (24U)), /*!< Clock gate name: LPUART2 */
kCLOCK_GateLPUART3 = (0x0000U | (25U)), /*!< Clock gate name: LPUART3 */
kCLOCK_GateLPUART4 = (0x0000U | (26U)), /*!< Clock gate name: LPUART4 */
kCLOCK_GateUSB0 = (0x0000U | (27U)), /*!< Clock gate name: USB0 */
kCLOCK_GateQDC0 = (0x0000U | (28U)), /*!< Clock gate name: QDC0 */
kCLOCK_GateQDC1 = (0x0000U | (29U)), /*!< Clock gate name: QDC1 */
kCLOCK_GateFLEXPWM0 = (0x0000U | (30U)), /*!< Clock gate name: FLEXPWM0 */
kCLOCK_GateFLEXPWM1 = (0x0000U | (31U)), /*!< Clock gate name: FLEXPWM1 */
kCLOCK_GateOSTIMER0 = ((0x10U << 16U) | (0U)), /*!< Clock gate name: OSTIMER0 */
kCLOCK_GateADC0 = ((0x10U << 16U) | (1U)), /*!< Clock gate name: ADC0 */
kCLOCK_GateADC1 = ((0x10U << 16U) | (2U)), /*!< Clock gate name: ADC1 */
kCLOCK_GateCMP0 = ((0x10U << 16U) | (3U)), /*!< Clock gate name: CMP0 */
kCLOCK_GateCMP1 = ((0x10U << 16U) | (4U)), /*!< Clock gate name: CMP1 */
kCLOCK_GateDAC0 = ((0x10U << 16U) | (5U)), /*!< Clock gate name: DAC0 */
kCLOCK_GateOPAMP0 = ((0x10U << 16U) | (6U)), /*!< Clock gate name: OPAMP0 */
kCLOCK_GatePORT0 = ((0x10U << 16U) | (7U)), /*!< Clock gate name: PORT0 */
kCLOCK_GatePORT1 = ((0x10U << 16U) | (8U)), /*!< Clock gate name: PORT1 */
kCLOCK_GatePORT2 = ((0x10U << 16U) | (9U)), /*!< Clock gate name: PORT2 */
kCLOCK_GatePORT3 = ((0x10U << 16U) | (10U)), /*!< Clock gate name: PORT3 */
kCLOCK_GatePORT4 = ((0x10U << 16U) | (11U)), /*!< Clock gate name: PORT4 */
kCLOCK_GateFLEXCAN0 = ((0x10U << 16U) | (12U)), /*!< Clock gate name: FLEXCAN0 */
kCLOCK_GateLPI2C2 = ((0x10U << 16U) | (13U)), /*!< Clock gate name: LPI2C2 */
kCLOCK_GateLPI2C3 = ((0x10U << 16U) | (14U)), /*!< Clock gate name: LPI2C3 */
kCLOCK_GateMTR = ((0x10U << 16U) | (16U)), /*!< Clock gate name: MTR */
kCLOCK_GateTCU = ((0x10U << 16U) | (17U)), /*!< Clock gate name: TCU */
kCLOCK_GateRAMA = ((0x10U << 16U) | (18U)), /*!< Clock gate name: RAMA */
kCLOCK_GateRAMB = ((0x10U << 16U) | (19U)), /*!< Clock gate name: RAMB */
kCLOCK_GateGPIO0 = ((0x10U << 16U) | (20U)), /*!< Clock gate name: GPIO0 */
kCLOCK_GateGPIO1 = ((0x10U << 16U) | (21U)), /*!< Clock gate name: GPIO1 */
kCLOCK_GateGPIO2 = ((0x10U << 16U) | (22U)), /*!< Clock gate name: GPIO2 */
kCLOCK_GateGPIO3 = ((0x10U << 16U) | (23U)), /*!< Clock gate name: GPIO3 */
kCLOCK_GateGPIO4 = ((0x10U << 16U) | (24U)), /*!< Clock gate name: GPIO4 */
kCLOCK_GateROMC = ((0x10U << 16U) | (25U)), /*!< Clock gate name: ROMC */
kCLOCK_GatePWM0SM0 = ((REG_PWM0SUBCTL << 16U) | (0U)), /*!< Clock gate name: FlexPWM0 SM0 */
kCLOCK_GatePWM0SM1 = ((REG_PWM0SUBCTL << 16U) | (1U)), /*!< Clock gate name: FlexPWM0 SM1 */
kCLOCK_GatePWM0SM2 = ((REG_PWM0SUBCTL << 16U) | (2U)), /*!< Clock gate name: FlexPWM0 SM2 */
kCLOCK_GatePWM1SM0 = ((REG_PWM1SUBCTL << 16U) | (0U)), /*!< Clock gate name: FlexPWM1 SM0 */
kCLOCK_GatePWM1SM1 = ((REG_PWM1SUBCTL << 16U) | (1U)), /*!< Clock gate name: FlexPWM1 SM1 */
kCLOCK_GatePWM1SM2 = ((REG_PWM1SUBCTL << 16U) | (2U)), /*!< Clock gate name: FlexPWM1 SM2 */
kCLOCK_GateNotAvail = (0xFFFFFFFFU), /**< Clock gate name: None */
} clock_ip_name_t;
/*! @brief Clock ip name array for AOI. */
#define AOI_CLOCKS \
{ \
kCLOCK_GateAOI0, kCLOCK_GateAOI1 \
}
/*! @brief Clock ip name array for CRC. */
#define CRC_CLOCKS \
{ \
kCLOCK_GateCRC0 \
}
/*! @brief Clock ip name array for CTIMER. */
#define CTIMER_CLOCKS \
{ \
kCLOCK_GateCTIMER0, kCLOCK_GateCTIMER1, kCLOCK_GateCTIMER2, kCLOCK_GateCTIMER3, kCLOCK_GateCTIMER4 \
}
/*! @brief Clock ip name array for DAC. */
#define LPDAC_CLOCKS \
{ \
kCLOCK_GateDAC0 \
}
/*! @brief Clock ip name array for DMA. */
#define DMA_CLOCKS \
{ \
kCLOCK_GateDMA \
}
/*! @brief Clock gate name array for EDMA. */
#define EDMA_CLOCKS \
{ \
kCLOCK_GateDMA \
}
/*! @brief Clock ip name array for ERM. */
#define ERM_CLOCKS \
{ \
kCLOCK_GateERM0 \
}
/*! @brief Clock ip name array for EIM. */
#define EIM_CLOCKS \
{ \
kCLOCK_GateEIM0 \
}
/*! @brief Clock ip name array for FLEXCAN. */
#define FLEXCAN_CLOCKS \
{ \
kCLOCK_GateFLEXCAN0 \
}
/*! @brief Clock ip name array for FLEXIO. */
#define FLEXIO_CLOCKS \
{ \
kCLOCK_GateFLEXIO0 \
}
/*! @brief Clock ip name array for FREQME. */
#define FREQME_CLOCKS \
{ \
kCLOCK_GateFREQME \
}
/*! @brief Clock ip name array for GPIO. */
#define GPIO_CLOCKS \
{ \
kCLOCK_GateGPIO0, kCLOCK_GateGPIO1, kCLOCK_GateGPIO2, kCLOCK_GateGPIO3, kCLOCK_GateGPIO4 \
}
/*! @brief Clock ip name array for I3C */
#define I3C_CLOCKS \
{ \
kCLOCK_GateI3C0 \
}
/*! @brief Clock ip name array for INPUTMUX. */
#define INPUTMUX_CLOCKS \
{ \
kCLOCK_GateINPUTMUX0 \
}
/*! @brief Clock ip name array for GPIO. */
#define LPCMP_CLOCKS \
{ \
kCLOCK_GateCMP0, kCLOCK_GateCMP1 \
}
/*! @brief Clock ip name array for LPADC. */
#define LPADC_CLOCKS \
{ \
kCLOCK_GateADC0, kCLOCK_GateADC1 \
}
/*! @brief Clock ip name array for LPUART. */
#define LPUART_CLOCKS \
{ \
kCLOCK_GateLPUART0, kCLOCK_GateLPUART1, kCLOCK_GateLPUART2, kCLOCK_GateLPUART3, kCLOCK_GateLPUART4 \
}
/*! @brief Clock ip name array for LPI2C. */
#define LPI2C_CLOCKS \
{ \
kCLOCK_GateLPI2C0, kCLOCK_GateLPI2C1, kCLOCK_GateLPI2C2, kCLOCK_GateLPI2C3 \
}
/*! @brief Clock ip name array for LSPI. */
#define LPSPI_CLOCKS \
{ \
kCLOCK_GateLPSPI0, kCLOCK_GateLPSPI1 \
}
/*! @brief Clock ip name array for MTR. */
#define MTR_CLOCKS \
{ \
kCLOCK_GateMTR \
}
/*! @brief Clock ip name array for OSTIMER. */
#define OSTIMER_CLOCKS \
{ \
kCLOCK_GateOSTIMER0 \
}
/*! @brief Clock ip name array for DAC. */
#define OPAMP_CLOCKS \
{ \
kCLOCK_GateOPAMP0 \
}
/*! @brief Clock ip name array for PWM. */
#define PWM_CLOCKS \
{ \
{kCLOCK_GatePWM0SM0, kCLOCK_GatePWM0SM1, kCLOCK_GatePWM0SM2}, \
{ \
kCLOCK_GatePWM1SM0, kCLOCK_GatePWM1SM1, kCLOCK_GatePWM1SM2 \
} \
}
/*! @brief Clock ip name array for QDC. */
#define QDC_CLOCKS \
{ \
kCLOCK_GateQDC0, kCLOCK_GateQDC1 \
}
/*! @brief Clock ip name array for UTICK. */
#define UTICK_CLOCKS \
{ \
kCLOCK_GateUTICK0 \
}
/*! @brief Clock ip name array for WWDT. */
#define WWDT_CLOCKS \
{ \
kCLOCK_GateWWDT0 \
}
/*! @brief Peripherals clock source definition. */
#define BUS_CLK kCLOCK_BusClk
/*! @brief Clock name used to get clock frequency. */
typedef enum _clock_name
{
kCLOCK_MainClk, /*!< MAIN_CLK */
kCLOCK_CoreSysClk, /*!< Core/system clock(CPU_CLK) */
kCLOCK_SYSTEM_CLK, /*!< AHB clock */
kCLOCK_BusClk, /*!< Bus clock (AHB clock) */
kCLOCK_ExtClk, /*!< External Clock */
kCLOCK_FroHf, /*!< FRO192 */
kCLOCK_FroHfDiv, /*!< Divided by FRO192 */
kCLOCK_Clk48M, /*!< CLK48M */
kCLOCK_Fro12M, /*!< FRO12M */
kCLOCK_Clk1M, /*!< CLK1M */
kCLOCK_Fro16K, /*!< FRO16K */
kCLOCK_Clk16K0, /*!< CLK16K[0] */
kCLOCK_Clk16K1, /*!< CLK16K[1] */
kCLOCK_SLOW_CLK, /*!< SYSTEM_CLK divided by 4 */
} clock_name_t;
/*! @brief Clock Mux Switches
* The encoding is as follows each connection identified is 32bits wide while 24bits are valuable
* starting from LSB upwards
*
* [4 bits for choice, 0 means invalid choice] [8 bits mux ID]*
*
*/
#define CLK_ATTACH_REG_OFFSET(value) (((uint32_t)(value)) >> 16U)
#define CLK_ATTACH_CLK_SEL(value) (((uint32_t)(value)) & 0x0000FFFFU)
#define CLK_ATTACH_MUX(reg, sel) ((((uint32_t)(reg)) << 16U) | (sel))
/*! @brief Clock name used to get clock frequency. */
typedef enum _clock_select_name
{
kCLOCK_SelI3C0_FCLK = (0x0A0), /*<! I3C0_FCLK clock selection */
kCLOCK_SelCTIMER0 = (0x0A8), /*<! CTIMER0 clock selection */
kCLOCK_SelCTIMER1 = (0x0B0), /*<! CTIMER1 clock selection */
kCLOCK_SelCTIMER2 = (0x0B8), /*<! CTIMER2 clock selection */
kCLOCK_SelCTIMER3 = (0x0C0), /*<! CTIMER3 clock selection */
kCLOCK_SelCTIMER4 = (0x0C8), /*<! CTIMER4 clock selection */
kCLOCK_SelFLEXIO0 = (0x0D8), /*<! FLEXIO0 clock selection */
kCLOCK_SelLPI2C0 = (0x0E0), /*<! LPI2C0 clock selection */
kCLOCK_SelLPI2C1 = (0x0E8), /*<! LPI2C1 clock selection */
kCLOCK_SelLPSPI0 = (0x0F0), /*<! LPSPI0 clock selection */
kCLOCK_SelLPSPI1 = (0x0F8), /*<! LPSPI1 clock selection */
kCLOCK_SelLPUART0 = (0x100), /*<! LPUART0 clock selection */
kCLOCK_SelLPUART1 = (0x108), /*<! LPUART1 clock selection */
kCLOCK_SelLPUART2 = (0x110), /*<! LPUART2 clock selection */
kCLOCK_SelLPUART3 = (0x118), /*<! LPUART3 clock selection */
kCLOCK_SelLPUART4 = (0x120), /*<! LPUART4 clock selection */
kCLOCK_SelUSB0 = (0x128), /*<! USB0 clock selection */
kCLOCK_SelLPTMR0 = (0x130), /*<! LPTMR0 clock selection */
kCLOCK_SelOSTIMER0 = (0x138), /*<! OSTIMER0 clock selection */
kCLOCK_SelADC0 = (0x140), /*<! ADC0 clock selection */
kCLOCK_SelADC1 = (0x148), /*<! ADC1 clock selection */
kCLOCK_SelCMP0_RR = (0x158), /*<! CMP0_RR clock selection */
kCLOCK_SelCMP1_RR = (0x168), /*<! CMP1_RR clock selection */
kCLOCK_SelDAC0 = (0x170), /*<! DAC0 clock selection */
kCLOCK_SelFLEXCAN0 = (0x178), /*<! FLEXCAN0 clock selection */
kCLOCK_SelLPI2C2 = (0x180), /*<! LPI2C2 clock selection */
kCLOCK_SelLPI2C3 = (0x188), /*<! LPI2C3 clock selection */
kCLOCK_SelTRACE = (0x190), /*<! DBG_TRACE clock selection */
kCLOCK_SelCLKOUT = (0x198), /*<! CLKOUT clock selection */
kCLOCK_SelSYSTICK = (0x1A0), /*<! SYSTICK clock selection */
kCLOCK_SelSCGSCS = (0x200U), /*!< SCG SCS clock selection */
kCLOCK_SelMax = (0x200U), /*!< MAX clock selection */
} clock_select_name_t;
/*!
* @brief The enumerator of clock attach Id.
*/
typedef enum _clock_attach_id
{
kCLK_IN_to_MAIN_CLK = CLK_ATTACH_MUX(kCLOCK_SelSCGSCS, 1U), /*!< Attach clk_in to MAIN_CLK. */
kFRO12M_to_MAIN_CLK = CLK_ATTACH_MUX(kCLOCK_SelSCGSCS, 2U), /*!< Attach FRO_12M to MAIN_CLK. */
kFRO_HF_to_MAIN_CLK = CLK_ATTACH_MUX(kCLOCK_SelSCGSCS, 3U), /*!< Attach FRO_HF to MAIN_CLK. */
kCLK_16K_to_MAIN_CLK = CLK_ATTACH_MUX(kCLOCK_SelSCGSCS, 4U), /*!< Attach CLK_16K[1] to MAIN_CLK. */
kNONE_to_MAIN_CLK = CLK_ATTACH_MUX(kCLOCK_SelSCGSCS, 7U), /*!< Attach NONE to MAIN_CLK. */
kFRO12M_to_I3C0FCLK = CLK_ATTACH_MUX(kCLOCK_SelI3C0_FCLK, 0U), /*!< Attach FRO12M to I3C0FCLK. */
kFRO_HF_DIV_to_I3C0FCLK = CLK_ATTACH_MUX(kCLOCK_SelI3C0_FCLK, 2U), /*!< Attach FRO_HF_DIV to I3C0FCLK. */
kCLK_IN_to_I3C0FCLK = CLK_ATTACH_MUX(kCLOCK_SelI3C0_FCLK, 3U), /*!< Attach CLK_IN to I3C0FCLK. */
kCLK_1M_to_I3C0FCLK = CLK_ATTACH_MUX(kCLOCK_SelI3C0_FCLK, 5U), /*!< Attach CLK_1M to I3C0FCLK. */
kNONE_to_I3C0FCLK = CLK_ATTACH_MUX(kCLOCK_SelI3C0_FCLK, 7U), /*!< Attach NONE to I3C0FCLK. */
kFRO12M_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 0U), /*!< Attach FRO12M to CTIMER0. */
kFRO_HF_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 1U), /*!< Attach FRO_HF to CTIMER0. */
kCLK_IN_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 3U), /*!< Attach CLK_IN to CTIMER0. */
kCLK_16K_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 4U), /*!< Attach CLK_16K to CTIMER0. */
kCLK_1M_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 5U), /*!< Attach CLK_1M to CTIMER0. */
kNONE_to_CTIMER0 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER0, 7U), /*!< Attach NONE to CTIMER0. */
kFRO12M_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 0U), /*!< Attach FRO12M to CTIMER1. */
kFRO_HF_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 1U), /*!< Attach FRO_HF to CTIMER1. */
kCLK_IN_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 3U), /*!< Attach CLK_IN to CTIMER1. */
kCLK_16K_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 4U), /*!< Attach CLK_16K to CTIMER1. */
kCLK_1M_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 5U), /*!< Attach CLK_1M to CTIMER1. */
kNONE_to_CTIMER1 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER1, 7U), /*!< Attach NONE to CTIMER1. */
kFRO12M_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 0U), /*!< Attach FRO12M to CTIMER2. */
kFRO_HF_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 1U), /*!< Attach FRO_HF to CTIMER2. */
kCLK_IN_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 3U), /*!< Attach CLK_IN to CTIMER2. */
kCLK_16K_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 4U), /*!< Attach CLK_16K to CTIMER2. */
kCLK_1M_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 5U), /*!< Attach CLK_1M to CTIMER2. */
kNONE_to_CTIMER2 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER2, 7U), /*!< Attach NONE to CTIMER2. */
kFRO12M_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 0U), /*!< Attach FRO12M to CTIMER3. */
kFRO_HF_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 1U), /*!< Attach FRO_HF to CTIMER3. */
kCLK_IN_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 3U), /*!< Attach CLK_IN to CTIMER3. */
kCLK_16K_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 4U), /*!< Attach CLK_16K to CTIMER3. */
kCLK_1M_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 5U), /*!< Attach CLK_1M to CTIMER3. */
kNONE_to_CTIMER3 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER3, 7U), /*!< Attach NONE to CTIMER3. */
kFRO12M_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 0U), /*!< Attach FRO12M to CTIMER4. */
kFRO_HF_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 1U), /*!< Attach FRO_HF to CTIMER4. */
kCLK_IN_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 3U), /*!< Attach CLK_IN to CTIMER4. */
kCLK_16K_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 4U), /*!< Attach CLK_16K to CTIMER4. */
kCLK_1M_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 5U), /*!< Attach CLK_1M to CTIMER4. */
kNONE_to_CTIMER4 = CLK_ATTACH_MUX(kCLOCK_SelCTIMER4, 7U), /*!< Attach NONE to CTIMER4. */
kFRO12M_to_FLEXIO0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXIO0, 0U), /*!< Attach FRO12M to FLEXIO0. */
kFRO_HF_to_FLEXIO0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXIO0, 1U), /*!< Attach FRO_HF to FLEXIO0. */
kCLK_IN_to_FLEXIO0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXIO0, 3U), /*!< Attach CLK_IN to FLEXIO0. */
kCLK_1M_to_FLEXIO0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXIO0, 5U), /*!< Attach CLK_1M to FLEXIO0. */
kNONE_to_FLEXIO0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXIO0, 7U), /*!< Attach NONE to FLEXIO0. */
kFRO_HF_DIV_to_FLEXCAN0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXCAN0, 2U), /*!< Attach FRO_HF_DIV to FLEXCAN0.*/
kCLK_IN_to_FLEXCAN0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXCAN0, 3U), /*!< Attach CLK_IN to FLEXCAN0. */
kNONE_to_FLEXCAN0 = CLK_ATTACH_MUX(kCLOCK_SelFLEXCAN0, 7U), /*!< Attach NONE to FLEXCAN0. */
kFRO12M_to_DAC0 = CLK_ATTACH_MUX(kCLOCK_SelDAC0, 0U), /*!< Attach FRO12M to DAC0. */
kFRO_HF_DIV_to_DAC0 = CLK_ATTACH_MUX(kCLOCK_SelDAC0, 2U), /*!< Attach FRO_HF_DIV to DAC0. */
kCLK_IN_to_DAC0 = CLK_ATTACH_MUX(kCLOCK_SelDAC0, 3U), /*!< Attach CLK_IN to DAC0. */
kCLK_1M_to_DAC0 = CLK_ATTACH_MUX(kCLOCK_SelDAC0, 5U), /*!< Attach CLK_1M to DAC0. */
kNONE_to_DAC0 = CLK_ATTACH_MUX(kCLOCK_SelDAC0, 7U), /*!< Attach NONE to DAC0. */
kFRO12M_to_LPI2C0 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C0, 0U), /*!< Attach FRO12M to LPI2C0. */
kFRO_HF_DIV_to_LPI2C0 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C0, 2U), /*!< Attach FRO_HF_DIV to LPI2C0. */
kCLK_IN_to_LPI2C0 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C0, 3U), /*!< Attach CLK_IN to LPI2C0. */
kCLK_1M_to_LPI2C0 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C0, 5U), /*!< Attach CLK_1M to LPI2C0. */
kNONE_to_LPI2C0 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C0, 7U), /*!< Attach NONE to LPI2C0. */
kFRO12M_to_LPI2C1 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C1, 0U), /*!< Attach FRO12M to LPI2C1. */
kFRO_HF_DIV_to_LPI2C1 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C1, 2U), /*!< Attach FRO_HF_DIV to LPI2C1. */
kCLK_IN_to_LPI2C1 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C1, 3U), /*!< Attach CLK_IN to LPI2C1. */
kCLK_1M_to_LPI2C1 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C1, 5U), /*!< Attach CLK_1M to LPI2C1. */
kNONE_to_LPI2C1 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C1, 7U), /*!< Attach NONE to LPI2C1. */
kFRO12M_to_LPI2C2 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C2, 0U), /*!< Attach FRO12M to LPI2C2. */
kFRO_HF_DIV_to_LPI2C2 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C2, 2U), /*!< Attach FRO_HF_DIV to LPI2C2. */
kCLK_IN_to_LPI2C2 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C2, 3U), /*!< Attach CLK_IN to LPI2C2. */
kCLK_1M_to_LPI2C2 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C2, 5U), /*!< Attach CLK_1M to LPI2C2. */
kNONE_to_LPI2C2 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C2, 7U), /*!< Attach NONE to LPI2C2. */
kFRO12M_to_LPI2C3 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C3, 0U), /*!< Attach FRO12M to LPI2C3. */
kFRO_HF_DIV_to_LPI2C3 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C3, 2U), /*!< Attach FRO_HF_DIV to LPI2C3. */
kCLK_IN_to_LPI2C3 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C3, 3U), /*!< Attach CLK_IN to LPI2C3. */
kCLK_1M_to_LPI2C3 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C3, 5U), /*!< Attach CLK_1M to LPI2C3. */
kNONE_to_LPI2C3 = CLK_ATTACH_MUX(kCLOCK_SelLPI2C3, 7U), /*!< Attach NONE to LPI2C3. */
kFRO12M_to_LPSPI0 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI0, 0U), /*!< Attach FRO12M to LPSPI0. */
kFRO_HF_DIV_to_LPSPI0 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI0, 2U), /*!< Attach FRO_HF_DIV to LPSPI0. */
kCLK_IN_to_LPSPI0 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI0, 3U), /*!< Attach CLK_IN to LPSPI0. */
kCLK_1M_to_LPSPI0 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI0, 5U), /*!< Attach CLK_1M to LPSPI0. */
kNONE_to_LPSPI0 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI0, 7U), /*!< Attach NONE to LPSPI0. */
kFRO12M_to_LPSPI1 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI1, 0U), /*!< Attach FRO12M to LPSPI1. */
kFRO_HF_DIV_to_LPSPI1 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI1, 2U), /*!< Attach FRO_HF_DIV to LPSPI1. */
kCLK_IN_to_LPSPI1 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI1, 3U), /*!< Attach CLK_IN to LPSPI1. */
kCLK_1M_to_LPSPI1 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI1, 5U), /*!< Attach CLK_1M to LPSPI1. */
kNONE_to_LPSPI1 = CLK_ATTACH_MUX(kCLOCK_SelLPSPI1, 7U), /*!< Attach NONE to LPSPI1. */
kFRO12M_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 0U), /*!< Attach FRO12M to LPUART0. */
kFRO_HF_DIV_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 2U), /*!< Attach FRO_HF_DIV to LPUART0. */
kCLK_IN_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 3U), /*!< Attach CLK_IN to LPUART0. */
kCLK_16K_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 4U), /*!< Attach CLK_16K to LPUART0. */
kCLK_1M_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 5U), /*!< Attach CLK_1M to LPUART0. */
kNONE_to_LPUART0 = CLK_ATTACH_MUX(kCLOCK_SelLPUART0, 7U), /*!< Attach NONE to LPUART0. */
kFRO12M_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 0U), /*!< Attach FRO12M to LPUART1. */
kFRO_HF_DIV_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 2U), /*!< Attach FRO_HF_DIV to LPUART1. */
kCLK_IN_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 3U), /*!< Attach CLK_IN to LPUART1. */
kCLK_16K_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 4U), /*!< Attach CLK_16K to LPUART1. */
kCLK_1M_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 5U), /*!< Attach CLK_1M to LPUART1. */
kNONE_to_LPUART1 = CLK_ATTACH_MUX(kCLOCK_SelLPUART1, 7U), /*!< Attach NONE to LPUART1. */
kFRO12M_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 0U), /*!< Attach FRO12M to LPUART2. */
kFRO_HF_DIV_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 2U), /*!< Attach FRO_HF_DIV to LPUART2. */
kCLK_IN_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 3U), /*!< Attach CLK_IN to LPUART2. */
kCLK_16K_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 4U), /*!< Attach CLK_16K to LPUART2. */
kCLK_1M_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 5U), /*!< Attach CLK_1M to LPUART2. */
kNONE_to_LPUART2 = CLK_ATTACH_MUX(kCLOCK_SelLPUART2, 7U), /*!< Attach NONE to LPUART2. */
kFRO12M_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 0U), /*!< Attach FRO12M to LPUART2. */
kFRO_HF_DIV_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 2U), /*!< Attach FRO_HF_DIV to LPUART2. */
kCLK_IN_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 3U), /*!< Attach CLK_IN to LPUART2. */
kCLK_16K_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 4U), /*!< Attach CLK_16K to LPUART2. */
kCLK_1M_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 5U), /*!< Attach CLK_1M to LPUART2. */
kNONE_to_LPUART3 = CLK_ATTACH_MUX(kCLOCK_SelLPUART3, 7U), /*!< Attach NONE to LPUART2. */
kFRO12M_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 0U), /*!< Attach FRO12M to LPUART4. */
kFRO_HF_DIV_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 2U), /*!< Attach FRO_HF_DIV to LPUART4. */
kCLK_IN_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 3U), /*!< Attach CLK_IN to LPUART4. */
kCLK_16K_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 4U), /*!< Attach CLK_16K to LPUART4. */
kCLK_1M_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 5U), /*!< Attach CLK_1M to LPUART4. */
kNONE_to_LPUART4 = CLK_ATTACH_MUX(kCLOCK_SelLPUART4, 7U), /*!< Attach NONE to LPUART4. */
kCLK_48M_to_USB0 = CLK_ATTACH_MUX(kCLOCK_SelUSB0, 1U), /*!< Attach FRO12M to USB0. */
kCLK_IN_to_USB0 = CLK_ATTACH_MUX(kCLOCK_SelUSB0, 2U), /*!< Attach CLK_IN to USB0. */
kNONE_to_USB0 = CLK_ATTACH_MUX(kCLOCK_SelUSB0, 3U), /*!< Attach NONE to USB0. */
kFRO12M_to_LPTMR0 = CLK_ATTACH_MUX(kCLOCK_SelLPTMR0, 0U), /*!< Attach FRO12M to LPTMR0. */
kFRO_HF_DIV_to_LPTMR0 = CLK_ATTACH_MUX(kCLOCK_SelLPTMR0, 2U), /*!< Attach FRO_HF_DIV to LPTMR0. */
kCLK_IN_to_LPTMR0 = CLK_ATTACH_MUX(kCLOCK_SelLPTMR0, 3U), /*!< Attach CLK_IN to LPTMR0. */
kCLK_1M_to_LPTMR0 = CLK_ATTACH_MUX(kCLOCK_SelLPTMR0, 5U), /*!< Attach CLK_1M to LPTMR0. */
kNONE_to_LPTMR0 = CLK_ATTACH_MUX(kCLOCK_SelLPTMR0, 7U), /*!< Attach NONE to LPTMR0. */
kCLK_16K_to_OSTIMER = CLK_ATTACH_MUX(kCLOCK_SelOSTIMER0, 0U), /*!< Attach FRO16K to OSTIMER0. */
kCLK_1M_to_OSTIMER = CLK_ATTACH_MUX(kCLOCK_SelOSTIMER0, 2U), /*!< Attach CLK_1M to OSTIMER0. */
kNONE_to_OSTIMER = CLK_ATTACH_MUX(kCLOCK_SelOSTIMER0, 3U), /*!< Attach NONE to OSTIMER0. */
kFRO12M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 0U), /*!< Attach FRO12M to ADC0. */
kFRO_HF_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 1U), /*!< Attach FRO_HF to ADC0. */
kCLK_IN_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 3U), /*!< Attach CLK_IN to ADC0. */
kCLK_1M_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 5U), /*!< Attach CLK_1M to ADC0. */
kNONE_to_ADC0 = CLK_ATTACH_MUX(kCLOCK_SelADC0, 7U), /*!< Attach NONE to ADC0. */
kFRO12M_to_ADC1 = CLK_ATTACH_MUX(kCLOCK_SelADC1, 0U), /*!< Attach FRO12M to ADC1. */
kFRO_HF_to_ADC1 = CLK_ATTACH_MUX(kCLOCK_SelADC1, 1U), /*!< Attach FRO_HF to ADC1. */
kCLK_IN_to_ADC1 = CLK_ATTACH_MUX(kCLOCK_SelADC1, 3U), /*!< Attach CLK_IN to ADC1. */
kCLK_1M_to_ADC1 = CLK_ATTACH_MUX(kCLOCK_SelADC1, 5U), /*!< Attach CLK_1M to ADC1. */
kNONE_to_ADC1 = CLK_ATTACH_MUX(kCLOCK_SelADC1, 7U), /*!< Attach NONE to ADC1. */
kFRO12M_to_CMP0 = CLK_ATTACH_MUX(kCLOCK_SelCMP0_RR, 0U), /*!< Attach FRO12M to CMP0. */
kFRO_HF_DIV_to_CMP0 = CLK_ATTACH_MUX(kCLOCK_SelCMP0_RR, 2U), /*!< Attach FRO_HF_DIV to CMP0. */
kCLK_IN_to_CMP0 = CLK_ATTACH_MUX(kCLOCK_SelCMP0_RR, 3U), /*!< Attach CLK_IN to CMP0. */
kCLK_1M_to_CMP0 = CLK_ATTACH_MUX(kCLOCK_SelCMP0_RR, 5U), /*!< Attach CLK_1M to CMP0. */
kNONE_to_CMP0 = CLK_ATTACH_MUX(kCLOCK_SelCMP0_RR, 7U), /*!< Attach NONE to CMP0. */
kFRO12M_to_CMP1 = CLK_ATTACH_MUX(kCLOCK_SelCMP1_RR, 0U), /*!< Attach FRO12M to CMP1. */
kFRO_HF_DIV_to_CMP1 = CLK_ATTACH_MUX(kCLOCK_SelCMP1_RR, 2U), /*!< Attach FRO_HF_DIV to CMP1. */
kCLK_IN_to_CMP1 = CLK_ATTACH_MUX(kCLOCK_SelCMP1_RR, 3U), /*!< Attach CLK_IN to CMP1. */
kCLK_1M_to_CMP1 = CLK_ATTACH_MUX(kCLOCK_SelCMP1_RR, 5U), /*!< Attach CLK_1M to CMP1. */
kNONE_to_CMP1 = CLK_ATTACH_MUX(kCLOCK_SelCMP1_RR, 7U), /*!< Attach NONE to CMP1. */
kCPU_CLK_to_TRACE = CLK_ATTACH_MUX(kCLOCK_SelTRACE, 0U), /*!< Attach CPU_CLK to TRACE. */
kCLK_1M_to_TRACE = CLK_ATTACH_MUX(kCLOCK_SelTRACE, 1U), /*!< Attach CLK_1M to TRACE. */
kCLK_16K_to_TRACE = CLK_ATTACH_MUX(kCLOCK_SelTRACE, 2U), /*!< Attach CLK_16K to TRACE. */
kNONE_to_TRACE = CLK_ATTACH_MUX(kCLOCK_SelTRACE, 3U), /*!< Attach NONE to TRACE. */
kFRO12M_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 0U), /*!< Attach FRO12M to CLKOUT. */
kFRO_HF_DIV_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 1U), /*!< Attach FRO_HF_DIV to CLKOUT. */
kCLK_IN_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 2U), /*!< Attach CLK_IN to CLKOUT. */
kCLK_16K_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 3U), /*!< Attach CLK_16K to CLKOUT. */
kSLOW_CLK_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 6U), /*!< Attach SLOW_CLK to CLKOUT. */
kNONE_to_CLKOUT = CLK_ATTACH_MUX(kCLOCK_SelCLKOUT, 7U), /*!< Attach NONE to CLKOUT. */
kCPU_CLK_to_SYSTICK = CLK_ATTACH_MUX(kCLOCK_SelSYSTICK, 0U), /*!< Attach CPU_CLK to SYSTICK. */
kCLK_1M_to_SYSTICK = CLK_ATTACH_MUX(kCLOCK_SelSYSTICK, 1U), /*!< Attach CLK_1M to SYSTICK. */
kCLK_16K_to_SYSTICK = CLK_ATTACH_MUX(kCLOCK_SelSYSTICK, 2U), /*!< Attach CLK_16K to SYSTICK. */
kNONE_to_SYSTICK = CLK_ATTACH_MUX(kCLOCK_SelSYSTICK, 3U), /*!< Attach NONE to SYSTICK. */
kNONE_to_NONE = (0xFFFFFFFFU), /*!< Attach NONE to NONE. */
} clock_attach_id_t;
/*! @brief Clock dividers */
typedef enum _clock_div_name
{
kCLOCK_DivI3C0_FCLK = (0x0A4), /*!< I3C0_FCLK clock divider */
kCLOCK_DivCTIMER0 = (0x0AC), /*!< CTIMER0 clock divider */
kCLOCK_DivCTIMER1 = (0x0B4), /*!< CTIMER1 clock divider */
kCLOCK_DivCTIMER2 = (0x0BC), /*!< CTIMER2 clock divider */
kCLOCK_DivCTIMER3 = (0x0C4), /*!< CTIMER3 clock divider */
kCLOCK_DivCTIMER4 = (0x0CC), /*!< CTIMER4 clock divider */
kCLOCK_DivWWDT0 = (0x0D4), /*!< WWDT0 clock divider */
kCLOCK_DivFLEXIO0 = (0x0DC), /*!< FLEXIO0 clock divider */
kCLOCK_DivLPI2C0 = (0x0E4), /*!< LPI2C0 clock divider */
kCLOCK_DivLPI2C1 = (0x0EC), /*!< LPI2C1 clock divider */
kCLOCK_DivLPSPI0 = (0x0F4), /*!< LPSPI0 clock divider */
kCLOCK_DivLPSPI1 = (0x0FC), /*!< LPSPI1 clock divider */
kCLOCK_DivLPUART0 = (0x104), /*!< LPUART0 clock divider */
kCLOCK_DivLPUART1 = (0x10C), /*!< LPUART1 clock divider */
kCLOCK_DivLPUART2 = (0x114), /*!< LPUART2 clock divider */
kCLOCK_DivLPUART3 = (0x11C), /*!< LPUART3 clock divider */
kCLOCK_DivLPUART4 = (0x124), /*!< LPUART4 clock divider */
kCLOCK_DivLPTMR0 = (0x134), /*!< LPTMR0 clock divider */
kCLOCK_DivADC0 = (0x144), /*!< ADC0 clock divider */
kCLOCK_DivADC1 = (0x14C), /*!< ADC1 clock divider */
kCLOCK_DivCMP0_FUNC = (0x154), /*!< CMP0_FUNC clock divider */
kCLOCK_DivCMP0_RR = (0x15C), /*!< CMP0_RR clock divider */
kCLOCK_DivCMP1_FUNC = (0x164), /*!< CMP1_FUNC clock divider */
kCLOCK_DivCMP1_RR = (0x16C), /*!< CMP1_RR clock divider */
kCLOCK_DivDAC0 = (0x174), /*!< DAC0 clock divider */
kCLOCK_DivFLEXCAN0 = (0x17C), /*!< FLEXCAN0 clock divider */
kCLOCK_DivLPI2C2 = (0x184), /*!< LPI2C2 clock divider */
kCLOCK_DivLPI2C3 = (0x18C), /*!< LPI2C3 clock divider */
kCLOCK_DivDBG_TRACE = (0x194), /*!< DBG_TRACE clock divider */
kCLOCK_DivTRACE = (0x194), /*!< DBG_TRACE clock divider */
kCLOCK_DivCLKOUT = (0x19C), /*!< CLKOUT clock divider */
kCLOCK_DivSYSTICK = (0x1A4), /*!< SYSTICK clock divider */
kCLOCK_DivFRO_HF_DIV = (0x1AC), /*!< FRO_HF_DIV clock divider */
kCLOCK_DivSLOWCLK = (0x378U), /*!< SLOWCLK clock divider */
kCLOCK_DivAHBCLK = (0x380U), /*!< System clock divider */
kCLOCK_DivMax = (0x380U), /*!< MAX clock divider */
} clock_div_name_t;
/*!
* @brief firc trim mode.
*/
typedef enum _firc_trim_mode
{
kSCG_FircTrimNonUpdate = SCG_FIRCCSR_FIRCTREN_MASK,
/*!< Trim enable but not enable trim value update. In this mode, the
trim value is fixed to the initialized value which is defined by
trimCoar and trimFine in configure structure \ref firc_trim_config_t.*/
kSCG_FircTrimUpdate = SCG_FIRCCSR_FIRCTREN_MASK | SCG_FIRCCSR_FIRCTRUP_MASK
/*!< Trim enable and trim value update enable. In this mode, the trim
value is auto update. */
} firc_trim_mode_t;
/*!
* @brief firc trim source.
*/
typedef enum _firc_trim_src
{
kSCG_FircTrimSrcUsb0 = 0U, /*!< USB0 start of frame (1kHz). */
kSCG_FircTrimSrcSysOsc = 2U, /*!< System OSC. */
} firc_trim_src_t;
/*!
* @brief firc trim configuration.
*/
typedef struct _firc_trim_config
{
firc_trim_mode_t trimMode; /*!< Trim mode. */
firc_trim_src_t trimSrc; /*!< Trim source. */
uint16_t trimDiv; /*!< Divider of SOSC. */
uint8_t trimCoar; /*!< Trim coarse value; Irrelevant if trimMode is kSCG_TrimUpdate. */
uint8_t trimFine; /*!< Trim fine value; Irrelevant if trimMode is kSCG_TrimUpdate. */
} firc_trim_config_t;
/*!
* @brief sirc trim mode.
*/
typedef enum _sirc_trim_mode
{
kSCG_SircTrimNonUpdate = SCG_SIRCCSR_SIRCTREN_MASK,
/*!< Trim enable but not enable trim value update. In this mode, the
trim value is fixed to the initialized value which is defined by
trimCoar and trimFine in configure structure \ref sirc_trim_config_t.*/
kSCG_SircTrimUpdate = SCG_SIRCCSR_SIRCTREN_MASK | SCG_SIRCCSR_SIRCTRUP_MASK
/*!< Trim enable and trim value update enable. In this mode, the trim
value is auto update. */
} sirc_trim_mode_t;
/*!
* @brief sirc trim source.
*/
typedef enum _sirc_trim_src
{
kNoTrimSrc = 0, /*!< No external tirm source. */
kSCG_SircTrimSrcSysOsc = 2U, /*!< System OSC. */
} sirc_trim_src_t;
/*!
* @brief sirc trim configuration.
*/
typedef struct _sirc_trim_config
{
sirc_trim_mode_t trimMode; /*!< Trim mode. */
sirc_trim_src_t trimSrc; /*!< Trim source. */
uint16_t trimDiv; /*!< Divider of SOSC. */
uint8_t cltrim; /*!< Trim coarse value; Irrelevant if trimMode is kSCG_TrimUpdate. */
uint8_t ccotrim; /*!< Trim fine value; Irrelevant if trimMode is kSCG_TrimUpdate. */
} sirc_trim_config_t;
/*!
* @brief SCG system OSC monitor mode.
*/
typedef enum _scg_sosc_monitor_mode
{
kSCG_SysOscMonitorDisable = 0U, /*!< Monitor disabled. */
kSCG_SysOscMonitorInt = SCG_SOSCCSR_SOSCCM_MASK, /*!< Interrupt when the SOSC error is detected. */
kSCG_SysOscMonitorReset =
SCG_SOSCCSR_SOSCCM_MASK | SCG_SOSCCSR_SOSCCMRE_MASK /*!< Reset when the SOSC error is detected. */
} scg_sosc_monitor_mode_t;
/*!
* @brief firc trim source.
*/
typedef enum _clke_16k
{
kCLKE_16K_SYSTEM = VBAT_FROCLKE_CLKE(1U), /*!< To VSYS domain. */
kCLKE_16K_COREMAIN = VBAT_FROCLKE_CLKE(2U) /*!< To VDD_CORE domain. */
} clke_16k_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/**
* @brief Enable the clock for specific IP.
* @param clk : Clock to be enabled.
* @return Nothing
*/
static inline void CLOCK_EnableClock(clock_ip_name_t clk)
{
uint32_t reg_offset = CLK_GATE_REG_OFFSET(clk);
uint32_t bit_shift = CLK_GATE_BIT_SHIFT(clk);
volatile uint32_t *pClkCtrl = (volatile uint32_t *)((uint32_t)(&(MRCC0->MRCC_GLB_CC0_SET)) + reg_offset);
if (clk == kCLOCK_GateNotAvail)
{
return;
}
/* Unlock clock configuration */
SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK;
if (reg_offset == REG_PWM0SUBCTL)
{
SYSCON->PWM0SUBCTL |= (1UL << bit_shift);
MRCC0->MRCC_GLB_CC0_SET = MRCC_MRCC_GLB_CC0_FLEXPWM0_MASK;
}
else if (reg_offset == REG_PWM1SUBCTL)
{
SYSCON->PWM1SUBCTL |= (1UL << bit_shift);
MRCC0->MRCC_GLB_CC0_SET = MRCC_MRCC_GLB_CC0_FLEXPWM1_MASK;
}
else
{
*pClkCtrl = (1UL << bit_shift);
}
/* Freeze clock configuration */
SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK;
}
/**
* @brief Disable the clock for specific IP.
* @param clk : Clock to be Disabled.
* @return Nothing
*/
static inline void CLOCK_DisableClock(clock_ip_name_t clk)
{
uint32_t reg_offset = CLK_GATE_REG_OFFSET(clk);
uint32_t bit_shift = CLK_GATE_BIT_SHIFT(clk);
volatile uint32_t *pClkCtrl = (volatile uint32_t *)((uint32_t)(&(MRCC0->MRCC_GLB_CC0_CLR)) + reg_offset);
if (clk == kCLOCK_GateNotAvail)
{
return;
}
/* Unlock clock configuration */
SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK;
if (reg_offset == REG_PWM0SUBCTL)
{
SYSCON->PWM0SUBCTL &= ~(1UL << bit_shift);
if (0U == (SYSCON->PWM0SUBCTL & 0xFU))
{
MRCC0->MRCC_GLB_CC0_CLR = MRCC_MRCC_GLB_CC0_FLEXPWM0_MASK;
}
}
else if (reg_offset == REG_PWM1SUBCTL)
{
SYSCON->PWM1SUBCTL &= ~(1UL << bit_shift);
if (0U == (SYSCON->PWM1SUBCTL & 0xFU))
{
MRCC0->MRCC_GLB_CC0_CLR = MRCC_MRCC_GLB_CC0_FLEXPWM1_MASK;
}
}
else
{
*pClkCtrl = (1UL << bit_shift);
}
/* Freeze clock configuration */
SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK;
}
/**
* @brief Configure the clock selection muxes.
* @param connection : Clock to be configured.
* @return Nothing
*/
void CLOCK_AttachClk(clock_attach_id_t connection);
/**
* @brief Get the actual clock attach id.
* This fuction uses the offset in input attach id, then it reads the actual source value in
* the register and combine the offset to obtain an actual attach id.
* @param connection : Clock attach id to get.
* @return Clock source value.
*/
clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t connection);
/**
* @brief Set the clock select value.
* This fuction set the peripheral clock select value.
* @param sel_name : Clock select.
* @param value : value to be set.
*/
void CLOCK_SetClockSelect(clock_select_name_t sel_name, uint32_t value);
/**
* @brief Get the clock select value.
* This fuction get the peripheral clock select value.
* @param sel_name : Clock select.
* @return Clock source value.
*/
uint32_t CLOCK_GetClockSelect(clock_select_name_t sel_name);
/**
* @brief Setup peripheral clock dividers.
* @param div_name : Clock divider name
* @param value : Value to be divided
* @return Nothing
*/
void CLOCK_SetClockDiv(clock_div_name_t div_name, uint32_t value);
/**
* @brief Get peripheral clock dividers.
* @param div_name : Clock divider name
* @return peripheral clock dividers
*/
uint32_t CLOCK_GetClockDiv(clock_div_name_t div_name);
/**
* @brief Halt peripheral clock dividers.
* @param div_name : Clock divider name
* @return Nothing
*/
void CLOCK_HaltClockDiv(clock_div_name_t div_name);
/**
* @brief Initialize the FROHF to given frequency (48,64,96,192).
* This function turns on FIRC and select the given frequency as the source of fro_hf
* @param iFreq : Desired frequency.
* @return returns success or fail status.
*/
status_t CLOCK_SetupFROHFClocking(uint32_t iFreq);
/**
* @brief Initialize the FRO12M.
* This function turns on FRO12M.
* @return returns success or fail status.
*/
status_t CLOCK_SetupFRO12MClocking(void);
/**
* @brief Initialize the FRO16K.
* This function turns on FRO16K.
* @param clk_16k_enable_mask: 0-3
* 0b00: disable both clk_16k0 and clk_16k1
* 0b01: only enable clk_16k0
* 0b10: only enable clk_16k1
* 0b11: enable both clk_16k0 and clk_16k1
* @return returns success or fail status.
*/
status_t CLOCK_SetupFRO16KClocking(uint8_t clk_16k_enable_mask);
/**
* @brief Initialize the external osc clock to given frequency.
* @param iFreq : Desired frequency (must be equal to exact rate in Hz)
* @return returns success or fail status.
*/
status_t CLOCK_SetupExtClocking(uint32_t iFreq);
/**
* @brief Initialize the external reference clock to given frequency.
* @param iFreq : Desired frequency (must be equal to exact rate in Hz)
* @return returns success or fail status.
*/
status_t CLOCK_SetupExtRefClocking(uint32_t iFreq);
/*! @brief Return Frequency of selected clock
* @return Frequency of selected clock
*/
uint32_t CLOCK_GetFreq(clock_name_t clockName);
/*! @brief Return Frequency of core
* @return Frequency of the core
*/
uint32_t CLOCK_GetCoreSysClkFreq(void);
/*! @brief Return Frequency of I3C FCLK
* @return Frequency of I3C FCLK.
*/
uint32_t CLOCK_GetI3CFClkFreq(void);
/*! @brief Return Frequency of CTimer functional Clock
* @return Frequency of CTimer functional Clock
*/
uint32_t CLOCK_GetCTimerClkFreq(uint32_t id);
/*! @brief Return Frequency of LPI2C0 functional Clock
* @return Frequency of LPI2C0 functional Clock
*/
uint32_t CLOCK_GetLpi2cClkFreq(uint32_t id);
/*! @brief Return Frequency of LPSPI functional Clock
* @return Frequency of LPSPI functional Clock
*/
uint32_t CLOCK_GetLpspiClkFreq(uint32_t id);
/*! @brief Return Frequency of LPUART functional Clock
* @return Frequency of LPUART functional Clock
*/
uint32_t CLOCK_GetLpuartClkFreq(uint32_t id);
/*! @brief Return Frequency of LPTMR functional Clock
* @return Frequency of LPTMR functional Clock
*/
uint32_t CLOCK_GetLptmrClkFreq(void);
/*! @brief Return Frequency of OSTIMER
* @return Frequency of OSTIMER Clock
*/
uint32_t CLOCK_GetOstimerClkFreq(void);
/*! @brief Return Frequency of Adc Clock
* @return Frequency of Adc.
*/
uint32_t CLOCK_GetAdcClkFreq(uint32_t id);
/*! @brief Return Frequency of Dac Clock
* @return Frequency of Dac.
*/
uint32_t CLOCK_GetDacClkFreq(void);
/*! @brief Return Frequency of CMP Function Clock
* @return Frequency of CMP Function.
*/
uint32_t CLOCK_GetCmpFClkFreq(uint32_t id);
/*! @brief Return Frequency of CMP Round Robin Clock
* @return Frequency of CMP Round Robin.
*/
uint32_t CLOCK_GetCmpRRClkFreq(uint32_t id);
/*! @brief Return Frequency of Trace Clock
* @return Frequency of Trace.
*/
uint32_t CLOCK_GetTraceClkFreq(void);
/*! @brief Return Frequency of CLKOUT Clock
* @return Frequency of CLKOUT.
*/
uint32_t CLOCK_GetClkoutClkFreq(void);
/*! @brief Return Frequency of Systick Clock
* @return Frequency of Systick.
*/
uint32_t CLOCK_GetSystickClkFreq(void);
/*! brief Return Frequency of Systick Clock
* return Frequency of Systick.
*/
uint32_t CLOCK_GetWwdtClkFreq(void);
/*! @brief Return Frequency of FLEXIO FCLK
* @return Frequency of FLEXIO FCLK.
*/
uint32_t CLOCK_GetFlexioClkFreq(void);
/*! @brief Return Frequency of FlexCAN FCLK
* @return Frequency of FlexCAN FCLK.
*/
uint32_t CLOCK_GetFlexcanClkFreq(void);
/**
* @brief Setup FROHF trim.
* @param config : FROHF trim value
* @return returns success or fail status.
*/
status_t CLOCK_FROHFTrimConfig(firc_trim_config_t config);
/**
* @brief Setup FRO 12M trim.
* @param config : FRO 12M trim value
* @return returns success or fail status.
*/
status_t CLOCK_FRO12MTrimConfig(sirc_trim_config_t config);
/*!
* @brief Sets the system OSC monitor mode.
*
* This function sets the system OSC monitor mode. The mode can be disabled,
* it can generate an interrupt when the error is disabled, or reset when the error is detected.
*
* @param mode Monitor mode to set.
*/
void CLOCK_SetSysOscMonitorMode(scg_sosc_monitor_mode_t mode);
/*! brief Enable USB FS clock.
* Enable USB Full Speed clock.
*/
bool CLOCK_EnableUsbfsClock(void);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @} */
#endif /* _FSL_CLOCK_H_ */

View File

@ -0,0 +1,310 @@
/*
* Copyright 2022-2024 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_cmc.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.mcx_cmc"
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t g_savedPrimask;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief Sets clock mode.
*
* This function configs the amount of clock gating when the core asserts
* Sleeping due to WFI, WFE or SLEEPONEXIT.
*
* param base CMC peripheral base address.
* param mode System clock mode.
*/
void CMC_SetClockMode(CMC_Type *base, cmc_clock_mode_t mode)
{
uint32_t reg;
reg = base->CKCTRL;
reg &= ~CMC_CKCTRL_CKMODE_MASK;
reg |= CMC_CKCTRL_CKMODE((mode));
base->CKCTRL = reg;
}
/*!
* brief Configures all power mode protection settings.
*
* This function configures the power mode protection settings for
* supported power modes. This should be done before setting the lowPower mode
* for each power doamin.
*
* The allowed lowpower modes are passed as bit map. For example, to allow
* Sleep and DeepSleep, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowSleepMode|kCMC_AllowDeepSleepMode).
* To allow all low power modes, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowAllLowPowerModes).
*
* param base CMC peripheral base address.
* param allowedModes Bitmaps of the allowed power modes.
*/
void CMC_SetPowerModeProtection(CMC_Type *base, uint32_t allowedModes)
{
uint32_t reg;
reg = base->PMPROT;
reg &= ~0xFUL;
reg |= allowedModes;
base->PMPROT = reg;
}
/*!
* brief Configure reset pin.
*
* This function configures reset pin. When enabled, the low power filter is enabled in both
* Active and Low power modes, the reset filter is only enabled in Active mode. When both filers
* are enabled, they operate in series.
*
* param base CMC peripheral base address.
* param config Pointer to the reset pin config structure.
*/
void CMC_ConfigResetPin(CMC_Type *base, const cmc_reset_pin_config_t *config)
{
assert(config != NULL);
uint32_t reg = base->RPC;
if (config->lowpowerFilterEnable)
{
reg |= CMC_RPC_LPFEN_MASK;
}
else
{
reg &= ~CMC_RPC_LPFEN_MASK;
}
if (config->resetFilterEnable)
{
reg |= (CMC_RPC_FILTEN_MASK | CMC_RPC_FILTCFG(config->resetFilterWidth));
}
else
{
reg &= ~(CMC_RPC_FILTEN_MASK | CMC_RPC_FILTCFG_MASK);
}
base->RPC = reg;
}
#if (defined(FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG) && FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG)
/*!
* brief Power off the selected system SRAM always.
*
* This function powers off the selected system SRAM always. The SRAM arrays should
* not be accessed while they are shut down. SRAM array contents are not retained
* if they are powered off.
*
* param base CMC peripheral base address.
* param mask Bitmap of the SRAM arrays to be powered off all modes.
*/
void CMC_PowerOffSRAMAllMode(CMC_Type *base, uint32_t mask)
{
uint32_t reg = base->SRAMDIS[0];
uint32_t maskToSet = mask & ((uint32_t)kCMC_AllSramArrays);
reg &= ~((uint32_t)kCMC_AllSramArrays);
reg |= CMC_SRAMDIS_DIS(maskToSet);
base->SRAMDIS[0] = reg;
}
/*!
* brief Power off the selected system SRAm during low power mode only.
*
* This function powers off the selected system SRAM only during low power mode.
* SRAM array contents are not retained if they are power off.
*
* param base CMC peripheral base address.
* param mask Bitmap of the SRAM arrays to be power off during low power mode only.
*/
void CMC_PowerOffSRAMLowPowerOnly(CMC_Type *base, uint32_t mask)
{
uint32_t reg = base->SRAMRET[0];
uint32_t maskToSet = mask & ((uint32_t)kCMC_AllSramArrays);
reg &= ~((uint32_t)kCMC_AllSramArrays);
reg |= CMC_SRAMRET_RET(maskToSet);
base->SRAMRET[0] = reg;
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG */
#if (defined(FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE) && FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE)
/*!
* brief Configs the low power mode of the on-chip flash memory.
*
* This function configs the low power mode of the on-chip flash memory.
*
* param base CMC peripheral base address.
* param doze true: Flash is disabled while core is sleeping
* false: No effect.
* param disable true: Flash memory is placed in low power state.
* false: No effect.
*/
void CMC_ConfigFlashMode(CMC_Type *base, bool doze, bool disable)
{
uint32_t reg = 0UL;
reg |= (disable ? CMC_FLASHCR_FLASHDIS(1U) : CMC_FLASHCR_FLASHDIS(0U)) |
(doze ? CMC_FLASHCR_FLASHDOZE(1U) : CMC_FLASHCR_FLASHDOZE(0U));
base->FLASHCR = reg;
}
#else
/*!
* brief Configs the low power mode of the on-chip flash memory.
*
* This function config the low power mode of the on-chip flash memory.
*
* param base CMC peripheral base address.
* param wake
* true - Flash will exit low power state during the flash memory accesses.
* false - No effect.
* param doze
* true - Flash is disabled while core is sleeping
* false - No effect.
* param disable
* true - Flash memory is placed in low power state.
* false - No effect.
*/
void CMC_ConfigFlashMode(CMC_Type *base, bool wake, bool doze, bool disable)
{
uint32_t reg = 0UL;
reg |= (disable ? CMC_FLASHCR_FLASHDIS(1U) : CMC_FLASHCR_FLASHDIS(0U)) |
(doze ? CMC_FLASHCR_FLASHDOZE(1U) : CMC_FLASHCR_FLASHDOZE(0U)) |
(wake ? CMC_FLASHCR_FLASHWAKE(1U) : CMC_FLASHCR_FLASHWAKE(0U));
base->FLASHCR = reg;
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE */
/*!
* brief Prepares to enter stop modes.
*
* This function should be called before entering low power modes.
*
*/
void CMC_PreEnterLowPowerMode(void)
{
g_savedPrimask = DisableGlobalIRQ();
__ISB();
}
/*!
* brief Recovers after wake up from stop modes.
*
* This function should be called after waking up from low power modes.
* This function should be used with CMC_PreEnterLowPowerMode()
*
*/
void CMC_PostExitLowPowerMode(void)
{
EnableGlobalIRQ(g_savedPrimask);
__ISB();
}
/*!
* brief Configs the entry into the same low power mode for each power domains.
*
* This function provides the feature to entry into the same low power mode for each power
* domains. Before invoking this function, please ensure the selected power mode have been allowed.
*
* param base CMC peripheral base address.
* param lowPowerMode The low power mode to be entered. See @ref cmc_low_power_mode_t for the details.
*
*/
void CMC_GlobalEnterLowPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode)
{
/* Note: unlock the CKCTRL register if this API will be reinvoked later. */
CMC_SetClockMode(base, kCMC_GateAllSystemClocksEnterLowPowerMode);
CMC_SetGlobalPowerMode(base, lowPowerMode);
/* Before executing WFI instruction read back the last register to
* ensure all registers writes have completed. */
(void)base->GPMCTRL;
/* Set the core into DeepSleep mode. */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
}
/*!
* brief Configs the entry into different low power modes for each of the power domains.
*
* This function provides the feature to entry into different low power modes for
* each power domains. Before invoking this function please ensure the selected
* modes are allowed.
*
* param base CMC peripheral base address.
* param base config Pointer to the cmc_power_domain_config_t structure.
*/
void CMC_EnterLowPowerMode(CMC_Type *base, const cmc_power_domain_config_t *config)
{
assert(config != NULL);
#if (CMC_PMCTRL_COUNT > 1U)
/* The WAKE domain must never be configured to a lower power mode compared with main power mode. */
assert(config->wake_domain <= config->main_domain);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
if (config->clock_mode < kCMC_GateAllSystemClocksEnterLowPowerMode)
{
/* In This case the power domain doesn't need to be placed in low power state. */
/* Note: unlock the register if this API will be reinvoked later. */
CMC_SetClockMode(base, config->clock_mode);
CMC_SetMAINPowerMode(base, kCMC_ActiveOrSleepMode);
#if (CMC_PMCTRL_COUNT > 1U)
CMC_SetWAKEPowerMode(base, kCMC_ActiveOrSleepMode);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
/* Before executing WFI instruction read back the last register to
* ensure all registers writes have completed. */
(void)base->CKCTRL;
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
}
else
{
/* Note: unlock the register if this API will be reinvoked later. */
CMC_SetClockMode(base, kCMC_GateAllSystemClocksEnterLowPowerMode);
CMC_SetMAINPowerMode(base, config->main_domain);
#if (CMC_PMCTRL_COUNT > 1U)
CMC_SetWAKEPowerMode(base, config->wake_domain);
#endif /* (CMC_PMCTRL_COUNT > 1U) */
/* Before execute WFI instruction read back the last register to
* ensure all registers writes have completed. */
#if (CMC_PMCTRL_COUNT > 1U)
if ((CMC_GetWAKEPowerMode(base) == config->wake_domain) && (CMC_GetMAINPowerMode(base) == config->main_domain))
{
#endif /* (CMC_PMCTRL_COUNT > 1U) */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
__ISB();
#if (CMC_PMCTRL_COUNT > 1U)
}
#endif /* (CMC_PMCTRL_COUNT > 1U) */
}
}

View File

@ -0,0 +1,929 @@
/*
* Copyright 2022-2024 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_CMC_H_
#define FSL_CMC_H_
#include "fsl_common.h"
/*!
* @addtogroup mcx_cmc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief CMC driver version 2.2.2. */
#define FSL_CMC_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
/* @} */
/*!
* @brief CMC power mode Protection enumeration.
*/
enum _cmc_power_mode_protection
{
kCMC_AllowDeepSleepMode = 0x1UL, /*!< Allow Deep Sleep mode. */
kCMC_AllowPowerDownMode = 0x2UL, /*!< Allow Power Down mode. */
kCMC_AllowDeepPowerDownMode = 0x8UL, /*!< Allow Deep Power Down mode. */
kCMC_AllowAllLowPowerModes = 0xFUL, /*!< Allow Deep Sleep, Power Down, Deep Power Down modes. */
};
/*!
* @brief Wake up sources from the previous low power mode entry.
*
* @note #kCMC_WakeupFromUsbFs, #kCMC_WakeupFromITRC, #kCMC_WakeupFromCpu1 are not supported in MCXA family.
*/
enum _cmc_wakeup_sources
{
kCMC_WakeupFromResetInterruptOrPowerDown =
CMC_CKSTAT_WAKEUP(1U << 0U), /*!< Wakeup source is reset interrupt, or wake up from Deep Power Down. */
kCMC_WakeupFromDebugReuqest = CMC_CKSTAT_WAKEUP(1U << 1U), /*!< Wakeup source is debug request. */
kCMC_WakeupFromInterrupt = CMC_CKSTAT_WAKEUP(1U << 2U), /*!< Wakeup source is interrupt. */
kCMC_WakeupFromDMAWakeup = CMC_CKSTAT_WAKEUP(1U << 3U), /*!< Wakeup source is DMA Wakeup. */
kCMC_WakeupFromWUURequest = CMC_CKSTAT_WAKEUP(1U << 4U), /*!< Wakeup source is WUU request. */
kCMC_WakeupFromUsbFs = CMC_CKSTAT_WAKEUP(1U << 5U), /*!< Wakeup source is USBFS(USB0). */
kCMC_WakeupFromITRC = CMC_CKSTAT_WAKEUP(1U << 6U), /*!< Wakeup source is ITRC. */
kCMC_WakeupFromCpu1 = CMC_CKSTAT_WAKEUP(1U << 7U), /*!< Wakeup source is CPU1. */
};
/*!
* @brief System Reset Interrupt enable enumeration.
*/
enum _cmc_system_reset_interrupt_enable
{
kCMC_PinResetInterruptEnable = CMC_SRIE_PIN_MASK, /*!< Pin Reset interrupt enable. */
kCMC_DAPResetInterruptEnable = CMC_SRIE_DAP_MASK, /*!< DAP Reset interrupt enable. */
kCMC_LowPowerAcknowledgeTimeoutResetInterruptEnable = CMC_SRIE_LPACK_MASK, /*!< Low Power Acknowledge Timeout
Reset interrupt enable. */
kCMC_WindowedWatchdog0ResetInterruptEnable = CMC_SRIE_WWDT0_MASK, /*!< Windowed Watchdog 0 reset
interrupt enable. */
kCMC_SoftwareResetInterruptEnable = CMC_SRIE_SW_MASK, /*!< Software Reset interrupt enable. */
kCMC_LockupResetInterruptEnable = CMC_SRIE_LOCKUP_MASK, /*!< Lockup Reset interrupt enable. */
#if defined(CMC_SRIE_CPU1_MASK)
kCMC_Cpu1ResetInterruptEnable = CMC_SRIE_CPU1_MASK, /*!< CPU1 Reset interrupt enable. */
#endif /* CMC_SRIE_CPU1_MASK */
#if defined(CMC_SRIE_ADVC_MASK)
kCMC_AdvcResetInterruptEnable = CMC_SRIE_ADVC_MASK, /*!< ADVC Reset interrupt enable. */
#endif /* CMC_SRIE_ADVC_MASK */
#if defined(CMC_SRIE_VBAT_MASK)
kCMC_VBATResetInterruptEnable = CMC_SRIE_VBAT_MASK, /*!< VBAT reset interrupt enable. */
#endif /* CMC_SRIE_VBAT_MASK */
#if defined(CMC_SRIE_WWDT1_MASK)
kCMC_WindowedWatchdog1ResetInterruptEnable = CMC_SRIE_WWDT1_MASK, /*!< Windowed Watchdog 1 reset
interrupt enable. */
#endif /* CMC_SRIE_WWDT1_MASK */
kCMC_CodeWatchDog0ResetInterruptEnable = CMC_SRIE_CDOG0_MASK, /*!< Code watchdog 0 reset interrupt enable. */
#if defined(CMC_SRIE_CDOG1_MASK)
kCMC_CodeWatchDog1ResetInterruptEnable = CMC_SRIE_CDOG1_MASK, /*!< Code watchdog 1 reset interrupt enable. */
#endif /* CMC_SRIE_CDOG1_MASK */
};
/*!
* @brief CMC System Reset Interrupt Status flag.
*/
enum _cmc_system_reset_interrupt_flag
{
kCMC_PinResetInterruptFlag = CMC_SRIF_PIN_MASK, /*!< Pin Reset interrupt flag. */
kCMC_DAPResetInterruptFlag = CMC_SRIF_DAP_MASK, /*!< DAP Reset interrupt flag. */
kCMC_LowPowerAcknowledgeTimeoutResetFlag = CMC_SRIF_LPACK_MASK, /*!< Low Power Acknowledge
Timeout Reset interrupt flag. */
kCMC_WindowedWatchdog0ResetInterruptFlag = CMC_SRIF_WWDT0_MASK, /*!< Windowned Watchdog 0 Reset interrupt flag. */
kCMC_SoftwareResetInterruptFlag = CMC_SRIF_SW_MASK, /*!< Software Reset interrupt flag. */
kCMC_LockupResetInterruptFlag = CMC_SRIF_LOCKUP_MASK, /*!< Lock up Reset interrupt flag. */
#if defined(CMC_SRIF_CPU1_MASK)
kCMC_Cpu1ResetInterruptFlag = CMC_SRIF_CPU1_MASK, /*!< CPU1 Reset interrupt flag. */
#endif /* CMC_SRIF_CPU1_MASK */
#if defined(CMC_SRIF_ADVC_MASK)
kCMC_AdvcResetInterruptFlag = CMC_SRIF_ADVC_MASK, /*!< ADVC Reset interrupt flag. */
#endif /* CMC_SRIF_ADVC_MASK */
#if defined(CMC_SRIF_VBAT_MASK)
kCMC_VbatResetInterruptFlag = CMC_SRIF_VBAT_MASK, /*!< VBAT system reset interrupt flag. */
#endif /* CMC_SRIF_VBAT_MASK */
#if defined(CMC_SRIF_WWDT1_MASK)
kCMC_WindowedWatchdog1ResetInterruptFlag = CMC_SRIF_WWDT1_MASK, /*!< Windowned Watchdog 1 Reset interrupt flag. */
#endif /* CMC_SRIF_WWDT1_MASK */
kCMC_CodeWatchdog0ResetInterruptFlag = CMC_SRIF_CDOG0_MASK, /*!< Code watchdog0 reset interrupt flag. */
#if defined(CMC_SRIF_CDOG1_MASK)
kCMC_CodeWatchdog1ResetInterruptFlag = CMC_SRIF_CDOG1_MASK, /*!< Code watchdog1 reset interrupt flag. */
#endif /* CMC_SRIF_CDOG1_MASK */
};
#if (defined(FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG) && FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG)
/*!
* @brief CMC System SRAM arrays low power mode enable enumeration.
*/
enum _cmc_system_sram_arrays
{
kCMC_RAMX0 = 1UL << 0UL, /*!< Used to control RAMX0. */
kCMC_RAMX1 = 1UL << 1UL, /*!< Used to control RAMX1. */
kCMC_RAMX2 = 1UL << 2UL, /*!< Used to control RAMX2. */
kCMC_RAMB = 1UL << 3UL, /*!< Used to control RAMB. */
kCMC_RAMC0 = 1UL << 4UL, /*!< Used to control RAMC0. */
kCMC_RAMC1 = 1UL << 5UL, /*!< Used to control RAMC1. */
kCMC_RAMD0 = 1UL << 6UL, /*!< Used to control RAMD0. */
kCMC_RAMD1 = 1UL << 7UL, /*!< Used to control RAMD1. */
kCMC_RAME0 = 1UL << 8UL, /*!< Used to control RAME0. */
kCMC_RAME1 = 1UL << 9UL, /*!< Used to control RAME1. */
kCMC_RAMF0 = 1UL << 10UL, /*!< Used to control RAMF0. */
kCMC_RAMF1 = 1UL << 11UL, /*!< Used to control RAMF1. */
kCMC_RAMG0_RAMG1 = 1UL << 12UL, /*!< Used to control RAMG0 and RAMG1. */
kCMC_RAMG2_RAMG3 = 1UL << 13UL, /*!< Used to control RAMG2 and RAMG3. */
kCMC_RAMH0_RAMH1 = 1UL << 14UL, /*!< Used to control RAMH0 and RAMH1. */
kCMC_LPCAC = 1UL << 24UL, /*!< Used to control LPCAC. */
kCMC_DMA0_DMA1_PKC = 1UL << 25UL, /*!< Used to control DMA0, DMA1 and PKC. */
kCMC_USB0 = 1UL << 26UL, /*!< Used to control USB0. */
kCMC_PQ = 1UL << 27UL, /*!< Used to control PQ. */
kCMC_CAN0_CAN1_ENET_USB1 = 1UL << 28UL, /*!< Used to control CAN0, CAN1, ENET, USB1. */
kCMC_FlexSPI = 1UL << 29UL, /*!< Used to control FlexSPI. */
kCMC_AllSramArrays = (kCMC_RAMX0 | kCMC_RAMX1 | kCMC_RAMX2 | kCMC_RAMB | kCMC_RAMC0 | kCMC_RAMC1 | kCMC_RAMD0 |
kCMC_RAMD1 | kCMC_RAME0 | kCMC_RAME1 | kCMC_RAMF0 | kCMC_RAMF1 | kCMC_RAMG0_RAMG1 |
kCMC_RAMG2_RAMG3 | kCMC_RAMH0_RAMH1 | kCMC_LPCAC | kCMC_DMA0_DMA1_PKC | kCMC_USB0 | kCMC_PQ |
kCMC_CAN0_CAN1_ENET_USB1 | kCMC_FlexSPI), /*!< Mask of all System SRAM arrays. */
};
#endif /* FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG */
/*!
* @brief System reset sources enumeration.
*/
enum _cmc_system_reset_sources
{
kCMC_WakeUpReset = CMC_SRS_WAKEUP_MASK, /*!< The reset caused by a wakeup from Power Down or
Deep Power Down mode. */
kCMC_PORReset = CMC_SRS_POR_MASK, /*!< The reset caused by power on reset detection logic. */
kCMC_VDReset = CMC_SRS_VD_MASK, /*!< The reset caused by an LVD or HVD. */
kCMC_WarmReset = CMC_SRS_WARM_MASK, /*!< The last reset source is a warm reset source. */
kCMC_FatalReset = CMC_SRS_FATAL_MASK, /*!< The last reset source is a fatal reset source. */
kCMC_PinReset = CMC_SRS_PIN_MASK, /*!< The reset caused by the RESET_b pin. */
kCMC_DAPReset = CMC_SRS_DAP_MASK, /*!< The reset caused by a reset request from the Debug Access port. */
kCMC_ResetTimeout = CMC_SRS_RSTACK_MASK, /*!< The reset caused by a timeout or other error condition in the system
reset generation. */
kCMC_LowPowerAcknowledgeTimeoutReset = CMC_SRS_LPACK_MASK, /*!< The reset caused by a timeout in
low power mode entry logic. */
kCMC_SCGReset = CMC_SRS_SCG_MASK, /*!< The reset caused by a loss of clock or loss of lock event in the SCG. */
kCMC_WindowedWatchdog0Reset = CMC_SRS_WWDT0_MASK, /*!< The reset caused by the Windowed WatchDog 0 timeout. */
kCMC_SoftwareReset = CMC_SRS_SW_MASK, /*!< The reset caused by a software reset request. */
kCMC_LockUoReset = CMC_SRS_LOCKUP_MASK, /*!< The reset caused by the ARM core indication of a LOCKUP event. */
#if defined(CMC_SRS_CPU1_MASK)
kCMC_Cpu1Reset = CMC_SRS_CPU1_MASK, /*!< The reset caused by a CPU1 system reset. */
#endif /* CMC_SRS_CPU1_MASK */
#if defined(CMC_SRS_ADVC_MASK)
kCMC_AdvcReset = CMC_SRS_ADVC_MASK, /*!< The reset caused by ADVC critical reset. */
#endif /* CMC_SRS_ADVC_MASK */
#if defined(CMC_SRS_VBAT_MASK)
kCMC_VbatReset = CMC_SRS_VBAT_MASK, /*!< The reset caused by a VBAT POR. */
#endif /* CMC_SRS_VBAT_MASK */
#if defined(CMC_SRS_WWDT1_MASK)
kCMC_WindowedWatchdog1Reset = CMC_SRS_WWDT1_MASK, /*!< The reset caused by the Windowed WatchDog 1 timeout. */
#endif /* CMC_SRS_WWDT1_MASK */
kCMC_CodeWatchDog0Reset = CMC_SRS_CDOG0_MASK, /*!< The reset caused by the code watchdog0 fault. */
#if defined(CMC_SRS_CDOG1_MASK)
kCMC_CodeWatchDog1Reset = CMC_SRS_CDOG1_MASK, /*!< The reset caused by the code watchdog1 fault. */
#endif /* CMC_SRS_CDOG1_MASK */
kCMC_JTAGSystemReset = CMC_SRS_JTAG_MASK, /*!< The reset caused by a JTAG system reset request. */
#if defined(CMC_SRS_SECVIO_MASK)
kCMC_SecurityViolationReset = CMC_SRS_SECVIO_MASK, /*!< The reset caused by a Security Violation logic. */
#endif /* CMC_SRS_SECVIO_MASK */
#if defined(CMC_SRS_TAMPER_MASK)
kCMC_TapmerReset = CMC_SRS_TAMPER_MASK, /*!< The reset caused by the tamper detection logic. */
#endif /* CMC_SRS_TAMPER_MASK */
};
/*!
* @brief Indicate the core clock was gated.
*/
typedef enum _cmc_core_clock_gate_status
{
kCMC_CoreClockNotGated = 0U, /*!< Core clock not gated. */
kCMC_CoreClockGated = 1U /*!< Core clock was gated due to low power mode entry. */
} cmc_core_clock_gate_status_t;
/*!
* @brief CMC clock mode enumeration.
*/
typedef enum _cmc_clock_mode
{
kCMC_GateNoneClock = 0x00U, /*!< No clock gating. */
kCMC_GateCoreClock = 0x01U, /*!< Gate Core clock. */
kCMC_GateCorePlatformClock = 0x03U, /*!< Gate Core clock and platform clock. */
kCMC_GateAllSystemClocks = 0x07U, /*!< Gate all System clocks, without getting core entering into low power mode. */
kCMC_GateAllSystemClocksEnterLowPowerMode = 0x0FU /*!< Gate all System clocks, with core
entering into low power mode. */
} cmc_clock_mode_t;
/*!
* @brief CMC power mode enumeration.
*/
typedef enum _cmc_low_power_mode
{
kCMC_ActiveOrSleepMode = 0x0U, /*!< Select Active/Sleep mode. */
kCMC_DeepSleepMode = 0x1U, /*!< Select Deep Sleep mode when a core executes WFI or WFE instruction. */
kCMC_PowerDownMode = 0x3U, /*!< Select Power Down mode when a core executes WFI or WFE instruction. */
kCMC_DeepPowerDown = 0xFU, /*!< Select Deep Power Down mode when a core executes WFI or WFE instruction. */
} cmc_low_power_mode_t;
/*!
* @brief CMC reset pin configuration.
*/
typedef struct _cmc_reset_pin_config
{
bool lowpowerFilterEnable; /*!< Low Power Filter enable. */
bool resetFilterEnable; /*!< Reset Filter enable. */
uint8_t resetFilterWidth; /*!< Width of the Reset Filter. */
} cmc_reset_pin_config_t;
/*!
* @brief power mode configuration for each power domain.
*/
typedef struct _cmc_power_domain_config
{
cmc_clock_mode_t clock_mode; /*!< Clock mode for each power domain. */
cmc_low_power_mode_t main_domain; /*!< The low power mode of the MAIN power domain. */
#if (CMC_PMCTRL_COUNT > 1U)
cmc_low_power_mode_t wake_domain; /*!< The low power mode of the WAKE power domain. */
#endif /* (CMC_PMCTRL_COUNT > 1U) */
} cmc_power_domain_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name CLOCK mode configuration.
* @{
*/
/*!
* @brief Sets clock mode.
*
* This function configs the amount of clock gating when the core asserts
* Sleeping due to WFI, WFE or SLEEPONEXIT.
*
* @param base CMC peripheral base address.
* @param mode System clock mode.
*/
void CMC_SetClockMode(CMC_Type *base, cmc_clock_mode_t mode);
/*!
* @brief Locks the clock mode setting.
*
* After invoking this function, any clock mode setting will be blocked.
*
* @param base CMC peripheral base address.
*/
static inline void CMC_LockClockModeSetting(CMC_Type *base)
{
base->CKCTRL |= CMC_CKCTRL_LOCK_MASK;
}
/* @} */
/*!
* @name Gets/Clears the Clock Mode, the wake up source, the Reset source.
* @{
*/
/*!
* @brief Gets the core clock gated status.
*
* This function get the status to indicate whether the core clock is gated.
* The core clock gated status can be cleared by software.
*
* @param base CMC peripheral base address.
* @return The status to indicate whether the core clock is gated.
*/
static inline cmc_core_clock_gate_status_t CMC_GetCoreClockGatedStatus(CMC_Type *base)
{
return (cmc_core_clock_gate_status_t)(uint32_t)((base->CKSTAT & CMC_CKSTAT_VALID_MASK) >> CMC_CKSTAT_VALID_SHIFT);
}
/*!
* @brief Clears the core clock gated status.
*
* This function clear clock status flag by software.
*
* @param base CMC peripheral base address.
*/
static inline void CMC_ClearCoreClockGatedStatus(CMC_Type *base)
{
base->CKSTAT |= CMC_CKSTAT_VALID_MASK;
}
/*!
* @brief Gets the Wakeup Source.
*
* This function gets the Wakeup sources from the previous low power mode entry.
*
* @param base CMC peripheral base address.
* @return The Wakeup sources from the previous low power mode entry. See @ref _cmc_wakeup_sources for details.
*/
static inline uint8_t CMC_GetWakeupSource(CMC_Type *base)
{
return ((uint8_t)((base->CKSTAT & CMC_CKSTAT_WAKEUP_MASK) >> CMC_CKSTAT_WAKEUP_SHIFT));
}
/*!
* @brief Gets the Clock mode.
*
* This function gets the clock mode of the previous low power mode entry.
*
* @param base CMC peripheral base address.
* @return The Low Power status.
*/
static inline cmc_clock_mode_t CMC_GetClockMode(CMC_Type *base)
{
return (cmc_clock_mode_t)(uint32_t)((base->CKSTAT & CMC_CKSTAT_CKMODE_MASK) >> CMC_CKSTAT_CKMODE_SHIFT);
}
/*!
* @brief Gets the System reset status.
*
* This function returns the system reset status. Those status
* updates on every MAIN Warm Reset to indicate the type/source
* of the most recent reset.
*
* @param base CMC peripheral base address.
* @return The most recent system reset status. See @ref _cmc_system_reset_sources for details.
*/
static inline uint32_t CMC_GetSystemResetStatus(CMC_Type *base)
{
return base->SRS;
}
/*!
* @brief Gets the sticky system reset status since the last WAKE Cold Reset.
*
* This function gets all source of system reset that have generated a
* system reset since the last WAKE Cold Reset, and that have not been
* cleared by software.
*
* @param base CMC peripheral base address.
* @return System reset status that have not been cleared by software. See @ref _cmc_system_reset_sources for details.
*/
static inline uint32_t CMC_GetStickySystemResetStatus(CMC_Type *base)
{
return base->SSRS;
}
/*!
* @brief Clears the sticky system reset status flags.
*
* @param base CMC peripheral base address.
* @param mask Bitmap of the sticky system reset status to be cleared.
*/
static inline void CMC_ClearStickySystemResetStatus(CMC_Type *base, uint32_t mask)
{
base->SSRS = mask;
}
#if (defined(FSL_FEATURE_MCX_CMC_HAS_RSTCNT_REG) && FSL_FEATURE_MCX_CMC_HAS_RSTCNT_REG)
/*!
* @brief Gets the number of reset sequences completed since the last Cold Reset.
*
* @param base CMC peripheral base address.
* @return The number of reset sequences.
*/
static inline uint8_t CMC_GetResetCount(CMC_Type *base)
{
return (uint8_t)(base->RSTCNT & CMC_RSTCNT_COUNT_MASK);
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_RSTCNT_REG */
/* @} */
/*!
* @name Power mode configuration.
* @{
*/
/*!
* @brief Configures all power mode protection settings.
*
* This function configures the power mode protection settings for
* supported power modes. This should be done before set the lowPower mode
* for each power doamin.
*
* The allowed lowpower modes are passed as bit map. For example, to allow
* Sleep and DeepSleep, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowSleepMode|kCMC_AllowDeepSleepMode).
* To allow all low power modes, use CMC_SetPowerModeProtection(CMC_base, kCMC_AllowAllLowPowerModes).
*
* @param base CMC peripheral base address.
* @param allowedModes Bitmaps of the allowed power modes. See @ref _cmc_power_mode_protection for details.
*/
void CMC_SetPowerModeProtection(CMC_Type *base, uint32_t allowedModes);
/*!
* @brief Locks the power mode protection.
*
* This function locks the power mode protection. After invoking this function,
* any power mode protection setting will be ignored.
*
* @param base CMC peripheral base address.
*/
static inline void CMC_LockPowerModeProtectionSetting(CMC_Type *base)
{
base->PMPROT |= CMC_PMPROT_LOCK_MASK;
}
/*!
* @brief Config the same lowPower mode for all power domain.
*
* This function configures the same low power mode for MAIN power domian and WAKE power domain.
*
* @param base CMC peripheral base address.
* @param lowPowerMode The desired lowPower mode. See @ref cmc_low_power_mode_t for details.
*/
static inline void CMC_SetGlobalPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode)
{
base->GPMCTRL = CMC_GPMCTRL_LPMODE((uint8_t)lowPowerMode);
}
/*!
* @brief Configures entry into low power mode for the MAIN Power domain.
*
* This function configures the low power mode for the MAIN power domian,
* when the core executes WFI/WFE instruction. The available lowPower modes
* are defined in the @ref cmc_low_power_mode_t.
*
* @param base CMC peripheral base address.
* @param lowPowerMode The desired lowPower mode. See @ref cmc_low_power_mode_t for details.
*
*/
static inline void CMC_SetMAINPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode)
{
base->PMCTRL[0] = CMC_PMCTRL_LPMODE((uint8_t)lowPowerMode);
}
/*!
* @brief Gets the power mode of the MAIN Power domain.
*
* @param base CMC peripheral base address.
* @return The power mode of MAIN Power domain. See @ref cmc_low_power_mode_t for details.
*/
static inline cmc_low_power_mode_t CMC_GetMAINPowerMode(CMC_Type *base)
{
return (cmc_low_power_mode_t)(uint32_t)(base->PMCTRL[0] & CMC_PMCTRL_LPMODE_MASK);
}
#if (CMC_PMCTRL_COUNT > 1U)
/*!
* @brief Configure entry into low power mode for the WAKE Power domain.
*
* This function configures the low power mode for the WAKE power domian,
* when the core executes WFI/WFE instruction. The available lowPower mode
* are defined in the @ref cmc_low_power_mode_t.
*
* @note The lowPower Mode for the WAKE domain must not be configured to a
* lower power mode than any other power domain.
*
* @param base CMC peripheral base address.
* @param lowPowerMode The desired lowPower mode. See @ref cmc_low_power_mode_t for details.
*
*/
static inline void CMC_SetWAKEPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode)
{
base->PMCTRL[1] = CMC_PMCTRL_LPMODE((uint8_t)lowPowerMode);
}
/*!
* @brief Gets the power mode of the WAKE Power domain.
*
* @param base CMC peripheral base address.
* @return The power mode of WAKE Power domain. See @ref cmc_low_power_mode_t for details.
*/
static inline cmc_low_power_mode_t CMC_GetWAKEPowerMode(CMC_Type *base)
{
return (cmc_low_power_mode_t)(uint32_t)(base->PMCTRL[1] & CMC_PMCTRL_LPMODE_MASK);
}
#endif /* CMC_PMCTRL_COUNT > 1U */
/* @} */
/*!
* @name Reset Pin configuration.
* @{
*/
/*!
* @brief Configure reset pin.
*
* This function configures reset pin. When enabled, the low power filter is enabled in both
* Active and Low power modes, the reset filter is only enabled in Active mode. When both filers
* are enabled, they operate in series.
*
* @param base CMC peripheral base address.
* @param config Pointer to the reset pin config structure.
*/
void CMC_ConfigResetPin(CMC_Type *base, const cmc_reset_pin_config_t *config);
/* @} */
/*!
* @name System Reset Interrupts.
* @{
*/
/*!
* @brief Enable system reset interrupts.
*
* This function enables the system reset interrupts. The assertion of
* non-fatal warm reset can be delayed for 258 cycles of the 32K_CLK clock
* while an enabled interrupt is generated. Then Software can perform a graceful
* shutdown or abort the non-fatal warm reset provided the pending reset source is cleared
* by resetting the reset source and then clearing the pending flag.
*
* @param base CMC peripheral base address.
* @param mask System reset interrupts. See @ref _cmc_system_reset_interrupt_enable for details.
*
*/
static inline void CMC_EnableSystemResetInterrupt(CMC_Type *base, uint32_t mask)
{
base->SRIE |= mask;
}
/*!
* @brief Disable system reset interrupts.
*
* This function disables the system reset interrupts.
*
* @param base CMC peripheral base address.
* @param mask System reset interrupts. See @ref _cmc_system_reset_interrupt_enable for details.
*/
static inline void CMC_DisableSystemResetInterrupt(CMC_Type *base, uint32_t mask)
{
base->SRIE &= (uint32_t)(~mask);
}
/*!
* @brief Gets System Reset interrupt flags.
*
* This function returns the System reset interrupt flags.
*
* @param base CMC peripheral base address.
* @return System reset interrupt flags. See @ref _cmc_system_reset_interrupt_flag for details.
*/
static inline uint32_t CMC_GetSystemResetInterruptFlags(CMC_Type *base)
{
return base->SRIF;
}
/*!
* @brief Clears System Reset interrupt flags.
*
* This function clears system reset interrupt flags. The pending reset source
* can be cleared by resetting the source of the reset and then clearing the pending
* flags.
*
* @param base CMC peripheral base address.
* @param mask System Reset interrupt flags. See @ref _cmc_system_reset_interrupt_flag for details.
*
*/
static inline void CMC_ClearSystemResetInterruptFlags(CMC_Type *base, uint32_t mask)
{
base->SRIF = mask;
}
/* @} */
/*!
* @name Non Maskable Pin interrupt.
* @{
*/
/*!
* @brief Enable/Disable Non maskable Pin interrupt.
*
* @param base CMC peripheral base address.
* @param enable Enable or disable Non maskable pin interrupt.
* true - enable Non-maskable pin interrupt.
* false - disable Non-maskable pin interupt.
*/
static inline void CMC_EnableNonMaskablePinInterrupt(CMC_Type *base, bool enable)
{
if (enable)
{
base->CORECTL |= CMC_CORECTL_NPIE_MASK;
}
else
{
base->CORECTL &= ~CMC_CORECTL_NPIE_MASK;
}
}
/* @} */
/*!
* @name Boot Configuration.
* @{
*/
/*!
* @brief Gets the logic state of the ISPMODE_n pin.
*
* This function returns the logic state of the ISPMODE_n pin
* on the last negation of RESET_b pin.
*
* @param base CMC peripheral base address.
* @return The logic state of the ISPMODE_n pin on the last negation of RESET_b pin.
*/
static inline uint8_t CMC_GetISPMODEPinLogic(CMC_Type *base)
{
return (uint8_t)((base->MR[0] & CMC_MR_ISPMODE_n_MASK) >> CMC_MR_ISPMODE_n_SHIFT);
}
/*!
* @brief Clears ISPMODE_n pin state.
*
* @param base CMC peripheral base address.
*/
static inline void CMC_ClearISPMODEPinLogic(CMC_Type *base)
{
base->MR[0] = CMC_MR_ISPMODE_n_MASK;
}
/*!
* @brief Set the logic state of the BOOT_CONFIGn pin.
*
* This function force the logic state of the Boot_Confign pin to assert
* on next system reset.
*
* @param base CMC peripheral base address.
* @param assert Assert the corresponding pin or not.
* true - Assert corresponding pin on next system reset.
* false - No effect.
*/
static inline void CMC_ForceBootConfiguration(CMC_Type *base, bool assert)
{
if (assert)
{
base->FM[0] |= CMC_FM_FORCECFG_MASK;
}
else
{
base->FM[0] &= ~CMC_FM_FORCECFG_MASK;
}
}
/* @} */
/*!
* @name BootROM Status.
* @{
*/
#if (defined(FSL_FEATURE_MCX_CMC_HAS_BSR_REG) && FSL_FEATURE_MCX_CMC_HAS_BSR_REG)
/*!
* @brief Gets the status information written by the BootROM.
*
* @param base CMC peripheral base address.
* @return The status information written by the BootROM.
*/
static inline uint32_t CMC_GetBootRomStatus(CMC_Type *base)
{
return base->BSR;
}
/*!
* @brief Sets the bootROM status value.
*
* @note This function is useful when result of CMC_CheckBootRomRegisterWrittable() is true.
*
* @param base CMC peripheral base address.
* @param stat The state value to set.
*/
static inline void CMC_SetBootRomStatus(CMC_Type *base, uint32_t statValue)
{
base->BSR = CMC_BSR_STAT(statValue);
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_BSR_REG */
#if (defined(FSL_FEATURE_MCX_CMC_HAS_BLR_REG) && FSL_FEATURE_MCX_CMC_HAS_BLR_REG)
/*!
* @brief Check if BootROM status and lock registers is writtable.
*
* @param base CMC peripheral base address.
* @return The result of whether BootROM status and lock register is writtable.
* - \b true BootROM status and lock registers are writtable;
* - \b false BootROM status and lock registers are not writtable.
*/
static inline bool CMC_CheckBootRomRegisterWrittable(CMC_Type *base)
{
return (base->BLR == 0x2UL);
}
/*!
* @brief After invoking this function, BootROM status and lock registers cannot be written.
*
* @param base CMC peripheral base address.
*/
static inline void CMC_LockBootRomStatusWritten(CMC_Type *base)
{
base->BLR = CMC_BLR_LOCK(0x5U);
}
/*!
* @brief After invoking this function, BootROM status and lock register can be written.s
*
* @param base
*/
static inline void CMC_UnlockBootRomStatusWritten(CMC_Type *base)
{
base->BLR = CMC_BLR_LOCK(0x2U);
}
#endif /* FSL_FEATURE_MCX_CMC_HAS_BLR_REG */
/* @} */
#if (defined(FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG) && FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG)
/*!
* @name System SRAM Configuration.
* @{
*/
/*!
* @brief Power off the selected system SRAM always.
*
* @note This function power off the selected system SRAM always. The SRAM arrays should
* not be accessed while they are shut down. SRAM array contents are not retained
* if they are powered off.
*
* @note Once invoked, the previous settings will be overwritten.
*
* @param base CMC peripheral base address.
* @param mask Bitmap of the SRAM arrays to be powered off all modes.
* See @ref _cmc_system_sram_arrays for details.
* Check Reference Manual for the SRAM region and mask bit relationship.
*/
void CMC_PowerOffSRAMAllMode(CMC_Type *base, uint32_t mask);
/*!
* @brief Power on SRAM during all mode.
*
* @note Once invoked, the previous settings will be overwritten.
*
* @param base CMC peripheral base address.
* @param mask Bitmap of the SRAM arrays to be powered on all modes.
* See @ref _cmc_system_sram_arrays for details.
* Check Reference Manual for the SRAM region and mask bit relationship.
*/
static inline void CMC_PowerOnSRAMAllMode(CMC_Type *base, uint32_t mask)
{
base->SRAMDIS[0] &= CMC_SRAMDIS_DIS((uint32_t)(~mask));
}
/*!
* @brief Power off the selected system SRAM during low power modes only.
*
* This function power off the selected system SRAM only during low power mode.
* SRAM array contents are not retained if they are power off.
*
* @param base CMC peripheral base address.
* @param mask Bitmap of the SRAM arrays to be power off during low power mode only.
* See @ref _cmc_system_sram_arrays for details.
* Check Reference Manual for the SRAM region and mask bit relationship.
*/
void CMC_PowerOffSRAMLowPowerOnly(CMC_Type *base, uint32_t mask);
/*!
* @brief Power on the selected system SRAM during low power modes only.
*
* This function power on the selected system SRAM. The SRAM arrray contents are
* retained in low power modes.
*
* @param base CMC peripheral base address.
* @param mask Bitmap of the SRAM arrays to be power on during low power mode only.
* See @ref _cmc_system_sram_arrays for details.
* Check Reference Manual for the SRAM region and mask bit relationship.
*/
static inline void CMC_PowerOnSRAMLowPowerOnly(CMC_Type *base, uint32_t mask)
{
base->SRAMRET[0] &= CMC_SRAMRET_RET((uint32_t)(~mask));
}
/* @} */
#endif /* FSL_FEATURE_MCX_CMC_HAS_SRAM_DIS_REG */
/*!
* @name Flash Low Power Mode configuration.
* @{
*/
#if (defined(FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE) && FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE)
/*!
* @brief Configs the low power mode of the on-chip flash memory.
*
* This function configs the low power mode of the on-chip flash memory.
*
* @param base CMC peripheral base address.
* @param doze true: Flash is disabled while core is sleeping
* false: No effect.
* @param disable true: Flash memory is placed in low power state.
* false: No effect.
*/
void CMC_ConfigFlashMode(CMC_Type *base, bool doze, bool disable);
#else
/*!
* @brief Configs the low power mode of the on-chip flash memory.
*
* This function configs the low power mode of the on-chip flash memory.
*
* @param base CMC peripheral base address.
* @param wake true: Flash will exit low power state during the flash memory accesses.
* false: No effect.
* @param doze true: Flash is disabled while core is sleeping
* false: No effect.
* @param disable true: Flash memory is placed in low power state.
* false: No effect.
*/
void CMC_ConfigFlashMode(CMC_Type *base, bool wake, bool doze, bool disable);
#endif /* FSL_FEATURE_MCX_CMC_HAS_NO_FLASHCR_WAKE */
/* @} */
/*!
* @name Debug Configuration.
*/
/*!
* @brief Enables/Disables debug Operation when the core sleep.
*
* This function configs what happens to debug when core sleeps.
*
* @param base CMC peripheral base address.
* @param enable Enable or disable Debug when Core is sleeping.
* true - Debug remains enabled when the core is sleeping.
* false - Debug is disabled when the core is sleeping.
*/
static inline void CMC_EnableDebugOperation(CMC_Type *base, bool enable)
{
if (enable)
{
base->DBGCTL &= ~CMC_DBGCTL_SOD_MASK;
}
else
{
base->DBGCTL |= CMC_DBGCTL_SOD_MASK;
}
}
/* @} */
/*!
* @name Low Power modes enter.
* @{
*/
/*!
* @brief Prepares to enter low power modes.
*
* This function should be called before entering low power modes.
*
*/
void CMC_PreEnterLowPowerMode(void);
/*!
* @brief Recovers after wake up from low power modes.
*
* This function should be called after wake up from low power modes.
* This function should be used with CMC_PreEnterLowPowerMode()
*
*/
void CMC_PostExitLowPowerMode(void);
/*!
* @brief Configs the entry into the same low power mode for each power domains.
*
* This function provides the feature to entry into the same low power mode for each power
* domains. Before invoking this function, please ensure the selected power mode have been allowed.
*
* @param base CMC peripheral base address.
* @param lowPowerMode The low power mode to be entered. See @ref cmc_low_power_mode_t for the details.
*
*/
void CMC_GlobalEnterLowPowerMode(CMC_Type *base, cmc_low_power_mode_t lowPowerMode);
/*!
* @brief Configs the entry into different low power modes for each power domains.
*
* This function provides the feature to entry into different low power modes for
* each power domains. Before invoking this function please ensure the selected
* modes are allowed.
*
* @param base CMC peripheral base address.
* @param config Pointer to the cmc_power_domain_config_t structure.
*/
void CMC_EnterLowPowerMode(CMC_Type *base, const cmc_power_domain_config_t *config);
/* @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* FSL_CMC_H_ */

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#define SDK_MEM_MAGIC_NUMBER 12345U
typedef struct _mem_align_control_block
{
uint16_t identifier; /*!< Identifier for the memory control block. */
uint16_t offset; /*!< offset from aligned address to real address */
} mem_align_cb_t;
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.common"
#endif
#if !((defined(__DSC__) && defined(__CW__)))
void *SDK_Malloc(size_t size, size_t alignbytes)
{
mem_align_cb_t *p_cb = NULL;
uint32_t alignedsize;
/* Check overflow. */
alignedsize = (uint32_t)(unsigned int)SDK_SIZEALIGN(size, alignbytes);
if (alignedsize < size)
{
return NULL;
}
if (alignedsize > SIZE_MAX - alignbytes - sizeof(mem_align_cb_t))
{
return NULL;
}
alignedsize += alignbytes + (uint32_t)sizeof(mem_align_cb_t);
union
{
void *pointer_value;
uintptr_t unsigned_value;
} p_align_addr, p_addr;
p_addr.pointer_value = malloc((size_t)alignedsize);
if (p_addr.pointer_value == NULL)
{
return NULL;
}
p_align_addr.unsigned_value = SDK_SIZEALIGN(p_addr.unsigned_value + sizeof(mem_align_cb_t), alignbytes);
p_cb = (mem_align_cb_t *)(p_align_addr.unsigned_value - 4U);
p_cb->identifier = SDK_MEM_MAGIC_NUMBER;
p_cb->offset = (uint16_t)(p_align_addr.unsigned_value - p_addr.unsigned_value);
return p_align_addr.pointer_value;
}
void SDK_Free(void *ptr)
{
union
{
void *pointer_value;
uintptr_t unsigned_value;
} p_free;
p_free.pointer_value = ptr;
mem_align_cb_t *p_cb = (mem_align_cb_t *)(p_free.unsigned_value - 4U);
if (p_cb->identifier != SDK_MEM_MAGIC_NUMBER)
{
return;
}
p_free.unsigned_value = p_free.unsigned_value - p_cb->offset;
free(p_free.pointer_value);
}
#endif

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_COMMON_H_
#define FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#if defined(__ICCARM__) || (defined(__CC_ARM) || defined(__ARMCC_VERSION)) || defined(__GNUC__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Configurations
******************************************************************************/
/*! @brief Macro to use the default weak IRQ handler in drivers. */
#ifndef FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
#define FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ 1
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100L) + (code)))
/*! @brief Construct the version number for drivers.
*
* The driver version is a 32-bit number, for both 32-bit platforms(such as Cortex M)
* and 16-bit platforms(such as DSC).
*
* @verbatim
| Unused || Major Version || Minor Version || Bug Fix |
31 25 24 17 16 9 8 0
@endverbatim
*/
#define MAKE_VERSION(major, minor, bugfix) (((major)*65536L) + ((minor)*256L) + (bugfix))
/*! @name Driver version */
/*! @{ */
/*! @brief common driver version. */
#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 4, 1))
/*! @} */
/*! @name Debug console type definition. */
/*! @{ */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console based on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console based on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console based on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console based on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console based on FLEXCOMM. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console based on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console based on LPC_VUSART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_MINI_USART 8U /*!< Debug console based on LPC_USART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_SWO 9U /*!< Debug console based on SWO. */
#define DEBUG_CONSOLE_DEVICE_TYPE_QSCI 10U /*!< Debug console based on QSCI. */
/*! @} */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_MIPI_DSI = 30, /*!< Group number for MIPI DSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_DCP = 67, /*!< Group number for DCP status codes.*/
kStatusGroup_MSCAN = 68, /*!< Group number for MSCAN status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_PDM = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
kStatusGroup_SPDIF = 75, /*!< Group number for SPDIF status codes. */
kStatusGroup_LPC_MINISPI = 76, /*!< Group number for LPC_MINISPI status codes. */
kStatusGroup_HASHCRYPT = 77, /*!< Group number for Hashcrypt status codes */
kStatusGroup_LPC_SPI_SSP = 78, /*!< Group number for LPC_SPI_SSP status codes. */
kStatusGroup_I3C = 79, /*!< Group number for I3C status codes */
kStatusGroup_LPC_I2C_1 = 97, /*!< Group number for LPC_I2C_1 status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */
kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */
kStatusGroup_IAP = 102, /*!< Group number for IAP status codes */
kStatusGroup_SFA = 103, /*!< Group number for SFA status codes*/
kStatusGroup_SPC = 104, /*!< Group number for SPC status codes. */
kStatusGroup_PUF = 105, /*!< Group number for PUF status codes. */
kStatusGroup_TOUCH_PANEL = 106, /*!< Group number for touch panel status codes */
kStatusGroup_VBAT = 107, /*!< Group number for VBAT status codes */
kStatusGroup_XSPI = 108, /*!< Group number for XSPI status codes */
kStatusGroup_PNGDEC = 109, /*!< Group number for PNGDEC status codes */
kStatusGroup_JPEGDEC = 110, /*!< Group number for JPEGDEC status codes */
kStatusGroup_HAL_GPIO = 121, /*!< Group number for HAL GPIO status codes. */
kStatusGroup_HAL_UART = 122, /*!< Group number for HAL UART status codes. */
kStatusGroup_HAL_TIMER = 123, /*!< Group number for HAL TIMER status codes. */
kStatusGroup_HAL_SPI = 124, /*!< Group number for HAL SPI status codes. */
kStatusGroup_HAL_I2C = 125, /*!< Group number for HAL I2C status codes. */
kStatusGroup_HAL_FLASH = 126, /*!< Group number for HAL FLASH status codes. */
kStatusGroup_HAL_PWM = 127, /*!< Group number for HAL PWM status codes. */
kStatusGroup_HAL_RNG = 128, /*!< Group number for HAL RNG status codes. */
kStatusGroup_HAL_I2S = 129, /*!< Group number for HAL I2S status codes. */
kStatusGroup_HAL_ADC_SENSOR = 130, /*!< Group number for HAL ADC SENSOR status codes. */
kStatusGroup_TIMERMANAGER = 135, /*!< Group number for TiMER MANAGER status codes. */
kStatusGroup_SERIALMANAGER = 136, /*!< Group number for SERIAL MANAGER status codes. */
kStatusGroup_LED = 137, /*!< Group number for LED status codes. */
kStatusGroup_BUTTON = 138, /*!< Group number for BUTTON status codes. */
kStatusGroup_EXTERN_EEPROM = 139, /*!< Group number for EXTERN EEPROM status codes. */
kStatusGroup_SHELL = 140, /*!< Group number for SHELL status codes. */
kStatusGroup_MEM_MANAGER = 141, /*!< Group number for MEM MANAGER status codes. */
kStatusGroup_LIST = 142, /*!< Group number for List status codes. */
kStatusGroup_OSA = 143, /*!< Group number for OSA status codes. */
kStatusGroup_COMMON_TASK = 144, /*!< Group number for Common task status codes. */
kStatusGroup_MSG = 145, /*!< Group number for messaging status codes. */
kStatusGroup_SDK_OCOTP = 146, /*!< Group number for OCOTP status codes. */
kStatusGroup_SDK_FLEXSPINOR = 147, /*!< Group number for FLEXSPINOR status codes.*/
kStatusGroup_CODEC = 148, /*!< Group number for codec status codes. */
kStatusGroup_ASRC = 149, /*!< Group number for codec status ASRC. */
kStatusGroup_OTFAD = 150, /*!< Group number for codec status codes. */
kStatusGroup_SDIOSLV = 151, /*!< Group number for SDIOSLV status codes. */
kStatusGroup_MECC = 152, /*!< Group number for MECC status codes. */
kStatusGroup_ENET_QOS = 153, /*!< Group number for ENET_QOS status codes. */
kStatusGroup_LOG = 154, /*!< Group number for LOG status codes. */
kStatusGroup_I3CBUS = 155, /*!< Group number for I3CBUS status codes. */
kStatusGroup_QSCI = 156, /*!< Group number for QSCI status codes. */
kStatusGroup_ELEMU = 157, /*!< Group number for ELEMU status codes. */
kStatusGroup_QUEUEDSPI = 158, /*!< Group number for QSPI status codes. */
kStatusGroup_POWER_MANAGER = 159, /*!< Group number for POWER_MANAGER status codes. */
kStatusGroup_IPED = 160, /*!< Group number for IPED status codes. */
kStatusGroup_ELS_PKC = 161, /*!< Group number for ELS PKC status codes. */
kStatusGroup_CSS_PKC = 162, /*!< Group number for CSS PKC status codes. */
kStatusGroup_HOSTIF = 163, /*!< Group number for HOSTIF status codes. */
kStatusGroup_CLIF = 164, /*!< Group number for CLIF status codes. */
kStatusGroup_BMA = 165, /*!< Group number for BMA status codes. */
kStatusGroup_NETC = 166, /*!< Group number for NETC status codes. */
kStatusGroup_ELE = 167, /*!< Group number for ELE status codes. */
kStatusGroup_GLIKEY = 168, /*!< Group number for GLIKEY status codes. */
};
/*! \public
* @brief Generic status return codes.
*/
enum
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< Generic status for Success. */
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< Generic status for Fail. */
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< Generic status for read only failure. */
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< Generic status for out of range access. */
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< Generic status for invalid argument check. */
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5), /*!< Generic status for timeout. */
kStatus_NoTransferInProgress =
MAKE_STATUS(kStatusGroup_Generic, 6), /*!< Generic status for no transfer in progress. */
kStatus_Busy = MAKE_STATUS(kStatusGroup_Generic, 7), /*!< Generic status for module is busy. */
kStatus_NoData =
MAKE_STATUS(kStatusGroup_Generic, 8), /*!< Generic status for no data is found for the operation. */
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
#ifdef __ZEPHYR__
#include <zephyr/sys/util.h>
#else
/*!
* @name Min/max macros
* @{
*/
#if !defined(MIN)
/*! Computes the minimum of \a a and \a b. */
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#if !defined(MAX)
/*! Computes the maximum of \a a and \a b. */
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
/*! @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
#endif /* __ZEPHYR__ */
/*! @name UINT16_MAX/UINT32_MAX value */
/*! @{ */
#if !defined(UINT16_MAX)
/*! Max value of uint16_t type. */
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
/*! Max value of uint32_t type. */
#define UINT32_MAX ((uint32_t)-1)
#endif
/*! @} */
/*! Macro to get upper 32 bits of a 64-bit value */
#if !defined(UINT64_H)
#define UINT64_H(X) ((uint32_t)((((uint64_t) (X)) >> 32U) & 0x0FFFFFFFFULL))
#endif
/*! Macro to get lower 32 bits of a 64-bit value */
#if !defined(UINT64_L)
#define UINT64_L(X) ((uint32_t)(((uint64_t) (X)) & 0x0FFFFFFFFULL))
#endif
/*!
* @def SUPPRESS_FALL_THROUGH_WARNING()
*
* For switch case code block, if case section ends without "break;" statement, there wil be
* fallthrough warning with compiler flag -Wextra or -Wimplicit-fallthrough=n when using armgcc.
* To suppress this warning, "SUPPRESS_FALL_THROUGH_WARNING();" need to be added at the end of each
* case section which misses "break;"statement.
*/
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
#define SUPPRESS_FALL_THROUGH_WARNING() __attribute__((fallthrough))
#else
#define SUPPRESS_FALL_THROUGH_WARNING()
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
#if !((defined(__DSC__) && defined(__CW__)))
/*!
* @brief Allocate memory with given alignment and aligned size.
*
* This is provided to support the dynamically allocated memory
* used in cache-able region.
* @param size The length required to malloc.
* @param alignbytes The alignment size.
* @retval The allocated memory.
*/
void *SDK_Malloc(size_t size, size_t alignbytes);
/*!
* @brief Free memory.
*
* @param ptr The memory to be release.
*/
void SDK_Free(void *ptr);
#endif
/*!
* @brief Delay at least for some time.
* Please note that, this API uses while loop for delay, different run-time environments make the time not precise,
* if precise delay count was needed, please implement a new delay function with hardware timer.
*
* @param delayTime_us Delay time in unit of microsecond.
* @param coreClock_Hz Core clock frequency with Hz.
*/
void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz);
#if defined(__cplusplus)
}
#endif
/*! @} */
#if (defined(__DSC__) && defined(__CW__))
#include "fsl_common_dsc.h"
#elif defined(__XTENSA__)
#include "fsl_common_dsp.h"
#else
#include "fsl_common_arm.h"
#endif
#endif /* FSL_COMMON_H_ */

View File

@ -0,0 +1,257 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.common_arm"
#endif
#ifndef __GIC_PRIO_BITS
#if defined(ENABLE_RAM_VECTOR_TABLE)
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
#ifdef __VECTOR_TABLE
#undef __VECTOR_TABLE
#endif
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern uint32_t Image$$VECTOR_ROM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$Base[];
extern uint32_t Image$$VECTOR_RAM$$ZI$$Limit[];
#define __VECTOR_TABLE Image$$VECTOR_ROM$$Base
#define __VECTOR_RAM Image$$VECTOR_RAM$$Base
#define __RAM_VECTOR_TABLE_SIZE (((uint32_t)Image$$VECTOR_RAM$$ZI$$Limit - (uint32_t)Image$$VECTOR_RAM$$Base))
#elif defined(__ICCARM__)
extern uint32_t __RAM_VECTOR_TABLE_SIZE[];
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
#elif defined(__GNUC__)
extern uint32_t __VECTOR_TABLE[];
extern uint32_t __VECTOR_RAM[];
extern uint32_t __RAM_VECTOR_TABLE_SIZE_BYTES[];
uint32_t __RAM_VECTOR_TABLE_SIZE = (uint32_t)(__RAM_VECTOR_TABLE_SIZE_BYTES);
#endif /* defined(__CC_ARM) || defined(__ARMCC_VERSION) */
uint32_t n;
uint32_t ret;
uint32_t irqMaskValue;
irqMaskValue = DisableGlobalIRQ();
if (SCB->VTOR != (uint32_t)__VECTOR_RAM)
{
/* Copy the vector table from ROM to RAM */
for (n = 0; n < ((uint32_t)__RAM_VECTOR_TABLE_SIZE) / sizeof(uint32_t); n++)
{
__VECTOR_RAM[n] = __VECTOR_TABLE[n];
}
/* Point the VTOR to the position of vector table */
SCB->VTOR = (uint32_t)__VECTOR_RAM;
}
ret = __VECTOR_RAM[(int32_t)irq + 16];
/* make sure the __VECTOR_RAM is noncachable */
__VECTOR_RAM[(int32_t)irq + 16] = irqHandler;
EnableGlobalIRQ(irqMaskValue);
return ret;
}
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#endif /* __GIC_PRIO_BITS. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*
* When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
* powerlib should be used instead of these functions.
*/
#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
/*
* When the SYSCON STARTER registers are discontinuous, these functions are
* implemented in fsl_power.c.
*/
#if !(defined(FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS) && FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS)
void EnableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERSET[index] = 1UL << intNumber;
(void)EnableIRQ(interrupt); /* also enable interrupt at NVIC */
}
void DisableDeepSleepIRQ(IRQn_Type interrupt)
{
uint32_t intNumber = (uint32_t)interrupt;
(void)DisableIRQ(interrupt); /* also disable interrupt at NVIC */
uint32_t index = 0;
while (intNumber >= 32u)
{
index++;
intNumber -= 32u;
}
SYSCON->STARTERCLR[index] = 1UL << intNumber;
}
#endif /* FSL_FEATURE_SYSCON_STARTER_DISCONTINUOUS */
#endif /* FSL_FEATURE_POWERLIB_EXTEND */
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(DWT)
/* Use WDT. */
void MSDK_EnableCpuCycleCounter(void)
{
/* Make sure the DWT trace fucntion is enabled. */
if (CoreDebug_DEMCR_TRCENA_Msk != (CoreDebug_DEMCR_TRCENA_Msk & CoreDebug->DEMCR))
{
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
}
/* CYCCNT not supported on this device. */
assert(DWT_CTRL_NOCYCCNT_Msk != (DWT->CTRL & DWT_CTRL_NOCYCCNT_Msk));
/* Read CYCCNT directly if CYCCENT has already been enabled, otherwise enable CYCCENT first. */
if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL))
{
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}
}
uint32_t MSDK_GetCpuCycleCount(void)
{
return DWT->CYCCNT;
}
#endif /* defined(DWT) */
#if !(defined(SDK_DELAY_USE_DWT) && defined(DWT))
/* Use software loop. */
#if defined(__CC_ARM) /* This macro is arm v5 specific */
/* clang-format off */
__ASM static void DelayLoop(uint32_t count)
{
loop
SUBS R0, R0, #1
CMP R0, #0
BNE loop
BX LR
}
#elif defined(__ARM_ARCH_8A__) /* This macro is ARMv8-A specific */
static void DelayLoop(uint32_t count)
{
__ASM volatile(" MOV X0, %0" : : "r"(count));
__ASM volatile(
"loop%=: \n"
" SUB X0, X0, #1 \n"
" CMP X0, #0 \n"
" BNE loop%= \n"
:
:
: "r0");
}
/* clang-format on */
#elif defined(__ARMCC_VERSION) || defined(__ICCARM__) || defined(__GNUC__)
/* Cortex-M0 has a smaller instruction set, SUBS isn't supported in thumb-16 mode reported from __GNUC__ compiler,
* use SUB and CMP here for compatibility */
static void DelayLoop(uint32_t count)
{
__ASM volatile(" MOV R0, %0" : : "r"(count));
__ASM volatile(
"loop%=: \n"
#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
" SUB R0, R0, #1 \n"
#else
" SUBS R0, R0, #1 \n"
#endif
" CMP R0, #0 \n"
" BNE loop%= \n"
:
:
: "r0");
}
#endif /* defined(__CC_ARM) */
#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
/*!
* @brief Delay at least for some time.
* Please note that, if not uses DWT, this API will use while loop for delay, different run-time environments have
* effect on the delay time. If precise delay is needed, please enable DWT delay. The two parmeters delayTime_us and
* coreClock_Hz have limitation. For example, in the platform with 1GHz coreClock_Hz, the delayTime_us only supports
* up to 4294967 in current code. If long time delay is needed, please implement a new delay function.
*
* @param delayTime_us Delay time in unit of microsecond.
* @param coreClock_Hz Core clock frequency with Hz.
*/
void SDK_DelayAtLeastUs(uint32_t delayTime_us, uint32_t coreClock_Hz)
{
uint64_t count;
if (delayTime_us > 0U)
{
count = USEC_TO_COUNT(delayTime_us, coreClock_Hz);
assert(count <= UINT32_MAX);
#if defined(SDK_DELAY_USE_DWT) && defined(DWT) /* Use DWT for better accuracy */
MSDK_EnableCpuCycleCounter();
/* Calculate the count ticks. */
count += MSDK_GetCpuCycleCount();
if (count > UINT32_MAX)
{
count -= UINT32_MAX;
/* Wait for cyccnt overflow. */
while (count < MSDK_GetCpuCycleCount())
{
}
}
/* Wait for cyccnt reach count value. */
while (count > MSDK_GetCpuCycleCount())
{
}
#else
#if defined(__CORTEX_Axx) && ((__CORTEX_Axx == 53) || (__CORTEX_Axx == 55))
/*
* Cortex-A53/A55 execution throughput:
* - SUB/CMP: 2 instructions per cycle
* - BNE: 1 instruction per cycle
* So, each loop takes 2 CPU cycles.
*/
count = count / 2U;
#elif (__CORTEX_M == 7)
/* Divide value may be different in various environment to ensure delay is precise.
* Every loop count includes three instructions, due to Cortex-M7 sometimes executes
* two instructions in one period, through test here set divide 1.5. Other M cores use
* divide 4. By the way, divide 1.5 or 4 could let the count lose precision, but it does
* not matter because other instructions outside while loop is enough to fill the time.
*/
count = count / 3U * 2U;
#else
count = count / 4U;
#endif
DelayLoop((uint32_t)count);
#endif /* defined(SDK_DELAY_USE_DWT) && defined(DWT) */
}
}

View File

@ -0,0 +1,898 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_COMMON_ARM_H_
#define FSL_COMMON_ARM_H_
/*
* For CMSIS pack RTE.
* CMSIS pack RTE generates "RTC_Components.h" which contains the statements
* of the related <RTE_Components_h> element for all selected software components.
*/
#ifdef _RTE_
#include "RTE_Components.h"
#endif
/*!
* @addtogroup ksdk_common
* @{
*/
/*! @name Atomic modification
*
* These macros are used for atomic access, such as read-modify-write
* to the peripheral registers.
*
* Take @ref SDK_ATOMIC_LOCAL_CLEAR_AND_SET as an example: the parameter @c addr
* means the address of the peripheral register or variable you want to modify
* atomically, the parameter @c clearBits is the bits to clear, the parameter
* @c setBits it the bits to set.
* For example, to set a 32-bit register bit1:bit0 to 0b10, use like this:
*
* @code
volatile uint32_t * reg = (volatile uint32_t *)REG_ADDR;
SDK_ATOMIC_LOCAL_CLEAR_AND_SET(reg, 0x03, 0x02);
@endcode
*
* In this example, the register bit1:bit0 are cleared and bit1 is set, as a result,
* register bit1:bit0 = 0b10.
*
* @note For the platforms don't support exclusive load and store, these macros
* disable the global interrupt to pretect the modification.
*
* @note These macros only guarantee the local processor atomic operations. For
* the multi-processor devices, use hardware semaphore such as SEMA42 to
* guarantee exclusive access if necessary.
*
* @{
*/
/*!
* @def SDK_ATOMIC_LOCAL_ADD(addr, val)
* Add value \a val from the variable at address \a address.
*
* @def SDK_ATOMIC_LOCAL_SUB(addr, val)
* Subtract value \a val to the variable at address \a address.
*
* @def SDK_ATOMIC_LOCAL_SET(addr, bits)
* Set the bits specifiled by \a bits to the variable at address \a address.
*
* @def SDK_ATOMIC_LOCAL_CLEAR(addr, bits)
* Clear the bits specifiled by \a bits to the variable at address \a address.
*
* @def SDK_ATOMIC_LOCAL_TOGGLE(addr, bits)
* Toggle the bits specifiled by \a bits to the variable at address \a address.
*
* @def SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits)
* For the variable at address \a address, clear the bits specifiled by \a clearBits
* and set the bits specifiled by \a setBits.
*/
/* clang-format off */
#if ((defined(__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
(defined(__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
(defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
(defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ == 1)))
/* clang-format on */
/* If the LDREX and STREX are supported, use them. */
#define _SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXB(addr); \
(ops); \
} while (0UL != __STREXB((val), (addr)))
#define _SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXH(addr); \
(ops); \
} while (0UL != __STREXH((val), (addr)))
#define _SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, val, ops) \
do \
{ \
(val) = __LDREXW(addr); \
(ops); \
} while (0UL != __STREXW((val), (addr)))
static inline void _SDK_AtomicLocalAdd1Byte(volatile uint8_t *addr, uint8_t val)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalAdd2Byte(volatile uint16_t *addr, uint16_t val)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalAdd4Byte(volatile uint32_t *addr, uint32_t val)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val += val);
}
static inline void _SDK_AtomicLocalSub1Byte(volatile uint8_t *addr, uint8_t val)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSub2Byte(volatile uint16_t *addr, uint16_t val)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSub4Byte(volatile uint32_t *addr, uint32_t val)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val -= val);
}
static inline void _SDK_AtomicLocalSet1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalSet2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalSet4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val |= bits);
}
static inline void _SDK_AtomicLocalClear1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalClear2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalClear4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val &= ~bits);
}
static inline void _SDK_AtomicLocalToggle1Byte(volatile uint8_t *addr, uint8_t bits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalToggle2Byte(volatile uint16_t *addr, uint16_t bits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalToggle4Byte(volatile uint32_t *addr, uint32_t bits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val ^= bits);
}
static inline void _SDK_AtomicLocalClearAndSet1Byte(volatile uint8_t *addr, uint8_t clearBits, uint8_t setBits)
{
uint8_t s_val;
_SDK_ATOMIC_LOCAL_OPS_1BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
static inline void _SDK_AtomicLocalClearAndSet2Byte(volatile uint16_t *addr, uint16_t clearBits, uint16_t setBits)
{
uint16_t s_val;
_SDK_ATOMIC_LOCAL_OPS_2BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
static inline void _SDK_AtomicLocalClearAndSet4Byte(volatile uint32_t *addr, uint32_t clearBits, uint32_t setBits)
{
uint32_t s_val;
_SDK_ATOMIC_LOCAL_OPS_4BYTE(addr, s_val, s_val = (s_val & ~clearBits) | setBits);
}
#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalAdd1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(val)) : \
((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalAdd2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(val)) : \
_SDK_AtomicLocalAdd4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(val))))
#define SDK_ATOMIC_LOCAL_SUB(addr, val) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalSub1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(val)) : \
((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalSub2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(val)) : \
_SDK_AtomicLocalSub4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(val))))
#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? _SDK_AtomicLocalSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClear1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClear2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalClear4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalToggle1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(bits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalToggle2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(bits)) : \
_SDK_AtomicLocalToggle4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(bits))))
#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
((1UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClearAndSet1Byte((volatile uint8_t *)(volatile void *)(addr), (uint8_t)(clearBits), (uint8_t)(setBits)) : \
((2UL == sizeof(*(addr))) ? \
_SDK_AtomicLocalClearAndSet2Byte((volatile uint16_t *)(volatile void *)(addr), (uint16_t)(clearBits), (uint16_t)(setBits)) : \
_SDK_AtomicLocalClearAndSet4Byte((volatile uint32_t *)(volatile void *)(addr), (uint32_t)(clearBits), (uint32_t)(setBits))))
#else
#define SDK_ATOMIC_LOCAL_ADD(addr, val) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) += (val); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#define SDK_ATOMIC_LOCAL_SUB(addr, val) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) -= (val); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#define SDK_ATOMIC_LOCAL_SET(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) |= (bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#define SDK_ATOMIC_LOCAL_CLEAR(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) &= ~(bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#define SDK_ATOMIC_LOCAL_TOGGLE(addr, bits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) ^= (bits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#define SDK_ATOMIC_LOCAL_CLEAR_AND_SET(addr, clearBits, setBits) \
do \
{ \
uint32_t s_atomicOldInt; \
s_atomicOldInt = DisableGlobalIRQ(); \
*(addr) = (*(addr) & ~(clearBits)) | (setBits); \
EnableGlobalIRQ(s_atomicOldInt); \
} while (false)
#endif
/*! @} */
/*! @name Timer utilities */
/*! @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)(((uint64_t)(us) * (clockFreqInHz)) / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000000U / (clockFreqInHz))
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)(ms) * (clockFreqInHz) / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)(count)*1000U / (clockFreqInHz))
/*! @} */
/*! @name ISR exit barrier
* @{
*
* ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
* exception return operation might vector to incorrect interrupt.
* For Cortex-M7, if core speed much faster than peripheral register write speed,
* the peripheral interrupt flags may be still set after exiting ISR, this results to
* the same error similar with errata 83869.
*/
#if (defined __CORTEX_M) && ((__CORTEX_M == 4U) || (__CORTEX_M == 7U))
#define SDK_ISR_EXIT_BARRIER __DSB()
#else
#define SDK_ISR_EXIT_BARRIER
#endif
/*! @} */
/*! @name Alignment variable definition macros */
/*! @{ */
#if (defined(__ICCARM__))
/*
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http:/ /supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __attribute__((aligned(alignbytes))) var
#elif defined(__GNUC__) || defined(DOXYGEN_OUTPUT)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported
#endif
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_ALIGN(var, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1U)) & (unsigned int)(~(unsigned int)((alignbytes)-1U)))
/*! @} */
/*!
* @name Non-cacheable region definition macros
*
* For initialized non-zero non-cacheable variables, please use "AT_NONCACHEABLE_SECTION_INIT(var) ={xx};" or
* "AT_NONCACHEABLE_SECTION_ALIGN_INIT(var) ={xx};" in your projects to define them. For zero-inited non-cacheable
* variables, please use "AT_NONCACHEABLE_SECTION(var);" or "AT_NONCACHEABLE_SECTION_ALIGN(var);" to define them,
* these zero-inited variables will be initialized to zero in system startup.
*
* @note For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*
* @{
*/
/*!
* @def AT_NONCACHEABLE_SECTION(var)
* Define a variable \a var, and place it in non-cacheable section.
*
* @def AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes)
* Define a variable \a var, and place it in non-cacheable section, the start address
* of the variable is aligned to \a alignbytes.
*
* @def AT_NONCACHEABLE_SECTION_INIT(var)
* Define a variable \a var with initial value, and place it in non-cacheable section.
*
* @def AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes)
* Define a variable \a var with initial value, and place it in non-cacheable section,
* the start address of the variable is aligned to \a alignbytes.
*/
#if ((!(defined(FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION) && FSL_FEATURE_HAS_NO_NONCACHEABLE_SECTION)) && \
defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE))
#if (defined(__ICCARM__))
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_INIT(var) var @"NonCacheable.init"
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable.init"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) __attribute__((aligned(alignbytes))) var
#if (defined(__CC_ARM))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __attribute__((aligned(alignbytes))) var
#else
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section(".bss.NonCacheable"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section(".bss.NonCacheable"))) __attribute__((aligned(alignbytes))) var
#endif
#elif (defined(__GNUC__)) || defined(DOXYGEN_OUTPUT)
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported.
#endif
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_ALIGN(var, alignbytes)
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_ALIGN(var, alignbytes)
#endif
/*! @} */
/*!
* @name Time sensitive region
* @{
*/
/*!
* @def AT_QUICKACCESS_SECTION_CODE(func)
* Place function in a section which can be accessed quickly by core.
*
* @def AT_QUICKACCESS_SECTION_DATA(var)
* Place data in a section which can be accessed quickly by core.
*
* @def AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes)
* Place data in a section which can be accessed quickly by core, and the variable
* address is set to align with \a alignbytes.
*/
#if (defined(__ICCARM__))
#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"
#define AT_QUICKACCESS_SECTION_DATA(var) var @"DataQuickAccess"
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
SDK_PRAGMA(data_alignment = alignbytes) var @"DataQuickAccess"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
__attribute__((section("DataQuickAccess"))) __attribute__((aligned(alignbytes))) var
#elif (defined(__GNUC__)) || defined(DOXYGEN_OUTPUT)
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(var) __attribute__((section("DataQuickAccess"))) var
#define AT_QUICKACCESS_SECTION_DATA_ALIGN(var, alignbytes) \
__attribute__((section("DataQuickAccess"))) var __attribute__((aligned(alignbytes)))
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
/*! @} */
/*!
* @name Ram Function
* @{
*
* @def RAMFUNCTION_SECTION_CODE(func)
* Place function in ram.
*/
#if (defined(__ICCARM__))
#define RAMFUNCTION_SECTION_CODE(func) func @"RamFunction"
#elif (defined(__CC_ARM) || defined(__ARMCC_VERSION))
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#elif (defined(__GNUC__)) || defined(DOXYGEN_OUTPUT)
#define RAMFUNCTION_SECTION_CODE(func) __attribute__((section("RamFunction"))) func
#else
#error Toolchain not supported.
#endif /* defined(__ICCARM__) */
/*! @} */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
void DefaultISR(void);
#endif
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
*/
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
#include "fsl_reset.h"
#endif
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus*/
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_EnableIRQ(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_DisableIRQ(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Enable the IRQ, and also set the interrupt priority.
*
* Only handle LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only handles the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ to Enable.
* @param priNum Priority number set to interrupt controller register.
* @retval kStatus_Success Interrupt priority set successfully
* @retval kStatus_Fail Failed to set the interrupt priority.
*/
static inline status_t EnableIRQWithPriority(IRQn_Type interrupt, uint8_t priNum)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_SetPriority(interrupt, priNum);
GIC_EnableIRQ(interrupt);
#else
NVIC_SetPriority(interrupt, priNum);
NVIC_EnableIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Set the IRQ priority.
*
* Only handle LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only handles the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ to set.
* @param priNum Priority number set to interrupt controller register.
*
* @retval kStatus_Success Interrupt priority set successfully
* @retval kStatus_Fail Failed to set the interrupt priority.
*/
static inline status_t IRQ_SetPriority(IRQn_Type interrupt, uint8_t priNum)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_SetPriority(interrupt, priNum);
#else
NVIC_SetPriority(interrupt, priNum);
#endif
}
return status;
}
/*!
* @brief Clear the pending IRQ flag.
*
* Only handle LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only handles the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The flag which IRQ to clear.
*
* @retval kStatus_Success Interrupt priority set successfully
* @retval kStatus_Fail Failed to set the interrupt priority.
*/
static inline status_t IRQ_ClearPendingIRQ(IRQn_Type interrupt)
{
status_t status = kStatus_Success;
if (NotAvail_IRQn == interrupt)
{
status = kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
else if ((int32_t)interrupt >= (int32_t)FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
status = kStatus_Fail;
}
#endif
else
{
#if defined(__GIC_PRIO_BITS)
GIC_ClearPendingIRQ(interrupt);
#else
NVIC_ClearPendingIRQ(interrupt);
#endif
}
return status;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
uint32_t mask;
#if defined(CPSR_I_Msk)
mask = __get_CPSR() & CPSR_I_Msk;
#elif defined(DAIF_I_BIT)
mask = __get_DAIF() & DAIF_I_BIT;
#else
mask = __get_PRIMASK();
#endif
__disable_irq();
return mask;
}
/*!
* @brief Enable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convenience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
#if defined(CPSR_I_Msk)
__set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
#elif defined(DAIF_I_BIT)
if (0UL == primask)
{
__enable_irq();
}
#else
__set_PRIMASK(primask);
#endif
}
#if defined(ENABLE_RAM_VECTOR_TABLE)
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*
* When FSL_FEATURE_POWERLIB_EXTEND is defined to non-zero value,
* powerlib should be used instead of these functions.
*/
#if !(defined(FSL_FEATURE_POWERLIB_EXTEND) && (FSL_FEATURE_POWERLIB_EXTEND != 0))
/*!
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
*
* Enable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internaly).
*
* @param interrupt The IRQ number.
*/
void EnableDeepSleepIRQ(IRQn_Type interrupt);
/*!
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
*
* Disable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internaly).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_POWERLIB_EXTEND */
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(DWT)
/*!
* @brief Enable the counter to get CPU cycles.
*/
void MSDK_EnableCpuCycleCounter(void);
/*!
* @brief Get the current CPU cycle count.
*
* @return Current CPU cycle count.
*/
uint32_t MSDK_GetCpuCycleCount(void);
#endif
#if defined(__cplusplus)
}
#endif /* __cplusplus*/
/*! @} */
#endif /* FSL_COMMON_ARM_H_ */

View File

@ -0,0 +1,371 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017, 2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_crc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.crc"
#endif
/*! @internal @brief Has data register with name CRC. */
#if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG
#define DATA CRC
#define DATALL CRCLL
#endif
#if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT
/* @brief Default user configuration structure for CRC-16-CCITT */
#define CRC_DRIVER_DEFAULT_POLYNOMIAL 0x1021U
/*< CRC-16-CCIT polynomial x**16 + x**12 + x**5 + x**0 */
#define CRC_DRIVER_DEFAULT_SEED 0xFFFFU
/*< Default initial checksum */
#define CRC_DRIVER_DEFAULT_REFLECT_IN false
/*< Default is no transpose */
#define CRC_DRIVER_DEFAULT_REFLECT_OUT false
/*< Default is transpose bytes */
#define CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM false
/*< Default is without complement of CRC data register read data */
#define CRC_DRIVER_DEFAULT_CRC_BITS kCrcBits16
/*< Default is 16-bit CRC protocol */
#define CRC_DRIVER_DEFAULT_CRC_RESULT kCrcFinalChecksum
/*< Default is resutl type is final checksum */
#endif /* CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT */
#if defined(CRC_RSTS)
#define CRC_RESETS_ARRAY CRC_RSTS
#endif
/*! @brief CRC type of transpose of read write data */
typedef enum _crc_transpose_type
{
kCrcTransposeNone = 0U, /*! No transpose */
kCrcTransposeBits = 1U, /*! Tranpose bits in bytes */
kCrcTransposeBitsAndBytes = 2U, /*! Transpose bytes and bits in bytes */
kCrcTransposeBytes = 3U, /*! Transpose bytes */
} crc_transpose_type_t;
/*!
* @brief CRC module configuration.
*
* This structure holds the configuration for the CRC module.
*/
typedef struct _crc_module_config
{
uint32_t polynomial; /*!< CRC Polynomial, MSBit first.@n
Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */
uint32_t seed; /*!< Starting checksum value */
crc_transpose_type_t readTranspose; /*!< Type of transpose when reading CRC result. */
crc_transpose_type_t writeTranspose; /*!< Type of transpose when writing CRC input data. */
bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */
crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */
} crc_module_config_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(CRC_RESETS_ARRAY)
/*!
* @brief Get instance number for CRC module.
*
* @param base CRC peripheral base address
*/
static uint32_t CRC_GetInstance(CRC_Type *base);
#endif
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(CRC_RESETS_ARRAY)
static CRC_Type *const s_crcBases[] = CRC_BASE_PTRS;
/* Reset array */
static const reset_ip_name_t s_crcResets[] = CRC_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if defined(CRC_RESETS_ARRAY)
static uint32_t CRC_GetInstance(CRC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_crcBases); instance++)
{
if (s_crcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_crcBases));
return instance;
}
#endif
/*!
* @brief Returns transpose type for CRC protocol reflect in parameter.
*
* This functions helps to set writeTranspose member of crc_config_t structure. Reflect in is CRC protocol parameter.
*
* @param enable True or false for the selected CRC protocol Reflect In (refin) parameter.
*/
static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable)
{
return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes);
}
/*!
* @brief Returns transpose type for CRC protocol reflect out parameter.
*
* This functions helps to set readTranspose member of crc_config_t structure. Reflect out is CRC protocol parameter.
*
* @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter.
*/
static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable)
{
return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone);
}
/*!
* @brief Starts checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts the checksum computation by writing the seed value
*
* @param base CRC peripheral address.
* @param config Pointer to protocol configuration structure.
*/
static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config)
{
uint32_t crcControl;
/* pre-compute value for CRC control registger based on user configuraton without WAS field */
crcControl = 0U | CRC_CTRL_TOT(config->writeTranspose) | CRC_CTRL_TOTR(config->readTranspose) |
CRC_CTRL_FXOR(config->complementChecksum) | CRC_CTRL_TCRC(config->crcBits);
/* make sure the control register is clear - WAS is deasserted, and protocol is set */
base->CTRL = crcControl;
/* write polynomial register */
base->GPOLY = config->polynomial;
/* write pre-computed control register value along with WAS to start checksum computation */
base->CTRL = crcControl | CRC_CTRL_WAS(true);
/* write seed (initial checksum) */
base->DATA = config->seed;
/* deassert WAS by writing pre-computed CRC control register value */
base->CTRL = crcControl;
}
/*!
* @brief Starts final checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts final checksum computation by writing the seed value.
* @note CRC_Get16bitResult() or CRC_Get32bitResult() return final checksum
* (output reflection and xor functions are applied).
*
* @param base CRC peripheral address.
* @param protocolConfig Pointer to protocol configuration structure.
*/
static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
{
crc_module_config_t moduleConfig;
/* convert protocol to CRC peripheral module configuration, prepare for final checksum */
moduleConfig.polynomial = protocolConfig->polynomial;
moduleConfig.seed = protocolConfig->seed;
moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut);
moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
moduleConfig.complementChecksum = protocolConfig->complementChecksum;
moduleConfig.crcBits = protocolConfig->crcBits;
CRC_ConfigureAndStart(base, &moduleConfig);
}
/*!
* @brief Starts intermediate checksum computation.
*
* Configures the CRC module for the specified CRC protocol. @n
* Starts intermediate checksum computation by writing the seed value.
* @note CRC_Get16bitResult() or CRC_Get32bitResult() return intermediate checksum (raw data register value).
*
* @param base CRC peripheral address.
* @param protocolConfig Pointer to protocol configuration structure.
*/
static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
{
crc_module_config_t moduleConfig;
/* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */
moduleConfig.polynomial = protocolConfig->polynomial;
moduleConfig.seed = protocolConfig->seed;
moduleConfig.readTranspose =
kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */
moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */
moduleConfig.crcBits = protocolConfig->crcBits;
CRC_ConfigureAndStart(base, &moduleConfig);
}
/*!
* brief Enables and configures the CRC peripheral module.
*
* This function enables the clock gate in the SIM module for the CRC peripheral.
* It also configures the CRC module and starts a checksum computation by writing the seed.
*
* param base CRC peripheral address.
* param config CRC module configuration structure.
*/
void CRC_Init(CRC_Type *base, const crc_config_t *config)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* ungate clock */
CLOCK_EnableClock(kCLOCK_Crc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(CRC_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_crcResets[CRC_GetInstance(base)]);
#endif
/* configure CRC module and write the seed */
if (config->crcResult == kCrcFinalChecksum)
{
CRC_SetProtocolConfig(base, config);
}
else
{
CRC_SetRawProtocolConfig(base, config);
}
}
/*!
* brief Loads default values to the CRC protocol configuration structure.
*
* Loads default values to the CRC protocol configuration structure. The default values are as follows.
* code
* config->polynomial = 0x1021;
* config->seed = 0xFFFF;
* config->reflectIn = false;
* config->reflectOut = false;
* config->complementChecksum = false;
* config->crcBits = kCrcBits16;
* config->crcResult = kCrcFinalChecksum;
* endcode
*
* param config CRC protocol configuration structure.
*/
void CRC_GetDefaultConfig(crc_config_t *config)
{
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
static const crc_config_t crc16ccit = {
CRC_DRIVER_DEFAULT_POLYNOMIAL, CRC_DRIVER_DEFAULT_SEED,
CRC_DRIVER_DEFAULT_REFLECT_IN, CRC_DRIVER_DEFAULT_REFLECT_OUT,
CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM, CRC_DRIVER_DEFAULT_CRC_BITS,
CRC_DRIVER_DEFAULT_CRC_RESULT,
};
*config = crc16ccit;
}
/*!
* brief Writes data to the CRC module.
*
* Writes input data buffer bytes to the CRC data register.
* The configured type of transpose is applied.
*
* param base CRC peripheral address.
* param data Input data stream, MSByte in data[0].
* param dataSize Size in bytes of the input data buffer.
*/
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize)
{
const uint32_t *data32;
/* 8-bit reads and writes till source address is aligned 4 bytes */
while ((0U != dataSize) && (0U != ((uint32_t)data & 3U)))
{
base->ACCESS8BIT.DATALL = *data;
data++;
dataSize--;
}
/* use 32-bit reads and writes as long as possible */
data32 = (const uint32_t *)(uint32_t)data;
while (dataSize >= sizeof(uint32_t))
{
base->DATA = *data32;
data32++;
dataSize -= sizeof(uint32_t);
}
data = (const uint8_t *)data32;
/* 8-bit reads and writes till end of data buffer */
while (dataSize != 0U)
{
base->ACCESS8BIT.DATALL = *data;
data++;
dataSize--;
}
}
/*!
* brief Reads the 32-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* param base CRC peripheral address.
* return An intermediate or the final 32-bit checksum, after configured transpose and complement operations.
*/
uint32_t CRC_Get32bitResult(CRC_Type *base)
{
return base->DATA;
}
/*!
* brief Reads a 16-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* param base CRC peripheral address.
* return An intermediate or the final 16-bit checksum, after configured transpose and complement operations.
*/
uint16_t CRC_Get16bitResult(CRC_Type *base)
{
uint32_t retval;
uint32_t totr; /* type of transpose read bitfield */
retval = base->DATA;
totr = (base->CTRL & CRC_CTRL_TOTR_MASK) >> CRC_CTRL_TOTR_SHIFT;
/* check transpose type to get 16-bit out of 32-bit register */
if (totr >= 2U)
{
/* transpose of bytes for read is set, the result CRC is in CRC_DATA[HU:HL] */
retval &= 0xFFFF0000U;
retval = retval >> 16U;
}
else
{
/* no transpose of bytes for read, the result CRC is in CRC_DATA[LU:LL] */
retval &= 0x0000FFFFU;
}
return (uint16_t)retval;
}

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017, 2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_CRC_H_
#define FSL_CRC_H_
#include "fsl_common.h"
/*!
* @addtogroup crc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief CRC driver version. Version 2.0.4.
*
* Current version: 2.0.4
*
* Change log:
*
* - Version 2.0.4
* - Release peripheral from reset if necessary in init function.
*
* - Version 2.0.3
* - Fix MISRA issues
*
* - Version 2.0.2
* - Fix MISRA issues
*
* - Version 2.0.1
* - move DATA and DATALL macro definition from header file to source file
*/
#define FSL_CRC_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
/*! @} */
#ifndef CRC_DRIVER_CUSTOM_DEFAULTS
/*! @brief Default configuration structure filled by CRC_GetDefaultConfig(). Use CRC16-CCIT-FALSE as defeault. */
#define CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT 1
#endif
/*! @brief CRC bit width */
typedef enum _crc_bits
{
kCrcBits16 = 0U, /*!< Generate 16-bit CRC code */
kCrcBits32 = 1U /*!< Generate 32-bit CRC code */
} crc_bits_t;
/*! @brief CRC result type */
typedef enum _crc_result
{
kCrcFinalChecksum = 0U, /*!< CRC data register read value is the final checksum.
Reflect out and final xor protocol features are applied. */
kCrcIntermediateChecksum = 1U /*!< CRC data register read value is intermediate checksum (raw value).
Reflect out and final xor protocol feature are not applied.
Intermediate checksum can be used as a seed for CRC_Init()
to continue adding data to this checksum. */
} crc_result_t;
/*!
* @brief CRC protocol configuration.
*
* This structure holds the configuration for the CRC protocol.
*
*/
typedef struct _crc_config
{
uint32_t polynomial; /*!< CRC Polynomial, MSBit first.
Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */
uint32_t seed; /*!< Starting checksum value */
bool reflectIn; /*!< Reflect bits on input. */
bool reflectOut; /*!< Reflect bits on output. */
bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */
crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */
crc_result_t crcResult; /*!< Selects final or intermediate checksum return from CRC_Get16bitResult() or
CRC_Get32bitResult() */
} crc_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Enables and configures the CRC peripheral module.
*
* This function enables the clock gate in the SIM module for the CRC peripheral.
* It also configures the CRC module and starts a checksum computation by writing the seed.
*
* @param base CRC peripheral address.
* @param config CRC module configuration structure.
*/
void CRC_Init(CRC_Type *base, const crc_config_t *config);
/*!
* @brief Disables the CRC peripheral module.
*
* This function disables the clock gate in the SIM module for the CRC peripheral.
*
* @param base CRC peripheral address.
*/
static inline void CRC_Deinit(CRC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* gate clock */
CLOCK_DisableClock(kCLOCK_Crc0);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* @brief Loads default values to the CRC protocol configuration structure.
*
* Loads default values to the CRC protocol configuration structure. The default values are as follows.
* @code
* config->polynomial = 0x1021;
* config->seed = 0xFFFF;
* config->reflectIn = false;
* config->reflectOut = false;
* config->complementChecksum = false;
* config->crcBits = kCrcBits16;
* config->crcResult = kCrcFinalChecksum;
* @endcode
*
* @param config CRC protocol configuration structure.
*/
void CRC_GetDefaultConfig(crc_config_t *config);
/*!
* @brief Writes data to the CRC module.
*
* Writes input data buffer bytes to the CRC data register.
* The configured type of transpose is applied.
*
* @param base CRC peripheral address.
* @param data Input data stream, MSByte in data[0].
* @param dataSize Size in bytes of the input data buffer.
*/
void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize);
/*!
* @brief Reads the 32-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* @param base CRC peripheral address.
* @return An intermediate or the final 32-bit checksum, after configured transpose and complement operations.
*/
uint32_t CRC_Get32bitResult(CRC_Type *base);
/*!
* @brief Reads a 16-bit checksum from the CRC module.
*
* Reads the CRC data register (either an intermediate or the final checksum).
* The configured type of transpose and complement is applied.
*
* @param base CRC peripheral address.
* @return An intermediate or the final 16-bit checksum, after configured transpose and complement operations.
*/
uint16_t CRC_Get16bitResult(CRC_Type *base);
#if defined(__cplusplus)
}
#endif
/*!
*@}
*/
#endif /* FSL_CRC_H_ */

View File

@ -0,0 +1,604 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_ctimer.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.ctimer"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address
*
* @param base Ctimer peripheral base address
*
* @return The Timer instance
*/
static uint32_t CTIMER_GetInstance(CTIMER_Type *base);
/*!
* @brief CTIMER generic IRQ handle function.
*
* @param index FlexCAN peripheral instance index.
*/
static void CTIMER_GenericIRQHandler(uint32_t index);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to Timer bases for each instance. */
static CTIMER_Type *const s_ctimerBases[] = CTIMER_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to Timer clocks for each instance. */
static const clock_ip_name_t s_ctimerClocks[] = CTIMER_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_RESET) && (FSL_FEATURE_CTIMER_HAS_NO_RESET))
#if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
#if defined(FSL_FEATURE_CTIMER_WRITE_ZERO_ASSERT_RESET) && FSL_FEATURE_CTIMER_WRITE_ZERO_ASSERT_RESET
/*! @brief Pointers to Timer resets for each instance, writing a zero asserts the reset */
static const reset_ip_name_t s_ctimerResets[] = CTIMER_RSTS_N;
#else
/*! @brief Pointers to Timer resets for each instance, writing a one asserts the reset */
static const reset_ip_name_t s_ctimerResets[] = CTIMER_RSTS;
#endif
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
/*! @brief Pointers real ISRs installed by drivers for each instance. */
static ctimer_callback_t *s_ctimerCallback[sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0])] = {0};
/*! @brief Callback type installed by drivers for each instance. */
static ctimer_callback_type_t ctimerCallbackType[sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0])] = {
kCTIMER_SingleCallback};
/*! @brief Array to map timer instance to IRQ number. */
static const IRQn_Type s_ctimerIRQ[] = CTIMER_IRQS;
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t CTIMER_GetInstance(CTIMER_Type *base)
{
uint32_t instance;
uint32_t ctimerArrayCount = (sizeof(s_ctimerBases) / sizeof(s_ctimerBases[0]));
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ctimerArrayCount; instance++)
{
if (s_ctimerBases[instance] == base)
{
break;
}
}
assert(instance < ctimerArrayCount);
return instance;
}
/*!
* brief Ungates the clock and configures the peripheral for basic operation.
*
* note This API should be called at the beginning of the application before using the driver.
*
* param base Ctimer peripheral base address
* param config Pointer to the user configuration structure.
*/
void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config)
{
assert(config != NULL);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the timer clock*/
CLOCK_EnableClock(s_ctimerClocks[CTIMER_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
/* Reset the module. */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_RESET) && (FSL_FEATURE_CTIMER_HAS_NO_RESET))
RESET_PeripheralReset(s_ctimerResets[CTIMER_GetInstance(base)]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
/* Setup the cimer mode and count select */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
base->CTCR = CTIMER_CTCR_CTMODE(config->mode) | CTIMER_CTCR_CINSEL(config->input);
#endif
/* Setup the timer prescale value */
base->PR = CTIMER_PR_PRVAL(config->prescale);
}
/*!
* brief Gates the timer clock.
*
* param base Ctimer peripheral base address
*/
void CTIMER_Deinit(CTIMER_Type *base)
{
uint32_t index = CTIMER_GetInstance(base);
/* Stop the timer */
base->TCR &= ~CTIMER_TCR_CEN_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the timer clock*/
CLOCK_DisableClock(s_ctimerClocks[index]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Disable IRQ at NVIC Level */
(void)DisableIRQ(s_ctimerIRQ[index]);
}
/*!
* brief Fills in the timers configuration structure with the default settings.
*
* The default values are:
* code
* config->mode = kCTIMER_TimerMode;
* config->input = kCTIMER_Capture_0;
* config->prescale = 0;
* endcode
* param config Pointer to the user configuration structure.
*/
void CTIMER_GetDefaultConfig(ctimer_config_t *config)
{
assert(config != NULL);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
/* Run as a timer */
config->mode = kCTIMER_TimerMode;
/* This field is ignored when mode is timer */
config->input = kCTIMER_Capture_0;
/* Timer counter is incremented on every APB bus clock */
config->prescale = 0;
}
/*!
* brief Configures the PWM signal parameters.
*
* Enables PWM mode on the match channel passed in and will then setup the match value
* and other match parameters to generate a PWM signal.
* This function can manually assign the specified channel to set the PWM cycle.
*
* note When setting PWM output from multiple output pins, all should use the same PWM
* frequency. Please use CTIMER_SetupPwmPeriod to set up the PWM with high resolution.
*
* param base Ctimer peripheral base address
* param pwmPeriodChannel Specify the channel to control the PWM period
* param matchChannel Match pin to be used to output the PWM signal
* param dutyCyclePercent PWM pulse width; the value should be between 0 to 100
* param pwmFreq_Hz PWM signal frequency in Hz
* param srcClock_Hz Timer counter clock in Hz
* param enableInt Enable interrupt when the timer value reaches the match value of the PWM pulse,
* if it is 0 then no interrupt will be generated.
*
* return kStatus_Success on success
* kStatus_Fail If matchChannel is equal to pwmPeriodChannel; this channel is reserved to set the PWM cycle
*/
status_t CTIMER_SetupPwm(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint8_t dutyCyclePercent,
uint32_t pwmFreq_Hz,
uint32_t srcClock_Hz,
bool enableInt)
{
assert(pwmFreq_Hz > 0U);
uint32_t reg;
uint32_t period, pulsePeriod = 0;
uint32_t timerClock = srcClock_Hz / (base->PR + 1U);
uint32_t index = CTIMER_GetInstance(base);
if (matchChannel == pwmPeriodChannel)
{
return kStatus_Fail;
}
/* Enable PWM mode on the match channel */
base->PWMC |= (1UL << (uint32_t)matchChannel);
/* Clear the stop, reset and interrupt bits for this channel */
reg = base->MCR;
reg &=
~(((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK))
<< ((uint32_t)matchChannel * 3U));
/* If call back function is valid then enable match interrupt for the channel */
if (enableInt)
{
reg |= (((uint32_t)CTIMER_MCR_MR0I_MASK) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
}
/* Reset the counter when match on PWM period channel (pwmPeriodChannel) */
reg |= ((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK) << ((uint32_t)pwmPeriodChannel * 3U));
base->MCR = reg;
/* Calculate PWM period match value */
period = (timerClock / pwmFreq_Hz) - 1U;
/* Calculate pulse width match value */
if (dutyCyclePercent == 0U)
{
pulsePeriod = period + 1U;
}
else
{
pulsePeriod = (period * (100U - (uint32_t)dutyCyclePercent)) / 100U;
}
/* Specified channel pwmPeriodChannel will define the PWM period */
base->MR[pwmPeriodChannel] = period;
/* This will define the PWM pulse period */
base->MR[matchChannel] = pulsePeriod;
/* Clear status flags */
CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
/* If call back function is valid then enable interrupt and update the call back function */
if (enableInt)
{
(void)EnableIRQ(s_ctimerIRQ[index]);
}
return kStatus_Success;
}
/*!
* brief Configures the PWM signal parameters.
*
* Enables PWM mode on the match channel passed in and will then setup the match value
* and other match parameters to generate a PWM signal.
* This function can manually assign the specified channel to set the PWM cycle.
*
* note When setting PWM output from multiple output pins, all should use the same PWM
* period
*
* param base Ctimer peripheral base address
* param pwmPeriodChannel Specify the channel to control the PWM period
* param matchChannel Match pin to be used to output the PWM signal
* param pwmPeriod PWM period match value
* param pulsePeriod Pulse width match value
* param enableInt Enable interrupt when the timer value reaches the match value of the PWM pulse,
* if it is 0 then no interrupt will be generated.
*
* return kStatus_Success on success
* kStatus_Fail If matchChannel is equal to pwmPeriodChannel; this channel is reserved to set the PWM period
*/
status_t CTIMER_SetupPwmPeriod(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint32_t pwmPeriod,
uint32_t pulsePeriod,
bool enableInt)
{
/* Some CTimers only have 16bits , so the value is limited*/
#if defined(FSL_FEATURE_SOC_CTIMER16B) && FSL_FEATURE_SOC_CTIMER16B
assert(!((FSL_FEATURE_CTIMER_BIT_SIZEn(base) < 32) && (pulsePeriod > 0xFFFFU)));
#endif
uint32_t reg;
uint32_t index = CTIMER_GetInstance(base);
if (matchChannel == pwmPeriodChannel)
{
return kStatus_Fail;
}
/* Enable PWM mode on PWM pulse channel */
base->PWMC |= (1UL << (uint32_t)matchChannel);
/* Clear the stop, reset and interrupt bits for PWM pulse channel */
reg = base->MCR;
reg &=
~((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK)
<< ((uint32_t)matchChannel * 3U));
/* If call back function is valid then enable match interrupt for PWM pulse channel */
if (enableInt)
{
reg |= (((uint32_t)CTIMER_MCR_MR0I_MASK) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
}
/* Reset the counter when match on PWM period channel (pwmPeriodChannel) */
reg |= ((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK) << ((uint32_t)pwmPeriodChannel * 3U));
base->MCR = reg;
/* Specified channel pwmPeriodChannel will define the PWM period */
base->MR[pwmPeriodChannel] = pwmPeriod;
/* This will define the PWM pulse period */
base->MR[matchChannel] = pulsePeriod;
/* Clear status flags */
CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
/* If call back function is valid then enable interrupt and update the call back function */
if (enableInt)
{
(void)EnableIRQ(s_ctimerIRQ[index]);
}
return kStatus_Success;
}
/*!
* brief Updates the duty cycle of an active PWM signal.
*
* note Please use CTIMER_SetupPwmPeriod to update the PWM with high resolution.
* This function can manually assign the specified channel to set the PWM cycle.
*
* param base Ctimer peripheral base address
* param pwmPeriodChannel Specify the channel to control the PWM period
* param matchChannel Match pin to be used to output the PWM signal
* param dutyCyclePercent New PWM pulse width; the value should be between 0 to 100
*/
void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint8_t dutyCyclePercent)
{
uint32_t pulsePeriod = 0, period;
/* Specified channel pwmPeriodChannel defines the PWM period */
period = base->MR[pwmPeriodChannel];
/* For 0% dutycyle, make pulse period greater than period so the event will never occur */
if (dutyCyclePercent == 0U)
{
pulsePeriod = period + 1U;
}
else
{
pulsePeriod = (period * (100U - (uint32_t)dutyCyclePercent)) / 100U;
}
/* Update dutycycle */
base->MR[matchChannel] = pulsePeriod;
}
/*!
* brief Setup the match register.
*
* User configuration is used to setup the match value and action to be taken when a match occurs.
*
* param base Ctimer peripheral base address
* param matchChannel Match register to configure
* param config Pointer to the match configuration structure
*/
void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config)
{
/* Some CTimers only have 16bits , so the value is limited*/
#if defined(FSL_FEATURE_SOC_CTIMER16B) && FSL_FEATURE_SOC_CTIMER16B
assert(!(FSL_FEATURE_CTIMER_BIT_SIZEn(base) < 32 && config->matchValue > 0xFFFFU));
#endif
uint32_t reg;
uint32_t index = CTIMER_GetInstance(base);
/* Set the counter operation when a match on this channel occurs */
reg = base->MCR;
reg &=
~((uint32_t)((uint32_t)CTIMER_MCR_MR0R_MASK | (uint32_t)CTIMER_MCR_MR0S_MASK | (uint32_t)CTIMER_MCR_MR0I_MASK)
<< ((uint32_t)matchChannel * 3U));
reg |= ((uint32_t)(config->enableCounterReset) << (CTIMER_MCR_MR0R_SHIFT + ((uint32_t)matchChannel * 3U)));
reg |= ((uint32_t)(config->enableCounterStop) << (CTIMER_MCR_MR0S_SHIFT + ((uint32_t)matchChannel * 3U)));
reg |= ((uint32_t)(config->enableInterrupt) << (CTIMER_MCR_MR0I_SHIFT + ((uint32_t)matchChannel * 3U)));
base->MCR = reg;
reg = base->EMR;
/* Set the match output operation when a match on this channel occurs */
reg &= ~(((uint32_t)CTIMER_EMR_EMC0_MASK) << ((uint32_t)matchChannel * 2U));
reg |= ((uint32_t)config->outControl) << (CTIMER_EMR_EMC0_SHIFT + ((uint32_t)matchChannel * 2U));
/* Set the initial state of the EM bit/output */
reg &= ~(((uint32_t)CTIMER_EMR_EM0_MASK) << (uint32_t)matchChannel);
reg |= ((uint32_t)config->outPinInitState) << (uint32_t)matchChannel;
base->EMR = reg;
/* Set the match value */
base->MR[matchChannel] = config->matchValue;
/* Clear status flags */
CTIMER_ClearStatusFlags(base, ((uint32_t)CTIMER_IR_MR0INT_MASK) << (uint32_t)matchChannel);
/* If interrupt is enabled then enable interrupt and update the call back function */
if (config->enableInterrupt)
{
(void)EnableIRQ(s_ctimerIRQ[index]);
}
}
/*!
* brief Get the status of output match.
*
* This function gets the status of output MAT, whether or not this output is connected to a pin.
* This status is driven to the MAT pins if the match function is selected via IOCON. 0 = LOW. 1 = HIGH.
*
* param base Ctimer peripheral base address
* param matchChannel External match channel, user can obtain the status of multiple match channels
* at the same time by using the logic of "|"
* enumeration ::ctimer_external_match_t
* return The mask of external match channel status flags. Users need to use the
* _ctimer_external_match type to decode the return variables.
*/
uint32_t CTIMER_GetOutputMatchStatus(CTIMER_Type *base, uint32_t matchChannel)
{
return (base->EMR & matchChannel);
}
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
/*!
* brief Setup the capture.
*
* param base Ctimer peripheral base address
* param capture Capture channel to configure
* param edge Edge on the channel that will trigger a capture
* param enableInt Flag to enable channel interrupts, if enabled then the registered call back
* is called upon capture
*/
void CTIMER_SetupCapture(CTIMER_Type *base,
ctimer_capture_channel_t capture,
ctimer_capture_edge_t edge,
bool enableInt)
{
uint32_t reg = base->CCR;
uint32_t index = CTIMER_GetInstance(base);
/* Set the capture edge */
reg &= ~((uint32_t)((uint32_t)CTIMER_CCR_CAP0RE_MASK | (uint32_t)CTIMER_CCR_CAP0FE_MASK |
(uint32_t)CTIMER_CCR_CAP0I_MASK)
<< ((uint32_t)capture * 3U));
reg |= ((uint32_t)edge) << (CTIMER_CCR_CAP0RE_SHIFT + ((uint32_t)capture * 3U));
/* Clear status flags */
CTIMER_ClearStatusFlags(base, (((uint32_t)kCTIMER_Capture0Flag) << (uint32_t)capture));
/* If call back function is valid then enable capture interrupt for the channel and update the call back function */
if (enableInt)
{
reg |= ((uint32_t)CTIMER_CCR_CAP0I_MASK) << ((uint32_t)capture * 3U);
(void)EnableIRQ(s_ctimerIRQ[index]);
}
base->CCR = reg;
}
#endif
/*!
* brief Register callback.
*
* param base Ctimer peripheral base address
* param cb_func callback function
* param cb_type callback function type, singular or multiple
*/
void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type)
{
uint32_t index = CTIMER_GetInstance(base);
s_ctimerCallback[index] = cb_func;
ctimerCallbackType[index] = cb_type;
}
/*!
* brief CTIMER generic IRQ handle function.
*
* param index FlexCAN peripheral instance index.
*/
static void CTIMER_GenericIRQHandler(uint32_t index)
{
uint32_t int_stat, i, mask;
/* Get Interrupt status flags */
int_stat = CTIMER_GetStatusFlags(s_ctimerBases[index]);
/* Clear the status flags that were set */
CTIMER_ClearStatusFlags(s_ctimerBases[index], int_stat);
if (ctimerCallbackType[index] == kCTIMER_SingleCallback)
{
if (s_ctimerCallback[index][0] != NULL)
{
s_ctimerCallback[index][0](int_stat);
}
}
else
{
#if defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE
for (i = 0; i <= CTIMER_IR_MR3INT_SHIFT; i++)
#else
#if defined(FSL_FEATURE_CTIMER_HAS_IR_CR3INT) && FSL_FEATURE_CTIMER_HAS_IR_CR3INT
for (i = 0; i <= CTIMER_IR_CR3INT_SHIFT; i++)
#else
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT) && FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT)
for (i = 0; i <= CTIMER_IR_CR2INT_SHIFT; i++)
#else
for (i = 0; i <= CTIMER_IR_CR1INT_SHIFT; i++)
#endif /* FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT */
#endif /* FSL_FEATURE_CTIMER_HAS_IR_CR3INT */
#endif
{
mask = 0x01UL << i;
/* For each status flag bit that was set call the callback function if it is valid */
if (((int_stat & mask) != 0U) && (s_ctimerCallback[index][i] != NULL))
{
s_ctimerCallback[index][i](int_stat);
}
}
}
SDK_ISR_EXIT_BARRIER;
}
/* IRQ handler functions overloading weak symbols in the startup */
#if defined(CTIMER0)
void CTIMER0_DriverIRQHandler(void);
void CTIMER0_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(0);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER1)
void CTIMER1_DriverIRQHandler(void);
void CTIMER1_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(1);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER2)
void CTIMER2_DriverIRQHandler(void);
void CTIMER2_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(2);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER3)
void CTIMER3_DriverIRQHandler(void);
void CTIMER3_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(3);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER4)
void CTIMER4_DriverIRQHandler(void);
void CTIMER4_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(4);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER5)
void CTIMER5_DriverIRQHandler(void);
void CTIMER5_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(5);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER6)
void CTIMER6_DriverIRQHandler(void);
void CTIMER6_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(6);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(CTIMER7)
void CTIMER7_DriverIRQHandler(void);
void CTIMER7_DriverIRQHandler(void)
{
CTIMER_GenericIRQHandler(7);
SDK_ISR_EXIT_BARRIER;
}
#endif

View File

@ -0,0 +1,682 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_CTIMER_H_
#define FSL_CTIMER_H_
#include "fsl_common.h"
/*!
* @addtogroup ctimer
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
#define FSL_CTIMER_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*!< Version 2.3.1 */
/*! @} */
/*! @brief List of Timer capture channels */
typedef enum _ctimer_capture_channel
{
kCTIMER_Capture_0 = 0U, /*!< Timer capture channel 0 */
kCTIMER_Capture_1, /*!< Timer capture channel 1 */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2) && FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2)
kCTIMER_Capture_2, /*!< Timer capture channel 2 */
#endif /* FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
kCTIMER_Capture_3 /*!< Timer capture channel 3 */
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
} ctimer_capture_channel_t;
/*! @brief List of capture edge options */
typedef enum _ctimer_capture_edge
{
kCTIMER_Capture_RiseEdge = 1U, /*!< Capture on rising edge */
kCTIMER_Capture_FallEdge = 2U, /*!< Capture on falling edge */
kCTIMER_Capture_BothEdge = 3U, /*!< Capture on rising and falling edge */
} ctimer_capture_edge_t;
/*! @brief List of Timer match registers */
typedef enum _ctimer_match
{
kCTIMER_Match_0 = 0U, /*!< Timer match register 0 */
kCTIMER_Match_1, /*!< Timer match register 1 */
kCTIMER_Match_2, /*!< Timer match register 2 */
kCTIMER_Match_3 /*!< Timer match register 3 */
} ctimer_match_t;
/*! @brief List of external match */
typedef enum _ctimer_external_match
{
kCTIMER_External_Match_0 = (1UL << 0), /*!< External match 0 */
kCTIMER_External_Match_1 = (1UL << 1), /*!< External match 1 */
kCTIMER_External_Match_2 = (1UL << 2), /*!< External match 2 */
kCTIMER_External_Match_3 = (1UL << 3) /*!< External match 3 */
} ctimer_external_match_t;
/*! @brief List of output control options */
typedef enum _ctimer_match_output_control
{
kCTIMER_Output_NoAction = 0U, /*!< No action is taken */
kCTIMER_Output_Clear, /*!< Clear the EM bit/output to 0 */
kCTIMER_Output_Set, /*!< Set the EM bit/output to 1 */
kCTIMER_Output_Toggle /*!< Toggle the EM bit/output */
} ctimer_match_output_control_t;
/*! @brief List of Timer modes */
typedef enum _ctimer_timer_mode
{
kCTIMER_TimerMode = 0U, /* TC is incremented every rising APB bus clock edge */
kCTIMER_IncreaseOnRiseEdge, /* TC is incremented on rising edge of input signal */
kCTIMER_IncreaseOnFallEdge, /* TC is incremented on falling edge of input signal */
kCTIMER_IncreaseOnBothEdge /* TC is incremented on both edges of input signal */
} ctimer_timer_mode_t;
/*! @brief List of Timer interrupts */
typedef enum _ctimer_interrupt_enable
{
kCTIMER_Match0InterruptEnable = CTIMER_MCR_MR0I_MASK, /*!< Match 0 interrupt */
kCTIMER_Match1InterruptEnable = CTIMER_MCR_MR1I_MASK, /*!< Match 1 interrupt */
kCTIMER_Match2InterruptEnable = CTIMER_MCR_MR2I_MASK, /*!< Match 2 interrupt */
kCTIMER_Match3InterruptEnable = CTIMER_MCR_MR3I_MASK, /*!< Match 3 interrupt */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
kCTIMER_Capture0InterruptEnable = CTIMER_CCR_CAP0I_MASK, /*!< Capture 0 interrupt */
kCTIMER_Capture1InterruptEnable = CTIMER_CCR_CAP1I_MASK, /*!< Capture 1 interrupt */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2) && FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2)
kCTIMER_Capture2InterruptEnable = CTIMER_CCR_CAP2I_MASK, /*!< Capture 2 interrupt */
#endif /* FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
kCTIMER_Capture3InterruptEnable = CTIMER_CCR_CAP3I_MASK, /*!< Capture 3 interrupt */
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
#endif
} ctimer_interrupt_enable_t;
/*! @brief List of Timer flags */
typedef enum _ctimer_status_flags
{
kCTIMER_Match0Flag = CTIMER_IR_MR0INT_MASK, /*!< Match 0 interrupt flag */
kCTIMER_Match1Flag = CTIMER_IR_MR1INT_MASK, /*!< Match 1 interrupt flag */
kCTIMER_Match2Flag = CTIMER_IR_MR2INT_MASK, /*!< Match 2 interrupt flag */
kCTIMER_Match3Flag = CTIMER_IR_MR3INT_MASK, /*!< Match 3 interrupt flag */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
kCTIMER_Capture0Flag = CTIMER_IR_CR0INT_MASK, /*!< Capture 0 interrupt flag */
kCTIMER_Capture1Flag = CTIMER_IR_CR1INT_MASK, /*!< Capture 1 interrupt flag */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT) && FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT)
kCTIMER_Capture2Flag = CTIMER_IR_CR2INT_MASK, /*!< Capture 2 interrupt flag */
#endif /* FSL_FEATURE_CTIMER_HAS_NO_IR_CR2INT */
#if defined(FSL_FEATURE_CTIMER_HAS_IR_CR3INT) && FSL_FEATURE_CTIMER_HAS_IR_CR3INT
kCTIMER_Capture3Flag = CTIMER_IR_CR3INT_MASK, /*!< Capture 3 interrupt flag */
#endif /* FSL_FEATURE_CTIMER_HAS_IR_CR3INT */
#endif
} ctimer_status_flags_t;
typedef void (*ctimer_callback_t)(uint32_t flags);
/*! @brief Callback type when registering for a callback. When registering a callback
* an array of function pointers is passed the size could be 1 or 8, the callback
* type will tell that.
*/
typedef enum
{
kCTIMER_SingleCallback, /*!< Single Callback type where there is only one callback for the timer.
based on the status flags different channels needs to be handled differently */
kCTIMER_MultipleCallback /*!< Multiple Callback type where there can be 8 valid callbacks, one per channel.
for both match/capture */
} ctimer_callback_type_t;
/*!
* @brief Match configuration
*
* This structure holds the configuration settings for each match register.
*/
typedef struct _ctimer_match_config
{
uint32_t matchValue; /*!< This is stored in the match register */
bool enableCounterReset; /*!< true: Match will reset the counter
false: Match will not reser the counter */
bool enableCounterStop; /*!< true: Match will stop the counter
false: Match will not stop the counter */
ctimer_match_output_control_t outControl; /*!< Action to be taken on a match on the EM bit/output */
bool outPinInitState; /*!< Initial value of the EM bit/output */
bool enableInterrupt; /*!< true: Generate interrupt upon match
false: Do not generate interrupt on match */
} ctimer_match_config_t;
/*!
* @brief Timer configuration structure
*
* This structure holds the configuration settings for the Timer peripheral. To initialize this
* structure to reasonable defaults, call the CTIMER_GetDefaultConfig() function and pass a
* pointer to the configuration structure instance.
*
* The configuration structure can be made constant so as to reside in flash.
*/
typedef struct _ctimer_config
{
ctimer_timer_mode_t mode; /*!< Timer mode */
ctimer_capture_channel_t input; /*!< Input channel to increment the timer, used only in timer
modes that rely on this input signal to increment TC */
uint32_t prescale; /*!< Prescale value */
} ctimer_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the clock and configures the peripheral for basic operation.
*
* @note This API should be called at the beginning of the application before using the driver.
*
* @param base Ctimer peripheral base address
* @param config Pointer to the user configuration structure.
*/
void CTIMER_Init(CTIMER_Type *base, const ctimer_config_t *config);
/*!
* @brief Gates the timer clock.
*
* @param base Ctimer peripheral base address
*/
void CTIMER_Deinit(CTIMER_Type *base);
/*!
* @brief Fills in the timers configuration structure with the default settings.
*
* The default values are:
* @code
* config->mode = kCTIMER_TimerMode;
* config->input = kCTIMER_Capture_0;
* config->prescale = 0;
* @endcode
* @param config Pointer to the user configuration structure.
*/
void CTIMER_GetDefaultConfig(ctimer_config_t *config);
/*! @}*/
/*!
* @name PWM setup operations
* @{
*/
/*!
* @brief Configures the PWM signal parameters.
*
* Enables PWM mode on the match channel passed in and will then setup the match value
* and other match parameters to generate a PWM signal.
* This function can manually assign the specified channel to set the PWM cycle.
*
* @note When setting PWM output from multiple output pins, all should use the same PWM
* period
*
* @param base Ctimer peripheral base address
* @param pwmPeriodChannel Specify the channel to control the PWM period
* @param matchChannel Match pin to be used to output the PWM signal
* @param pwmPeriod PWM period match value
* @param pulsePeriod Pulse width match value
* @param enableInt Enable interrupt when the timer value reaches the match value of the PWM pulse,
* if it is 0 then no interrupt will be generated.
*/
status_t CTIMER_SetupPwmPeriod(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint32_t pwmPeriod,
uint32_t pulsePeriod,
bool enableInt);
/*!
* @brief Configures the PWM signal parameters.
*
* Enables PWM mode on the match channel passed in and will then setup the match value
* and other match parameters to generate a PWM signal.
* This function can manually assign the specified channel to set the PWM cycle.
*
* @note When setting PWM output from multiple output pins, all should use the same PWM
* frequency. Please use CTIMER_SetupPwmPeriod to set up the PWM with high resolution.
*
* @param base Ctimer peripheral base address
* @param pwmPeriodChannel Specify the channel to control the PWM period
* @param matchChannel Match pin to be used to output the PWM signal
* @param dutyCyclePercent PWM pulse width; the value should be between 0 to 100
* @param pwmFreq_Hz PWM signal frequency in Hz
* @param srcClock_Hz Timer counter clock in Hz
* @param enableInt Enable interrupt when the timer value reaches the match value of the PWM pulse,
* if it is 0 then no interrupt will be generated.
*/
status_t CTIMER_SetupPwm(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint8_t dutyCyclePercent,
uint32_t pwmFreq_Hz,
uint32_t srcClock_Hz,
bool enableInt);
/*!
* @brief Updates the pulse period of an active PWM signal.
*
* @param base Ctimer peripheral base address
* @param matchChannel Match pin to be used to output the PWM signal
* @param pulsePeriod New PWM pulse width match value
*/
static inline void CTIMER_UpdatePwmPulsePeriod(CTIMER_Type *base, ctimer_match_t matchChannel, uint32_t pulsePeriod)
{
/* Update PWM pulse period match value */
base->MR[matchChannel] = pulsePeriod;
}
/*!
* @brief Updates the duty cycle of an active PWM signal.
*
* @note Please use CTIMER_SetupPwmPeriod to update the PWM with high resolution.
* This function can manually assign the specified channel to set the PWM cycle.
*
* @param base Ctimer peripheral base address
* @param pwmPeriodChannel Specify the channel to control the PWM period
* @param matchChannel Match pin to be used to output the PWM signal
* @param dutyCyclePercent New PWM pulse width; the value should be between 0 to 100
*/
void CTIMER_UpdatePwmDutycycle(CTIMER_Type *base,
const ctimer_match_t pwmPeriodChannel,
ctimer_match_t matchChannel,
uint8_t dutyCyclePercent);
/*! @}*/
/*!
* @brief Setup the match register.
*
* User configuration is used to setup the match value and action to be taken when a match occurs.
*
* @param base Ctimer peripheral base address
* @param matchChannel Match register to configure
* @param config Pointer to the match configuration structure
*/
void CTIMER_SetupMatch(CTIMER_Type *base, ctimer_match_t matchChannel, const ctimer_match_config_t *config);
/*!
* @brief Get the status of output match.
*
* This function gets the status of output MAT, whether or not this output is connected to a pin.
* This status is driven to the MAT pins if the match function is selected via IOCON. 0 = LOW. 1 = HIGH.
*
* @param base Ctimer peripheral base address
* @param matchChannel External match channel, user can obtain the status of multiple match channels
* at the same time by using the logic of "|"
* enumeration ::ctimer_external_match_t
* @return The mask of external match channel status flags. Users need to use the
* _ctimer_external_match type to decode the return variables.
*/
uint32_t CTIMER_GetOutputMatchStatus(CTIMER_Type *base, uint32_t matchChannel);
/*!
* @brief Setup the capture.
*
* @param base Ctimer peripheral base address
* @param capture Capture channel to configure
* @param edge Edge on the channel that will trigger a capture
* @param enableInt Flag to enable channel interrupts, if enabled then the registered call back
* is called upon capture
*/
void CTIMER_SetupCapture(CTIMER_Type *base,
ctimer_capture_channel_t capture,
ctimer_capture_edge_t edge,
bool enableInt);
/*!
* @brief Get the timer count value from TC register.
*
* @param base Ctimer peripheral base address.
* @return return the timer count value.
*/
static inline uint32_t CTIMER_GetTimerCountValue(CTIMER_Type *base)
{
return (base->TC);
}
/*!
* @brief Register callback.
*
* @param base Ctimer peripheral base address
* @param cb_func callback function
* @param cb_type callback function type, singular or multiple
*/
void CTIMER_RegisterCallBack(CTIMER_Type *base, ctimer_callback_t *cb_func, ctimer_callback_type_t cb_type);
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected Timer interrupts.
*
* @param base Ctimer peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::ctimer_interrupt_enable_t
*/
static inline void CTIMER_EnableInterrupts(CTIMER_Type *base, uint32_t mask)
{
/* Enable match interrupts */
base->MCR |= mask & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK);
/* Enable capture interrupts */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
base->CCR |= mask & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2) && FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2)
| CTIMER_CCR_CAP2I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
| CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
);
#endif
}
/*!
* @brief Disables the selected Timer interrupts.
*
* @param base Ctimer peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::ctimer_interrupt_enable_t
*/
static inline void CTIMER_DisableInterrupts(CTIMER_Type *base, uint32_t mask)
{
/* Disable match interrupts */
base->MCR &= ~(mask & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK));
/* Disable capture interrupts */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
base->CCR &= ~(mask & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2) && FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2)
| CTIMER_CCR_CAP2I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
| CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
));
#endif
}
/*!
* @brief Gets the enabled Timer interrupts.
*
* @param base Ctimer peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::ctimer_interrupt_enable_t
*/
static inline uint32_t CTIMER_GetEnabledInterrupts(CTIMER_Type *base)
{
uint32_t enabledIntrs = 0;
/* Get all the match interrupts enabled */
enabledIntrs =
base->MCR & (CTIMER_MCR_MR0I_MASK | CTIMER_MCR_MR1I_MASK | CTIMER_MCR_MR2I_MASK | CTIMER_MCR_MR3I_MASK);
/* Get all the capture interrupts enabled */
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE) && (FSL_FEATURE_CTIMER_HAS_NO_INPUT_CAPTURE))
enabledIntrs |= base->CCR & (CTIMER_CCR_CAP0I_MASK | CTIMER_CCR_CAP1I_MASK
#if !(defined(FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2) && FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2)
| CTIMER_CCR_CAP2I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_NO_CCR_CAP2 */
#if defined(FSL_FEATURE_CTIMER_HAS_CCR_CAP3) && FSL_FEATURE_CTIMER_HAS_CCR_CAP3
| CTIMER_CCR_CAP3I_MASK
#endif /* FSL_FEATURE_CTIMER_HAS_CCR_CAP3 */
);
#endif
return enabledIntrs;
}
/*! @}*/
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the Timer status flags.
*
* @param base Ctimer peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::ctimer_status_flags_t
*/
static inline uint32_t CTIMER_GetStatusFlags(CTIMER_Type *base)
{
return base->IR;
}
/*!
* @brief Clears the Timer status flags.
*
* @param base Ctimer peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::ctimer_status_flags_t
*/
static inline void CTIMER_ClearStatusFlags(CTIMER_Type *base, uint32_t mask)
{
base->IR = mask;
}
/*! @}*/
/*!
* @name Counter Start and Stop
* @{
*/
/*!
* @brief Starts the Timer counter.
*
* @param base Ctimer peripheral base address
*/
static inline void CTIMER_StartTimer(CTIMER_Type *base)
{
base->TCR |= CTIMER_TCR_CEN_MASK;
}
/*!
* @brief Stops the Timer counter.
*
* @param base Ctimer peripheral base address
*/
static inline void CTIMER_StopTimer(CTIMER_Type *base)
{
base->TCR &= ~CTIMER_TCR_CEN_MASK;
}
/*! @}*/
/*!
* @brief Reset the counter.
*
* The timer counter and prescale counter are reset on the next positive edge of the APB clock.
*
* @param base Ctimer peripheral base address
*/
static inline void CTIMER_Reset(CTIMER_Type *base)
{
base->TCR |= CTIMER_TCR_CRST_MASK;
base->TCR &= ~CTIMER_TCR_CRST_MASK;
}
/*!
* @brief Setup the timer prescale value.
*
* Specifies the maximum value for the Prescale Counter.
*
* @param base Ctimer peripheral base address
* @param prescale Prescale value
*/
static inline void CTIMER_SetPrescale(CTIMER_Type *base, uint32_t prescale)
{
base->PR = CTIMER_PR_PRVAL(prescale);
}
/*!
* @brief Get capture channel value.
*
* Get the counter/timer value on the corresponding capture channel.
*
* @param base Ctimer peripheral base address
* @param capture Select capture channel
*
* @return The timer count capture value.
*/
static inline uint32_t CTIMER_GetCaptureValue(CTIMER_Type *base, ctimer_capture_channel_t capture)
{
return base->CR[capture];
}
/*!
* @brief Enable reset match channel.
*
* Set the specified match channel reset operation.
*
* @param base Ctimer peripheral base address
* @param match match channel used
* @param enable Enable match channel reset operation.
*/
static inline void CTIMER_EnableResetMatchChannel(CTIMER_Type *base, ctimer_match_t match, bool enable)
{
if (enable)
{
base->MCR |= (1UL << (CTIMER_MCR_MR0R_SHIFT + ((uint32_t)match * 3U)));
}
else
{
base->MCR &= ~(1UL << (CTIMER_MCR_MR0R_SHIFT + ((uint32_t)match * 3U)));
}
}
/*!
* @brief Enable stop match channel.
*
* Set the specified match channel stop operation.
*
* @param base Ctimer peripheral base address.
* @param match match channel used.
* @param enable Enable match channel stop operation.
*/
static inline void CTIMER_EnableStopMatchChannel(CTIMER_Type *base, ctimer_match_t match, bool enable)
{
if (enable)
{
base->MCR |= (1UL << (CTIMER_MCR_MR0S_SHIFT + ((uint32_t)match * 3U)));
}
else
{
base->MCR &= ~(1UL << (CTIMER_MCR_MR0S_SHIFT + ((uint32_t)match * 3U)));
}
}
#if (defined(FSL_FEATURE_CTIMER_HAS_MSR) && (FSL_FEATURE_CTIMER_HAS_MSR))
/*!
* @brief Enable reload channel falling edge.
*
* Enable the specified match channel reload match shadow value.
*
* @param base Ctimer peripheral base address.
* @param match match channel used.
* @param enable Enable .
*/
static inline void CTIMER_EnableMatchChannelReload(CTIMER_Type *base, ctimer_match_t match, bool enable)
{
if (enable)
{
base->MCR |= (1UL << (CTIMER_MCR_MR0RL_SHIFT + (uint32_t)match));
}
else
{
base->MCR &= ~(1UL << (CTIMER_MCR_MR0RL_SHIFT + (uint32_t)match));
}
}
#endif /* FSL_FEATURE_CTIMER_HAS_MSR */
/*!
* @brief Enable capture channel rising edge.
*
* Sets the specified capture channel for rising edge capture.
*
* @param base Ctimer peripheral base address.
* @param capture capture channel used.
* @param enable Enable rising edge capture.
*/
static inline void CTIMER_EnableRisingEdgeCapture(CTIMER_Type *base, ctimer_capture_channel_t capture, bool enable)
{
if (enable)
{
base->CCR |= (1UL << (CTIMER_CCR_CAP0RE_SHIFT + ((uint32_t)capture * 3U)));
}
else
{
base->CCR &= ~(1UL << (CTIMER_CCR_CAP0RE_SHIFT + ((uint32_t)capture * 3U)));
}
}
/*!
* @brief Enable capture channel falling edge.
*
* Sets the specified capture channel for falling edge capture.
*
* @param base Ctimer peripheral base address.
* @param capture capture channel used.
* @param enable Enable falling edge capture.
*/
static inline void CTIMER_EnableFallingEdgeCapture(CTIMER_Type *base, ctimer_capture_channel_t capture, bool enable)
{
if (enable)
{
base->CCR |= (1UL << (CTIMER_CCR_CAP0FE_SHIFT + ((uint32_t)capture * 3U)));
}
else
{
base->CCR &= ~(1UL << (CTIMER_CCR_CAP0FE_SHIFT + ((uint32_t)capture * 3U)));
}
}
#if (defined(FSL_FEATURE_CTIMER_HAS_MSR) && (FSL_FEATURE_CTIMER_HAS_MSR))
/*!
* @brief Set the specified match shadow channel.
*
* @param base Ctimer peripheral base address.
* @param match match channel used.
* @param matchvalue Reload the value of the corresponding match register.
*/
static inline void CTIMER_SetShadowValue(CTIMER_Type *base, ctimer_match_t match, uint32_t matchvalue)
{
base->MSR[match] = matchvalue;
}
#endif /* FSL_FEATURE_CTIMER_HAS_MSR */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_CTIMER_H_ */

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_dac.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.dac_1"
#endif
#if defined(DAC_RSTS)
#define DAC_RESETS_ARRAY DAC_RSTS
#elif defined(DAC_RSTS_N)
#define DAC_RESETS_ARRAY DAC_RSTS_N
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for DAC module.
*
* @param base DAC peripheral base address
*/
static uint32_t DAC_GetInstance(LPDAC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to DAC bases for each instance. */
static LPDAC_Type *const s_dacBases[] = LPDAC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to DAC clocks for each instance. */
static const clock_ip_name_t s_dacClocks[] = LPDAC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(DAC_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_dacResets[] = DAC_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t DAC_GetInstance(LPDAC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_dacBases); instance++)
{
if (s_dacBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_dacBases));
return instance;
}
/*!
* brief Initialize the DAC module with common configuartion.
*
* The clock will be enabled in this function.
*
* param base DAC peripheral base address.
* param config Pointer to configuration structure.
*/
void DAC_Init(LPDAC_Type *base, const dac_config_t *config)
{
assert(NULL != config);
uint32_t tmp32 = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_dacClocks[DAC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(DAC_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_dacResets[DAC_GetInstance(base)]);
#endif
/* Reset the logic. */
DAC_SetReset(base, kDAC_ResetLogic);
DAC_ClearReset(base, kDAC_ResetLogic);
/* Reset the FIFO. */
DAC_SetReset(base, kDAC_ResetFIFO);
DAC_ClearReset(base, kDAC_ResetFIFO);
/* Configuration. */
if (kDAC_FIFOTriggerBySoftwareMode == config->fifoTriggerMode)
{
tmp32 |= LPDAC_GCR_TRGSEL_MASK; /* Software trigger. */
}
switch (config->fifoWorkMode)
{
case kDAC_FIFOWorkAsNormalMode: /* Normal FIFO. */
tmp32 |= LPDAC_GCR_FIFOEN_MASK;
break;
case kDAC_FIFOWorkAsSwingMode:
tmp32 |= LPDAC_GCR_FIFOEN_MASK | LPDAC_GCR_SWMD_MASK; /* Enable swing mode. */
break;
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
case kDAC_FIFOWorkAsPeriodTriggerMode:
tmp32 |= LPDAC_GCR_FIFOEN_MASK | LPDAC_GCR_PTGEN_MASK; /* Enable period trigger mode. */
/* Set trigger number and width. */
base->PCR =
LPDAC_PCR_PTG_NUM(config->periodicTriggerNumber) | LPDAC_PCR_PTG_PERIOD(config->periodicTriggerWidth);
break;
case kDAC_FIFOWorkAsPeriodTriggerAndSwingMode:
tmp32 |= LPDAC_GCR_FIFOEN_MASK | LPDAC_GCR_PTGEN_MASK | LPDAC_GCR_SWMD_MASK;
/* Set trigger number and width. */
base->PCR =
LPDAC_PCR_PTG_NUM(config->periodicTriggerNumber) | LPDAC_PCR_PTG_PERIOD(config->periodicTriggerWidth);
break;
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
default: /* kDAC_FIFODisabled. */
break;
}
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG) && FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG
if (config->enableExternalTriggerSource)
{
tmp32 |= LPDAC_GCR_RCV_TRG_MASK; /* Use trigger source from another DAC. */
}
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL
if (false == config->enableLowerLowPowerMode)
{
tmp32 |= LPDAC_GCR_BUF_SPD_CTRL_MASK; /* Enable low power. */
}
#else
if (config->enableLowPowerMode)
{
tmp32 |= LPDAC_GCR_LPEN_MASK; /* Enable low power. */
}
#endif /* LPDAC_GCR_BUF_SPD_CTRL_MASK */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN
tmp32 |= LPDAC_GCR_BUF_EN_MASK; /* Opamp is used as buffer. */
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC) && FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC
/* Configure DAC sync cycles. */
tmp32 |= LPDAC_GCR_LATCH_CYC(config->syncTime);
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC */
#if defined(FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT) && FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT
tmp32 |= (uint32_t)config->referenceCurrentSource;
#endif /* FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT */
/* Set reference voltage source. */
tmp32 |= LPDAC_GCR_DACRFS(config->referenceVoltageSource);
base->GCR = tmp32;
base->FCR = LPDAC_FCR_WML(config->fifoWatermarkLevel);
/* Now, the DAC is disabled. It needs to be enabled in application. */
}
/*!
* brief Get the default settings for initialization's configuration.
*
* This function initializes the user configuration structure to a default value. The default values are:
* code
* config->fifoWatermarkLevel = 0U;
* config->fifoTriggerMode = kDAC_FIFOTriggerByHardwareMode;
* config->fifoWorkMode = kDAC_FIFODisabled;
* config->enableLowPowerMode = false;
* config->referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1;
* endcode
*
* param config Pointer to configuration structure.
* param
*/
void DAC_GetDefaultConfig(dac_config_t *config)
{
assert(config != NULL);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
config->fifoWatermarkLevel = 0U;
config->fifoTriggerMode = kDAC_FIFOTriggerByHardwareMode;
config->fifoWorkMode = kDAC_FIFODisabled;
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG) && FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG
config->enableExternalTriggerSource = false;
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL
config->enableLowerLowPowerMode = true;
#else
config->enableLowPowerMode = false;
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL */
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
config->periodicTriggerNumber = 0UL;
config->periodicTriggerWidth = 0UL;
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC) && FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC
/* Configure DAC sync cycles. */
config->syncTime = 1U;
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC */
#if defined(FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT) && FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT
config->referenceCurrentSource = kDAC_ReferenceCurrentSourcePtat;
#endif /* FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT */
config->referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1;
}
/*!
* brief De-initialize the DAC module.
*
* The clock will be disabled in this function.
*
* param base DAC peripheral base address.
* param
*/
void DAC_Deinit(LPDAC_Type *base)
{
/* Disable the module. */
DAC_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_dacClocks[DAC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

View File

@ -0,0 +1,442 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_DAC_H_
#define FSL_DAC_H_
#include "fsl_common.h"
/*!
* @addtogroup dac
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief DAC driver version 2.1.2. */
#define FSL_DAC_DRIVER_VERSION (MAKE_VERSION(2, 1, 2))
/*! @} */
/*!
* @brief DAC reset control.
*/
enum
{
kDAC_ResetFIFO = LPDAC_RCR_FIFORST_MASK, /*!< Resets the FIFO pointers and flags. */
kDAC_ResetLogic = LPDAC_RCR_SWRST_MASK, /*!< Resets all DAC registers and internal logic. */
};
/*!
* @brief DAC interrupts.
*/
enum
{
kDAC_FIFOFullInterruptEnable = LPDAC_IER_FULL_IE_MASK, /*!< FIFO full interrupt enable. */
kDAC_FIFOEmptyInterruptEnable = LPDAC_IER_EMPTY_IE_MASK, /*!< FIFO empty interrupt enable. */
kDAC_FIFOWatermarkInterruptEnable = LPDAC_IER_WM_IE_MASK, /*!< FIFO watermark interrupt enable. */
kDAC_SwingBackInterruptEnable = LPDAC_IER_SWBK_IE_MASK, /*!< Swing back one cycle complete interrupt enable. */
kDAC_FIFOOverflowInterruptEnable = LPDAC_IER_OF_IE_MASK, /*!< FIFO overflow interrupt enable. */
kDAC_FIFOUnderflowInterruptEnable = LPDAC_IER_UF_IE_MASK, /*!< FIFO underflow interrupt enable. */
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
kDAC_PeriodTriggerCompleteInterruptEnable =
LPDAC_IER_PTGCOCO_IE_MASK, /*!< Period trigger mode conversion complete interrupt enable */
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
};
/*!
* @brief DAC DMA switchers.
*/
enum
{
kDAC_FIFOEmptyDMAEnable = LPDAC_DER_EMPTY_DMAEN_MASK, /*!< FIFO empty DMA enable. */
kDAC_FIFOWatermarkDMAEnable = LPDAC_DER_WM_DMAEN_MASK, /*!< FIFO watermark DMA enable. */
};
/*!
* @brief DAC status flags.
*/
enum
{
kDAC_FIFOUnderflowFlag = LPDAC_FSR_UF_MASK, /*!< This flag means that there is a new trigger after the buffer is
empty. The FIFO read pointer will not
increase in this case and the data sent to DAC analog conversion will not changed. This flag is cleared by writing a 1
to it. */
kDAC_FIFOOverflowFlag =
LPDAC_FSR_OF_MASK, /*!< This flag indicates that data is intended to write into FIFO after the
buffer is full. The writer pointer will
not increase in this case. The extra data will not be written into the FIFO. This flag is cleared by writing a 1 to it.
*/
kDAC_FIFOSwingBackFlag = LPDAC_FSR_SWBK_MASK, /*!< This flag indicates that the DAC has completed one period of
conversion in swing back mode. It means
that the read pointer has increased to the top (write pointer) once and then decreased to zero once. For
example, after three data is written to FIFO, the writer pointer is now 3. Then, if continually triggered, the
read pointer will swing like: 0-1-2-1-0-1-2-, and so on. After the fourth trigger, the flag is set. This flag is
cleared by writing a 1 to it. */
kDAC_FIFOWatermarkFlag = LPDAC_FSR_WM_MASK, /*!< This field is set if the remaining data in FIFO is less than or
equal to the setting value of wartermark. By writing data into FIFO by DMA or CPU, this flag is
cleared automatically when the data in FIFO is more than the setting value of watermark. */
kDAC_FIFOEmptyFlag = LPDAC_FSR_EMPTY_MASK, /*!< FIFO empty flag. */
kDAC_FIFOFullFlag = LPDAC_FSR_FULL_MASK, /*!< FIFO full flag. */
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
kDAC_PeriodTriggerCompleteFlag = LPDAC_FSR_PTGCOCO_MASK, /*!< Period trigger mode conversion complete flag. */
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
};
/*!
* @brief DAC FIFO trigger mode.
*/
typedef enum _dac_fifo_trigger_mode
{
kDAC_FIFOTriggerByHardwareMode = 0U, /*!< Buffer would be triggered by hardware. */
kDAC_FIFOTriggerBySoftwareMode = 1U, /*!< Buffer would be triggered by software. */
} dac_fifo_trigger_mode_t;
/*!
* @brief DAC FIFO work mode.
*/
typedef enum _dac_fifo_work_mode
{
kDAC_FIFODisabled = 0U, /*!< FIFO mode is disabled and buffer mode is enabled. Any data written to DATA[DATA] goes
to buffer then goes to conversion. */
kDAC_FIFOWorkAsNormalMode = 1U, /*!< FIFO mode is enabled. Data will be first read from FIFO to buffer then goes to
conversion. */
kDAC_FIFOWorkAsSwingMode = 2U, /*!< In swing mode, the read pointer swings between the writer pointer and zero. That
is, the trigger increases the read pointer till reach the writer pointer and
decreases the read pointer till zero, and so on. The FIFO empty/full/watermark
flag will not update during swing back mode. */
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
kDAC_FIFOWorkAsPeriodTriggerMode =
3U, /*!< In periodic trigger mode, user only needs to send the first trigger. Then after every [PTG_PERIOD+1]
RCLK cycles, DAC will be automatically triggered by internal trigger. There will be [PTG_NUM] internal
triggers, thus in total [PTG_NUM+1] conversions including the first trigger sent by user. User can
terminate the current conversion queue by clearing the GCR[PTGEN] bit. Then, after the current conversion
is completed, the conversion is terminated and the PTGCOCO flag is set. If PCR[PTG_NUM] is set to zero,
there will be infinite triggers following the first hardware/software trigger, until the GCR[PTGEN] is
cleared by software. In any case, the conversion can be terminated by FIFORST/SWRST. */
kDAC_FIFOWorkAsPeriodTriggerAndSwingMode = 4U, /*!< Periodically trigger DAC and swing back. */
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
} dac_fifo_work_mode_t;
/*!
* @brief DAC reference voltage source.
*/
typedef enum _dac_reference_voltage_source
{
#if defined(FSL_FEATURE_ANALOG_NUM_OF_VREF_SRC) && (FSL_FEATURE_ANALOG_NUM_OF_VREF_SRC == 3)
kDAC_ReferenceVoltageSourceAlt1 = 0U, /*!< The DAC selects VDD_ANA as the reference voltage. */
kDAC_ReferenceVoltageSourceAlt2 = 1U, /*!< The DAC selects VREF_OUT as the reference voltage. */
kDAC_ReferenceVoltageSourceAlt3 = 2U, /*!< THe DAC selects VREFH as the reference voltage. */
#else
kDAC_ReferenceVoltageSourceAlt1 = 0U, /*!< The DAC selects VREFH_INT as the reference voltage. */
kDAC_ReferenceVoltageSourceAlt2 = 1U, /*!< The DAC selects VREFH_EXT as the reference voltage. */
#endif /* FSL_FEATURE_ANALOG_NUM_OF_VREF_SRC */
} dac_reference_voltage_source_t;
#if defined(FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT) && FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT
/*
* @brief DAC internal reference current source
*/
typedef enum _dac_reference_current_source
{
kDAC_ReferenceCurrentSourcePtat = LPDAC_GCR_IREF_PTAT_EXT_SEL_MASK, /* Internal PTAT Current Reference selected */
kDAC_ReferenceCurrentSourceZtc = LPDAC_GCR_IREF_ZTC_EXT_SEL_MASK, /* Internal ZTC Current Reference selected */
} dac_reference_current_source_t;
#endif /* FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT */
/*!
* @brief DAC configuration structure.
*/
typedef struct _dac_config
{
uint32_t fifoWatermarkLevel; /*!< FIFO's watermark, the max value can be the hardware FIFO size. */
dac_fifo_trigger_mode_t fifoTriggerMode; /*!< Select the trigger mode for FIFO. */
dac_fifo_work_mode_t fifoWorkMode; /*!< Select the work mode for FIFO. */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN
bool enableOpampBuffer; /*!< Opamp is used as buffer. */
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_BUF_EN */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG) && FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG
bool enableExternalTriggerSource; /* DAC uses another DAC's hardware/software trigger as its trigger source. */
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_RCV_TRG */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL
bool enableLowerLowPowerMode; /*!< Enable the lower low power mode. */
#else
bool enableLowPowerMode; /*!< Enable the low power mode. */
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL */
#if defined(FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE) && FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE
uint32_t periodicTriggerNumber; /*!< There will be 'periodicTriggerNumber' internal triggers following the first
hardware/software trigger. So there will be 'periodicTriggerNumber + 1'
conversions in total. If set to zero, there will be infinite triggers following
the first hw/sw trigger, until the GCR[PTGEN] is cleared. */
uint32_t periodicTriggerWidth; /*!< Control the periodic trigger frequency. There will be 'periodicTriggerWidth + 1'
RCLK cycles between each periodic trigger. The periodic trigger frequency should
be configured to not larger than the analog conversion speed. */
#endif /* FSL_FEATURE_LPDAC_HAS_PERIODIC_TRIGGER_MODE */
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC) && FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC
uint32_t syncTime; /*!< RCLK cycles before data latch. accessible range is 0-15. It is used to configure the DAC
sync cycles which is helpful to reduce glitch on the output. The sync time is (LATCH_CYC+1)
RCLK cycles. User should configure this register according to the RCLK frequency. The
recommended sync time is at least 40ns.*/
#endif /* FSL_FEATURE_LPDAC_HAS_GCR_LATCH_CYC */
#if defined(FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT) && FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT
dac_reference_current_source_t referenceCurrentSource; /*!< Select the internal reference current source. */
#endif /* FSL_FEATURE_LPDAC_HAS_INTERNAL_REFERENCE_CURRENT */
dac_reference_voltage_source_t referenceVoltageSource; /*!< Select the reference voltage source. */
} dac_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and de-initialization
* @{
*/
/*!
* @brief Initialize the DAC module with common configuartion.
*
* The clock will be enabled in this function.
*
* @param base DAC peripheral base address.
* @param config Pointer to configuration structure.
*/
void DAC_Init(LPDAC_Type *base, const dac_config_t *config);
/*!
* @brief Get the default settings for initialization's configuration.
*
* This function initializes the user configuration structure to a default value. The default values are:
* @code
* config->fifoWatermarkLevel = 0U;
* config->fifoTriggerMode = kDAC_FIFOTriggerByHardwareMode;
* config->fifoWorkMode = kDAC_FIFODisabled;
* config->enableLowPowerMode = false;
* config->referenceVoltageSource = kDAC_ReferenceVoltageSourceAlt1;
* @endcode
*
* @param config Pointer to configuration structure.
*/
void DAC_GetDefaultConfig(dac_config_t *config);
/*!
* @brief De-initialize the DAC module.
*
* The clock will be disabled in this function.
*
* @param base DAC peripheral base address.
*/
void DAC_Deinit(LPDAC_Type *base);
/*!
* @brief Assert the reset control to part hardware.
*
* This function is to assert the reset control to part hardware. Responding part hardware would remain reset untill
* cleared by software.
*
* @param base DAC peripheral base address.
* @param mask The reset control mask, see to _dac_reset_control_t.
*/
static inline void DAC_SetReset(LPDAC_Type *base, uint32_t mask)
{
base->RCR |= mask;
}
/*!
* @brief Clear the reset control to part hardware.
*
* This function is to clear the reset control to part hardware. Responding part hardware would work after the reset
* control is cleared by software.
*
* @param base DAC peripheral base address.
* @param mask The reset control mask, see to _dac_reset_control_t.
*/
static inline void DAC_ClearReset(LPDAC_Type *base, uint32_t mask)
{
base->RCR &= ~mask;
}
/*!
* @brief Enable the DAC hardware system or not.
*
* This function is to start the Programmable Reference Generator operation or not.
*
* @param base DAC peripheral base address.
* @param enable Assertion of indicated event.
*/
static inline void DAC_Enable(LPDAC_Type *base, bool enable)
{
if (enable)
{
base->GCR |= LPDAC_GCR_DACEN_MASK;
}
else
{
base->GCR &= ~LPDAC_GCR_DACEN_MASK;
}
}
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enable the interrupts.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated interrupt events. See to _dac_interrupt_enable.
*/
static inline void DAC_EnableInterrupts(LPDAC_Type *base, uint32_t mask)
{
base->IER |= mask;
}
/*!
* @brief Disable the interrupts.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated interrupt events. See to _dac_interrupt_enable.
*/
static inline void DAC_DisableInterrupts(LPDAC_Type *base, uint32_t mask)
{
base->IER &= ~mask;
}
/*! @} */
/*!
* @name DMA control
* @{
*/
/*!
* @brief Enable the DMA switchers or not.
*
* @param base DAC peripheral base address.
* @param mask Mask value of indicated DMA requeset. See to _dac_dma_enable.
* @param enable Enable the DMA or not.
*/
static inline void DAC_EnableDMA(LPDAC_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->DER |= mask;
}
else
{
base->DER &= ~mask;
}
}
/*! @} */
/*!
* @name Status flags
* @{
*/
/*!
* @brief Get status flags of DAC module.
*
* @param base DAC peripheral base address.
* @return Mask value of status flags. See to _dac_status_flags.
*/
static inline uint32_t DAC_GetStatusFlags(LPDAC_Type *base)
{
return base->FSR;
}
/*!
* @brief Clear status flags of DAC module.
*
* @param base DAC peripheral base address.
* @param flags Mask value of status flags to be cleared. See to _dac_status_flags.
*/
static inline void DAC_ClearStatusFlags(LPDAC_Type *base, uint32_t flags)
{
base->FSR = flags;
}
/*! @} */
/*!
* @name Functional feature
* @{
*/
/*!
* @brief Set data into the entry of FIFO buffer.
*
* @param base DAC peripheral base address.
* @param value Setting value into FIFO buffer.
*/
static inline void DAC_SetData(LPDAC_Type *base, uint32_t value)
{
base->DATA = LPDAC_DATA_DATA(value);
}
/*!
* @brief Get the value of the FIFO write pointer.
*
* @param base DAC peripheral base address.
* @return Current value of the FIFO write pointer.
*/
static inline uint32_t DAC_GetFIFOWritePointer(LPDAC_Type *base)
{
return (LPDAC_FPR_FIFO_WPT_MASK & base->FPR) >> LPDAC_FPR_FIFO_WPT_SHIFT;
}
/*!
* @brief Get the value of the FIFO read pointer.
*
* @param base DAC peripheral base address.
* @return Current value of the FIFO read pointer.
*/
static inline uint32_t DAC_GetFIFOReadPointer(LPDAC_Type *base)
{
return (LPDAC_FPR_FIFO_RPT_MASK & base->FPR) >> LPDAC_FPR_FIFO_RPT_SHIFT;
}
/*!
* @brief Do software trigger to FIFO when in software mode.
*
* @param base DAC peripheral base address.
*/
static inline void DAC_DoSoftwareTriggerFIFO(LPDAC_Type *base)
{
base->TCR = LPDAC_TCR_SWTRG_MASK;
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* FSL_DAC12_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,357 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_EDMA_CORE_H_
#define FSL_EDMA_CORE_H_
#include "fsl_edma_soc.h"
/*!
* @addtogroup edma_core
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
#define DMA_CSR_INTMAJOR_MASK (0x2U)
#define DMA_CSR_INTHALF_MASK (0x4U)
#define DMA_CSR_DREQ_MASK (0x8U)
#define DMA_CSR_ESG_MASK (0x10U)
#define DMA_CSR_BWC_MASK (0xC000U)
#define DMA_CSR_BWC(x) (((uint16_t)(((uint16_t)(x)) << (14U))) & (0xC000U))
#define DMA_CSR_START_MASK (0x1U)
#define DMA_CITER_ELINKNO_CITER_MASK (0x7FFFU)
#define DMA_BITER_ELINKNO_BITER_MASK (0x7FFFU)
#define DMA_CITER_ELINKNO_CITER_SHIFT (0U)
#define DMA_CITER_ELINKYES_CITER_MASK (0x1FFU)
#define DMA_CITER_ELINKYES_CITER_SHIFT (0U)
#define DMA_ATTR_SMOD_MASK (0xF800U)
#define DMA_ATTR_DMOD_MASK (0xF8U)
#define DMA_CITER_ELINKNO_ELINK_MASK (0x8000U)
#define DMA_CSR_MAJORELINK_MASK (0x20U)
#define DMA_BITER_ELINKYES_ELINK_MASK (0x8000U)
#define DMA_CITER_ELINKYES_ELINK_MASK (0x8000U)
#define DMA_CSR_MAJORLINKCH_MASK (0x1F00U)
#define DMA_BITER_ELINKYES_LINKCH_MASK (0x3E00U)
#define DMA_CITER_ELINKYES_LINKCH_MASK (0x3E00U)
#define DMA_NBYTES_MLOFFYES_MLOFF_MASK (0x3FFFFC00U)
#define DMA_NBYTES_MLOFFYES_DMLOE_MASK (0x40000000U)
#define DMA_NBYTES_MLOFFYES_SMLOE_MASK (0x80000000U)
#define DMA_NBYTES_MLOFFNO_NBYTES_MASK (0x3FFFFFFFU)
#define DMA_ATTR_DMOD(x) (((uint16_t)(((uint16_t)(x)) << (3U))) & (0xF8U))
#define DMA_ATTR_SMOD(x) (((uint16_t)(((uint16_t)(x)) << (11U))) & (0xF800U))
#define DMA_BITER_ELINKYES_LINKCH(x) (((uint16_t)(((uint16_t)(x)) << (9U))) & (0x3E00U))
#define DMA_CITER_ELINKYES_LINKCH(x) (((uint16_t)(((uint16_t)(x)) << (9U))) & (0x3E00U))
#define DMA_NBYTES_MLOFFYES_MLOFF(x) (((uint32_t)(((uint32_t)(x)) << (10U))) & (0x3FFFFC00U))
#define DMA_NBYTES_MLOFFYES_DMLOE(x) (((uint32_t)(((uint32_t)(x)) << (30U))) & (0x40000000U))
#define DMA_NBYTES_MLOFFYES_SMLOE(x) (((uint32_t)(((uint32_t)(x)) << (31U))) & (0x80000000U))
#define DMA_NBYTES_MLOFFNO_NBYTES(x) (((uint32_t)(((uint32_t)(x)) << (0U))) & (0x3FFFFFFFU))
#define DMA_NBYTES_MLOFFYES_NBYTES(x) (((uint32_t)(((uint32_t)(x)) << (0U))) & (0x3FFU))
#define DMA_ATTR_DSIZE(x) (((uint16_t)(((uint16_t)(x)) << (0U))) & (0x7U))
#define DMA_ATTR_SSIZE(x) (((uint16_t)(((uint16_t)(x)) << (8U))) & (0x700U))
#define DMA_CSR_DREQ(x) (((uint16_t)(((uint16_t)(x)) << (3U))) & (0x8U))
#define DMA_CSR_MAJORLINKCH(x) (((uint16_t)(((uint16_t)(x)) << (8U))) & (0x1F00U))
#define DMA_CH_MATTR_WCACHE(x) (((uint16_t)(((uint16_t)(x)) << (4U))) & (0xF0U))
#define DMA_CH_MATTR_RCACHE(x) (((uint16_t)(((uint16_t)(x)) << (0U))) & (0xFU))
#define DMA_CH_CSR_SIGNEXT_MASK (0x3F0000U)
#define DMA_CH_CSR_SIGNEXT_SHIFT (16U)
#define DMA_CH_CSR_SWAP_MASK (0xF000U)
#define DMA_CH_CSR_SWAP_SHIFT (12U)
#define DMA_CH_SBR_INSTR_MASK (0x2000U)
#define DMA_CH_SBR_INSTR_SHIFT (13U)
#define DMA_CH_MUX_SOURCE(x) (((uint32_t)(((uint32_t)(x)) << (0U))) & (0xFFU))
/*! @brief DMA error flag */
#if defined(FSL_EDMA_SOC_IP_EDMA) && FSL_EDMA_SOC_IP_EDMA
#define DMA_ERR_DBE_FLAG DMA_ES_DBE_MASK
#define DMA_ERR_SBE_FLAG DMA_ES_SBE_MASK
#define DMA_ERR_SGE_FLAG DMA_ES_SGE_MASK
#define DMA_ERR_NCE_FLAG DMA_ES_NCE_MASK
#define DMA_ERR_DOE_FLAG DMA_ES_DOE_MASK
#define DMA_ERR_DAE_FLAG DMA_ES_DAE_MASK
#define DMA_ERR_SOE_FLAG DMA_ES_SOE_MASK
#define DMA_ERR_SAE_FLAG DMA_ES_SAE_MASK
#define DMA_ERR_ERRCHAN_FLAG DMA_ES_ERRCHN_MASK
#define DMA_ERR_CPE_FLAG DMA_ES_CPE_MASK
#define DMA_ERR_ECX_FLAG DMA_ES_ECX_MASK
#if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && (FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1)
#define DMA_ERR_GPE_FLAG DMA_ES_GPE_MASK
#endif
#define DMA_ERR_FLAG DMA_ES_VLD_MASK
/*! @brief get/clear DONE status*/
#define DMA_CLEAR_DONE_STATUS(base, channel) (EDMA_BASE(base)->CDNE = (uint8_t)channel)
#define DMA_GET_DONE_STATUS(base, channel) \
((EDMA_TCD_BASE(base, channel)->CSR & DMA_CSR_DONE_MASK) >> DMA_CSR_DONE_SHIFT)
/*! @brief enable/disable error interrupt*/
#define DMA_ENABLE_ERROR_INT(base, channel) (base->EEI |= ((uint32_t)0x1U << channel))
#define DMA_DISABLE_ERROR_INT(base, channel) (base->EEI &= (~((uint32_t)0x1U << channel)))
/*! @brief get/clear error status*/
#define DMA_GET_ERROR_STATUS(base, channel) (((uint32_t)EDMA_BASE(base)->ERR >> channel) & 0x1U)
#define DMA_CLEAR_ERROR_STATUS(base, channel) ((uint32_t)EDMA_BASE(base)->CERR = (uint8_t)channel)
/*! @brief get/clear int status*/
#define DMA_GET_INT_STATUS(base, channel) ((((uint32_t)EDMA_BASE(base)->INT >> channel) & 0x1U))
#define DMA_CLEAR_INT_STATUS(base, channel) ((uint32_t)EDMA_BASE(base)->CINT = (uint8_t)channel)
#else
#define DMA_ERR_DBE_FLAG DMA_MP_ES_DBE_MASK
#define DMA_ERR_SBE_FLAG DMA_MP_ES_SBE_MASK
#define DMA_ERR_SGE_FLAG DMA_MP_ES_SGE_MASK
#define DMA_ERR_NCE_FLAG DMA_MP_ES_NCE_MASK
#define DMA_ERR_DOE_FLAG DMA_MP_ES_DOE_MASK
#define DMA_ERR_DAE_FLAG DMA_MP_ES_DAE_MASK
#define DMA_ERR_SOE_FLAG DMA_MP_ES_SOE_MASK
#define DMA_ERR_SAE_FLAG DMA_MP_ES_SAE_MASK
#define DMA_ERR_ERRCHAN_FLAG DMA_MP_ES_ERRCHN_MASK
#define DMA_ERR_ECX_FLAG DMA_MP_ES_ECX_MASK
#define DMA_ERR_FLAG DMA_MP_ES_VLD_MASK
/*! @brief get/clear DONE bit*/
#define DMA_CLEAR_DONE_STATUS(base, channel) (EDMA_CHANNEL_BASE(base, channel)->CH_CSR |= DMA_CH_CSR_DONE_MASK)
#define DMA_GET_DONE_STATUS(base, channel) \
((EDMA_CHANNEL_BASE(base, channel)->CH_CSR & DMA_CH_CSR_DONE_MASK) >> DMA_CH_CSR_DONE_SHIFT)
/*! @brief enable/disable error interupt*/
#define DMA_ENABLE_ERROR_INT(base, channel) (EDMA_CHANNEL_BASE(base, channel)->CH_CSR |= DMA_CH_CSR_EEI_MASK)
#define DMA_DISABLE_ERROR_INT(base, channel) (EDMA_CHANNEL_BASE(base, channel)->CH_CSR &= ~DMA_CH_CSR_EEI_MASK)
/*! @brief get/clear error status*/
#define DMA_CLEAR_ERROR_STATUS(base, channel) (EDMA_CHANNEL_BASE(base, channel)->CH_ES |= DMA_CH_ES_ERR_MASK)
#define DMA_GET_ERROR_STATUS(base, channel) \
(((uint32_t)EDMA_CHANNEL_BASE(base, channel)->CH_ES >> DMA_CH_ES_ERR_SHIFT) & 0x1U)
/*! @brief get/clear INT status*/
#define DMA_CLEAR_INT_STATUS(base, channel) (EDMA_CHANNEL_BASE(base, channel)->CH_INT = DMA_CH_INT_INT_MASK)
#define DMA_GET_INT_STATUS(base, channel) ((((uint32_t)EDMA_CHANNEL_BASE(base, channel)->CH_INT) & 0x1U))
#endif /*FSL_EDMA_SOC_IP_EDMA*/
/*! @brief enable/dsiable MAJOR/HALF INT*/
#define DMA_ENABLE_MAJOR_INT(base, channel) \
(EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) |= DMA_CSR_INTMAJOR_MASK)
#define DMA_ENABLE_HALF_INT(base, channel) \
(EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) |= DMA_CSR_INTHALF_MASK)
#define DMA_DISABLE_MAJOR_INT(base, channel) \
(EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_INTMAJOR_MASK)
#define DMA_DISABLE_HALF_INT(base, channel) \
(EDMA_TCD_CSR(EDMA_TCD_BASE(base, channel), EDMA_TCD_TYPE(base)) &= ~(uint16_t)DMA_CSR_INTHALF_MASK)
/*!@brief EDMA tcd align size */
#define EDMA_TCD_ALIGN_SIZE (32U)
/*!@brief edma core channel struture definition */
typedef struct _edma_core_mp
{
__IO uint32_t MP_CSR; /**< Channel Control and Status, array offset: 0x10000, array step: 0x10000 */
__IO uint32_t MP_ES; /**< Channel Error Status, array offset: 0x10004, array step: 0x10000 */
union
{
struct
{
__IO uint32_t MP_INT_LOW; /**< Channel Control and Status, array offset: 0x10008, array step: 0x10000 */
__I uint32_t MP_INT_HIGH; /**< Channel Control and Status, array offset: 0x1000C, array step: 0x10000 */
__I uint32_t MP_HRS_LOW; /**< Channel Control and Status, array offset: 0x10010, array step: 0x10000 */
__I uint32_t MP_HRS_HIGH; /**< Channel Control and Status, array offset: 0x10014, array step: 0x10000 */
uint8_t RESERVED_0[8];
__IO uint32_t MP_STOPCH; /**< Channel Control and Status, array offset: 0x10020, array step: 0x10000 */
uint8_t RESERVED_1[12];
__I uint32_t MP_SSR_LOW; /**< Channel Control and Status, array offset: 0x10030, array step: 0x10000 */
__I uint32_t MP_SSR_HIGH; /**< Channel Control and Status, array offset: 0x10034, array step: 0x10000 */
uint8_t RESERVED_2[200];
__IO uint32_t CH_GRPRI[64]; /**< Channel Control and Status, array offset: 0x10100, array step: 0x10000 */
__IO uint32_t CH_MUX[64]; /**< Channel Control and Status, array offset: 0x10200, array step: 0x10000 */
uint8_t RESERVED_3[256];
__IO uint32_t CH_PROT[64]; /**< Channel Control and Status, array offset: 0x10400, array step: 0x10000 */
} EDMA5_REG;
} MP_REGS;
} edma_core_mp_t;
/*!@brief edma core channel struture definition */
typedef struct _edma_core_channel
{
__IO uint32_t CH_CSR; /**< Channel Control and Status, array offset: 0x10000, array step: 0x10000 */
__IO uint32_t CH_ES; /**< Channel Error Status, array offset: 0x10004, array step: 0x10000 */
__IO uint32_t CH_INT; /**< Channel Interrupt Status, array offset: 0x10008, array step: 0x10000 */
__IO uint32_t CH_SBR; /**< Channel System Bus, array offset: 0x1000C, array step: 0x10000 */
__IO uint32_t CH_PRI; /**< Channel Priority, array offset: 0x10010, array step: 0x10000 */
union
{
struct
{
__IO uint8_t RESERVED_1[4];
__IO uint32_t CH_MATTR; /**< Memory Attributes Register, array offset: 0x10018, array step: 0x8000 */
} EDMA5_REG;
struct
{
__IO uint32_t CH_MUX; /**< Channel Multiplexor Configuration, array offset: 0x10014, array step: 0x10000 */
__IO uint16_t CH_MATTR; /**< Memory Attributes Register, array offset: 0x10018, array step: 0x8000 */
} EDMA4_REG;
} CH_REGS;
} edma_core_channel_t;
/*! @brief eDMA tcd flag type */
typedef enum _edma_tcd_type
{
kEDMA_EDMA4Flag = 0x0U, /*!< Data access for eDMA4 transfers. */
kEDMA_EDMA5Flag = 0x1U, /*!< Instruction access for eDMA4 transfers. */
} edma_tcd_type_t;
/*!@brief edma5 core TCD struture definition */
typedef struct _edma5_core_tcd
{
__IO uint32_t SADDR; /*!< SADDR register, used to save source address */
__IO uint32_t SADDR_HIGH; /*!< SADDR HIGH register, used to save source address */
__IO uint16_t SOFF; /*!< SOFF register, save offset bytes every transfer */
__IO uint16_t ATTR; /*!< ATTR register, source/destination transfer size and modulo */
__IO uint32_t NBYTES; /*!< Nbytes register, minor loop length in bytes */
__IO uint32_t SLAST; /*!< SLAST register */
__IO uint32_t SLAST_SDA_HIGH; /*!< SLAST SDA HIGH register */
__IO uint32_t DADDR; /*!< DADDR register, used for destination address */
__IO uint32_t DADDR_HIGH; /*!< DADDR HIGH register, used for destination address */
__IO uint32_t DLAST_SGA; /*!< DLASTSGA register, next tcd address used in scatter-gather mode */
__IO uint32_t DLAST_SGA_HIGH; /*!< DLASTSGA HIGH register, next tcd address used in scatter-gather mode */
__IO uint16_t DOFF; /*!< DOFF register, used for destination offset */
__IO uint16_t CITER; /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
__IO uint16_t CSR; /*!< CSR register, for TCD control status */
__IO uint16_t BITER; /*!< BITER register, begin minor loop count. */
uint8_t RESERVED[16]; /*!< Aligned 64 bytes */
} edma5_core_tcd_t;
/*!@brief edma4 core TCD struture definition */
typedef struct _edma4_core_tcd
{
__IO uint32_t SADDR; /*!< SADDR register, used to save source address */
__IO uint16_t SOFF; /*!< SOFF register, save offset bytes every transfer */
__IO uint16_t ATTR; /*!< ATTR register, source/destination transfer size and modulo */
__IO uint32_t NBYTES; /*!< Nbytes register, minor loop length in bytes */
__IO uint32_t SLAST; /*!< SLAST register */
__IO uint32_t DADDR; /*!< DADDR register, used for destination address */
__IO uint16_t DOFF; /*!< DOFF register, used for destination offset */
__IO uint16_t CITER; /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
__IO uint32_t DLAST_SGA; /*!< DLASTSGA register, next tcd address used in scatter-gather mode */
__IO uint16_t CSR; /*!< CSR register, for TCD control status */
__IO uint16_t BITER; /*!< BITER register, begin minor loop count. */
} edma4_core_tcd_t;
/*!@brief edma core TCD struture definition */
typedef struct _edma_core_tcd
{
union
{
edma4_core_tcd_t edma4_tcd;
#if defined FSL_EDMA_SOC_IP_DMA5 && FSL_EDMA_SOC_IP_DMA5
edma5_core_tcd_t edma5_tcd;
#endif /* FSL_EDMA_SOC_IP_DMA5 */
} TCD_REGS;
} edma_core_tcd_t;
/*!@brief EDMA typedef */
typedef edma_core_channel_t EDMA_ChannelType;
typedef edma_core_tcd_t EDMA_TCDType;
typedef void EDMA_Type;
/*!@brief EDMA base address convert macro */
#define EDMA_BASE(base)
#define EDMA_CHANNEL_BASE(base, channel) \
((edma_core_channel_t *)((uint32_t)(uint32_t *)(base) + EDMA_CHANNEL_OFFSET + \
(channel)*EDMA_CHANNEL_ARRAY_STEP(base)))
#define EDMA_TCD_BASE(base, channel) \
((edma_core_tcd_t *)((uint32_t)(uint32_t *)(base) + EDMA_CHANNEL_OFFSET + \
(channel)*EDMA_CHANNEL_ARRAY_STEP(base) + 0x20U))
#define EDMA_MP_BASE(base) ((edma_core_mp_t *)((uint32_t)(uint32_t *)(base)))
/*!@brief EDMA TCD type macro */
#if defined FSL_FEATURE_EDMA_TCD_TYPEn
#define EDMA_TCD_TYPE(x) FSL_FEATURE_EDMA_TCD_TYPEn(x)
#else
#define EDMA_TCD_TYPE(x) (0)
#endif
#if defined FSL_EDMA_SOC_IP_DMA5 && FSL_EDMA_SOC_IP_DMA5
/*!@brief EDMA TCD address convert macro */
#define EDMA_TCD_SADDR(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SADDR)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->SADDR))))
#define EDMA_TCD_SOFF(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SOFF)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->SOFF))))
#define EDMA_TCD_ATTR(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->ATTR)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->ATTR))))
#define EDMA_TCD_NBYTES(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->NBYTES)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->NBYTES))))
#define EDMA_TCD_SLAST(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SLAST)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->SLAST))))
#define EDMA_TCD_DADDR(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DADDR)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->DADDR))))
#define EDMA_TCD_DOFF(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DOFF)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->DOFF))))
#define EDMA_TCD_CITER(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->CITER)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->CITER))))
#define EDMA_TCD_DLAST_SGA(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? \
(&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DLAST_SGA)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->DLAST_SGA))))
#define EDMA_TCD_CSR(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->CSR)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->CSR))))
#define EDMA_TCD_BITER(tcd, flag) \
(*(((edma_tcd_type_t)(flag) == kEDMA_EDMA4Flag) ? (&(((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->BITER)) : \
(&(((edma5_core_tcd_t *)(&(tcd)->TCD_REGS.edma5_tcd))->BITER))))
#else
/*!@brief EDMA TCD address convert macro */
#define EDMA_TCD_SADDR(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SADDR)
#define EDMA_TCD_SOFF(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SOFF)
#define EDMA_TCD_ATTR(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->ATTR)
#define EDMA_TCD_NBYTES(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->NBYTES)
#define EDMA_TCD_SLAST(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->SLAST)
#define EDMA_TCD_DADDR(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DADDR)
#define EDMA_TCD_DOFF(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DOFF)
#define EDMA_TCD_CITER(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->CITER)
#define EDMA_TCD_DLAST_SGA(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->DLAST_SGA)
#define EDMA_TCD_CSR(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->CSR)
#define EDMA_TCD_BITER(tcd, flag) (((edma4_core_tcd_t *)(&(tcd)->TCD_REGS.edma4_tcd))->BITER)
#endif /* FSL_EDMA_SOC_IP_DMA5 */
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*!
* @}
*/
#endif /* FSL_EDMA_CORE_H_ */

View File

@ -0,0 +1,112 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_edma_soc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.edma_soc"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
extern void DMA_CH0_DriverIRQHandler(void);
extern void DMA_CH1_DriverIRQHandler(void);
extern void DMA_CH2_DriverIRQHandler(void);
extern void DMA_CH3_DriverIRQHandler(void);
extern void DMA_CH4_DriverIRQHandler(void);
extern void DMA_CH5_DriverIRQHandler(void);
extern void DMA_CH6_DriverIRQHandler(void);
extern void DMA_CH7_DriverIRQHandler(void);
extern void EDMA_DriverIRQHandler(uint32_t instance, uint32_t channel);
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief DMA instance 0, channel 0 IRQ handler.
*
*/
void DMA_CH0_DriverIRQHandler(void)
{
/* Instance 0 channel 0 */
EDMA_DriverIRQHandler(0U, 0U);
}
/*!
* brief DMA instance 0, channel 1 IRQ handler.
*
*/
void DMA_CH1_DriverIRQHandler(void)
{
/* Instance 0 channel 1 */
EDMA_DriverIRQHandler(0U, 1U);
}
/*!
* brief DMA instance 0, channel 2 IRQ handler.
*
*/
void DMA_CH2_DriverIRQHandler(void)
{
/* Instance 0 channel 2 */
EDMA_DriverIRQHandler(0U, 2U);
}
/*!
* brief DMA instance 0, channel 3 IRQ handler.
*
*/
void DMA_CH3_DriverIRQHandler(void)
{
/* Instance 0 channel 3 */
EDMA_DriverIRQHandler(0U, 3U);
}
/*!
* brief DMA instance 0, channel 4 IRQ handler.
*
*/
void DMA_CH4_DriverIRQHandler(void)
{
/* Instance 0 channel 4 */
EDMA_DriverIRQHandler(0U, 4U);
}
/*!
* brief DMA instance 0, channel 5 IRQ handler.
*
*/
void DMA_CH5_DriverIRQHandler(void)
{
/* Instance 0 channel 5 */
EDMA_DriverIRQHandler(0U, 5U);
}
/*!
* brief DMA instance 0, channel 6 IRQ handler.
*
*/
void DMA_CH6_DriverIRQHandler(void)
{
/* Instance 0 channel 6 */
EDMA_DriverIRQHandler(0U, 6U);
}
/*!
* brief DMA instance 0, channel 7 IRQ handler.
*
*/
void DMA_CH7_DriverIRQHandler(void)
{
/* Instance 0 channel 7 */
EDMA_DriverIRQHandler(0U, 7U);
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_EDMA_SOC_H_
#define _FSL_EDMA_SOC_H_
#include "fsl_common.h"
/*!
* @addtogroup edma_soc
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief Driver version 2.0.0. */
#define FSL_EDMA_SOC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!@brief DMA IP version */
#define FSL_EDMA_SOC_IP_DMA3 (1)
#define FSL_EDMA_SOC_IP_DMA4 (0)
/*!@brief DMA base table */
#define EDMA_BASE_PTRS \
{ \
DMA0 \
}
#define EDMA_CHN_IRQS \
{ \
{ \
DMA_CH0_IRQn, DMA_CH1_IRQn, DMA_CH2_IRQn, DMA_CH3_IRQn, DMA_CH4_IRQn, DMA_CH5_IRQn, DMA_CH6_IRQn, \
DMA_CH7_IRQn \
} \
}
/*!@brief EDMA base address convert macro */
#define EDMA_CHANNEL_OFFSET 0x1000U
#define EDMA_CHANNEL_ARRAY_STEP(base) (0x1000U)
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*!
* @}
*/
#endif /* _FSL_EDMA_SOC_H_ */

View File

@ -0,0 +1,312 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_eim.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.eim"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to EIM bases for each instance. */
static EIM_Type *const s_eimBases[] = EIM_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to EIM clocks for each instance. */
static const clock_ip_name_t s_eimClocks[] = EIM_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t EIM_GetInstance(EIM_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_eimBases); instance++)
{
if (s_eimBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_eimBases));
return instance;
}
/*!
* brief EIM module initialization function.
*
* param base EIM base address.
*/
void EIM_Init(EIM_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate EIM clock. */
CLOCK_EnableClock(s_eimClocks[EIM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
base->EIMCR = 0x00U;
base->EICHEN = 0x00U;
}
/*!
* brief Deinitializes the EIM.
*
*/
void EIM_Deinit(EIM_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate EIM clock. */
CLOCK_DisableClock(s_eimClocks[EIM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
void EIM_InjectCheckBitError(EIM_Type *base, eim_memory_channel_t channel, uint8_t mask)
{
switch ((uint8_t)channel)
{
case 0U:
base->EICHD0_WORD0 = EIM_EICHD0_WORD0_CHKBIT_MASK(mask);
break;
#ifdef EIM_EICHEN_EICH1EN_MASK
case 1U:
base->EICHD1_WORD0 = EIM_EICHD1_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH2EN_MASK
case 2U:
base->EICHD2_WORD0 = EIM_EICHD2_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH3EN_MASK
case 3U:
base->EICHD3_WORD0 = EIM_EICHD3_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH4EN_MASK
case 4U:
base->EICHD4_WORD0 = EIM_EICHD4_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH5EN_MASK
case 5U:
base->EICHD5_WORD0 = EIM_EICHD5_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH6EN_MASK
case 6U:
base->EICHD6_WORD0 = EIM_EICHD6_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH7EN_MASK
case 7U:
base->EICHD7_WORD0 = EIM_EICHD7_WORD0_CHKBIT_MASK(mask);
break;
#endif
#ifdef EIM_EICHEN_EICH8EN_MASK
case 8U:
base->EICHD8_WORD0 = EIM_EICHD8_WORD0_CHKBIT_MASK(mask);
break;
#endif
default:
assert(NULL);
break;
}
}
uint8_t EIM_GetCheckBitMask(EIM_Type *base, eim_memory_channel_t channel)
{
uint8_t mask = 0x00U;
switch ((uint8_t)channel)
{
case 0U:
mask = (uint8_t)((base->EICHD0_WORD0 & EIM_EICHD0_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD0_WORD0_CHKBIT_MASK_SHIFT);
break;
#ifdef EIM_EICHEN_EICH1EN_MASK
case 1U:
mask = (uint8_t)((base->EICHD1_WORD0 & EIM_EICHD1_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD1_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH2EN_MASK
case 2U:
mask = (uint8_t)((base->EICHD2_WORD0 & EIM_EICHD2_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD2_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH3EN_MASK
case 3U:
mask = (uint8_t)((base->EICHD3_WORD0 & EIM_EICHD3_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD3_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH4EN_MASK
case 4U:
mask = (uint8_t)((base->EICHD4_WORD0 & EIM_EICHD4_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD4_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH5EN_MASK
case 5U:
mask = (uint8_t)((base->EICHD5_WORD0 & EIM_EICHD5_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD5_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH6EN_MASK
case 6U:
mask = (uint8_t)((base->EICHD6_WORD0 & EIM_EICHD6_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD6_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH7EN_MASK
case 7U:
mask = (uint8_t)((base->EICHD7_WORD0 & EIM_EICHD7_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD7_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
#ifdef EIM_EICHEN_EICH8EN_MASK
case 8U:
mask = (uint8_t)((base->EICHD8_WORD0 & EIM_EICHD8_WORD0_CHKBIT_MASK_MASK) >>
EIM_EICHD8_WORD0_CHKBIT_MASK_SHIFT);
break;
#endif
default:
assert(NULL);
break;
}
return mask;
}
void EIM_InjectDataBitError(EIM_Type *base, eim_memory_channel_t channel, uint8_t mask)
{
switch ((uint8_t)channel)
{
case 0U:
base->EICHD0_WORD1 = mask;
break;
#ifdef EIM_EICHEN_EICH1EN_MASK
case 1U:
base->EICHD1_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH2EN_MASK
case 2U:
base->EICHD2_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH3EN_MASK
case kEIM_MemoryChannelRAMC:
base->EICHD3_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH4EN_MASK
case kEIM_MemoryChannelRAMD:
base->EICHD4_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH5EN_MASK
case kEIM_MemoryChannelRAME:
base->EICHD5_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH6EN_MASK
case kEIM_MemoryChannelRAMF:
base->EICHD6_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH7EN_MASK
case kEIM_MemoryChannelLPCACRAM:
base->EICHD7_WORD1 = mask;
break;
#endif
#ifdef EIM_EICHEN_EICH8EN_MASK
case kEIM_MemoryChannelPKCRAM:
base->EICHD8_WORD1 = mask;
break;
#endif
default:
assert(NULL);
break;
}
}
uint32_t EIM_GetDataBitMask(EIM_Type *base, eim_memory_channel_t channel)
{
uint32_t mask = 0x00U;
switch ((uint8_t)channel)
{
case 0U:
mask = (base->EICHD0_WORD0 & EIM_EICHD0_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD0_WORD1_B0_3DATA_MASK_SHIFT;
break;
#ifdef EIM_EICHEN_EICH1EN_MASK
case 1U:
mask = (base->EICHD1_WORD0 & EIM_EICHD1_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD1_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH2EN_MASK
case 2U:
mask = (base->EICHD2_WORD0 & EIM_EICHD2_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD2_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH3EN_MASK
case 3U:
mask = (base->EICHD3_WORD0 & EIM_EICHD3_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD3_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH4EN_MASK
case 4U:
mask = (base->EICHD4_WORD0 & EIM_EICHD4_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD4_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH5EN_MASK
case 5U:
mask = (base->EICHD5_WORD0 & EIM_EICHD5_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD5_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH6EN_MASK
case 6U:
mask = (base->EICHD6_WORD0 & EIM_EICHD6_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD6_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH7EN_MASK
case 7U:
mask = (base->EICHD7_WORD0 & EIM_EICHD7_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD7_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
#ifdef EIM_EICHEN_EICH8EN_MASK
case 8U:
mask = (base->EICHD8_WORD1 & EIM_EICHD8_WORD1_B0_3DATA_MASK_MASK) >> EIM_EICHD8_WORD1_B0_3DATA_MASK_SHIFT;
break;
#endif
default:
assert(NULL);
break;
}
return mask;
}

View File

@ -0,0 +1,144 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_EIM_H_
#define FSL_EIM_H_
#include "fsl_common.h"
/*!
* @addtogroup eim
* @{
*/
/******************************************************************************
* Definitions.
*****************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief Driver version. */
#define FSL_ERM_DRIVER_VERSION (MAKE_VERSION(2U, 0U, 1U))
/*! @} */
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief EIM module initialization function.
*
* @param base EIM base address.
*/
void EIM_Init(EIM_Type *base);
/*!
* @brief De-initializes the EIM.
*
*/
void EIM_Deinit(EIM_Type *base);
/*! @} */
/*!
* @name functional
* @{
*/
/*!
* @brief EIM module enable global error injection.
*
* @param base EIM base address.
* @param mask The interrupts to enable.
*/
static inline void EIM_EnableGlobalErrorInjection(EIM_Type *base, bool enable)
{
if (enable)
{
base->EIMCR = EIM_EIMCR_GEIEN_MASK;
}
else
{
base->EIMCR = ~EIM_EIMCR_GEIEN_MASK;
}
}
/*!
* @brief EIM module enable error injection for memory channel n, this function enables the corresponding error
* injection channel. The Global Error Injection Enable function must also be called to enable error injection.
*
* @param base EIM base address.
* @param mask The interrupts to enable. Refer to "_eim_error_injection_channel_enable" enumeration.
*/
static inline void EIM_EnableErrorInjectionChannels(EIM_Type *base, uint32_t mask)
{
base->EICHEN |= mask;
}
/*!
* @brief EIM module disable error injection for memory channel n.
*
* @param base EIM base address.
* @param mask The interrupts to enable. Refer to "_eim_error_injection_channel_enable" enumeration.
*/
static inline void EIM_DisableErrorInjectionChannels(EIM_Type *base, uint32_t mask)
{
base->EICHEN &= ~mask;
}
/*!
* @brief EIM module inject checkbit error for memory channel n, an attempt to invert more than 2 bits in one operation
* might result in undefined behavior.
*
* @param base EIM base address.
* @param channel memory channel.
* @param mask The interrupts to enable.
*/
void EIM_InjectCheckBitError(EIM_Type *base, eim_memory_channel_t channel, uint8_t mask);
/*!
* @brief EIM module get checkbit mask for memory channel n.
*
* @param base EIM base address.
* @param channel memory channel.
* @retval return checkbit mask.
*/
uint8_t EIM_GetCheckBitMask(EIM_Type *base, eim_memory_channel_t channel);
/*!
* @brief EIM module inject databit error for memory channel n, an attempt to invert more than 2 bits in one operation
* might result in undefined behavior.
*
* @param base EIM base address.
* @param channel memory channel.
* @param mask The interrupts to enable.
*/
void EIM_InjectDataBitError(EIM_Type *base, eim_memory_channel_t channel, uint8_t mask);
/*!
* @brief EIM module get databit mask for memory channel n.
*
* @param base EIM base address.
* @param channel memory channel.
* @retval return checkbit mask.
*/
uint32_t EIM_GetDataBitMask(EIM_Type *base, eim_memory_channel_t channel);
/*! @}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif

View File

@ -0,0 +1,301 @@
/*
* Copyright 2022, 2023 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_eqdc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.eqdc"
#endif
#if defined(EQDC_RSTS)
#define EQDC_RESETS_ARRAY EQDC_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for EQDC module.
*
* @param base EQDC peripheral base address
*/
static uint32_t EQDC_GetInstance(EQDC_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to EQDC bases for each instance. */
static EQDC_Type *const s_eqdcBases[] = EQDC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to EQDC clocks for each instance. */
#if defined(QDC_CLOCKS)
static const clock_ip_name_t s_eqdcClocks[] = QDC_CLOCKS;
#elif defined(ENC_CLOCKS)
static const clock_ip_name_t s_eqdcClocks[] = ENC_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(EQDC_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_eqdcResets[] = EQDC_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t EQDC_GetInstance(EQDC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_eqdcBases); instance++)
{
if (s_eqdcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_eqdcBases));
return instance;
}
/*
* Initializes the EQDC module.
*
* This function initializes the EQDC by enabling the IP bus clock (optional).
*
* param base EQDC peripheral base address.
* param psConfig Pointer to configuration structure.
*/
void EQDC_Init(EQDC_Type *base, const eqdc_config_t *psConfig)
{
assert(NULL != psConfig);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(EQDC_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_eqdcResets[EQDC_GetInstance(base)]);
#endif
/* Initialize Double-set registers */
EQDC_ClearBufferedRegisterLoadUpdateMode(base);
EQDC_ClearEqdcLdok(base);
/* Counter value. */
EQDC_SetPositionCounterValue(base, psConfig->positionCounterValue);
/* Initial value. */
EQDC_SetInitialPositionValue(base, psConfig->positionInitialValue);
/* Modulus value. */
EQDC_SetPositionModulusValue(base, psConfig->positionModulusValue);
/* Compare value. */
EQDC_SetPositionCompare0Value(base, psConfig->positionCompareValue[0]);
EQDC_SetPositionCompare1Value(base, psConfig->positionCompareValue[1]);
EQDC_SetPositionCompare2Value(base, psConfig->positionCompareValue[2]);
EQDC_SetPositionCompare3Value(base, psConfig->positionCompareValue[3]);
EQDC_SetEqdcLdok(base);
while (EQDC_GetEqdcLdok(base) != 0U)
{
}
/* Watchdog. */
EQDC_SetWatchdogTimeout(base, psConfig->watchdogTimeoutValue);
/* Clear EQDC_REV */
base->REV = 0U;
/* EQDC_IMR. */
base->IMR = EQDC_IMR_FPHA(psConfig->filterPhaseA) | EQDC_IMR_FPHB(psConfig->filterPhaseB) |
EQDC_IMR_FIND_PRE(psConfig->filterIndPre) | EQDC_IMR_FHOM_ENA(psConfig->filterHomEna);
/* EQDC_FILT. */
base->FILT = EQDC_FILT_PRSC(psConfig->prescaler) | /* Prescaler used by LASTEDGE and POSDPER. */
EQDC_FILT_FILT_CS(psConfig->filterClockSourceselection) |
EQDC_FILT_FILT_CNT(psConfig->filterSampleCount) | EQDC_FILT_FILT_PER(psConfig->filterSamplePeriod);
/* EQDC_CTRL. */
base->CTRL = EQDC_CTRL_W1C_FLAGS | /* W1C flags. */
(uint16_t)psConfig->homeEnableInitPosCounterMode | /* HOME Enable trigger. */
(uint16_t)psConfig->indexPresetInitPosCounterMode | /* INDEX Preset trigger. */
EQDC_CTRL_REV(psConfig->enableReverseDirection) | /* Reverse direction. */
EQDC_CTRL_WDE(psConfig->enableWatchdog) | /* Enable watchdog. */
EQDC_CTRL_DMAEN(psConfig->enableDma); /* Enable Dma. */
/* Set mode of count. */
EQDC_SetCountMode(base, psConfig->countMode); /* eqdcoder count mode. */
/* EQDC_CTRL2. */
base->CTRL2 =
EQDC_CTRL2_ONCE(psConfig->countOnce) |
EQDC_CTRL2_INITPOS(psConfig->enableTriggerInitPositionCounter) | /* TRIGGER initializes position counter. */
#if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
EQDC_CTRL2_EMIP(psConfig->enableIndexInitPositionCounter)| /* Index Event Edge Mark initializes position counter */
#endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
EQDC_CTRL2_PMEN(psConfig->enablePeriodMeasurement) | /* Enable period measurement. */
EQDC_CTRL2_OUTCTL(psConfig->outputPulseMode) | /* Output pulse. */
EQDC_CTRL2_REVMOD(psConfig->revolutionCountCondition) | /* Revolution count condition. */
EQDC_CTRL2_LDMOD(psConfig->bufferedRegisterLoadMode) | /* Buffered register load (Update) mode select. */
EQDC_CTRL2_UPDPOS(psConfig->enableTriggerClearPositionRegisters) | /* TRIGGER clears position register. */
EQDC_CTRL2_UPDHLD(psConfig->enableTriggerHoldPositionRegisters); /* TRIGGER loads position registers. */
/* Set mode of operation. */
EQDC_SetOperateMode(base, psConfig->operateMode); /* eqdcoder work mode. */
/* Enable interrupts. */
EQDC_EnableInterrupts(base, psConfig->enabledInterruptsMask);
}
/*
* De-initializes the EQDC module.
*
* This function deinitializes the EQDC by:
* 1. Disables the IP bus clock (optional).
*
* param base EQDC peripheral base address.
*/
void EQDC_Deinit(EQDC_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* Gets an available pre-defined configuration.
*
* The default value are:
* psConfig->enableReverseDirection = false;
* psConfig->countOnce = false;
* psConfig->operateMode = kEQDC_QuadratureDecodeOperationMode;
* psConfig->countMode = kEQDC_QuadratureX4;
* psConfig->homeEnableInitPosCounterMode = kEQDC_HomeInitPosCounterDisabled;
* psConfig->indexPresetInitPosCounterMode = kEQDC_IndexInitPosCounterDisabled;
* psConfig->enableIndexInitPositionCounter = false;
* psConfig->enableDma = false;
* psConfig->bufferedRegisterLoadMode = false;
* psConfig->enableTriggerInitPositionCounter = false;
* psConfig->enableTriggerClearPositionRegisters = false;
* psConfig->enableTriggerHoldPositionRegisters = false;
* psConfig->enableWatchdog = false;
* psConfig->watchdogTimeoutValue = 0xFFFFU;
* psConfig->filterPhaseA = 0U;
* psConfig->filterPhaseB = 0U;
* psConfig->filterIndPre = 0U;
* psConfig->filterHomEna = 0U;
* psConfig->filterClockSourceselection = false;
* psConfig->filterSampleCount = kEQDC_Filter3Samples;
* psConfig->filterSamplePeriod = 0U;
* psConfig->outputPulseMode = kEQDC_OutputPulseOnCounterEqualCompare;
* psConfig->positionCompareValue[0] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[1] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[2] = 0xFFFFFFFFU;
* psConfig->positionCompareValue[3] = 0xFFFFFFFFU;
* psConfig->revolutionCountCondition = kEQDC_RevolutionCountOnIndexPulse;
* psConfig->positionModulusValue = 0U;
* psConfig->positionInitialValue = 0U;
* psConfig->positionCounterValue = 0U;
* psConfig->enablePeriodMeasurement = false;
* psConfig->prescaler = kEQDC_Prescaler1;
* psConfig->enabledInterruptsMask = 0U;
*
* param psConfig Pointer to configuration structure.
*/
void EQDC_GetDefaultConfig(eqdc_config_t *psConfig)
{
assert(NULL != psConfig);
psConfig->enableReverseDirection = false;
psConfig->countOnce = false;
psConfig->operateMode = kEQDC_QuadratureDecodeOperationMode; /*!< Decode Mode. */
psConfig->countMode = kEQDC_QuadratureX4;
psConfig->homeEnableInitPosCounterMode = kEQDC_HomeInitPosCounterDisabled;
psConfig->indexPresetInitPosCounterMode = kEQDC_IndexInitPosCounterDisabled;
#if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
psConfig->enableIndexInitPositionCounter = false;
#endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
psConfig->enableDma = false;
psConfig->bufferedRegisterLoadMode = false;
psConfig->enableTriggerInitPositionCounter = false;
psConfig->enableTriggerClearPositionRegisters = false;
psConfig->enableTriggerHoldPositionRegisters = false;
psConfig->enableWatchdog = false;
psConfig->watchdogTimeoutValue = 0xFFFFU;
psConfig->filterPhaseA = 0U;
psConfig->filterPhaseB = 0U;
psConfig->filterIndPre = 0U;
psConfig->filterHomEna = 0U;
psConfig->filterClockSourceselection = false;
psConfig->filterSampleCount = kEQDC_Filter3Samples;
psConfig->filterSamplePeriod = 0U;
psConfig->outputPulseMode = kEQDC_OutputPulseOnCounterEqualCompare;
psConfig->positionCompareValue[0] = 0xFFFFFFFFU;
psConfig->positionCompareValue[1] = 0xFFFFFFFFU;
psConfig->positionCompareValue[2] = 0xFFFFFFFFU;
psConfig->positionCompareValue[3] = 0xFFFFFFFFU;
psConfig->revolutionCountCondition = kEQDC_RevolutionCountOnIndexPulse;
psConfig->positionModulusValue = 0U;
psConfig->positionInitialValue = 0U;
psConfig->positionCounterValue = 0U;
psConfig->enablePeriodMeasurement = false;
psConfig->prescaler = kEQDC_Prescaler1;
psConfig->enabledInterruptsMask = 0U;
}
/*
* Initializes the mode of operation.
*
* The Quadrature Decoder operates in following 4 operation modes:
* 1.Quadrature Decode(QDC) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 0)
* 2.Quadrature Count(QCT) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 1)
* 3.Single Phase Decode(PH1DC) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 0)
* 4.Single Phase Count(PH1CT) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 1)
*
* param base EQDC peripheral base address.
* param psConfig Pointer to configuration structure.
*/
void EQDC_SetOperateMode(EQDC_Type *base, eqdc_operate_mode_t operateMode)
{
switch (operateMode)
{
case kEQDC_QuadratureDecodeOperationMode:
base->CTRL &= ~EQDC_CTRL_PH1_MASK;
base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_QuadratureCountOperationMode:
base->CTRL &= ~EQDC_CTRL_PH1_MASK;
base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_SinglePhaseDecodeOperationMode:
base->CTRL |= EQDC_CTRL_PH1_MASK;
base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
break;
case kEQDC_SinglePhaseCountOperationMode:
base->CTRL |= EQDC_CTRL_PH1_MASK;
base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
break;
default:
assert(false);
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,317 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_erm.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.erm"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to ERM bases for each instance. */
static ERM_Type *const s_ermBases[] = ERM_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to ERM clocks for each instance. */
static const clock_ip_name_t s_ermClocks[] = ERM_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t ERM_GetInstance(ERM_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_ermBases); instance++)
{
if (s_ermBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_ermBases));
return instance;
}
/*!
* brief ERM module initialization function.
*
* param base ERM base address.
*/
void ERM_Init(ERM_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate ERM clock. */
CLOCK_EnableClock(s_ermClocks[ERM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
base->CR0 = 0x00U;
#ifdef ERM_CR1_ENCIE8_MASK
base->CR1 = 0x00U;
#endif
base->SR0 = 0xFFFFFFFFU;
#ifdef ERM_SR1_SBC8_MASK
base->SR1 = 0xFFFFFFFFU;
#endif
}
/*!
* brief Deinitializes the ERM.
*
*/
void ERM_Deinit(ERM_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate ERM clock. */
CLOCK_DisableClock(s_ermClocks[ERM_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
uint32_t ERM_GetMemoryErrorAddr(ERM_Type *base, erm_memory_channel_t channel)
{
uint32_t absoluteErrorAddress = 0x00U;
switch ((uint8_t)channel)
{
case 0U:
absoluteErrorAddress = base->EAR0;
break;
#ifdef ERM_EAR1_EAR_MASK
case 1U:
absoluteErrorAddress = base->EAR1;
break;
#endif
#ifdef ERM_EAR2_EAR_MASK
case 2U:
absoluteErrorAddress = base->EAR2;
break;
#endif
#ifdef ERM_EAR3_EAR_MASK
case 3U:
absoluteErrorAddress = base->EAR3;
break;
#endif
#ifdef ERM_EAR4_EAR_MASK
case 4U:
absoluteErrorAddress = base->EAR4;
break;
#endif
#ifdef ERM_EAR5_EAR_MASK
case 5U:
absoluteErrorAddress = base->EAR5;
break;
#endif
#ifdef ERM_EAR6_EAR_MASK
case 6U:
absoluteErrorAddress = base->EAR6;
break;
#endif
default:
assert(NULL);
break;
}
return absoluteErrorAddress;
}
uint32_t ERM_GetSyndrome(ERM_Type *base, erm_memory_channel_t channel)
{
uint32_t syndrome = 0x00U;
switch ((uint8_t)channel)
{
case 0U:
syndrome = (base->SYN0 & ERM_SYN0_SYNDROME_MASK) >> ERM_SYN0_SYNDROME_SHIFT;
break;
#ifdef ERM_SYN1_SYNDROME_MASK
case 1U:
syndrome = (base->SYN1 & ERM_SYN1_SYNDROME_MASK) >> ERM_SYN1_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN2_SYNDROME_MASK
case 2U:
syndrome = (base->SYN2 & ERM_SYN2_SYNDROME_MASK) >> ERM_SYN2_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN3_SYNDROME_MASK
case 3U:
syndrome = (base->SYN3 & ERM_SYN3_SYNDROME_MASK) >> ERM_SYN3_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN4_SYNDROME_MASK
case 4U:
syndrome = (base->SYN4 & ERM_SYN4_SYNDROME_MASK) >> ERM_SYN4_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN5_SYNDROME_MASK
case 5U:
syndrome = (base->SYN5 & ERM_SYN5_SYNDROME_MASK) >> ERM_SYN5_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN6_SYNDROME_MASK
case 6U:
syndrome = (base->SYN6 & ERM_SYN6_SYNDROME_MASK) >> ERM_SYN6_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN7_SYNDROME_MASK
case 7U:
syndrome = (base->SYN7 & ERM_SYN6_SYNDROME_MASK) >> ERM_SYN7_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN8_SYNDROME_MASK
case 8U:
syndrome = (base->SYN8 & ERM_SYN8_SYNDROME_MASK) >> ERM_SYN8_SYNDROME_SHIFT;
break;
#endif
#ifdef ERM_SYN9_SYNDROME_MASK
case 8U:
syndrome = (base->SYN9 & ERM_SYN9_SYNDROME_MASK) >> ERM_SYN9_SYNDROME_SHIFT;
break;
#endif
default:
assert(NULL);
break;
}
return syndrome;
}
uint32_t ERM_GetErrorCount(ERM_Type *base, erm_memory_channel_t channel)
{
uint32_t count = 0x00U;
switch ((uint8_t)channel)
{
case 0U:
count = (base->CORR_ERR_CNT0 & ERM_CORR_ERR_CNT0_COUNT_MASK) >> ERM_CORR_ERR_CNT0_COUNT_SHIFT;
break;
#ifdef ERM_CORR_ERR_CNT1_COUNT_MASK
case 1U:
count = (base->CORR_ERR_CNT1 & ERM_CORR_ERR_CNT1_COUNT_MASK) >> ERM_CORR_ERR_CNT1_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT2_COUNT_MASK
case 2U:
count = (base->CORR_ERR_CNT2 & ERM_CORR_ERR_CNT2_COUNT_MASK) >> ERM_CORR_ERR_CNT2_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT3_COUNT_MASK
case 3U:
count = (base->CORR_ERR_CNT3 & ERM_CORR_ERR_CNT3_COUNT_MASK) >> ERM_CORR_ERR_CNT3_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT4_COUNT_MASK
case 4U:
count = (base->CORR_ERR_CNT4 & ERM_CORR_ERR_CNT4_COUNT_MASK) >> ERM_CORR_ERR_CNT4_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT5_COUNT_MASK
case 5U:
count = (base->CORR_ERR_CNT5 & ERM_CORR_ERR_CNT5_COUNT_MASK) >> ERM_CORR_ERR_CNT5_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT6_COUNT_MASK
case 6U:
count = (base->CORR_ERR_CNT6 & ERM_CORR_ERR_CNT6_COUNT_MASK) >> ERM_CORR_ERR_CNT6_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT7_COUNT_MASK
case 7U:
count = (base->CORR_ERR_CNT7 & ERM_CORR_ERR_CNT7_COUNT_MASK) >> ERM_CORR_ERR_CNT7_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT8_COUNT_MASK
case 8U:
count = (base->CORR_ERR_CNT8 & ERM_CORR_ERR_CNT8_COUNT_MASK) >> ERM_CORR_ERR_CNT8_COUNT_SHIFT;
break;
#endif
#ifdef ERM_CORR_ERR_CNT9_COUNT_MASK
case 9U:
count = (base->CORR_ERR_CNT9 & ERM_CORR_ERR_CNT9_COUNT_MASK) >> ERM_CORR_ERR_CNT9_COUNT_SHIFT;
break;
#endif
default:
assert(NULL);
break;
}
return count;
}
void ERM_ResetErrorCount(ERM_Type *base, erm_memory_channel_t channel)
{
switch ((uint8_t)channel)
{
case 0U:
base->CORR_ERR_CNT0 = 0x00U;
break;
#ifdef ERM_CORR_ERR_CNT1_COUNT_MASK
case 1U:
base->CORR_ERR_CNT1 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT2_COUNT_MASK
case 2U:
base->CORR_ERR_CNT2 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT3_COUNT_MASK
case 3U:
base->CORR_ERR_CNT3 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT4_COUNT_MASK
case 4U:
base->CORR_ERR_CNT4 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT5_COUNT_MASK
case 5U:
base->CORR_ERR_CNT5 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT6_COUNT_MASK
case 6U:
base->CORR_ERR_CNT6 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT6_COUNT_MASK
case 7U:
base->CORR_ERR_CNT7 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT8_COUNT_MASK
case 8U:
base->CORR_ERR_CNT8 = 0x00U;
break;
#endif
#ifdef ERM_CORR_ERR_CNT9_COUNT_MASK
case 9U:
base->CORR_ERR_CNT9 = 0x00U;
break;
#endif
default:
assert(NULL);
break;
}
}

View File

@ -0,0 +1,235 @@
/*
* Copyright 2022 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_ERM_H_
#define FSL_ERM_H_
#include "fsl_common.h"
/*!
* @addtogroup erm
* @{
*/
/******************************************************************************
* Definitions.
*****************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief Driver version. */
#define FSL_ERM_DRIVER_VERSION (MAKE_VERSION(2U, 0U, 1U))
/*! @} */
/*!
* @brief ERM interrupt configuration structure, default settings all disabled, _erm_interrupt_enable.
*
* This structure contains the settings for all of the ERM interrupt configurations.
*/
enum
{
kERM_SingleCorrectionIntEnable = 0x08U, /*!< Single Correction Interrupt Notification enable.*/
kERM_NonCorrectableIntEnable = 0x04U, /*!< Non-Correction Interrupt Notification enable.*/
kERM_AllInterruptsEnable = 0xFFFFFFFFUL, /*!< All Interrupts enable */
};
/*!
* @brief ERM interrupt status, _erm_interrupt_flag.
*
* This provides constants for the ERM event status for use in the ERM functions.
*/
enum
{
kERM_SingleBitCorrectionIntFlag = 0x08U, /*!< Single-Bit Correction Event.*/
kERM_NonCorrectableErrorIntFlag = 0x04U, /*!< Non-Correctable Error Event.*/
kERM_AllIntsFlag = 0xFFFFFFFFUL, /*!< All Events. */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and de-initialization
* @{
*/
/*!
* @brief ERM module initialization function.
*
* @param base ERM base address.
*/
void ERM_Init(ERM_Type *base);
/*!
* @brief De-initializes the ERM.
*
*/
void ERM_Deinit(ERM_Type *base);
/*! @} */
/*!
* @name Interrupt
* @{
*/
/*!
* @brief ERM enable interrupts.
*
* @param base ERM peripheral base address.
* @param channel memory channel.
* @param mask single correction interrupt or non-correction interrupt enable to disable for one specific memory region.
* Refer to "_erm_interrupt_enable" enumeration.
*/
static inline void ERM_EnableInterrupts(ERM_Type *base, erm_memory_channel_t channel, uint32_t mask)
{
uint32_t temp = 0x00U;
if ((uint32_t)channel <= 0x07U)
{
temp = base->CR0;
base->CR0 =
(temp & ~(0x0CUL << ((0x07U - (uint32_t)channel) * 4U))) | (mask << ((0x07U - (uint32_t)channel) * 4U));
}
#ifdef ERM_CR1_ESCIE8_MASK
else
{
temp = base->CR1;
base->CR1 = (temp & ~(0x0CUL << ((0x07U + 0x08U - (uint32_t)channel) * 4U))) |
(mask << ((0x07U + 0x08U - (uint32_t)channel) * 4U));
}
#endif
}
/*!
* @brief ERM module disable interrupts.
*
* @param base ERM base address.
* @param channel memory channel.
* @param mask single correction interrupt or non-correction interrupt enable to disable for one specific memory region.
* Refer to "_erm_interrupt_enable" enumeration.
*/
static inline void ERM_DisableInterrupts(ERM_Type *base, erm_memory_channel_t channel, uint32_t mask)
{
if ((uint32_t)channel <= 0x07U)
{
base->CR0 &= ~(mask << ((0x07U - (uint32_t)channel) * 4U));
}
#ifdef ERM_CR1_ESCIE8_MASK
else
{
base->CR1 &= ~(mask << ((0x07U + 0x08U - (uint32_t)channel) * 4U));
}
#endif
}
/*!
* @brief Gets ERM interrupt flags.
*
* @param base ERM peripheral base address.
* @return ERM event flags.
*/
static inline uint32_t ERM_GetInterruptStatus(ERM_Type *base, erm_memory_channel_t channel)
{
if ((uint32_t)channel <= 0x07U)
{
return ((base->SR0 & (uint32_t)kERM_AllIntsFlag) >> (0x07U - (uint32_t)channel) * 4U);
}
#ifdef ERM_SR1_SBC8_MASK
else
{
return ((base->SR1 & (uint32_t)kERM_AllIntsFlag) >> ((0x07U + 0x08U - (uint32_t)channel) * 4U));
}
#else
{
return 0;
}
#endif
}
/*!
* @brief ERM module clear interrupt status flag.
*
* @param base ERM base address.
* @param mask event flag to clear. Refer to "_erm_interrupt_flag" enumeration.
*/
static inline void ERM_ClearInterruptStatus(ERM_Type *base, erm_memory_channel_t channel, uint32_t mask)
{
if ((uint32_t)channel <= 0x07U)
{
base->SR0 = mask << ((0x07U - (uint32_t)channel) * 4U);
}
#ifdef ERM_SR1_SBC8_MASK
else
{
base->SR1 = mask << ((0x07U + 0x08U - (uint32_t)channel) * 4U);
}
#endif
}
/*! @} */
/*!
* @name functional
* @{
*/
/*!
* @brief ERM get memory error absolute address, which capturing the address of the last ECC event in Memory n.
*
* @param base ERM base address.
* @param channel memory channel.
* @retval memory error absolute address.
*/
uint32_t ERM_GetMemoryErrorAddr(ERM_Type *base, erm_memory_channel_t channel);
/*!
* @brief ERM get syndrome, which identifies the pertinent bit position on a correctable, single-bit data inversion or a
* non-correctable, single-bit address inversion. The syndrome value does not provide any additional diagnostic
* information on non-correctable, multi-bit inversions.
*
* @param base ERM base address.
* @param channel memory channel.
* @retval syndrome value.
*/
uint32_t ERM_GetSyndrome(ERM_Type *base, erm_memory_channel_t channel);
/*!
* @brief ERM get error count, which records the count value of the number of correctable ECC error events for Memory
* n. Non-correctable errors are considered a serious fault, so the ERM does not provide any mechanism to count
* non-correctable errors. Only correctable errors are counted.
*
* @param base ERM base address.
* @param channel memory channel.
* @retval error count.
*/
uint32_t ERM_GetErrorCount(ERM_Type *base, erm_memory_channel_t channel);
/*!
* @brief ERM reset error count.
*
* @param base ERM base address.
* @param channel memory channel.
*/
void ERM_ResetErrorCount(ERM_Type *base, erm_memory_channel_t channel);
/*! @}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexcan_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flexcan_edma"
#endif
/*<! Structure definition for flexcan_edma_private_handle_t. The structure is private. */
typedef struct _flexcan_edma_private_handle
{
CAN_Type *base;
flexcan_edma_handle_t *handle;
} flexcan_edma_private_handle_t;
/* FlexCAN EDMA transfer handle. */
enum _flexcan_edma_tansfer_state
{
KFLEXCAN_RxFifoIdle = 0U, /* Rx Fifo idle. */
KFLEXCAN_RxFifoBusy = 1U, /* Rx Fifo busy. */
};
/*******************************************************************************
* Variables
******************************************************************************/
/* Array of FlexCAN peripheral base address. */
static CAN_Type *const s_flexcanBases[] = CAN_BASE_PTRS;
/* Private handle only used for internally. */
static flexcan_edma_private_handle_t s_flexcanEdmaPrivateHandle[ARRAY_SIZE(s_flexcanBases)];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief FlexCAN EDMA receive finished callback function.
*
* This function is called when FlexCAN Rx FIFO EDMA receive finished.
* It disables the FlexCAN Rx FIFO EDMA request and sends
* @ref kStatus_FLEXCAN_RxFifoIdle to FlexCAN EDMA callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void FLEXCAN_ReceiveFifoEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXCAN_ReceiveFifoEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
handle = handle;
tcds = tcds;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
flexcan_fd_frame_t *framefd;
uint32_t idHitIndex;
#endif
flexcan_edma_private_handle_t *flexcanPrivateHandle = (flexcan_edma_private_handle_t *)param;
/*
* $Branch Coverage Justification$
* (!transferDone) not covered. Unable to simulate DMA transfer error.
*/
if (transferDone)
{
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
if (0U != (flexcanPrivateHandle->base->ERFCR & CAN_ERFCR_ERFEN_MASK))
{
framefd = flexcanPrivateHandle->handle->framefd;
for (uint32_t i = 0; i < flexcanPrivateHandle->handle->frameNum; i++)
{
/* Enhanced Rx FIFO ID HIT offset is changed dynamically according to data length code (DLC) . */
idHitIndex = (DLC_LENGTH_DECODE(framefd->length) + 3U) / 4U;
framefd->idhit = framefd->dataWord[idHitIndex];
/* Clear the unused frame data. */
for (uint32_t j = idHitIndex; j < 16U; j++)
{
framefd->dataWord[j] = 0x0U;
}
framefd++;
}
}
#endif
/* Disable transfer. */
FLEXCAN_TransferAbortReceiveFifoEDMA(flexcanPrivateHandle->base, flexcanPrivateHandle->handle);
if (NULL != flexcanPrivateHandle->handle->callback)
{
flexcanPrivateHandle->handle->callback(flexcanPrivateHandle->base, flexcanPrivateHandle->handle,
kStatus_FLEXCAN_RxFifoIdle, flexcanPrivateHandle->handle->userData);
}
}
}
/*!
* brief Initializes the FlexCAN handle, which is used in transactional functions.
*
* param base FlexCAN peripheral base address.
* param handle Pointer to flexcan_edma_handle_t structure.
* param callback The callback function.
* param userData The parameter of the callback function.
* param rxFifoEdmaHandle User-requested DMA handle for Rx FIFO DMA transfer.
*/
void FLEXCAN_TransferCreateHandleEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *rxFifoEdmaHandle)
{
assert(NULL != handle);
uint32_t instance = FLEXCAN_GetInstance(base);
s_flexcanEdmaPrivateHandle[instance].base = base;
s_flexcanEdmaPrivateHandle[instance].handle = handle;
(void)memset(handle, 0, sizeof(flexcan_edma_handle_t));
handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoIdle;
handle->rxFifoEdmaHandle = rxFifoEdmaHandle;
/* Register Callback. */
handle->callback = callback;
handle->userData = userData;
/* Configure Legacy/Enhanced Rx FIFO DMA callback. */
EDMA_SetCallback(handle->rxFifoEdmaHandle, FLEXCAN_ReceiveFifoEDMACallback, &s_flexcanEdmaPrivateHandle[instance]);
}
/*!
* brief Prepares the eDMA transfer configuration for FLEXCAN Legacy RX FIFO.
*
* This function prepares the eDMA transfer configuration structure according to FLEXCAN Legacy RX FIFO.
*
* param base FlexCAN peripheral base address.
* param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* param pEdmaConfig The user configuration structure of type edma_transfer_t.
*
*/
void FLEXCAN_PrepareTransfConfiguration(CAN_Type *base,
flexcan_fifo_transfer_t *pFifoXfer,
edma_transfer_config_t *pEdmaConfig)
{
assert(NULL != pFifoXfer);
assert(NULL != pFifoXfer->frame);
assert(NULL != pEdmaConfig);
flexcan_frame_t *fifoAddr = (flexcan_frame_t *)FLEXCAN_GetRxFifoHeadAddr(base);
#if (defined(FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER)
EDMA_PrepareTransfer(pEdmaConfig, (void *)fifoAddr, sizeof(flexcan_frame_t), (void *)pFifoXfer->frame,
sizeof(uint32_t), sizeof(flexcan_frame_t), sizeof(flexcan_frame_t) * pFifoXfer->frameNum,
kEDMA_PeripheralToMemory);
#else
/* The Data Size of FLEXCAN Legacy RX FIFO output port is 16 Bytes, but lots of chips not support 16Bytes width DMA
* transfer. These chips always support 4Byte width memory transfer, so we need prepare Memory to Memory mode by 4
* Bytes width mode.
*/
EDMA_PrepareTransfer(pEdmaConfig, (void *)fifoAddr, 4U, (void *)pFifoXfer->frame, sizeof(uint32_t),
sizeof(flexcan_frame_t), sizeof(flexcan_frame_t) * pFifoXfer->frameNum, kEDMA_MemoryToMemory);
#endif
}
/*!
* brief Start Transfer Data from the FLEXCAN Legacy Rx FIFO using eDMA.
*
* This function to Update edma transfer confiugration and Start eDMA transfer
*
* param base FlexCAN peripheral base address.
* param handle Pointer to flexcan_edma_handle_t structure.
* param pEdmaConfig The user configuration structure of type edma_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
*/
status_t FLEXCAN_StartTransferDatafromRxFIFO(CAN_Type *base,
flexcan_edma_handle_t *handle,
edma_transfer_config_t *pEdmaConfig)
{
assert(NULL != handle->rxFifoEdmaHandle);
assert(NULL != pEdmaConfig);
status_t status;
/* If previous Rx FIFO receive not finished. */
if ((uint8_t)KFLEXCAN_RxFifoBusy == handle->rxFifoState)
{
status = kStatus_FLEXCAN_RxFifoBusy;
}
else
{
handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoBusy;
/* Enable FlexCAN Rx FIFO EDMA. */
FLEXCAN_EnableRxFifoDMA(base, true);
/* Submit configuration. */
(void)EDMA_SubmitTransfer(handle->rxFifoEdmaHandle, (const edma_transfer_config_t *)pEdmaConfig);
EDMA_SetModulo(handle->rxFifoEdmaHandle->base, handle->rxFifoEdmaHandle->channel, kEDMA_Modulo16bytes,
kEDMA_ModuloDisable);
/* Start transfer. */
EDMA_StartTransfer(handle->rxFifoEdmaHandle);
status = kStatus_Success;
}
return status;
}
/*!
* brief Receives the CAN Messages from the Legacy Rx FIFO using eDMA.
*
* This function receives the CAN Message using eDMA. This is a non-blocking function, which returns
* right away. After the CAN Message is received, the receive callback function is called.
*
* param base FlexCAN peripheral base address.
* param handle Pointer to flexcan_edma_handle_t structure.
* param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
*/
status_t FLEXCAN_TransferReceiveFifoEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_fifo_transfer_t *pFifoXfer)
{
assert(NULL != handle->rxFifoEdmaHandle);
assert(NULL != pFifoXfer->frame);
edma_transfer_config_t dmaXferConfig = {0};
status_t status;
handle->frameNum = pFifoXfer->frameNum;
/* Prepare transfer. */
FLEXCAN_PrepareTransfConfiguration(base, pFifoXfer, &dmaXferConfig);
/* Submit configuration and start edma transfer. */
status = FLEXCAN_StartTransferDatafromRxFIFO(base, handle, &dmaXferConfig);
return status;
}
/*!
* brief Gets the Legacy Rx Fifo transfer status during a interrupt non-blocking receive.
*
* param base FlexCAN peripheral base address.
* param handle FlexCAN handle pointer.
* param count Number of CAN messages receive so far by the non-blocking transaction.
* retval kStatus_InvalidArgument count is Invalid.
* retval kStatus_Success Successfully return the count.
*/
status_t FLEXCAN_TransferGetReceiveFifoCountEMDA(CAN_Type *base, flexcan_edma_handle_t *handle, size_t *count)
{
assert(NULL != handle);
status_t result = kStatus_Success;
if (handle->rxFifoState == (uint32_t)KFLEXCAN_RxFifoIdle)
{
result = kStatus_NoTransferInProgress;
}
else
{
*count = handle->frameNum -
EDMA_GetRemainingMajorLoopCount(handle->rxFifoEdmaHandle->base, handle->rxFifoEdmaHandle->channel);
}
return result;
}
/*!
* brief Aborts the receive Legacy/Enhanced Rx FIFO process which used eDMA.
*
* This function aborts the receive Legacy/Enhanced Rx FIFO process which used eDMA.
*
* param base FlexCAN peripheral base address.
* param handle Pointer to flexcan_edma_handle_t structure.
*/
void FLEXCAN_TransferAbortReceiveFifoEDMA(CAN_Type *base, flexcan_edma_handle_t *handle)
{
assert(NULL != handle->rxFifoEdmaHandle);
/* Stop transfer. */
EDMA_AbortTransfer(handle->rxFifoEdmaHandle);
handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoIdle;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
handle->framefd = NULL;
#endif
handle->frameNum = 0U;
/* Disable FlexCAN Legacy/Enhanced Rx FIFO EDMA. */
FLEXCAN_EnableRxFifoDMA(base, false);
}
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
/*!
* brief Receives the CAN FD Message from the Enhanced Rx FIFO using eDMA.
*
* This function receives the CAN FD Message using eDMA. This is a non-blocking function, which returns
* right away. After the CAN Message is received, the receive callback function is called.
*
* param base FlexCAN peripheral base address.
* param handle Pointer to flexcan_edma_handle_t structure.
* param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
* retval kStatus_InvalidArgument The watermark configuration is invalid, the watermark need be set to
1 to do successfully EDMA transfer with this API.
*/
status_t FLEXCAN_TransferReceiveEnhancedFifoEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_fifo_transfer_t *pFifoXfer)
{
assert(NULL != handle->rxFifoEdmaHandle);
assert(NULL != pFifoXfer->framefd);
edma_transfer_config_t dmaXferConfig;
edma_minor_offset_config_t dmaMinorOffsetConfig;
status_t status;
flexcan_fd_frame_t *fifoAddr = (flexcan_fd_frame_t *)E_RX_FIFO(base);
uint32_t perReadWords = ((base->ERFCR & CAN_ERFCR_DMALW_MASK) >> CAN_ERFCR_DMALW_SHIFT) + 1U;
uint32_t watermark = ((base->ERFCR & CAN_ERFCR_ERFWM_MASK) >> CAN_ERFCR_ERFWM_SHIFT) + 1U;
/* If previous Rx FIFO receive not finished. */
if ((uint8_t)KFLEXCAN_RxFifoBusy == handle->rxFifoState)
{
status = kStatus_FLEXCAN_RxFifoBusy;
}
else
{
handle->frameNum = pFifoXfer->frameNum;
handle->framefd = pFifoXfer->framefd;
/*!< To reduce the complexity of DMA software configuration, need to set watermark to 1 to make that each DMA
request read once Rx FIFO. Because a DMA transfer cannot be dynamically changed, Number of words read per
transfer (ERFCR[DMALW] + 1) should be programmed so that the Enhanced Rx FIFO element can store the largest
CAN message present on the CAN bus. */
if ((watermark != 1U) || ((sizeof(uint32_t) * perReadWords) != sizeof(flexcan_fd_frame_t)))
{
return kStatus_InvalidArgument;
}
/* Prepare transfer. */
EDMA_PrepareTransfer(
&dmaXferConfig, (void *)fifoAddr, sizeof(uint32_t), (void *)pFifoXfer->framefd, sizeof(uint32_t),
sizeof(uint32_t) * perReadWords, /* minor loop bytes : 4* perReadWords */
sizeof(uint32_t) * perReadWords * handle->frameNum, /* major loop counts : handle->frameNum */
kEDMA_MemoryToMemory);
/* Submit configuration. */
(void)EDMA_SubmitTransfer(handle->rxFifoEdmaHandle, &dmaXferConfig);
dmaMinorOffsetConfig.enableDestMinorOffset = false;
dmaMinorOffsetConfig.enableSrcMinorOffset = true;
dmaMinorOffsetConfig.minorOffset = 128U - sizeof(uint32_t) * perReadWords;
EDMA_SetMinorOffsetConfig(handle->rxFifoEdmaHandle->base, handle->rxFifoEdmaHandle->channel,
&dmaMinorOffsetConfig);
EDMA_SetModulo(handle->rxFifoEdmaHandle->base, handle->rxFifoEdmaHandle->channel, kEDMA_Modulo128bytes,
kEDMA_ModuloDisable);
handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoBusy;
/* Enable FlexCAN Rx FIFO EDMA. */
FLEXCAN_EnableRxFifoDMA(base, true);
/* Start transfer. */
EDMA_StartTransfer(handle->rxFifoEdmaHandle);
status = kStatus_Success;
}
return status;
}
#endif

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXCAN_EDMA_H_
#define FSL_FLEXCAN_EDMA_H_
#include "fsl_flexcan.h"
#include "fsl_edma.h"
/*!
* @addtogroup flexcan_edma_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexCAN EDMA driver version. */
#define FSL_FLEXCAN_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 11, 3))
/*! @} */
/* Forward declaration of the handle typedef. */
typedef struct _flexcan_edma_handle flexcan_edma_handle_t;
/*! @brief FlexCAN transfer callback function. */
typedef void (*flexcan_edma_transfer_callback_t)(CAN_Type *base,
flexcan_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief FlexCAN eDMA handle
*/
struct _flexcan_edma_handle
{
flexcan_edma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< FlexCAN callback function parameter.*/
edma_handle_t *rxFifoEdmaHandle; /*!< The EDMA handler for Rx FIFO. */
volatile uint8_t rxFifoState; /*!< Rx FIFO transfer state. */
size_t frameNum; /*!< The number of messages that need to be received. */
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
flexcan_fd_frame_t *framefd; /*!< Point to the buffer of CAN Message to be received from Enhanced Rx FIFO. */
#endif
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the FlexCAN handle, which is used in transactional functions.
*
* @param base FlexCAN peripheral base address.
* @param handle Pointer to flexcan_edma_handle_t structure.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @param rxFifoEdmaHandle User-requested DMA handle for Rx FIFO DMA transfer.
*/
void FLEXCAN_TransferCreateHandleEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *rxFifoEdmaHandle);
/*!
* @brief Prepares the eDMA transfer configuration for FLEXCAN Legacy RX FIFO.
*
* This function prepares the eDMA transfer configuration structure according to FLEXCAN Legacy RX FIFO.
*
* @param base FlexCAN peripheral base address.
* @param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* @param pEdmaConfig The user configuration structure of type edma_transfer_t.
*
*/
void FLEXCAN_PrepareTransfConfiguration(CAN_Type *base,
flexcan_fifo_transfer_t *pFifoXfer,
edma_transfer_config_t *pEdmaConfig);
/*!
* @brief Start Transfer Data from the FLEXCAN Legacy Rx FIFO using eDMA.
*
* This function to Update edma transfer confiugration and Start eDMA transfer
*
* @param base FlexCAN peripheral base address.
* @param handle Pointer to flexcan_edma_handle_t structure.
* @param pEdmaConfig The user configuration structure of type edma_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
*/
status_t FLEXCAN_StartTransferDatafromRxFIFO(CAN_Type *base,
flexcan_edma_handle_t *handle,
edma_transfer_config_t *pEdmaConfig);
/*!
* @brief Receives the CAN Message from the Legacy Rx FIFO using eDMA.
*
* This function receives the CAN Message using eDMA. This is a non-blocking function, which returns
* right away. After the CAN Message is received, the receive callback function is called.
*
* @param base FlexCAN peripheral base address.
* @param handle Pointer to flexcan_edma_handle_t structure.
* @param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
*/
status_t FLEXCAN_TransferReceiveFifoEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_fifo_transfer_t *pFifoXfer);
/*!
* @brief Gets the Legacy Rx Fifo transfer status during a interrupt non-blocking receive.
*
* @param base FlexCAN peripheral base address.
* @param handle FlexCAN handle pointer.
* @param count Number of CAN messages receive so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXCAN_TransferGetReceiveFifoCountEMDA(CAN_Type *base, flexcan_edma_handle_t *handle, size_t *count);
/*!
* @brief Aborts the receive Legacy/Enhanced Rx FIFO process which used eDMA.
*
* This function aborts the receive Legacy/Enhanced Rx FIFO process which used eDMA.
*
* @param base FlexCAN peripheral base address.
* @param handle Pointer to flexcan_edma_handle_t structure.
*/
void FLEXCAN_TransferAbortReceiveFifoEDMA(CAN_Type *base, flexcan_edma_handle_t *handle);
#if (defined(FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO) && FSL_FEATURE_FLEXCAN_HAS_ENHANCED_RX_FIFO)
/*!
* @brief Receives the CAN FD Message from the Enhanced Rx FIFO using eDMA.
*
* This function receives the CAN FD Message using eDMA. This is a non-blocking function, which returns
* right away. After the CAN Message is received, the receive callback function is called.
*
* @param base FlexCAN peripheral base address.
* @param handle Pointer to flexcan_edma_handle_t structure.
* @param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
*/
status_t FLEXCAN_TransferReceiveEnhancedFifoEDMA(CAN_Type *base,
flexcan_edma_handle_t *handle,
flexcan_fifo_transfer_t *pFifoXfer);
/*!
* @brief Gets the Enhanced Rx Fifo transfer status during a interrupt non-blocking receive.
*
* @param base FlexCAN peripheral base address.
* @param handle FlexCAN handle pointer.
* @param count Number of CAN messages receive so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
static inline status_t FLEXCAN_TransferGetReceiveEnhancedFifoCountEMDA(CAN_Type *base,
flexcan_edma_handle_t *handle,
size_t *count)
{
return FLEXCAN_TransferGetReceiveFifoCountEMDA(base, handle, count);
}
#endif
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_FLEXCAN_EDMA_H_ */

View File

@ -0,0 +1,511 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flexio"
#endif
/*< @brief user configurable flexio handle count. */
#define FLEXIO_HANDLE_COUNT 2
#if defined(FLEXIO_RSTS)
#define FLEXIO_RESETS_ARRAY FLEXIO_RSTS
#elif defined(FLEXIO_RSTS_N)
#define FLEXIO_RESETS_ARRAY FLEXIO_RSTS_N
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to flexio bases for each instance. */
FLEXIO_Type *const s_flexioBases[] = FLEXIO_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to flexio clocks for each instance. */
const clock_ip_name_t s_flexioClocks[] = FLEXIO_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*< @brief pointer to array of FLEXIO handle. */
static void *s_flexioHandle[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO IP types. */
static void *s_flexioType[FLEXIO_HANDLE_COUNT];
/*< @brief pointer to array of FLEXIO Isr. */
static flexio_isr_t s_flexioIsr[FLEXIO_HANDLE_COUNT];
/* FlexIO common IRQ Handler. */
static void FLEXIO_CommonIRQHandler(void);
#if defined(FLEXIO_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_flexioResets[] = FLEXIO_RESETS_ARRAY;
#endif
/*******************************************************************************
* Codes
******************************************************************************/
/*!
* brief Get instance number for FLEXIO module.
*
* param base FLEXIO peripheral base address.
*/
uint32_t FLEXIO_GetInstance(FLEXIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_flexioBases); instance++)
{
if (s_flexioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_flexioBases));
return instance;
}
/*!
* brief Configures the FlexIO with a FlexIO configuration. The configuration structure
* can be filled by the user or be set with default values by FLEXIO_GetDefaultConfig().
*
* Example
code
flexio_config_t config = {
.enableFlexio = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false
};
FLEXIO_Configure(base, &config);
endcode
*
* param base FlexIO peripheral base address
* param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig)
{
uint32_t ctrlReg = 0;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_EnableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(FLEXIO_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_flexioResets[FLEXIO_GetInstance(base)]);
#endif
FLEXIO_Reset(base);
ctrlReg = base->CTRL;
ctrlReg &= ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
ctrlReg |= (FLEXIO_CTRL_DBGE(userConfig->enableInDebug) | FLEXIO_CTRL_FASTACC(userConfig->enableFastAccess) |
FLEXIO_CTRL_FLEXEN(userConfig->enableFlexio));
if (!userConfig->enableInDoze)
{
ctrlReg |= FLEXIO_CTRL_DOZEN_MASK;
}
base->CTRL = ctrlReg;
}
/*!
* brief Gates the FlexIO clock. Call this API to stop the FlexIO clock.
*
* note After calling this API, call the FLEXO_Init to use the FlexIO module.
*
* param base FlexIO peripheral base address
*/
void FLEXIO_Deinit(FLEXIO_Type *base)
{
FLEXIO_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
CLOCK_DisableClock(s_flexioClocks[FLEXIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* brief Gets the default configuration to configure the FlexIO module. The configuration
* can used directly to call the FLEXIO_Configure().
*
* Example:
code
flexio_config_t config;
FLEXIO_GetDefaultConfig(&config);
endcode
*
* param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig)
{
assert(userConfig != NULL);
/* Initializes the configure structure to zero. */
(void)memset(userConfig, 0, sizeof(*userConfig));
userConfig->enableFlexio = true;
userConfig->enableInDoze = false;
userConfig->enableInDebug = true;
userConfig->enableFastAccess = false;
}
/*!
* brief Resets the FlexIO module.
*
* param base FlexIO peripheral base address
*/
void FLEXIO_Reset(FLEXIO_Type *base)
{
/*do software reset, software reset operation affect all other FLEXIO registers except CTRL*/
base->CTRL |= FLEXIO_CTRL_SWRST_MASK;
base->CTRL = 0;
}
/*!
* brief Gets the shifter buffer address for the DMA transfer usage.
*
* param base FlexIO peripheral base address
* param type Shifter type of flexio_shifter_buffer_type_t
* param index Shifter index
* return Corresponding shifter buffer index
*/
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index)
{
assert(index < FLEXIO_SHIFTBUF_COUNT);
uint32_t address = 0;
switch (type)
{
case kFLEXIO_ShifterBuffer:
address = (uint32_t) & (base->SHIFTBUF[index]);
break;
case kFLEXIO_ShifterBufferBitSwapped:
address = (uint32_t) & (base->SHIFTBUFBIS[index]);
break;
case kFLEXIO_ShifterBufferByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBYS[index]);
break;
case kFLEXIO_ShifterBufferBitByteSwapped:
address = (uint32_t) & (base->SHIFTBUFBBS[index]);
break;
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
case kFLEXIO_ShifterBufferNibbleByteSwapped:
address = (uint32_t) & (base->SHIFTBUFNBS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
case kFLEXIO_ShifterBufferHalfWordSwapped:
address = (uint32_t) & (base->SHIFTBUFHWS[index]);
break;
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
case kFLEXIO_ShifterBufferNibbleSwapped:
address = (uint32_t) & (base->SHIFTBUFNIS[index]);
break;
#endif
default:
address = (uint32_t) & (base->SHIFTBUF[index]);
break;
}
return address;
}
/*!
* brief Configures the shifter with the shifter configuration. The configuration structure
* covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper
* mode, select which timer controls the shifter to shift, whether to generate start bit/stop
* bit, and the polarity of start bit and stop bit.
*
* Example
code
flexio_shifter_config_t config = {
.timerSelect = 0,
.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinPolarity = kFLEXIO_PinActiveLow,
.shifterMode = kFLEXIO_ShifterModeTransmit,
.inputSource = kFLEXIO_ShifterInputFromPin,
.shifterStop = kFLEXIO_ShifterStopBitHigh,
.shifterStart = kFLEXIO_ShifterStartBitLow
};
FLEXIO_SetShifterConfig(base, &config);
endcode
*
* param base FlexIO peripheral base address
* param index Shifter index
* param shifterConfig Pointer to flexio_shifter_config_t structure
*/
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig)
{
base->SHIFTCFG[index] = FLEXIO_SHIFTCFG_INSRC(shifterConfig->inputSource)
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
| FLEXIO_SHIFTCFG_PWIDTH(shifterConfig->parallelWidth)
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
| FLEXIO_SHIFTCFG_SSTOP(shifterConfig->shifterStop) |
FLEXIO_SHIFTCFG_SSTART(shifterConfig->shifterStart);
base->SHIFTCTL[index] =
FLEXIO_SHIFTCTL_TIMSEL(shifterConfig->timerSelect) | FLEXIO_SHIFTCTL_TIMPOL(shifterConfig->timerPolarity) |
FLEXIO_SHIFTCTL_PINCFG(shifterConfig->pinConfig) | FLEXIO_SHIFTCTL_PINSEL(shifterConfig->pinSelect) |
FLEXIO_SHIFTCTL_PINPOL(shifterConfig->pinPolarity) | FLEXIO_SHIFTCTL_SMOD(shifterConfig->shifterMode);
}
/*!
* brief Configures the timer with the timer configuration. The configuration structure
* covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper
* mode, select trigger source for timer and the timer pin output and the timing for timer.
*
* Example
code
flexio_timer_config_t config = {
.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow,
.triggerSource = kFLEXIO_TimerTriggerSourceInternal,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinSelect = 0,
.pinPolarity = kFLEXIO_PinActiveHigh,
.timerMode = kFLEXIO_TimerModeDual8BitBaudBit,
.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset,
.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput,
.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput,
.timerDisable = kFLEXIO_TimerDisableOnTimerCompare,
.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh,
.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable,
.timerStart = kFLEXIO_TimerStartBitEnabled
};
FLEXIO_SetTimerConfig(base, &config);
endcode
*
* param base FlexIO peripheral base address
* param index Timer index
* param timerConfig Pointer to the flexio_timer_config_t structure
*/
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig)
{
base->TIMCFG[index] =
FLEXIO_TIMCFG_TIMOUT(timerConfig->timerOutput) | FLEXIO_TIMCFG_TIMDEC(timerConfig->timerDecrement) |
FLEXIO_TIMCFG_TIMRST(timerConfig->timerReset) | FLEXIO_TIMCFG_TIMDIS(timerConfig->timerDisable) |
FLEXIO_TIMCFG_TIMENA(timerConfig->timerEnable) | FLEXIO_TIMCFG_TSTOP(timerConfig->timerStop) |
FLEXIO_TIMCFG_TSTART(timerConfig->timerStart);
base->TIMCMP[index] = FLEXIO_TIMCMP_CMP(timerConfig->timerCompare);
base->TIMCTL[index] = FLEXIO_TIMCTL_TRGSEL(timerConfig->triggerSelect) |
FLEXIO_TIMCTL_TRGPOL(timerConfig->triggerPolarity) |
FLEXIO_TIMCTL_TRGSRC(timerConfig->triggerSource) |
FLEXIO_TIMCTL_PINCFG(timerConfig->pinConfig) | FLEXIO_TIMCTL_PINSEL(timerConfig->pinSelect) |
FLEXIO_TIMCTL_PINPOL(timerConfig->pinPolarity) | FLEXIO_TIMCTL_TIMOD(timerConfig->timerMode);
}
/*!
* brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* param base Pointer to the FlexIO simulated peripheral type.
* param handle Pointer to the handler for FlexIO simulated peripheral.
* param isr FlexIO simulated peripheral interrupt handler.
* retval kStatus_Success Successfully create the handle.
* retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr)
{
assert(base != NULL);
assert(handle != NULL);
assert(isr != NULL);
uint8_t index;
/* Find the an empty handle pointer to store the handle. */
for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index] == NULL)
{
/* Register FLEXIO simulated driver base, handle and isr. */
s_flexioType[index] = base;
s_flexioHandle[index] = handle;
s_flexioIsr[index] = isr;
break;
}
}
if (index == (uint8_t)FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
/*!
* brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* param base Pointer to the FlexIO simulated peripheral type.
* retval kStatus_Success Successfully create the handle.
* retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UnregisterHandleIRQ(void *base)
{
assert(base != NULL);
uint8_t index;
/* Find the index from base address mappings. */
for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioType[index] == base)
{
/* Unregister FLEXIO simulated driver handle and isr. */
s_flexioType[index] = NULL;
s_flexioHandle[index] = NULL;
s_flexioIsr[index] = NULL;
break;
}
}
if (index == (uint8_t)FLEXIO_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
else
{
return kStatus_Success;
}
}
static void FLEXIO_CommonIRQHandler(void)
{
uint8_t index;
for (index = 0U; index < (uint8_t)FLEXIO_HANDLE_COUNT; index++)
{
if (s_flexioHandle[index] != NULL)
{
s_flexioIsr[index](s_flexioType[index], s_flexioHandle[index]);
}
}
SDK_ISR_EXIT_BARRIER;
}
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER
/*!
* brief Configure a FLEXIO pin used by the board.
*
* To Config the FLEXIO PIN, define a pin configuration, as either input or output, in the user file.
* Then, call the FLEXIO_SetPinConfig() function.
*
* This is an example to define an input pin or an output pin configuration.
* code
* Define a digital input pin configuration,
* flexio_gpio_config_t config =
* {
* kFLEXIO_DigitalInput,
* 0U,
* kFLEXIO_FlagRisingEdgeEnable | kFLEXIO_InputInterruptEnable,
* }
* Define a digital output pin configuration,
* flexio_gpio_config_t config =
* {
* kFLEXIO_DigitalOutput,
* 0U,
* 0U
* }
* endcode
* param base FlexIO peripheral base address
* param pin FLEXIO pin number.
* param config FLEXIO pin configuration pointer.
*/
void FLEXIO_SetPinConfig(FLEXIO_Type *base, uint32_t pin, flexio_gpio_config_t *config)
{
assert(NULL != config);
IRQn_Type flexio_irqs[] = FLEXIO_IRQS;
if (config->pinDirection == kFLEXIO_DigitalInput)
{
base->PINOUTE &= ~(1UL << pin);
if (0U != (config->inputConfig & (uint8_t)kFLEXIO_InputInterruptEnable))
{
base->PINIEN = 1UL << pin;
/* Clear pending NVIC IRQ before enable NVIC IRQ. */
NVIC_ClearPendingIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
/* Enable interrupt in NVIC. */
(void)EnableIRQ(flexio_irqs[FLEXIO_GetInstance(base)]);
}
if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagRisingEdgeEnable))
{
base->PINREN = 1UL << pin;
}
if (0U != (config->inputConfig & (uint8_t)kFLEXIO_FlagFallingEdgeEnable))
{
base->PINFEN = 1UL << pin;
}
}
else
{
FLEXIO_EnablePinOutput(base, pin);
FLEXIO_PinWrite(base, pin, config->outputLogic);
}
}
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER*/
void FLEXIO_DriverIRQHandler(void);
void FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO0_DriverIRQHandler(void);
void FLEXIO0_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO1_DriverIRQHandler(void);
void FLEXIO1_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void UART2_FLEXIO_DriverIRQHandler(void);
void UART2_FLEXIO_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO2_DriverIRQHandler(void);
void FLEXIO2_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}
void FLEXIO3_DriverIRQHandler(void);
void FLEXIO3_DriverIRQHandler(void)
{
FLEXIO_CommonIRQHandler();
}

View File

@ -0,0 +1,917 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_H_
#define FSL_FLEXIO_H_
#include "fsl_common.h"
/*!
* @addtogroup flexio_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO driver version. */
#define FSL_FLEXIO_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
/*! @} */
/*! @brief Calculate FlexIO timer trigger.*/
#define FLEXIO_TIMER_TRIGGER_SEL_PININPUT(x) ((uint32_t)(x) << 1U)
#define FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(x) (((uint32_t)(x) << 2U) | 0x1U)
#define FLEXIO_TIMER_TRIGGER_SEL_TIMn(x) (((uint32_t)(x) << 2U) | 0x3U)
/*! @brief Define time of timer trigger polarity.*/
typedef enum _flexio_timer_trigger_polarity
{
kFLEXIO_TimerTriggerPolarityActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_TimerTriggerPolarityActiveLow = 0x1U, /*!< Active low. */
} flexio_timer_trigger_polarity_t;
/*! @brief Define type of timer trigger source.*/
typedef enum _flexio_timer_trigger_source
{
kFLEXIO_TimerTriggerSourceExternal = 0x0U, /*!< External trigger selected. */
kFLEXIO_TimerTriggerSourceInternal = 0x1U, /*!< Internal trigger selected. */
} flexio_timer_trigger_source_t;
/*! @brief Define type of timer/shifter pin configuration.*/
typedef enum _flexio_pin_config
{
kFLEXIO_PinConfigOutputDisabled = 0x0U, /*!< Pin output disabled. */
kFLEXIO_PinConfigOpenDrainOrBidirection = 0x1U, /*!< Pin open drain or bidirectional output enable. */
kFLEXIO_PinConfigBidirectionOutputData = 0x2U, /*!< Pin bidirectional output data. */
kFLEXIO_PinConfigOutput = 0x3U, /*!< Pin output. */
} flexio_pin_config_t;
/*! @brief Definition of pin polarity.*/
typedef enum _flexio_pin_polarity
{
kFLEXIO_PinActiveHigh = 0x0U, /*!< Active high. */
kFLEXIO_PinActiveLow = 0x1U, /*!< Active low. */
} flexio_pin_polarity_t;
/*! @brief Define type of timer work mode.*/
typedef enum _flexio_timer_mode
{
kFLEXIO_TimerModeDisabled = 0x0U, /*!< Timer Disabled. */
kFLEXIO_TimerModeDual8BitBaudBit = 0x1U, /*!< Dual 8-bit counters baud/bit mode. */
kFLEXIO_TimerModeDual8BitPWM = 0x2U, /*!< Dual 8-bit counters PWM mode. */
kFLEXIO_TimerModeSingle16Bit = 0x3U, /*!< Single 16-bit counter mode. */
} flexio_timer_mode_t;
/*! @brief Define type of timer initial output or timer reset condition.*/
typedef enum _flexio_timer_output
{
kFLEXIO_TimerOutputOneNotAffectedByReset = 0x0U, /*!< Logic one when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputZeroNotAffectedByReset = 0x1U, /*!< Logic zero when enabled and is not affected by timer
reset. */
kFLEXIO_TimerOutputOneAffectedByReset = 0x2U, /*!< Logic one when enabled and on timer reset. */
kFLEXIO_TimerOutputZeroAffectedByReset = 0x3U, /*!< Logic zero when enabled and on timer reset. */
} flexio_timer_output_t;
/*! @brief Define type of timer decrement.*/
typedef enum _flexio_timer_decrement_source
{
kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput = 0x0U, /*!< Decrement counter on FlexIO clock, Shift clock
equals Timer output. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTimerOutput, /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Timer output. */
kFLEXIO_TimerDecSrcOnPinInputShiftPinInput, /*!< Decrement counter on Pin input (both edges),
Shift clock equals Pin input. */
kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput /*!< Decrement counter on Trigger input (both edges),
Shift clock equals Trigger input. */
#if (defined(FSL_FEATURE_FLEXIO_TIMCFG_TIMDCE_FIELD_WIDTH) && (FSL_FEATURE_FLEXIO_TIMCFG_TIMDCE_FIELD_WIDTH == 3))
,
kFLEXIO_TimerDecSrcDiv16OnFlexIOClockShiftTimerOutput, /*!< Decrement counter on FlexIO clock divided by 16,
Shift clock equals Timer output. */
kFLEXIO_TimerDecSrcDiv256OnFlexIOClockShiftTimerOutput, /*!< Decrement counter on FlexIO clock divided by 256,
Shift clock equals Timer output. */
kFLEXIO_TimerRisSrcOnPinInputShiftPinInput, /*!< Decrement counter on Pin input (rising edges),
Shift clock equals Pin input. */
kFLEXIO_TimerRisSrcOnTriggerInputShiftTriggerInput /*!< Decrement counter on Trigger input (rising edges), Shift
clock equals Trigger input. */
#endif /* FSL_FEATURE_FLEXIO_TIMCFG_TIMDCE_FIELD_WIDTH */
} flexio_timer_decrement_source_t;
/*! @brief Define type of timer reset condition.*/
typedef enum _flexio_timer_reset_condition
{
kFLEXIO_TimerResetNever = 0x0U, /*!< Timer never reset. */
kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput = 0x2U, /*!< Timer reset on Timer Pin equal to Timer Output. */
kFLEXIO_TimerResetOnTimerTriggerEqualToTimerOutput = 0x3U, /*!< Timer reset on Timer Trigger equal to
Timer Output. */
kFLEXIO_TimerResetOnTimerPinRisingEdge = 0x4U, /*!< Timer reset on Timer Pin rising edge. */
kFLEXIO_TimerResetOnTimerTriggerRisingEdge = 0x6U, /*!< Timer reset on Trigger rising edge. */
kFLEXIO_TimerResetOnTimerTriggerBothEdge = 0x7U, /*!< Timer reset on Trigger rising or falling edge. */
} flexio_timer_reset_condition_t;
/*! @brief Define type of timer disable condition.*/
typedef enum _flexio_timer_disable_condition
{
kFLEXIO_TimerDisableNever = 0x0U, /*!< Timer never disabled. */
kFLEXIO_TimerDisableOnPreTimerDisable = 0x1U, /*!< Timer disabled on Timer N-1 disable. */
kFLEXIO_TimerDisableOnTimerCompare = 0x2U, /*!< Timer disabled on Timer compare. */
kFLEXIO_TimerDisableOnTimerCompareTriggerLow = 0x3U, /*!< Timer disabled on Timer compare and Trigger Low. */
kFLEXIO_TimerDisableOnPinBothEdge = 0x4U, /*!< Timer disabled on Pin rising or falling edge. */
kFLEXIO_TimerDisableOnPinBothEdgeTriggerHigh = 0x5U, /*!< Timer disabled on Pin rising or falling edge provided
Trigger is high. */
kFLEXIO_TimerDisableOnTriggerFallingEdge = 0x6U, /*!< Timer disabled on Trigger falling edge. */
} flexio_timer_disable_condition_t;
/*! @brief Define type of timer enable condition.*/
typedef enum _flexio_timer_enable_condition
{
kFLEXIO_TimerEnabledAlways = 0x0U, /*!< Timer always enabled. */
kFLEXIO_TimerEnableOnPrevTimerEnable = 0x1U, /*!< Timer enabled on Timer N-1 enable. */
kFLEXIO_TimerEnableOnTriggerHigh = 0x2U, /*!< Timer enabled on Trigger high. */
kFLEXIO_TimerEnableOnTriggerHighPinHigh = 0x3U, /*!< Timer enabled on Trigger high and Pin high. */
kFLEXIO_TimerEnableOnPinRisingEdge = 0x4U, /*!< Timer enabled on Pin rising edge. */
kFLEXIO_TimerEnableOnPinRisingEdgeTriggerHigh = 0x5U, /*!< Timer enabled on Pin rising edge and Trigger high. */
kFLEXIO_TimerEnableOnTriggerRisingEdge = 0x6U, /*!< Timer enabled on Trigger rising edge. */
kFLEXIO_TimerEnableOnTriggerBothEdge = 0x7U, /*!< Timer enabled on Trigger rising or falling edge. */
} flexio_timer_enable_condition_t;
/*! @brief Define type of timer stop bit generate condition.*/
typedef enum _flexio_timer_stop_bit_condition
{
kFLEXIO_TimerStopBitDisabled = 0x0U, /*!< Stop bit disabled. */
kFLEXIO_TimerStopBitEnableOnTimerCompare = 0x1U, /*!< Stop bit is enabled on timer compare. */
kFLEXIO_TimerStopBitEnableOnTimerDisable = 0x2U, /*!< Stop bit is enabled on timer disable. */
kFLEXIO_TimerStopBitEnableOnTimerCompareDisable = 0x3U, /*!< Stop bit is enabled on timer compare and timer
disable. */
} flexio_timer_stop_bit_condition_t;
/*! @brief Define type of timer start bit generate condition.*/
typedef enum _flexio_timer_start_bit_condition
{
kFLEXIO_TimerStartBitDisabled = 0x0U, /*!< Start bit disabled. */
kFLEXIO_TimerStartBitEnabled = 0x1U, /*!< Start bit enabled. */
} flexio_timer_start_bit_condition_t;
/*! @brief FlexIO as PWM channel output state */
typedef enum _flexio_timer_output_state
{
kFLEXIO_PwmLow = 0, /*!< The output state of PWM channel is low */
kFLEXIO_PwmHigh, /*!< The output state of PWM channel is high */
} flexio_timer_output_state_t;
/*! @brief Define type of timer polarity for shifter control. */
typedef enum _flexio_shifter_timer_polarity
{
kFLEXIO_ShifterTimerPolarityOnPositive = 0x0U, /*!< Shift on positive edge of shift clock. */
kFLEXIO_ShifterTimerPolarityOnNegitive = 0x1U, /*!< Shift on negative edge of shift clock. */
} flexio_shifter_timer_polarity_t;
/*! @brief Define type of shifter working mode.*/
typedef enum _flexio_shifter_mode
{
kFLEXIO_ShifterDisabled = 0x0U, /*!< Shifter is disabled. */
kFLEXIO_ShifterModeReceive = 0x1U, /*!< Receive mode. */
kFLEXIO_ShifterModeTransmit = 0x2U, /*!< Transmit mode. */
kFLEXIO_ShifterModeMatchStore = 0x4U, /*!< Match store mode. */
kFLEXIO_ShifterModeMatchContinuous = 0x5U, /*!< Match continuous mode. */
#if FSL_FEATURE_FLEXIO_HAS_STATE_MODE
kFLEXIO_ShifterModeState = 0x6U, /*!< SHIFTBUF contents are used for storing
programmable state attributes. */
#endif /* FSL_FEATURE_FLEXIO_HAS_STATE_MODE */
#if FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE
kFLEXIO_ShifterModeLogic = 0x7U, /*!< SHIFTBUF contents are used for implementing
programmable logic look up table. */
#endif /* FSL_FEATURE_FLEXIO_HAS_LOGIC_MODE */
} flexio_shifter_mode_t;
/*! @brief Define type of shifter input source.*/
typedef enum _flexio_shifter_input_source
{
kFLEXIO_ShifterInputFromPin = 0x0U, /*!< Shifter input from pin. */
kFLEXIO_ShifterInputFromNextShifterOutput = 0x1U, /*!< Shifter input from Shifter N+1. */
} flexio_shifter_input_source_t;
/*! @brief Define of STOP bit configuration.*/
typedef enum _flexio_shifter_stop_bit
{
kFLEXIO_ShifterStopBitDisable = 0x0U, /*!< Disable shifter stop bit. */
kFLEXIO_ShifterStopBitLow = 0x2U, /*!< Set shifter stop bit to logic low level. */
kFLEXIO_ShifterStopBitHigh = 0x3U, /*!< Set shifter stop bit to logic high level. */
} flexio_shifter_stop_bit_t;
/*! @brief Define type of START bit configuration.*/
typedef enum _flexio_shifter_start_bit
{
kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable = 0x0U, /*!< Disable shifter start bit, transmitter loads
data on enable. */
kFLEXIO_ShifterStartBitDisabledLoadDataOnShift = 0x1U, /*!< Disable shifter start bit, transmitter loads
data on first shift. */
kFLEXIO_ShifterStartBitLow = 0x2U, /*!< Set shifter start bit to logic low level. */
kFLEXIO_ShifterStartBitHigh = 0x3U, /*!< Set shifter start bit to logic high level. */
} flexio_shifter_start_bit_t;
/*! @brief Define FlexIO shifter buffer type*/
typedef enum _flexio_shifter_buffer_type
{
kFLEXIO_ShifterBuffer = 0x0U, /*!< Shifter Buffer N Register. */
kFLEXIO_ShifterBufferBitSwapped = 0x1U, /*!< Shifter Buffer N Bit Byte Swapped Register. */
kFLEXIO_ShifterBufferByteSwapped = 0x2U, /*!< Shifter Buffer N Byte Swapped Register. */
kFLEXIO_ShifterBufferBitByteSwapped = 0x3U, /*!< Shifter Buffer N Bit Swapped Register. */
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP
kFLEXIO_ShifterBufferNibbleByteSwapped = 0x4U, /*!< Shifter Buffer N Nibble Byte Swapped Register. */
#endif /*FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_BYTE_SWAP*/
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_HALF_WORD_SWAP
kFLEXIO_ShifterBufferHalfWordSwapped = 0x5U, /*!< Shifter Buffer N Half Word Swapped Register. */
#endif
#if defined(FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP) && FSL_FEATURE_FLEXIO_HAS_SHFT_BUFFER_NIBBLE_SWAP
kFLEXIO_ShifterBufferNibbleSwapped = 0x6U, /*!< Shifter Buffer N Nibble Swapped Register. */
#endif
} flexio_shifter_buffer_type_t;
/*! @brief Define FlexIO user configuration structure. */
typedef struct _flexio_config_
{
bool enableFlexio; /*!< Enable/disable FlexIO module */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
} flexio_config_t;
/*! @brief Define FlexIO timer configuration structure. */
typedef struct _flexio_timer_config
{
/* Trigger. */
uint32_t triggerSelect; /*!< The internal trigger selection number using MACROs. */
flexio_timer_trigger_polarity_t triggerPolarity; /*!< Trigger Polarity. */
flexio_timer_trigger_source_t triggerSource; /*!< Trigger Source, internal (see 'trgsel') or external. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Timer Pin Configuration. */
uint32_t pinSelect; /*!< Timer Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Timer Pin Polarity. */
/* Timer. */
flexio_timer_mode_t timerMode; /*!< Timer work Mode. */
flexio_timer_output_t timerOutput; /*!< Configures the initial state of the Timer Output and
whether it is affected by the Timer reset. */
flexio_timer_decrement_source_t timerDecrement; /*!< Configures the source of the Timer decrement and the
source of the Shift clock. */
flexio_timer_reset_condition_t timerReset; /*!< Configures the condition that causes the timer counter
(and optionally the timer output) to be reset. */
flexio_timer_disable_condition_t timerDisable; /*!< Configures the condition that causes the Timer to be
disabled and stop decrementing. */
flexio_timer_enable_condition_t timerEnable; /*!< Configures the condition that causes the Timer to be
enabled and start decrementing. */
flexio_timer_stop_bit_condition_t timerStop; /*!< Timer STOP Bit generation. */
flexio_timer_start_bit_condition_t timerStart; /*!< Timer STRAT Bit generation. */
uint32_t timerCompare; /*!< Value for Timer Compare N Register. */
} flexio_timer_config_t;
/*! @brief Define FlexIO shifter configuration structure. */
typedef struct _flexio_shifter_config
{
/* Timer. */
uint32_t timerSelect; /*!< Selects which Timer is used for controlling the
logic/shift register and generating the Shift clock. */
flexio_shifter_timer_polarity_t timerPolarity; /*!< Timer Polarity. */
/* Pin. */
flexio_pin_config_t pinConfig; /*!< Shifter Pin Configuration. */
uint32_t pinSelect; /*!< Shifter Pin number Select. */
flexio_pin_polarity_t pinPolarity; /*!< Shifter Pin Polarity. */
/* Shifter. */
flexio_shifter_mode_t shifterMode; /*!< Configures the mode of the Shifter. */
#if FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH
uint32_t parallelWidth; /*!< Configures the parallel width when using parallel mode.*/
#endif /* FSL_FEATURE_FLEXIO_HAS_PARALLEL_WIDTH */
flexio_shifter_input_source_t inputSource; /*!< Selects the input source for the shifter. */
flexio_shifter_stop_bit_t shifterStop; /*!< Shifter STOP bit. */
flexio_shifter_start_bit_t shifterStart; /*!< Shifter START bit. */
} flexio_shifter_config_t;
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER
/*! @brief FLEXIO gpio direction definition */
typedef enum _flexio_gpio_direction
{
kFLEXIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
kFLEXIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
} flexio_gpio_direction_t;
/*! @brief FLEXIO gpio input config */
typedef enum _flexio_pin_input_config
{
kFLEXIO_InputInterruptDisabled = 0x0U, /*!< Interrupt request is disabled. */
kFLEXIO_InputInterruptEnable = 0x1U, /*!< Interrupt request is enable. */
kFLEXIO_FlagRisingEdgeEnable = 0x2U, /*!< Input pin flag on rising edge. */
kFLEXIO_FlagFallingEdgeEnable = 0x4U, /*!< Input pin flag on falling edge. */
} flexio_pin_input_config_t;
/*!
* @brief The FLEXIO pin configuration structure.
*
* Each pin can only be configured as either an output pin or an input pin at a time.
* If configured as an input pin, use inputConfig param.
* If configured as an output pin, use outputLogic.
*/
typedef struct _flexio_gpio_config
{
flexio_gpio_direction_t pinDirection; /*!< FLEXIO pin direction, input or output */
uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */
uint8_t inputConfig; /*!< Set an input config */
} flexio_gpio_config_t;
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER*/
/*! @brief typedef for FlexIO simulated driver interrupt handler.*/
typedef void (*flexio_isr_t)(void *base, void *handle);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to flexio bases for each instance. */
extern FLEXIO_Type *const s_flexioBases[];
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to flexio clocks for each instance. */
extern const clock_ip_name_t s_flexioClocks[];
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO Initialization and De-initialization
* @{
*/
/*!
* @brief Gets the default configuration to configure the FlexIO module. The configuration
* can used directly to call the FLEXIO_Configure().
*
* Example:
@code
flexio_config_t config;
FLEXIO_GetDefaultConfig(&config);
@endcode
*
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_GetDefaultConfig(flexio_config_t *userConfig);
/*!
* @brief Configures the FlexIO with a FlexIO configuration. The configuration structure
* can be filled by the user or be set with default values by FLEXIO_GetDefaultConfig().
*
* Example
@code
flexio_config_t config = {
.enableFlexio = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false
};
FLEXIO_Configure(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param userConfig pointer to flexio_config_t structure
*/
void FLEXIO_Init(FLEXIO_Type *base, const flexio_config_t *userConfig);
/*!
* @brief Gates the FlexIO clock. Call this API to stop the FlexIO clock.
*
* @note After calling this API, call the FLEXO_Init to use the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Deinit(FLEXIO_Type *base);
/*!
* @brief Get instance number for FLEXIO module.
*
* @param base FLEXIO peripheral base address.
*/
uint32_t FLEXIO_GetInstance(FLEXIO_Type *base);
/*! @} */
/*!
* @name FlexIO Basic Operation
* @{
*/
/*!
* @brief Resets the FlexIO module.
*
* @param base FlexIO peripheral base address
*/
void FLEXIO_Reset(FLEXIO_Type *base);
/*!
* @brief Enables the FlexIO module operation.
*
* @param base FlexIO peripheral base address
* @param enable true to enable, false to disable.
*/
static inline void FLEXIO_Enable(FLEXIO_Type *base, bool enable)
{
if (enable)
{
base->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
else
{
base->CTRL &= ~FLEXIO_CTRL_FLEXEN_MASK;
}
}
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
/*!
* @brief Reads the input data on each of the FlexIO pins.
*
* @param base FlexIO peripheral base address
* @return FlexIO pin input data
*/
static inline uint32_t FLEXIO_ReadPinInput(FLEXIO_Type *base)
{
return base->PIN;
}
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
#if defined(FSL_FEATURE_FLEXIO_HAS_STATE_MODE) && FSL_FEATURE_FLEXIO_HAS_STATE_MODE
/*!
* @brief Gets the current state pointer for state mode use.
*
* @param base FlexIO peripheral base address
* @return current State pointer
*/
static inline uint8_t FLEXIO_GetShifterState(FLEXIO_Type *base)
{
return ((uint8_t)(base->SHIFTSTATE) & FLEXIO_SHIFTSTATE_STATE_MASK);
}
#endif /*FSL_FEATURE_FLEXIO_HAS_STATE_MODE*/
/*!
* @brief Configures the shifter with the shifter configuration. The configuration structure
* covers both the SHIFTCTL and SHIFTCFG registers. To configure the shifter to the proper
* mode, select which timer controls the shifter to shift, whether to generate start bit/stop
* bit, and the polarity of start bit and stop bit.
*
* Example
@code
flexio_shifter_config_t config = {
.timerSelect = 0,
.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinPolarity = kFLEXIO_PinActiveLow,
.shifterMode = kFLEXIO_ShifterModeTransmit,
.inputSource = kFLEXIO_ShifterInputFromPin,
.shifterStop = kFLEXIO_ShifterStopBitHigh,
.shifterStart = kFLEXIO_ShifterStartBitLow
};
FLEXIO_SetShifterConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index Shifter index
* @param shifterConfig Pointer to flexio_shifter_config_t structure
*/
void FLEXIO_SetShifterConfig(FLEXIO_Type *base, uint8_t index, const flexio_shifter_config_t *shifterConfig);
/*!
* @brief Configures the timer with the timer configuration. The configuration structure
* covers both the TIMCTL and TIMCFG registers. To configure the timer to the proper
* mode, select trigger source for timer and the timer pin output and the timing for timer.
*
* Example
@code
flexio_timer_config_t config = {
.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow,
.triggerSource = kFLEXIO_TimerTriggerSourceInternal,
.pinConfig = kFLEXIO_PinConfigOpenDrainOrBidirection,
.pinSelect = 0,
.pinPolarity = kFLEXIO_PinActiveHigh,
.timerMode = kFLEXIO_TimerModeDual8BitBaudBit,
.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset,
.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput,
.timerReset = kFLEXIO_TimerResetOnTimerPinEqualToTimerOutput,
.timerDisable = kFLEXIO_TimerDisableOnTimerCompare,
.timerEnable = kFLEXIO_TimerEnableOnTriggerHigh,
.timerStop = kFLEXIO_TimerStopBitEnableOnTimerDisable,
.timerStart = kFLEXIO_TimerStartBitEnabled
};
FLEXIO_SetTimerConfig(base, &config);
@endcode
*
* @param base FlexIO peripheral base address
* @param index Timer index
* @param timerConfig Pointer to the flexio_timer_config_t structure
*/
void FLEXIO_SetTimerConfig(FLEXIO_Type *base, uint8_t index, const flexio_timer_config_t *timerConfig);
/*!
* @brief This function set the value of the prescaler on flexio channels
*
* @param base Pointer to the FlexIO simulated peripheral type.
* @param index Timer index
* @param clocksource Set clock value
*/
static inline void FLEXIO_SetClockMode(FLEXIO_Type *base, uint8_t index, flexio_timer_decrement_source_t clocksource)
{
uint32_t reg = base->TIMCFG[index];
reg &= ~FLEXIO_TIMCFG_TIMDEC_MASK;
reg |= FLEXIO_TIMCFG_TIMDEC(clocksource);
base->TIMCFG[index] = reg;
}
/*! @} */
/*!
* @name FlexIO Interrupt Operation
* @{
*/
/*!
* @brief Enables the shifter status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For multiple shifter status interrupt enable, for example, two shifter status enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN |= mask;
}
/*!
* @brief Disables the shifter status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For multiple shifter status interrupt enable, for example, two shifter status enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSIEN &= ~mask;
}
/*!
* @brief Enables the shifter error interrupt. The interrupt generates when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For multiple shifter error interrupt enable, for example, two shifter error enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_EnableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN |= mask;
}
/*!
* @brief Disables the shifter error interrupt. The interrupt won't generate when the corresponding SEF is set.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For multiple shifter error interrupt enable, for example, two shifter error enable, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_DisableShifterErrorInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTEIEN &= ~mask;
}
/*!
* @brief Enables the timer status interrupt. The interrupt generates when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For multiple timer status interrupt enable, for example, two timer status enable, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_EnableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN |= mask;
}
/*!
* @brief Disables the timer status interrupt. The interrupt won't generate when the corresponding SSF is set.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For multiple timer status interrupt enable, for example, two timer status enable, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_DisableTimerStatusInterrupts(FLEXIO_Type *base, uint32_t mask)
{
base->TIMIEN &= ~mask;
}
/*! @} */
/*!
* @name FlexIO Status Operation
* @{
*/
/*!
* @brief Gets the shifter status flags.
*
* @param base FlexIO peripheral base address
* @return Shifter status flags
*/
static inline uint32_t FLEXIO_GetShifterStatusFlags(FLEXIO_Type *base)
{
return ((base->SHIFTSTAT) & FLEXIO_SHIFTSTAT_SSF_MASK);
}
/*!
* @brief Clears the shifter status flags.
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @note For clearing multiple shifter status flags, for example, two shifter status flags, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTSTAT = mask;
}
/*!
* @brief Gets the shifter error flags.
*
* @param base FlexIO peripheral base address
* @return Shifter error flags
*/
static inline uint32_t FLEXIO_GetShifterErrorFlags(FLEXIO_Type *base)
{
return ((base->SHIFTERR) & FLEXIO_SHIFTERR_SEF_MASK);
}
/*!
* @brief Clears the shifter error flags.
*
* @param base FlexIO peripheral base address
* @param mask The shifter error mask which can be calculated by (1 << shifter index)
* @note For clearing multiple shifter error flags, for example, two shifter error flags, can calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*/
static inline void FLEXIO_ClearShifterErrorFlags(FLEXIO_Type *base, uint32_t mask)
{
base->SHIFTERR = mask;
}
/*!
* @brief Gets the timer status flags.
*
* @param base FlexIO peripheral base address
* @return Timer status flags
*/
static inline uint32_t FLEXIO_GetTimerStatusFlags(FLEXIO_Type *base)
{
return ((base->TIMSTAT) & FLEXIO_TIMSTAT_TSF_MASK);
}
/*!
* @brief Clears the timer status flags.
*
* @param base FlexIO peripheral base address
* @param mask The timer status mask which can be calculated by (1 << timer index)
* @note For clearing multiple timer status flags, for example, two timer status flags, can calculate
* the mask by using ((1 << timer index0) | (1 << timer index1))
*/
static inline void FLEXIO_ClearTimerStatusFlags(FLEXIO_Type *base, uint32_t mask)
{
base->TIMSTAT = mask;
}
/*! @} */
/*!
* @name FlexIO DMA Operation
* @{
*/
/*!
* @brief Enables/disables the shifter status DMA. The DMA request generates when the corresponding SSF is set.
*
* @note For multiple shifter status DMA enables, for example, calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*
* @param base FlexIO peripheral base address
* @param mask The shifter status mask which can be calculated by (1 << shifter index)
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_EnableShifterStatusDMA(FLEXIO_Type *base, uint32_t mask, bool enable)
{
if (enable)
{
base->SHIFTSDEN |= mask;
}
else
{
base->SHIFTSDEN &= ~mask;
}
}
/*!
* @brief Gets the shifter buffer address for the DMA transfer usage.
*
* @param base FlexIO peripheral base address
* @param type Shifter type of flexio_shifter_buffer_type_t
* @param index Shifter index
* @return Corresponding shifter buffer index
*/
uint32_t FLEXIO_GetShifterBufferAddress(FLEXIO_Type *base, flexio_shifter_buffer_type_t type, uint8_t index);
/*!
* @brief Registers the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base Pointer to the FlexIO simulated peripheral type.
* @param handle Pointer to the handler for FlexIO simulated peripheral.
* @param isr FlexIO simulated peripheral interrupt handler.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_RegisterHandleIRQ(void *base, void *handle, flexio_isr_t isr);
/*!
* @brief Unregisters the handle and the interrupt handler for the FlexIO-simulated peripheral.
*
* @param base Pointer to the FlexIO simulated peripheral type.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UnregisterHandleIRQ(void *base);
/*! @} */
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER
/*!
* @brief Configure a FLEXIO pin used by the board.
*
* To Config the FLEXIO PIN, define a pin configuration, as either input or output, in the user file.
* Then, call the FLEXIO_SetPinConfig() function.
*
* This is an example to define an input pin or an output pin configuration.
* @code
* Define a digital input pin configuration,
* flexio_gpio_config_t config =
* {
* kFLEXIO_DigitalInput,
* 0U,
* kFLEXIO_FlagRisingEdgeEnable | kFLEXIO_InputInterruptEnable,
* }
* Define a digital output pin configuration,
* flexio_gpio_config_t config =
* {
* kFLEXIO_DigitalOutput,
* 0U,
* 0U
* }
* @endcode
* @param base FlexIO peripheral base address
* @param pin FLEXIO pin number.
* @param config FLEXIO pin configuration pointer.
*/
void FLEXIO_SetPinConfig(FLEXIO_Type *base, uint32_t pin, flexio_gpio_config_t *config);
/*!
* @name GPIO Output Operations
* @{
*/
/*!
* @brief Sets the output level of the multiple FLEXIO pins to the logic 0.
*
* @param base FlexIO peripheral base address
* @param mask FLEXIO pin number mask
*/
static inline void FLEXIO_ClearPortOutput(FLEXIO_Type *base, uint32_t mask)
{
base->PINOUTCLR = mask;
}
/*!
* @brief Sets the output level of the multiple FLEXIO pins to the logic 1.
*
* @param base FlexIO peripheral base address
* @param mask FLEXIO pin number mask
*/
static inline void FLEXIO_SetPortOutput(FLEXIO_Type *base, uint32_t mask)
{
base->PINOUTSET = mask;
}
/*!
* @brief Reverses the current output logic of the multiple FLEXIO pins.
*
* @param base FlexIO peripheral base address
* @param mask FLEXIO pin number mask
*/
static inline void FLEXIO_TogglePortOutput(FLEXIO_Type *base, uint32_t mask)
{
base->PINOUTTOG = mask;
}
/*!
* @brief Sets the output level of the FLEXIO pins to the logic 1 or 0.
*
* @param base FlexIO peripheral base address
* @param pin FLEXIO pin number.
* @param output FLEXIO pin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
static inline void FLEXIO_PinWrite(FLEXIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
FLEXIO_ClearPortOutput(base, 1UL << pin);
}
else
{
FLEXIO_SetPortOutput(base, 1UL << pin);
}
}
/*!
* @brief Enables the FLEXIO output pin function.
*
* @param base FlexIO peripheral base address
* @param pin FLEXIO pin number.
*/
static inline void FLEXIO_EnablePinOutput(FLEXIO_Type *base, uint32_t pin)
{
base->PINOUTE |= (1UL << pin);
}
/*! @} */
/*!
* @name FLEXIO PIN Input Operations
* @{
*/
/*!
* @brief Reads the current input value of the FLEXIO pin.
*
* @param base FlexIO peripheral base address
* @param pin FLEXIO pin number.
* @retval FLEXIO port input value
* - 0: corresponding pin input low-logic level.
* - 1: corresponding pin input high-logic level.
*/
static inline uint32_t FLEXIO_PinRead(FLEXIO_Type *base, uint32_t pin)
{
return (((base->PIN) >> pin) & 0x01U);
}
/*!
* @brief Gets the FLEXIO input pin status.
*
* @param base FlexIO peripheral base address
* @param pin FLEXIO pin number.
* @retval FLEXIO port input status
* - 0: corresponding pin input capture no status.
* - 1: corresponding pin input capture rising or falling edge.
*/
static inline uint32_t FLEXIO_GetPinStatus(FLEXIO_Type *base, uint32_t pin)
{
return (((base->PINSTAT) >> pin) & 0x01U);
}
/*!
* @brief Clears the multiple FLEXIO input pins status.
*
* @param base FlexIO peripheral base address
* @param mask FLEXIO pin number mask
*/
static inline void FLEXIO_ClearPortStatus(FLEXIO_Type *base, uint32_t mask)
{
base->PINSTAT = mask;
}
/*! @} */
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER*/
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /*FSL_FLEXIO_H_*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,485 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_I2C_MASTER_H_
#define FSL_FLEXIO_I2C_MASTER_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_i2c_master
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
#define FSL_FLEXIO_I2C_MASTER_DRIVER_VERSION (MAKE_VERSION(2, 5, 0))
/*! @} */
/*! @brief Retry times for waiting flag. */
#ifndef I2C_RETRY_TIMES
#define I2C_RETRY_TIMES 0U /* Define to zero means keep waiting until the flag is assert/deassert. */
#endif
/*! @brief FlexIO I2C transfer status*/
enum
{
kStatus_FLEXIO_I2C_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 0), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 1), /*!< I2C is busy doing transfer. */
kStatus_FLEXIO_I2C_Nak = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 2), /*!< NAK received during transfer. */
kStatus_FLEXIO_I2C_Timeout = MAKE_STATUS(kStatusGroup_FLEXIO_I2C, 3), /*!< Timeout polling status flags. */
};
/*! @brief Define FlexIO I2C master interrupt mask. */
enum _flexio_i2c_master_interrupt
{
kFLEXIO_I2C_TxEmptyInterruptEnable = 0x1U, /*!< Tx buffer empty interrupt enable. */
kFLEXIO_I2C_RxFullInterruptEnable = 0x2U, /*!< Rx buffer full interrupt enable. */
};
/*! @brief Define FlexIO I2C master status mask. */
enum _flexio_i2c_master_status_flags
{
kFLEXIO_I2C_TxEmptyFlag = 0x1U, /*!< Tx shifter empty flag. */
kFLEXIO_I2C_RxFullFlag = 0x2U, /*!< Rx shifter full/Transfer complete flag. */
kFLEXIO_I2C_ReceiveNakFlag = 0x4U, /*!< Receive NAK flag. */
};
/*! @brief Direction of master transfer.*/
typedef enum _flexio_i2c_direction
{
kFLEXIO_I2C_Write = 0x0U, /*!< Master send to slave. */
kFLEXIO_I2C_Read = 0x1U, /*!< Master receive from slave. */
} flexio_i2c_direction_t;
/*! @brief Define FlexIO I2C master access structure typedef. */
typedef struct _flexio_i2c_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDAPinIndex; /*!< Pin select for I2C SDA. */
uint8_t SCLPinIndex; /*!< Pin select for I2C SCL. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO I2C. */
uint8_t timerIndex[3]; /*!< Timer index used in FlexIO I2C. */
uint32_t baudrate; /*!< Master transfer baudrate, used to calculate delay time. */
} FLEXIO_I2C_Type;
/*! @brief Define FlexIO I2C master user configuration structure. */
typedef struct _flexio_i2c_master_config
{
bool enableMaster; /*!< Enables the FlexIO I2C peripheral at initialization time. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers, fast access requires
the FlexIO clock to be at least twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
} flexio_i2c_master_config_t;
/*! @brief Define FlexIO I2C master transfer structure. */
typedef struct _flexio_i2c_master_transfer
{
uint32_t flags; /*!< Transfer flag which controls the transfer, reserved for FlexIO I2C. */
uint8_t slaveAddress; /*!< 7-bit slave address. */
flexio_i2c_direction_t direction; /*!< Transfer direction, read or write. */
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
uint8_t subaddressSize; /*!< Size of command buffer. */
uint8_t volatile *data; /*!< Transfer buffer. */
volatile size_t dataSize; /*!< Transfer size. */
} flexio_i2c_master_transfer_t;
/*! @brief FlexIO I2C master handle typedef. */
typedef struct _flexio_i2c_master_handle flexio_i2c_master_handle_t;
/*! @brief FlexIO I2C master transfer callback typedef. */
typedef void (*flexio_i2c_master_transfer_callback_t)(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO I2C master handle structure. */
struct _flexio_i2c_master_handle
{
flexio_i2c_master_transfer_t transfer; /*!< FlexIO I2C master transfer copy. */
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t state; /*!< Transfer state maintained during transfer. */
flexio_i2c_master_transfer_callback_t completionCallback; /*!< Callback function called at transfer event. */
/*!< Callback function called at transfer event. */
void *userData; /*!< Callback parameter passed to callback function. */
bool needRestart; /*!< Whether master needs to send re-start signal. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
#if defined(FSL_FEATURE_FLEXIO_HAS_PIN_STATUS) && FSL_FEATURE_FLEXIO_HAS_PIN_STATUS
/*!
* @brief Make sure the bus isn't already pulled down.
*
* Check the FLEXIO pin status to see whether either of SDA and SCL pin is pulled down.
*
* @param base Pointer to FLEXIO_I2C_Type structure..
* @retval kStatus_Success
* @retval kStatus_FLEXIO_I2C_Busy
*/
status_t FLEXIO_I2C_CheckForBusyBus(FLEXIO_I2C_Type *base);
#endif /*FSL_FEATURE_FLEXIO_HAS_PIN_STATUS*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, and configures the FlexIO I2C
* hardware configuration.
*
* Example
@code
FLEXIO_I2C_Type base = {
.flexioBase = FLEXIO,
.SDAPinIndex = 0,
.SCLPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_i2c_master_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 100000
};
FLEXIO_I2C_MasterInit(base, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param masterConfig Pointer to flexio_i2c_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
* @retval kStatus_Success Initialization successful
* @retval kStatus_InvalidArgument The source clock exceed upper range limitation
*/
status_t FLEXIO_I2C_MasterInit(FLEXIO_I2C_Type *base, flexio_i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief De-initializes the FlexIO I2C master peripheral. Calling this API Resets the FlexIO I2C master
* shifer and timer config, module can't work unless the FLEXIO_I2C_MasterInit is called.
*
* @param base pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterDeinit(FLEXIO_I2C_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO module. The configuration
* can be used directly for calling the FLEXIO_I2C_MasterInit().
*
* Example:
@code
flexio_i2c_master_config_t config;
FLEXIO_I2C_MasterGetDefaultConfig(&config);
@endcode
* @param masterConfig Pointer to flexio_i2c_master_config_t structure.
*/
void FLEXIO_I2C_MasterGetDefaultConfig(flexio_i2c_master_config_t *masterConfig);
/*!
* @brief Enables/disables the FlexIO module operation.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param enable Pass true to enable module, false does not have any effect.
*/
static inline void FLEXIO_I2C_MasterEnable(FLEXIO_I2C_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO I2C master status flags.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @return Status flag, use status flag to AND #_flexio_i2c_master_status_flags can get the related status.
*/
uint32_t FLEXIO_I2C_MasterGetStatusFlags(FLEXIO_I2C_Type *base);
/*!
* @brief Clears the FlexIO I2C master status flags.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Status flag.
* The parameter can be any combination of the following values:
* @arg kFLEXIO_I2C_RxFullFlag
* @arg kFLEXIO_I2C_ReceiveNakFlag
*/
void FLEXIO_I2C_MasterClearStatusFlags(FLEXIO_I2C_Type *base, uint32_t mask);
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO i2c master interrupt requests.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Interrupt source.
* Currently only one interrupt request source:
* @arg kFLEXIO_I2C_TransferCompleteInterruptEnable
*/
void FLEXIO_I2C_MasterEnableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO I2C master interrupt requests.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_I2C_MasterDisableInterrupts(FLEXIO_I2C_Type *base, uint32_t mask);
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Sets the FlexIO I2C master transfer baudrate.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param baudRate_Bps the baud rate value in HZ
* @param srcClock_Hz source clock in HZ
*/
void FLEXIO_I2C_MasterSetBaudRate(FLEXIO_I2C_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Sends START + 7-bit address to the bus.
*
* @note This API should be called when the transfer configuration is ready to send a START signal
* and 7-bit address to the bus. This is a non-blocking API, which returns directly after the address
* is put into the data register but the address transfer is not finished on the bus. Ensure that
* the kFLEXIO_I2C_RxFullFlag status is asserted before calling this API.
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param address 7-bit address.
* @param direction transfer direction.
* This parameter is one of the values in flexio_i2c_direction_t:
* @arg kFLEXIO_I2C_Write: Transmit
* @arg kFLEXIO_I2C_Read: Receive
*/
void FLEXIO_I2C_MasterStart(FLEXIO_I2C_Type *base, uint8_t address, flexio_i2c_direction_t direction);
/*!
* @brief Sends the stop signal on the bus.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterStop(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the repeated start signal on the bus.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterRepeatedStart(FLEXIO_I2C_Type *base);
/*!
* @brief Sends the stop signal when transfer is still on-going.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
*/
void FLEXIO_I2C_MasterAbortStop(FLEXIO_I2C_Type *base);
/*!
* @brief Configures the sent ACK/NAK for the following byte.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param enable True to configure send ACK, false configure to send NAK.
*/
void FLEXIO_I2C_MasterEnableAck(FLEXIO_I2C_Type *base, bool enable);
/*!
* @brief Sets the number of bytes to be transferred from a start signal to a stop signal.
*
* @note Call this API before a transfer begins because the timer generates a number of clocks according
* to the number of bytes that need to be transferred.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param count Number of bytes need to be transferred from a start signal to a re-start/stop signal
* @retval kStatus_Success Successfully configured the count.
* @retval kStatus_InvalidArgument Input argument is invalid.
*/
status_t FLEXIO_I2C_MasterSetTransferCount(FLEXIO_I2C_Type *base, uint16_t count);
/*!
* @brief Writes one byte of data to the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but the data transfer is not finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param data a byte of data.
*/
static inline void FLEXIO_I2C_MasterWriteByte(FLEXIO_I2C_Type *base, uint32_t data)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
/*!
* @brief Reads one byte of data from the I2C bus.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the data is ready in the register.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @return data byte read.
*/
static inline uint8_t FLEXIO_I2C_MasterReadByte(FLEXIO_I2C_Type *base)
{
return (uint8_t)(base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]]);
}
/*!
* @brief Sends a buffer of data in bytes.
*
* @note This function blocks via polling until all bytes have been sent.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param txBuff The data bytes to send.
* @param txSize The number of data bytes to send.
* @retval kStatus_Success Successfully write data.
* @retval kStatus_FLEXIO_I2C_Nak Receive NAK during writing data.
* @retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
*/
status_t FLEXIO_I2C_MasterWriteBlocking(FLEXIO_I2C_Type *base, const uint8_t *txBuff, uint8_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param rxBuff The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
* @retval kStatus_Success Successfully read data.
* @retval kStatus_FLEXIO_I2C_Timeout Timeout polling status flags.
*/
status_t FLEXIO_I2C_MasterReadBlocking(FLEXIO_I2C_Type *base, uint8_t *rxBuff, uint8_t rxSize);
/*!
* @brief Performs a master polling transfer on the I2C bus.
*
* @note The API does not return until the transfer succeeds or fails due
* to receiving NAK.
*
* @param base pointer to FLEXIO_I2C_Type structure.
* @param xfer pointer to flexio_i2c_master_transfer_t structure.
* @return status of status_t.
*/
status_t FLEXIO_I2C_MasterTransferBlocking(FLEXIO_I2C_Type *base, flexio_i2c_master_transfer_t *xfer);
/*! @} */
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the I2C handle which is used in transactional functions.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param handle Pointer to flexio_i2c_master_handle_t structure to store the transfer state.
* @param callback Pointer to user callback function.
* @param userData User param passed to the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/isr table out of range.
*/
status_t FLEXIO_I2C_MasterTransferCreateHandle(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
*
* @note The API returns immediately after the transfer initiates.
* Call FLEXIO_I2C_MasterTransferGetCount to poll the transfer status to check whether
* the transfer is finished. If the return status is not kStatus_FLEXIO_I2C_Busy, the transfer
* is finished.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
* @param xfer pointer to flexio_i2c_master_transfer_t structure
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_FLEXIO_I2C_Busy FlexIO I2C is not idle, is running another transfer.
*/
status_t FLEXIO_I2C_MasterTransferNonBlocking(FLEXIO_I2C_Type *base,
flexio_i2c_master_handle_t *handle,
flexio_i2c_master_transfer_t *xfer);
/*!
* @brief Gets the master transfer status during a interrupt non-blocking transfer.
*
* @param base Pointer to FLEXIO_I2C_Type structure.
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_I2C_MasterTransferGetCount(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle, size_t *count);
/*!
* @brief Aborts an interrupt non-blocking transfer early.
*
* @note This API can be called at any time when an interrupt non-blocking transfer initiates
* to abort the transfer early.
*
* @param base Pointer to FLEXIO_I2C_Type structure
* @param handle Pointer to flexio_i2c_master_handle_t structure which stores the transfer state
*/
void FLEXIO_I2C_MasterTransferAbort(FLEXIO_I2C_Type *base, flexio_i2c_master_handle_t *handle);
/*!
* @brief Master interrupt handler.
*
* @param i2cType Pointer to FLEXIO_I2C_Type structure
* @param i2cHandle Pointer to flexio_i2c_master_transfer_t structure
*/
void FLEXIO_I2C_MasterTransferHandleIRQ(void *i2cType, void *i2cHandle);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /*FSL_FLEXIO_I2C_MASTER_H_*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,686 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_MCULCD_H_
#define FSL_FLEXIO_MCULCD_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_mculcd
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO MCULCD driver version. */
#define FSL_FLEXIO_MCULCD_DRIVER_VERSION (MAKE_VERSION(2, 1, 0))
/*! @} */
#ifndef FLEXIO_MCULCD_WAIT_COMPLETE_TIME
/*!
* @brief The delay time to wait for FLEXIO transmit complete.
*
* Currently there is no method to detect whether the data has been
* sent out from the shifter, so the driver use a software delay for this. When
* the data is written to shifter buffer, the driver call the delay
* function to wait for the data shift out.
* If this value is too small, then the last few bytes might be lost when writing
* data using interrupt method or DMA method.
*/
#define FLEXIO_MCULCD_WAIT_COMPLETE_TIME 512
#endif
#ifndef FLEXIO_MCULCD_DATA_BUS_WIDTH
/*!
* @brief The data bus width, must be 8 or 16.
*/
#define FLEXIO_MCULCD_DATA_BUS_WIDTH 16UL
#endif
#if (16UL != FLEXIO_MCULCD_DATA_BUS_WIDTH) && (8UL != FLEXIO_MCULCD_DATA_BUS_WIDTH)
#error Only support data bus 8-bit or 16-bit
#endif
/*! @brief FlexIO LCD transfer status */
enum
{
kStatus_FLEXIO_MCULCD_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_MCULCD, 0), /*!< FlexIO LCD is idle. */
kStatus_FLEXIO_MCULCD_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_MCULCD, 1), /*!< FlexIO LCD is busy */
kStatus_FLEXIO_MCULCD_Error = MAKE_STATUS(kStatusGroup_FLEXIO_MCULCD, 2), /*!< FlexIO LCD error occurred */
};
/*! @brief Define FlexIO MCULCD pixel format. */
typedef enum _flexio_mculcd_pixel_format
{
kFLEXIO_MCULCD_RGB565 = 0, /*!< RGB565, 16-bit. */
kFLEXIO_MCULCD_BGR565, /*!< BGR565, 16-bit. */
kFLEXIO_MCULCD_RGB888, /*!< RGB888, 24-bit. */
kFLEXIO_MCULCD_BGR888, /*!< BGR888, 24-bit. */
} flexio_mculcd_pixel_format_t;
/*! @brief Define FlexIO MCULCD bus type. */
typedef enum _flexio_mculcd_bus
{
kFLEXIO_MCULCD_8080, /*!< Using Intel 8080 bus. */
kFLEXIO_MCULCD_6800, /*!< Using Motorola 6800 bus. */
} flexio_mculcd_bus_t;
/*! @brief Define FlexIO MCULCD interrupt mask. */
enum _flexio_mculcd_interrupt_enable
{
kFLEXIO_MCULCD_TxEmptyInterruptEnable = (1U << 0U), /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_MCULCD_RxFullInterruptEnable = (1U << 1U), /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO MCULCD status mask. */
enum _flexio_mculcd_status_flags
{
kFLEXIO_MCULCD_TxEmptyFlag = (1U << 0U), /*!< Transmit buffer empty flag. */
kFLEXIO_MCULCD_RxFullFlag = (1U << 1U), /*!< Receive buffer full flag. */
};
/*! @brief Define FlexIO MCULCD DMA mask. */
enum _flexio_mculcd_dma_enable
{
kFLEXIO_MCULCD_TxDmaEnable = 0x1U, /*!< Tx DMA request source */
kFLEXIO_MCULCD_RxDmaEnable = 0x2U, /*!< Rx DMA request source */
};
/*! @brief Function to set or clear the CS and RS pin. */
typedef void (*flexio_mculcd_pin_func_t)(bool set);
/*! @brief Define FlexIO MCULCD access structure typedef. */
typedef struct _flexio_mculcd_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
flexio_mculcd_bus_t busType; /*!< The bus type, 8080 or 6800. */
uint8_t dataPinStartIndex; /*!< Start index of the data pin, the FlexIO pin dataPinStartIndex
to (dataPinStartIndex + FLEXIO_MCULCD_DATA_BUS_WIDTH -1)
will be used for data transfer. Only support data bus width 8 and 16. */
uint8_t ENWRPinIndex; /*!< Pin select for WR(8080 mode), EN(6800 mode). */
uint8_t RDPinIndex; /*!< Pin select for RD(8080 mode), not used in 6800 mode. */
uint8_t txShifterStartIndex; /*!< Start index of shifters used for data write, it must be 0 or 4. */
uint8_t txShifterEndIndex; /*!< End index of shifters used for data write. */
uint8_t rxShifterStartIndex; /*!< Start index of shifters used for data read. */
uint8_t rxShifterEndIndex; /*!< End index of shifters used for data read, it must be 3 or 7. */
uint8_t timerIndex; /*!< Timer index used in FlexIO MCULCD. */
flexio_mculcd_pin_func_t setCSPin; /*!< Function to set or clear the CS pin. */
flexio_mculcd_pin_func_t setRSPin; /*!< Function to set or clear the RS pin. */
flexio_mculcd_pin_func_t setRDWRPin; /*!< Function to set or clear the RD/WR pin, only used in 6800 mode. */
} FLEXIO_MCULCD_Type;
/*! @brief Define FlexIO MCULCD configuration structure. */
typedef struct _flexio_mculcd_config
{
bool enable; /*!< Enable/disable FlexIO MCULCD after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in bit-per-second for all data lines combined. */
} flexio_mculcd_config_t;
/*! @brief Transfer mode.*/
typedef enum _flexio_mculcd_transfer_mode
{
kFLEXIO_MCULCD_ReadArray, /*!< Read data into an array. */
kFLEXIO_MCULCD_WriteArray, /*!< Write data from an array. */
kFLEXIO_MCULCD_WriteSameValue, /*!< Write the same value many times. */
} flexio_mculcd_transfer_mode_t;
/*! @brief Define FlexIO MCULCD transfer structure. */
typedef struct _flexio_mculcd_transfer
{
uint32_t command; /*!< Command to send. */
uint32_t dataAddrOrSameValue; /*!< When sending the same value for many times,
this is the value to send. When writing or reading array,
this is the address of the data array. */
size_t dataSize; /*!< How many bytes to transfer. */
flexio_mculcd_transfer_mode_t mode; /*!< Transfer mode. */
bool dataOnly; /*!< Send data only when tx without the command. */
} flexio_mculcd_transfer_t;
/*! @brief typedef for flexio_mculcd_handle_t in advance. */
typedef struct _flexio_mculcd_handle flexio_mculcd_handle_t;
/*! @brief FlexIO MCULCD callback for finished transfer.
*
* When transfer finished, the callback function is called and returns the
* @p status as kStatus_FLEXIO_MCULCD_Idle.
*/
typedef void (*flexio_mculcd_transfer_callback_t)(FLEXIO_MCULCD_Type *base,
flexio_mculcd_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO MCULCD handle structure. */
struct _flexio_mculcd_handle
{
uint32_t dataAddrOrSameValue; /*!< When sending the same value for many times,
this is the value to send. When writing or reading array,
this is the address of the data array. */
size_t dataCount; /*!< Total count to be transferred. */
volatile size_t remainingCount; /*!< Remaining count to transfer. */
volatile uint32_t state; /*!< FlexIO MCULCD internal state. */
flexio_mculcd_transfer_callback_t completionCallback; /*!< FlexIO MCULCD transfer completed callback. */
void *userData; /*!< Callback parameter. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO MCULCD Configuration
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the
* FlexIO MCULCD hardware, and configures the FlexIO MCULCD with FlexIO MCULCD
* configuration.
* The configuration structure can be filled by the user, or be set with default
* values
* by the @ref FLEXIO_MCULCD_GetDefaultConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param config Pointer to the flexio_mculcd_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
* @retval kStatus_Success Initialization success.
* @retval kStatus_InvalidArgument Initialization failed because of invalid
* argument.
*/
status_t FLEXIO_MCULCD_Init(FLEXIO_MCULCD_Type *base, flexio_mculcd_config_t *config, uint32_t srcClock_Hz);
/*!
* @brief Resets the FLEXIO_MCULCD timer and shifter configuration.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*/
void FLEXIO_MCULCD_Deinit(FLEXIO_MCULCD_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO MCULCD.
*
* The default configuration value is:
* @code
* config->enable = true;
* config->enableInDoze = false;
* config->enableInDebug = true;
* config->enableFastAccess = true;
* config->baudRate_Bps = 96000000U;
* @endcode
* @param config Pointer to the flexio_mculcd_config_t structure.
*/
void FLEXIO_MCULCD_GetDefaultConfig(flexio_mculcd_config_t *config);
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets FlexIO MCULCD status flags.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @return status flag; OR'ed value or the @ref _flexio_mculcd_status_flags.
*
* @note Don't use this function with DMA APIs.
*/
uint32_t FLEXIO_MCULCD_GetStatusFlags(FLEXIO_MCULCD_Type *base);
/*!
* @brief Clears FlexIO MCULCD status flags.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param mask Status to clear, it is the OR'ed value of @ref
* _flexio_mculcd_status_flags.
*
* @note Don't use this function with DMA APIs.
*/
void FLEXIO_MCULCD_ClearStatusFlags(FLEXIO_MCULCD_Type *base, uint32_t mask);
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO MCULCD interrupt.
*
* This function enables the FlexIO MCULCD interrupt.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param mask Interrupts to enable, it is the OR'ed value of @ref
* _flexio_mculcd_interrupt_enable.
*/
void FLEXIO_MCULCD_EnableInterrupts(FLEXIO_MCULCD_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO MCULCD interrupt.
*
* This function disables the FlexIO MCULCD interrupt.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param mask Interrupts to disable, it is the OR'ed value of @ref
* _flexio_mculcd_interrupt_enable.
*/
void FLEXIO_MCULCD_DisableInterrupts(FLEXIO_MCULCD_Type *base, uint32_t mask);
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables the FlexIO MCULCD transmit DMA.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void FLEXIO_MCULCD_EnableTxDMA(FLEXIO_MCULCD_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, (1UL << base->txShifterStartIndex), enable);
}
/*!
* @brief Enables/disables the FlexIO MCULCD receive DMA.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param enable True means enable DMA, false means disable DMA.
*/
static inline void FLEXIO_MCULCD_EnableRxDMA(FLEXIO_MCULCD_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, (1UL << base->rxShifterEndIndex), enable);
}
/*!
* @brief Gets the FlexIO MCULCD transmit data register address.
*
* This function returns the MCULCD data register address, which is mainly used
* by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @return FlexIO MCULCD transmit data register address.
*/
static inline uint32_t FLEXIO_MCULCD_GetTxDataRegisterAddress(FLEXIO_MCULCD_Type *base)
{
return (uint32_t) & (base->flexioBase->SHIFTBUF[base->txShifterStartIndex]);
}
/*!
* @brief Gets the FlexIO MCULCD receive data register address.
*
* This function returns the MCULCD data register address, which is mainly used
* by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @return FlexIO MCULCD receive data register address.
*/
static inline uint32_t FLEXIO_MCULCD_GetRxDataRegisterAddress(FLEXIO_MCULCD_Type *base)
{
return (uint32_t) & (base->flexioBase->SHIFTBUF[base->rxShifterStartIndex]);
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Set desired baud rate.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param baudRate_Bps Desired baud rate in bit-per-second for all data lines combined.
* @param srcClock_Hz FLEXIO clock frequency in Hz.
* @retval kStatus_Success Set successfully.
* @retval kStatus_InvalidArgument Could not set the baud rate.
*/
status_t FLEXIO_MCULCD_SetBaudRate(FLEXIO_MCULCD_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz);
/*!
* @brief Configures the FLEXIO MCULCD to multiple beats write mode.
*
* At the begining multiple beats write operation, the FLEXIO MCULCD is configured to
* multiple beats write mode using this function. After write operation, the configuration
* is cleared by @ref FLEXIO_MCULCD_ClearSingleBeatWriteConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_SetSingleBeatWriteConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Clear the FLEXIO MCULCD multiple beats write mode configuration.
*
* Clear the write configuration set by @ref FLEXIO_MCULCD_SetSingleBeatWriteConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_ClearSingleBeatWriteConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Configures the FLEXIO MCULCD to multiple beats read mode.
*
* At the begining or multiple beats read operation, the FLEXIO MCULCD is configured
* to multiple beats read mode using this function. After read operation, the configuration
* is cleared by @ref FLEXIO_MCULCD_ClearSingleBeatReadConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_SetSingleBeatReadConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Clear the FLEXIO MCULCD multiple beats read mode configuration.
*
* Clear the read configuration set by @ref FLEXIO_MCULCD_SetSingleBeatReadConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_ClearSingleBeatReadConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Configures the FLEXIO MCULCD to multiple beats write mode.
*
* At the begining multiple beats write operation, the FLEXIO MCULCD is configured to
* multiple beats write mode using this function. After write operation, the configuration
* is cleared by FLEXIO_MCULCD_ClearMultBeatsWriteConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_SetMultiBeatsWriteConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Clear the FLEXIO MCULCD multiple beats write mode configuration.
*
* Clear the write configuration set by FLEXIO_MCULCD_SetMultBeatsWriteConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Configures the FLEXIO MCULCD to multiple beats read mode.
*
* At the begining or multiple beats read operation, the FLEXIO MCULCD is configured
* to multiple beats read mode using this function. After read operation, the configuration
* is cleared by FLEXIO_MCULCD_ClearMultBeatsReadConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_SetMultiBeatsReadConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Clear the FLEXIO MCULCD multiple beats read mode configuration.
*
* Clear the read configuration set by FLEXIO_MCULCD_SetMultBeatsReadConfig.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
*
* @note This is an internal used function, upper layer should not use.
*/
void FLEXIO_MCULCD_ClearMultiBeatsReadConfig(FLEXIO_MCULCD_Type *base);
/*!
* @brief Enables/disables the FlexIO MCULCD module operation.
*
* @param base Pointer to the FLEXIO_MCULCD_Type.
* @param enable True to enable, false does not have any effect.
*/
static inline void FLEXIO_MCULCD_Enable(FLEXIO_MCULCD_Type *base, bool enable)
{
if (enable)
{
FLEXIO_Enable(base->flexioBase, enable);
}
}
/*!
* @brief Read data from the FLEXIO MCULCD RX shifter buffer.
*
* Read data from the RX shift buffer directly, it does no check whether the
* buffer is empty or not.
*
* If the data bus width is 8-bit:
* @code
* uint8_t value;
* value = (uint8_t)FLEXIO_MCULCD_ReadData(base);
* @endcode
*
* If the data bus width is 16-bit:
* @code
* uint16_t value;
* value = (uint16_t)FLEXIO_MCULCD_ReadData(base);
* @endcode
*
* @note This function returns the RX shifter buffer value (32-bit) directly.
* The return value should be converted according to data bus width.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @return The data read out.
*
* @note Don't use this function with DMA APIs.
*/
uint32_t FLEXIO_MCULCD_ReadData(FLEXIO_MCULCD_Type *base);
/*!
* @brief Write data into the FLEXIO MCULCD TX shifter buffer.
*
* Write data into the TX shift buffer directly, it does no check whether the
* buffer is full or not.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param data The data to write.
*
* @note Don't use this function with DMA APIs.
*/
static inline void FLEXIO_MCULCD_WriteData(FLEXIO_MCULCD_Type *base, uint32_t data)
{
base->flexioBase->SHIFTBUF[base->txShifterStartIndex] = data;
}
/*!
* @brief Assert the nCS to start transfer.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
*/
static inline void FLEXIO_MCULCD_StartTransfer(FLEXIO_MCULCD_Type *base)
{
base->setCSPin(false);
}
/*!
* @brief De-assert the nCS to stop transfer.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
*/
static inline void FLEXIO_MCULCD_StopTransfer(FLEXIO_MCULCD_Type *base)
{
base->setCSPin(true);
}
/*!
* @brief Wait for transmit data send out finished.
*
* Currently there is no effective method to wait for the data send out
* from the shiter, so here use a while loop to wait.
*
* @note This is an internal used function.
*/
void FLEXIO_MCULCD_WaitTransmitComplete(void);
/*!
* @brief Send command in blocking way.
*
* This function sends the command and returns when the command has been sent
* out.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param command The command to send.
*/
void FLEXIO_MCULCD_WriteCommandBlocking(FLEXIO_MCULCD_Type *base, uint32_t command);
/*!
* @brief Send data array in blocking way.
*
* This function sends the data array and returns when the data sent out.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param data The data array to send.
* @param size How many bytes to write.
*/
void FLEXIO_MCULCD_WriteDataArrayBlocking(FLEXIO_MCULCD_Type *base, const void *data, size_t size);
/*!
* @brief Read data into array in blocking way.
*
* This function reads the data into array and returns when the data read
* finished.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param data The array to save the data.
* @param size How many bytes to read.
*/
void FLEXIO_MCULCD_ReadDataArrayBlocking(FLEXIO_MCULCD_Type *base, void *data, size_t size);
/*!
* @brief Send the same value many times in blocking way.
*
* This function sends the same value many times. It could be used to clear the
* LCD screen. If the data bus width is 8, this function will send LSB 8 bits of
* @p sameValue for @p size times. If the data bus is 16, this function will send
* LSB 16 bits of @p sameValue for @p size / 2 times.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param sameValue The same value to send.
* @param size How many bytes to send.
*/
void FLEXIO_MCULCD_WriteSameValueBlocking(FLEXIO_MCULCD_Type *base, uint32_t sameValue, size_t size);
/*!
* @brief Performs a polling transfer.
*
* @note The API does not return until the transfer finished.
*
* @param base pointer to FLEXIO_MCULCD_Type structure.
* @param xfer pointer to flexio_mculcd_transfer_t structure.
*/
void FLEXIO_MCULCD_TransferBlocking(FLEXIO_MCULCD_Type *base, flexio_mculcd_transfer_t *xfer);
/*! @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO MCULCD handle, which is used in transactional
* functions.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param handle Pointer to the flexio_mculcd_handle_t structure to store the
* transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_MCULCD_TransferCreateHandle(FLEXIO_MCULCD_Type *base,
flexio_mculcd_handle_t *handle,
flexio_mculcd_transfer_callback_t callback,
void *userData);
/*!
* @brief Transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which
* returns right away. When all data is sent out/received, the callback
* function is called.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param handle Pointer to the flexio_mculcd_handle_t structure to store the
* transfer state.
* @param xfer FlexIO MCULCD transfer structure. See #flexio_mculcd_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_MCULCD_Busy MCULCD is busy with another transfer.
*/
status_t FLEXIO_MCULCD_TransferNonBlocking(FLEXIO_MCULCD_Type *base,
flexio_mculcd_handle_t *handle,
flexio_mculcd_transfer_t *xfer);
/*!
* @brief Aborts the data transfer, which used IRQ.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param handle Pointer to the flexio_mculcd_handle_t structure to store the
* transfer state.
*/
void FLEXIO_MCULCD_TransferAbort(FLEXIO_MCULCD_Type *base, flexio_mculcd_handle_t *handle);
/*!
* @brief Gets the data transfer status which used IRQ.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param handle Pointer to the flexio_mculcd_handle_t structure to store the
* transfer state.
* @param count How many bytes transferred so far by the non-blocking transaction.
* @retval kStatus_Success Get the transferred count Successfully.
* @retval kStatus_NoTransferInProgress No transfer in process.
*/
status_t FLEXIO_MCULCD_TransferGetCount(FLEXIO_MCULCD_Type *base, flexio_mculcd_handle_t *handle, size_t *count);
/*!
* @brief FlexIO MCULCD IRQ handler function.
*
* @param base Pointer to the FLEXIO_MCULCD_Type structure.
* @param handle Pointer to the flexio_mculcd_handle_t structure to store the
* transfer state.
*/
void FLEXIO_MCULCD_TransferHandleIRQ(void *base, void *handle);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /*FSL_FLEXIO_MCULCD_H_*/

View File

@ -0,0 +1,568 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019,2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_mculcd_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flexio_mculcd_edma"
#endif
#define EDMA_MAX_MAJOR_COUNT (DMA_CITER_ELINKNO_CITER_MASK >> DMA_CITER_ELINKNO_CITER_SHIFT)
enum
{
kFLEXIO_MCULCD_StateIdle, /*!< No transfer in progress. */
kFLEXIO_MCULCD_StateReadArray, /*!< Reading array in progress. */
kFLEXIO_MCULCD_StateWriteArray, /*!< Writing array in progress. */
kFLEXIO_MCULCD_StateWriteSameValue, /*!< Writing the same value in progress.
*/
};
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief EDMA callback function for FLEXIO MCULCD TX.
*
* For details, see @ref edma_callback.
*/
static void FLEXIO_MCULCD_TxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief EDMA callback function for FLEXIO MCULCD RX.
*
* For details, see @ref edma_callback.
*/
static void FLEXIO_MCULCD_RxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief Set EDMA config for FLEXIO MCULCD transfer.
*
* @param base pointer to FLEXIO_MCULCD_Type structure.
* @param handle pointer to flexio_mculcd_edma_handle_t structure to store the
* transfer state.
*/
static void FLEXIO_MCULCD_EDMAConfig(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle);
/*!
* @brief Convert the FlexIO shifter number to eDMA modulo.
*
* @param shifterNum The FlexIO shifter number.
* @param modulo The modulo number.
* @retval Get the modulo successfully.
* @retval Could not get the modulo for the shifter number.
*/
static bool FLEXIO_MCULCD_GetEDMAModulo(uint8_t shifterNum, edma_modulo_t *modulo);
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_MCULCD_TxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
flexio_mculcd_edma_handle_t *flexioLcdMcuHandle = (flexio_mculcd_edma_handle_t *)param;
FLEXIO_MCULCD_Type *flexioLcdMcuBase = flexioLcdMcuHandle->base;
if (transferDone)
{
if (flexioLcdMcuHandle->remainingCount >= flexioLcdMcuHandle->minorLoopBytes)
{
FLEXIO_MCULCD_EDMAConfig(flexioLcdMcuBase, flexioLcdMcuHandle);
EDMA_StartTransfer(flexioLcdMcuHandle->txDmaHandle);
}
else
{
FLEXIO_MCULCD_EnableTxDMA(flexioLcdMcuBase, false);
/* Now the data are in shifter, wait for the data send out from the shifter. */
FLEXIO_MCULCD_WaitTransmitComplete();
/* Disable the TX shifter and the timer. */
FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(flexioLcdMcuBase);
/* Send the remaining data. */
if (0U != flexioLcdMcuHandle->remainingCount)
{
if ((uint32_t)kFLEXIO_MCULCD_StateWriteSameValue == flexioLcdMcuHandle->state)
{
FLEXIO_MCULCD_WriteSameValueBlocking(flexioLcdMcuBase, flexioLcdMcuHandle->dataAddrOrSameValue,
flexioLcdMcuHandle->remainingCount);
}
else
{
FLEXIO_MCULCD_WriteDataArrayBlocking(flexioLcdMcuBase,
(uint8_t *)flexioLcdMcuHandle->dataAddrOrSameValue,
flexioLcdMcuHandle->remainingCount);
}
}
/* De-assert nCS. */
FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
/* Change the state. */
flexioLcdMcuHandle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
flexioLcdMcuHandle->dataCount = 0;
flexioLcdMcuHandle->remainingCount = 0;
/* Callback to inform upper layer. */
if (NULL != flexioLcdMcuHandle->completionCallback)
{
flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle, kStatus_FLEXIO_MCULCD_Idle,
flexioLcdMcuHandle->userData);
}
}
}
}
static void FLEXIO_MCULCD_RxEDMACallback(edma_handle_t *DmaHandle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
uint32_t i;
uint32_t rxBufAddr;
flexio_mculcd_edma_handle_t *flexioLcdMcuHandle = (flexio_mculcd_edma_handle_t *)param;
FLEXIO_MCULCD_Type *flexioLcdMcuBase = flexioLcdMcuHandle->base;
FLEXIO_Type *flexioBase = flexioLcdMcuBase->flexioBase;
if (transferDone)
{
if (flexioLcdMcuHandle->remainingCount >= (2U * flexioLcdMcuHandle->minorLoopBytes))
{
FLEXIO_MCULCD_EDMAConfig(flexioLcdMcuBase, flexioLcdMcuHandle);
EDMA_StartTransfer(flexioLcdMcuHandle->rxDmaHandle);
}
else
{
FLEXIO_MCULCD_EnableRxDMA(flexioLcdMcuBase, false);
/* Wait the data saved to the shifter buffer. */
while (0U == ((1UL << flexioLcdMcuBase->rxShifterEndIndex) & FLEXIO_GetShifterStatusFlags(flexioBase)))
{
}
/* Disable the RX shifter and the timer. */
FLEXIO_MCULCD_ClearMultiBeatsReadConfig(flexioLcdMcuBase);
rxBufAddr = FLEXIO_MCULCD_GetRxDataRegisterAddress(flexioLcdMcuBase);
/* Read out the data. */
#if (defined(__CORTEX_M) && (__CORTEX_M == 0))
/* Cortex M0 and M0+ only support aligned access. */
for (i = 0; i < flexioLcdMcuHandle->rxShifterNum * 4; i++)
{
((uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue))[i] = ((volatile uint8_t *)rxBufAddr)[i];
}
#else
for (i = 0; i < flexioLcdMcuHandle->rxShifterNum; i++)
{
((uint32_t *)(flexioLcdMcuHandle->dataAddrOrSameValue))[i] = ((volatile uint32_t *)rxBufAddr)[i];
}
#endif
flexioLcdMcuHandle->remainingCount -= flexioLcdMcuHandle->minorLoopBytes;
if (0U != flexioLcdMcuHandle->remainingCount)
{
FLEXIO_MCULCD_ReadDataArrayBlocking(
flexioLcdMcuBase,
(uint8_t *)(flexioLcdMcuHandle->dataAddrOrSameValue + flexioLcdMcuHandle->minorLoopBytes),
flexioLcdMcuHandle->remainingCount);
}
/* De-assert nCS. */
FLEXIO_MCULCD_StopTransfer(flexioLcdMcuBase);
/* Change the state. */
flexioLcdMcuHandle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
flexioLcdMcuHandle->dataCount = 0;
flexioLcdMcuHandle->remainingCount = 0;
/* Callback to inform upper layer. */
if (NULL != flexioLcdMcuHandle->completionCallback)
{
flexioLcdMcuHandle->completionCallback(flexioLcdMcuBase, flexioLcdMcuHandle, kStatus_FLEXIO_MCULCD_Idle,
flexioLcdMcuHandle->userData);
}
}
}
}
static void FLEXIO_MCULCD_EDMAConfig(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle)
{
edma_transfer_config_t xferConfig = {0};
edma_transfer_size_t transferSize = kEDMA_TransferSize1Bytes;
int16_t offset;
uint32_t majorLoopCounts;
uint32_t transferCount;
#if (8 == FLEXIO_MCULCD_DATA_BUS_WIDTH)
transferSize = kEDMA_TransferSize1Bytes;
offset = 1;
#else
transferSize = kEDMA_TransferSize2Bytes;
offset = 2;
#endif
majorLoopCounts = handle->remainingCount / handle->minorLoopBytes;
/* For reading, the last minor loop data is not tranfered by DMA. */
if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == handle->state)
{
majorLoopCounts--;
}
if (majorLoopCounts > EDMA_MAX_MAJOR_COUNT)
{
majorLoopCounts = EDMA_MAX_MAJOR_COUNT;
}
transferCount = majorLoopCounts * handle->minorLoopBytes;
if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == handle->state)
{
xferConfig.srcAddr = FLEXIO_MCULCD_GetRxDataRegisterAddress(base);
xferConfig.destAddr = handle->dataAddrOrSameValue;
xferConfig.srcTransferSize = kEDMA_TransferSize4Bytes;
xferConfig.destTransferSize = transferSize;
xferConfig.srcOffset = 4;
xferConfig.destOffset = offset;
xferConfig.minorLoopBytes = handle->minorLoopBytes;
xferConfig.majorLoopCounts = majorLoopCounts;
handle->remainingCount -= transferCount;
handle->dataAddrOrSameValue += transferCount;
(void)EDMA_SubmitTransfer(handle->rxDmaHandle, &xferConfig);
EDMA_SetModulo(handle->rxDmaHandle->base, handle->rxDmaHandle->channel, handle->rxEdmaModulo,
kEDMA_ModuloDisable);
}
else
{
if ((uint32_t)kFLEXIO_MCULCD_StateWriteArray == handle->state)
{
xferConfig.srcAddr = handle->dataAddrOrSameValue;
xferConfig.srcOffset = offset;
handle->dataAddrOrSameValue += transferCount;
}
else
{
xferConfig.srcAddr = (uint32_t)(&(handle->dataAddrOrSameValue));
xferConfig.srcOffset = 0;
}
xferConfig.destAddr = FLEXIO_MCULCD_GetTxDataRegisterAddress(base);
xferConfig.srcTransferSize = transferSize;
xferConfig.destTransferSize = kEDMA_TransferSize4Bytes;
xferConfig.destOffset = 4;
xferConfig.minorLoopBytes = handle->minorLoopBytes;
xferConfig.majorLoopCounts = majorLoopCounts;
handle->remainingCount -= transferCount;
(void)EDMA_SubmitTransfer(handle->txDmaHandle, &xferConfig);
EDMA_SetModulo(handle->txDmaHandle->base, handle->txDmaHandle->channel, kEDMA_ModuloDisable,
handle->txEdmaModulo);
}
}
static bool FLEXIO_MCULCD_GetEDMAModulo(uint8_t shifterNum, edma_modulo_t *modulo)
{
bool ret = true;
switch (shifterNum)
{
case 1U:
*modulo = kEDMA_Modulo4bytes;
break;
case 2U:
*modulo = kEDMA_Modulo8bytes;
break;
case 4U:
*modulo = kEDMA_Modulo16bytes;
break;
case 8U:
*modulo = kEDMA_Modulo32bytes;
break;
default:
ret = false;
break;
}
return ret;
}
/*!
* brief Initializes the FLEXO MCULCD master eDMA handle.
*
* This function initializes the FLEXO MCULCD master eDMA handle which can be
* used for other FLEXO MCULCD transactional APIs. For a specified FLEXO MCULCD
* instance, call this API once to get the initialized handle.
*
* param base Pointer to FLEXIO_MCULCD_Type structure.
* param handle Pointer to flexio_mculcd_edma_handle_t structure to store the
* transfer state.
* param callback MCULCD transfer complete callback, NULL means no callback.
* param userData callback function parameter.
* param txDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA TX,
* the DMA request source of this handle should be the first of TX shifters.
* param rxDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA RX,
* the DMA request source of this handle should be the last of RX shifters.
* retval kStatus_Success Successfully create the handle.
*/
status_t FLEXIO_MCULCD_TransferCreateHandleEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
flexio_mculcd_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txDmaHandle,
edma_handle_t *rxDmaHandle)
{
assert(NULL != handle);
/* Zero the handle. */
(void)memset(handle, 0, sizeof(*handle));
/* Initialize the state. */
handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
/* Register callback and userData. */
handle->completionCallback = callback;
handle->userData = userData;
handle->base = base;
handle->txShifterNum = base->txShifterEndIndex - base->txShifterStartIndex + 1U;
handle->rxShifterNum = base->rxShifterEndIndex - base->rxShifterStartIndex + 1U;
if (NULL != rxDmaHandle)
{
if (!FLEXIO_MCULCD_GetEDMAModulo(handle->rxShifterNum, &handle->rxEdmaModulo))
{
return kStatus_InvalidArgument;
}
handle->rxDmaHandle = rxDmaHandle;
EDMA_SetCallback(rxDmaHandle, FLEXIO_MCULCD_RxEDMACallback, handle);
}
if (NULL != txDmaHandle)
{
if (!FLEXIO_MCULCD_GetEDMAModulo(handle->txShifterNum, &handle->txEdmaModulo))
{
return kStatus_InvalidArgument;
}
handle->txDmaHandle = txDmaHandle;
EDMA_SetCallback(txDmaHandle, FLEXIO_MCULCD_TxEDMACallback, handle);
}
return kStatus_Success;
}
/*!
* brief Performs a non-blocking FlexIO MCULCD transfer using eDMA.
*
* This function returns immediately after transfer initiates. To check whether
* the transfer is completed, user could:
* 1. Use the transfer completed callback;
* 2. Polling function ref FLEXIO_MCULCD_GetTransferCountEDMA
*
* param base pointer to FLEXIO_MCULCD_Type structure.
* param handle pointer to flexio_mculcd_edma_handle_t structure to store the
* transfer state.
* param xfer Pointer to FlexIO MCULCD transfer structure.
* retval kStatus_Success Successfully start a transfer.
* retval kStatus_InvalidArgument Input argument is invalid.
* retval kStatus_FLEXIO_MCULCD_Busy FlexIO MCULCD is not idle, it is running another
* transfer.
*/
status_t FLEXIO_MCULCD_TransferEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
flexio_mculcd_transfer_t *xfer)
{
assert(NULL != handle);
assert(NULL != xfer);
/*
* The data transfer mechanism:
*
* Read:
* Assume the data length is Lr = (n1 * minorLoopBytes + n2), where
* n2 < minorLoopBytes.
* If (n1 <= 1), then all data are sent using blocking method.
* If (n1 > 1), then the beginning ((n1-1) * minorLoopBytes) are read
* using DMA, the left (minorLoopBytes + n2) are read using blocking method.
*
* Write:
* Assume the data length is Lw = (n1 * minorLoopBytes + n2), where
* n2 < minorLoopBytes.
* If (n1 = 0), then all data are sent using blocking method.
* If (n1 >= 1), then the beginning (n1 * minorLoopBytes) are sent
* using DMA, the left n2 are sent using blocking method.
*/
/* Check if the device is busy. */
if ((uint32_t)kFLEXIO_MCULCD_StateIdle != handle->state)
{
return kStatus_FLEXIO_MCULCD_Busy;
}
/* Set the state in handle. */
if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
{
handle->state = (uint32_t)kFLEXIO_MCULCD_StateReadArray;
handle->minorLoopBytes = handle->rxShifterNum * 4UL;
}
else
{
handle->minorLoopBytes = handle->txShifterNum * 4UL;
if (kFLEXIO_MCULCD_WriteArray == xfer->mode)
{
handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteArray;
}
else
{
handle->state = (uint32_t)kFLEXIO_MCULCD_StateWriteSameValue;
}
}
/*
* For TX, if data is less than one minor loop, then use polling method.
* For RX, if data is less than two minor loop, then use polling method.
*/
if ((xfer->dataSize < handle->minorLoopBytes) ||
((kFLEXIO_MCULCD_ReadArray == xfer->mode) && (xfer->dataSize < 2U * (handle->minorLoopBytes))))
{
FLEXIO_MCULCD_TransferBlocking(base, xfer);
handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
/* Callback to inform upper layer. */
if (NULL != handle->completionCallback)
{
handle->completionCallback(base, handle, kStatus_FLEXIO_MCULCD_Idle, handle->userData);
}
}
else
{
handle->dataCount = xfer->dataSize;
handle->remainingCount = xfer->dataSize;
handle->dataAddrOrSameValue = xfer->dataAddrOrSameValue;
/* Setup DMA to transfer data. */
/* Assert the nCS. */
FLEXIO_MCULCD_StartTransfer(base);
if (!xfer->dataOnly)
{
/* Send the command. */
FLEXIO_MCULCD_WriteCommandBlocking(base, xfer->command);
}
/* Setup the DMA configuration. */
FLEXIO_MCULCD_EDMAConfig(base, handle);
/* Start the transfer. */
if (kFLEXIO_MCULCD_ReadArray == xfer->mode)
{
/* For 6800, assert the RDWR pin. */
if (kFLEXIO_MCULCD_6800 == base->busType)
{
base->setRDWRPin(true);
}
FLEXIO_MCULCD_SetMultiBeatsReadConfig(base);
FLEXIO_MCULCD_EnableRxDMA(base, true);
EDMA_StartTransfer(handle->rxDmaHandle);
}
else
{
/* For 6800, de-assert the RDWR pin. */
if (kFLEXIO_MCULCD_6800 == base->busType)
{
base->setRDWRPin(false);
}
FLEXIO_MCULCD_SetMultiBeatsWriteConfig(base);
FLEXIO_MCULCD_EnableTxDMA(base, true);
EDMA_StartTransfer(handle->txDmaHandle);
}
}
return kStatus_Success;
}
/*!
* brief Aborts a FlexIO MCULCD transfer using eDMA.
*
* param base pointer to FLEXIO_MCULCD_Type structure.
* param handle FlexIO MCULCD eDMA handle pointer.
*/
void FLEXIO_MCULCD_TransferAbortEDMA(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle)
{
assert(NULL != handle);
/* Disable dma. */
if (NULL != handle->txDmaHandle)
{
EDMA_AbortTransfer(handle->txDmaHandle);
}
if (NULL != handle->rxDmaHandle)
{
EDMA_AbortTransfer(handle->rxDmaHandle);
}
/* Disable DMA enable bit. */
FLEXIO_MCULCD_EnableTxDMA(handle->base, false);
FLEXIO_MCULCD_EnableRxDMA(handle->base, false);
/* Set the handle state. */
handle->state = (uint32_t)kFLEXIO_MCULCD_StateIdle;
handle->dataCount = 0;
}
/*!
* brief Gets the remaining bytes for FlexIO MCULCD eDMA transfer.
*
* param base pointer to FLEXIO_MCULCD_Type structure.
* param handle FlexIO MCULCD eDMA handle pointer.
* param count Number of count transferred so far by the eDMA transaction.
* retval kStatus_Success Get the transferred count Successfully.
* retval kStatus_NoTransferInProgress No transfer in process.
*/
status_t FLEXIO_MCULCD_TransferGetCountEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
size_t *count)
{
assert(NULL != handle);
assert(NULL != count);
uint32_t state = handle->state;
if ((uint32_t)kFLEXIO_MCULCD_StateIdle == state)
{
return kStatus_NoTransferInProgress;
}
else
{
*count = handle->dataCount - handle->remainingCount;
if ((uint32_t)kFLEXIO_MCULCD_StateReadArray == state)
{
*count -= handle->minorLoopBytes *
EDMA_GetRemainingMajorLoopCount(handle->rxDmaHandle->base, handle->rxDmaHandle->channel);
}
else
{
*count -= handle->minorLoopBytes *
EDMA_GetRemainingMajorLoopCount(handle->txDmaHandle->base, handle->txDmaHandle->channel);
}
}
return kStatus_Success;
}

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2020,2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_MCULCD_EDMA_H_
#define FSL_FLEXIO_MCULCD_EDMA_H_
#include "fsl_edma.h"
#include "fsl_flexio_mculcd.h"
/*!
* @addtogroup flexio_edma_mculcd
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @{ */
/*! @brief FlexIO MCULCD EDMA driver version. */
#define FSL_FLEXIO_MCULCD_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 0, 5))
/*! @} */
/*! @brief typedef for flexio_mculcd_edma_handle_t in advance. */
typedef struct _flexio_mculcd_edma_handle flexio_mculcd_edma_handle_t;
/*! @brief FlexIO MCULCD master callback for transfer complete.
*
* When transfer finished, the callback function is called and returns the
* @p status as kStatus_FLEXIO_MCULCD_Idle.
*/
typedef void (*flexio_mculcd_edma_transfer_callback_t)(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO MCULCD eDMA transfer handle, users should not touch the
* content of the handle.*/
struct _flexio_mculcd_edma_handle
{
FLEXIO_MCULCD_Type *base; /*!< Pointer to the FLEXIO_MCULCD_Type. */
uint8_t txShifterNum; /*!< Number of shifters used for TX. */
uint8_t rxShifterNum; /*!< Number of shifters used for RX. */
uint32_t minorLoopBytes; /*!< eDMA transfer minor loop bytes. */
edma_modulo_t txEdmaModulo; /*!< Modulo value for the FlexIO shifter buffer access. */
edma_modulo_t rxEdmaModulo; /*!< Modulo value for the FlexIO shifter buffer access. */
uint32_t dataAddrOrSameValue; /*!< When sending the same value for many times,
this is the value to send. When writing or
reading array, this is the address of the
data array. */
size_t dataCount; /*!< Total count to be transferred. */
volatile size_t remainingCount; /*!< Remaining count still not transfered. */
volatile uint32_t state; /*!< FlexIO MCULCD driver internal state. */
edma_handle_t *txDmaHandle; /*!< DMA handle for MCULCD TX */
edma_handle_t *rxDmaHandle; /*!< DMA handle for MCULCD RX */
flexio_mculcd_edma_transfer_callback_t completionCallback; /*!< Callback for MCULCD DMA transfer */
void *userData; /*!< User Data for MCULCD DMA callback */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA Transactional
* @{
*/
/*!
* @brief Initializes the FLEXO MCULCD master eDMA handle.
*
* This function initializes the FLEXO MCULCD master eDMA handle which can be
* used for other FLEXO MCULCD transactional APIs. For a specified FLEXO MCULCD
* instance, call this API once to get the initialized handle.
*
* @param base Pointer to FLEXIO_MCULCD_Type structure.
* @param handle Pointer to flexio_mculcd_edma_handle_t structure to store the
* transfer state.
* @param callback MCULCD transfer complete callback, NULL means no callback.
* @param userData callback function parameter.
* @param txDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA TX,
* the DMA request source of this handle should be the first of TX shifters.
* @param rxDmaHandle User requested eDMA handle for FlexIO MCULCD eDMA RX,
* the DMA request source of this handle should be the last of RX shifters.
* @retval kStatus_Success Successfully create the handle.
*/
status_t FLEXIO_MCULCD_TransferCreateHandleEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
flexio_mculcd_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txDmaHandle,
edma_handle_t *rxDmaHandle);
/*!
* @brief Performs a non-blocking FlexIO MCULCD transfer using eDMA.
*
* This function returns immediately after transfer initiates. To check whether
* the transfer is completed, user could:
* 1. Use the transfer completed callback;
* 2. Polling function FLEXIO_MCULCD_GetTransferCountEDMA
*
* @param base pointer to FLEXIO_MCULCD_Type structure.
* @param handle pointer to flexio_mculcd_edma_handle_t structure to store the
* transfer state.
* @param xfer Pointer to FlexIO MCULCD transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_MCULCD_Busy FlexIO MCULCD is not idle, it is running another
* transfer.
*/
status_t FLEXIO_MCULCD_TransferEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
flexio_mculcd_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO MCULCD transfer using eDMA.
*
* @param base pointer to FLEXIO_MCULCD_Type structure.
* @param handle FlexIO MCULCD eDMA handle pointer.
*/
void FLEXIO_MCULCD_TransferAbortEDMA(FLEXIO_MCULCD_Type *base, flexio_mculcd_edma_handle_t *handle);
/*!
* @brief Gets the remaining bytes for FlexIO MCULCD eDMA transfer.
*
* @param base pointer to FLEXIO_MCULCD_Type structure.
* @param handle FlexIO MCULCD eDMA handle pointer.
* @param count Number of count transferred so far by the eDMA transaction.
* @retval kStatus_Success Get the transferred count Successfully.
* @retval kStatus_NoTransferInProgress No transfer in process.
*/
status_t FLEXIO_MCULCD_TransferGetCountEDMA(FLEXIO_MCULCD_Type *base,
flexio_mculcd_edma_handle_t *handle,
size_t *count);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* FSL_FLEXIO_MCULCD_EDMA_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,718 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_SPI_H_
#define FSL_FLEXIO_SPI_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_spi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO SPI driver version. */
#define FSL_FLEXIO_SPI_DRIVER_VERSION (MAKE_VERSION(2, 3, 4))
/*! @} */
#ifndef FLEXIO_SPI_DUMMYDATA
/*! @brief FlexIO SPI dummy transfer data, the data is sent while txData is NULL. */
#define FLEXIO_SPI_DUMMYDATA (0x00U)
#endif
/*! @brief Retry times for waiting flag. */
#ifndef SPI_RETRY_TIMES
#define SPI_RETRY_TIMES 0U /* Define to zero means keep waiting until the flag is assert/deassert. */
#endif
/*! @brief Get the transfer data format of width and bit order. */
#define FLEXIO_SPI_XFER_DATA_FORMAT(flag) ((flag) & (0x7U))
/*! @brief Error codes for the FlexIO SPI driver. */
enum
{
kStatus_FLEXIO_SPI_Busy = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 1), /*!< FlexIO SPI is busy. */
kStatus_FLEXIO_SPI_Idle = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 2), /*!< SPI is idle */
kStatus_FLEXIO_SPI_Error = MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 3), /*!< FlexIO SPI error. */
kStatus_FLEXIO_SPI_Timeout =
MAKE_STATUS(kStatusGroup_FLEXIO_SPI, 4), /*!< FlexIO SPI timeout polling status flags. */
};
/*! @brief FlexIO SPI clock phase configuration. */
typedef enum _flexio_spi_clock_phase
{
kFLEXIO_SPI_ClockPhaseFirstEdge = 0x0U, /*!< First edge on SPSCK occurs at the middle of the first
* cycle of a data transfer. */
kFLEXIO_SPI_ClockPhaseSecondEdge = 0x1U, /*!< First edge on SPSCK occurs at the start of the
* first cycle of a data transfer. */
} flexio_spi_clock_phase_t;
/*! @brief FlexIO SPI data shifter direction options. */
typedef enum _flexio_spi_shift_direction
{
kFLEXIO_SPI_MsbFirst = 0, /*!< Data transfers start with most significant bit. */
kFLEXIO_SPI_LsbFirst = 1, /*!< Data transfers start with least significant bit. */
} flexio_spi_shift_direction_t;
/*! @brief FlexIO SPI data length mode options. */
typedef enum _flexio_spi_data_bitcount_mode
{
kFLEXIO_SPI_8BitMode = 0x08U, /*!< 8-bit data transmission mode. */
kFLEXIO_SPI_16BitMode = 0x10U, /*!< 16-bit data transmission mode. */
kFLEXIO_SPI_32BitMode = 0x20U, /*!< 32-bit data transmission mode. */
} flexio_spi_data_bitcount_mode_t;
/*! @brief Define FlexIO SPI interrupt mask. */
enum _flexio_spi_interrupt_enable
{
kFLEXIO_SPI_TxEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_SPI_RxFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO SPI status mask. */
enum _flexio_spi_status_flags
{
kFLEXIO_SPI_TxBufferEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_SPI_RxBufferFullFlag = 0x2U, /*!< Receive buffer full flag. */
};
/*! @brief Define FlexIO SPI DMA mask. */
enum _flexio_spi_dma_enable
{
kFLEXIO_SPI_TxDmaEnable = 0x1U, /*!< Tx DMA request source */
kFLEXIO_SPI_RxDmaEnable = 0x2U, /*!< Rx DMA request source */
kFLEXIO_SPI_DmaAllEnable = 0x3U, /*!< All DMA request source*/
};
/*! @brief Define FlexIO SPI transfer flags.
* @note Use kFLEXIO_SPI_csContinuous and one of the other flags to OR together to form the transfer flag. */
enum _flexio_spi_transfer_flags
{
kFLEXIO_SPI_8bitMsb = 0x0U, /*!< FlexIO SPI 8-bit MSB first */
kFLEXIO_SPI_8bitLsb = 0x1U, /*!< FlexIO SPI 8-bit LSB first */
kFLEXIO_SPI_16bitMsb = 0x2U, /*!< FlexIO SPI 16-bit MSB first */
kFLEXIO_SPI_16bitLsb = 0x3U, /*!< FlexIO SPI 16-bit LSB first */
kFLEXIO_SPI_32bitMsb = 0x4U, /*!< FlexIO SPI 32-bit MSB first */
kFLEXIO_SPI_32bitLsb = 0x5U, /*!< FlexIO SPI 32-bit LSB first */
kFLEXIO_SPI_csContinuous = 0x8U, /*!< Enable the CS signal continuous mode */
};
/*! @brief Define FlexIO SPI access structure typedef. */
typedef struct _flexio_spi_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t SDOPinIndex; /*!< Pin select for data output. To set SDO pin in Hi-Z state, user needs to mux the pin as
GPIO input and disable all pull up/down in application. */
uint8_t SDIPinIndex; /*!< Pin select for data input. */
uint8_t SCKPinIndex; /*!< Pin select for clock. */
uint8_t CSnPinIndex; /*!< Pin select for enable. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO SPI. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO SPI. */
} FLEXIO_SPI_Type;
/*! @brief Define FlexIO SPI master configuration structure. */
typedef struct _flexio_spi_master_config
{
bool enableMaster; /*!< Enable/disable FlexIO SPI master after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_master_config_t;
/*! @brief Define FlexIO SPI slave configuration structure. */
typedef struct _flexio_spi_slave_config
{
bool enableSlave; /*!< Enable/disable FlexIO SPI slave after configuration. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode. */
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode. */
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
flexio_spi_clock_phase_t phase; /*!< Clock phase. */
flexio_spi_data_bitcount_mode_t dataMode; /*!< 8bit or 16bit mode. */
} flexio_spi_slave_config_t;
/*! @brief Define FlexIO SPI transfer structure. */
typedef struct _flexio_spi_transfer
{
const uint8_t *txData; /*!< Send buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t dataSize; /*!< Transfer bytes. */
uint8_t flags; /*!< FlexIO SPI control flag, MSB first or LSB first. */
} flexio_spi_transfer_t;
/*! @brief typedef for flexio_spi_master_handle_t in advance. */
typedef struct _flexio_spi_master_handle flexio_spi_master_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_handle_t flexio_spi_slave_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FlexIO SPI handle structure. */
struct _flexio_spi_master_handle
{
const uint8_t *txData; /*!< Transfer buffer. */
uint8_t *rxData; /*!< Receive buffer. */
size_t transferSize; /*!< Total bytes to be transferred. */
volatile size_t txRemainingBytes; /*!< Send data remaining in bytes. */
volatile size_t rxRemainingBytes; /*!< Receive data remaining in bytes. */
volatile uint32_t state; /*!< FlexIO SPI internal state. */
uint8_t bytePerFrame; /*!< SPI mode, 2bytes or 1byte in a frame */
flexio_spi_shift_direction_t direction; /*!< Shift direction. */
flexio_spi_master_transfer_callback_t callback; /*!< FlexIO SPI callback. */
void *userData; /*!< Callback parameter. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name FlexIO SPI Configuration
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI master hardware,
* and configures the FlexIO SPI with FlexIO SPI master configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_MasterGetDefaultConfig().
*
* @note 1.FlexIO SPI master only support CPOL = 0, which means clock inactive low.
* 2.For FlexIO SPI master, the input valid time is 1.5 clock cycles, for slave the output valid time
* is 2.5 clock cycles. So if FlexIO SPI master communicates with other spi IPs, the maximum baud
* rate is FlexIO clock frequency divided by 2*2=4. If FlexIO SPI master communicates with FlexIO
* SPI slave, the maximum baud rate is FlexIO clock frequency divided by (1.5+2.5)*2=8.
*
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_spi_master_config_t config = {
.enableMaster = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 500000,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_MasterInit(&spiDev, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
*/
void FLEXIO_SPI_MasterInit(FLEXIO_SPI_Type *base, flexio_spi_master_config_t *masterConfig, uint32_t srcClock_Hz);
/*!
* @brief Resets the FlexIO SPI timer and shifter config.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_MasterDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI master. The configuration
* can be used directly by calling the FLEXIO_SPI_MasterConfigure().
* Example:
@code
flexio_spi_master_config_t masterConfig;
FLEXIO_SPI_MasterGetDefaultConfig(&masterConfig);
@endcode
* @param masterConfig Pointer to the flexio_spi_master_config_t structure.
*/
void FLEXIO_SPI_MasterGetDefaultConfig(flexio_spi_master_config_t *masterConfig);
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures the FlexIO SPI slave hardware
* configuration, and configures the FlexIO SPI with FlexIO SPI slave configuration. The
* configuration structure can be filled by the user, or be set with default values
* by the FLEXIO_SPI_SlaveGetDefaultConfig().
*
* @note 1.Only one timer is needed in the FlexIO SPI slave. As a result, the second timer index is ignored.
* 2.FlexIO SPI slave only support CPOL = 0, which means clock inactive low.
* 3.For FlexIO SPI master, the input valid time is 1.5 clock cycles, for slave the output valid time
* is 2.5 clock cycles. So if FlexIO SPI slave communicates with other spi IPs, the maximum baud
* rate is FlexIO clock frequency divided by 3*2=6. If FlexIO SPI slave communicates with FlexIO
* SPI master, the maximum baud rate is FlexIO clock frequency divided by (1.5+2.5)*2=8.
* Example
@code
FLEXIO_SPI_Type spiDev = {
.flexioBase = FLEXIO,
.SDOPinIndex = 0,
.SDIPinIndex = 1,
.SCKPinIndex = 2,
.CSnPinIndex = 3,
.shifterIndex = {0,1},
.timerIndex = {0}
};
flexio_spi_slave_config_t config = {
.enableSlave = true,
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.phase = kFLEXIO_SPI_ClockPhaseFirstEdge,
.direction = kFLEXIO_SPI_MsbFirst,
.dataMode = kFLEXIO_SPI_8BitMode
};
FLEXIO_SPI_SlaveInit(&spiDev, &config);
@endcode
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveInit(FLEXIO_SPI_Type *base, flexio_spi_slave_config_t *slaveConfig);
/*!
* @brief Gates the FlexIO clock.
*
* @param base Pointer to the FLEXIO_SPI_Type.
*/
void FLEXIO_SPI_SlaveDeinit(FLEXIO_SPI_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO SPI slave. The configuration
* can be used directly for calling the FLEXIO_SPI_SlaveConfigure().
* Example:
@code
flexio_spi_slave_config_t slaveConfig;
FLEXIO_SPI_SlaveGetDefaultConfig(&slaveConfig);
@endcode
* @param slaveConfig Pointer to the flexio_spi_slave_config_t structure.
*/
void FLEXIO_SPI_SlaveGetDefaultConfig(flexio_spi_slave_config_t *slaveConfig);
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @return status flag; Use the status flag to AND the following flag mask and get the status.
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
uint32_t FLEXIO_SPI_GetStatusFlags(FLEXIO_SPI_Type *base);
/*!
* @brief Clears FlexIO SPI status flags.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask status flag
* The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_TxEmptyFlag
* @arg kFLEXIO_SPI_RxEmptyFlag
*/
void FLEXIO_SPI_ClearStatusFlags(FLEXIO_SPI_Type *base, uint32_t mask);
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO SPI interrupt.
*
* This function enables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source. The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_EnableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO SPI interrupt.
*
* This function disables the FlexIO SPI interrupt.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask interrupt source The parameter can be any combination of the following values:
* @arg kFLEXIO_SPI_RxFullInterruptEnable
* @arg kFLEXIO_SPI_TxEmptyInterruptEnable
*/
void FLEXIO_SPI_DisableInterrupts(FLEXIO_SPI_Type *base, uint32_t mask);
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI transmit DMA. This function enables/disables the FlexIO SPI Tx DMA,
* which means that asserting the kFLEXIO_SPI_TxEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param mask SPI DMA source.
* @param enable True means enable DMA, false means disable DMA.
*/
void FLEXIO_SPI_EnableDMA(FLEXIO_SPI_Type *base, uint32_t mask, bool enable);
/*!
* @brief Gets the FlexIO SPI transmit data register address for MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI transmit data register address.
*/
static inline uint32_t FLEXIO_SPI_GetTxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped,
base->shifterIndex[0]) +
3U;
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
}
/*!
* @brief Gets the FlexIO SPI receive data register address for the MSB first transfer.
*
* This function returns the SPI data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return FlexIO SPI receive data register address.
*/
static inline uint32_t FLEXIO_SPI_GetRxDataRegisterAddress(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferBitSwapped, base->shifterIndex[1]);
}
else
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[1]) + 3U;
}
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO SPI module operation.
*
* @param base Pointer to the FLEXIO_SPI_Type.
* @param enable True to enable, false does not have any effect.
*/
static inline void FLEXIO_SPI_Enable(FLEXIO_SPI_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Sets baud rate for the FlexIO SPI transfer, which is only used for the master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param baudRate_Bps Baud Rate needed in Hz.
* @param srcClockHz SPI source clock frequency in Hz.
*/
void FLEXIO_SPI_MasterSetBaudRate(FLEXIO_SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcClockHz);
/*!
* @brief Writes one byte of data, which is sent using the MSB method.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register but the data transfer is not finished on the bus. Ensure that
* the TxEmptyFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param data 8/16/32 bit data.
*/
static inline void FLEXIO_SPI_WriteData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction, uint32_t data)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
base->flexioBase->SHIFTBUFBBS[base->shifterIndex[0]] = data;
}
else
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = data;
}
}
/*!
* @brief Reads 8 bit/16 bit data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @return 8 bit/16 bit data received.
*/
static inline uint32_t FLEXIO_SPI_ReadData(FLEXIO_SPI_Type *base, flexio_spi_shift_direction_t direction)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
return (uint32_t)(base->flexioBase->SHIFTBUFBIS[base->shifterIndex[1]]);
}
else
{
return (uint32_t)(base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]]);
}
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The data bytes to send.
* @param size The number of data bytes to send.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
*/
status_t FLEXIO_SPI_WriteBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
const uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param direction Shift direction of MSB first or LSB first.
* @param buffer The buffer to store the received bytes.
* @param size The number of data bytes to be received.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
*/
status_t FLEXIO_SPI_ReadBlocking(FLEXIO_SPI_Type *base,
flexio_spi_shift_direction_t direction,
uint8_t *buffer,
size_t size);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks via polling until all bytes have been received.
*
* @param base pointer to FLEXIO_SPI_Type structure
* @param xfer FlexIO SPI transfer structure, see #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_FLEXIO_SPI_Timeout The transfer timed out and was aborted.
*/
status_t FLEXIO_SPI_MasterTransferBlocking(FLEXIO_SPI_Type *base, flexio_spi_transfer_t *xfer);
/*!
* @brief Flush tx/rx shifters.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
*/
void FLEXIO_SPI_FlushShifters(FLEXIO_SPI_Type *base);
/*! @} */
/*Transactional APIs*/
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO SPI Master handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_master_transfer_callback_t callback,
void *userData);
/*!
* @brief Master transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_master_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the master data transfer, which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle);
/*!
* @brief Gets the data transfer status which used IRQ.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_SPI_MasterTransferGetCount(FLEXIO_SPI_Type *base, flexio_spi_master_handle_t *handle, size_t *count);
/*!
* @brief FlexIO SPI master IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_master_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_MasterTransferHandleIRQ(void *spiType, void *spiHandle);
/*!
* @brief Initializes the FlexIO SPI Slave handle, which is used in transactional functions.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_SPI_SlaveTransferCreateHandle(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_slave_transfer_callback_t callback,
void *userData);
/*!
* @brief Slave transfer data using IRQ.
*
* This function sends data using IRQ. This is a non-blocking function, which returns
* right away. When all data is sent out/received, the callback function is called.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param xfer FlexIO SPI transfer structure. See #flexio_spi_transfer_t.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy SPI is not idle; it is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferNonBlocking(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts the slave data transfer which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbort(FLEXIO_SPI_Type *base, flexio_spi_slave_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbort(base, handle);
}
/*!
* @brief Gets the data transfer status which used IRQ, share same API with master.
*
* @param base Pointer to the FLEXIO_SPI_Type structure.
* @param handle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
* @param count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_InvalidArgument count is Invalid.
* @retval kStatus_Success Successfully return the count.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCount(FLEXIO_SPI_Type *base,
flexio_spi_slave_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCount(base, handle, count);
}
/*!
* @brief FlexIO SPI slave IRQ handler function.
*
* @param spiType Pointer to the FLEXIO_SPI_Type structure.
* @param spiHandle Pointer to the flexio_spi_slave_handle_t structure to store the transfer state.
*/
void FLEXIO_SPI_SlaveTransferHandleIRQ(void *spiType, void *spiHandle);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /*FSL_FLEXIO_SPI_H_*/

View File

@ -0,0 +1,565 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_spi_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flexio_spi_edma"
#endif
/*<! Structure definition for spi_edma_private_handle_t. The structure is private. */
typedef struct _flexio_spi_master_edma_private_handle
{
FLEXIO_SPI_Type *base;
flexio_spi_master_edma_handle_t *handle;
} flexio_spi_master_edma_private_handle_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief EDMA callback function for FLEXIO SPI send transfer.
*
* @param handle EDMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief EDMA callback function for FLEXIO SPI receive transfer.
*
* @param handle EDMA handle pointer.
* @param param Callback function parameter.
*/
static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief EDMA config for FLEXIO SPI transfer.
*
* @param base pointer to FLEXIO_SPI_Type structure.
* @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to flexio spi transfer structure.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_InvalidArgument The transfer size is not supported.
*/
static status_t FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*******************************************************************************
* Variables
******************************************************************************/
/* Dummy data used to send */
static const uint32_t s_dummyData = FLEXIO_SPI_DUMMYDATA;
/*< @brief user configurable flexio spi handle count. */
#define FLEXIO_SPI_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_spi_master_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_SPI_HANDLE_COUNT];
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_SPI_TxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
/* Disable Tx DMA */
if (transferDone)
{
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, (uint32_t)kFLEXIO_SPI_TxDmaEnable, false);
/* change the state */
spiPrivateHandle->handle->txInProgress = false;
/* All finished, call the callback */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback != NULL)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
}
static void FLEXIO_SPI_RxEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
tcds = tcds;
flexio_spi_master_edma_private_handle_t *spiPrivateHandle = (flexio_spi_master_edma_private_handle_t *)param;
if (transferDone)
{
/* Disable Rx dma */
FLEXIO_SPI_EnableDMA(spiPrivateHandle->base, (uint32_t)kFLEXIO_SPI_RxDmaEnable, false);
/* change the state */
spiPrivateHandle->handle->rxInProgress = false;
/* All finished, call the callback */
if ((spiPrivateHandle->handle->txInProgress == false) && (spiPrivateHandle->handle->rxInProgress == false))
{
if (spiPrivateHandle->handle->callback != NULL)
{
(spiPrivateHandle->handle->callback)(spiPrivateHandle->base, spiPrivateHandle->handle, kStatus_Success,
spiPrivateHandle->handle->userData);
}
}
}
}
static status_t FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
edma_transfer_config_t xferConfig = {0};
flexio_spi_shift_direction_t direction = kFLEXIO_SPI_MsbFirst;
uint8_t bytesPerFrame;
uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
/* Configure the values in handle. */
switch (dataFormat)
{
case (uint8_t)kFLEXIO_SPI_8bitMsb:
bytesPerFrame = 1U;
direction = kFLEXIO_SPI_MsbFirst;
break;
case (uint8_t)kFLEXIO_SPI_8bitLsb:
bytesPerFrame = 1U;
direction = kFLEXIO_SPI_LsbFirst;
break;
case (uint8_t)kFLEXIO_SPI_16bitMsb:
bytesPerFrame = 2U;
direction = kFLEXIO_SPI_MsbFirst;
break;
case (uint8_t)kFLEXIO_SPI_16bitLsb:
bytesPerFrame = 2U;
direction = kFLEXIO_SPI_LsbFirst;
break;
case (uint8_t)kFLEXIO_SPI_32bitMsb:
bytesPerFrame = 4U;
direction = kFLEXIO_SPI_MsbFirst;
break;
case (uint8_t)kFLEXIO_SPI_32bitLsb:
bytesPerFrame = 4U;
direction = kFLEXIO_SPI_LsbFirst;
break;
default:
bytesPerFrame = 1U;
direction = kFLEXIO_SPI_MsbFirst;
assert(true);
break;
}
/* Transfer size should be bytesPerFrame divisible. */
if ((xfer->dataSize % bytesPerFrame) != 0U)
{
return kStatus_InvalidArgument;
}
/* Save total transfer size. */
handle->transferSize = xfer->dataSize;
/* Configure tx transfer EDMA. */
xferConfig.destAddr = FLEXIO_SPI_GetTxDataRegisterAddress(base, direction);
xferConfig.destOffset = 0;
if (bytesPerFrame == 1U)
{
xferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
xferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
xferConfig.minorLoopBytes = 1U;
}
else if (bytesPerFrame == 2U)
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
xferConfig.destAddr -= 1U;
}
xferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;
xferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
xferConfig.minorLoopBytes = 2U;
}
else
{
if (direction == kFLEXIO_SPI_MsbFirst)
{
xferConfig.destAddr -= 3U;
}
xferConfig.srcTransferSize = kEDMA_TransferSize4Bytes;
xferConfig.destTransferSize = kEDMA_TransferSize4Bytes;
xferConfig.minorLoopBytes = 4U;
}
/* Configure DMA channel. */
if (xfer->txData != NULL)
{
xferConfig.srcOffset = (int16_t)bytesPerFrame;
xferConfig.srcAddr = (uint32_t)(xfer->txData);
}
else
{
/* Disable the source increasement and source set to dummyData. */
xferConfig.srcOffset = 0;
xferConfig.srcAddr = (uint32_t)(&s_dummyData);
}
xferConfig.majorLoopCounts = (xfer->dataSize / xferConfig.minorLoopBytes);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO SPI handle */
handle->nbytes = (uint8_t)xferConfig.minorLoopBytes;
if (handle->txHandle != NULL)
{
(void)EDMA_SubmitTransfer(handle->txHandle, &xferConfig);
}
/* Configure rx transfer EDMA. */
if (xfer->rxData != NULL)
{
xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction);
if (bytesPerFrame == 2U)
{
if (direction == kFLEXIO_SPI_LsbFirst)
{
xferConfig.srcAddr -= 1U;
}
}
else if (bytesPerFrame == 4U)
{
if (direction == kFLEXIO_SPI_LsbFirst)
{
xferConfig.srcAddr -= 3U;
}
}
else
{
}
xferConfig.srcOffset = 0;
xferConfig.destAddr = (uint32_t)(xfer->rxData);
xferConfig.destOffset = (int16_t)bytesPerFrame;
(void)EDMA_SubmitTransfer(handle->rxHandle, &xferConfig);
handle->rxInProgress = true;
FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_RxDmaEnable, true);
EDMA_StartTransfer(handle->rxHandle);
}
/* Always start tx transfer. */
if (handle->txHandle != NULL)
{
handle->txInProgress = true;
FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_TxDmaEnable, true);
EDMA_StartTransfer(handle->txHandle);
}
return kStatus_Success;
}
/*!
* brief Initializes the FlexIO SPI master eDMA handle.
*
* This function initializes the FlexIO SPI master eDMA handle which can be used for other FlexIO SPI master
* transactional
* APIs.
* For a specified FlexIO SPI instance, call this API once to get the initialized handle.
*
* param base Pointer to FLEXIO_SPI_Type structure.
* param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* param callback SPI callback, NULL means no callback.
* param userData callback function parameter.
* param txHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
* param rxHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
* retval kStatus_Success Successfully create the handle.
* retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle)
{
assert(handle != NULL);
uint8_t index = 0;
/* Find the an empty handle pointer to store the handle. */
for (index = 0U; index < (uint8_t)FLEXIO_SPI_HANDLE_COUNT; index++)
{
if (s_edmaPrivateHandle[index].base == NULL)
{
s_edmaPrivateHandle[index].base = base;
s_edmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == (uint16_t)FLEXIO_SPI_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
/* Set spi base to handle. */
handle->txHandle = txHandle;
handle->rxHandle = rxHandle;
/* Register callback and userData. */
handle->callback = callback;
handle->userData = userData;
/* Set SPI state to idle. */
handle->txInProgress = false;
handle->rxInProgress = false;
/* Install callback for Tx/Rx dma channel. */
if (handle->txHandle != NULL)
{
EDMA_SetCallback(handle->txHandle, FLEXIO_SPI_TxEDMACallback, &s_edmaPrivateHandle[index]);
}
if (handle->rxHandle != NULL)
{
EDMA_SetCallback(handle->rxHandle, FLEXIO_SPI_RxEDMACallback, &s_edmaPrivateHandle[index]);
}
return kStatus_Success;
}
/*!
* brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status and check
* whether the FlexIO SPI transfer is finished.
*
* param base Pointer to FLEXIO_SPI_Type structure.
* param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* param xfer Pointer to FlexIO SPI transfer structure.
* retval kStatus_Success Successfully start a transfer.
* retval kStatus_InvalidArgument Input argument is invalid.
* retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle != NULL);
assert(xfer != NULL);
uint32_t dataMode = 0;
uint16_t timerCmp = (uint16_t)base->flexioBase->TIMCMP[base->timerIndex[0]];
uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
timerCmp &= 0x00FFU;
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* Timer1 controls the CS signal which enables/disables(asserts/deasserts) when timer0 enable/disable. Timer0
enables when tx shifter is written and disables when timer compare. The timer compare event causes the
transmit shift registers to load which generates a tx register empty event. Since when timer stop bit is
disabled, a timer enable condition can be detected in the same cycle as a timer disable condition, so if
software writes the tx register upon the detection of tx register empty event, the timer enable condition
is triggered again, then the CS signal can remain low until software no longer writes the tx register. */
if ((xfer->flags & (uint8_t)kFLEXIO_SPI_csContinuous) != 0U)
{
base->flexioBase->TIMCFG[base->timerIndex[0]] =
(base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TSTOP_MASK) |
FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitDisabled);
}
else
{
base->flexioBase->TIMCFG[base->timerIndex[0]] =
(base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TSTOP_MASK) |
FLEXIO_TIMCFG_TSTOP(kFLEXIO_TimerStopBitEnableOnTimerDisable);
}
/* configure data mode. */
if ((dataFormat == (uint8_t)kFLEXIO_SPI_8bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_8bitLsb))
{
dataMode = (8UL * 2UL - 1UL) << 8U;
}
else if ((dataFormat == (uint8_t)kFLEXIO_SPI_16bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_16bitLsb))
{
dataMode = (16UL * 2UL - 1UL) << 8U;
}
else if ((dataFormat == (uint8_t)kFLEXIO_SPI_32bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_32bitLsb))
{
dataMode = (32UL * 2UL - 1UL) << 8U;
}
else
{
dataMode = (8UL * 2UL - 1UL) << 8U;
}
dataMode |= timerCmp;
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
return FLEXIO_SPI_EDMAConfig(base, handle, xfer);
}
/*!
* brief Gets the remaining bytes for FlexIO SPI eDMA transfer.
*
* param base Pointer to FLEXIO_SPI_Type structure.
* param handle FlexIO SPI eDMA handle pointer.
* param count Number of bytes transferred so far by the non-blocking transaction.
*/
status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
size_t *count)
{
assert(handle != NULL);
if (NULL == count)
{
return kStatus_InvalidArgument;
}
if (handle->rxInProgress)
{
*count =
(handle->transferSize - (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(
handle->rxHandle->base, handle->rxHandle->channel));
}
else
{
*count =
(handle->transferSize - (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(
handle->txHandle->base, handle->txHandle->channel));
}
return kStatus_Success;
}
/*!
* brief Aborts a FlexIO SPI transfer using eDMA.
*
* param base Pointer to FLEXIO_SPI_Type structure.
* param handle FlexIO SPI eDMA handle pointer.
*/
void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle)
{
assert(handle != NULL);
/* Disable dma. */
EDMA_AbortTransfer(handle->txHandle);
EDMA_AbortTransfer(handle->rxHandle);
/* Disable DMA enable bit. */
FLEXIO_SPI_EnableDMA(base, (uint32_t)kFLEXIO_SPI_DmaAllEnable, false);
/* Set the handle state. */
handle->txInProgress = false;
handle->rxInProgress = false;
}
/*!
* brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status and
* check whether the FlexIO SPI transfer is finished.
*
* param base Pointer to FLEXIO_SPI_Type structure.
* param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
* param xfer Pointer to FlexIO SPI transfer structure.
* retval kStatus_Success Successfully start a transfer.
* retval kStatus_InvalidArgument Input argument is invalid.
* retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_transfer_t *xfer)
{
assert(handle != NULL);
assert(xfer != NULL);
uint32_t dataMode = 0U;
uint8_t dataFormat = FLEXIO_SPI_XFER_DATA_FORMAT(xfer->flags);
/* Check if the device is busy. */
if ((handle->txInProgress) || (handle->rxInProgress))
{
return kStatus_FLEXIO_SPI_Busy;
}
/* SCK timer use CS pin as inverted trigger so timer should be disbaled on trigger falling edge(CS re-asserts). */
/* However if CPHA is first edge mode, timer will restart each time right after timer compare event occur and
before CS pin re-asserts, which triggers another shifter load. To avoid this, when in CS dis-continuous mode,
timer should disable in timer compare rather than trigger falling edge(CS re-asserts), and in CS continuous mode,
tx/rx shifters should be flushed after transfer finishes and before next transfer starts. */
FLEXIO_SPI_FlushShifters(base);
if ((xfer->flags & (uint8_t)kFLEXIO_SPI_csContinuous) != 0U)
{
base->flexioBase->TIMCFG[base->timerIndex[0]] |= FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTriggerFallingEdge);
}
else
{
if ((base->flexioBase->SHIFTCTL[base->shifterIndex[0]] & FLEXIO_SHIFTCTL_TIMPOL_MASK) ==
FLEXIO_SHIFTCTL_TIMPOL(kFLEXIO_ShifterTimerPolarityOnNegitive))
{
base->flexioBase->TIMCFG[base->timerIndex[0]] =
(base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TIMDIS_MASK) |
FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTimerCompare);
}
else
{
base->flexioBase->TIMCFG[base->timerIndex[0]] =
(base->flexioBase->TIMCFG[base->timerIndex[0]] & ~FLEXIO_TIMCFG_TIMDIS_MASK) |
FLEXIO_TIMCFG_TIMDIS(kFLEXIO_TimerDisableOnTriggerFallingEdge);
}
}
/* Check if input parameter invalid. */
if (((xfer->txData == NULL) && (xfer->rxData == NULL)) || (xfer->dataSize == 0U))
{
return kStatus_InvalidArgument;
}
/* configure data mode. */
if ((dataFormat == (uint8_t)kFLEXIO_SPI_8bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_8bitLsb))
{
dataMode = 8U * 2U - 1U;
}
else if ((dataFormat == (uint8_t)kFLEXIO_SPI_16bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_16bitLsb))
{
dataMode = 16U * 2U - 1U;
}
else if ((dataFormat == (uint8_t)kFLEXIO_SPI_32bitMsb) || (dataFormat == (uint8_t)kFLEXIO_SPI_32bitLsb))
{
dataMode = 32UL * 2UL - 1UL;
}
else
{
dataMode = 8U * 2U - 1U;
}
base->flexioBase->TIMCMP[base->timerIndex[0]] = dataMode;
return FLEXIO_SPI_EDMAConfig(base, handle, xfer);
}

View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_SPI_EDMA_H_
#define FSL_FLEXIO_SPI_EDMA_H_
#include "fsl_flexio_spi.h"
#include "fsl_edma.h"
/*!
* @addtogroup flexio_edma_spi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO SPI EDMA driver version. */
#define FSL_FLEXIO_SPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 3, 0))
/*! @} */
/*! @brief typedef for flexio_spi_master_edma_handle_t in advance. */
typedef struct _flexio_spi_master_edma_handle flexio_spi_master_edma_handle_t;
/*! @brief Slave handle is the same with master handle. */
typedef flexio_spi_master_edma_handle_t flexio_spi_slave_edma_handle_t;
/*! @brief FlexIO SPI master callback for finished transmit */
typedef void (*flexio_spi_master_edma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI slave callback for finished transmit */
typedef void (*flexio_spi_slave_edma_transfer_callback_t)(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief FlexIO SPI eDMA transfer handle, users should not touch the content of the handle.*/
struct _flexio_spi_master_edma_handle
{
size_t transferSize; /*!< Total bytes to be transferred. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
bool txInProgress; /*!< Send transfer in progress */
bool rxInProgress; /*!< Receive transfer in progress */
edma_handle_t *txHandle; /*!< DMA handler for SPI send */
edma_handle_t *rxHandle; /*!< DMA handler for SPI receive */
flexio_spi_master_edma_transfer_callback_t callback; /*!< Callback for SPI DMA transfer */
void *userData; /*!< User Data for SPI DMA callback */
};
/*******************************************************************************
* APIs
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA Transactional
* @{
*/
/*!
* @brief Initializes the FlexIO SPI master eDMA handle.
*
* This function initializes the FlexIO SPI master eDMA handle which can be used for other FlexIO SPI master
* transactional
* APIs.
* For a specified FlexIO SPI instance, call this API once to get the initialized handle.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
* @param rxHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle);
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status and check
* whether the FlexIO SPI transfer is finished.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
*/
void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle);
/*!
* @brief Gets the number of bytes transferred so far using FlexIO SPI master eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_master_edma_handle_t *handle,
size_t *count);
/*!
* @brief Initializes the FlexIO SPI slave eDMA handle.
*
* This function initializes the FlexIO SPI slave eDMA handle.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
* @param callback SPI callback, NULL means no callback.
* @param userData callback function parameter.
* @param txHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer.
* @param rxHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer.
*/
static inline void FLEXIO_SPI_SlaveTransferCreateHandleEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_slave_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txHandle,
edma_handle_t *rxHandle)
{
(void)FLEXIO_SPI_MasterTransferCreateHandleEDMA(base, handle, callback, userData, txHandle, rxHandle);
}
/*!
* @brief Performs a non-blocking FlexIO SPI transfer using eDMA.
*
* @note This interface returns immediately after transfer initiates. Call
* FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status and
* check whether the FlexIO SPI transfer is finished.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
* @param xfer Pointer to FlexIO SPI transfer structure.
* @retval kStatus_Success Successfully start a transfer.
* @retval kStatus_InvalidArgument Input argument is invalid.
* @retval kStatus_FLEXIO_SPI_Busy FlexIO SPI is not idle, is running another transfer.
*/
status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
flexio_spi_transfer_t *xfer);
/*!
* @brief Aborts a FlexIO SPI transfer using eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state.
*/
static inline void FLEXIO_SPI_SlaveTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_slave_edma_handle_t *handle)
{
FLEXIO_SPI_MasterTransferAbortEDMA(base, handle);
}
/*!
* @brief Gets the number of bytes transferred so far using FlexIO SPI slave eDMA.
*
* @param base Pointer to FLEXIO_SPI_Type structure.
* @param handle FlexIO SPI eDMA handle pointer.
* @param count Number of bytes transferred so far by the non-blocking transaction.
*/
static inline status_t FLEXIO_SPI_SlaveTransferGetCountEDMA(FLEXIO_SPI_Type *base,
flexio_spi_slave_edma_handle_t *handle,
size_t *count)
{
return FLEXIO_SPI_MasterTransferGetCountEDMA(base, handle, count);
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,588 @@
/*
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_UART_H_
#define FSL_FLEXIO_UART_H_
#include "fsl_common.h"
#include "fsl_flexio.h"
/*!
* @addtogroup flexio_uart
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO UART driver version. */
#define FSL_FLEXIO_UART_DRIVER_VERSION (MAKE_VERSION(2, 5, 0))
/*! @} */
/*! @brief Retry times for waiting flag. */
#ifndef UART_RETRY_TIMES
#define UART_RETRY_TIMES 0U /* Defining to zero means to keep waiting for the flag until it is assert/deassert. */
#endif
/*! @brief Error codes for the UART driver. */
enum
{
kStatus_FLEXIO_UART_TxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 0), /*!< Transmitter is busy. */
kStatus_FLEXIO_UART_RxBusy = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 1), /*!< Receiver is busy. */
kStatus_FLEXIO_UART_TxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 2), /*!< UART transmitter is idle. */
kStatus_FLEXIO_UART_RxIdle = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 3), /*!< UART receiver is idle. */
kStatus_FLEXIO_UART_ERROR = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 4), /*!< ERROR happens on UART. */
kStatus_FLEXIO_UART_RxRingBufferOverrun =
MAKE_STATUS(kStatusGroup_FLEXIO_UART, 5), /*!< UART RX software ring buffer overrun. */
kStatus_FLEXIO_UART_RxHardwareOverrun = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 6), /*!< UART RX receiver overrun. */
kStatus_FLEXIO_UART_Timeout = MAKE_STATUS(kStatusGroup_FLEXIO_UART, 7), /*!< UART times out. */
kStatus_FLEXIO_UART_BaudrateNotSupport =
MAKE_STATUS(kStatusGroup_FLEXIO_UART, 8) /*!< Baudrate is not supported in current clock source */
};
/*! @brief FlexIO UART bit count per char. */
typedef enum _flexio_uart_bit_count_per_char
{
kFLEXIO_UART_7BitsPerChar = 7U, /*!< 7-bit data characters */
kFLEXIO_UART_8BitsPerChar = 8U, /*!< 8-bit data characters */
kFLEXIO_UART_9BitsPerChar = 9U, /*!< 9-bit data characters */
} flexio_uart_bit_count_per_char_t;
/*! @brief Define FlexIO UART interrupt mask. */
enum _flexio_uart_interrupt_enable
{
kFLEXIO_UART_TxDataRegEmptyInterruptEnable = 0x1U, /*!< Transmit buffer empty interrupt enable. */
kFLEXIO_UART_RxDataRegFullInterruptEnable = 0x2U, /*!< Receive buffer full interrupt enable. */
};
/*! @brief Define FlexIO UART status mask. */
enum _flexio_uart_status_flags
{
kFLEXIO_UART_TxDataRegEmptyFlag = 0x1U, /*!< Transmit buffer empty flag. */
kFLEXIO_UART_RxDataRegFullFlag = 0x2U, /*!< Receive buffer full flag. */
kFLEXIO_UART_RxOverRunFlag = 0x4U, /*!< Receive buffer over run flag. */
};
/*! @brief Define FlexIO UART access structure typedef. */
typedef struct _flexio_uart_type
{
FLEXIO_Type *flexioBase; /*!< FlexIO base pointer. */
uint8_t TxPinIndex; /*!< Pin select for UART_Tx. */
uint8_t RxPinIndex; /*!< Pin select for UART_Rx. */
uint8_t shifterIndex[2]; /*!< Shifter index used in FlexIO UART. */
uint8_t timerIndex[2]; /*!< Timer index used in FlexIO UART. */
} FLEXIO_UART_Type;
/*! @brief Define FlexIO UART user configuration structure. */
typedef struct _flexio_uart_config
{
bool enableUart; /*!< Enable/disable FlexIO UART TX & RX. */
bool enableInDoze; /*!< Enable/disable FlexIO operation in doze mode*/
bool enableInDebug; /*!< Enable/disable FlexIO operation in debug mode*/
bool enableFastAccess; /*!< Enable/disable fast access to FlexIO registers,
fast access requires the FlexIO clock to be at least
twice the frequency of the bus clock. */
uint32_t baudRate_Bps; /*!< Baud rate in Bps. */
flexio_uart_bit_count_per_char_t bitCountPerChar; /*!< number of bits, 7/8/9 -bit */
} flexio_uart_config_t;
/*! @brief Define FlexIO UART transfer structure. */
typedef struct _flexio_uart_transfer
{
/*
* Use separate TX and RX data pointer, because TX data is const data.
* The member data is kept for backward compatibility.
*/
union
{
uint8_t *data; /*!< The buffer of data to be transfer.*/
uint8_t *rxData; /*!< The buffer to receive data. */
const uint8_t *txData; /*!< The buffer of data to be sent. */
};
size_t dataSize; /*!< Transfer size*/
} flexio_uart_transfer_t;
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_handle flexio_uart_handle_t;
/*! @brief FlexIO UART transfer callback function. */
typedef void (*flexio_uart_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
status_t status,
void *userData);
/*! @brief Define FLEXIO UART handle structure*/
struct _flexio_uart_handle
{
const uint8_t *volatile txData; /*!< Address of remaining data to send. */
volatile size_t txDataSize; /*!< Size of the remaining data to send. */
uint8_t *volatile rxData; /*!< Address of remaining data to receive. */
volatile size_t rxDataSize; /*!< Size of the remaining data to receive. */
size_t txDataSizeAll; /*!< Total bytes to be sent. */
size_t rxDataSizeAll; /*!< Total bytes to be received. */
uint8_t *rxRingBuffer; /*!< Start address of the receiver ring buffer. */
size_t rxRingBufferSize; /*!< Size of the ring buffer. */
volatile uint16_t rxRingBufferHead; /*!< Index for the driver to store received data into ring buffer. */
volatile uint16_t rxRingBufferTail; /*!< Index for the user to get data from the ring buffer. */
flexio_uart_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the FlexIO clock, resets the FlexIO module, configures FlexIO UART
* hardware, and configures the FlexIO UART with FlexIO UART configuration.
* The configuration structure can be filled by the user or be set with
* default values by FLEXIO_UART_GetDefaultConfig().
*
* Example
@code
FLEXIO_UART_Type base = {
.flexioBase = FLEXIO,
.TxPinIndex = 0,
.RxPinIndex = 1,
.shifterIndex = {0,1},
.timerIndex = {0,1}
};
flexio_uart_config_t config = {
.enableInDoze = false,
.enableInDebug = true,
.enableFastAccess = false,
.baudRate_Bps = 115200U,
.bitCountPerChar = 8
};
FLEXIO_UART_Init(base, &config, srcClock_Hz);
@endcode
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param userConfig Pointer to the flexio_uart_config_t structure.
* @param srcClock_Hz FlexIO source clock in Hz.
* @retval kStatus_Success Configuration success.
* @retval kStatus_FLEXIO_UART_BaudrateNotSupport Baudrate is not supported for current clock source frequency.
*/
status_t FLEXIO_UART_Init(FLEXIO_UART_Type *base, const flexio_uart_config_t *userConfig, uint32_t srcClock_Hz);
/*!
* @brief Resets the FlexIO UART shifter and timer config.
*
* @note After calling this API, call the FLEXO_UART_Init to use the FlexIO UART module.
*
* @param base Pointer to FLEXIO_UART_Type structure
*/
void FLEXIO_UART_Deinit(FLEXIO_UART_Type *base);
/*!
* @brief Gets the default configuration to configure the FlexIO UART. The configuration
* can be used directly for calling the FLEXIO_UART_Init().
* Example:
@code
flexio_uart_config_t config;
FLEXIO_UART_GetDefaultConfig(&userConfig);
@endcode
* @param userConfig Pointer to the flexio_uart_config_t structure.
*/
void FLEXIO_UART_GetDefaultConfig(flexio_uart_config_t *userConfig);
/*! @} */
/*!
* @name Status
* @{
*/
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART status flags.
*/
uint32_t FLEXIO_UART_GetStatusFlags(FLEXIO_UART_Type *base);
/*!
* @brief Gets the FlexIO UART status flags.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Status flag.
* The parameter can be any combination of the following values:
* @arg kFLEXIO_UART_TxDataRegEmptyFlag
* @arg kFLEXIO_UART_RxEmptyFlag
* @arg kFLEXIO_UART_RxOverRunFlag
*/
void FLEXIO_UART_ClearStatusFlags(FLEXIO_UART_Type *base, uint32_t mask);
/*! @} */
/*!
* @name Interrupts
* @{
*/
/*!
* @brief Enables the FlexIO UART interrupt.
*
* This function enables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_EnableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/*!
* @brief Disables the FlexIO UART interrupt.
*
* This function disables the FlexIO UART interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param mask Interrupt source.
*/
void FLEXIO_UART_DisableInterrupts(FLEXIO_UART_Type *base, uint32_t mask);
/*! @} */
/*!
* @name DMA Control
* @{
*/
/*!
* @brief Gets the FlexIO UARt transmit data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART transmit data register address.
*/
static inline uint32_t FLEXIO_UART_GetTxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBuffer, base->shifterIndex[0]);
}
/*!
* @brief Gets the FlexIO UART receive data register address.
*
* This function returns the UART data register address, which is mainly used by DMA/eDMA.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @return FlexIO UART receive data register address.
*/
static inline uint32_t FLEXIO_UART_GetRxDataRegisterAddress(FLEXIO_UART_Type *base)
{
return FLEXIO_GetShifterBufferAddress(base->flexioBase, kFLEXIO_ShifterBufferByteSwapped, base->shifterIndex[1]);
}
/*!
* @brief Enables/disables the FlexIO UART transmit DMA.
* This function enables/disables the FlexIO UART Tx DMA,
* which means asserting the kFLEXIO_UART_TxDataRegEmptyFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableTxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1UL << base->shifterIndex[0], enable);
}
/*!
* @brief Enables/disables the FlexIO UART receive DMA.
* This function enables/disables the FlexIO UART Rx DMA,
* which means asserting kFLEXIO_UART_RxDataRegFullFlag does/doesn't trigger the DMA request.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param enable True to enable, false to disable.
*/
static inline void FLEXIO_UART_EnableRxDMA(FLEXIO_UART_Type *base, bool enable)
{
FLEXIO_EnableShifterStatusDMA(base->flexioBase, 1UL << base->shifterIndex[1], enable);
}
/*! @} */
/*!
* @name Bus Operations
* @{
*/
/*!
* @brief Enables/disables the FlexIO UART module operation.
*
* @param base Pointer to the FLEXIO_UART_Type.
* @param enable True to enable, false does not have any effect.
*/
static inline void FLEXIO_UART_Enable(FLEXIO_UART_Type *base, bool enable)
{
if (enable)
{
base->flexioBase->CTRL |= FLEXIO_CTRL_FLEXEN_MASK;
}
}
/*!
* @brief Writes one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is put into the
* data register. Ensure that the TxEmptyFlag is asserted before calling
* this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The data bytes to send.
*/
static inline void FLEXIO_UART_WriteByte(FLEXIO_UART_Type *base, const uint8_t *buffer)
{
base->flexioBase->SHIFTBUF[base->shifterIndex[0]] = *buffer;
}
/*!
* @brief Reads one byte of data.
*
* @note This is a non-blocking API, which returns directly after the data is read from the
* data register. Ensure that the RxFullFlag is asserted before calling this API.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param buffer The buffer to store the received bytes.
*/
static inline void FLEXIO_UART_ReadByte(FLEXIO_UART_Type *base, uint8_t *buffer)
{
*buffer = (uint8_t)(base->flexioBase->SHIFTBUFBYS[base->shifterIndex[1]]);
}
/*!
* @brief Sends a buffer of data bytes.
*
* @note This function blocks using the polling method until all bytes have been sent.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param txData The data bytes to send.
* @param txSize The number of data bytes to send.
* @retval kStatus_FLEXIO_UART_Timeout Transmission timed out and was aborted.
* @retval kStatus_Success Successfully wrote all data.
*/
status_t FLEXIO_UART_WriteBlocking(FLEXIO_UART_Type *base, const uint8_t *txData, size_t txSize);
/*!
* @brief Receives a buffer of bytes.
*
* @note This function blocks using the polling method until all bytes have been received.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param rxData The buffer to store the received bytes.
* @param rxSize The number of data bytes to be received.
* @retval kStatus_FLEXIO_UART_Timeout Transmission timed out and was aborted.
* @retval kStatus_Success Successfully received all data.
*/
status_t FLEXIO_UART_ReadBlocking(FLEXIO_UART_Type *base, uint8_t *rxData, size_t rxSize);
/*! @} */
/*!
* @name Transactional
* @{
*/
/*!
* @brief Initializes the UART handle.
*
* This function initializes the FlexIO UART handle, which can be used for other FlexIO
* UART transactional APIs. Call this API once to get the
* initialized handle.
*
* The UART driver supports the "background" receiving, which means that users can set up
* a RX ring buffer optionally. Data received is stored into the ring buffer even when
* the user doesn't call the FLEXIO_UART_TransferReceiveNonBlocking() API. If there is already data
* received in the ring buffer, users can get the received data from the ring buffer
* directly. The ring buffer is disabled if passing NULL as @p ringBuffer.
*
* @param base to FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO type/handle/ISR table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandle(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_callback_t callback,
void *userData);
/*!
* @brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received is stored into the ring buffer even when
* the user doesn't call the UART_ReceiveNonBlocking() API. If there is already data received
* in the ring buffer, users can get the received data from the ring buffer directly.
*
* @note When using the RX ring buffer, one byte is reserved for internal use. In other
* words, if @p ringBufferSize is 32, only 31 bytes are used for saving data.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param ringBuffer Start address of ring buffer for background receiving. Pass NULL to disable the ring buffer.
* @param ringBufferSize Size of the ring buffer.
*/
void FLEXIO_UART_TransferStartRingBuffer(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
uint8_t *ringBuffer,
size_t ringBufferSize);
/*!
* @brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferStopRingBuffer(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Transmits a buffer of data using the interrupt method.
*
* This function sends data using an interrupt method. This is a non-blocking function,
* which returns directly without waiting for all data to be written to the TX register. When
* all data is written to the TX register in ISR, the FlexIO UART driver calls the callback
* function and passes the @ref kStatus_FLEXIO_UART_TxIdle as status parameter.
*
* @note The kStatus_FLEXIO_UART_TxIdle is passed to the upper layer when all data is written
* to the TX register. However, it does not ensure that all data is sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer FlexIO UART transfer structure. See #flexio_uart_transfer_t.
* @retval kStatus_Success Successfully starts the data transmission.
* @retval kStatus_UART_TxBusy Previous transmission still not finished, data not written to the TX register.
*/
status_t FLEXIO_UART_TransferSendNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt-driven data sending. Get the remainBytes to find out
* how many bytes are still not sent out.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortSend(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of bytes sent.
*
* This function gets the number of bytes sent driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes sent so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief Receives a buffer of data using the interrupt method.
*
* This function receives data using the interrupt method. This is a non-blocking function,
* which returns without waiting for all data to be received.
* If the RX ring buffer is used and not empty, the data in ring buffer is copied and
* the parameter @p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in ring buffer is not enough to read, the receive
* request is saved by the UART driver. When new data arrives, the receive request
* is serviced first. When all data is received, the UART driver notifies the upper layer
* through a callback function and passes the status parameter kStatus_UART_RxIdle.
* For example, if the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer,
* the 5 bytes are copied to xfer->data. This function returns with the
* parameter @p receivedBytes set to 5. For the last 5 bytes, newly arrived data is
* saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to xfer->data. When all data is received, the upper layer is notified.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param xfer UART transfer structure. See #flexio_uart_transfer_t.
* @param receivedBytes Bytes received from the ring buffer directly.
* @retval kStatus_Success Successfully queue the transfer into the transmit queue.
* @retval kStatus_FLEXIO_UART_RxBusy Previous receive request is not finished.
*/
status_t FLEXIO_UART_TransferReceiveNonBlocking(FLEXIO_UART_Type *base,
flexio_uart_handle_t *handle,
flexio_uart_transfer_t *xfer,
size_t *receivedBytes);
/*!
* @brief Aborts the receive data which was using IRQ.
*
* This function aborts the receive data which was using IRQ.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferAbortReceive(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle);
/*!
* @brief Gets the number of bytes received.
*
* This function gets the number of bytes received driven by interrupt.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
* @param handle Pointer to the flexio_uart_handle_t structure to store the transfer state.
* @param count Number of bytes received so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCount(FLEXIO_UART_Type *base, flexio_uart_handle_t *handle, size_t *count);
/*!
* @brief FlexIO UART IRQ handler function.
*
* This function processes the FlexIO UART transmit and receives the IRQ request.
*
* @param uartType Pointer to the FLEXIO_UART_Type structure.
* @param uartHandle Pointer to the flexio_uart_handle_t structure to store the transfer state.
*/
void FLEXIO_UART_TransferHandleIRQ(void *uartType, void *uartHandle);
/*!
* @brief Flush tx/rx shifters.
*
* @param base Pointer to the FLEXIO_UART_Type structure.
*/
void FLEXIO_UART_FlushShifters(FLEXIO_UART_Type *base);
/*! @} */
#if defined(__cplusplus)
}
#endif /*_cplusplus*/
/*! @} */
#endif /*FSL_FLEXIO_UART_H_*/

View File

@ -0,0 +1,407 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_flexio_uart_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flexio_uart_edma"
#endif
/*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
typedef struct _flexio_uart_edma_private_handle
{
FLEXIO_UART_Type *base;
flexio_uart_edma_handle_t *handle;
} flexio_uart_edma_private_handle_t;
/* UART EDMA transfer handle. */
enum _flexio_uart_edma_tansfer_states
{
kFLEXIO_UART_TxIdle, /* TX idle. */
kFLEXIO_UART_TxBusy, /* TX busy. */
kFLEXIO_UART_RxIdle, /* RX idle. */
kFLEXIO_UART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Variables
******************************************************************************/
/*< @brief user configurable flexio uart handle count. */
#define FLEXIO_UART_HANDLE_COUNT 2
/*<! Private handle only used for internally. */
static flexio_uart_edma_private_handle_t s_edmaPrivateHandle[FLEXIO_UART_HANDLE_COUNT];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief FLEXIO UART EDMA send finished callback function.
*
* This function is called when FLEXIO UART EDMA send finished. It disables the UART
* TX EDMA request and sends @ref kStatus_FLEXIO_UART_TxIdle to FLEXIO UART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief FLEXIO UART EDMA receive finished callback function.
*
* This function is called when FLEXIO UART EDMA receive finished. It disables the UART
* RX EDMA request and sends @ref kStatus_FLEXIO_UART_RxIdle to UART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
void *param,
bool transferDone,
uint32_t tcds);
/*******************************************************************************
* Code
******************************************************************************/
static void FLEXIO_UART_TransferSendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
assert(uartPrivateHandle->handle != NULL);
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
if (transferDone)
{
FLEXIO_UART_TransferAbortSendEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
if (uartPrivateHandle->handle->callback != NULL)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_TxIdle, uartPrivateHandle->handle->userData);
}
}
}
static void FLEXIO_UART_TransferReceiveEDMACallback(edma_handle_t *handle,
void *param,
bool transferDone,
uint32_t tcds)
{
flexio_uart_edma_private_handle_t *uartPrivateHandle = (flexio_uart_edma_private_handle_t *)param;
assert(uartPrivateHandle->handle != NULL);
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
if (transferDone)
{
/* Disable transfer. */
FLEXIO_UART_TransferAbortReceiveEDMA(uartPrivateHandle->base, uartPrivateHandle->handle);
if (uartPrivateHandle->handle->callback != NULL)
{
uartPrivateHandle->handle->callback(uartPrivateHandle->base, uartPrivateHandle->handle,
kStatus_FLEXIO_UART_RxIdle, uartPrivateHandle->handle->userData);
}
}
}
/*!
* brief Initializes the UART handle which is used in transactional functions.
*
* param base Pointer to FLEXIO_UART_Type.
* param handle Pointer to flexio_uart_edma_handle_t structure.
* param callback The callback function.
* param userData The parameter of the callback function.
* param rxEdmaHandle User requested DMA handle for RX DMA transfer.
* param txEdmaHandle User requested DMA handle for TX DMA transfer.
* retval kStatus_Success Successfully create the handle.
* retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle)
{
assert(handle != NULL);
uint8_t index = 0U;
/* Find the an empty handle pointer to store the handle. */
for (index = 0U; index < (uint8_t)FLEXIO_UART_HANDLE_COUNT; index++)
{
if (s_edmaPrivateHandle[index].base == NULL)
{
s_edmaPrivateHandle[index].base = base;
s_edmaPrivateHandle[index].handle = handle;
break;
}
}
if (index == (uint8_t)FLEXIO_UART_HANDLE_COUNT)
{
return kStatus_OutOfRange;
}
(void)memset(handle, 0, sizeof(*handle));
handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
handle->rxEdmaHandle = rxEdmaHandle;
handle->txEdmaHandle = txEdmaHandle;
handle->callback = callback;
handle->userData = userData;
/* Configure TX. */
if (txEdmaHandle != NULL)
{
EDMA_SetCallback(handle->txEdmaHandle, FLEXIO_UART_TransferSendEDMACallback, &s_edmaPrivateHandle);
}
/* Configure RX. */
if (rxEdmaHandle != NULL)
{
EDMA_SetCallback(handle->rxEdmaHandle, FLEXIO_UART_TransferReceiveEDMACallback, &s_edmaPrivateHandle);
}
return kStatus_Success;
}
/*!
* brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent out, the send callback function is called.
*
* param base Pointer to FLEXIO_UART_Type
* param handle UART handle pointer.
* param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_FLEXIO_UART_TxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->txEdmaHandle != NULL);
edma_transfer_config_t xferConfig;
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous TX not finished. */
if ((uint8_t)kFLEXIO_UART_TxBusy == handle->txState)
{
status = kStatus_FLEXIO_UART_TxBusy;
}
else
{
handle->txState = (uint8_t)kFLEXIO_UART_TxBusy;
handle->txDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
(uint32_t *)FLEXIO_UART_GetTxDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
xfer->dataSize, kEDMA_MemoryToPeripheral);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
handle->nbytes = 1U;
/* Submit transfer. */
(void)EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->txEdmaHandle);
/* Enable UART TX EDMA. */
FLEXIO_UART_EnableTxDMA(base, true);
status = kStatus_Success;
}
return status;
}
/*!
* brief Receives data using eDMA.
*
* This function receives data using eDMA. This is a non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* param base Pointer to FLEXIO_UART_Type
* param handle Pointer to flexio_uart_edma_handle_t structure
* param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_UART_RxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer)
{
assert(handle->rxEdmaHandle != NULL);
edma_transfer_config_t xferConfig;
status_t status;
/* Return error if xfer invalid. */
if ((0U == xfer->dataSize) || (NULL == xfer->data))
{
return kStatus_InvalidArgument;
}
/* If previous RX not finished. */
if ((uint8_t)kFLEXIO_UART_RxBusy == handle->rxState)
{
status = kStatus_FLEXIO_UART_RxBusy;
}
else
{
handle->rxState = (uint8_t)kFLEXIO_UART_RxBusy;
handle->rxDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, (uint32_t *)FLEXIO_UART_GetRxDataRegisterAddress(base), sizeof(uint8_t),
xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory);
/* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */
handle->nbytes = (uint8_t)sizeof(uint8_t);
/* Submit transfer. */
(void)EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig);
EDMA_StartTransfer(handle->rxEdmaHandle);
/* Enable UART RX EDMA. */
FLEXIO_UART_EnableRxDMA(base, true);
status = kStatus_Success;
}
return status;
}
/*!
* brief Aborts the sent data which using eDMA.
*
* This function aborts sent data which using eDMA.
*
* param base Pointer to FLEXIO_UART_Type
* param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
{
assert(handle->txEdmaHandle != NULL);
/* Disable UART TX EDMA. */
FLEXIO_UART_EnableTxDMA(base, false);
/* Stop transfer. */
EDMA_StopTransfer(handle->txEdmaHandle);
handle->txState = (uint8_t)kFLEXIO_UART_TxIdle;
}
/*!
* brief Aborts the receive data which using eDMA.
*
* This function aborts the receive data which using eDMA.
*
* param base Pointer to FLEXIO_UART_Type
* param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle)
{
assert(handle->rxEdmaHandle != NULL);
/* Disable UART RX EDMA. */
FLEXIO_UART_EnableRxDMA(base, false);
/* Stop transfer. */
EDMA_StopTransfer(handle->rxEdmaHandle);
handle->rxState = (uint8_t)kFLEXIO_UART_RxIdle;
}
/*!
* brief Gets the number of bytes received.
*
* This function gets the number of bytes received.
*
* param base Pointer to FLEXIO_UART_Type
* param handle Pointer to flexio_uart_edma_handle_t structure
* param count Number of bytes received so far by the non-blocking transaction.
* retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
size_t *count)
{
assert(handle != NULL);
assert(handle->rxEdmaHandle != NULL);
assert(count != NULL);
if ((uint8_t)kFLEXIO_UART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->rxDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel);
return kStatus_Success;
}
/*!
* brief Gets the number of bytes sent out.
*
* This function gets the number of bytes sent out.
*
* param base Pointer to FLEXIO_UART_Type
* param handle Pointer to flexio_uart_edma_handle_t structure
* param count Number of bytes sent so far by the non-blocking transaction.
* retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count)
{
assert(handle != NULL);
assert(handle->txEdmaHandle != NULL);
assert(count != NULL);
if ((uint8_t)kFLEXIO_UART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll -
(uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel);
return kStatus_Success;
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FLEXIO_UART_EDMA_H_
#define FSL_FLEXIO_UART_EDMA_H_
#include "fsl_flexio_uart.h"
#include "fsl_edma.h"
/*!
* @addtogroup flexio_edma_uart
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FlexIO UART EDMA driver version. */
#define FSL_FLEXIO_UART_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 4, 1))
/*! @} */
/* Forward declaration of the handle typedef. */
typedef struct _flexio_uart_edma_handle flexio_uart_edma_handle_t;
/*! @brief UART transfer callback function. */
typedef void (*flexio_uart_edma_transfer_callback_t)(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief UART eDMA handle
*/
struct _flexio_uart_edma_handle
{
flexio_uart_edma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< UART callback function parameter.*/
size_t txDataSizeAll; /*!< Total bytes to be sent. */
size_t rxDataSizeAll; /*!< Total bytes to be received. */
edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */
edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the UART handle which is used in transactional functions.
*
* @param base Pointer to FLEXIO_UART_Type.
* @param handle Pointer to flexio_uart_edma_handle_t structure.
* @param callback The callback function.
* @param userData The parameter of the callback function.
* @param rxEdmaHandle User requested DMA handle for RX DMA transfer.
* @param txEdmaHandle User requested DMA handle for TX DMA transfer.
* @retval kStatus_Success Successfully create the handle.
* @retval kStatus_OutOfRange The FlexIO SPI eDMA type/handle table out of range.
*/
status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle);
/*!
* @brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent out, the send callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle UART handle pointer.
* @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_FLEXIO_UART_TxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Receives data using eDMA.
*
* This function receives data using eDMA. This is a non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_UART_RxBusy Previous transfer on going.
*/
status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
flexio_uart_transfer_t *xfer);
/*!
* @brief Aborts the sent data which using eDMA.
*
* This function aborts sent data which using eDMA.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle);
/*!
* @brief Aborts the receive data which using eDMA.
*
* This function aborts the receive data which using eDMA.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
*/
void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle);
/*!
* @brief Gets the number of bytes sent out.
*
* This function gets the number of bytes sent out.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param count Number of bytes sent so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count);
/*!
* @brief Gets the number of bytes received.
*
* This function gets the number of bytes received.
*
* @param base Pointer to FLEXIO_UART_Type
* @param handle Pointer to flexio_uart_edma_handle_t structure
* @param count Number of bytes received so far by the non-blocking transaction.
* @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress.
* @retval kStatus_Success Successfully return the count.
*/
status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
size_t *count);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_UART_EDMA_H_ */

View File

@ -0,0 +1,155 @@
/*
* Copyright 2021-2022 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_freqme.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpc_freqme"
#endif
#if defined(FREQME_RSTS_N)
#define FREQME_RESETS_ARRAY FREQME_RSTS_N
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
static uint32_t FREQME_GetInstance(FREQME_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Array to map freqme instance number to base address. */
static FREQME_Type *const s_freqmeBases[] = FREQME_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to FREQME clocks for each instance. */
static const clock_ip_name_t s_freqmeClocks[] = FREQME_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(FREQME_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_freqmeResets[] = FREQME_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t FREQME_GetInstance(FREQME_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0U; instance < ARRAY_SIZE(s_freqmeBases); instance++)
{
if (s_freqmeBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_freqmeBases));
return instance;
}
/*!
* brief Initialize freqme module, set operate mode, operate mode attribute and initialize measurement cycle.
*
* param base FREQME peripheral base address.
* param config The pointer to module basic configuration, please refer to freq_measure_config_t.
*/
void FREQME_Init(FREQME_Type *base, const freq_measure_config_t *config)
{
assert(config);
uint32_t tmp32 = 0UL;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable FREQME clock. */
CLOCK_EnableClock(s_freqmeClocks[FREQME_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(FREQME_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_freqmeResets[FREQME_GetInstance(base)]);
#endif
if (config->startMeasurement)
{
tmp32 |= FREQME_CTRL_W_MEASURE_IN_PROGRESS_MASK;
}
tmp32 |= FREQME_CTRL_W_CONTINUOUS_MODE_EN(config->enableContinuousMode) |
FREQME_CTRL_W_PULSE_MODE(config->operateMode);
if (config->operateMode == kFREQME_FreqMeasurementMode)
{
tmp32 |= FREQME_CTRL_W_REF_SCALE(config->operateModeAttribute.refClkScaleFactor);
}
else
{
tmp32 |= FREQME_CTRL_W_PULSE_POL(config->operateModeAttribute.pulsePolarity);
}
base->CTRL_W = tmp32;
}
/*!
* brief Get default configuration.
*
* code
* config->operateMode = kFREQME_FreqMeasurementMode;
* config->operateModeAttribute.refClkScaleFactor = 0U;
* config->enableContinuousMode = false;
* config->startMeasurement = false;
* endcode
*
* param config The pointer to module basic configuration, please refer to freq_measure_config_t.
*/
void FREQME_GetDefaultConfig(freq_measure_config_t *config)
{
assert(config);
(void)memset(config, 0, sizeof(*config));
config->operateMode = kFREQME_FreqMeasurementMode;
config->operateModeAttribute.refClkScaleFactor = 0U;
config->enableContinuousMode = false;
config->startMeasurement = false;
}
/*!
* brief Calculate the frequency of selected target clock.
*
* note The formula: Ftarget = (RESULT - 2) * Freference / 2 ^ REF_SCALE.
*
* note This function only useful when the operate mode is selected as frequency measurement mode.
*
* param base FREQME peripheral base address.
* param refClkFrequency The frequency of reference clock.
* return The frequency of target clock, if the output result is 0, please check the module's operate mode.
*/
uint32_t FREQME_CalculateTargetClkFreq(FREQME_Type *base, uint32_t refClkFrequency)
{
uint32_t measureResult = 0UL;
uint32_t targetFreq = 0UL;
uint64_t tmp64 = 0ULL;
while ((base->CTRL_R & FREQME_CTRL_R_MEASURE_IN_PROGRESS_MASK) != 0UL)
{
}
if (!FREQME_CheckOperateMode(base))
{
measureResult = base->CTRL_R & FREQME_CTRL_R_RESULT_MASK;
tmp64 = ((uint64_t)measureResult - 2ULL) * (uint64_t)refClkFrequency;
targetFreq = (uint32_t)(tmp64 / (1ULL << (uint64_t)FREQME_GetReferenceClkScaleValue(base)));
}
return targetFreq;
}

View File

@ -0,0 +1,441 @@
/*
* Copyright 2021-2022 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_FREQME_H_
#define FSL_FREQME_H_
#include "fsl_common.h"
/*!
* @addtogroup lpc_freqme
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief FREQME driver version 2.1.2. */
#define FSL_FREQME_DRIVER_VERSION (MAKE_VERSION(2, 1, 2))
/*! @} */
/*!
* @brief The enumeration of interrupt status flags.
* @anchor _freqme_interrupt_status_flags
*/
enum _freqme_interrupt_status_flags
{
kFREQME_UnderflowInterruptStatusFlag = FREQME_CTRLSTAT_LT_MIN_STAT_MASK, /*!< Indicate the measurement is
just done and the result is less
than minimun value. */
kFREQME_OverflowInterruptStatusFlag = FREQME_CTRLSTAT_GT_MAX_STAT_MASK, /*!< Indicate the measurement is
just done and the result is greater
than maximum value. */
kFREQME_ReadyInterruptStatusFlag = FREQME_CTRLSTAT_RESULT_READY_STAT_MASK, /*!< Indicate the measurement is
just done and the result is ready to
read. */
kFREQME_AllInterruptStatusFlags = FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_GT_MAX_STAT_MASK |
FREQME_CTRLSTAT_RESULT_READY_STAT_MASK, /*!< All interrupt
status flags. */
};
/*!
* @brief The enumeration of interrupts, including underflow interrupt, overflow interrupt,
* and result ready interrupt.
* @anchor _freqme_interrupt_enable
*/
enum _freqme_interrupt_enable
{
kFREQME_UnderflowInterruptEnable = FREQME_CTRL_W_LT_MIN_INT_EN_MASK, /*!< Enable interrupt when the result is
less than minimum value. */
kFREQME_OverflowInterruptEnable = FREQME_CTRL_W_GT_MAX_INT_EN_MASK, /*!< Enable interrupt when the result is
greater than maximum value. */
kFREQME_ReadyInterruptEnable = FREQME_CTRL_W_RESULT_READY_INT_EN_MASK, /*!< Enable interrupt when a
measurement completes and the result
is ready. */
};
/*!
* @brief FREQME module operate mode enumeration, including frequency measurement mode
* and pulse width measurement mode.
*/
typedef enum _freqme_operate_mode
{
kFREQME_FreqMeasurementMode = 0U, /*!< The module works in the frequency measurement mode. */
kFREOME_PulseWidthMeasurementMode, /*!< The module works in the pulse width measurement mode. */
} freqme_operate_mode_t;
/*!
* @brief The enumeration of pulse polarity.
*/
typedef enum _freqme_pulse_polarity
{
kFREQME_PulseHighPeriod = 0U, /*!< Select high period of the reference clock. */
kFREQME_PulseLowPeriod, /*!< Select low period of the reference clock. */
} freqme_pulse_polarity_t;
/*!
* @brief The union of operate mode attribute.
* @note If the operate mode is selected as frequency measurement mode the member \b refClkScaleFactor should be used,
* if the operate mode is selected as pulse width measurement mode the member \b pulsePolarity should be used.
*/
typedef union _freqme_mode_attribute
{
uint8_t refClkScaleFactor; /*!< Only useful in frequency measurement operate mode,
used to set the reference clock counter scaling factor. */
freqme_pulse_polarity_t pulsePolarity; /*!< Only Useful in pulse width measurement operate mode,
used to set period polarity. */
} freqme_mode_attribute_t;
/*!
* @brief The structure of freqme module basic configuration,
* including operate mode, operate mode attribute and so on.
*/
typedef struct _freq_measure_config
{
freqme_operate_mode_t operateMode; /*!< Select operate mode, please refer to @ref freqme_operate_mode_t. */
freqme_mode_attribute_t operateModeAttribute; /*!< Used to set the attribute of the selected operate mode, if
the operate mode is selected as @ref kFREQME_FreqMeasurementMode
set freqme_mode_attribute_t::refClkScaleFactor, if operate mode is
selected as @ref kFREOME_PulseWidthMeasurementMode, please set
freqme_mode_attribute_t::pulsePolarity. */
bool enableContinuousMode; /*!< Enable/disable continuous mode, if continuous mode is enable,
the measurement is performed continuously and the result for the
last completed measurement is available in the result register. */
bool startMeasurement;
} freq_measure_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Basic Control APIs
* @{
*/
/*!
* @brief Initialize freqme module, set operate mode, operate mode attribute and initialize measurement cycle.
*
* @param base FREQME peripheral base address.
* @param config The pointer to module basic configuration, please refer to @ref freq_measure_config_t.
*/
void FREQME_Init(FREQME_Type *base, const freq_measure_config_t *config);
/*!
* @brief Get default configuration.
*
* @code
* config->operateMode = kFREQME_FreqMeasurementMode;
* config->operateModeAttribute.refClkScaleFactor = 0U;
* config->enableContinuousMode = false;
* config->startMeasurement = false;
* @endcode
*
* @param config The pointer to module basic configuration, please refer to @ref freq_measure_config_t.
*/
void FREQME_GetDefaultConfig(freq_measure_config_t *config);
/*!
* @brief Start frequency or pulse width measurement process.
*
* @param base FREQME peripheral base address.
*/
static inline void FREQME_StartMeasurementCycle(FREQME_Type *base)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_MEASURE_IN_PROGRESS_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
tmp32 |= FREQME_CTRL_W_MEASURE_IN_PROGRESS_MASK;
base->CTRL_W = tmp32;
}
/*!
* @brief Force the termination of any measurement cycle currently in progress and resets RESULT or just reset
* RESULT if the module in idle state.
*
* @param base FREQME peripheral base address.
*/
static inline void FREQME_TerminateMeasurementCycle(FREQME_Type *base)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_MEASURE_IN_PROGRESS_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
base->CTRL_W = tmp32;
}
/*!
* @brief Enable/disable Continuous mode.
*
* @param base FREQME peripheral base address.
* @param enable Used to enable/disable continuous mode,
* - \b true Enable Continuous mode.
* - \b false Disable Continuous mode.
*/
static inline void FREQME_EnableContinuousMode(FREQME_Type *base, bool enable)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_CONTINUOUS_MODE_EN_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
if (enable)
{
tmp32 |= FREQME_CTRL_W_CONTINUOUS_MODE_EN_MASK;
}
base->CTRL_W = tmp32;
}
/*!
* @brief Check whether continuous mode is enabled.
*
* @param base FREQME peripheral base address.
* @retval True Continuous mode is enabled, the measurement is performed continuously.
* @retval False Continuous mode is disabled.
*/
static inline bool FREQME_CheckContinuousMode(FREQME_Type *base)
{
return (bool)((base->CTRLSTAT & FREQME_CTRLSTAT_CONTINUOUS_MODE_EN_MASK) != 0UL);
}
/*!
* @brief Set operate mode of freqme module.
*
* @param base FREQME peripheral base address.
* @param operateMode The operate mode to be set, please refer to @ref freqme_operate_mode_t.
*/
static inline void FREQME_SetOperateMode(FREQME_Type *base, freqme_operate_mode_t operateMode)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_PULSE_MODE_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
if (operateMode == kFREOME_PulseWidthMeasurementMode)
{
tmp32 |= FREQME_CTRL_W_PULSE_MODE_MASK;
}
base->CTRL_W = tmp32;
}
/*!
* @brief Check module's operate mode.
*
* @param base FREQME peripheral base address.
* @retval True Pulse width measurement mode.
* @retval False Frequency measurement mode.
*/
static inline bool FREQME_CheckOperateMode(FREQME_Type *base)
{
return (bool)((base->CTRLSTAT & FREQME_CTRLSTAT_PULSE_MODE_MASK) != 0UL);
}
/*!
* @brief Set the minimum expected value for the measurement result.
*
* @param base FREQME peripheral base address.
* @param minValue The minimum value to set, please note that this value is 31 bits width.
*/
static inline void FREQME_SetMinExpectedValue(FREQME_Type *base, uint32_t minValue)
{
base->MIN = minValue;
}
/*!
* @brief Set the maximum expected value for the measurement result.
*
* @param base FREQME peripheral base address.
* @param maxValue The maximum value to set, please note that this value is 31 bits width.
*/
static inline void FREQME_SetMaxExpectedValue(FREQME_Type *base, uint32_t maxValue)
{
base->MAX = maxValue;
}
/*! @} */
/*!
* @name Frequency Measurement Mode Control APIs
* @{
*/
/*!
* @brief Calculate the frequency of selected target clock
*
* @note The formula: Ftarget = (RESULT - 2) * Freference / 2 ^ REF_SCALE.
*
* @note This function only useful when the operate mode is selected as frequency measurement mode.
*
* @param base FREQME peripheral base address.
* @param refClkFrequency The frequency of reference clock.
* @return The frequency of target clock the unit is Hz, if the output result is 0, please check the module's
* operate mode.
*/
uint32_t FREQME_CalculateTargetClkFreq(FREQME_Type *base, uint32_t refClkFrequency);
/*!
* @brief Get reference clock scaling factor.
*
* @param base FREQME peripheral base address.
* @return Reference clock scaling factor, the reference count cycle is 2 ^ ref_scale.
*/
static inline uint8_t FREQME_GetReferenceClkScaleValue(FREQME_Type *base)
{
return (uint8_t)(base->CTRLSTAT & FREQME_CTRLSTAT_REF_SCALE_MASK);
}
/*! @} */
/*!
* @name Pulse Width Measurement Mode Control APIs
* @{
*/
/*!
* @brief Set pulse polarity when operate mode is selected as Pulse Width Measurement mode.
*
* @param base FREQME peripheral base address.
* @param pulsePolarity The pulse polarity to be set, please refer to @ref freqme_pulse_polarity_t.
*/
static inline void FREQME_SetPulsePolarity(FREQME_Type *base, freqme_pulse_polarity_t pulsePolarity)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_PULSE_POL_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
if (pulsePolarity != kFREQME_PulseHighPeriod)
{
tmp32 |= FREQME_CTRL_W_PULSE_POL_MASK;
}
base->CTRL_W = tmp32;
}
/*!
* @brief Check pulse polarity when the operate mode is selected as pulse width measurement mode.
*
* @param base FREQME peripheral base address.
* @retval True Low period.
* @retval False High period.
*/
static inline bool FREQME_CheckPulsePolarity(FREQME_Type *base)
{
return (bool)((base->CTRLSTAT & FREQME_CTRLSTAT_PULSE_POL_MASK) != 0UL);
}
/*!
* @brief Get measurement result, if operate mode is selected as pulse width measurement mode this function can
* be used to calculate pulse width.
*
* @note Pulse width = counter result / Frequency of target clock.
*
* @param base FREQME peripheral base address.
* @return Measurement result.
*/
static inline uint32_t FREQME_GetMeasurementResult(FREQME_Type *base)
{
return base->CTRL_R & FREQME_CTRL_R_RESULT_MASK;
}
/*! @} */
/*!
* @name Status Control APIs
* @{
*/
/*!
* @brief Get interrupt status flags, such as overflow interrupt status flag,
* underflow interrupt status flag, and so on.
*
* @param base FREQME peripheral base address.
* @return Current interrupt status flags, should be the OR'ed value of @ref _freqme_interrupt_status_flags.
*/
static inline uint32_t FREQME_GetInterruptStatusFlags(FREQME_Type *base)
{
return (base->CTRLSTAT & (uint32_t)kFREQME_AllInterruptStatusFlags);
}
/*!
* @brief Clear interrupt status flags.
*
* @param base FREQME peripheral base address.
* @param statusFlags The combination of interrupt status flags to clear,
* should be the OR'ed value of @ref _freqme_interrupt_status_flags.
*/
static inline void FREQME_ClearInterruptStatusFlags(FREQME_Type *base, uint32_t statusFlags)
{
base->CTRLSTAT |= statusFlags;
}
/*! @} */
/*!
* @name Interrupt Control APIs
* @{
*/
/*!
* @brief Enable interrupts, such as result ready interrupt, overflow interrupt and so on.
*
* @param base FREQME peripheral base address.
* @param masks The mask of interrupts to enable, should be the OR'ed value of @ref _freqme_interrupt_enable.
*/
static inline void FREQME_EnableInterrupts(FREQME_Type *base, uint32_t masks)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_LT_MIN_INT_EN_MASK |
FREQME_CTRLSTAT_GT_MAX_STAT_MASK | FREQME_CTRLSTAT_GT_MAX_INT_EN_MASK |
FREQME_CTRLSTAT_RESULT_READY_INT_EN_MASK | FREQME_CTRLSTAT_RESULT_READY_STAT_MASK);
tmp32 |= masks;
base->CTRL_W = tmp32;
}
/*!
* @brief Disable interrupts, such as result ready interrupt, overflow interrupt and so on.
*
* @param base FREQME peripheral base address.
* @param masks The mask of interrupts to disable, should be the OR'ed value of @ref _freqme_interrupt_enable.
*/
static inline void FREQME_DisableInterrupts(FREQME_Type *base, uint32_t masks)
{
uint32_t tmp32;
tmp32 = base->CTRLSTAT;
tmp32 &= ~(FREQME_CTRLSTAT_LT_MIN_STAT_MASK | FREQME_CTRLSTAT_GT_MAX_STAT_MASK |
FREQME_CTRLSTAT_RESULT_READY_STAT_MASK | masks);
base->CTRL_W = tmp32;
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* FSL_FREQME_H_ */

View File

@ -0,0 +1,403 @@
/*
* Copyright 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#include "fsl_glikey.h"
/*******************************************************************************
* Definitions
*******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.glikey"
#endif
#define GLIKEY_SFR_LOCK 0x05u
#define GLIKEY_SFR_UNLOCK 0x0Au
/* Define to select between write to CTRL0_WR_0 or CTRL1_WR_1 */
#define WR_EN0 (0x0Fu)
#define WR_EN1 (0xF0u)
#define WR_EN0_VALUE_SHIFT (0u)
#define WR_EN1_VALUE_SHIFT (16u)
#define CTRL_SEL_CODEWORD_SHIFT (24u)
#define WR_0_INIT (0x2u)
#define WR_1_INIT (0x0u)
/*******************************************************************************
* Prototypes
******************************************************************************/
static inline void Glikey_Internal_Set_WR_0(GLIKEY_Type *base, uint32_t value);
static inline void Glikey_Internal_Set_WR_1(GLIKEY_Type *base, uint32_t value);
/*******************************************************************************
* Code
******************************************************************************/
/*!
* Weak implementation of GLIKEY IRQ, should be re-defined by user when using GLIKEY IRQ
__WEAK void GLIKEY0_DriverIRQHandler(void)
{
GLIKEY generates IRQ until corresponding bit in STATUS is cleared by calling
GLIKEY_ClearStatusFlags();
}
*/
static inline void Glikey_Internal_Set_WR_0(GLIKEY_Type *base, uint32_t value)
{
uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
/* Clear WR_0 */
ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WR_EN_0_MASK);
/* Assign value */
((GLIKEY_Type *)base)->CTRL_0 = ctrl0 | GLIKEY_CTRL_0_WR_EN_0(value);
}
static inline void Glikey_Internal_Set_WR_1(GLIKEY_Type *base, uint32_t value)
{
uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
/* Clear WR_1 */
ctrl1 = ctrl1 & (~GLIKEY_CTRL_1_WR_EN_1_MASK);
/* Assign value */
((GLIKEY_Type *)base)->CTRL_1 = ctrl1 | GLIKEY_CTRL_1_WR_EN_1(value);
}
uint32_t GLIKEY_GetStatus(GLIKEY_Type *base)
{
return ((GLIKEY_Type *)base)->STATUS;
}
status_t GLIKEY_IsLocked(GLIKEY_Type *base)
{
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked == retCode)
{
return kStatus_GLIKEY_NotLocked;
}
else
{
return kStatus_GLIKEY_Locked;
}
}
status_t GLIKEY_CheckLock(GLIKEY_Type *base)
{
uint32_t sfrLock = (((GLIKEY_Type *)base)->CTRL_1 & GLIKEY_CTRL_1_SFR_LOCK_MASK) >> GLIKEY_CTRL_1_SFR_LOCK_SHIFT;
if (GLIKEY_SFR_UNLOCK != sfrLock) /* Locked */
{
return kStatus_GLIKEY_LockedError;
}
return kStatus_GLIKEY_NotLocked;
}
#if defined(GLIKEY_VERSION_FSM_CONFIG)
status_t GLIKEY_GetVersion(GLIKEY_Type *base, uint32_t *result)
{
*result = ((GLIKEY_Type *)base)->VERSION;
return kStatus_Success;
}
#endif
status_t GLIKEY_SyncReset(GLIKEY_Type *base)
{
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Set CTRL_0.SFT_RST = 1 */
((GLIKEY_Type *)base)->CTRL_0 |= GLIKEY_CTRL_0_SFT_RST_MASK;
return kStatus_Success;
}
status_t GLIKEY_SetIntEnable(GLIKEY_Type *base, uint32_t value)
{
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
((GLIKEY_Type *)base)->INTR_CTRL = GLIKEY_INTR_CTRL_INT_EN(value);
return kStatus_Success;
}
status_t GLIKEY_GetIntEnable(GLIKEY_Type *base, uint32_t *value)
{
*value = ((GLIKEY_Type *)base)->INTR_CTRL & GLIKEY_INTR_CTRL_INT_EN_MASK;
return kStatus_Success;
}
status_t GLIKEY_ClearIntStatus(GLIKEY_Type *base)
{
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
((GLIKEY_Type *)base)->INTR_CTRL |= GLIKEY_INTR_CTRL_INT_CLR_MASK;
return kStatus_Success;
}
status_t GLIKEY_SetIntStatus(GLIKEY_Type *base)
{
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
((GLIKEY_Type *)base)->INTR_CTRL |= GLIKEY_INTR_CTRL_INT_SET_MASK;
return kStatus_Success;
}
status_t GLIKEY_Lock(GLIKEY_Type *base)
{
/* Check if SFR_LOCK is locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode) /* Glikey is not locked -> lock */
{
uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
/* Clear SFR_LOCK */
ctrl1 = ctrl1 & (~GLIKEY_CTRL_1_SFR_LOCK_MASK);
/* Lock Gliekey */
((GLIKEY_Type *)base)->CTRL_1 = ctrl1 | GLIKEY_CTRL_1_SFR_LOCK(GLIKEY_SFR_LOCK);
}
return kStatus_Success;
}
status_t GLIKEY_IsIndexLocked(GLIKEY_Type *base, uint32_t index)
{
/* Set CTRL_1.READ_INDEX = index */
uint32_t ctr1Val = ((GLIKEY_Type *)base)->CTRL_1;
/* Clear READ_INDEX */
ctr1Val = ctr1Val & (~GLIKEY_CTRL_1_READ_INDEX_MASK);
/* Set index value */
((GLIKEY_Type *)base)->CTRL_1 = ctr1Val | GLIKEY_CTRL_1_READ_INDEX(index);
/* Check ERROR_STATUS */
if (0u != (GLIKEY_GetStatus(base) & GLIKEY_STATUS_ERROR_STATUS_MASK))
{
return kStatus_Fail;
}
/* Check if STATUS.LOCK_STATUS is 0 */
if (0u == (GLIKEY_GetStatus(base) & GLIKEY_STATUS_LOCK_STATUS_MASK))
{
return kStatus_GLIKEY_NotLocked;
}
else
{
return kStatus_GLIKEY_Locked;
}
}
status_t GLIKEY_LockIndex(GLIKEY_Type *base)
{
/* Check if Glikey SFR locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Check if FSM is in WR_EN state */
uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
if (GLIKEY_FSM_WR_EN == state)
{
/* Set WR_EN0 = b11 */
((GLIKEY_Type *)base)->CTRL_0 |= GLIKEY_CTRL_0_WR_EN_0(0x3u);
return kStatus_GLIKEY_Locked;
}
else
{
return kStatus_GLIKEY_DisabledError;
}
}
status_t GLIKEY_StartEnable(GLIKEY_Type *base, uint32_t index)
{
/* Check if Glikey SFR locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Check if index is locked */
retCode = GLIKEY_IsIndexLocked(base, index);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* CTRL0 */
uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
/* Clear old index */
ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WRITE_INDEX_MASK);
/* Clear old CTRL0.WR_EN_0 */
ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WR_EN_0_MASK);
/* Set new index */
ctrl0 |= GLIKEY_CTRL_0_WRITE_INDEX(index);
/* Start the enable process by writting 0x01 to CTRL0.WR_EN_0 */
ctrl0 = ctrl0 | ((uint32_t)0x01u << GLIKEY_CTRL_0_WR_EN_0_SHIFT);
/* Write to CTRL0 (new index and WR_EN_0 = 0x01) */
((GLIKEY_Type *)base)->CTRL_0 = ctrl0;
/* CTRL1 */
uint32_t ctrl1 = ((GLIKEY_Type *)base)->CTRL_1;
/* Clear CTRL1.WR_EN_1 */
ctrl1 &= ~GLIKEY_CTRL_1_WR_EN_1_MASK;
((GLIKEY_Type*)base)->CTRL_1 = ctrl1;
return kStatus_Success;
}
status_t GLIKEY_ContinueEnable(GLIKEY_Type *base, uint32_t codeword)
{
/* Check if Glikey SFR locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Set correctly we_en0 and wr_en1 according to codeword */
/* Select between CTRL0/CTRL1 */
if (WR_EN1 == (codeword >> CTRL_SEL_CODEWORD_SHIFT))
{
Glikey_Internal_Set_WR_1(base, codeword >> WR_EN1_VALUE_SHIFT);
}
else if (WR_EN0 == (codeword >> CTRL_SEL_CODEWORD_SHIFT))
{
Glikey_Internal_Set_WR_0(base, codeword >> WR_EN0_VALUE_SHIFT);
}
else
{
return kStatus_Fail;
}
if (0u != (GLIKEY_GetStatus(base) & GLIKEY_STATUS_ERROR_STATUS_MASK))
{
return kStatus_GLIKEY_DisabledError;
}
/* Validate codeword - check if XXYZ^UUVW == 0xFFFF */
if (0xFFFFu != (((codeword) ^ (codeword >> 16u)) & 0xFFFFu))
{
return kStatus_Fail;
}
return kStatus_Success;
}
status_t GLIKEY_EndOperation(GLIKEY_Type *base)
{
/* Check if Glikey SFR locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
// check state
uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
switch (state)
{
case GLIKEY_FSM_LOCKED:
{
/* If locked -> try to go to init with wr_en0 = WR_0_INIT (0x02); wr_en1 = WR_1_INIT (0x00) */
Glikey_Internal_Set_WR_0(base, WR_0_INIT);
Glikey_Internal_Set_WR_1(base, WR_1_INIT);
/* if still locked return locked - need to change index */
if (GLIKEY_FSM_LOCKED ==
(GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT)
{
return kStatus_GLIKEY_Locked;
}
retCode = kStatus_Success;
break;
}
case GLIKEY_FSM_SSR_RESET:
case GLIKEY_FSM_WR_EN:
{
/* If FSM in RESET -> wr_en0 = WR_0_INIT; wr_en1 = WR_1_INIT */
/* If FSM in WR_EN -> wr_en0 = WR_0_INIT; wr_en1 = WR_1_INIT */
Glikey_Internal_Set_WR_0(base, WR_0_INIT);
Glikey_Internal_Set_WR_1(base, WR_1_INIT);
retCode = kStatus_Success;
break;
}
default:
/* Disabled error */
retCode = kStatus_GLIKEY_DisabledError;
break;
}
return retCode;
}
status_t GLIKEY_ResetIndex(GLIKEY_Type *base, uint32_t index)
{
/* Check if Glikey SFR locked */
status_t retCode = GLIKEY_CheckLock(base);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Check if index is locked */
retCode = GLIKEY_IsIndexLocked(base, index);
if (kStatus_GLIKEY_NotLocked != retCode)
{
return retCode;
}
/* Check if FSM is in INIT state */
uint32_t state = (GLIKEY_GetStatus(base) & GLIKEY_STATUS_FSM_STATE_MASK) >> GLIKEY_STATUS_FSM_STATE_SHIFT;
if (GLIKEY_FSM_INIT == state)
{
/* CTRL0.WRITE_INDEX = index */
uint32_t ctrl0 = ((GLIKEY_Type *)base)->CTRL_0;
/* Clear index */
ctrl0 = ctrl0 & (~GLIKEY_CTRL_0_WRITE_INDEX_MASK);
/* Write new value */
((GLIKEY_Type *)base)->CTRL_0 = ctrl0 | GLIKEY_CTRL_0_WRITE_INDEX(index);
return kStatus_Success;
}
else
{
return kStatus_GLIKEY_DisabledError;
}
}

View File

@ -0,0 +1,311 @@
/*
* Copyright 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_GLIKEY_H_
#define _FSL_GLIKEY_H_
#include "fsl_common.h"
/*!
* @addtogroup GLIKEY
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief Defines GLIKEY driver version 2.0.0.
*
* Change log:
* - Version 2.0.0
* - Initial version
*/
#define FSL_GLIKEY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
enum
{
kStatus_GLIKEY_LockedError =
MAKE_STATUS(kStatusGroup_GLIKEY, 0x1u), /*!< GLIKEY status for locked SFR registers (unexpected) . */
kStatus_GLIKEY_NotLocked = MAKE_STATUS(kStatusGroup_GLIKEY, 0x2u), /*!< GLIKEY status for unlocked SFR registers. */
kStatus_GLIKEY_Locked = MAKE_STATUS(kStatusGroup_GLIKEY, 0x3u), /*!< GLIKEY status for locked SFR registers. */
kStatus_GLIKEY_DisabledError = MAKE_STATUS(kStatusGroup_GLIKEY, 0x4u), /*!< GLIKEY status for disabled error. */
};
/* [Design]
Value: XX YZ UU VW
- XX: F0: write to WR_EN1, 0F: do not write to WR_EN1
- UU: F0: write to WR_EN0, 0F: do not write to WR_EN0
- Y: equal to <step> ^ W
- Z: value to write to WR_EN1 or equal to ~W
- V: equal to <step> ^ Z
- W: value to write to WR_EN0 or equal to ~Z
Invariant: XXYZ ^ UUVW == 0xFFFF
*/
#define GLIKEY_CODEWORD_STEP1 ((uint32_t)0xF0C10F3EU) /*< Codeword for transition from STEP1 --> STEP2 */
#define GLIKEY_CODEWORD_STEP2 ((uint32_t)0x0F1DF0E2U) /*< Codeword for transition from STEP2 --> STEP3 */
#define GLIKEY_CODEWORD_STEP3 ((uint32_t)0xF0B00F4FU) /*< Codeword for transition from STEP3 --> STEP4 */
#define GLIKEY_CODEWORD_STEP4 ((uint32_t)0x0F4EF0B1U) /*< Codeword for transition from STEP4 --> STEP5 */
#define GLIKEY_CODEWORD_STEP5 ((uint32_t)0xF0810F7EU) /*< Codeword for transition from STEP5 --> STEP6 */
#define GLIKEY_CODEWORD_STEP6 ((uint32_t)0x0F5DF0A2U) /*< Codeword for transition from STEP6 --> STEP7 */
#define GLIKEY_CODEWORD_STEP7 ((uint32_t)0xF0700F8FU) /*< Codeword for transition from STEP7 --> STEP8 */
#define GLIKEY_CODEWORD_STEP_EN ((uint32_t)0x0FFFF000U) /*< Codeword for transition from STEP 4/8 --> WR_EN */
#define GLIKEY_FSM_WR_DIS 0x0Bu
#define GLIKEY_FSM_INIT 0x16u
#define GLIKEY_FSM_STEP1 0x2Cu
#define GLIKEY_FSM_STEP2 0x58u
#define GLIKEY_FSM_STEP3 0xB0u
#define GLIKEY_FSM_STEP4 0x160u
#define GLIKEY_FSM_LOCKED 0xC01u
#define GLIKEY_FSM_WR_EN 0x1802u
#define GLIKEY_FSM_SSR_RESET 0x1005u
/*@}*/
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name GLIKEY Functional Operation
* @{
*/
/*!
* @brief Retreives the current status of Glikey.
*
* @param[in] base The base address of the Glikey instance
*
* @return Glikey status information
*/
uint32_t GLIKEY_GetStatus(GLIKEY_Type *base);
/*!
* @brief Get if Glikey is locked
*
* This operation returns the locking status of Glikey.
*
* @return Status
* @retval kStatus_GLIKEY_Locked if locked
* @retval kStatus_GLIKEY_NotLocked if unlocked
*/
status_t GLIKEY_IsLocked(GLIKEY_Type *base);
/*!
* @brief Check if Glikey is locked
*
* This operation returns the locking status of Glikey.
*
* @return Status kStatus_Success if success
* @retval kStatus_GLIKEY_LockedError if locked
* @retval kStatus_GLIKEY_NotLocked if unlocked
*/
status_t GLIKEY_CheckLock(GLIKEY_Type *base);
/*!
* @brief Retreives the version and configuration of Glikey.
*
*
* @param[in] base The base address of the Glikey instance
* @param[out] result Pointer which will be filled with the Glikey hardware version
*
* @return Status kStatus_Success if success
*/
status_t GLIKEY_GetVersion(GLIKEY_Type *base, uint32_t *result);
/*!
* @brief Perform a synchronous reset of Glikey.
*
* This function performs a synchrounous reset of the Glikey. This results in:
* - Glikey will return to the INIT state, unless it is in the LOCK state
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError
*/
status_t GLIKEY_SyncReset(GLIKEY_Type *base);
/*!
* @brief Set interrupt enable flag of Glikey.
*
* @param[in] base The base address of the Glikey instance
* @param[in] value Value to set the interrupt enable flag to, see #[TODO: add reference to constants]
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError
*/
status_t GLIKEY_SetIntEnable(GLIKEY_Type *base, uint32_t value);
/*!
* @brief Get interrupt enable flag of Glikey.
*
* @param[in] base The base address of the Glikey instance
* @param[out] value Pointer which will be filled with the interrupt enable status, see #[TODO: add reference to
* constants]
*
* @return Status kStatus_Success if success
*/
status_t GLIKEY_GetIntEnable(GLIKEY_Type *base, uint32_t *value);
/*!
* @brief Clear the interrupt status flag of Glikey.
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError
*/
status_t GLIKEY_ClearIntStatus(GLIKEY_Type *base);
/*!
* @brief Set the interrupt status flag of Glikey.
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError
*/
status_t GLIKEY_SetIntStatus(GLIKEY_Type *base);
/*!
* @brief Lock Glikey SFR (Special Function Registers) interface
*
* This operation locks the Glikey SFR interface if it is not locked yet.
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success
*/
status_t GLIKEY_Lock(GLIKEY_Type *base);
/*!
* @brief Lock Glikey index
*
* This operation is used to lock a Glikey index. It can only be executed from the WR_EN state,
* executing it from any other state will result in Glikey entering WR_DIS state. When this happens
* Glikey requires a reset (synchrous or asynchronous) to go back to INIT state.
* If the Glikey SFR lock is active this operation will return an error.
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError, kStatus_GLIKEY_DisabledError
*/
status_t GLIKEY_LockIndex(GLIKEY_Type *base);
/*!
* @brief Check if Glikey index is locked
*
* This operation returns the locking status of Glikey index.
*
* @param[in] base The base address of the Glikey instance
* @param[in] index The index of the Glikey instance
*
* @return kStatus_GLIKEY_Locked if locked, kStatus_GLIKEY_NotLocked if unlocked
* Possible errors: kStatus_Fail
*/
status_t GLIKEY_IsIndexLocked(GLIKEY_Type *base, uint32_t index);
/**
* @brief Start Glikey enable
*
* This operation is used to set a new index and start a the sequence to enable it. It needs to be
* started from the INIT state. If the new index is already locked Glikey will go to LOCKED state,
* otherwise it will go to STEP1 state.
* If this operation is used when Glikey is in any state other than INIT Glikey will go to WR_DIS
* state. It can only recover from this state through a reset (synchrounous or asyncrhonous).
* If the Glikey SFR lock is active this operation will return an error.
*
* @param[in] base The base address of the Glikey instance
* @param[in] index The index of the Glikey instance
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError, kStatus_Fail
*/
status_t GLIKEY_StartEnable(GLIKEY_Type *base, uint32_t index);
/**
* @brief Continue Glikey enable
*
* This operation is used to progress through the different states of the state machine, starting
* from STEP1 until the state WR_EN is reached. Each next state of the state machine can only be
* reached by providing the right codeword to this function. If anything goes wrong the state machine
* will go to WR_DIS state and can only recover from it through a reset (synchrous or asynchronous).
* If the Glikey SFR lock is active this operation will return an error.
*
* @param[in] base The base address of the Glikey instance
* @param[in] codeword Encoded word for progressing to next FSM state (see GLIKEY_CODEWORD_STEPx/EN)
*
* @return Status kStatus_Success if success
* Possible errors: kStatus_GLIKEY_LockedError, kStatus_Fail, kStatus_GLIKEY_DisabledError
*/
/* [Design]
- Check if Glikey is locked
if ( GLIKEY_LOCKED == GLIKEY_GET_SFR_LOCK(base) ) return NXPCLGLIKEY_STATUS_LOCKED_ERROR
- Decode the codeword and write to Glikey CTRL[]
Write GLIKEY_CTRL(base, EnableSelect, EnableValue)
- Check if an error occured
- the only possible error here is FSM error which results in a transition to WR_DIS state
- alternatively this can be confirmed by checking FSM state value
- Only now we will check if the codeword itself is valid
- this is done in this order to assure that the state machine reaches WR_DIS state when needed
- check if XXYZ^UUVW == 0xFFFF and return kStatus_Fail when it fails
- Return kStatus_Success
*/
status_t GLIKEY_ContinueEnable(GLIKEY_Type *base, uint32_t codeword);
/**
* @brief End Glikey operation
*
* This operation is used to end a Glikey operation. It can only be executed from the WR_EN, LOCKED
* and RESET states. Executing it from any other state will result in Glikey entering WR_DIS state.
* When this happens Glikey requires a reset (synchrous or asynchronous) to go back to INIT state.
* After this operation Glikey will go to INIT state or stay in LOCKED state when the index was locked.
* If the Glikey SFR lock is active this operation will return an error.
*
* @return A code-flow protected error code (see @ref nxpCsslFlowProtection)
*
* @param[in] base The base address of the Glikey instance
*
* @return Status kStatus_Success if success, kStatus_GLIKEY_Locked if index is still locked
* Possible errors: kStatus_GLIKEY_LockedError, kStatus_GLIKEY_DisabledError
*/
status_t GLIKEY_EndOperation(GLIKEY_Type *base);
/**
* @brief Reset Glikey index
*
* This operation is used to reset a Glikey index. It can only be executed from the INIT state,
* executing it from any other state will result in Glikey entering WR_DIS state. When this happens
* Glikey requires a reset (synchrous or asynchronous) to go back to INIT state.
* If the Glikey SFR lock is active or the index is locked this operation will return an error.
*
* @return A code-flow protected error code (see @ref nxpCsslFlowProtection)
*
* @return Status kStatus_Success if success, kStatus_GLIKEY_Locked if index is still locked
* Possible errors: kStatus_GLIKEY_LockedError, kStatus_GLIKEY_DisabledError
*/
status_t GLIKEY_ResetIndex(GLIKEY_Type *base, uint32_t index);
/*! @}*/
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/ /* end of group glikey */
#endif /* _FSL_GLIKEY_H_ */

View File

@ -0,0 +1,444 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2019, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_gpio.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.gpio"
#endif
#if defined(GPIO_RSTS)
#define GPIO_RESETS_ARRAY GPIO_RSTS
#endif
/*******************************************************************************
* Variables
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
static PORT_Type *const s_portBases[] = PORT_BASE_PTRS;
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
#else
#if defined(GPIO_RESETS_ARRAY)
static GPIO_Type *const s_gpioBases[] = GPIO_BASE_PTRS;
#endif
#endif
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
#if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Array to map FGPIO instance number to clock name. */
static const clock_ip_name_t s_fgpioClockName[] = FGPIO_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
#if defined(GPIO_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_gpioResets[] = GPIO_RESETS_ARRAY;
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* @brief Gets the GPIO instance according to the GPIO base
*
* @param base GPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval GPIO instance
*/
static uint32_t GPIO_GetInstance(GPIO_Type *base);
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT) || defined(GPIO_RESETS_ARRAY)
static uint32_t GPIO_GetInstance(GPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_gpioBases); instance++)
{
if (s_gpioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_gpioBases));
return instance;
}
#endif
/*!
* brief Initializes a GPIO pin used by the board.
*
* To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
* Then, call the GPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration.
* code
* Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* endcode
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* param pin GPIO port pin number
* param config GPIO pin configuration pointer
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(NULL != config);
#if defined(GPIO_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_gpioResets[GPIO_GetInstance(base)]);
#endif
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= GPIO_FIT_REG(~(1UL << pin));
}
else
{
GPIO_PinWrite(base, pin, config->outputLogic);
base->PDDR |= GPIO_FIT_REG((1UL << pin));
}
}
#if defined(FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER
void GPIO_GetVersionInfo(GPIO_Type *base, gpio_version_info_t *info)
{
info->feature = (uint16_t)base->VERID;
info->minor = (uint8_t)(base->VERID >> GPIO_VERID_MINOR_SHIFT);
info->major = (uint8_t)(base->VERID >> GPIO_VERID_MAJOR_SHIFT);
}
#endif /* FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* brief Reads the GPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* retval The current GPIO port interrupt status flag, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t GPIO_PortGetInterruptFlags(GPIO_Type *base)
{
uint8_t instance;
PORT_Type *portBase;
instance = (uint8_t)GPIO_GetInstance(base);
portBase = s_portBases[instance];
return portBase->ISFR;
}
#else
/*!
* brief Read the GPIO interrupt status flags.
*
* param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
* return The current GPIO's interrupt status flag.
* '1' means the related pin's flag is set, '0' means the related pin's flag not set.
* For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
*/
uint32_t GPIO_GpioGetInterruptFlags(GPIO_Type *base)
{
return base->ISFR[0];
}
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*!
* brief Read the GPIO interrupt status flags based on selected interrupt channel(IRQS).
* param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
* param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
*
* return The current GPIO's interrupt status flag based on the selected interrupt channel.
* '1' means the related pin's flag is set, '0' means the related pin's flag not set.
* For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
*/
uint32_t GPIO_GpioGetInterruptChannelFlags(GPIO_Type *base, uint32_t channel)
{
assert(channel < 2U);
return base->ISFR[channel];
}
#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT */
/*!
* brief Read individual pin's interrupt status flag.
*
* param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on)
* param pin GPIO specific pin number.
* return The current selected pin's interrupt status flag.
*/
uint8_t GPIO_PinGetInterruptFlag(GPIO_Type *base, uint32_t pin)
{
return (uint8_t)((base->ICR[pin] & GPIO_ICR_ISF_MASK) >> GPIO_ICR_ISF_SHIFT);
}
#endif /* FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* brief Clears multiple GPIO pin interrupt status flags.
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* param mask GPIO pin number macro
*/
void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t mask)
{
uint8_t instance;
PORT_Type *portBase;
instance = (uint8_t)GPIO_GetInstance(base);
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#else
/*!
* brief Clears GPIO pin interrupt status flags.
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* param mask GPIO pin number macro
*/
void GPIO_GpioClearInterruptFlags(GPIO_Type *base, uint32_t mask)
{
base->ISFR[0] = GPIO_FIT_REG(mask);
}
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*!
* brief Clears GPIO pin interrupt status flags based on selected interrupt channel(IRQS).
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* param mask GPIO pin number macro
* param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
*/
void GPIO_GpioClearInterruptChannelFlags(GPIO_Type *base, uint32_t mask, uint32_t channel)
{
assert(channel < 2U);
base->ISFR[channel] = GPIO_FIT_REG(mask);
}
#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT */
/*!
* brief Clear GPIO individual pin's interrupt status flag.
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on).
* param pin GPIO specific pin number.
*/
void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t pin)
{
base->ICR[pin] |= GPIO_FIT_REG(GPIO_ICR_ISF(1U));
}
#endif /* FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*!
* brief The GPIO module supports a device-specific number of data ports, organized as 32-bit
* words/8-bit Bytes. Each 32-bit/8-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. If the GPIO module's GACR register
* organized as 32-bit words, the attribute controls for the 4 data bytes in the GACR follow a standard little
* endian data convention.
*
* param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* param attribute GPIO checker attribute
*/
void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute)
{
#if defined(FSL_FEATURE_GPIO_REGISTERS_WIDTH) && (FSL_FEATURE_GPIO_REGISTERS_WIDTH == 8U)
base->GACR = ((uint8_t)attribute << GPIO_GACR_ACB_SHIFT);
#else
base->GACR = ((uint32_t)attribute << GPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB1_SHIFT) |
((uint32_t)attribute << GPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << GPIO_GACR_ACB3_SHIFT);
#endif /* FSL_FEATURE_GPIO_REGISTERS_WIDTH */
}
#endif
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*******************************************************************************
* Variables
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
static FGPIO_Type *const s_fgpioBases[] = FGPIO_BASE_PTRS;
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* @brief Gets the FGPIO instance according to the GPIO base
*
* @param base FGPIO peripheral base pointer(PTA, PTB, PTC, etc.)
* @retval FGPIO instance
*/
static uint32_t FGPIO_GetInstance(FGPIO_Type *base);
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
static uint32_t FGPIO_GetInstance(FGPIO_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_fgpioBases); instance++)
{
if (s_fgpioBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_fgpioBases));
return instance;
}
#endif
#if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
/*!
* brief Initializes the FGPIO peripheral.
*
* This function ungates the FGPIO clock.
*
* param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
*/
void FGPIO_PortInit(FGPIO_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Ungate FGPIO periphral clock */
CLOCK_EnableClock(s_fgpioClockName[FGPIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
#endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
/*!
* brief Initializes a FGPIO pin used by the board.
*
* To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
* Then, call the FGPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration:
* code
* Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* endcode
*
* param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* param pin FGPIO port pin number
* param config FGPIO pin configuration pointer
*/
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config)
{
assert(NULL != config);
if (config->pinDirection == kGPIO_DigitalInput)
{
base->PDDR &= ~(1UL << pin);
}
else
{
FGPIO_PinWrite(base, pin, config->outputLogic);
base->PDDR |= (1UL << pin);
}
}
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* brief Reads the FGPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level-sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t FGPIO_PortGetInterruptFlags(FGPIO_Type *base)
{
uint8_t instance;
instance = (uint8_t)FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
return portBase->ISFR;
}
/*!
* brief Clears the multiple FGPIO pin interrupt status flag.
*
* param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* param mask FGPIO pin number macro
*/
void FGPIO_PortClearInterruptFlags(FGPIO_Type *base, uint32_t mask)
{
uint8_t instance;
instance = (uint8_t)FGPIO_GetInstance(base);
PORT_Type *portBase;
portBase = s_portBases[instance];
portBase->ISFR = mask;
}
#endif
#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER
/*!
* brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit
* words. Each 32-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data
* bytes in the GACR follow a standard little endian
* data convention.
*
* param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* param attribute FGPIO checker attribute
*/
void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute)
{
base->GACR = ((uint32_t)attribute << FGPIO_GACR_ACB0_SHIFT) | ((uint32_t)attribute << FGPIO_GACR_ACB1_SHIFT) |
((uint32_t)attribute << FGPIO_GACR_ACB2_SHIFT) | ((uint32_t)attribute << FGPIO_GACR_ACB3_SHIFT);
}
#endif
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */

View File

@ -0,0 +1,799 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_GPIO_H_
#define FSL_GPIO_H_
#include "fsl_common.h"
/*!
* @addtogroup gpio
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief GPIO driver version. */
#define FSL_GPIO_DRIVER_VERSION (MAKE_VERSION(2, 7, 3))
/*! @} */
#if defined(FSL_FEATURE_GPIO_REGISTERS_WIDTH) && (FSL_FEATURE_GPIO_REGISTERS_WIDTH == 8U)
#define GPIO_FIT_REG(value) \
((uint8_t)(value)) /*!< For some platforms with 8-bit register width, cast the type to uint8_t */
#else
#define GPIO_FIT_REG(value) ((uint32_t)(value))
#endif /*FSL_FEATURE_GPIO_REGISTERS_WIDTH*/
/*! @brief GPIO direction definition */
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output*/
} gpio_pin_direction_t;
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*! @brief GPIO checker attribute */
typedef enum _gpio_checker_attribute
{
kGPIO_UsernonsecureRWUsersecureRWPrivilegedsecureRW =
0x00U, /*!< User nonsecure:Read+Write; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureRUsersecureRWPrivilegedsecureRW =
0x01U, /*!< User nonsecure:Read; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureRWPrivilegedsecureRW =
0x02U, /*!< User nonsecure:None; User Secure:Read+Write; Privileged Secure:Read+Write */
kGPIO_UsernonsecureRUsersecureRPrivilegedsecureRW =
0x03U, /*!< User nonsecure:Read; User Secure:Read; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureRPrivilegedsecureRW =
0x04U, /*!< User nonsecure:None; User Secure:Read; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureRW =
0x05U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read+Write */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureR =
0x06U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:Read */
kGPIO_UsernonsecureNUsersecureNPrivilegedsecureN =
0x07U, /*!< User nonsecure:None; User Secure:None; Privileged Secure:None */
kGPIO_IgnoreAttributeCheck = 0x80U, /*!< Ignores the attribute check */
} gpio_checker_attribute_t;
#endif
/*!
* @brief The GPIO pin configuration structure.
*
* Each pin can only be configured as either an output pin or an input pin at a time.
* If configured as an input pin, leave the outputConfig unused.
* Note that in some use cases, the corresponding port property should be configured in advance
* with the PORT_SetPinConfig().
*/
typedef struct _gpio_pin_config
{
gpio_pin_direction_t pinDirection; /*!< GPIO direction, input or output */
/* Output configurations; ignore if configured as an input pin */
uint8_t outputLogic; /*!< Set a default output logic, which has no use in input */
} gpio_pin_config_t;
#if (defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) || \
!(defined(FSL_FEATURE_SOC_PORT_COUNT))
/*! @brief Configures the interrupt generation condition. */
typedef enum _gpio_interrupt_config
{
kGPIO_InterruptStatusFlagDisabled = 0x0U, /*!< Interrupt status flag is disabled. */
kGPIO_DMARisingEdge = 0x1U, /*!< ISF flag and DMA request on rising edge. */
kGPIO_DMAFallingEdge = 0x2U, /*!< ISF flag and DMA request on falling edge. */
kGPIO_DMAEitherEdge = 0x3U, /*!< ISF flag and DMA request on either edge. */
kGPIO_FlagRisingEdge = 0x05U, /*!< Flag sets on rising edge. */
kGPIO_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
kGPIO_FlagEitherEdge = 0x07U, /*!< Flag sets on either edge. */
kGPIO_InterruptLogicZero = 0x8U, /*!< Interrupt when logic zero. */
kGPIO_InterruptRisingEdge = 0x9U, /*!< Interrupt on rising edge. */
kGPIO_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
kGPIO_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */
kGPIO_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */
kGPIO_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */
kGPIO_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */
} gpio_interrupt_config_t;
#endif
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*! @brief Configures the selection of interrupt/DMA request/trigger output. */
typedef enum _gpio_interrupt_selection
{
kGPIO_InterruptOutput0 = 0x0U, /*!< Interrupt/DMA request/trigger output 0. */
kGPIO_InterruptOutput1 = 0x1U, /*!< Interrupt/DMA request/trigger output 1. */
} gpio_interrupt_selection_t;
#endif /* FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT */
#if defined(FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER
/*! @brief GPIO version information. */
typedef struct _gpio_version_info
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor Version Number. */
uint8_t major; /*!< Major Version Number. */
} gpio_version_info_t;
#endif /* FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER */
#if defined(FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL) && FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL
/*! @brief GPIO pin and interrupt control. */
typedef enum
{
kGPIO_PinControlNonSecure = 0x01U, /*!< Pin Control Non-Secure. */
kGPIO_InterruptControlNonSecure = 0x02U, /*!< Interrupt Control Non-Secure. */
kGPIO_PinControlNonPrivilege = 0x04U, /*!< Pin Control Non-Privilege. */
kGPIO_InterruptControlNonPrivilege = 0x08U, /*!< Interrupt Control Non-Privilege. */
} gpio_pin_interrupt_control_t;
#endif /* FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL */
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup gpio_driver
* @{
*/
/*! @name GPIO Configuration */
/*! @{ */
/*!
* @brief Initializes a GPIO pin used by the board.
*
* To initialize the GPIO, define a pin configuration, as either input or output, in the user file.
* Then, call the GPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration.
* @code
* Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO port pin number
* @param config GPIO pin configuration pointer
*/
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
#if defined(FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER
/*!
* @brief Get GPIO version information.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param info GPIO version information
*/
void GPIO_GetVersionInfo(GPIO_Type *base, gpio_version_info_t *info);
#endif /* FSL_FEATURE_GPIO_HAS_VERSION_INFO_REGISTER */
#if defined(FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL) && FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL
/*!
* @brief lock or unlock secure privilege.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask pin or interrupt macro
*/
static inline void GPIO_SecurePrivilegeLock(GPIO_Type *base, gpio_pin_interrupt_control_t mask)
{
base->LOCK |= GPIO_FIT_REG(mask);
}
/*!
* @brief Enable Pin Control Non-Secure.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_EnablePinControlNonSecure(GPIO_Type *base, uint32_t mask)
{
base->PCNS |= GPIO_FIT_REG(mask);
}
/*!
* @brief Disable Pin Control Non-Secure.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_DisablePinControlNonSecure(GPIO_Type *base, uint32_t mask)
{
base->PCNS &= GPIO_FIT_REG(~mask);
}
/*!
* @brief Enable Pin Control Non-Privilege.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_EnablePinControlNonPrivilege(GPIO_Type *base, uint32_t mask)
{
base->PCNP |= GPIO_FIT_REG(mask);
}
/*!
* @brief Disable Pin Control Non-Privilege.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_DisablePinControlNonPrivilege(GPIO_Type *base, uint32_t mask)
{
base->PCNP &= GPIO_FIT_REG(~mask);
}
/*!
* @brief Enable Interrupt Control Non-Secure.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_EnableInterruptControlNonSecure(GPIO_Type *base, uint32_t mask)
{
base->ICNS |= GPIO_FIT_REG(mask);
}
/*!
* @brief Disable Interrupt Control Non-Secure.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_DisableInterruptControlNonSecure(GPIO_Type *base, uint32_t mask)
{
base->ICNS &= GPIO_FIT_REG(~mask);
}
/*!
* @brief Enable Interrupt Control Non-Privilege.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_EnableInterruptControlNonPrivilege(GPIO_Type *base, uint32_t mask)
{
base->ICNP |= GPIO_FIT_REG(mask);
}
/*!
* @brief Disable Interrupt Control Non-Privilege.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_DisableInterruptControlNonPrivilege(GPIO_Type *base, uint32_t mask)
{
base->ICNP &= GPIO_FIT_REG(~mask);
}
#endif /* FSL_FEATURE_GPIO_HAS_SECURE_PRIVILEGE_CONTROL */
#if defined(FSL_FEATURE_GPIO_HAS_PORT_INPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_PORT_INPUT_CONTROL
/*!
* @brief Enable port input.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortInputEnable(GPIO_Type *base, uint32_t mask)
{
base->PIDR &= GPIO_FIT_REG(~mask);
}
/*!
* @brief Disable port input.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortInputDisable(GPIO_Type *base, uint32_t mask)
{
base->PIDR |= GPIO_FIT_REG(mask);
}
#endif /* FSL_FEATURE_GPIO_HAS_PORT_INPUT_CONTROL */
/*! @} */
/*! @name GPIO Output Operations */
/*! @{ */
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1 or 0.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin number
* @param output GPIO pin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
static inline void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output)
{
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL)
if (output == 0U)
{
base->PCOR = GPIO_FIT_REG(1UL << pin);
}
else
{
base->PSOR = GPIO_FIT_REG(1UL << pin);
}
#else
if (output == 0U)
{
base->PDOR |= GPIO_FIT_REG(1UL << pin);
}
else
{
base->PDOR &= ~GPIO_FIT_REG(1UL << pin);
}
#endif
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 1.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortSet(GPIO_Type *base, uint32_t mask)
{
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL)
base->PSOR = GPIO_FIT_REG(mask);
#else
base->PDOR |= GPIO_FIT_REG(mask);
#endif
}
/*!
* @brief Sets the output level of the multiple GPIO pins to the logic 0.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortClear(GPIO_Type *base, uint32_t mask)
{
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL)
base->PCOR = GPIO_FIT_REG(mask);
#else
base->PDOR &= ~GPIO_FIT_REG(mask);
#endif
}
/*!
* @brief Reverses the current output logic of the multiple GPIO pins.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
static inline void GPIO_PortToggle(GPIO_Type *base, uint32_t mask)
{
#if !(defined(FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL) && FSL_FEATURE_GPIO_HAS_NO_INDEP_OUTPUT_CONTROL)
base->PTOR = GPIO_FIT_REG(mask);
#else
base->PDOR ^= GPIO_FIT_REG(mask);
#endif
}
/*! @} */
/*! @name GPIO Input Operations */
/*! @{ */
/*!
* @brief Reads the current input value of the GPIO port.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param pin GPIO pin number
* @retval GPIO port input value
* - 0: corresponding pin input low-logic level.
* - 1: corresponding pin input high-logic level.
*/
static inline uint32_t GPIO_PinRead(GPIO_Type *base, uint32_t pin)
{
return (((uint32_t)(base->PDIR) >> pin) & 0x01UL);
}
/*! @} */
/*! @name GPIO Interrupt */
/*! @{ */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* @brief Reads the GPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @retval The current GPIO port interrupt status flag, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t GPIO_PortGetInterruptFlags(GPIO_Type *base);
/*!
* @brief Clears multiple GPIO pin interrupt status flags.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
void GPIO_PortClearInterruptFlags(GPIO_Type *base, uint32_t mask);
#else
/*!
* @brief Configures the gpio pin interrupt/DMA request.
*
* @param base GPIO peripheral base pointer.
* @param pin GPIO pin number.
* @param config GPIO pin interrupt configuration.
* - #kGPIO_InterruptStatusFlagDisabled: Interrupt/DMA request disabled.
* - #kGPIO_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kGPIO_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kGPIO_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kGPIO_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kGPIO_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kGPIO_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kGPIO_InterruptLogicZero : Interrupt when logic zero.
* - #kGPIO_InterruptRisingEdge : Interrupt on rising edge.
* - #kGPIO_InterruptFallingEdge: Interrupt on falling edge.
* - #kGPIO_InterruptEitherEdge : Interrupt on either edge.
* - #kGPIO_InterruptLogicOne : Interrupt when logic one.
* - #kGPIO_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kGPIO_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit).
*/
static inline void GPIO_SetPinInterruptConfig(GPIO_Type *base, uint32_t pin, gpio_interrupt_config_t config)
{
assert(base);
base->ICR[pin] = GPIO_FIT_REG((base->ICR[pin] & ~GPIO_ICR_IRQC_MASK) | GPIO_ICR_IRQC(config));
}
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*!
* @brief Configures the gpio pin interrupt/DMA request/trigger output channel selection.
*
* @param base GPIO peripheral base pointer.
* @param pin GPIO pin number.
* @param selection GPIO pin interrupt output selection.
* - #kGPIO_InterruptOutput0: Interrupt/DMA request/trigger output 0.
* - #kGPIO_InterruptOutput1 : Interrupt/DMA request/trigger output 1.
*/
static inline void GPIO_SetPinInterruptChannel(GPIO_Type *base, uint32_t pin, gpio_interrupt_selection_t selection)
{
assert(base);
base->ICR[pin] = GPIO_FIT_REG((base->ICR[pin] & ~GPIO_ICR_IRQS_MASK) | GPIO_ICR_IRQS(selection));
}
#endif
/*!
* @brief Read the GPIO interrupt status flags.
*
* @param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
* @return The current GPIO's interrupt status flag.
* '1' means the related pin's flag is set, '0' means the related pin's flag not set.
* For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
*/
uint32_t GPIO_GpioGetInterruptFlags(GPIO_Type *base);
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*!
* @brief Read the GPIO interrupt status flags based on selected interrupt channel(IRQS).
*
* @param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on.)
* @param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
* @return The current GPIO's interrupt status flag based on the selected interrupt channel.
* '1' means the related pin's flag is set, '0' means the related pin's flag not set.
* For example, the return value 0x00010001 means the pin 0 and 17 have the interrupt pending.
*/
uint32_t GPIO_GpioGetInterruptChannelFlags(GPIO_Type *base, uint32_t channel);
#endif
/*!
* @brief Read individual pin's interrupt status flag.
*
* @param base GPIO peripheral base pointer. (GPIOA, GPIOB, GPIOC, and so on)
* @param pin GPIO specific pin number.
* @return The current selected pin's interrupt status flag.
*/
uint8_t GPIO_PinGetInterruptFlag(GPIO_Type *base, uint32_t pin);
/*!
* @brief Clears GPIO pin interrupt status flags.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
*/
void GPIO_GpioClearInterruptFlags(GPIO_Type *base, uint32_t mask);
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
/*!
* @brief Clears GPIO pin interrupt status flags based on selected interrupt channel(IRQS).
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param mask GPIO pin number macro
* @param channel '0' means selete interrupt channel 0, '1' means selete interrupt channel 1.
*/
void GPIO_GpioClearInterruptChannelFlags(GPIO_Type *base, uint32_t mask, uint32_t channel);
#endif
/*!
* @brief Clear GPIO individual pin's interrupt status flag.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on).
* @param pin GPIO specific pin number.
*/
void GPIO_PinClearInterruptFlag(GPIO_Type *base, uint32_t pin);
/*!
* @brief Reads the GPIO DMA request flags.
* The corresponding flag will be cleared automatically at the completion of the requested
* DMA transfer
*/
static inline uint32_t GPIO_GetPinsDMARequestFlags(GPIO_Type *base)
{
assert(base);
return (base->ISFR[1]);
}
/*!
* @brief Sets the GPIO interrupt configuration in PCR register for multiple pins.
*
* @param base GPIO peripheral base pointer.
* @param mask GPIO pin number macro.
* @param config GPIO pin interrupt configuration.
* - #kGPIO_InterruptStatusFlagDisabled: Interrupt disabled.
* - #kGPIO_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kGPIO_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kGPIO_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kGPIO_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kGPIO_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kGPIO_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kGPIO_InterruptLogicZero : Interrupt when logic zero.
* - #kGPIO_InterruptRisingEdge : Interrupt on rising edge.
* - #kGPIO_InterruptFallingEdge: Interrupt on falling edge.
* - #kGPIO_InterruptEitherEdge : Interrupt on either edge.
* - #kGPIO_InterruptLogicOne : Interrupt when logic one.
* - #kGPIO_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kGPIO_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit)..
*/
static inline void GPIO_SetMultipleInterruptPinsConfig(GPIO_Type *base, uint32_t mask, gpio_interrupt_config_t config)
{
assert(base);
if (0UL != (mask & 0xffffUL))
{
base->GICLR = GPIO_FIT_REG((GPIO_ICR_IRQC(config)) | (mask & 0xffffU));
}
mask = mask >> 16U;
if (mask != 0UL)
{
base->GICHR = GPIO_FIT_REG((GPIO_ICR_IRQC(config)) | (mask & 0xffffU));
}
}
#endif
#if defined(FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_GPIO_HAS_ATTRIBUTE_CHECKER
/*!
* brief The GPIO module supports a device-specific number of data ports, organized as 32-bit
* words/8-bit Bytes. Each 32-bit/8-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. If the GPIO module's GACR register
* organized as 32-bit words, the attribute controls for the 4 data bytes in the GACR follow a standard little
* endian data convention.
*
* @param base GPIO peripheral base pointer (GPIOA, GPIOB, GPIOC, and so on.)
* @param attribute GPIO checker attribute
*/
void GPIO_CheckAttributeBytes(GPIO_Type *base, gpio_checker_attribute_t attribute);
#endif
/*! @} */
/*! @} */
/*!
* @addtogroup fgpio_driver
* @{
*/
/*
* Introduces the FGPIO feature.
*
* The FGPIO features are only support on some Kinetis MCUs. The FGPIO registers are aliased to the IOPORT
* interface. Accesses via the IOPORT interface occur in parallel with any instruction fetches and
* complete in a single cycle. This aliased Fast GPIO memory map is called FGPIO.
*/
#if defined(FSL_FEATURE_SOC_FGPIO_COUNT) && FSL_FEATURE_SOC_FGPIO_COUNT
/*! @name FGPIO Configuration */
/*! @{ */
#if defined(FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL) && FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL
/*!
* @brief Initializes the FGPIO peripheral.
*
* This function ungates the FGPIO clock.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
*/
void FGPIO_PortInit(FGPIO_Type *base);
#endif /* FSL_FEATURE_PCC_HAS_FGPIO_CLOCK_GATE_CONTROL */
/*!
* @brief Initializes a FGPIO pin used by the board.
*
* To initialize the FGPIO driver, define a pin configuration, as either input or output, in the user file.
* Then, call the FGPIO_PinInit() function.
*
* This is an example to define an input pin or an output pin configuration:
* @code
* Define a digital input pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalInput,
* 0,
* }
* Define a digital output pin configuration,
* gpio_pin_config_t config =
* {
* kGPIO_DigitalOutput,
* 0,
* }
* @endcode
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO port pin number
* @param config FGPIO pin configuration pointer
*/
void FGPIO_PinInit(FGPIO_Type *base, uint32_t pin, const gpio_pin_config_t *config);
/*! @} */
/*! @name FGPIO Output Operations */
/*! @{ */
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1 or 0.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO pin number
* @param output FGPIOpin output logic level.
* - 0: corresponding pin output low-logic level.
* - 1: corresponding pin output high-logic level.
*/
static inline void FGPIO_PinWrite(FGPIO_Type *base, uint32_t pin, uint8_t output)
{
if (output == 0U)
{
base->PCOR = 1UL << pin;
}
else
{
base->PSOR = 1UL << pin;
}
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 1.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_PortSet(FGPIO_Type *base, uint32_t mask)
{
base->PSOR = mask;
}
/*!
* @brief Sets the output level of the multiple FGPIO pins to the logic 0.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_PortClear(FGPIO_Type *base, uint32_t mask)
{
base->PCOR = mask;
}
/*!
* @brief Reverses the current output logic of the multiple FGPIO pins.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
static inline void FGPIO_PortToggle(FGPIO_Type *base, uint32_t mask)
{
base->PTOR = mask;
}
/*! @} */
/*! @name FGPIO Input Operations */
/*! @{ */
/*!
* @brief Reads the current input value of the FGPIO port.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param pin FGPIO pin number
* @retval FGPIO port input value
* - 0: corresponding pin input low-logic level.
* - 1: corresponding pin input high-logic level.
*/
static inline uint32_t FGPIO_PinRead(FGPIO_Type *base, uint32_t pin)
{
return (((base->PDIR) >> pin) & 0x01U);
}
/*! @} */
/*! @name FGPIO Interrupt */
/*! @{ */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && \
defined(FSL_FEATURE_SOC_PORT_COUNT)
/*!
* @brief Reads the FGPIO port interrupt status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level-sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @retval The current FGPIO port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 17 have the interrupt.
*/
uint32_t FGPIO_PortGetInterruptFlags(FGPIO_Type *base);
/*!
* @brief Clears the multiple FGPIO pin interrupt status flag.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param mask FGPIO pin number macro
*/
void FGPIO_PortClearInterruptFlags(FGPIO_Type *base, uint32_t mask);
#endif
#if defined(FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER) && FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER
/*!
* @brief The FGPIO module supports a device-specific number of data ports, organized as 32-bit
* words. Each 32-bit data port includes a GACR register, which defines the byte-level
* attributes required for a successful access to the GPIO programming model. The attribute controls for the 4 data
* bytes in the GACR follow a standard little endian
* data convention.
*
* @param base FGPIO peripheral base pointer (FGPIOA, FGPIOB, FGPIOC, and so on.)
* @param attribute FGPIO checker attribute
*/
void FGPIO_CheckAttributeBytes(FGPIO_Type *base, gpio_checker_attribute_t attribute);
#endif /* FSL_FEATURE_FGPIO_HAS_ATTRIBUTE_CHECKER */
/*! @} */
#endif /* FSL_FEATURE_SOC_FGPIO_COUNT */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif /* FSL_GPIO_H_*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,279 @@
/*
* Copyright 2022-2023 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_I3C_EDMA_H_
#define FSL_I3C_EDMA_H_
#include "fsl_i3c.h"
#include "fsl_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief I3C EDMA driver version. */
#define FSL_I3C_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 2, 9))
/*! @} */
/*!
* @addtogroup i3c_master_edma_driver
* @{
*/
/* Forward declaration of the transfer descriptor and handle typedefs. */
typedef struct _i3c_master_edma_handle i3c_master_edma_handle_t;
/*! @brief i3c master callback functions. */
typedef struct _i3c_master_edma_callback
{
void (*slave2Master)(I3C_Type *base, void *userData); /*!< Transfer complete callback */
void (*ibiCallback)(I3C_Type *base,
i3c_master_edma_handle_t *handle,
i3c_ibi_type_t ibiType,
i3c_ibi_state_t ibiState); /*!< IBI event callback */
void (*transferComplete)(I3C_Type *base,
i3c_master_edma_handle_t *handle,
status_t status,
void *userData); /*!< Transfer complete callback */
} i3c_master_edma_callback_t;
/*!
* @brief Driver handle for master EDMA APIs.
* @note The contents of this structure are private and subject to change.
*/
struct _i3c_master_edma_handle
{
I3C_Type *base; /*!< I3C base pointer. */
uint8_t state; /*!< Transfer state machine current state. */
uint32_t transferCount; /*!< Indicates progress of the transfer */
uint8_t subaddressBuffer[4]; /*!< Saving subaddress command. */
uint8_t subaddressCount; /*!< Saving command count. */
i3c_master_transfer_t transfer; /*!< Copy of the current transfer info. */
i3c_master_edma_callback_t callback; /*!< Callback function pointer. */
void *userData; /*!< Application data passed to callback. */
edma_handle_t *rxDmaHandle; /*!< Handle for receive DMA channel. */
edma_handle_t *txDmaHandle; /*!< Handle for transmit DMA channel. */
uint8_t ibiAddress; /*!< Slave address which request IBI. */
uint8_t *ibiBuff; /*!< Pointer to IBI buffer to keep ibi bytes. */
size_t ibiPayloadSize; /*!< IBI payload size. */
i3c_ibi_type_t ibiType; /*!< IBI type. */
};
/*! @} */
/*!
* @addtogroup i3c_slave_edma_driver
* @{
*/
/* Forward declaration of the transfer descriptor and handle typedefs. */
typedef struct _i3c_slave_edma_handle i3c_slave_edma_handle_t;
/*! @brief I3C slave transfer structure */
typedef struct _i3c_slave_edma_transfer
{
uint32_t event; /*!< Reason the callback is being invoked. */
uint8_t *txData; /*!< Transfer buffer */
size_t txDataSize; /*!< Transfer size */
uint8_t *rxData; /*!< Transfer buffer */
size_t rxDataSize; /*!< Transfer size */
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
#kI3C_SlaveCompletionEvent. */
} i3c_slave_edma_transfer_t;
/*!
* @brief Slave event callback function pointer type.
*
* This callback is used only for the slave DMA transfer API.
*
* @param base Base address for the I3C instance on which the event occurred.
* @param handle Pointer to slave DMA transfer handle.
* @param transfer Pointer to transfer descriptor containing values passed to and/or from the callback.
* @param userData Arbitrary pointer-sized value passed from the application.
*/
typedef void (*i3c_slave_edma_callback_t)(I3C_Type *base, i3c_slave_edma_transfer_t *transfer, void *userData);
/*!
* @brief I3C slave edma handle structure.
* @note The contents of this structure are private and subject to change.
*/
struct _i3c_slave_edma_handle
{
I3C_Type *base; /*!< I3C base pointer. */
i3c_slave_edma_transfer_t transfer; /*!< I3C slave transfer copy. */
bool isBusy; /*!< Whether transfer is busy. */
bool wasTransmit; /*!< Whether the last transfer was a transmit. */
uint32_t eventMask; /*!< Mask of enabled events. */
i3c_slave_edma_callback_t callback; /*!< Callback function called at transfer event. */
edma_handle_t *rxDmaHandle; /*!< Handle for receive DMA channel. */
edma_handle_t *txDmaHandle; /*!< Handle for transmit DMA channel. */
void *userData; /*!< Callback parameter passed to callback. */
};
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup i3c_master_edma_driver
* @{
*/
/*! @name Master DMA */
/*! @{ */
/*!
* @brief Create a new handle for the I3C master DMA APIs.
*
* The creation of a handle is for use with the DMA APIs. Once a handle
* is created, there is not a corresponding destroy handle. If the user wants to
* terminate a transfer, the I3C_MasterTransferAbortDMA() API shall be called.
*
* For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
* parameter is ignored and may be set to NULL.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C master driver handle.
* @param callback User provided pointer to the asynchronous callback function.
* @param userData User provided pointer to the application callback data.
* @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
* @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
*/
void I3C_MasterTransferCreateHandleEDMA(I3C_Type *base,
i3c_master_edma_handle_t *handle,
const i3c_master_edma_callback_t *callback,
void *userData,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle);
/*!
* @brief Performs a non-blocking DMA-based transaction on the I3C bus.
*
* The callback specified when the @a handle was created is invoked when the transaction has
* completed.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C master driver handle.
* @param transfer The pointer to the transfer descriptor.
* @retval kStatus_Success The transaction was started successfully.
* @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
* transaction is already in progress.
*/
status_t I3C_MasterTransferEDMA(I3C_Type *base, i3c_master_edma_handle_t *handle, i3c_master_transfer_t *transfer);
/*!
* @brief Returns number of bytes transferred so far.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C master driver handle.
* @param[out] count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_Success
* @retval kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
*/
status_t I3C_MasterTransferGetCountEDMA(I3C_Type *base, i3c_master_edma_handle_t *handle, size_t *count);
/*!
* @brief Terminates a non-blocking I3C master transmission early.
*
* @note It is not safe to call this function from an IRQ handler that has a higher priority than the
* DMA peripheral's IRQ priority.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C master driver handle.
*/
void I3C_MasterTransferAbortEDMA(I3C_Type *base, i3c_master_edma_handle_t *handle);
/*!
* @brief Reusable routine to handle master interrupts.
* @note This function does not need to be called unless you are reimplementing the
* nonblocking API's interrupt handler routines to add special functionality.
* @param base The I3C peripheral base address.
* @param i3cHandle Pointer to the I3C master DMA driver handle.
*/
void I3C_MasterTransferEDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
/*! @} */
/*! @} */
/*!
* @addtogroup i3c_slave_edma_driver
* @{
*/
/*! @name Slave DMA */
/*! @{ */
/*!
* @brief Create a new handle for the I3C slave DMA APIs.
*
* The creation of a handle is for use with the DMA APIs. Once a handle
* is created, there is not a corresponding destroy handle. If the user wants to
* terminate a transfer, the I3C_SlaveTransferAbortDMA() API shall be called.
*
* For devices where the I3C send and receive DMA requests are OR'd together, the @a txDmaHandle
* parameter is ignored and may be set to NULL.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C slave driver handle.
* @param callback User provided pointer to the asynchronous callback function.
* @param userData User provided pointer to the application callback data.
* @param rxDmaHandle Handle for the DMA receive channel. Created by the user prior to calling this function.
* @param txDmaHandle Handle for the DMA transmit channel. Created by the user prior to calling this function.
*/
void I3C_SlaveTransferCreateHandleEDMA(I3C_Type *base,
i3c_slave_edma_handle_t *handle,
i3c_slave_edma_callback_t callback,
void *userData,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle);
/*!
* @brief Prepares for a non-blocking DMA-based transaction on the I3C bus.
*
* The API will do DMA configuration according to the input transfer descriptor, and the data will be transferred when
* there's bus master requesting transfer from/to this slave. So the timing of call to this API need be aligned
* with master application to ensure the transfer is executed as expected.
* Callback specified when the @a handle was created is invoked when the transaction has completed.
*
* @param base The I3C peripheral base address.
* @param handle Pointer to the I3C slave driver handle.
* @param transfer The pointer to the transfer descriptor.
* @param eventMask Bit mask formed by OR'ing together #i3c_slave_transfer_event_t enumerators to specify
* which events to send to the callback. The transmit and receive events is not allowed to be enabled.
* @retval kStatus_Success The transaction was started successfully.
* @retval #kStatus_I3C_Busy Either another master is currently utilizing the bus, or another DMA
* transaction is already in progress.
* @retval #kStatus_Fail The transaction can't be set.
*/
status_t I3C_SlaveTransferEDMA(I3C_Type *base,
i3c_slave_edma_handle_t *handle,
i3c_slave_edma_transfer_t *transfer,
uint32_t eventMask);
/*!
* @brief Abort a slave edma non-blocking transfer in a early time
*
* @param base I3C peripheral base address
* @param handle pointer to i3c_slave_edma_handle_t structure
*/
void I3C_SlaveTransferAbortEDMA(I3C_Type *base, i3c_slave_edma_handle_t *handle);
/*!
* @brief Reusable routine to handle slave interrupts.
* @note This function does not need to be called unless you are reimplementing the
* nonblocking API's interrupt handler routines to add special functionality.
* @param base The I3C peripheral base address.
* @param i3cHandle Pointer to the I3C slave DMA driver handle.
*/
void I3C_SlaveTransferEDMAHandleIRQ(I3C_Type *base, void *i3cHandle);
/*! @} */
/*! @} */
#if defined(__cplusplus)
}
#endif
#endif /* FSL_I3C_EDMA_H_ */

View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_inputmux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.inputmux"
#endif
#if defined(INPUTMUX_RSTS)
#define INPUTMUX_RESETS_ARRAY INPUTMUX_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(INPUTMUX_RESETS_ARRAY)
/*!
* @brief Get instance number for INPUTMUX module.
*
* @param base INPUTMUX peripheral base address
*/
static uint32_t INPUTMUX_GetInstance(INPUTMUX_Type *base);
#endif
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(INPUTMUX_RESETS_ARRAY)
/*! @brief Pointers to INPUTMUX bases for each instance. */
static INPUTMUX_Type *const s_inputmuxBases[] = INPUTMUX_BASE_PTRS;
/* Reset array */
static const reset_ip_name_t s_inputmuxResets[] = INPUTMUX_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if defined(INPUTMUX_RESETS_ARRAY)
static uint32_t INPUTMUX_GetInstance(INPUTMUX_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_inputmuxBases); instance++)
{
if (s_inputmuxBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_inputmuxBases));
return instance;
}
#endif
/*!
* brief Initialize INPUTMUX peripheral.
* This function enables the INPUTMUX clock.
*
* param base Base address of the INPUTMUX peripheral.
*
* retval None.
*/
void INPUTMUX_Init(INPUTMUX_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#if defined(FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE) && FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE
#if (defined(FSL_FEATURE_SOC_SCT_COUNT) && (FSL_FEATURE_SOC_SCT_COUNT > 0))
CLOCK_EnableClock(kCLOCK_Sct);
#endif /* FSL_FEATURE_SOC_SCT_COUNT */
CLOCK_EnableClock(kCLOCK_Dma);
#else
CLOCK_EnableClock(kCLOCK_InputMux);
#endif /* FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE */
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(INPUTMUX_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_inputmuxResets[INPUTMUX_GetInstance(base)]);
#endif
}
/*!
* brief Attaches a signal
*
* This function attaches multiplexed signals from INPUTMUX to target signals.
* For example, to attach GPIO PORT0 Pin 5 to PINT peripheral, do the following:
* code
* INPUTMUX_AttachSignal(INPUTMUX, 2, kINPUTMUX_GpioPort0Pin5ToPintsel);
* endcode
* In this example, INTMUX has 8 registers for PINT, PINT_SEL0~PINT_SEL7.
* With parameter p index specified as 2, this function configures register PINT_SEL2.
*
* param base Base address of the INPUTMUX peripheral.
* param index The serial number of destination register in the group of INPUTMUX registers with same name.
* param connection Applies signal from source signals collection to target signal.
*
* retval None.
*/
void INPUTMUX_AttachSignal(INPUTMUX_Type *base, uint32_t index, inputmux_connection_t connection)
{
uint32_t pmux_id;
uint32_t output_id;
/* extract pmux to be used */
pmux_id = ((uint32_t)(connection)) >> PMUX_SHIFT;
/* extract function number */
output_id = ((uint32_t)(connection)) & ((1UL << PMUX_SHIFT) - 1U);
/* programm signal */
*(volatile uint32_t *)(((uint32_t)base) + pmux_id + (index * 4U)) = output_id;
}
#if defined(FSL_FEATURE_INPUTMUX_HAS_SIGNAL_ENA)
/*!
* brief Enable/disable a signal
*
* This function gates the INPUTPMUX clock.
*
* param base Base address of the INPUTMUX peripheral.
* param signal Enable signal register id and bit offset.
* param enable Selects enable or disable.
*
* retval None.
*/
void INPUTMUX_EnableSignal(INPUTMUX_Type *base, inputmux_signal_t signal, bool enable)
{
uint32_t ena_id;
uint32_t ena_id_mask = (1UL << (32U - ENA_SHIFT)) - 1U;
uint32_t bit_offset;
#if defined(FSL_FEATURE_INPUTMUX_HAS_CHANNEL_MUX) && FSL_FEATURE_INPUTMUX_HAS_CHANNEL_MUX
uint32_t chmux_offset;
uint32_t chmux_value;
/* Only enable need to update channel mux */
if (enable && ((((uint32_t)signal) & (1UL << CHMUX_AVL_SHIFT)) != 0U))
{
chmux_offset = (((uint32_t)signal) >> CHMUX_OFF_SHIFT) & ((1UL << (CHMUX_AVL_SHIFT - CHMUX_OFF_SHIFT)) - 1UL);
chmux_value = (((uint32_t)signal) >> CHMUX_VAL_SHIFT) & ((1UL << (CHMUX_OFF_SHIFT - CHMUX_VAL_SHIFT)) - 1UL);
*(volatile uint32_t *)(((uint32_t)base) + chmux_offset) = chmux_value;
}
ena_id_mask = (1UL << (CHMUX_VAL_SHIFT - ENA_SHIFT)) - 1U;
#endif
/* extract enable register to be used */
ena_id = (((uint32_t)signal) >> ENA_SHIFT) & ena_id_mask;
/* extract enable bit offset */
bit_offset = ((uint32_t)signal) & ((1UL << ENA_SHIFT) - 1U);
/* set signal */
if (enable)
{
*(volatile uint32_t *)(((uint32_t)base) + ena_id) |= (1UL << bit_offset);
}
else
{
*(volatile uint32_t *)(((uint32_t)base) + ena_id) &= ~(1UL << bit_offset);
}
}
#endif
/*!
* brief Deinitialize INPUTMUX peripheral.
* This function disables the INPUTMUX clock.
*
* param base Base address of the INPUTMUX peripheral.
*
* retval None.
*/
void INPUTMUX_Deinit(INPUTMUX_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#if defined(FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE) && FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE
#if (defined(FSL_FEATURE_SOC_SCT_COUNT) && (FSL_FEATURE_SOC_SCT_COUNT > 0))
CLOCK_DisableClock(kCLOCK_Sct);
#endif /* FSL_FEATURE_SOC_SCT_COUNT */
CLOCK_DisableClock(kCLOCK_Dma);
#else
CLOCK_DisableClock(kCLOCK_InputMux);
#endif /* FSL_FEATURE_INPUTMUX_HAS_NO_INPUTMUX_CLOCK_SOURCE */
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_INPUTMUX_H_
#define FSL_INPUTMUX_H_
#include "fsl_inputmux_connections.h"
#include "fsl_common.h"
/*!
* @addtogroup inputmux_driver
* @{
*/
/*! @file */
/*! @file fsl_inputmux_connections.h */
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief Group interrupt driver version for SDK */
#define FSL_INPUTMUX_DRIVER_VERSION (MAKE_VERSION(2, 0, 7))
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @brief Initialize INPUTMUX peripheral.
* This function enables the INPUTMUX clock.
*
* @param base Base address of the INPUTMUX peripheral.
*
* @retval None.
*/
void INPUTMUX_Init(INPUTMUX_Type *base);
/*!
* @brief Attaches a signal
*
* This function attaches multiplexed signals from INPUTMUX to target signals.
* For example, to attach GPIO PORT0 Pin 5 to PINT peripheral, do the following:
* @code
* INPUTMUX_AttachSignal(INPUTMUX, 2, kINPUTMUX_GpioPort0Pin5ToPintsel);
* @endcode
* In this example, INTMUX has 8 registers for PINT, PINT_SEL0~PINT_SEL7.
* With parameter @p index specified as 2, this function configures register PINT_SEL2.
*
* @param base Base address of the INPUTMUX peripheral.
* @param index The serial number of destination register in the group of INPUTMUX registers with same name.
* @param connection Applies signal from source signals collection to target signal.
*
* @retval None.
*/
void INPUTMUX_AttachSignal(INPUTMUX_Type *base, uint32_t index, inputmux_connection_t connection);
#if defined(FSL_FEATURE_INPUTMUX_HAS_SIGNAL_ENA)
/*!
* @brief Enable/disable a signal
*
* This function gates the INPUTPMUX clock.
*
* @param base Base address of the INPUTMUX peripheral.
* @param signal Enable signal register id and bit offset.
* @param enable Selects enable or disable.
*
* @retval None.
*/
void INPUTMUX_EnableSignal(INPUTMUX_Type *base, inputmux_signal_t signal, bool enable);
#endif
/*!
* @brief Deinitialize INPUTMUX peripheral.
* This function disables the INPUTMUX clock.
*
* @param base Base address of the INPUTMUX peripheral.
*
* @retval None.
*/
void INPUTMUX_Deinit(INPUTMUX_Type *base);
#ifdef __cplusplus
}
#endif
/*! @} */
#endif /* FSL_INPUTMUX_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,977 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpadc.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpadc"
#endif
#ifndef ADC_VERID_DIFFEN_MASK
#define ADC_VERID_DIFFEN_MASK (0x2U)
#endif /* ADC_VERID_DIFFEN_MASK */
#ifndef ADC_VERID_NUM_SEC_MASK
#define ADC_VERID_NUM_SEC_MASK (0x800U)
#endif /* ADC_VERID_NUM_SEC_MASK */
#define ADC_CMDL_CHANNEL_MODE_MASK (0x60U)
#define ADC_CMDL_CHANNEL_MODE_SHIFT (5U)
#define ADC_CMDL_CHANNEL_MODE(x) \
(((uint32_t)(((uint32_t)(x)) << ADC_CMDL_CHANNEL_MODE_SHIFT)) & ADC_CMDL_CHANNEL_MODE_MASK)
#define GET_ADC_CFG_TPRICTRL_VALUE(val) (((uint32_t)val) & 0x3U)
#if defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES
#define GET_ADC_CFG_TRES_VALUE(val) ((((uint32_t)val) & 0x4U) >> 2U)
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES
#define GET_ADC_CFG_TCMDRES_VALUE(val) ((((uint32_t)val) & 0x8U) >> 3U)
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI
#define GET_ADC_CFG_HPT_EXDI_VALUE(val) ((((uint32_t)val) & 0x10U) >> 4U)
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
#if defined(LPADC_RSTS)
#define LPADC_RESETS_ARRAY LPADC_RSTS
#elif defined(ADC_RSTS)
#define LPADC_RESETS_ARRAY ADC_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Get instance number for LPADC module.
*
* @param base LPADC peripheral base address
*/
static uint32_t LPADC_GetInstance(ADC_Type *base);
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
/*!
* @brief Get gain conversion result .
*
* @param gainAdjustment gain adjustment value.
*/
static uint32_t LPADC_GetGainConvResult(float gainAdjustment);
#endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
/*******************************************************************************
* Variables
******************************************************************************/
/*! @brief Pointers to LPADC bases for each instance. */
static ADC_Type *const s_lpadcBases[] = ADC_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to LPADC clocks for each instance. */
static const clock_ip_name_t s_lpadcClocks[] = LPADC_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(LPADC_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_lpadcResets[] = LPADC_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t LPADC_GetInstance(ADC_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
/*
* $Branch Coverage Justification$
* (instance >= ARRAY_SIZE(s_lpadcBases)) not covered. The peripheral base
* address is always valid and checked by assert.
*/
for (instance = 0; instance < ARRAY_SIZE(s_lpadcBases); instance++)
{
/*
* $Branch Coverage Justification$
* (s_lpadcBases[instance] != base) not covered. The peripheral base
* address is always valid and checked by assert.
*/
if (s_lpadcBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lpadcBases));
return instance;
}
#if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
/*!
* brief Get gain conversion Result .
*
* param gainAdjustment gain adjustment value.
*/
static uint32_t LPADC_GetGainConvResult(float gainAdjustment)
{
uint16_t i = 0U;
uint32_t tmp32 = 0U;
uint32_t GCRa[17] = {0};
uint32_t GCALR = 0U;
for (i = 0x11U; i > 0U; i--)
{
tmp32 = (uint32_t)((gainAdjustment) / ((float)(1.0 / (double)(1U << (0x10U - (i - 1U))))));
GCRa[i - 1U] = tmp32;
gainAdjustment = gainAdjustment - ((float)tmp32) * ((float)(1.0 / (double)(1U << (0x10U - (i - 1U)))));
}
/* Get GCALR value calculated */
for (i = 0x11U; i > 0U; i--)
{
GCALR += GCRa[i - 1U] * ((uint32_t)(1UL << (uint32_t)(i - 1UL)));
}
/* to return GCALR value calculated */
return GCALR;
}
#endif /* defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
/*!
* brief Initializes the LPADC module.
*
* param base LPADC peripheral base address.
* param config Pointer to configuration structure. See "lpadc_config_t".
*/
void LPADC_Init(ADC_Type *base, const lpadc_config_t *config)
{
/* Check if the pointer is available. */
assert(config != NULL);
uint32_t tmp32 = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock for LPADC instance. */
(void)CLOCK_EnableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(LPADC_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_lpadcResets[LPADC_GetInstance(base)]);
#endif
/* Reset the module. */
LPADC_DoResetConfig(base);
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
LPADC_DoResetFIFO0(base);
LPADC_DoResetFIFO1(base);
#else
LPADC_DoResetFIFO(base);
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
/* Disable the module before setting configuration. */
LPADC_Enable(base, false);
/* Configure the module generally. */
if (config->enableInDozeMode)
{
base->CTRL &= ~ADC_CTRL_DOZEN_MASK;
}
else
{
base->CTRL |= ADC_CTRL_DOZEN_MASK;
}
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
/* Set calibration average mode. */
base->CTRL |= ADC_CTRL_CAL_AVGS(config->conversionAverageMode);
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
/* ADCx_CFG. */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
if (config->enableInternalClock)
{
tmp32 |= ADC_CFG_ADCKEN_MASK;
}
#endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
if (config->enableVref1LowVoltage)
{
tmp32 |= ADC_CFG_VREF1RNG_MASK;
}
#endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
if (config->enableAnalogPreliminary)
{
tmp32 |= ADC_CFG_PWREN_MASK;
}
tmp32 |= (ADC_CFG_PUDLY(config->powerUpDelay) /* Power up delay. */
| ADC_CFG_REFSEL(config->referenceVoltageSource) /* Reference voltage. */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
| ADC_CFG_PWRSEL(config->powerLevelMode) /* Power configuration. */
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
);
tmp32 |= ADC_CFG_TPRICTRL(GET_ADC_CFG_TPRICTRL_VALUE(config->triggerPriorityPolicy));
#if (defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES)
tmp32 |= ADC_CFG_TRES(GET_ADC_CFG_TRES_VALUE(config->triggerPriorityPolicy));
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TRES) && FSL_FEATURE_LPADC_HAS_CFG_TRES */
#if (defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES)
tmp32 |= ADC_CFG_TCMDRES(GET_ADC_CFG_TCMDRES_VALUE(config->triggerPriorityPolicy));
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_TCMDRES) && FSL_FEATURE_LPADC_HAS_CFG_TCMDRES */
#if (defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI)
tmp32 |= ADC_CFG_HPT_EXDI(GET_ADC_CFG_HPT_EXDI_VALUE(config->triggerPriorityPolicy));
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI) && FSL_FEATURE_LPADC_HAS_CFG_HPT_EXDI */
base->CFG = tmp32;
/* ADCx_PAUSE. */
if (config->enableConvPause)
{
base->PAUSE = ADC_PAUSE_PAUSEEN_MASK | ADC_PAUSE_PAUSEDLY(config->convPauseDelay);
}
else
{
base->PAUSE = 0U;
}
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
/* ADCx_FCTRL0. */
base->FCTRL[0] = ADC_FCTRL_FWMARK(config->FIFO0Watermark);
/* ADCx_FCTRL1. */
base->FCTRL[1] = ADC_FCTRL_FWMARK(config->FIFO1Watermark);
#else
/* ADCx_FCTRL. */
base->FCTRL = ADC_FCTRL_FWMARK(config->FIFOWatermark);
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
/* Enable the module after setting configuration. */
LPADC_Enable(base, true);
}
/*!
* brief Gets an available pre-defined settings for initial configuration.
*
* This function initializes the converter configuration structure with an available settings. The default values are:
* code
* config->enableInDozeMode = true;
* config->conversionAverageMode = kLPADC_ConversionAverage1;
* config->enableAnalogPreliminary = false;
* config->powerUpDelay = 0x80;
* config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
* config->powerLevelMode = kLPADC_PowerLevelAlt1;
* config->triggerPriorityPolicy = kLPADC_TriggerPriorityPreemptImmediately;
* config->enableConvPause = false;
* config->convPauseDelay = 0U;
* config->FIFO0Watermark = 0U;
* config->FIFO1Watermark = 0U;
* config->FIFOWatermark = 0U;
* endcode
* param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConfig(lpadc_config_t *config)
{
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
#if defined(FSL_FEATURE_LPADC_HAS_CFG_ADCKEN) && FSL_FEATURE_LPADC_HAS_CFG_ADCKEN
config->enableInternalClock = false;
#endif /* FSL_FEATURE_LPADC_HAS_CFG_ADCKEN */
#if defined(FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG) && FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG
config->enableVref1LowVoltage = false;
#endif /* FSL_FEATURE_LPADC_HAS_CFG_VREF1RNG */
config->enableInDozeMode = true;
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS
/* Set calibration average mode. */
config->conversionAverageMode = kLPADC_ConversionAverage1;
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */
config->enableAnalogPreliminary = false;
config->powerUpDelay = 0x80;
config->referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
#if defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U)
config->powerLevelMode = kLPADC_PowerLevelAlt1;
#endif /* defined(FSL_FEATURE_LPADC_HAS_CFG_PWRSEL) && (FSL_FEATURE_LPADC_HAS_CFG_PWRSEL == 1U) */
config->triggerPriorityPolicy = kLPADC_TriggerPriorityPreemptImmediately;
config->enableConvPause = false;
config->convPauseDelay = 0U;
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
config->FIFO0Watermark = 0U;
config->FIFO1Watermark = 0U;
#else
config->FIFOWatermark = 0U;
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
}
/*!
* brief De-initializes the LPADC module.
*
* param base LPADC peripheral base address.
*/
void LPADC_Deinit(ADC_Type *base)
{
/* Disable the module. */
LPADC_Enable(base, false);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Gate the clock. */
(void)CLOCK_DisableClock(s_lpadcClocks[LPADC_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
/*!
* brief Get the result in conversion FIFOn.
*
* param base LPADC peripheral base address.
* param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
* param index Result FIFO index.
*
* return Status whether FIFOn entry is valid.
*/
bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
{
assert(result != NULL); /* Check if the input pointer is available. */
uint32_t tmp32 = 0U;
tmp32 = base->RESFIFO[index];
if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
{
return false; /* FIFO is empty. Discard any read from RESFIFO. */
}
result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
return true;
}
/*!
* brief Get the result in conversion FIFOn using blocking method.
*
* param base LPADC peripheral base address.
* param result Pointer to structure variable that keeps the conversion result in conversion FIFOn.
* param index Result FIFO index.
*/
void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result, uint8_t index)
{
assert(result != NULL); /* Check if the input pointer is available. */
uint32_t tmp32 = 0U;
tmp32 = base->RESFIFO[index];
while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
{
tmp32 = base->RESFIFO[index];
}
result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
}
#else
/*!
* brief Get the result in conversion FIFO.
*
* param base LPADC peripheral base address.
* param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
*
* return Status whether FIFO entry is valid.
*/
bool LPADC_GetConvResult(ADC_Type *base, lpadc_conv_result_t *result)
{
assert(result != NULL); /* Check if the input pointer is available. */
uint32_t tmp32 = 0U;
tmp32 = base->RESFIFO;
if (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
{
return false; /* FIFO is empty. Discard any read from RESFIFO. */
}
result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
return true;
}
/*!
* @brief Get the result in conversion FIFO using blocking method.
*
* @param base LPADC peripheral base address.
* @param result Pointer to structure variable that keeps the conversion result in conversion FIFO.
*/
void LPADC_GetConvResultBlocking(ADC_Type *base, lpadc_conv_result_t *result)
{
assert(result != NULL); /* Check if the input pointer is available. */
uint32_t tmp32 = 0U;
tmp32 = base->RESFIFO;
while (ADC_RESFIFO_VALID_MASK != (tmp32 & ADC_RESFIFO_VALID_MASK))
{
tmp32 = base->RESFIFO;
}
result->commandIdSource = (tmp32 & ADC_RESFIFO_CMDSRC_MASK) >> ADC_RESFIFO_CMDSRC_SHIFT;
result->loopCountIndex = (tmp32 & ADC_RESFIFO_LOOPCNT_MASK) >> ADC_RESFIFO_LOOPCNT_SHIFT;
result->triggerIdSource = (tmp32 & ADC_RESFIFO_TSRC_MASK) >> ADC_RESFIFO_TSRC_SHIFT;
result->convValue = (uint16_t)(tmp32 & ADC_RESFIFO_D_MASK);
}
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
/*!
* brief Configure the conversion trigger source.
*
* Each programmable trigger can launch the conversion command in command buffer.
*
* param base LPADC peripheral base address.
* param triggerId ID for each trigger. Typically, the available value range is from 0 to 3.
* param config Pointer to configuration structure. See to #lpadc_conv_trigger_config_t.
*/
void LPADC_SetConvTriggerConfig(ADC_Type *base, uint32_t triggerId, const lpadc_conv_trigger_config_t *config)
{
assert(triggerId < ADC_TCTRL_COUNT); /* Check if the triggerId is available in this device. */
assert(config != NULL); /* Check if the input pointer is available. */
uint32_t tmp32;
tmp32 = ADC_TCTRL_TCMD(config->targetCommandId) /* Trigger command select. */
| ADC_TCTRL_TDLY(config->delayPower) /* Trigger delay select. */
| ADC_TCTRL_TPRI(config->priority) /* Trigger priority setting. */
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
| ADC_TCTRL_FIFO_SEL_A(config->channelAFIFOSelect)
#if !(defined(FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B) && FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B)
| ADC_TCTRL_FIFO_SEL_B(config->channelBFIFOSelect)
#endif /* FSL_FEATURE_LPADC_HAS_NO_TCTRL_FIFO_SEL_B */
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
;
if (config->enableHardwareTrigger)
{
tmp32 |= ADC_TCTRL_HTEN_MASK;
}
base->TCTRL[triggerId] = tmp32;
}
/*!
* brief Gets an available pre-defined settings for trigger's configuration.
*
* This function initializes the trigger's configuration structure with an available settings. The default values are:
* code
* config->targetCommandId = 0U;
* config->delayPower = 0U;
* config->priority = 0U;
* config->channelAFIFOSelect = 0U;
* config->channelBFIFOSelect = 0U;
* config->enableHardwareTrigger = false;
* endcode
* param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConvTriggerConfig(lpadc_conv_trigger_config_t *config)
{
assert(config != NULL); /* Check if the input pointer is available. */
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
config->targetCommandId = 0U;
config->delayPower = 0U;
config->priority = 0U;
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
config->channelAFIFOSelect = 0U;
config->channelBFIFOSelect = 0U;
#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */
config->enableHardwareTrigger = false;
}
/*!
* brief Configure conversion command.
*
* note The number of compare value register on different chips is different, that is mean in some chips, some
* command buffers do not have the compare functionality.
*
* param base LPADC peripheral base address.
* param commandId ID for command in command buffer. Typically, the available value range is 1 - 15.
* param config Pointer to configuration structure. See to #lpadc_conv_command_config_t.
*/
void LPADC_SetConvCommandConfig(ADC_Type *base, uint32_t commandId, const lpadc_conv_command_config_t *config)
{
assert(commandId < (ADC_CMDL_COUNT + 1U)); /* Check if the commandId is available on this device. */
assert(config != NULL); /* Check if the input pointer is available. */
uint32_t tmp32 = 0;
commandId--; /* The available command number are 1-15, while the index of register group are 0-14. */
/* ADCx_CMDL. */
tmp32 = ADC_CMDL_ADCH(config->channelNumber); /* Channel number. */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
tmp32 |= ADC_CMDL_ALTB_ADCH(config->channelBNumber); /* Alternate channel B number. */
#endif
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
tmp32 |= ADC_CMDL_CSCALE(config->sampleScaleMode); /* Full/Part scale input voltage. */
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
tmp32 |= ADC_CMDL_ALTB_CSCALE(config->channelBScaleMode); /* Alternate channel B full/Part scale input voltage. */
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
#if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF
assert(((config->sampleChannelMode >= kLPADC_SampleChannelDiffBothSideAB) &&
(((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
(config->sampleChannelMode < kLPADC_SampleChannelDiffBothSideAB));
#endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_DIFF) && FSL_FEATURE_LPADC_HAS_CMDL_DIFF */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE
assert(((config->sampleChannelMode == kLPADC_SampleChannelDiffBothSide) &&
(((base->VERID) & ADC_VERID_DIFFEN_MASK) != 0U)) ||
((config->sampleChannelMode == kLPADC_SampleChannelDualSingleEndBothSide) &&
(((base->VERID) & ADC_VERID_NUM_SEC_MASK) != 0U)) ||
(config->sampleChannelMode < kLPADC_SampleChannelDualSingleEndBothSide));
#endif /* defined(FSL_FEATURE_LPADC_HAS_CMDL_CTYPE) && FSL_FEATURE_LPADC_HAS_CMDL_CTYPE */
#endif /* !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
tmp32 |= ADC_CMDL_CHANNEL_MODE(config->sampleChannelMode);
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
tmp32 |= ADC_CMDL_MODE(config->conversionResolutionMode);
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
/* Enable alternate channel B.*/
if (config->enableChannelB)
{
tmp32 |= ADC_CMDL_ALTBEN_MASK;
}
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
base->CMD[commandId].CMDL = tmp32;
/* ADCx_CMDH. */
tmp32 = ADC_CMDH_NEXT(config->chainedNextCommandNumber) /* Next Command Select. */
| ADC_CMDH_LOOP(config->loopCount) /* Loop Count Select. */
| ADC_CMDH_AVGS(config->hardwareAverageMode) /* Hardware Average Select. */
| ADC_CMDH_STS(config->sampleTimeMode) /* Sample Time Select. */
| ADC_CMDH_CMPEN(config->hardwareCompareMode); /* Hardware compare enable. */
#if (defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG)
if (config->enableWaitTrigger)
{
tmp32 |= ADC_CMDH_WAIT_TRIG_MASK; /* Wait trigger enable. */
}
#endif /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
if (config->enableAutoChannelIncrement)
{
tmp32 |= ADC_CMDH_LWI_MASK;
}
base->CMD[commandId].CMDH = tmp32;
/* Hardware compare settings.
* Not all Command Buffers have an associated Compare Value register. The compare function is only available on
* Command Buffers that have a corresponding Compare Value register. Therefore, assertion judgment needs to be
* made before setting the CV register.
*/
if ((kLPADC_HardwareCompareDisabled != config->hardwareCompareMode) && (commandId < ADC_CV_COUNT))
{
/* Set CV register. */
base->CV[commandId] = (ADC_CV_CVH(config->hardwareCompareValueHigh) /* Compare value high. */
| ADC_CV_CVL(config->hardwareCompareValueLow)); /* Compare value low. */
}
}
/*!
* brief Gets an available pre-defined settings for conversion command's configuration.
*
* This function initializes the conversion command's configuration structure with an available settings. The default
* values are:
* code
* config->sampleScaleMode = kLPADC_SampleFullScale;
* config->channelBScaleMode = kLPADC_SampleFullScale;
* config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
* config->channelNumber = 0U;
* config->channelBNumber = 0U;
* config->chainedNextCommandNumber = 0U;
* config->enableAutoChannelIncrement = false;
* config->loopCount = 0U;
* config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
* config->sampleTimeMode = kLPADC_SampleTimeADCK3;
* config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
* config->hardwareCompareValueHigh = 0U;
* config->hardwareCompareValueLow = 0U;
* config->conversionResolutionMode = kLPADC_ConversionResolutionStandard;
* config->enableWaitTrigger = false;
* config->enableChannelB = false;
* endcode
* param config Pointer to configuration structure.
*/
void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config)
{
assert(config != NULL); /* Check if the input pointer is available. */
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_CSCALE
config->sampleScaleMode = kLPADC_SampleFullScale;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_CSCALE */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE
config->channelBScaleMode = kLPADC_SampleFullScale;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
config->sampleChannelMode = kLPADC_SampleChannelSingleEndSideA;
config->channelNumber = 0U;
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH) && FSL_FEATURE_LPADC_HAS_CMDL_ALTB_ADCH
config->channelBNumber = 0U;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTB_CSCALE */
config->chainedNextCommandNumber = 0U; /* No next command defined. */
config->enableAutoChannelIncrement = false;
config->loopCount = 0U;
config->hardwareAverageMode = kLPADC_HardwareAverageCount1;
config->sampleTimeMode = kLPADC_SampleTimeADCK3;
config->hardwareCompareMode = kLPADC_HardwareCompareDisabled;
config->hardwareCompareValueHigh = 0U; /* No used. */
config->hardwareCompareValueLow = 0U; /* No used. */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_MODE) && FSL_FEATURE_LPADC_HAS_CMDL_MODE
config->conversionResolutionMode = kLPADC_ConversionResolutionStandard;
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_MODE */
#if defined(FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG) && FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG
config->enableWaitTrigger = false;
#endif /* FSL_FEATURE_LPADC_HAS_CMDH_WAIT_TRIG */
#if defined(FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN) && FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN
config->enableChannelB = false; /* Enable alternate channel B.*/
#endif /* FSL_FEATURE_LPADC_HAS_CMDL_ALTBEN */
}
#if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS
/*!
* brief Enable the calibration function.
*
* When CALOFS is set, the ADC is configured to perform a calibration function anytime the ADC executes
* a conversion. Any channel selected is ignored and the value returned in the RESFIFO is a signed value
* between -31 and 31. -32 is not a valid and is never a returned value. Software should copy the lower 6-
* bits of the conversion result stored in the RESFIFO after a completed calibration conversion to the
* OFSTRIM field. The OFSTRIM field is used in normal operation for offset correction.
*
* param base LPADC peripheral base address.
* param enable switcher to the calibration function.
*/
void LPADC_EnableCalibration(ADC_Type *base, bool enable)
{
LPADC_Enable(base, false);
if (enable)
{
base->CFG |= ADC_CFG_CALOFS_MASK;
}
else
{
base->CFG &= ~ADC_CFG_CALOFS_MASK;
}
LPADC_Enable(base, true);
}
#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM
/*!
* brief Do auto calibration.
*
* Calibration function should be executed before using converter in application. It used the software trigger and a
* dummy conversion, get the offset and write them into the OFSTRIM register. It called some of functional API
* including: -LPADC_EnableCalibration(...) -LPADC_LPADC_SetOffsetValue(...) -LPADC_SetConvCommandConfig(...)
* -LPADC_SetConvTriggerConfig(...)
*
* param base LPADC peripheral base address.
*/
void LPADC_DoAutoCalibration(ADC_Type *base)
{
assert(0u == LPADC_GetConvResultCount(base));
uint32_t mLpadcCMDL;
uint32_t mLpadcCMDH;
uint32_t mLpadcTrigger;
lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct;
lpadc_conv_command_config_t mLpadcCommandConfigStruct;
lpadc_conv_result_t mLpadcResultConfigStruct;
/* Enable the calibration function. */
LPADC_EnableCalibration(base, true);
/* Keep the CMD and TRG state here and restore it later if the calibration completes.*/
mLpadcCMDL = base->CMD[0].CMDL; /* CMD1L. */
mLpadcCMDH = base->CMD[0].CMDH; /* CMD1H. */
mLpadcTrigger = base->TCTRL[0]; /* Trigger0. */
/* Set trigger0 configuration - for software trigger. */
LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct);
mLpadcTriggerConfigStruct.targetCommandId = 1U; /* CMD1 is executed. */
LPADC_SetConvTriggerConfig(base, 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */
/* Set conversion CMD configuration. */
LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct);
mLpadcCommandConfigStruct.hardwareAverageMode = kLPADC_HardwareAverageCount128;
LPADC_SetConvCommandConfig(base, 1U, &mLpadcCommandConfigStruct); /* Set CMD1 configuration. */
/* Do calibration. */
LPADC_DoSoftwareTrigger(base, 1U); /* 1U is trigger0 mask. */
while (!LPADC_GetConvResult(base, &mLpadcResultConfigStruct))
{
}
/* The valid bits of data are bits 14:3 in the RESFIFO register. */
LPADC_SetOffsetValue(base, (uint32_t)(mLpadcResultConfigStruct.convValue) >> 3UL);
/* Disable the calibration function. */
LPADC_EnableCalibration(base, false);
/* restore CMD and TRG registers. */
base->CMD[0].CMDL = mLpadcCMDL; /* CMD1L. */
base->CMD[0].CMDH = mLpadcCMDH; /* CMD1H. */
base->TCTRL[0] = mLpadcTrigger; /* Trigger0. */
}
#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */
#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS
/*!
* brief Do offset calibration.
*
* param base LPADC peripheral base address.
*/
void LPADC_DoOffsetCalibration(ADC_Type *base)
{
LPADC_EnableOffsetCalibration(base, true);
while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
{
}
}
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ
/*!
* brief Do auto calibration.
*
* param base LPADC peripheral base address.
*/
void LPADC_DoAutoCalibration(ADC_Type *base)
{
LPADC_PrepareAutoCalibration(base);
LPADC_FinishAutoCalibration(base);
}
/*!
* brief Prepare auto calibration, LPADC_FinishAutoCalibration has to be called before using the LPADC.
* LPADC_DoAutoCalibration has been split in two API to avoid to be stuck too long in the function.
*
* param base LPADC peripheral base address.
*/
void LPADC_PrepareAutoCalibration(ADC_Type *base)
{
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2))
assert((0U == LPADC_GetConvResultCount(base, 0)) && (0U == LPADC_GetConvResultCount(base, 1)));
#else /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 1)) */
assert(LPADC_GetConvResultCount(base) == 0U);
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2)) */
/* Request gain calibration. */
base->CTRL |= ADC_CTRL_CAL_REQ_MASK;
}
/*!
* brief Finish auto calibration start with LPADC_PrepareAutoCalibration.
*
* param base LPADC peripheral base address.
*/
void LPADC_FinishAutoCalibration(ADC_Type *base)
{
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
int32_t GCCa;
int32_t GCCb;
float GCRa;
float GCRb;
#else
uint32_t GCCa;
float GCRa;
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
uint32_t GCCb;
float GCRb;
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
while ((ADC_GCC_RDY_MASK != (base->GCC[0] & ADC_GCC_RDY_MASK))
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
|| (ADC_GCC_RDY_MASK != (base->GCC[1] & ADC_GCC_RDY_MASK))
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
)
{
}
#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE
GCCa = (int32_t)(base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
GCCb = (int32_t)(base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
if (0U != ((base->GCC[0]) & 0x8000U))
{
GCCa = GCCa - 0x10000;
GCRa = (float)((131072.0) /
(131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
base->GCR[0] = LPADC_GetGainConvResult(GCRa); /* write A side GCALR. */
}
if (0U != ((base->GCC[1]) & 0x8000U))
{
GCCb = GCCb - 0x10000;
GCRb = (float)((131072.0) /
(131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
base->GCR[1] = LPADC_GetGainConvResult(GCRb); /* write B side GCALR. */
}
#else
/* Calculate gain offset. */
GCCa = (base->GCC[0] & ADC_GCC_GAIN_CAL_MASK);
GCRa = (float)((131072.0) /
(131072.0 - (double)GCCa)); /* Gain_CalA = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[0]))*/
base->GCR[0] = LPADC_GetGainConvResult(GCRa); /* write A side GCALR. */
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
GCCb = (base->GCC[1] & ADC_GCC_GAIN_CAL_MASK);
GCRb = (float)((131072.0) /
(131072.0 - (double)GCCb)); /* Gain_CalB = (131072.0 / (131072-(ADC_GCC_GAIN_CAL(ADC->GCC[1]))*/
base->GCR[1] = LPADC_GetGainConvResult(GCRb); /* write B side GCALR. */
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFSMODE */
/* Indicate the values are valid. */
base->GCR[0] |= ADC_GCR_RDY_MASK;
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
base->GCR[1] |= ADC_GCR_RDY_MASK;
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
{
}
}
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
/*!
* brief Get calibration value into the memory which is defined by invoker.
*
* note Please note the ADC will be disabled temporary.
* note This function should be used after finish calibration.
*
* param base LPADC peripheral base address.
* param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure, this memory block should be always powered
* on even in low power modes.
*/
void LPADC_GetCalibrationValue(ADC_Type *base, lpadc_calibration_value_t *ptrCalibrationValue)
{
assert(ptrCalibrationValue != NULL);
bool adcEnabled = false;
/* Check if ADC is enabled. */
if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
{
LPADC_Enable(base, false);
adcEnabled = true;
}
#if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
uint32_t i;
for (i = 0UL; i < 33UL; i++)
{
#if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
ptrCalibrationValue->generalCalibrationValueA[i] =
(uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR0))) + i)) & 0xFFFFU);
#if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
ptrCalibrationValue->generalCalibrationValueB[i] =
(uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR0))) + i)) & 0xFFFFU);
#endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
#else
ptrCalibrationValue->generalCalibrationValueA[i] =
(uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i)) & 0xFFFFU);
#if !(defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U))
ptrCalibrationValue->generalCalibrationValueB[i] =
(uint16_t)((*(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i)) & 0xFFFFU);
#endif /* (defined(FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS) && (FSL_FEATURE_LPADC_HAS_B_SIDE_CHANNELS == 0U)) */
#endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
}
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
ptrCalibrationValue->gainCalibrationResultA = (uint16_t)(base->GCR[0] & ADC_GCR_GCALR_MASK);
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
ptrCalibrationValue->gainCalibrationResultB = (uint16_t)(base->GCR[1] & ADC_GCR_GCALR_MASK);
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
if (adcEnabled)
{
LPADC_Enable(base, true);
}
}
/*!
* brief Set calibration value into ADC calibration registers.
*
* note Please note the ADC will be disabled temporary.
*
* param base LPADC peripheral base address.
* param ptrCalibrationValue Pointer to lpadc_calibration_value_t structure which contains ADC's calibration value.
*/
void LPADC_SetCalibrationValue(ADC_Type *base, const lpadc_calibration_value_t *ptrCalibrationValue)
{
assert(ptrCalibrationValue != NULL);
bool adcEnabled = false;
/* Check if ADC is enabled. */
if ((base->CTRL & ADC_CTRL_ADCEN_MASK) != 0UL)
{
LPADC_Enable(base, false);
adcEnabled = true;
}
#if (defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ)
for (uint32_t i = 0UL; i < 33UL; i++)
{
#if defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK)
*(((volatile uint32_t *)(&(base->CAL_GAR0))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
*(((volatile uint32_t *)(&(base->CAL_GBR0))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
#else
*(((volatile uint32_t *)(&(base->CAL_GAR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueA[i];
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
*(((volatile uint32_t *)(&(base->CAL_GBR[0]))) + i) = ptrCalibrationValue->generalCalibrationValueB[i];
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
#endif /* defined(ADC_CAL_GAR0_CAL_GAR_VAL_MASK) */
}
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */
base->GCR[0] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultA) | ADC_GCR_RDY_MASK;
#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U))
base->GCR[1] = ADC_GCR_GCALR(ptrCalibrationValue->gainCalibrationResultB) | ADC_GCR_RDY_MASK;
#endif /* (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) */
/*
* $Branch Coverage Justification$
* while ((base->STAT & ADC_STAT_CAL_RDY_MASK) == ADC_STAT_CAL_RDY_MASK) not covered. Test unfeasible,
* the calibration ready state is too short not to catch.
*/
while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK))
{
}
if (adcEnabled)
{
LPADC_Enable(base, true);
}
}
#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,372 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2019, 2023 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpcmp.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpcmp"
#endif
#if defined(LPCMP_RSTS)
#define LPCMP_RESETS_ARRAY LPCMP_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(LPCMP_CLOCKS)
/*!
* @brief Get instance number for LPCMP module.
*
* @param base LPCMP peripheral base address
*/
static uint32_t LPCMP_GetInstance(LPCMP_Type *base);
#endif /* LPCMP_CLOCKS */
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(LPCMP_CLOCKS)
/*! @brief Pointers to LPCMP bases for each instance. */
static LPCMP_Type *const s_lpcmpBases[] = LPCMP_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to LPCMP clocks for each instance. */
static const clock_ip_name_t s_lpcmpClocks[] = LPCMP_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPCMP_CLOCKS */
#if defined(LPCMP_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_lpcmpResets[] = LPCMP_RESETS_ARRAY;
#endif
/*******************************************************************************
* Codes
******************************************************************************/
#if defined(LPCMP_CLOCKS)
static uint32_t LPCMP_GetInstance(LPCMP_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
/*
* $Branch Coverage Justification$
* (instance >= ARRAY_SIZE(s_lpcmpBases)) not covered. The peripheral base
* address is always valid and checked by assert.
*/
for (instance = 0; instance < ARRAY_SIZE(s_lpcmpBases); instance++)
{
/*
* $Branch Coverage Justification$
* (s_lpcmpBases[instance] != base) not covered. The peripheral base
* address is always valid and checked by assert.
*/
if (s_lpcmpBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lpcmpBases));
return instance;
}
#endif /* LPCMP_CLOCKS */
/*!
* brief Initialize the LPCMP
*
* This function initializes the LPCMP module. The operations included are:
* - Enabling the clock for LPCMP module.
* - Configuring the comparator.
* - Enabling the LPCMP module.
* Note: For some devices, multiple LPCMP instance share the same clock gate. In this case, to enable the clock for
* any instance enables all the LPCMPs. Check the chip reference manual for the clock assignment of the LPCMP.
*
* param base LPCMP peripheral base address.
* param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_Init(LPCMP_Type *base, const lpcmp_config_t *config)
{
assert(config != NULL);
uint32_t tmp32;
#if defined(LPCMP_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_lpcmpClocks[LPCMP_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPCMP_CLOCKS */
#if defined(LPCMP_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_lpcmpResets[LPCMP_GetInstance(base)]);
#endif
/* Configure. */
LPCMP_Enable(base, false);
#if !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN)
/* CCR0 register. */
#if defined(FSL_FEATURE_LPCMP_INSTANCE_SUPPORT_CCR0_CMP_STOP_ENn)
if (1U == FSL_FEATURE_LPCMP_INSTANCE_SUPPORT_CCR0_CMP_STOP_ENn(base))
#endif /* FSL_FEATURE_LPCMP_INSTANCE_SUPPORT_CCR0_CMP_STOP_ENn */
{
if (config->enableStopMode)
{
base->CCR0 |= LPCMP_CCR0_CMP_STOP_EN_MASK;
}
else
{
base->CCR0 &= ~LPCMP_CCR0_CMP_STOP_EN_MASK;
}
}
#endif /* !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) */
/* CCR1 register. */
tmp32 = (base->CCR1 & (~(LPCMP_CCR1_COUT_PEN_MASK | LPCMP_CCR1_COUT_SEL_MASK | LPCMP_CCR1_COUT_INV_MASK
#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL
| LPCMP_CCR1_FUNC_CLK_SEL_MASK
#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */
)));
if (config->enableOutputPin)
{
tmp32 |= LPCMP_CCR1_COUT_PEN_MASK;
}
if (config->useUnfilteredOutput)
{
tmp32 |= LPCMP_CCR1_COUT_SEL_MASK;
}
if (config->enableInvertOutput)
{
tmp32 |= LPCMP_CCR1_COUT_INV_MASK;
}
#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL
tmp32 |= LPCMP_CCR1_FUNC_CLK_SEL(config->functionalSourceClock);
#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */
base->CCR1 = tmp32;
/* CCR2 register. */
tmp32 = base->CCR2 & ~(LPCMP_CCR2_HYSTCTR_MASK | LPCMP_CCR2_CMP_NPMD_MASK | LPCMP_CCR2_CMP_HPMD_MASK);
tmp32 |= LPCMP_CCR2_HYSTCTR(config->hysteresisMode);
tmp32 |= ((uint32_t)(config->powerMode) << LPCMP_CCR2_CMP_HPMD_SHIFT);
base->CCR2 = tmp32;
LPCMP_Enable(base, true); /* Enable the LPCMP module. */
}
/*!
* brief De-initializes the LPCMP module.
*
* This function de-initializes the LPCMP module. The operations included are:
* - Disabling the LPCMP module.
* - Disabling the clock for LPCMP module.
*
* This function disables the clock for the LPCMP.
* Note: For some devices, multiple LPCMP instance shares the same clock gate. In this case, before disabling the
* clock for the LPCMP, ensure that all the LPCMP instances are not used.
*
* param base LPCMP peripheral base address.
*/
void LPCMP_Deinit(LPCMP_Type *base)
{
/* Disable the LPCMP module. */
LPCMP_Enable(base, false);
#if defined(LPCMP_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_lpcmpClocks[LPCMP_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPCMP_CLOCKS */
}
/*!
* brief Gets an available pre-defined settings for the comparator's configuration.
*
* This function initializes the comparator configuration structure to these default values:
* code
* config->enableStopMode = false;
* config->enableOutputPin = false;
* config->useUnfilteredOutput = false;
* config->enableInvertOutput = false;
* config->hysteresisMode = kLPCMP_HysteresisLevel0;
* config->powerMode = kLPCMP_LowSpeedPowerMode;
* config->functionalSourceClock = kLPCMP_FunctionalClockSource0;
* endcode
* param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_GetDefaultConfig(lpcmp_config_t *config)
{
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
#if !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN)
config->enableStopMode = false;
#endif /* !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) */
config->enableOutputPin = false;
config->useUnfilteredOutput = false;
config->enableInvertOutput = false;
config->hysteresisMode = kLPCMP_HysteresisLevel0;
config->powerMode = kLPCMP_LowSpeedPowerMode;
#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL
config->functionalSourceClock = kLPCMP_FunctionalClockSource0;
#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */
}
/*!
* brief Select the input channels for LPCMP. This function determines which input
* is selected for the negative and positive mux.
*
* param base LPCMP peripheral base address.
* param positiveChannel Positive side input channel number.
* param negativeChannel Negative side input channel number.
*/
void LPCMP_SetInputChannels(LPCMP_Type *base, uint32_t positiveChannel, uint32_t negativeChannel)
{
uint32_t tmp32;
tmp32 = base->CCR2 & ~(LPCMP_CCR2_PSEL_MASK | LPCMP_CCR2_MSEL_MASK);
tmp32 |= LPCMP_CCR2_PSEL(positiveChannel) | LPCMP_CCR2_MSEL(negativeChannel);
base->CCR2 = tmp32;
}
/*!
* brief Configures the filter.
*
* param base LPCMP peripheral base address.
* param config Pointer to "lpcmp_filter_config_t" structure.
*/
void LPCMP_SetFilterConfig(LPCMP_Type *base, const lpcmp_filter_config_t *config)
{
assert(config != NULL);
uint32_t tmp32;
tmp32 = base->CCR1 & ~(LPCMP_CCR1_FILT_PER_MASK | LPCMP_CCR1_FILT_CNT_MASK | LPCMP_CCR1_SAMPLE_EN_MASK);
if (config->enableSample)
{
tmp32 |= LPCMP_CCR1_SAMPLE_EN_MASK;
}
tmp32 |= LPCMP_CCR1_FILT_PER(config->filterSamplePeriod) | LPCMP_CCR1_FILT_CNT(config->filterSampleCount);
base->CCR1 = tmp32;
}
/*!
* brief Configure the internal DAC module.
*
* param base LPCMP peripheral base address.
* param config Pointer to "lpcmp_dac_config_t" structure. If config is "NULL", disable internal DAC.
*/
void LPCMP_SetDACConfig(LPCMP_Type *base, const lpcmp_dac_config_t *config)
{
uint32_t tmp32;
if (config == NULL)
{
tmp32 = 0U; /* Disable internal DAC. */
}
else
{
tmp32 = LPCMP_DCR_VRSEL(config->referenceVoltageSource) | LPCMP_DCR_DAC_DATA(config->DACValue);
if (config->enableLowPowerMode)
{
tmp32 |= LPCMP_DCR_DAC_HPMD_MASK;
}
tmp32 |= LPCMP_DCR_DAC_EN_MASK;
}
base->DCR = tmp32;
}
#if defined(FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL) && FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL
/*!
* @brief Configure the window control, users can use this API to implement operations on the window,
* such as inverting the window signal, setting the window closing event(only valid in windowing mode),
* and setting the COUTA signal after the window is closed(only valid in windowing mode).
*
* @param base LPCMP peripheral base address.
* @param config Pointer "lpcmp_window_control_config_t" structure.
*/
void LPCMP_SetWindowControl(LPCMP_Type *base, const lpcmp_window_control_config_t *config)
{
assert(config != NULL);
uint32_t tmp32 = 0UL;
tmp32 = (base->CCR1 & (~(LPCMP_CCR1_COUTA_CFG_MASK | LPCMP_CCR1_EVT_SEL_CFG_MASK | LPCMP_CCR1_WINDOW_INV_MASK)));
if (config->enableInvertWindowSignal)
{
tmp32 |= LPCMP_CCR1_WINDOW_INV_MASK;
}
/* Set COUT event, which can close the active window in window mode. */
tmp32 |= LPCMP_CCR1_EVT_SEL_CFG(config->closeWindowEvent);
/* Set the COUTA signal value when the window is closed. */
tmp32 |= LPCMP_CCR1_COUTA_CFG(config->COUTASignal);
base->CCR1 = tmp32;
}
#endif /* FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL */
#if defined(FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE) && FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE
/*!
* @brief Configure the roundrobin mode.
*
* @param base LPCMP peripheral base address.
* @param config Pointer "lpcmp_roundrobin_config_t" structure.
*/
void LPCMP_SetRoundRobinConfig(LPCMP_Type *base, const lpcmp_roundrobin_config_t *config)
{
assert(config != NULL);
uint32_t tmp32 = 0UL;
/* LPCMPx_RRCR0 register, Configuration options for the round-robin operation. */
tmp32 = (base->RRCR0 &
(~(LPCMP_RRCR0_RR_TRG_SEL_MASK | LPCMP_RRCR0_RR_NSAM_MASK | LPCMP_RRCR0_RR_CLK_SEL_MASK |
LPCMP_RRCR0_RR_INITMOD_MASK | LPCMP_RRCR0_RR_SAMPLE_CNT_MASK | LPCMP_RRCR0_RR_SAMPLE_THRESHOLD_MASK)));
tmp32 |=
(LPCMP_RRCR0_RR_TRG_SEL(config->roundrobinTriggerSource) | LPCMP_RRCR0_RR_NSAM(config->sampleClockNumbers) |
LPCMP_RRCR0_RR_CLK_SEL(config->roundrobinClockSource) | LPCMP_RRCR0_RR_INITMOD(config->initDelayModules) |
LPCMP_RRCR0_RR_SAMPLE_CNT(config->channelSampleNumbers) |
LPCMP_RRCR0_RR_SAMPLE_THRESHOLD(config->sampleTimeThreshhold));
base->RRCR0 = tmp32;
/* LPCMPx_RRCR1 register, Configure the fix port, fix channel and checker channel. */
tmp32 =
(base->RRCR1 & (~(LPCMP_RRCR1_FIXP_MASK | LPCMP_RRCR1_FIXCH_MASK | (0xFFUL << LPCMP_RRCR1_RR_CH0EN_SHIFT))));
tmp32 |= (LPCMP_RRCR1_FIXP(config->fixedMuxPort) | LPCMP_RRCR1_FIXCH(config->fixedChannel) |
((uint32_t)(config->checkerChannelMask) << LPCMP_RRCR1_RR_CH0EN_SHIFT));
base->RRCR1 = tmp32;
}
/*!
* brief Configure the roundrobin internal timer reload value.
*
* param base LPCMP peripheral base address.
* param value RoundRobin internal timer reload value, allowed range:0x0UL-0xFFFFFFFUL.
*/
void LPCMP_SetRoundRobinInternalTimer(LPCMP_Type *base, uint32_t value)
{
uint32_t tmp32 = 0UL;
tmp32 = (base->RRCR2 & (~LPCMP_RRCR2_RR_TIMER_RELOAD_MASK));
tmp32 |= LPCMP_RRCR2_RR_TIMER_RELOAD(value);
base->RRCR2 = tmp32;
}
#endif /* FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE */

View File

@ -0,0 +1,585 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2020, 2023-2024 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_LPCMP_H_
#define FSL_LPCMP_H_
#include "fsl_common.h"
/*!
* @addtogroup lpcmp
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief LPCMP driver version 2.1.3. */
#define FSL_LPCMP_DRIVER_VERSION (MAKE_VERSION(2, 1, 3))
/*! @} */
#define LPCMP_CCR1_COUTA_CFG_MASK (LPCMP_CCR1_COUTA_OWEN_MASK | LPCMP_CCR1_COUTA_OW_MASK)
#define LPCMP_CCR1_COUTA_CFG_SHIFT LPCMP_CCR1_COUTA_OWEN_SHIFT
#define LPCMP_CCR1_COUTA_CFG(x) \
(((uint32_t)(((uint32_t)(x)) << LPCMP_CCR1_COUTA_CFG_SHIFT)) & LPCMP_CCR1_COUTA_CFG_MASK)
#define LPCMP_CCR1_EVT_SEL_CFG_MASK (LPCMP_CCR1_EVT_SEL_MASK | LPCMP_CCR1_WINDOW_CLS_MASK)
#define LPCMP_CCR1_EVT_SEL_CFG_SHIFT LPCMP_CCR1_WINDOW_CLS_SHIFT
#define LPCMP_CCR1_EVT_SEL_CFG(x) \
(((uint32_t)(((uint32_t)(x)) << LPCMP_CCR1_EVT_SEL_CFG_SHIFT)) & LPCMP_CCR1_EVT_SEL_CFG_MASK)
/*!
* @brief LPCMP status falgs mask.
*/
enum _lpcmp_status_flags
{
kLPCMP_OutputRisingEventFlag = LPCMP_CSR_CFR_MASK, /*!< Rising-edge on the comparison output has occurred. */
kLPCMP_OutputFallingEventFlag = LPCMP_CSR_CFF_MASK, /*!< Falling-edge on the comparison output has occurred. */
#if defined(FSL_FEATURE_LPCMP_HAS_CSR_RRF) && FSL_FEATURE_LPCMP_HAS_CSR_RRF
kLPCMP_OutputRoundRobinEventFlag = LPCMP_CSR_RRF_MASK, /*!< Detects when any channel's last comparison result is
different from the pre-set value in trigger mode. */
#endif /* FSL_FEATURE_LPCMP_HAS_CSR_RRF */
kLPCMP_OutputAssertEventFlag = LPCMP_CSR_COUT_MASK, /*!< Return the current value of the analog comparator output.
The flag does not support W1C. */
};
/*!
* @brief LPCMP interrupt enable/disable mask.
*/
enum _lpcmp_interrupt_enable
{
kLPCMP_OutputRisingInterruptEnable = LPCMP_IER_CFR_IE_MASK, /*!< Comparator interrupt enable rising. */
kLPCMP_OutputFallingInterruptEnable = LPCMP_IER_CFF_IE_MASK, /*!< Comparator interrupt enable falling. */
#if defined(FSL_FEATURE_LPCMP_HAS_IER_RRF_IE) && FSL_FEATURE_LPCMP_HAS_IER_RRF_IE
kLPCMP_RoundRobinInterruptEnable = LPCMP_IER_RRF_IE_MASK, /*!< Comparator round robin mode interrupt
occurred when the comparison result changes for a given channel. */
#endif /* FSL_FEATURE_LPCMP_HAS_IER_RRF_IE */
};
/*!
* @brief LPCMP hysteresis mode. See chip data sheet to get the actual hystersis
* value with each level
*/
typedef enum _lpcmp_hysteresis_mode
{
kLPCMP_HysteresisLevel0 = 0U, /*!< The hard block output has level 0 hysteresis internally. */
kLPCMP_HysteresisLevel1 = 1U, /*!< The hard block output has level 1 hysteresis internally. */
kLPCMP_HysteresisLevel2 = 2U, /*!< The hard block output has level 2 hysteresis internally. */
kLPCMP_HysteresisLevel3 = 3U, /*!< The hard block output has level 3 hysteresis internally. */
} lpcmp_hysteresis_mode_t;
/*!
* @brief LPCMP nano mode.
*/
typedef enum _lpcmp_power_mode
{
kLPCMP_LowSpeedPowerMode = 0U, /*!< Low speed comparison mode is selected. */
kLPCMP_HighSpeedPowerMode = 1U, /*!< High speed comparison mode is selected. */
kLPCMP_NanoPowerMode = 2U, /*!< Nano power comparator is enabled. */
} lpcmp_power_mode_t;
/*!
* @brief Internal DAC reference voltage source.
*/
typedef enum _lpcmp_dac_reference_voltage_source
{
kLPCMP_VrefSourceVin1 = 0U, /*!< vrefh_int is selected as resistor ladder network supply reference Vin. */
kLPCMP_VrefSourceVin2 = 1U, /*!< vrefh_ext is selected as resistor ladder network supply reference Vin. */
} lpcmp_dac_reference_voltage_source_t;
#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL
/*!
* @brief LPCMP functional mode clock source selection.
*
* Note: In different devices, the functional mode clock source selection is different,
* please refer to specific device Reference Manual for details.
*/
typedef enum _lpcmp_functional_source_clock
{
kLPCMP_FunctionalClockSource0 = 0U, /*!< Select functional mode clock source0. */
kLPCMP_FunctionalClockSource1 = 1U, /*!< Select functional mode clock source1. */
kLPCMP_FunctionalClockSource2 = 2U, /*!< Select functional mode clock source2. */
kLPCMP_FunctionalClockSource3 = 3U, /*!< Select functional mode clock source3. */
} lpcmp_functional_source_clock_t;
#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */
#if defined(FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL) && FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL
/*!
* @brief Set the COUTA signal value when the window is closed.
*/
typedef enum _lpcmp_couta_signal
{
kLPCMP_COUTASignalNoSet = 0U, /*!< NO set the COUTA signal value when the window is closed. */
kLPCMP_COUTASignalLow = 1U, /*!< Set COUTA signal low(0) when the window is closed. */
kLPCMP_COUTASignalHigh = 3U, /*!< Set COUTA signal high(1) when the window is closed. */
} lpcmp_couta_signal_t;
/*!
* @brief Set COUT event, which can close the active window in window mode.
*/
typedef enum _lpcmp_close_window_event
{
kLPCMP_CLoseWindowEventNoSet = 0U, /*!< No Set COUT event, which can close the active window in window mode. */
kLPCMP_CloseWindowEventRisingEdge = 1U, /*!< Set rising edge COUT signal as COUT event. */
kLPCMP_CloseWindowEventFallingEdge = 3U, /*!< Set falling edge COUT signal as COUT event. */
kLPCMP_CLoseWindowEventBothEdge = 5U, /*!< Set both rising and falling edge COUT signal as COUT event. */
} lpcmp_close_window_event_t;
#endif /* FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL */
#if defined(FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE) && FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE
/*!
* @brief LPCMP round robin mode fixed mux port.
*/
typedef enum _lpcmp_roundrobin_fixedmuxport
{
kLPCMP_FixedPlusMuxPort = 0U, /*!< Fixed plus mux port. */
kLPCMP_FixedMinusMuxPort = 1U, /*!< Fixed minus mux port. */
} lpcmp_roundrobin_fixedmuxport_t;
/*!
* @brief LPCMP round robin mode clock source selection.
*
* Note: In different devices,the round robin mode clock source selection is different,
* please refer to the specific device Reference Manual for details.
*/
typedef enum _lpcmp_roundrobin_clock_source
{
kLPCMP_RoundRobinClockSource0 = 0U, /*!< Select roundrobin mode clock source0. */
kLPCMP_RoundRobinClockSource1 = 1U, /*!< Select roundrobin mode clock source1. */
kLPCMP_RoundRobinClockSource2 = 2U, /*!< Select roundrobin mode clock source2. */
kLPCMP_RoundRobinClockSource3 = 3U, /*!< Select roundrobin mode clock source3. */
} lpcmp_roundrobin_clock_source_t;
/*!
* @brief LPCMP round robin mode trigger source.
*/
typedef enum _lpcmp_roundrobin_trigger_source
{
kLPCMP_TriggerSourceExternally = 0U, /*!< Select external trigger source. */
kLPCMP_TriggerSourceInternally = 1U, /*!< Select internal trigger source. */
} lpcmp_roundrobin_trigger_source_t;
#endif /* FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE */
/*!
* @brief Configure the filter.
*/
typedef struct _lpcmp_filter_config
{
bool enableSample; /*!< Decide whether to use the external SAMPLE as a sampling clock input. */
uint8_t filterSampleCount; /*!< Filter Sample Count. Available range is 1-7; 0 disables the filter. */
uint8_t filterSamplePeriod; /*!< Filter Sample Period. The divider to the bus clock. Available range is 0-255. The
sampling clock must be at least 4 times slower than the system clock to the comparator.
So if enableSample is "false", filterSamplePeriod should be set greater than 4.*/
} lpcmp_filter_config_t;
/*!
* @brief configure the internal DAC.
*/
typedef struct _lpcmp_dac_config
{
bool enableLowPowerMode; /*!< Decide whether to enable DAC low power mode. */
lpcmp_dac_reference_voltage_source_t referenceVoltageSource; /*!< Internal DAC supply voltage reference source. */
uint8_t DACValue; /*!< Value for the DAC Output Voltage. Different devices has different available range,
for specific values, please refer to the reference manual.*/
} lpcmp_dac_config_t;
/*!
* @brief Configures the comparator.
*/
typedef struct _lpcmp_config
{
#if !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN)
bool enableStopMode; /*!< Decide whether to enable the comparator when in STOP modes. */
#endif /* !(defined(FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) && FSL_FEATURE_LPCMP_HAS_NO_CCR0_CMP_STOP_EN) */
bool enableOutputPin; /*!< Decide whether to enable the comparator is available in selected pin. */
bool useUnfilteredOutput; /*!< Decide whether to use unfiltered output. */
bool enableInvertOutput; /*!< Decide whether to inverts the comparator output. */
lpcmp_hysteresis_mode_t hysteresisMode; /*!< LPCMP hysteresis mode. */
lpcmp_power_mode_t powerMode; /*!< LPCMP power mode. */
#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL
lpcmp_functional_source_clock_t functionalSourceClock; /*!< Select LPCMP functional mode clock source. */
#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */
} lpcmp_config_t;
#if defined(FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL) && FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL
/*!
* @brief Configure the window mode control.
*/
typedef struct _lpcmp_window_control_config
{
bool enableInvertWindowSignal; /*!< True: enable invert window signal, False: disable invert window signal. */
lpcmp_couta_signal_t COUTASignal; /*!< Decide whether to define the COUTA signal value when the window is closed. */
lpcmp_close_window_event_t closeWindowEvent; /*!< Decide whether to select COUT event signal edge defines
a COUT event to close window. */
} lpcmp_window_control_config_t;
#endif /* FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL */
#if defined(FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE) && FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE
/*!
* @brief Configure the round robin mode.
*/
typedef struct _lpcmp_roundrobin_config
{
uint8_t initDelayModules; /*!< Comparator and DAC initialization delay modulus, See Reference Manual and DataSheet
for specific value. */
uint8_t sampleClockNumbers; /*!< Specify the number of the round robin clock cycles(0~3) to wait after scanning the
active channel before sampling the channel's comparison result. */
uint8_t channelSampleNumbers; /*!< Specify the number of samples for one channel, note that channelSampleNumbers
must not smaller than sampleTimeThreshhold. */
uint8_t sampleTimeThreshhold; /*!< Specify that for one channel, when (sampleTimeThreshhold + 1) sample results are
"1",the final result is "1", otherwise the final result is "0", note that the
sampleTimeThreshhold must not be larger than channelSampleNumbers. */
lpcmp_roundrobin_clock_source_t roundrobinClockSource; /*!< Decide which clock source to
choose in round robin mode. */
lpcmp_roundrobin_trigger_source_t roundrobinTriggerSource; /*!< Decide which trigger source to
choose in round robin mode. */
lpcmp_roundrobin_fixedmuxport_t fixedMuxPort; /*!< Decide which mux port to choose as
fixed channel in round robin mode. */
uint8_t fixedChannel; /*!< Indicate which channel of the fixed mux port is used in round robin mode. */
uint8_t checkerChannelMask; /*!< Indicate which channel of the non-fixed mux port to check its voltage value in
round robin mode, for example, if checkerChannelMask set to 0x11U means select
channel 0 and channel 4 as checker channel.*/
} lpcmp_roundrobin_config_t;
#endif /* FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and configuration
* @{
*/
/*!
* @brief Initialize the LPCMP
*
* This function initializes the LPCMP module. The operations included are:
* - Enabling the clock for LPCMP module.
* - Configuring the comparator.
* - Enabling the LPCMP module.
* Note: For some devices, multiple LPCMP instance share the same clock gate. In this case, to enable the clock for
* any instance enables all the LPCMPs. Check the chip reference manual for the clock assignment of the LPCMP.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_Init(LPCMP_Type *base, const lpcmp_config_t *config);
/*!
* @brief De-initializes the LPCMP module.
*
* This function de-initializes the LPCMP module. The operations included are:
* - Disabling the LPCMP module.
* - Disabling the clock for LPCMP module.
*
* This function disables the clock for the LPCMP.
* Note: For some devices, multiple LPCMP instance shares the same clock gate. In this case, before disabling the
* clock for the LPCMP, ensure that all the LPCMP instances are not used.
*
* @param base LPCMP peripheral base address.
*/
void LPCMP_Deinit(LPCMP_Type *base);
/*!
* @brief Gets an available pre-defined settings for the comparator's configuration.
*
* This function initializes the comparator configuration structure to these default values:
* @code
* config->enableStopMode = false;
* config->enableOutputPin = false;
* config->useUnfilteredOutput = false;
* config->enableInvertOutput = false;
* config->hysteresisMode = kLPCMP_HysteresisLevel0;
* config->powerMode = kLPCMP_LowSpeedPowerMode;
* config->functionalSourceClock = kLPCMP_FunctionalClockSource0;
* @endcode
* @param config Pointer to "lpcmp_config_t" structure.
*/
void LPCMP_GetDefaultConfig(lpcmp_config_t *config);
/*!
* @brief Enable/Disable LPCMP module.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable the module, and "false" means disable the module.
*/
static inline void LPCMP_Enable(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR0 |= LPCMP_CCR0_CMP_EN_MASK;
}
else
{
base->CCR0 &= ~LPCMP_CCR0_CMP_EN_MASK;
}
}
/*!
* @brief Select the input channels for LPCMP. This function determines which input
* is selected for the negative and positive mux.
*
* @param base LPCMP peripheral base address.
* @param positiveChannel Positive side input channel number. Available range is 0-7.
* @param negativeChannel Negative side input channel number. Available range is 0-7.
*/
void LPCMP_SetInputChannels(LPCMP_Type *base, uint32_t positiveChannel, uint32_t negativeChannel);
/*!
* @brief Enables/disables the DMA request for rising/falling events.
* Normally, the LPCMP generates a CPU interrupt if there is a rising/falling event. When
* DMA support is enabled and the rising/falling interrupt is enabled , the rising/falling
* event forces a DMA transfer request rather than a CPU interrupt instead.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable DMA support, and "false" means disable DMA support.
*/
static inline void LPCMP_EnableDMA(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR1 |= LPCMP_CCR1_DMA_EN_MASK;
}
else
{
base->CCR1 &= ~LPCMP_CCR1_DMA_EN_MASK;
}
}
/*!
* @brief Configures the filter.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_filter_config_t" structure.
*/
void LPCMP_SetFilterConfig(LPCMP_Type *base, const lpcmp_filter_config_t *config);
/*!
* @brief Configure the internal DAC module.
*
* @param base LPCMP peripheral base address.
* @param config Pointer to "lpcmp_dac_config_t" structure. If config is "NULL", disable internal DAC.
*/
void LPCMP_SetDACConfig(LPCMP_Type *base, const lpcmp_dac_config_t *config);
/*!
* @brief Enable the interrupts.
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for interrupts. See "_lpcmp_interrupt_enable".
*/
static inline void LPCMP_EnableInterrupts(LPCMP_Type *base, uint32_t mask)
{
base->IER |= mask;
}
/*!
* @brief Disable the interrupts.
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for interrupts. See "_lpcmp_interrupt_enable".
*/
static inline void LPCMP_DisableInterrupts(LPCMP_Type *base, uint32_t mask)
{
base->IER &= ~mask;
}
/*!
* @brief Get the LPCMP status flags.
*
* @param base LPCMP peripheral base address.
*
* @return Mask value for the asserted flags. See "_lpcmp_status_flags".
*/
static inline uint32_t LPCMP_GetStatusFlags(LPCMP_Type *base)
{
return base->CSR;
}
/*!
* @brief Clear the LPCMP status flags
*
* @param base LPCMP peripheral base address.
* @param mask Mask value for the flags. See "_lpcmp_status_flags".
*/
static inline void LPCMP_ClearStatusFlags(LPCMP_Type *base, uint32_t mask)
{
base->CSR = mask;
}
/*! @} */
/*!
* @name Window mode
* @{
*/
/*!
* @brief Enable/Disable window mode.When any windowed mode is active, COUTA is clocked by
* the bus clock whenever WINDOW = 1. The last latched value is held when WINDOW = 0.
* The optionally inverted comparator output COUT_RAW is sampled on every bus clock
* when WINDOW=1 to generate COUTA.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable window mode, and "false" means disable window mode.
*/
static inline void LPCMP_EnableWindowMode(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->CCR1 |= LPCMP_CCR1_WINDOW_EN_MASK;
}
else
{
base->CCR1 &= ~LPCMP_CCR1_WINDOW_EN_MASK;
}
}
#if defined(FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL) && FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL
/*!
* @brief Configure the window control, users can use this API to implement operations on the window,
* such as inverting the window signal, setting the window closing event(only valid in windowing mode),
* and setting the COUTA signal after the window is closed(only valid in windowing mode).
*
* @param base LPCMP peripheral base address.
* @param config Pointer "lpcmp_window_control_config_t" structure.
*/
void LPCMP_SetWindowControl(LPCMP_Type *base, const lpcmp_window_control_config_t *config);
#endif /* FSL_FEATURE_LPCMP_HAS_WINDOW_CONTROL */
/*! @} */
#if defined(FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE) && FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE
/*!
* @name RoundRobin mode
* @{
*/
/*!
* @brief Configure the roundrobin mode.
*
* @param base LPCMP peripheral base address.
* @param config Pointer "lpcmp_roundrobin_config_t" structure.
*/
void LPCMP_SetRoundRobinConfig(LPCMP_Type *base, const lpcmp_roundrobin_config_t *config);
/*!
* brief Configure the roundrobin internal timer reload value.
*
* param base LPCMP peripheral base address.
* param value RoundRobin internal timer reload value, allowed range:0x0UL-0xFFFFFFFUL.
*/
void LPCMP_SetRoundRobinInternalTimer(LPCMP_Type *base, uint32_t value);
/*!
* @brief Enable/Disable roundrobin mode.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable roundrobin mode, and "false" means disable roundrobin mode.
*/
static inline void LPCMP_EnableRoundRobinMode(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->RRCR0 |= LPCMP_RRCR0_RR_EN_MASK;
}
else
{
base->RRCR0 &= ~LPCMP_RRCR0_RR_EN_MASK;
}
}
/*!
* @brief Enable/Disable roundrobin internal timer, note that this function is only valid
* when using the internal trigger source.
*
* @param base LPCMP peripheral base address.
* @param enable "true" means enable roundrobin internal timer, and "false" means disable roundrobin internal timer.
*/
static inline void LPCMP_EnableRoundRobinInternalTimer(LPCMP_Type *base, bool enable)
{
if (enable)
{
base->RRCR2 |= LPCMP_RRCR2_RR_TIMER_EN_MASK;
}
else
{
base->RRCR2 &= ~LPCMP_RRCR2_RR_TIMER_EN_MASK;
}
}
/*!
* @brief Set preset value for all channels, users can set all channels' preset vaule through this API,
* for example, if the mask set to 0x03U means channel0 and channel2's preset value set to 1U and other
* channels' preset value set to 0U.
*
* @param base LPCMP peripheral base address.
* @param mask Mask of channel index.
*/
static inline void LPCMP_SetPreSetValue(LPCMP_Type *base, uint8_t mask)
{
base->RRCSR = (uint32_t)mask;
}
/*!
* @brief Get comparison results for all channels, users can get all channels' comparison
* results through this API.
*
* @param base LPCMP peripheral base address.
* @return return All channels' comparison result.
*/
static inline uint8_t LPCMP_GetComparisonResult(LPCMP_Type *base)
{
return (uint8_t)base->RRCSR;
}
/*!
* @brief Clear input changed flags for single channel or multiple channels, users can clear
* input changed flag of a single channel or multiple channels through this API, for example,
* if the mask set to 0x03U means clear channel0 and channel2's input changed flags.
*
* @param base LPCMP peripheral base address.
* @param mask Mask of channel index.
*/
static inline void LPCMP_ClearInputChangedFlags(LPCMP_Type *base, uint8_t mask)
{
base->RRSR = (uint32_t)mask;
}
/*!
* @brief Get input changed flags for all channels, Users can get all channels' input changed
* flags through this API.
*
* @param base LPCMP peripheral base address.
* @return return All channels' changed flag.
*/
static inline uint8_t LPCMP_GetInputChangedFlags(LPCMP_Type *base)
{
return (uint8_t)base->RRSR;
}
/*! @} */
#endif /* FSL_FEATURE_LPCMP_HAS_ROUNDROBIN_MODE */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* FSL_LPCMP_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,659 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpi2c_edma.h"
#include <stdlib.h>
#include <string.h>
/*
* $Coverage Justification Reference$
*
* $Justification fsl_lpi2c_edma_c_ref_1$
* Need multiple master and slave modules on bus to simulate the true branch
*
* $Justification fsl_lpi2c_edma_c_ref_2$
* FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(X) is a constant.
*
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpi2c_edma"
#endif
/* @brief Mask to align an address to edma_tcd_t size. */
#define ALIGN_TCD_SIZE_MASK (sizeof(edma_tcd_t) - 1U)
/* ! @brief LPI2C master fifo commands. */
enum _lpi2c_master_fifo_cmd
{
kTxDataCmd = LPI2C_MTDR_CMD(0x0U), /*!< Transmit DATA[7:0] */
kRxDataCmd = LPI2C_MTDR_CMD(0X1U), /*!< Receive (DATA[7:0] + 1) bytes */
kStopCmd = LPI2C_MTDR_CMD(0x2U), /*!< Generate STOP condition */
kStartCmd = LPI2C_MTDR_CMD(0x4U), /*!< Generate(repeated) START and transmit address in DATA[[7:0] */
};
/*! @brief States for the state machine used by transactional APIs. */
enum _lpi2c_transfer_states
{
kIdleState = 0,
kSendCommandState,
kIssueReadCommandState,
kTransferDataState,
kStopState,
kWaitForCompletionState,
};
/*! @brief Typedef for interrupt handler. */
typedef void (*lpi2c_isr_t)(LPI2C_Type *base, void *handle);
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Prepares the command buffer with the sequence of commands needed to send the requested transaction.
* @param handle Master DMA driver handle.
* @return Number of command words.
*/
static uint32_t LPI2C_GenerateCommands(lpi2c_master_edma_handle_t *handle);
/*!
* @brief DMA completion callback.
* @param dmaHandle DMA channel handle for the channel that completed.
* @param userData User data associated with the channel handle. For this callback, the user data is the
* LPI2C DMA driver handle.
* @param isTransferDone Whether the DMA transfer has completed.
* @param tcds Number of TCDs that completed.
*/
static void LPI2C_MasterEDMACallback(edma_handle_t *dmaHandle, void *userData, bool isTransferDone, uint32_t tcds);
/*!
* @brief LPI2C master edma transfer IRQ handle routine.
*
* This API handles the LPI2C bus error status and invoke callback if needed.
*
* @param base The LPI2C peripheral base address.
* @param lpi2cMasterEdmaHandle Pointer to the LPI2C master edma handle.
*/
static void LPI2C_MasterTransferEdmaHandleIRQ(LPI2C_Type *base, void *lpi2cMasterEdmaHandle);
/*******************************************************************************
* Variables
******************************************************************************/
static uint32_t lpi2c_edma_RecSetting = 0x02;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief Create a new handle for the LPI2C master DMA APIs.
*
* The creation of a handle is for use with the DMA APIs. Once a handle
* is created, there is not a corresponding destroy handle. If the user wants to
* terminate a transfer, the LPI2C_MasterTransferAbortEDMA() API shall be called.
*
* For devices where the LPI2C send and receive DMA requests are OR'd together, the a txDmaHandle
* parameter is ignored and may be set to NULL.
*
* param base The LPI2C peripheral base address.
* param[out] handle Pointer to the LPI2C master driver handle.
* param rxDmaHandle Handle for the eDMA receive channel. Created by the user prior to calling this function.
* param txDmaHandle Handle for the eDMA transmit channel. Created by the user prior to calling this function.
* param callback User provided pointer to the asynchronous callback function.
* param userData User provided pointer to the application callback data.
*/
void LPI2C_MasterCreateEDMAHandle(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle,
lpi2c_master_edma_transfer_callback_t callback,
void *userData)
{
assert(handle != NULL);
assert(rxDmaHandle != NULL);
assert(txDmaHandle != NULL);
/* Look up instance number */
uint32_t instance = LPI2C_GetInstance(base);
/* Clear out the handle. */
(void)memset(handle, 0, sizeof(*handle));
/* Set up the handle. For combined rx/tx DMA requests, the tx channel handle is set to the rx handle */
/* in order to make the transfer API code simpler. */
handle->base = base;
handle->completionCallback = callback;
handle->userData = userData;
handle->rx = rxDmaHandle;
handle->tx = (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) > 0) ? txDmaHandle : rxDmaHandle;
/* Save the handle in global variables to support the double weak mechanism. */
s_lpi2cMasterHandle[instance] = handle;
/* Set LPI2C_MasterTransferEdmaHandleIRQ as LPI2C DMA IRQ handler */
s_lpi2cMasterIsr = LPI2C_MasterTransferEdmaHandleIRQ;
/* Enable interrupt in NVIC. */
(void)EnableIRQ(kLpi2cIrqs[instance]);
/* Set DMA channel completion callbacks. */
EDMA_SetCallback(handle->rx, LPI2C_MasterEDMACallback, handle);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0)
{
EDMA_SetCallback(handle->tx, LPI2C_MasterEDMACallback, handle);
}
}
static uint32_t LPI2C_GenerateCommands(lpi2c_master_edma_handle_t *handle)
{
lpi2c_master_transfer_t *xfer = &handle->transfer;
uint16_t *cmd = (uint16_t *)&handle->commandBuffer;
uint32_t cmdCount = 0;
/* Handle no start option. */
if ((xfer->flags & (uint32_t)kLPI2C_TransferNoStartFlag) != 0U)
{
if (xfer->direction == kLPI2C_Read)
{
/* Need to issue read command first. */
cmd[cmdCount++] = (uint16_t)kRxDataCmd | (uint16_t)LPI2C_MTDR_DATA(xfer->dataSize - 1U);
}
}
else
{
/*
* Initial direction depends on whether a subaddress was provided, and of course the actual
* data transfer direction.
*/
lpi2c_direction_t direction = (xfer->subaddressSize != 0U) ? kLPI2C_Write : xfer->direction;
/* Start command. */
cmd[cmdCount++] =
(uint16_t)kStartCmd | (uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)direction);
/* Subaddress, MSB first. */
if (xfer->subaddressSize != 0U)
{
uint32_t subaddressRemaining = xfer->subaddressSize;
while (0U != subaddressRemaining--)
{
uint8_t subaddressByte = (uint8_t)(xfer->subaddress >> (8U * subaddressRemaining)) & 0xffU;
cmd[cmdCount++] = subaddressByte;
}
}
/* Reads need special handling because we have to issue a read command and maybe a repeated start. */
if ((xfer->dataSize != 0U) && (xfer->direction == kLPI2C_Read))
{
/* Need to send repeated start if switching directions to read. */
if (direction == kLPI2C_Write)
{
cmd[cmdCount++] = (uint16_t)kStartCmd |
(uint16_t)((uint16_t)((uint16_t)xfer->slaveAddress << 1U) | (uint16_t)kLPI2C_Read);
}
/* Read command. A single write to MTDR can issue read operation of 0xFFU + 1 byte of data at most, so when
the dataSize is larger than 0x100U, push multiple read commands to MTDR until dataSize is reached. */
size_t tmpRxSize = xfer->dataSize;
while (tmpRxSize != 0U)
{
if (tmpRxSize > 256U)
{
cmd[cmdCount++] = (uint16_t)kRxDataCmd | (uint16_t)LPI2C_MTDR_DATA(0xFFU);
tmpRxSize -= 256U;
}
else
{
cmd[cmdCount++] = (uint16_t)kRxDataCmd | (uint16_t)LPI2C_MTDR_DATA(tmpRxSize - 1U);
tmpRxSize = 0U;
}
}
}
}
return cmdCount;
}
/*!
* brief Performs a non-blocking DMA-based transaction on the I2C bus.
*
* The callback specified when the a handle was created is invoked when the transaction has
* completed.
*
* param base The LPI2C peripheral base address.
* param handle Pointer to the LPI2C master driver handle.
* param transfer The pointer to the transfer descriptor.
* retval #kStatus_Success The transaction was started successfully.
* retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or another DMA
* transaction is already in progress.
*/
status_t LPI2C_MasterTransferEDMA(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
lpi2c_master_transfer_t *transfer)
{
status_t result;
assert(handle != NULL);
assert(transfer != NULL);
assert(transfer->subaddressSize <= sizeof(transfer->subaddress));
/* Check transfer data size in read operation. */
/* A single write to MTDR can issue read operation of 0xFFU + 1 byte of data at most, so when the dataSize is larger
than 0x100U, push multiple read commands to MTDR until dataSize is reached. LPI2C edma transfer uses linked
descriptor to transfer command and data, the command buffer is stored in handle. Allocate 4 command words to
carry read command which can cover nearly all use cases. */
if ((transfer->direction == kLPI2C_Read) && (transfer->dataSize > (256U * 4U)))
{
return kStatus_InvalidArgument;
}
/* Return busy if another transaction is in progress. */
if (handle->isBusy)
{
return kStatus_LPI2C_Busy;
}
/* Enable the master function and disable the slave function. */
LPI2C_MasterEnable(base, true);
LPI2C_SlaveEnable(base, false);
/* Return an error if the bus is already in use not by us. */
result = LPI2C_CheckForBusyBus(base);
/*
* $Branch Coverage Justification$
* $ref fsl_lpi2c_edma_c_ref_1$
*/
if (result != kStatus_Success)
{
return result;
}
/* We're now busy. */
handle->isBusy = true;
/* Disable LPI2C IRQ and DMA sources while we configure stuff. */
LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
LPI2C_MasterEnableDMA(base, false, false);
/* Clear all flags. */
LPI2C_MasterClearStatusFlags(base, (uint32_t)kLPI2C_MasterClearFlags);
/* Save transfer into handle. */
handle->transfer = *transfer;
/* Generate commands to send. */
uint32_t commandCount = LPI2C_GenerateCommands(handle);
/* If the user is transmitting no data with no start or stop, then just go ahead and invoke the callback. */
if ((0U == commandCount) && (transfer->dataSize == 0U))
{
if (handle->completionCallback != NULL)
{
handle->completionCallback(base, handle, kStatus_Success, handle->userData);
}
return kStatus_Success;
}
/* Reset DMA channels. */
EDMA_ResetChannel(handle->rx->base, handle->rx->channel);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0)
{
EDMA_ResetChannel(handle->tx->base, handle->tx->channel);
}
/* Get a 32-byte aligned TCD pointer. */
edma_tcd_t *tcd = (edma_tcd_t *)((uint32_t)(&handle->tcds[1]) & (~ALIGN_TCD_SIZE_MASK));
bool hasSendData = (transfer->direction == kLPI2C_Write) && (transfer->dataSize != 0U);
bool hasReceiveData = (transfer->direction == kLPI2C_Read) && (transfer->dataSize != 0U);
edma_transfer_config_t transferConfig = {0};
edma_tcd_t *linkTcd = NULL;
/* Set up data transmit. */
if (hasSendData)
{
uint32_t *srcAddr = (uint32_t *)transfer->data;
transferConfig.srcAddr = (uint32_t)srcAddr;
transferConfig.destAddr = (uint32_t)LPI2C_MasterGetTxFifoAddress(base);
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = (int16_t)sizeof(uint8_t);
transferConfig.destOffset = 0;
transferConfig.minorLoopBytes = sizeof(uint8_t); /* TODO optimize to fill fifo */
transferConfig.majorLoopCounts = transfer->dataSize;
/* Store the initially configured eDMA minor byte transfer count into the LPI2C handle */
handle->nbytes = (uint8_t)transferConfig.minorLoopBytes;
if (commandCount != 0U)
{
#if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
/* Create a software TCD, which will be chained after the commands. */
EDMA_TcdResetExt(handle->tx->base, tcd);
EDMA_TcdSetTransferConfigExt(handle->tx->base, tcd, &transferConfig, NULL);
EDMA_TcdEnableInterruptsExt(handle->tx->base, tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#else
/* Create a software TCD, which will be chained after the commands. */
EDMA_TcdReset(tcd);
EDMA_TcdSetTransferConfig(tcd, &transferConfig, NULL);
EDMA_TcdEnableInterrupts(tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#endif
linkTcd = tcd;
}
else
{
/* User is only transmitting data with no required commands, so this transfer can stand alone. */
EDMA_SetTransferConfig(handle->tx->base, handle->tx->channel, &transferConfig, NULL);
EDMA_EnableChannelInterrupts(handle->tx->base, handle->tx->channel, (uint32_t)kEDMA_MajorInterruptEnable);
}
}
else if (hasReceiveData)
{
uint32_t *srcAddr = (uint32_t *)transfer->data;
/* Set up data receive. */
transferConfig.srcAddr = (uint32_t)LPI2C_MasterGetRxFifoAddress(base);
transferConfig.destAddr = (uint32_t)srcAddr;
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = 0;
transferConfig.destOffset = (int16_t)sizeof(uint8_t);
transferConfig.minorLoopBytes = sizeof(uint8_t); /* TODO optimize to empty fifo */
transferConfig.majorLoopCounts = transfer->dataSize;
/* Store the initially configured eDMA minor byte transfer count into the LPI2C handle */
handle->nbytes = (uint8_t)transferConfig.minorLoopBytes;
if ((FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0) || (0U == commandCount))
{
/* We can put this receive transfer on its own DMA channel. */
EDMA_SetTransferConfig(handle->rx->base, handle->rx->channel, &transferConfig, NULL);
EDMA_EnableChannelInterrupts(handle->rx->base, handle->rx->channel, (uint32_t)kEDMA_MajorInterruptEnable);
}
else
{
/* For shared rx/tx DMA requests, when there are commands, create a software TCD of
enabling rx dma and disabling tx dma, which will be chained onto the commands transfer,
and create another software TCD of transfering data and chain it onto the last TCD.
Notice that in this situation assume tx/rx uses same channel */
#if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
EDMA_TcdResetExt(handle->rx->base, tcd);
EDMA_TcdSetTransferConfigExt(handle->rx->base, tcd, &transferConfig, NULL);
EDMA_TcdEnableInterruptsExt(handle->rx->base, tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#else
EDMA_TcdReset(tcd);
EDMA_TcdSetTransferConfig(tcd, &transferConfig, NULL);
EDMA_TcdEnableInterrupts(tcd, (uint32_t)kEDMA_MajorInterruptEnable);
#endif
transferConfig.srcAddr = (uint32_t)&lpi2c_edma_RecSetting;
transferConfig.destAddr = (uint32_t) & (base->MDER);
transferConfig.srcTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize1Bytes;
transferConfig.srcOffset = 0;
transferConfig.destOffset = (int16_t)sizeof(uint8_t);
transferConfig.minorLoopBytes = sizeof(uint8_t);
transferConfig.majorLoopCounts = 1;
edma_tcd_t *tcdSetRxClearTxDMA = (edma_tcd_t *)((uint32_t)(&handle->tcds[2]) & (~ALIGN_TCD_SIZE_MASK));
#if defined FSL_EDMA_DRIVER_EDMA4 && FSL_EDMA_DRIVER_EDMA4
EDMA_TcdResetExt(handle->rx->base, tcdSetRxClearTxDMA);
EDMA_TcdSetTransferConfigExt(handle->rx->base, tcdSetRxClearTxDMA, &transferConfig, tcd);
#else
EDMA_TcdReset(tcdSetRxClearTxDMA);
EDMA_TcdSetTransferConfig(tcdSetRxClearTxDMA, &transferConfig, tcd);
#endif
linkTcd = tcdSetRxClearTxDMA;
}
}
else
{
/* No data to send */
}
/* Set up commands transfer. */
if (commandCount != 0U)
{
transferConfig.srcAddr = (uint32_t)handle->commandBuffer;
transferConfig.destAddr = (uint32_t)LPI2C_MasterGetTxFifoAddress(base);
transferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;
transferConfig.destTransferSize = kEDMA_TransferSize2Bytes;
transferConfig.srcOffset = (int16_t)sizeof(uint16_t);
transferConfig.destOffset = 0;
transferConfig.minorLoopBytes = sizeof(uint16_t); /* TODO optimize to fill fifo */
transferConfig.majorLoopCounts = commandCount;
EDMA_SetTransferConfig(handle->tx->base, handle->tx->channel, &transferConfig, linkTcd);
}
/* Start DMA transfer. */
/*
* $Branch Coverage Justification$
* $ref fsl_lpi2c_edma_c_ref_2$
*/
if (hasReceiveData || (0 == FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
{
EDMA_StartTransfer(handle->rx);
}
/*
* $Branch Coverage Justification$
* $ref fsl_lpi2c_edma_c_ref_2$
*/
if ((hasSendData || (commandCount != 0U)) && (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0))
{
EDMA_StartTransfer(handle->tx);
}
/* Enable DMA in both directions. This actually kicks of the transfer. */
LPI2C_MasterEnableDMA(base, true, true);
/* Enable all LPI2C master interrupts */
LPI2C_MasterEnableInterrupts(base,
(uint32_t)kLPI2C_MasterArbitrationLostFlag | (uint32_t)kLPI2C_MasterNackDetectFlag |
(uint32_t)kLPI2C_MasterPinLowTimeoutFlag | (uint32_t)kLPI2C_MasterFifoErrFlag);
return result;
}
/*!
* brief Returns number of bytes transferred so far.
*
* param base The LPI2C peripheral base address.
* param handle Pointer to the LPI2C master driver handle.
* param[out] count Number of bytes transferred so far by the non-blocking transaction.
* retval #kStatus_Success
* retval #kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferGetCountEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle, size_t *count)
{
assert(handle != NULL);
if (NULL == count)
{
return kStatus_InvalidArgument;
}
/* Catch when there is not an active transfer. */
if (!handle->isBusy)
{
*count = 0;
return kStatus_NoTransferInProgress;
}
uint32_t remaining = handle->transfer.dataSize;
/* If the DMA is still on a commands transfer that chains to the actual data transfer, */
/* we do nothing and return the number of transferred bytes as zero. */
if (EDMA_GetNextTCDAddress(handle->tx) == 0U)
{
if (handle->transfer.direction == kLPI2C_Write)
{
remaining =
(uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->tx->base, handle->tx->channel);
}
else
{
remaining =
(uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->rx->base, handle->rx->channel);
}
}
*count = handle->transfer.dataSize - remaining;
return kStatus_Success;
}
/*!
* brief Terminates a non-blocking LPI2C master transmission early.
*
* note It is not safe to call this function from an IRQ handler that has a higher priority than the
* eDMA peripheral's IRQ priority.
*
* param base The LPI2C peripheral base address.
* param handle Pointer to the LPI2C master driver handle.
* retval #kStatus_Success A transaction was successfully aborted.
* retval #kStatus_LPI2C_Idle There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferAbortEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle)
{
/* Catch when there is not an active transfer. */
if (!handle->isBusy)
{
return kStatus_LPI2C_Idle;
}
/* Terminate DMA transfers. */
EDMA_AbortTransfer(handle->rx);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0)
{
EDMA_AbortTransfer(handle->tx);
}
/* Reset fifos. */
base->MCR |= LPI2C_MCR_RRF_MASK | LPI2C_MCR_RTF_MASK;
/* Disable LPI2C interrupts. */
LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
/* If master is still busy and has not send out stop signal yet. */
if ((LPI2C_MasterGetStatusFlags(base) &
((uint32_t)kLPI2C_MasterStopDetectFlag | (uint32_t)kLPI2C_MasterBusyFlag)) == (uint32_t)kLPI2C_MasterBusyFlag)
{
/* Send a stop command to finalize the transfer. */
base->MTDR = (uint32_t)kStopCmd;
}
/* Reset handle. */
handle->isBusy = false;
return kStatus_Success;
}
static void LPI2C_MasterEDMACallback(edma_handle_t *dmaHandle, void *userData, bool isTransferDone, uint32_t tcds)
{
lpi2c_master_edma_handle_t *handle = (lpi2c_master_edma_handle_t *)userData;
if (NULL == handle)
{
return;
}
/* Check for errors. */
status_t result = LPI2C_MasterCheckAndClearError(handle->base, LPI2C_MasterGetStatusFlags(handle->base));
/* Done with this transaction. */
handle->isBusy = false;
if (0U == (handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag))
{
/* Send a stop command to finalize the transfer. */
handle->base->MTDR = (uint32_t)kStopCmd;
}
/* Invoke callback. */
if (handle->completionCallback != NULL)
{
handle->completionCallback(handle->base, handle, result, handle->userData);
}
}
static void LPI2C_MasterTransferEdmaHandleIRQ(LPI2C_Type *base, void *lpi2cMasterEdmaHandle)
{
assert(lpi2cMasterEdmaHandle != NULL);
lpi2c_master_edma_handle_t *handle = (lpi2c_master_edma_handle_t *)lpi2cMasterEdmaHandle;
uint32_t status = LPI2C_MasterGetStatusFlags(base);
status_t result = kStatus_Success;
/* Terminate DMA transfers. */
EDMA_AbortTransfer(handle->rx);
if (FSL_FEATURE_LPI2C_HAS_SEPARATE_DMA_RX_TX_REQn(base) != 0)
{
EDMA_AbortTransfer(handle->tx);
}
/* Done with this transaction. */
handle->isBusy = false;
/* Disable LPI2C interrupts. */
LPI2C_MasterDisableInterrupts(base, (uint32_t)kLPI2C_MasterIrqFlags);
/* Check error status */
if (0U != (status & (uint32_t)kLPI2C_MasterPinLowTimeoutFlag))
{
result = kStatus_LPI2C_PinLowTimeout;
}
/*
* $Branch Coverage Justification$
* $ref fsl_lpi2c_edma_c_ref_1$
*/
else if (0U != (status & (uint32_t)kLPI2C_MasterArbitrationLostFlag))
{
result = kStatus_LPI2C_ArbitrationLost;
}
else if (0U != (status & (uint32_t)kLPI2C_MasterNackDetectFlag))
{
result = kStatus_LPI2C_Nak;
}
else if (0U != (status & (uint32_t)kLPI2C_MasterFifoErrFlag))
{
result = kStatus_LPI2C_FifoError;
}
else
{
; /* Intentional empty */
}
/* Clear error status. */
(void)LPI2C_MasterCheckAndClearError(base, status);
/* Send stop flag if needed */
if (0U == (handle->transfer.flags & (uint32_t)kLPI2C_TransferNoStopFlag))
{
status = LPI2C_MasterGetStatusFlags(base);
/* If bus is still busy and the master has not generate stop flag */
if ((status & ((uint32_t)kLPI2C_MasterBusBusyFlag | (uint32_t)kLPI2C_MasterStopDetectFlag)) ==
(uint32_t)kLPI2C_MasterBusBusyFlag)
{
/* Send a stop command to finalize the transfer. */
handle->base->MTDR = (uint32_t)kStopCmd;
}
}
/* Invoke callback. */
if (handle->completionCallback != NULL)
{
handle->completionCallback(base, handle, result, handle->userData);
}
}

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_LPI2C_EDMA_H_
#define FSL_LPI2C_EDMA_H_
#include "fsl_lpi2c.h"
#include "fsl_edma.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/*!
* @name Driver version
* @{
*/
/*! @brief LPI2C EDMA driver version. */
#define FSL_LPI2C_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 4, 2))
/*! @} */
/*!
* @addtogroup lpi2c_master_edma_driver
* @{
*/
/* Forward declaration of the transfer descriptor and handle typedefs. */
/*! @brief LPI2C master EDMA handle of the transfer. */
typedef struct _lpi2c_master_edma_handle lpi2c_master_edma_handle_t;
/*!
* @brief Master DMA completion callback function pointer type.
*
* This callback is used only for the non-blocking master transfer API. Specify the callback you wish to use
* in the call to LPI2C_MasterCreateEDMAHandle().
*
* @param base The LPI2C peripheral base address.
* @param handle Handle associated with the completed transfer.
* @param completionStatus Either kStatus_Success or an error code describing how the transfer completed.
* @param userData Arbitrary pointer-sized value passed from the application.
*/
typedef void (*lpi2c_master_edma_transfer_callback_t)(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
status_t completionStatus,
void *userData);
/*!
* @brief Driver handle for master DMA APIs.
* @note The contents of this structure are private and subject to change.
*/
struct _lpi2c_master_edma_handle
{
LPI2C_Type *base; /*!< LPI2C base pointer. */
bool isBusy; /*!< Transfer state machine current state. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
uint16_t commandBuffer[10]; /*!< LPI2C command sequence. When all 10 command words are used:
Start&addr&write[1 word] + subaddr[4 words] + restart&addr&read[1 word] + receive&Size[4 words] */
lpi2c_master_transfer_t transfer; /*!< Copy of the current transfer info. */
lpi2c_master_edma_transfer_callback_t completionCallback; /*!< Callback function pointer. */
void *userData; /*!< Application data passed to callback. */
edma_handle_t *rx; /*!< Handle for receive DMA channel. */
edma_handle_t *tx; /*!< Handle for transmit DMA channel. */
edma_tcd_t tcds[3]; /*!< Software TCD. Three are allocated to provide enough room to align to 32-bytes. */
};
/*! @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @addtogroup lpi2c_master_edma_driver
* @{
*/
/*!
* @name Master DMA
* @{
*/
/*!
* @brief Create a new handle for the LPI2C master DMA APIs.
*
* The creation of a handle is for use with the DMA APIs. Once a handle
* is created, there is not a corresponding destroy handle. If the user wants to
* terminate a transfer, the LPI2C_MasterTransferAbortEDMA() API shall be called.
*
* For devices where the LPI2C send and receive DMA requests are OR'd together, the @a txDmaHandle
* parameter is ignored and may be set to NULL.
*
* @param base The LPI2C peripheral base address.
* @param[out] handle Pointer to the LPI2C master driver handle.
* @param rxDmaHandle Handle for the eDMA receive channel. Created by the user prior to calling this function.
* @param txDmaHandle Handle for the eDMA transmit channel. Created by the user prior to calling this function.
* @param callback User provided pointer to the asynchronous callback function.
* @param userData User provided pointer to the application callback data.
*/
void LPI2C_MasterCreateEDMAHandle(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
edma_handle_t *rxDmaHandle,
edma_handle_t *txDmaHandle,
lpi2c_master_edma_transfer_callback_t callback,
void *userData);
/*!
* @brief Performs a non-blocking DMA-based transaction on the I2C bus.
*
* The callback specified when the @a handle was created is invoked when the transaction has
* completed.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @param transfer The pointer to the transfer descriptor.
* @retval kStatus_Success The transaction was started successfully.
* @retval #kStatus_LPI2C_Busy Either another master is currently utilizing the bus, or another DMA
* transaction is already in progress.
*/
status_t LPI2C_MasterTransferEDMA(LPI2C_Type *base,
lpi2c_master_edma_handle_t *handle,
lpi2c_master_transfer_t *transfer);
/*!
* @brief Returns number of bytes transferred so far.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @param[out] count Number of bytes transferred so far by the non-blocking transaction.
* @retval kStatus_Success
* @retval kStatus_NoTransferInProgress There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferGetCountEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle, size_t *count);
/*!
* @brief Terminates a non-blocking LPI2C master transmission early.
*
* @note It is not safe to call this function from an IRQ handler that has a higher priority than the
* eDMA peripheral's IRQ priority.
*
* @param base The LPI2C peripheral base address.
* @param handle Pointer to the LPI2C master driver handle.
* @retval kStatus_Success A transaction was successfully aborted.
* @retval #kStatus_LPI2C_Idle There is not a DMA transaction currently in progress.
*/
status_t LPI2C_MasterTransferAbortEDMA(LPI2C_Type *base, lpi2c_master_edma_handle_t *handle);
/*! @} */
/*! @} */
#if defined(__cplusplus)
}
#endif
#endif /* FSL_LPI2C_EDMA_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,353 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_LPSPI_EDMA_H_
#define FSL_LPSPI_EDMA_H_
#include "fsl_lpspi.h"
#include "fsl_edma.h"
/*!
* @addtogroup lpspi_edma_driver
* @{
*/
/***********************************************************************************************************************
* Definitions
**********************************************************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief LPSPI EDMA driver version. */
#define FSL_LPSPI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 4, 4))
/*! @brief DMA max transfer size */
#define DMA_MAX_TRANSFER_COUNT 0x7FFFU
/*! @} */
/*!
* @brief Forward declaration of the _lpspi_master_edma_handle typedefs.
*/
typedef struct _lpspi_master_edma_handle lpspi_master_edma_handle_t;
/*!
* @brief Forward declaration of the _lpspi_slave_edma_handle typedefs.
*/
typedef struct _lpspi_slave_edma_handle lpspi_slave_edma_handle_t;
/*!
* @brief Completion callback function pointer type.
*
* @param base LPSPI peripheral base address.
* @param handle Pointer to the handle for the LPSPI master.
* @param status Success or error code describing whether the transfer completed.
* @param userData Arbitrary pointer-dataSized value passed from the application.
*/
typedef void (*lpspi_master_edma_transfer_callback_t)(LPSPI_Type *base,
lpspi_master_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief Completion callback function pointer type.
*
* @param base LPSPI peripheral base address.
* @param handle Pointer to the handle for the LPSPI slave.
* @param status Success or error code describing whether the transfer completed.
* @param userData Arbitrary pointer-dataSized value passed from the application.
*/
typedef void (*lpspi_slave_edma_transfer_callback_t)(LPSPI_Type *base,
lpspi_slave_edma_handle_t *handle,
status_t status,
void *userData);
/*! @brief LPSPI master eDMA transfer handle structure used for transactional API. */
struct _lpspi_master_edma_handle
{
volatile bool isPcsContinuous; /*!< Is PCS continuous in transfer. */
volatile bool isByteSwap; /*!< A flag that whether should byte swap. */
volatile uint8_t fifoSize; /*!< FIFO dataSize. */
volatile uint8_t rxWatermark; /*!< Rx watermark. */
volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR. */
volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR. */
volatile uint8_t bytesLastRead; /*!< Bytes for last read RDR. */
volatile bool isThereExtraRxBytes; /*!< Is there extra RX byte. */
const uint8_t *volatile txData; /*!< Send buffer. */
uint8_t *volatile rxData; /*!< Receive buffer. */
volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/
volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/
volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times. */
volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times. */
uint32_t totalByteCount; /*!< Number of transfer bytes*/
edma_tcd_t *lastTimeTCD; /*!< Pointer to the lastTime TCD*/
bool isMultiDMATransmit; /*!< Is there multi DMA transmit*/
volatile uint8_t dmaTransmitTime; /*!< DMA Transfer times. */
uint32_t lastTimeDataBytes; /*!< DMA transmit last Time data Bytes */
uint32_t dataBytesEveryTime; /*!< Bytes in a time for DMA transfer, default is DMA_MAX_TRANSFER_COUNT */
edma_transfer_config_t transferConfigRx; /*!< Config of DMA rx channel.*/
edma_transfer_config_t transferConfigTx; /*!< Config of DMA tx channel.*/
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
uint32_t transmitCommand; /*!< Used to write TCR for DMA purpose.*/
volatile uint8_t state; /*!< LPSPI transfer state , _lpspi_transfer_state.*/
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
lpspi_master_edma_transfer_callback_t callback; /*!< Completion callback. */
void *userData; /*!< Callback user data. */
edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/
edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg buff*/
edma_tcd_t lpspiSoftwareTCD[3]; /*!<SoftwareTCD, internal used*/
};
/*! @brief LPSPI slave eDMA transfer handle structure used for transactional API.*/
struct _lpspi_slave_edma_handle
{
volatile bool isByteSwap; /*!< A flag that whether should byte swap. */
volatile uint8_t fifoSize; /*!< FIFO dataSize. */
volatile uint8_t rxWatermark; /*!< Rx watermark. */
volatile uint8_t bytesEachWrite; /*!< Bytes for each write TDR. */
volatile uint8_t bytesEachRead; /*!< Bytes for each read RDR. */
volatile uint8_t bytesLastRead; /*!< Bytes for last read RDR. */
volatile bool isThereExtraRxBytes; /*!< Is there extra RX byte. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
const uint8_t *volatile txData; /*!< Send buffer. */
uint8_t *volatile rxData; /*!< Receive buffer. */
volatile size_t txRemainingByteCount; /*!< Number of bytes remaining to send.*/
volatile size_t rxRemainingByteCount; /*!< Number of bytes remaining to receive.*/
volatile uint32_t writeRegRemainingTimes; /*!< Write TDR register remaining times. */
volatile uint32_t readRegRemainingTimes; /*!< Read RDR register remaining times. */
uint32_t totalByteCount; /*!< Number of transfer bytes*/
uint32_t txBuffIfNull; /*!< Used if there is not txData for DMA purpose.*/
uint32_t rxBuffIfNull; /*!< Used if there is not rxData for DMA purpose.*/
volatile uint8_t state; /*!< LPSPI transfer state.*/
uint32_t errorCount; /*!< Error count for slave transfer.*/
lpspi_slave_edma_transfer_callback_t callback; /*!< Completion callback. */
void *userData; /*!< Callback user data. */
edma_handle_t *edmaRxRegToRxDataHandle; /*!<edma_handle_t handle point used for RxReg to RxData buff*/
edma_handle_t *edmaTxDataToTxRegHandle; /*!<edma_handle_t handle point used for TxData to TxReg*/
edma_tcd_t lpspiSoftwareTCD[2]; /*!<SoftwareTCD, internal used*/
};
/***********************************************************************************************************************
* API
**********************************************************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/
/*Transactional APIs*/
/*!
* @brief Initializes the LPSPI master eDMA handle.
*
* This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
* specified LPSPI instance, call this API once to get the initialized handle.
*
* Note that the LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx and Tx are the same source) DMA
* request source.
* (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
* Tx DMAMUX source for edmaTxDataToTxRegHandle.
* (2) For a shared DMA request source, enable and set the Rx/Tx DMAMUX source for edmaRxRegToRxDataHandle.
*
* @param base LPSPI peripheral base address.
* @param handle LPSPI handle pointer to lpspi_master_edma_handle_t.
* @param callback LPSPI callback.
* @param userData callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
* @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
*/
void LPSPI_MasterTransferCreateHandleEDMA(LPSPI_Type *base,
lpspi_master_edma_handle_t *handle,
lpspi_master_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *edmaRxRegToRxDataHandle,
edma_handle_t *edmaTxDataToTxRegHandle);
/*!
* @brief LPSPI master transfer data using eDMA.
*
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
* is transferred, the callback function is called.
*
* Note:
* The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
* For bytesPerFrame greater than 4:
* The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
* Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param transfer pointer to lpspi_transfer_t structure.
* @return status of status_t.
*/
status_t LPSPI_MasterTransferEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer);
/*!
* @brief LPSPI master config transfer parameter while using eDMA.
*
* This function is preparing to transfer data using eDMA, work with LPSPI_MasterTransferEDMALite.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param configFlags transfer configuration flags. @ref _lpspi_transfer_config_flag_for_master.
* @return Indicates whether LPSPI master transfer was successful or not.
* @retval kStatus_Success Execution successfully.
* @retval kStatus_LPSPI_Busy The LPSPI device is busy.
*/
status_t LPSPI_MasterTransferPrepareEDMALite(LPSPI_Type *base,
lpspi_master_edma_handle_t *handle,
uint32_t configFlags);
/*!
* @brief LPSPI master transfer data using eDMA without configs.
*
* This function transfers data using eDMA. This is a non-blocking function, which returns right away. When all data
* is transferred, the callback function is called.
*
* Note:
* This API is only for transfer through DMA without configuration.
* Before calling this API, you must call LPSPI_MasterTransferPrepareEDMALite to configure it once.
* The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
* For bytesPerFrame greater than 4:
* The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
* Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param transfer pointer to lpspi_transfer_t structure, config field is not uesed.
* @return Indicates whether LPSPI master transfer was successful or not.
* @retval kStatus_Success Execution successfully.
* @retval kStatus_LPSPI_Busy The LPSPI device is busy.
* @retval kStatus_InvalidArgument The transfer structure is invalid.
*/
status_t LPSPI_MasterTransferEDMALite(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, lpspi_transfer_t *transfer);
/*!
* @brief LPSPI master aborts a transfer which is using eDMA.
*
* This function aborts a transfer which is using eDMA.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
*/
void LPSPI_MasterTransferAbortEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle);
/*!
* @brief Gets the master eDMA transfer remaining bytes.
*
* This function gets the master eDMA transfer remaining bytes.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_master_edma_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the EDMA transaction.
* @return status of status_t.
*/
status_t LPSPI_MasterTransferGetCountEDMA(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, size_t *count);
/*!
* @brief Initializes the LPSPI slave eDMA handle.
*
* This function initializes the LPSPI eDMA handle which can be used for other LPSPI transactional APIs. Usually, for a
* specified LPSPI instance, call this API once to get the initialized handle.
*
* Note that LPSPI eDMA has a separated (Rx and Tx as two sources) or shared (Rx and Tx as the same source) DMA request
* source.
*
* (1) For a separated DMA request source, enable and set the Rx DMAMUX source for edmaRxRegToRxDataHandle and
* Tx DMAMUX source for edmaTxDataToTxRegHandle.
* (2) For a shared DMA request source, enable and set the Rx/Rx DMAMUX source for edmaRxRegToRxDataHandle .
*
* @param base LPSPI peripheral base address.
* @param handle LPSPI handle pointer to lpspi_slave_edma_handle_t.
* @param callback LPSPI callback.
* @param userData callback function parameter.
* @param edmaRxRegToRxDataHandle edmaRxRegToRxDataHandle pointer to edma_handle_t.
* @param edmaTxDataToTxRegHandle edmaTxDataToTxRegHandle pointer to edma_handle_t.
*/
void LPSPI_SlaveTransferCreateHandleEDMA(LPSPI_Type *base,
lpspi_slave_edma_handle_t *handle,
lpspi_slave_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *edmaRxRegToRxDataHandle,
edma_handle_t *edmaTxDataToTxRegHandle);
/*!
* @brief LPSPI slave transfers data using eDMA.
*
* This function transfers data using eDMA. This is a non-blocking function, which return right away. When all data
* is transferred, the callback function is called.
*
* Note:
* The transfer data size should be an integer multiple of bytesPerFrame if bytesPerFrame is less than or equal to 4.
* For bytesPerFrame greater than 4:
* The transfer data size should be equal to bytesPerFrame if the bytesPerFrame is not an integer multiple of 4.
* Otherwise, the transfer data size can be an integer multiple of bytesPerFrame.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
* @param transfer pointer to lpspi_transfer_t structure.
* @return status of status_t.
*/
status_t LPSPI_SlaveTransferEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, lpspi_transfer_t *transfer);
/*!
* @brief LPSPI slave aborts a transfer which is using eDMA.
*
* This function aborts a transfer which is using eDMA.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
*/
void LPSPI_SlaveTransferAbortEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle);
/*!
* @brief Gets the slave eDMA transfer remaining bytes.
*
* This function gets the slave eDMA transfer remaining bytes.
*
* @param base LPSPI peripheral base address.
* @param handle pointer to lpspi_slave_edma_handle_t structure which stores the transfer state.
* @param count Number of bytes transferred so far by the eDMA transaction.
* @return status of status_t.
*/
status_t LPSPI_SlaveTransferGetCountEDMA(LPSPI_Type *base, lpspi_slave_edma_handle_t *handle, size_t *count);
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /*FSL_LPSPI_EDMA_H_*/

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lptmr.h"
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lptmr"
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
#if defined(LPTMR_CLOCKS)
/*!
* @brief Gets the instance from the base address to be used to gate or ungate the module clock
*
* @param base LPTMR peripheral base address
*
* @return The LPTMR instance
*/
static uint32_t LPTMR_GetInstance(LPTMR_Type *base);
#endif /* LPTMR_CLOCKS */
/*******************************************************************************
* Variables
******************************************************************************/
#if defined(LPTMR_CLOCKS)
/*! @brief Pointers to LPTMR bases for each instance. */
static LPTMR_Type *const s_lptmrBases[] = LPTMR_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to LPTMR clocks for each instance. */
static const clock_ip_name_t s_lptmrClocks[] = LPTMR_CLOCKS;
#if defined(LPTMR_PERIPH_CLOCKS)
/* Array of LPTMR functional clock name. */
static const clock_ip_name_t s_lptmrPeriphClocks[] = LPTMR_PERIPH_CLOCKS;
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
/*******************************************************************************
* Code
******************************************************************************/
#if defined(LPTMR_CLOCKS)
static uint32_t LPTMR_GetInstance(LPTMR_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_lptmrBases); instance++)
{
if (s_lptmrBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_lptmrBases));
return instance;
}
#endif /* LPTMR_CLOCKS */
/*!
* brief Ungates the LPTMR clock and configures the peripheral for a basic operation.
*
* note This API should be called at the beginning of the application using the LPTMR driver.
*
* param base LPTMR peripheral base address
* param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config)
{
assert(NULL != config);
#if defined(LPTMR_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPTMR_GetInstance(base);
/* Ungate the LPTMR clock*/
CLOCK_EnableClock(s_lptmrClocks[instance]);
#if defined(LPTMR_PERIPH_CLOCKS)
CLOCK_EnableClock(s_lptmrPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
/* Configure the timers operation mode and input pin setup */
base->CSR = (LPTMR_CSR_TMS(config->timerMode) | LPTMR_CSR_TFC(config->enableFreeRunning) |
LPTMR_CSR_TPP(config->pinPolarity) | LPTMR_CSR_TPS(config->pinSelect));
/* Configure the prescale value and clock source */
base->PSR = (LPTMR_PSR_PRESCALE(config->value) | LPTMR_PSR_PBYP(config->bypassPrescaler) |
LPTMR_PSR_PCS(config->prescalerClockSource));
}
/*!
* brief Gates the LPTMR clock.
*
* param base LPTMR peripheral base address
*/
void LPTMR_Deinit(LPTMR_Type *base)
{
/* Disable the LPTMR and reset the internal logic */
base->CSR &= ~LPTMR_CSR_TEN_MASK;
#if defined(LPTMR_CLOCKS)
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
uint32_t instance = LPTMR_GetInstance(base);
/* Gate the LPTMR clock*/
CLOCK_DisableClock(s_lptmrClocks[instance]);
#if defined(LPTMR_PERIPH_CLOCKS)
CLOCK_DisableClock(s_lptmrPeriphClocks[instance]);
#endif
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#endif /* LPTMR_CLOCKS */
}
/*!
* brief Fills in the LPTMR configuration structure with default settings.
*
* The default values are as follows.
* code
* config->timerMode = kLPTMR_TimerModeTimeCounter;
* config->pinSelect = kLPTMR_PinSelectInput_0;
* config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
* config->enableFreeRunning = false;
* config->bypassPrescaler = true;
* config->prescalerClockSource = kLPTMR_PrescalerClock_1;
* config->value = kLPTMR_Prescale_Glitch_0;
* endcode
* param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_GetDefaultConfig(lptmr_config_t *config)
{
assert(NULL != config);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
/* Use time counter mode */
config->timerMode = kLPTMR_TimerModeTimeCounter;
/* Use input 0 as source in pulse counter mode */
config->pinSelect = kLPTMR_PinSelectInput_0;
/* Pulse input pin polarity is active-high */
config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
/* Counter resets whenever TCF flag is set */
config->enableFreeRunning = false;
/* Bypass the prescaler */
config->bypassPrescaler = true;
/* LPTMR clock source */
#if !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT)
config->prescalerClockSource = kLPTMR_PrescalerClock_1;
#elif !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_0_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_0_SUPPORT)
config->prescalerClockSource = kLPTMR_PrescalerClock_0;
#elif !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_2_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_2_SUPPORT)
config->prescalerClockSource = kLPTMR_PrescalerClock_2;
#elif !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT)
config->prescalerClockSource = kLPTMR_PrescalerClock_3;
#else
#error No valid source
#endif
/* Divide the prescaler clock by 2 */
config->value = kLPTMR_Prescale_Glitch_0;
}

View File

@ -0,0 +1,384 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_LPTMR_H_
#define FSL_LPTMR_H_
#include "fsl_common.h"
/*!
* @addtogroup lptmr
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! Driver Version */
#define FSL_LPTMR_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
/*! @} */
/*! @brief LPTMR pin selection used in pulse counter mode.*/
typedef enum _lptmr_pin_select
{
kLPTMR_PinSelectInput_0 = 0x0U, /*!< Pulse counter input 0 is selected */
kLPTMR_PinSelectInput_1 = 0x1U, /*!< Pulse counter input 1 is selected */
kLPTMR_PinSelectInput_2 = 0x2U, /*!< Pulse counter input 2 is selected */
kLPTMR_PinSelectInput_3 = 0x3U /*!< Pulse counter input 3 is selected */
} lptmr_pin_select_t;
/*! @brief LPTMR pin polarity used in pulse counter mode.*/
typedef enum _lptmr_pin_polarity
{
kLPTMR_PinPolarityActiveHigh = 0x0U, /*!< Pulse Counter input source is active-high */
kLPTMR_PinPolarityActiveLow = 0x1U /*!< Pulse Counter input source is active-low */
} lptmr_pin_polarity_t;
/*! @brief LPTMR timer mode selection.*/
typedef enum _lptmr_timer_mode
{
kLPTMR_TimerModeTimeCounter = 0x0U, /*!< Time Counter mode */
kLPTMR_TimerModePulseCounter = 0x1U /*!< Pulse Counter mode */
} lptmr_timer_mode_t;
/*! @brief LPTMR prescaler/glitch filter values*/
typedef enum _lptmr_prescaler_glitch_value
{
kLPTMR_Prescale_Glitch_0 = 0x0U, /*!< Prescaler divide 2, glitch filter does not support this setting */
kLPTMR_Prescale_Glitch_1 = 0x1U, /*!< Prescaler divide 4, glitch filter 2 */
kLPTMR_Prescale_Glitch_2 = 0x2U, /*!< Prescaler divide 8, glitch filter 4 */
kLPTMR_Prescale_Glitch_3 = 0x3U, /*!< Prescaler divide 16, glitch filter 8 */
kLPTMR_Prescale_Glitch_4 = 0x4U, /*!< Prescaler divide 32, glitch filter 16 */
kLPTMR_Prescale_Glitch_5 = 0x5U, /*!< Prescaler divide 64, glitch filter 32 */
kLPTMR_Prescale_Glitch_6 = 0x6U, /*!< Prescaler divide 128, glitch filter 64 */
kLPTMR_Prescale_Glitch_7 = 0x7U, /*!< Prescaler divide 256, glitch filter 128 */
kLPTMR_Prescale_Glitch_8 = 0x8U, /*!< Prescaler divide 512, glitch filter 256 */
kLPTMR_Prescale_Glitch_9 = 0x9U, /*!< Prescaler divide 1024, glitch filter 512*/
kLPTMR_Prescale_Glitch_10 = 0xAU, /*!< Prescaler divide 2048 glitch filter 1024 */
kLPTMR_Prescale_Glitch_11 = 0xBU, /*!< Prescaler divide 4096, glitch filter 2048 */
kLPTMR_Prescale_Glitch_12 = 0xCU, /*!< Prescaler divide 8192, glitch filter 4096 */
kLPTMR_Prescale_Glitch_13 = 0xDU, /*!< Prescaler divide 16384, glitch filter 8192 */
kLPTMR_Prescale_Glitch_14 = 0xEU, /*!< Prescaler divide 32768, glitch filter 16384 */
kLPTMR_Prescale_Glitch_15 = 0xFU /*!< Prescaler divide 65536, glitch filter 32768 */
} lptmr_prescaler_glitch_value_t;
/*!
* @brief LPTMR prescaler/glitch filter clock select.
* @note Clock connections are SoC-specific
*/
typedef enum _lptmr_prescaler_clock_select
{
#if !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_0_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_0_SUPPORT)
kLPTMR_PrescalerClock_0 = 0x0U, /*!< Prescaler/glitch filter clock 0 selected. */
#endif
#if !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT)
kLPTMR_PrescalerClock_1 = 0x1U, /*!< Prescaler/glitch filter clock 1 selected. */
#endif /* FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_1_SUPPORT */
#if !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_2_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_2_SUPPORT)
kLPTMR_PrescalerClock_2 = 0x2U, /*!< Prescaler/glitch filter clock 2 selected. */
#endif
#if !(defined(FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT) && \
FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT)
kLPTMR_PrescalerClock_3 = 0x3U, /*!< Prescaler/glitch filter clock 3 selected. */
#endif /* FSL_FEATURE_LPTMR_HAS_NO_PRESCALER_CLOCK_SOURCE_3_SUPPORT */
} lptmr_prescaler_clock_select_t;
/*! @brief List of the LPTMR interrupts */
typedef enum _lptmr_interrupt_enable
{
kLPTMR_TimerInterruptEnable = LPTMR_CSR_TIE_MASK, /*!< Timer interrupt enable */
} lptmr_interrupt_enable_t;
/*! @brief List of the LPTMR status flags */
typedef enum _lptmr_status_flags
{
kLPTMR_TimerCompareFlag = LPTMR_CSR_TCF_MASK, /*!< Timer compare flag */
} lptmr_status_flags_t;
/*!
* @brief LPTMR config structure
*
* This structure holds the configuration settings for the LPTMR peripheral. To initialize this
* structure to reasonable defaults, call the LPTMR_GetDefaultConfig() function and pass a
* pointer to your configuration structure instance.
*
* The configuration struct can be made constant so it resides in flash.
*/
typedef struct _lptmr_config
{
lptmr_timer_mode_t timerMode; /*!< Time counter mode or pulse counter mode */
lptmr_pin_select_t pinSelect; /*!< LPTMR pulse input pin select; used only in pulse counter mode */
lptmr_pin_polarity_t pinPolarity; /*!< LPTMR pulse input pin polarity; used only in pulse counter mode */
bool enableFreeRunning; /*!< True: enable free running, counter is reset on overflow
False: counter is reset when the compare flag is set */
bool bypassPrescaler; /*!< True: bypass prescaler; false: use clock from prescaler */
lptmr_prescaler_clock_select_t prescalerClockSource; /*!< LPTMR clock source */
lptmr_prescaler_glitch_value_t value; /*!< Prescaler or glitch filter value */
} lptmr_config_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Ungates the LPTMR clock and configures the peripheral for a basic operation.
*
* @note This API should be called at the beginning of the application using the LPTMR driver.
*
* @param base LPTMR peripheral base address
* @param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_Init(LPTMR_Type *base, const lptmr_config_t *config);
/*!
* @brief Gates the LPTMR clock.
*
* @param base LPTMR peripheral base address
*/
void LPTMR_Deinit(LPTMR_Type *base);
/*!
* @brief Fills in the LPTMR configuration structure with default settings.
*
* The default values are as follows.
* @code
* config->timerMode = kLPTMR_TimerModeTimeCounter;
* config->pinSelect = kLPTMR_PinSelectInput_0;
* config->pinPolarity = kLPTMR_PinPolarityActiveHigh;
* config->enableFreeRunning = false;
* config->bypassPrescaler = true;
* config->prescalerClockSource = kLPTMR_PrescalerClock_1;
* config->value = kLPTMR_Prescale_Glitch_0;
* @endcode
* @param config A pointer to the LPTMR configuration structure.
*/
void LPTMR_GetDefaultConfig(lptmr_config_t *config);
/*! @}*/
/*!
* @name Interrupt Interface
* @{
*/
/*!
* @brief Enables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to enable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline void LPTMR_EnableInterrupts(LPTMR_Type *base, uint32_t mask)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit so that we don't clear this w1c bit when writing back */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg |= mask;
base->CSR = reg;
}
/*!
* @brief Disables the selected LPTMR interrupts.
*
* @param base LPTMR peripheral base address
* @param mask The interrupts to disable. This is a logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t.
*/
static inline void LPTMR_DisableInterrupts(LPTMR_Type *base, uint32_t mask)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit so that we don't clear this w1c bit when writing back */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg &= ~mask;
base->CSR = reg;
}
/*!
* @brief Gets the enabled LPTMR interrupts.
*
* @param base LPTMR peripheral base address
*
* @return The enabled interrupts. This is the logical OR of members of the
* enumeration ::lptmr_interrupt_enable_t
*/
static inline uint32_t LPTMR_GetEnabledInterrupts(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TIE_MASK);
}
/*! @}*/
#if defined(FSL_FEATURE_LPTMR_HAS_CSR_TDRE) && (FSL_FEATURE_LPTMR_HAS_CSR_TDRE)
/*!
* @brief Enable or disable timer DMA request
*
* @param base base LPTMR peripheral base address
* @param enable Switcher of timer DMA feature. "true" means to enable, "false" means to disable.
*/
static inline void LPTMR_EnableTimerDMA(LPTMR_Type *base, bool enable)
{
if (enable)
{
base->CSR |= LPTMR_CSR_TDRE_MASK;
}
else
{
base->CSR &= ~(LPTMR_CSR_TDRE_MASK);
}
}
#endif /* FSL_FEATURE_LPTMR_HAS_CSR_TDRE */
/*!
* @name Status Interface
* @{
*/
/*!
* @brief Gets the LPTMR status flags.
*
* @param base LPTMR peripheral base address
*
* @return The status flags. This is the logical OR of members of the
* enumeration ::lptmr_status_flags_t
*/
static inline uint32_t LPTMR_GetStatusFlags(LPTMR_Type *base)
{
return (base->CSR & LPTMR_CSR_TCF_MASK);
}
/*!
* @brief Clears the LPTMR status flags.
*
* @param base LPTMR peripheral base address
* @param mask The status flags to clear. This is a logical OR of members of the
* enumeration ::lptmr_status_flags_t.
*/
static inline void LPTMR_ClearStatusFlags(LPTMR_Type *base, uint32_t mask)
{
base->CSR |= mask;
}
/*! @}*/
/*!
* @name Read and write the timer period
* @{
*/
/*!
* @brief Sets the timer period in units of count.
*
* Timers counts from 0 until it equals the count value set here. The count value is written to
* the CMR register.
*
* @note
* 1. The TCF flag is set with the CNR equals the count provided here and then increments.
* 2. Call the utility macros provided in the fsl_common.h to convert to ticks.
*
* @param base LPTMR peripheral base address
* @param ticks A timer period in units of ticks, which should be equal or greater than 1.
*/
static inline void LPTMR_SetTimerPeriod(LPTMR_Type *base, uint32_t ticks)
{
assert(ticks > 0U);
base->CMR = LPTMR_CMR_COMPARE(ticks - 1U);
}
/*!
* @brief Reads the current timer counting value.
*
* This function returns the real-time timer counting value in a range from 0 to a
* timer period.
*
* @note Call the utility macros provided in the fsl_common.h to convert ticks to usec or msec.
*
* @param base LPTMR peripheral base address
*
* @return The current counter value in ticks
*/
static inline uint32_t LPTMR_GetCurrentTimerCount(LPTMR_Type *base)
{
/* Must first write any value to the CNR. This synchronizes and registers the current value
* of the CNR into a temporary register which can then be read
*/
base->CNR = 0U;
return (uint32_t)((base->CNR & LPTMR_CNR_COUNTER_MASK) >> LPTMR_CNR_COUNTER_SHIFT);
}
/*! @}*/
/*!
* @name Timer Start and Stop
* @{
*/
/*!
* @brief Starts the timer.
*
* After calling this function, the timer counts up to the CMR register value.
* Each time the timer reaches the CMR value and then increments, it generates a
* trigger pulse and sets the timeout interrupt flag. An interrupt is also
* triggered if the timer interrupt is enabled.
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StartTimer(LPTMR_Type *base)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit to avoid clearing the w1c bit when writing back. */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg |= LPTMR_CSR_TEN_MASK;
base->CSR = reg;
}
/*!
* @brief Stops the timer.
*
* This function stops the timer and resets the timer's counter register.
*
* @param base LPTMR peripheral base address
*/
static inline void LPTMR_StopTimer(LPTMR_Type *base)
{
uint32_t reg = base->CSR;
/* Clear the TCF bit to avoid clearing the w1c bit when writing back. */
reg &= ~(LPTMR_CSR_TCF_MASK);
reg &= ~LPTMR_CSR_TEN_MASK;
base->CSR = reg;
}
/*! @}*/
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_LPTMR_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,522 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_lpuart_edma.h"
/*
* $Coverage Justification Reference$
*
* $Justification fsl_lpuart_edma_c_ref_1$
* The EDMA handle is only used by the LPUART EDMA driver, with the LPUART EDMA driver workflow,
* the callback is only called when EDMA transfer done.
*
* $Justification fsl_lpuart_edma_c_ref_2$
* This function only handles the kLPUART_TransmissionCompleteFlag event.
*
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.lpuart_edma"
#endif
/*<! Structure definition for lpuart_edma_private_handle_t. The structure is private. */
typedef struct _lpuart_edma_private_handle
{
LPUART_Type *base;
lpuart_edma_handle_t *handle;
} lpuart_edma_private_handle_t;
/* LPUART EDMA transfer handle. */
enum
{
kLPUART_TxIdle, /* TX idle. */
kLPUART_TxBusy, /* TX busy. */
kLPUART_RxIdle, /* RX idle. */
kLPUART_RxBusy /* RX busy. */
};
/*******************************************************************************
* Variables
******************************************************************************/
/* Array of LPUART handle. */
#if (defined(LPUART12))
#define LPUART_HANDLE_ARRAY_SIZE 13
#else /* LPUART12 */
#if (defined(LPUART11))
#define LPUART_HANDLE_ARRAY_SIZE 12
#else /* LPUART11 */
#if (defined(LPUART10))
#define LPUART_HANDLE_ARRAY_SIZE 11
#else /* LPUART10 */
#if (defined(LPUART9))
#define LPUART_HANDLE_ARRAY_SIZE 10
#else /* LPUART9 */
#if (defined(LPUART8))
#define LPUART_HANDLE_ARRAY_SIZE 9
#else /* LPUART8 */
#if (defined(LPUART7))
#define LPUART_HANDLE_ARRAY_SIZE 8
#else /* LPUART7 */
#if (defined(LPUART6))
#define LPUART_HANDLE_ARRAY_SIZE 7
#else /* LPUART6 */
#if (defined(LPUART5))
#define LPUART_HANDLE_ARRAY_SIZE 6
#else /* LPUART5 */
#if (defined(LPUART4))
#define LPUART_HANDLE_ARRAY_SIZE 5
#else /* LPUART4 */
#if (defined(LPUART3))
#define LPUART_HANDLE_ARRAY_SIZE 4
#else /* LPUART3 */
#if (defined(LPUART2))
#define LPUART_HANDLE_ARRAY_SIZE 3
#else /* LPUART2 */
#if (defined(LPUART1))
#define LPUART_HANDLE_ARRAY_SIZE 2
#else /* LPUART1 */
#if (defined(LPUART0))
#define LPUART_HANDLE_ARRAY_SIZE 1
#else /* LPUART0 */
#define LPUART_HANDLE_ARRAY_SIZE FSL_FEATURE_SOC_LPUART_COUNT
#endif /* LPUART 0 */
#endif /* LPUART 1 */
#endif /* LPUART 2 */
#endif /* LPUART 3 */
#endif /* LPUART 4 */
#endif /* LPUART 5 */
#endif /* LPUART 6 */
#endif /* LPUART 7 */
#endif /* LPUART 8 */
#endif /* LPUART 9 */
#endif /* LPUART 10 */
#endif /* LPUART 11 */
#endif /* LPUART 12 */
/*<! Private handle only used for internally. */
static lpuart_edma_private_handle_t s_lpuartEdmaPrivateHandle[LPUART_HANDLE_ARRAY_SIZE];
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief LPUART EDMA send finished callback function.
*
* This function is called when LPUART EDMA send finished. It disables the LPUART
* TX EDMA request and sends @ref kStatus_LPUART_TxIdle to LPUART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*!
* @brief LPUART EDMA receive finished callback function.
*
* This function is called when LPUART EDMA receive finished. It disables the LPUART
* RX EDMA request and sends @ref kStatus_LPUART_RxIdle to LPUART callback.
*
* @param handle The EDMA handle.
* @param param Callback function parameter.
*/
static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
/*******************************************************************************
* Code
******************************************************************************/
static void LPUART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
assert(NULL != param);
lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param;
/* Avoid the warning for unused variables. */
handle = handle;
tcds = tcds;
/*
* $Branch Coverage Justification$
* $ref fsl_lpuart_edma_c_ref_1$
*/
if (transferDone)
{
/* Disable LPUART TX EDMA. */
LPUART_EnableTxDMA(lpuartPrivateHandle->base, false);
/* Stop transfer. */
EDMA_AbortTransfer(handle);
/* Enable tx complete interrupt */
LPUART_EnableInterrupts(lpuartPrivateHandle->base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
}
}
static void LPUART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
{
assert(NULL != param);
lpuart_edma_private_handle_t *lpuartPrivateHandle = (lpuart_edma_private_handle_t *)param;
/* Avoid warning for unused parameters. */
handle = handle;
tcds = tcds;
/*
* $Branch Coverage Justification$
* $ref fsl_lpuart_edma_c_ref_1$
*/
if (transferDone)
{
/* Disable transfer. */
LPUART_TransferAbortReceiveEDMA(lpuartPrivateHandle->base, lpuartPrivateHandle->handle);
if (NULL != lpuartPrivateHandle->handle->callback)
{
lpuartPrivateHandle->handle->callback(lpuartPrivateHandle->base, lpuartPrivateHandle->handle,
kStatus_LPUART_RxIdle, lpuartPrivateHandle->handle->userData);
}
}
}
/*!
* brief Initializes the LPUART handle which is used in transactional functions.
*
* note This function disables all LPUART interrupts.
*
* param base LPUART peripheral base address.
* param handle Pointer to lpuart_edma_handle_t structure.
* param callback Callback function.
* param userData User data.
* param txEdmaHandle User requested DMA handle for TX DMA transfer.
* param rxEdmaHandle User requested DMA handle for RX DMA transfer.
*/
void LPUART_TransferCreateHandleEDMA(LPUART_Type *base,
lpuart_edma_handle_t *handle,
lpuart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle)
{
assert(NULL != handle);
uint32_t instance = LPUART_GetInstance(base);
s_lpuartEdmaPrivateHandle[instance].base = base;
s_lpuartEdmaPrivateHandle[instance].handle = handle;
(void)memset(handle, 0, sizeof(*handle));
handle->rxState = (uint8_t)kLPUART_RxIdle;
handle->txState = (uint8_t)kLPUART_TxIdle;
handle->rxEdmaHandle = rxEdmaHandle;
handle->txEdmaHandle = txEdmaHandle;
handle->callback = callback;
handle->userData = userData;
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
/* Note:
Take care of the RX FIFO, EDMA request only assert when received bytes
equal or more than RX water mark, there is potential issue if RX water
mark larger than 1.
For example, if RX FIFO water mark is 2, upper layer needs 5 bytes and
5 bytes are received. the last byte will be saved in FIFO but not trigger
EDMA transfer because the water mark is 2.
*/
if (NULL != rxEdmaHandle)
{
base->WATER &= (~LPUART_WATER_RXWATER_MASK);
}
#endif
/* Save the handle in global variables to support the double weak mechanism. */
s_lpuartHandle[instance] = handle;
/* Set LPUART_TransferEdmaHandleIRQ as DMA IRQ handler */
s_lpuartIsr[instance] = LPUART_TransferEdmaHandleIRQ;
/* Disable all LPUART internal interrupts */
LPUART_DisableInterrupts(base, (uint32_t)kLPUART_AllInterruptEnable);
/* Enable interrupt in NVIC. */
#if defined(FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ) && FSL_FEATURE_LPUART_HAS_SEPARATE_RX_TX_IRQ
(void)EnableIRQ(s_lpuartTxIRQ[instance]);
#else
(void)EnableIRQ(s_lpuartIRQ[instance]);
#endif
/* Configure TX. */
if (NULL != txEdmaHandle)
{
EDMA_SetCallback(handle->txEdmaHandle, LPUART_SendEDMACallback, &s_lpuartEdmaPrivateHandle[instance]);
}
/* Configure RX. */
if (NULL != rxEdmaHandle)
{
EDMA_SetCallback(handle->rxEdmaHandle, LPUART_ReceiveEDMACallback, &s_lpuartEdmaPrivateHandle[instance]);
}
}
/*!
* brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent, the send callback function is called.
*
* param base LPUART peripheral base address.
* param handle LPUART handle pointer.
* param xfer LPUART eDMA transfer structure. See #lpuart_transfer_t.
* retval kStatus_Success if succeed, others failed.
* retval kStatus_LPUART_TxBusy Previous transfer on going.
* retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(NULL != handle);
assert(NULL != handle->txEdmaHandle);
assert(NULL != xfer);
assert(NULL != xfer->data);
assert(0U != xfer->dataSize);
edma_transfer_config_t xferConfig;
status_t status;
/* If previous TX not finished. */
if ((uint8_t)kLPUART_TxBusy == handle->txState)
{
status = kStatus_LPUART_TxBusy;
}
else
{
handle->txState = (uint8_t)kLPUART_TxBusy;
handle->txDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t),
(void *)(uint32_t *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t),
xfer->dataSize, kEDMA_MemoryToPeripheral);
/* Store the initially configured eDMA minor byte transfer count into the LPUART handle */
handle->nbytes = (uint8_t)sizeof(uint8_t);
/* Submit transfer. */
if (kStatus_Success !=
EDMA_SubmitTransfer(handle->txEdmaHandle, (const edma_transfer_config_t *)(uint32_t)&xferConfig))
{
return kStatus_Fail;
}
EDMA_StartTransfer(handle->txEdmaHandle);
/* Enable LPUART TX EDMA. */
LPUART_EnableTxDMA(base, true);
status = kStatus_Success;
}
return status;
}
/*!
* brief Receives data using eDMA.
*
* This function receives data using eDMA. This is non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* param base LPUART peripheral base address.
* param handle Pointer to lpuart_edma_handle_t structure.
* param xfer LPUART eDMA transfer structure, see #lpuart_transfer_t.
* retval kStatus_Success if succeed, others fail.
* retval kStatus_LPUART_RxBusy Previous transfer ongoing.
* retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer)
{
assert(NULL != handle);
assert(NULL != handle->rxEdmaHandle);
assert(NULL != xfer);
assert(NULL != xfer->data);
assert(0U != xfer->dataSize);
edma_transfer_config_t xferConfig;
status_t status;
/* If previous RX not finished. */
if ((uint8_t)kLPUART_RxBusy == handle->rxState)
{
status = kStatus_LPUART_RxBusy;
}
else
{
handle->rxState = (uint8_t)kLPUART_RxBusy;
handle->rxDataSizeAll = xfer->dataSize;
/* Prepare transfer. */
EDMA_PrepareTransfer(&xferConfig, (void *)(uint32_t *)LPUART_GetDataRegisterAddress(base), sizeof(uint8_t),
xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory);
/* Store the initially configured eDMA minor byte transfer count into the LPUART handle */
handle->nbytes = (uint8_t)sizeof(uint8_t);
/* Submit transfer. */
if (kStatus_Success !=
EDMA_SubmitTransfer(handle->rxEdmaHandle, (const edma_transfer_config_t *)(uint32_t)&xferConfig))
{
return kStatus_Fail;
}
EDMA_StartTransfer(handle->rxEdmaHandle);
/* Enable LPUART RX EDMA. */
LPUART_EnableRxDMA(base, true);
status = kStatus_Success;
}
return status;
}
/*!
* brief Aborts the sent data using eDMA.
*
* This function aborts the sent data using eDMA.
*
* param base LPUART peripheral base address.
* param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle)
{
assert(NULL != handle);
assert(NULL != handle->txEdmaHandle);
/* Disable LPUART TX EDMA. */
LPUART_EnableTxDMA(base, false);
/* Stop transfer. */
EDMA_AbortTransfer(handle->txEdmaHandle);
handle->txState = (uint8_t)kLPUART_TxIdle;
}
/*!
* brief Aborts the received data using eDMA.
*
* This function aborts the received data using eDMA.
*
* param base LPUART peripheral base address.
* param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle)
{
assert(NULL != handle);
assert(NULL != handle->rxEdmaHandle);
/* Disable LPUART RX EDMA. */
LPUART_EnableRxDMA(base, false);
/* Stop transfer. */
EDMA_AbortTransfer(handle->rxEdmaHandle);
handle->rxState = (uint8_t)kLPUART_RxIdle;
}
/*!
* brief Gets the number of received bytes.
*
* This function gets the number of received bytes.
*
* param base LPUART peripheral base address.
* param handle LPUART handle pointer.
* param count Receive bytes count.
* retval kStatus_NoTransferInProgress No receive in progress.
* retval kStatus_InvalidArgument Parameter is invalid.
* retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count)
{
assert(NULL != handle);
assert(NULL != handle->rxEdmaHandle);
assert(NULL != count);
if ((uint8_t)kLPUART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->rxDataSizeAll -
((uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel));
return kStatus_Success;
}
/*!
* brief Gets the number of bytes written to the LPUART TX register.
*
* This function gets the number of bytes written to the LPUART TX
* register by DMA.
*
* param base LPUART peripheral base address.
* param handle LPUART handle pointer.
* param count Send bytes count.
* retval kStatus_NoTransferInProgress No send in progress.
* retval kStatus_InvalidArgument Parameter is invalid.
* retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count)
{
assert(NULL != handle);
assert(NULL != handle->txEdmaHandle);
assert(NULL != count);
if ((uint8_t)kLPUART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll -
((uint32_t)handle->nbytes *
EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel));
return kStatus_Success;
}
/*!
* brief LPUART eDMA IRQ handle function.
*
* This function handles the LPUART tx complete IRQ request and invoke user callback.
* It is not set to static so that it can be used in user application.
* note This function is used as default IRQ handler by double weak mechanism.
* If user's specific IRQ handler is implemented, make sure this function is invoked in the handler.
*
* param base LPUART peripheral base address.
* param lpuartEdmaHandle LPUART handle pointer.
*/
void LPUART_TransferEdmaHandleIRQ(LPUART_Type *base, void *lpuartEdmaHandle)
{
assert(lpuartEdmaHandle != NULL);
/*
* $Branch Coverage Justification$
* $ref fsl_lpuart_edma_c_ref_2$
*/
if (((uint32_t)kLPUART_TransmissionCompleteFlag & LPUART_GetStatusFlags(base)) != 0U)
{
lpuart_edma_handle_t *handle = (lpuart_edma_handle_t *)lpuartEdmaHandle;
/* Disable tx complete interrupt */
LPUART_DisableInterrupts(base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
handle->txState = (uint8_t)kLPUART_TxIdle;
if (handle->callback != NULL)
{
handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData);
}
}
}

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_LPUART_EDMA_H_
#define FSL_LPUART_EDMA_H_
#include "fsl_lpuart.h"
#include "fsl_edma.h"
/*!
* @addtogroup lpuart_edma_driver
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief LPUART EDMA driver version. */
#define FSL_LPUART_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 6, 0))
/*! @} */
/* Forward declaration of the handle typedef. */
typedef struct _lpuart_edma_handle lpuart_edma_handle_t;
/*! @brief LPUART transfer callback function. */
typedef void (*lpuart_edma_transfer_callback_t)(LPUART_Type *base,
lpuart_edma_handle_t *handle,
status_t status,
void *userData);
/*!
* @brief LPUART eDMA handle
*/
struct _lpuart_edma_handle
{
lpuart_edma_transfer_callback_t callback; /*!< Callback function. */
void *userData; /*!< LPUART callback function parameter.*/
size_t rxDataSizeAll; /*!< Size of the data to receive. */
size_t txDataSizeAll; /*!< Size of the data to send out. */
edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */
edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
volatile uint8_t txState; /*!< TX transfer state. */
volatile uint8_t rxState; /*!< RX transfer state */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name eDMA transactional
* @{
*/
/*!
* @brief Initializes the LPUART handle which is used in transactional functions.
*
* @note This function disables all LPUART interrupts.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
* @param callback Callback function.
* @param userData User data.
* @param txEdmaHandle User requested DMA handle for TX DMA transfer.
* @param rxEdmaHandle User requested DMA handle for RX DMA transfer.
*/
void LPUART_TransferCreateHandleEDMA(LPUART_Type *base,
lpuart_edma_handle_t *handle,
lpuart_edma_transfer_callback_t callback,
void *userData,
edma_handle_t *txEdmaHandle,
edma_handle_t *rxEdmaHandle);
/*!
* @brief Sends data using eDMA.
*
* This function sends data using eDMA. This is a non-blocking function, which returns
* right away. When all data is sent, the send callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param xfer LPUART eDMA transfer structure. See #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others failed.
* @retval kStatus_LPUART_TxBusy Previous transfer on going.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_SendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Receives data using eDMA.
*
* This function receives data using eDMA. This is non-blocking function, which returns
* right away. When all data is received, the receive callback function is called.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
* @param xfer LPUART eDMA transfer structure, see #lpuart_transfer_t.
* @retval kStatus_Success if succeed, others fail.
* @retval kStatus_LPUART_RxBusy Previous transfer ongoing.
* @retval kStatus_InvalidArgument Invalid argument.
*/
status_t LPUART_ReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, lpuart_transfer_t *xfer);
/*!
* @brief Aborts the sent data using eDMA.
*
* This function aborts the sent data using eDMA.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortSendEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle);
/*!
* @brief Aborts the received data using eDMA.
*
* This function aborts the received data using eDMA.
*
* @param base LPUART peripheral base address.
* @param handle Pointer to lpuart_edma_handle_t structure.
*/
void LPUART_TransferAbortReceiveEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle);
/*!
* @brief Gets the number of bytes written to the LPUART TX register.
*
* This function gets the number of bytes written to the LPUART TX
* register by DMA.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Send bytes count.
* @retval kStatus_NoTransferInProgress No send in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetSendCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count);
/*!
* @brief Gets the number of received bytes.
*
* This function gets the number of received bytes.
*
* @param base LPUART peripheral base address.
* @param handle LPUART handle pointer.
* @param count Receive bytes count.
* @retval kStatus_NoTransferInProgress No receive in progress.
* @retval kStatus_InvalidArgument Parameter is invalid.
* @retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t LPUART_TransferGetReceiveCountEDMA(LPUART_Type *base, lpuart_edma_handle_t *handle, uint32_t *count);
/*!
* @brief LPUART eDMA IRQ handle function.
*
* This function handles the LPUART tx complete IRQ request and invoke user callback.
* It is not set to static so that it can be used in user application.
* @note This function is used as default IRQ handler by double weak mechanism.
* If user's specific IRQ handler is implemented, make sure this function is invoked in the handler.
*
* @param base LPUART peripheral base address.
* @param lpuartEdmaHandle LPUART handle pointer.
*/
void LPUART_TransferEdmaHandleIRQ(LPUART_Type *base, void *lpuartEdmaHandle);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_LPUART_EDMA_H_ */

View File

@ -0,0 +1,193 @@
/*
* Copyright 2021-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_opamp.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.opamp"
#endif
#if defined(OPAMP_RSTS)
#define OPAMP_RESETS_ARRAY OPAMP_RSTS
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
static uint32_t OPAMP_GetInstance(OPAMP_Type *base);
/*******************************************************************************
* Variables
******************************************************************************/
static OPAMP_Type *const s_opampBases[] = OPAMP_BASE_PTRS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/*! @brief Pointers to OPAMP clocks for each instance. */
static const clock_ip_name_t s_opampClocks[] = OPAMP_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(OPAMP_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_opampResets[] = OPAMP_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
static uint32_t OPAMP_GetInstance(OPAMP_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0UL; instance < ARRAY_SIZE(s_opampBases); instance++)
{
if (s_opampBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_opampBases));
return instance;
}
/*!
* brief Initialize OPAMP instance.
*
* param base OPAMP peripheral base address.
* param config The pointer to opamp_config_t.
*/
void OPAMP_Init(OPAMP_Type *base, const opamp_config_t *config)
{
assert(config != NULL);
uint32_t tmp32 = 0U;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable the clock. */
CLOCK_EnableClock(s_opampClocks[OPAMP_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(OPAMP_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_opampResets[OPAMP_GetInstance(base)]);
#endif
tmp32 = OPAMP_OPAMP_CTR_EN(config->enable) | OPAMP_OPAMP_CTR_MODE(config->mode) |
OPAMP_OPAMP_CTR_BIASC(config->trimOption) | OPAMP_OPAMP_CTR_INTREF(config->intRefVoltage) |
OPAMP_OPAMP_CTR_PREF(config->posRefVoltage) |
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW
OPAMP_OPAMP_CTR_OUTSW(config->enableOutputSwitch) |
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1
OPAMP_OPAMP_CTR_ADCSW1(config->enablePosADCSw1) |
#else
OPAMP_OPAMP_CTR_ADCSW(config->enablePosADCSw) |
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2
OPAMP_OPAMP_CTR_ADCSW2(config->enablePosADCSw2) |
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
OPAMP_OPAMP_CTR_INPSEL(config->PosInputChannelSelection) |
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
OPAMP_OPAMP_CTR_TRIGMD(config->enableTriggerMode) |
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
OPAMP_OPAMP_CTR_NGAIN(config->negGain);
base->OPAMP_CTR = tmp32;
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
if (config->enableRefBuffer)
{
assert((uint32_t)(config->posGain) <= 7UL);
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain) | OPAMP_OPAMP_CTR_BUFEN_MASK;
}
else
{
if ((uint32_t)(config->posGain) > 7UL)
{
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN((uint32_t)(config->posGain) - 7UL);
}
else
{
assert((uint32_t)(config->posGain) == 0UL);
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain);
}
}
#else
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_PGAIN(config->posGain);
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
}
/*!
* brief De-initialize OPAMP instance.
*
* param base OPAMP peripheral base address.
*/
void OPAMP_Deinit(OPAMP_Type *base)
{
/* Disable OPAMP instance. */
base->OPAMP_CTR &= ~OPAMP_OPAMP_CTR_EN_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable the clock. */
CLOCK_DisableClock(s_opampClocks[OPAMP_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* brief Get default configuration of OPAMP.
*
* code
* config->enable = false;
* config->mode = kOPAMP_LowNoiseMode;
* config->trimOption = kOPAMP_TrimOptionDefault;
* config->intRefVoltage = kOPAMP_IntRefVoltVddaDiv2;
* config->enablePosADCSw = false;
* config->posRefVoltage = kOPAMP_PosRefVoltVrefh3;
* config->posGain = kOPAMP_PosGainReserved;
* config->negGain = kOPAMP_NegGainBufferMode;
* endcode
*
* param config The pointer to opamp_config_t.
*/
void OPAMP_GetDefaultConfig(opamp_config_t *config)
{
assert(config != NULL);
config->enable = false;
config->mode = kOPAMP_LowNoiseMode;
config->trimOption = kOPAMP_TrimOptionDefault;
config->intRefVoltage = kOPAMP_IntRefVoltVddaDiv2;
config->posRefVoltage = kOPAMP_PosRefVoltVrefh3;
config->posGain = kOPAMP_PosGainReserved;
config->negGain = kOPAMP_NegGainBufferMode;
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW
config->enableOutputSwitch = true;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1
config->enablePosADCSw1 = false;
#else
config->enablePosADCSw = false;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2
config->enablePosADCSw2 = false;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
config->enableRefBuffer = false;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
config->PosInputChannelSelection = kOPAMP_PosInputChannel0;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
config->enableTriggerMode = false;
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
}

View File

@ -0,0 +1,301 @@
/*
* Copyright 2021-2022, 2024 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_OPAMP_H_
#define FSL_OPAMP_H_
#include "fsl_common.h"
/*!
* @addtogroup opamp
* @{
*/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief OPAMP driver version. */
#define FSL_OPAMP_DRIVER_VERSION (MAKE_VERSION(2, 2, 0))
/*! @} */
/*!
* @brief The enumeration of OPAMP mode, including low noise mode and high speed mode.
*/
typedef enum _opamp_mode
{
kOPAMP_LowNoiseMode = 0U, /*!< Set opamp mode as low noise mode. */
kOPAMP_HighSpeedMode, /*!< Set opamp mode as high speed mode. */
} opamp_mode_t;
/*!
* @brief The enumeration of bias current trim option.
*/
typedef enum _opamp_bias_current_trim_option
{
kOPAMP_TrimOptionDefault = 0U, /*!< Default Bias current trim option. */
kOPAMP_TrimOptionIncreaseCurrent, /*!< Trim option selected as increase current. */
kOPAMP_TrimOptionDecreaseCurrent, /*!< Trim option selected as decrease current. */
kOPAMP_TrimOptionFurtherDecreaseCurrent, /*!< Trim option selected as further decrease current. */
} opamp_bias_current_trim_option_t;
/*!
* @brief The enumeration of internal reference voltage.
*/
typedef enum _opamp_internal_ref_voltage
{
kOPAMP_IntRefVoltVddaDiv2 = 0U, /*!< Internal reference voltage selected as Vdda/2. */
kOPAMP_IntRefVoltVdda3V, /*!< Internal reference voltage selected as Vdda_3V. */
kOPAMP_IntRefVoltVssa3V, /*!< Internal reference voltage selected as Vssa_3V. */
kOPAMP_IntRefVoltNotAllowed, /*!< Internal reference voltage not allowed. */
} opamp_internal_ref_voltage_t;
/*!
* @brief The enumeration of positive reference voltageplease refer to manual use.
*/
typedef enum _opamp_positive_ref_voltage
{
kOPAMP_PosRefVoltVrefh3 = 0U, /*!< Positive part reference voltage select Vrefh3, connected from DAC output. */
kOPAMP_PosRefVoltVrefh0 = 1U, /*!< Positive part reference voltage select Vrefh0, connected from VDDA supply. */
kOPAMP_PosRefVoltVrefh1 = 2U, /*!< Positive part reference voltage select Vrefh1,
connected from Voltage reference output. */
kOPAMP_PosRefVoltVrefh4 = 3U, /*!< Positive part reference voltage select 520mv or reserved.*/
} opamp_positive_ref_voltage_t;
/*!
* @brief The enumeration of positive programmable gain (please refer to manual use).
*/
typedef enum _opamp_positive_gain
{
kOPAMP_PosGainReserved = 0U, /*!< Positive Gain reserved. */
kOPAMP_PosGainNonInvert1X = 1U, /*!< Positive non-inverting gain application 1X. */
kOPAMP_PosGainNonInvert2X = 2U, /*!< Positive non-inverting gain application 2X. */
kOPAMP_PosGainNonInvert4X = 3U, /*!< Positive non-inverting gain application 4X. */
kOPAMP_PosGainNonInvert8X = 4U, /*!< Positive non-inverting gain application 8X. */
kOPAMP_PosGainNonInvert16X = 5U, /*!< Positive non-inverting gain application 16X. */
kOPAMP_PosGainNonInvert33X = 6U, /*!< Positive non-inverting gain application 33X. */
kOPAMP_PosGainNonInvert64X = 7U, /*!< Positive non-inverting gain application 64X. */
#if defined(FSL_FEATURE_OPAMP_HAS_SUPPORT_REFERENCE_BUFFER) && FSL_FEATURE_OPAMP_HAS_SUPPORT_REFERENCE_BUFFER
/* The following gain selections are for basic OPAMP only, and signal inputs are
supported on the non-inverting and inverting terminals.*/
kOPAMP_PosGainNonInvertDisableBuffer2X = 8U, /*!< Positive non-inverting gain application 2X. */
kOPAMP_PosGainNonInvertDisableBuffer3X = 9U, /*!< Positive non-inverting gain application 3X. */
kOPAMP_PosGainNonInvertDisableBuffer5X = 10U, /*!< Positive non-inverting gain application 5X. */
kOPAMP_PosGainNonInvertDisableBuffer9X = 11U, /*!< Positive non-inverting gain application 9X. */
kOPAMP_PosGainNonInvertDisableBuffer17X = 12U, /*!< Positive non-inverting gain application 17X. */
kOPAMP_PosGainNonInvertDisableBuffer34X = 13U, /*!< Positive non-inverting gain application 34X. */
kOPAMP_PosGainNonInvertDisableBuffer65X = 14U, /*!< Positive non-inverting gain application 65X. */
#endif /* FSL_FEATURE_OPAMP_HAS_SUPPORT_REFERENCE_BUFFER */
} opamp_positive_gain_t;
/*!
* @brief The enumeration of negative programmable gain.
*/
typedef enum _opamp_negative_gain
{
kOPAMP_NegGainBufferMode = 0U, /*!< Negative Buffer Mode. */
kOPAMP_NegGainInvert1X, /*!< Negative inverting gain application -1X. */
kOPAMP_NegGainInvert2X, /*!< Negative inverting gain application -2X. */
kOPAMP_NegGainInvert4X, /*!< Negative inverting gain application -4X. */
kOPAMP_NegGainInvert8X, /*!< Negative inverting gain application -8X. */
kOPAMP_NegGainInvert16X, /*!< Negative inverting gain application -16X. */
kOPAMP_NegGainInvert33X, /*!< Negative inverting gain application -33X. */
kOPAMP_NegGainInvert64X, /*!< Negative inverting gain application -64X. */
} opamp_negative_gain_t;
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
/*!
* @brief The enumeration of positive input channel selection.
*/
typedef enum _opamp_positive_input_channel_selection
{
kOPAMP_PosInputChannel0 = 0U, /*!< When OPAMP not in trigger mode, select positive input 0 (INP0).*/
kOPAMP_PosInputChannel1 = 1U, /*!< When OPAMP not in trigger mode, select positive input 1 (INP1).*/
} opamp_positive_input_channel_selection_t;
#endif
/*!
* @brief OPAMP configuraion, including mode, internal reference voltage, positive gain, negative gain and so on.
*/
typedef struct _opamp_config
{
bool enable; /*!< Enable/disable OPAMP. */
opamp_mode_t mode; /*!< Opamp mode, available values are @ref kOPAMP_LowNoiseMode and @ref kOPAMP_HighSpeedMode. */
opamp_bias_current_trim_option_t trimOption; /*!< Bias current trim option, please refer to
@ref opamp_bias_current_trim_option_t. */
opamp_internal_ref_voltage_t intRefVoltage; /*!< Internal reference voltage, please refer to
@ref opamp_internal_ref_voltage_t. */
opamp_positive_ref_voltage_t posRefVoltage; /*!< Positive part reference voltage, please refer
to @ref opamp_positive_ref_voltage_t. */
/* Positive part configuration. */
opamp_positive_gain_t posGain; /*!< Positive part programmable gain, please refer
to @ref opamp_positive_gain_t. */
/* Negative part configuration. */
opamp_negative_gain_t negGain; /*!< Negative part programmable gain, please refer
to @ref opamp_negative_gain_t. */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW
bool enableOutputSwitch; /*!< OPAMP out to negative gain resistor ladder switch.*/
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_OUTSW */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1
bool enablePosADCSw1; /*!< Positive part reference voltage switch to ADC channel or not.
- \b true Positive part reference voltage switch to ADC channel.
- \b false Positive part reference voltage do not switch to ADC channel. */
#else
bool enablePosADCSw; /*!< Positive part reference voltage switch to ADC channel or not.
- \b true Positive part reference voltage switch to ADC channel.
- \b false Positive part reference voltage do not switch to ADC channel. */
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW1 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2
bool enablePosADCSw2; /*!< Positive part reference voltage switch to ADC channel or not.
- \b true Positive part reference voltage switch to ADC channel.
- \b false Positive part reference voltage do not switch to ADC channel. */
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_ADCSW2 */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
bool enableRefBuffer; /*!< Reference buffer enable.*/
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL
opamp_positive_input_channel_selection_t PosInputChannelSelection; /*!< Positive Input Channel Selection*/
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_INPSEL */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
bool enableTriggerMode; /*!< Trigger Mode Enable.*/
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
} opamp_config_t;
/*******************************************************************************
* API
*******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initialize OPAMP instance.
*
* @param base OPAMP peripheral base address.
* @param config The pointer to @ref opamp_config_t.
*/
void OPAMP_Init(OPAMP_Type *base, const opamp_config_t *config);
/*!
* @brief De-initialize OPAMP instance.
*
* @param base OPAMP peripheral base address.
*/
void OPAMP_Deinit(OPAMP_Type *base);
/*!
* @brief Get default configuration of OPAMP.
*
* @code
* config->enable = false;
* config->mode = kOPAMP_LowNoiseMode;
* config->trimOption = kOPAMP_TrimOptionDefault;
* config->intRefVoltage = kOPAMP_IntRefVoltVddaDiv2;
* config->enablePosADCSw = false;
* config->posRefVoltage = kOPAMP_PosRefVoltVrefh3;
* config->posGain = kOPAMP_PosGainReserved;
* config->negGain = kOPAMP_NegGainBufferMode;
* @endcode
*
* @param config The pointer to @ref opamp_config_t.
*/
void OPAMP_GetDefaultConfig(opamp_config_t *config);
/*! @} */
/*!
* @name Positive port gain and negative gain configuration.
* @{
*/
/*!
* @brief Configure OPAMP positive port gain.
*
* @param base OPAMP peripheral base address.
* @param option OPAMP positive port gain.
*/
static inline void OPAMP_DoPosGainConfig(OPAMP_Type *base, opamp_positive_gain_t option)
{
base->OPAMP_CTR = (((base->OPAMP_CTR) & (~OPAMP_OPAMP_CTR_PGAIN_MASK)) | OPAMP_OPAMP_CTR_PGAIN(option));
}
/*!
* @brief Configure OPAMP negative port gain.
*
* @param base OPAMP peripheral base address.
* @param option OPAMP negative port gain.
*/
static inline void OPAMP_DoNegGainConfig(OPAMP_Type *base, opamp_negative_gain_t option)
{
base->OPAMP_CTR = (((base->OPAMP_CTR) & (~OPAMP_OPAMP_CTR_NGAIN_MASK)) | OPAMP_OPAMP_CTR_NGAIN(option));
}
/*! @} */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN
/*!
* @name Reference Buffer Control Interface
* @{
*/
/*!
* @brief Enable reference buffer.
*
* @param base OPAMP peripheral base address.
* @param enable true to enable and false to disable.
*/
static inline void OPAMP_EnableRefBuffer(OPAMP_Type *base, bool enable)
{
if (enable)
{
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_BUFEN_MASK;
}
else
{
base->OPAMP_CTR &= ~(uint32_t)OPAMP_OPAMP_CTR_BUFEN_MASK;
}
}
/*! @} */
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_BUFEN */
#if defined(FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD) && FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD
/*!
* @name Trigger Mode Control Interface
* @{
*/
/*!
* @brief Enable OPAMP trigger mode.
*
* @param base OPAMP peripheral base address.
* @param enable true to enable and false to disable.
*/
static inline void OPAMP_EnableTriggerMode(OPAMP_Type *base, bool enable)
{
if (enable)
{
base->OPAMP_CTR |= OPAMP_OPAMP_CTR_TRIGMD_MASK;
}
else
{
base->OPAMP_CTR &= ~(uint32_t)OPAMP_OPAMP_CTR_TRIGMD_MASK;
}
}
/*! @} */
#endif /* FSL_FEATURE_OPAMP_HAS_OPAMP_CTR_TRIGMD */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* FSL_OPAMP_H_ */

View File

@ -0,0 +1,384 @@
/*
* Copyright 2018-2021, 2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_ostimer.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.ostimer"
#endif
#if defined(OSTIMER_RSTS)
#define OSTIMER_RESETS_ARRAY OSTIMER_RSTS
#endif
/* Typedef for interrupt handler. */
typedef void (*ostimer_isr_t)(OSTIMER_Type *base, ostimer_callback_t cb);
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Gets the instance from the base address
*
* @param base OSTIMER peripheral base address
*
* @return The OSTIMER instance
*/
static uint32_t OSTIMER_GetInstance(OSTIMER_Type *base);
#if (defined(FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY) && FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY)
/* @brief Translate the value from gray-code to decimal by the Code Gray in SYSCTL.
*
* @param gray The gray value input.
*
* @return the decimal value.
*/
static uint64_t OSTIMER_GrayToDecimalbyCodeGray(uint64_t gray);
#endif /* FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY. */
/*******************************************************************************
* Variables
******************************************************************************/
/* Array of OSTIMER handle. */
static ostimer_callback_t s_ostimerHandle[FSL_FEATURE_SOC_OSTIMER_COUNT];
/* Array of OSTIMER peripheral base address. */
static OSTIMER_Type *const s_ostimerBases[] = OSTIMER_BASE_PTRS;
/* Array of OSTIMER IRQ number. */
static const IRQn_Type s_ostimerIRQ[] = OSTIMER_IRQS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Array of OSTIMER clock name. */
static const clock_ip_name_t s_ostimerClock[] = OSTIMER_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* OSTIMER ISR for transactional APIs. */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
static ostimer_isr_t s_ostimerIsr = (ostimer_isr_t)DefaultISR;
#else
static ostimer_isr_t s_ostimerIsr;
#endif
#if defined(OSTIMER_RESETS_ARRAY)
/* Reset array */
static const reset_ip_name_t s_ostimerResets[] = OSTIMER_RESETS_ARRAY;
#endif
/*******************************************************************************
* Code
******************************************************************************/
/* @brief Function for getting the instance number of OS timer. */
static uint32_t OSTIMER_GetInstance(OSTIMER_Type *base)
{
uint32_t instance;
/* Find the instance index from base address mappings. */
for (instance = 0; instance < ARRAY_SIZE(s_ostimerBases); instance++)
{
if (s_ostimerBases[instance] == base)
{
break;
}
}
assert(instance < ARRAY_SIZE(s_ostimerBases));
return instance;
}
#if (defined(FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY) && FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY)
/* @brief Translate the value from gray-code to decimal by the Code Gray in SYSCTL.
*
* @param gray The gray value input.
*
* @return the decimal value.
*/
static uint64_t OSTIMER_GrayToDecimalbyCodeGray(uint64_t gray)
{
uint64_t decOut;
SYSCTL->CODE_GRAY_LSB = (uint32_t)(gray & 0xFFFFFFFFU);
SYSCTL->CODE_GRAY_MSB = (uint32_t)((gray >> 32U) & 0x3FFU); // limit to 42bits as OSevent timer
__NOP();
decOut = ((uint64_t)(SYSCTL->CODE_BIN_MSB) & 0x3FFU) << 32U;
decOut |= (uint64_t)(SYSCTL->CODE_BIN_LSB);
return decOut;
}
#endif /* FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY. */
/* @brief Translate the value from gray-code to decimal. */
/*
* @param gray The gray value input.
*
* @return the decimal value.
*/
uint64_t OSTIMER_GrayToDecimal(uint64_t gray)
{
#if (defined(FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY) && FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY)
return OSTIMER_GrayToDecimalbyCodeGray(gray);
#else
uint64_t temp = gray;
while (temp != 0U)
{
temp >>= 1U;
gray ^= temp;
}
return gray;
#endif /* FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY. */
}
/* @brief Enable the OSTIMER interrupt.
*
* After calling this function, the OSTIMER driver will enable/disable the IRQ and module interrupt enablement.
*
* @param base OSTIMER peripheral base address.
* @param enable enable/disable the IRQ and module interrupt enablement.
* - true: Disable the IRQ and module interrupt enablement.
* - false: Disable the IRQ and module interrupt enablement.
* @return none
*/
static void OSTIMER_EnableInterrupt(OSTIMER_Type *base, bool enable)
{
assert(NULL != base);
if (enable)
{
/* Enable the IRQ and module interrupt enablement. */
(void)EnableIRQ(s_ostimerIRQ[OSTIMER_GetInstance(base)]);
base->OSEVENT_CTRL |= OSTIMER_OSEVENT_CTRL_OSTIMER_INTENA_MASK;
}
else
{
/* Clear interrupt flag, disable the IRQ and module interrupt enablement. */
(void)DisableIRQ(s_ostimerIRQ[OSTIMER_GetInstance(base)]);
base->OSEVENT_CTRL &= ~OSTIMER_OSEVENT_CTRL_OSTIMER_INTENA_MASK; /* Clear interrupt flag by writing 1. */
}
}
/*!
* @brief Initializes an OSTIMER by turning it's clock on.
*
*/
void OSTIMER_Init(OSTIMER_Type *base)
{
assert(NULL != base);
uint32_t instance = OSTIMER_GetInstance(base);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
#if !(defined(FSL_FEATURE_PMC_HAS_NO_OSTIMER_REG) && FSL_FEATURE_PMC_HAS_NO_OSTIMER_REG)
/* Enable the OSTIMER 32k clock in PMC module. */
CLOCK_EnableOstimer32kClock();
#endif
/* Enable clock for OSTIMER. */
CLOCK_EnableClock(s_ostimerClock[instance]);
#if (defined(FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY) && FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY)
CLOCK_EnableClock(kCLOCK_Sysctl);
#endif /* FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY. */
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
#if defined(OSTIMER_RESETS_ARRAY)
RESET_ReleasePeripheralReset(s_ostimerResets[OSTIMER_GetInstance(base)]);
#endif
}
/*!
* @brief Deinitializes a OSTIMER instance.
*
* This function shuts down OSTIMER clock
*
* @param base OSTIMER peripheral base address.
*/
void OSTIMER_Deinit(OSTIMER_Type *base)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable clock for OSTIMER. */
CLOCK_DisableClock(s_ostimerClock[OSTIMER_GetInstance(base)]);
#if (defined(FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY) && FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY)
CLOCK_DisableClock(kCLOCK_Sysctl);
#endif /* FSL_FEATURE_SYSCTRL_HAS_CODE_GRAY. */
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!
* @brief Get OSTIMER status Flags.
*
* This returns the status flag.
* Currently, only match interrupt flag can be got.
*
* @param base OSTIMER peripheral base address.
* @return status register value
*/
uint32_t OSTIMER_GetStatusFlags(OSTIMER_Type *base)
{
return base->OSEVENT_CTRL & OSTIMER_OSEVENT_CTRL_OSTIMER_INTRFLAG_MASK;
}
/*!
* @brief Clear Status Interrupt Flags.
*
* This clears intr status flag.
* Currently, only match interrupt flag can be cleared.
*
* @param base OSTIMER peripheral base address.
* @param mask Clear bit mask.
* @return none
*/
void OSTIMER_ClearStatusFlags(OSTIMER_Type *base, uint32_t mask)
{
base->OSEVENT_CTRL |= mask;
}
/*!
* @brief Set the match raw value for OSTIMER.
*
* This function will set a match value for OSTIMER with an optional callback. And this callback
* will be called while the data in dedicated pair match register is equals to the value of central EVTIMER.
* Please note that, the data format is gray-code, if decimal data was desired, please using OSTIMER_SetMatchValue().
*
* @param base OSTIMER peripheral base address.
* @param count OSTIMER timer match value.(Value is gray-code format)
*
* @param cb OSTIMER callback (can be left as NULL if none, otherwise should be a void func(void)).
* @retval kStatus_Success - Set match raw value and enable interrupt Successfully.
* @retval kStatus_Fail - Set match raw value fail.
*/
status_t OSTIMER_SetMatchRawValue(OSTIMER_Type *base, uint64_t count, ostimer_callback_t cb)
{
#ifdef OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK
uint64_t decValueTimer;
#endif
status_t status;
uint64_t tmp = count;
uint32_t instance = OSTIMER_GetInstance(base);
/* Clear interrupt flag, disable the IRQ and module interrupt enablement. */
OSTIMER_EnableInterrupt(base, false);
s_ostimerIsr = OSTIMER_HandleIRQ;
s_ostimerHandle[instance] = cb;
/* Set the match value. */
base->MATCH_L = (uint32_t)tmp;
base->MATCH_H = (uint32_t)(tmp >> 32U);
#ifdef OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK
/* Workaround-2019-12-30:
* Since OSTimer's counter register is Gray-encoded, it would cost more time to write register. When EVTimer Match
* Write Ready bit is low, which means the previous match value has been updated successfully by that time, it is
* safe to reload (write) the Match Registers. Even if there is the RM comment that "In typical applications, it
* should not be necessary to test this bit", but we found the interruption would not be reported when the delta
* timer user added is smaller(IE: RT595 11us in 1MHz typical application) in release version." To prevent such
* issue from happening, we'd better wait for the match value to update successfully before enabling IRQ.
*/
while (0U != (base->OSEVENT_CTRL & OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK))
{
}
/* After the WR_RDY bit became low, we need to check whether current time goes ahead of the match value we set.
* (1) If current timer value has gone ahead of the match value, the interrupt will not be reported before 64-bit
* timer value over flow. We need to check whether the interrupt flag has been set or not: if yes, we will enable
* interrupt and return success; if not, we will return fail directly.
* (2) If current timer value has not gone ahead of match value, we will enable interrupt and return success.
*/
decValueTimer = OSTIMER_GetCurrentTimerValue(base);
if ((decValueTimer >= OSTIMER_GrayToDecimal(tmp)) &&
(0U == (base->OSEVENT_CTRL & (uint32_t)kOSTIMER_MatchInterruptFlag)))
{
status = kStatus_Fail;
}
else
#endif /* #ifdef OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK */
{
/* Enable the module interrupt enablement. */
OSTIMER_EnableInterrupt(base, true);
status = kStatus_Success;
}
return status;
}
/*!
* @brief Set the match value for OSTIMER.
*
* This function will set a match value for OSTIMER with an optional callback. And this callback
* will be called while the data in dedicated pair match register is equals to the value of central EVTIMER.
*
* @param base OSTIMER peripheral base address.
* @param count OSTIMER timer match value.(Value is decimal format, and this value will be translate to Gray code in
* API. )
* @param cb OSTIMER callback (can be left as NULL if none, otherwise should be a void func(void)).
* @retval kStatus_Success - Set match value and enable interrupt Successfully.
* @retval kStatus_Fail - Set match value fail.
*/
status_t OSTIMER_SetMatchValue(OSTIMER_Type *base, uint64_t count, ostimer_callback_t cb)
{
uint64_t tmp = OSTIMER_DecimalToGray(count);
return OSTIMER_SetMatchRawValue(base, tmp, cb);
}
/*!
* @brief Get current timer count value from OSTIMER.
*
* This function will get a decimal timer count value.
* The RAW value of timer count is gray code format, will be translated to decimal data internally.
*
* @param base OSTIMER peripheral base address.
* @return Value of OSTIMER which will formated to decimal value.
*/
uint64_t OSTIMER_GetCurrentTimerValue(OSTIMER_Type *base)
{
uint64_t tmp = 0U;
tmp = OSTIMER_GetCurrentTimerRawValue(base);
return OSTIMER_GrayToDecimal(tmp);
}
/*!
* @brief Get the capture value from OSTIMER.
*
* This function will get a capture decimal-value from OSTIMER.
* The RAW value of timer capture is gray code format, will be translated to decimal data internally.
*
* @param base OSTIMER peripheral base address.
* @return Value of capture register, data format is decimal.
*/
uint64_t OSTIMER_GetCaptureValue(OSTIMER_Type *base)
{
uint64_t tmp = 0U;
tmp = OSTIMER_GetCaptureRawValue(base);
return OSTIMER_GrayToDecimal(tmp);
}
void OSTIMER_HandleIRQ(OSTIMER_Type *base, ostimer_callback_t cb)
{
/* Clear interrupt flag, disable the IRQ and module interrupt enablement. */
OSTIMER_EnableInterrupt(base, false);
if (cb != NULL)
{
cb();
}
}
void OS_EVENT_DriverIRQHandler(void);
void OS_EVENT_DriverIRQHandler(void)
{
s_ostimerIsr(s_ostimerBases[0], s_ostimerHandle[0]);
SDK_ISR_EXIT_BARRIER;
}

View File

@ -0,0 +1,273 @@
/*
* Copyright 2018-2021 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_OSTIMER_H_
#define FSL_OSTIMER_H_
#include "fsl_common.h"
/*!
* @addtogroup ostimer
* @{
*/
/*! @file*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
/*! @brief OSTIMER driver version. */
#define FSL_OSTIMER_DRIVER_VERSION (MAKE_VERSION(2, 2, 2))
/*! @} */
/*!
* @brief OSTIMER status flags.
*/
enum _ostimer_flags
{
kOSTIMER_MatchInterruptFlag = (OSTIMER_OSEVENT_CTRL_OSTIMER_INTRFLAG_MASK), /*!< Match interrupt flag bit, sets if
the match value was reached. */
};
/*! @brief ostimer callback function. */
typedef void (*ostimer_callback_t)(void);
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
/*!
* @name Initialization and deinitialization
* @{
*/
/*!
* @brief Initializes an OSTIMER by turning its bus clock on
*
*/
void OSTIMER_Init(OSTIMER_Type *base);
/*!
* @brief Deinitializes a OSTIMER instance.
*
* This function shuts down OSTIMER bus clock
*
* @param base OSTIMER peripheral base address.
*/
void OSTIMER_Deinit(OSTIMER_Type *base);
/*!
* @brief Translate the value from gray-code to decimal.
*
* @param gray The gray value input.
* @return The decimal value.
*/
uint64_t OSTIMER_GrayToDecimal(uint64_t gray);
/*!
* @brief Translate the value from decimal to gray-code.
*
* @param dec The decimal value.
* @return The gray code of the input value.
*/
static inline uint64_t OSTIMER_DecimalToGray(uint64_t dec)
{
return (dec ^ (dec >> 1U));
}
/*!
* @brief Get OSTIMER status Flags.
*
* This returns the status flag.
* Currently, only match interrupt flag can be got.
*
* @param base OSTIMER peripheral base address.
* @return status register value
*/
uint32_t OSTIMER_GetStatusFlags(OSTIMER_Type *base);
/*!
* @brief Clear Status Interrupt Flags.
*
* This clears intrrupt status flag.
* Currently, only match interrupt flag can be cleared.
*
* @param base OSTIMER peripheral base address.
* @param mask Clear bit mask.
* @return none
*/
void OSTIMER_ClearStatusFlags(OSTIMER_Type *base, uint32_t mask);
/*!
* @brief Set the match raw value for OSTIMER.
*
* This function will set a match value for OSTIMER with an optional callback. And this callback
* will be called while the data in dedicated pair match register is equals to the value of central EVTIMER.
* Please note that, the data format is gray-code, if decimal data was desired, please using OSTIMER_SetMatchValue().
*
* @param base OSTIMER peripheral base address.
* @param count OSTIMER timer match value.(Value is gray-code format)
*
* @param cb OSTIMER callback (can be left as NULL if none, otherwise should be a void func(void)).
* @retval kStatus_Success - Set match raw value and enable interrupt Successfully.
* @retval kStatus_Fail - Set match raw value fail.
*/
status_t OSTIMER_SetMatchRawValue(OSTIMER_Type *base, uint64_t count, ostimer_callback_t cb);
/*!
* @brief Set the match value for OSTIMER.
*
* This function will set a match value for OSTIMER with an optional callback. And this callback
* will be called while the data in dedicated pair match register is equals to the value of central OS TIMER.
*
* @param base OSTIMER peripheral base address.
* @param count OSTIMER timer match value.(Value is decimal format, and this value will be translate to Gray code
* internally.)
*
* @param cb OSTIMER callback (can be left as NULL if none, otherwise should be a void func(void)).
* @retval kStatus_Success - Set match value and enable interrupt Successfully.
* @retval kStatus_Fail - Set match value fail.
*/
status_t OSTIMER_SetMatchValue(OSTIMER_Type *base, uint64_t count, ostimer_callback_t cb);
/*!
* @brief Set value to OSTIMER MATCH register directly.
*
* This function writes the input value to OSTIMER MATCH register directly,
* it does not touch any other registers. Note that, the data format is
* gray-code. The function @ref OSTIMER_DecimalToGray could convert decimal
* value to gray code.
*
* @param base OSTIMER peripheral base address.
* @param value OSTIMER timer match value (Value is gray-code format).
*/
static inline void OSTIMER_SetMatchRegister(OSTIMER_Type *base, uint64_t value)
{
#ifdef OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK
/* Wait for MATCH register ready for write. */
while (0U != (base->OSEVENT_CTRL & OSTIMER_OSEVENT_CTRL_MATCH_WR_RDY_MASK))
{
}
#endif
base->MATCH_L = (uint32_t)value;
base->MATCH_H = (uint32_t)(value >> 32U);
}
/*!
* @brief Enable the OSTIMER counter match interrupt.
*
* Enable the timer counter match interrupt. The interrupt happens when OSTIMER
* counter matches the value in MATCH registers.
*
* @param base OSTIMER peripheral base address.
*/
static inline void OSTIMER_EnableMatchInterrupt(OSTIMER_Type *base)
{
base->OSEVENT_CTRL |= OSTIMER_OSEVENT_CTRL_OSTIMER_INTENA_MASK;
}
/*!
* @brief Disable the OSTIMER counter match interrupt.
*
* Disable the timer counter match interrupt. The interrupt happens when OSTIMER
* counter matches the value in MATCH registers.
*
* @param base OSTIMER peripheral base address.
*/
static inline void OSTIMER_DisableMatchInterrupt(OSTIMER_Type *base)
{
base->OSEVENT_CTRL &= ~OSTIMER_OSEVENT_CTRL_OSTIMER_INTENA_MASK;
}
/*!
* @brief Get current timer raw count value from OSTIMER.
*
* This function will get a gray code type timer count value from OS timer register.
* The raw value of timer count is gray code format.
*
* @param base OSTIMER peripheral base address.
* @return Raw value of OSTIMER, gray code format.
*/
static inline uint64_t OSTIMER_GetCurrentTimerRawValue(OSTIMER_Type *base)
{
uint64_t tmp = 0U;
tmp = base->EVTIMERL;
tmp |= (uint64_t)(base->EVTIMERH) << 32U;
return tmp;
}
/*!
* @brief Get current timer count value from OSTIMER.
*
* This function will get a decimal timer count value.
* The RAW value of timer count is gray code format, will be translated to decimal data internally.
*
* @param base OSTIMER peripheral base address.
* @return Value of OSTIMER which will be formated to decimal value.
*/
uint64_t OSTIMER_GetCurrentTimerValue(OSTIMER_Type *base);
/*!
* @brief Get the capture value from OSTIMER.
*
* This function will get a captured gray-code value from OSTIMER.
* The Raw value of timer capture is gray code format.
*
* @param base OSTIMER peripheral base address.
* @return Raw value of capture register, data format is gray code.
*/
static inline uint64_t OSTIMER_GetCaptureRawValue(OSTIMER_Type *base)
{
uint64_t tmp = 0U;
tmp = base->CAPTURE_L;
tmp |= (uint64_t)(base->CAPTURE_H) << 32U;
return tmp;
}
/*!
* @brief Get the capture value from OSTIMER.
*
* This function will get a capture decimal-value from OSTIMER.
* The RAW value of timer capture is gray code format, will be translated to decimal data internally.
*
* @param base OSTIMER peripheral base address.
* @return Value of capture register, data format is decimal.
*/
uint64_t OSTIMER_GetCaptureValue(OSTIMER_Type *base);
/*!
* @brief OS timer interrupt Service Handler.
*
* This function handles the interrupt and refers to the callback array in the driver to callback user (as per request
* in OSTIMER_SetMatchValue()).
* if no user callback is scheduled, the interrupt will simply be cleared.
*
* @param base OS timer peripheral base address.
* @param cb callback scheduled for this instance of OS timer
* @return none
*/
void OSTIMER_HandleIRQ(OSTIMER_Type *base, ostimer_callback_t cb);
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_OSTIMER_H_ */

View File

@ -0,0 +1,684 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022, 2024 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_PORT_H_
#define FSL_PORT_H_
#include "fsl_common.h"
/*!
* @addtogroup port
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.port"
#endif
/*! @name Driver version */
/*! @{ */
/*! @brief PORT driver version. */
#define FSL_PORT_DRIVER_VERSION (MAKE_VERSION(2, 5, 0))
/*! @} */
#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
/*! @brief Internal resistor pull feature selection */
enum _port_pull
{
kPORT_PullDisable = 0U, /*!< Internal pull-up/down resistor is disabled. */
kPORT_PullDown = 2U, /*!< Internal pull-down resistor is enabled. */
kPORT_PullUp = 3U, /*!< Internal pull-up resistor is enabled. */
};
#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE
/*! @brief Internal resistor pull value selection */
enum _port_pull_value
{
kPORT_LowPullResistor = 0U, /*!< Low internal pull resistor value is selected. */
kPORT_HighPullResistor = 1U, /*!< High internal pull resistor value is selected. */
};
#endif /* FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE */
#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
/*! @brief Slew rate selection */
enum _port_slew_rate
{
kPORT_FastSlewRate = 0U, /*!< Fast slew rate is configured. */
kPORT_SlowSlewRate = 1U, /*!< Slow slew rate is configured. */
};
#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
/*! @brief Open Drain feature enable/disable */
enum _port_open_drain_enable
{
kPORT_OpenDrainDisable = 0U, /*!< Open drain output is disabled. */
kPORT_OpenDrainEnable = 1U, /*!< Open drain output is enabled. */
};
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
/*! @brief Passive filter feature enable/disable */
enum _port_passive_filter_enable
{
kPORT_PassiveFilterDisable = 0U, /*!< Passive input filter is disabled. */
kPORT_PassiveFilterEnable = 1U, /*!< Passive input filter is enabled. */
};
#endif
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
/*! @brief Configures the drive strength. */
enum _port_drive_strength
{
kPORT_LowDriveStrength = 0U, /*!< Low-drive strength is configured. */
kPORT_HighDriveStrength = 1U, /*!< High-drive strength is configured. */
};
#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH */
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1
/*! @brief Configures the drive strength1. */
enum _port_drive_strength1
{
kPORT_NormalDriveStrength = 0U, /*!< Normal drive strength */
kPORT_DoubleDriveStrength = 1U, /*!< Double drive strength */
};
#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 */
#if defined(FSL_FEATURE_PORT_HAS_INPUT_BUFFER) && FSL_FEATURE_PORT_HAS_INPUT_BUFFER
/*! @brief input buffer disable/enable. */
enum _port_input_buffer
{
kPORT_InputBufferDisable = 0U, /*!< Digital input is disabled */
kPORT_InputBufferEnable = 1U, /*!< Digital input is enabled */
};
#endif /* FSL_FEATURE_PORT_HAS_INPUT_BUFFER */
#if defined(FSL_FEATURE_PORT_HAS_INVERT_INPUT) && FSL_FEATURE_PORT_HAS_INVERT_INPUT
/*! @brief Digital input is not inverted or it is inverted. */
enum _port_invet_input
{
kPORT_InputNormal = 0U, /*!< Digital input is not inverted */
kPORT_InputInvert = 1U, /*!< Digital input is inverted */
};
#endif /* FSL_FEATURE_PORT_HAS_INVERT_INPUT */
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
/*! @brief Unlock/lock the pin control register field[15:0] */
enum _port_lock_register
{
kPORT_UnlockRegister = 0U, /*!< Pin Control Register fields [15:0] are not locked. */
kPORT_LockRegister = 1U, /*!< Pin Control Register fields [15:0] are locked. */
};
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
/*! @brief Pin mux selection */
typedef enum _port_mux
{
#if defined(FSL_FEATURE_PORT_PCR_MUX_GPIO) && (FSL_FEATURE_PORT_PCR_MUX_GPIO == 0)
kPORT_MuxAsGpio = 0U, /*!< Corresponding pin is configured as GPIO. */
#else
kPORT_PinDisabledOrAnalog = 0U, /*!< Corresponding pin is disabled, but is used as an analog pin. */
kPORT_MuxAsGpio = 1U, /*!< Corresponding pin is configured as GPIO. */
#endif
kPORT_MuxAlt0 = 0U, /*!< Chip-specific */
kPORT_MuxAlt1 = 1U, /*!< Chip-specific */
kPORT_MuxAlt2 = 2U, /*!< Chip-specific */
kPORT_MuxAlt3 = 3U, /*!< Chip-specific */
kPORT_MuxAlt4 = 4U, /*!< Chip-specific */
kPORT_MuxAlt5 = 5U, /*!< Chip-specific */
kPORT_MuxAlt6 = 6U, /*!< Chip-specific */
kPORT_MuxAlt7 = 7U, /*!< Chip-specific */
kPORT_MuxAlt8 = 8U, /*!< Chip-specific */
kPORT_MuxAlt9 = 9U, /*!< Chip-specific */
kPORT_MuxAlt10 = 10U, /*!< Chip-specific */
kPORT_MuxAlt11 = 11U, /*!< Chip-specific */
kPORT_MuxAlt12 = 12U, /*!< Chip-specific */
kPORT_MuxAlt13 = 13U, /*!< Chip-specific */
kPORT_MuxAlt14 = 14U, /*!< Chip-specific */
kPORT_MuxAlt15 = 15U, /*!< Chip-specific */
} port_mux_t;
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
/*! @brief Configures the interrupt generation condition. */
typedef enum _port_interrupt
{
kPORT_InterruptOrDMADisabled = 0x0U, /*!< Interrupt/DMA request is disabled. */
#if defined(FSL_FEATURE_PORT_HAS_DMA_REQUEST) && FSL_FEATURE_PORT_HAS_DMA_REQUEST || defined(DOXYGEN_OUTPUT)
kPORT_DMARisingEdge = 0x1U, /*!< DMA request on rising edge. */
kPORT_DMAFallingEdge = 0x2U, /*!< DMA request on falling edge. */
kPORT_DMAEitherEdge = 0x3U, /*!< DMA request on either edge. */
#endif
#if defined(FSL_FEATURE_PORT_HAS_IRQC_FLAG) && FSL_FEATURE_PORT_HAS_IRQC_FLAG || defined(DOXYGEN_OUTPUT)
kPORT_FlagRisingEdge = 0x05U, /*!< Flag sets on rising edge. */
kPORT_FlagFallingEdge = 0x06U, /*!< Flag sets on falling edge. */
kPORT_FlagEitherEdge = 0x07U, /*!< Flag sets on either edge. */
#endif
kPORT_InterruptLogicZero = 0x8U, /*!< Interrupt when logic zero. */
kPORT_InterruptRisingEdge = 0x9U, /*!< Interrupt on rising edge. */
kPORT_InterruptFallingEdge = 0xAU, /*!< Interrupt on falling edge. */
kPORT_InterruptEitherEdge = 0xBU, /*!< Interrupt on either edge. */
kPORT_InterruptLogicOne = 0xCU, /*!< Interrupt when logic one. */
#if defined(FSL_FEATURE_PORT_HAS_IRQC_TRIGGER) && FSL_FEATURE_PORT_HAS_IRQC_TRIGGER || defined(DOXYGEN_OUTPUT)
kPORT_ActiveHighTriggerOutputEnable = 0xDU, /*!< Enable active high-trigger output. */
kPORT_ActiveLowTriggerOutputEnable = 0xEU, /*!< Enable active low-trigger output. */
#endif
} port_interrupt_t;
#endif
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*! @brief Digital filter clock source selection */
typedef enum _port_digital_filter_clock_source
{
kPORT_BusClock = 0U, /*!< Digital filters are clocked by the bus clock. */
kPORT_LpoClock = 1U, /*!< Digital filters are clocked by the 1 kHz LPO clock. */
} port_digital_filter_clock_source_t;
/*! @brief PORT digital filter feature configuration definition */
typedef struct _port_digital_filter_config
{
uint32_t digitalFilterWidth; /*!< Set digital filter width */
port_digital_filter_clock_source_t clockSource; /*!< Set digital filter clockSource */
} port_digital_filter_config_t;
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
/*! @brief PORT pin configuration structure */
typedef struct _port_pin_config
{
#if defined(FSL_FEATURE_PORT_HAS_PULL_ENABLE) && FSL_FEATURE_PORT_HAS_PULL_ENABLE
uint16_t pullSelect : 2; /*!< No-pull/pull-down/pull-up select */
#else
uint16_t : 2;
#endif /* FSL_FEATURE_PORT_HAS_PULL_ENABLE */
#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE
uint16_t pullValueSelect : 1; /*!< Pull value select */
#endif /* FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE */
#if defined(FSL_FEATURE_PORT_HAS_SLEW_RATE) && FSL_FEATURE_PORT_HAS_SLEW_RATE
uint16_t slewRate : 1; /*!< Fast/slow slew rate Configure */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_SLEW_RATE */
#if !(defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE)
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE */
#if defined(FSL_FEATURE_PORT_HAS_PASSIVE_FILTER) && FSL_FEATURE_PORT_HAS_PASSIVE_FILTER
uint16_t passiveFilterEnable : 1; /*!< Passive filter enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_PASSIVE_FILTER */
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
uint16_t openDrainEnable : 1; /*!< Open drain enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_OPEN_DRAIN */
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
uint16_t driveStrength : 1; /*!< Fast/slow drive strength configure */
#else
uint16_t : 1;
#endif
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1
uint16_t driveStrength1 : 1; /*!< Normal/Double drive strength enable/disable */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1 */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 3)
uint16_t mux : 3; /*!< Pin mux Configure */
uint16_t : 1;
#elif defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && (FSL_FEATURE_PORT_PCR_MUX_WIDTH == 4)
uint16_t mux : 4; /*!< Pin mux Configure */
#else
uint16_t : 4;
#endif
#if defined(FSL_FEATURE_PORT_HAS_INPUT_BUFFER) && FSL_FEATURE_PORT_HAS_INPUT_BUFFER
uint16_t inputBuffer : 1; /*!< Input Buffer Configure */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_INPUT_BUFFER */
#if defined(FSL_FEATURE_PORT_HAS_INVERT_INPUT) && FSL_FEATURE_PORT_HAS_INVERT_INPUT
uint16_t invertInput : 1; /*!< Invert Input Configure */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_INVERT_INPUT */
uint16_t : 1;
#if defined(FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK) && FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK
uint16_t lockRegister : 1; /*!< Lock/unlock the PCR field[15:0] */
#else
uint16_t : 1;
#endif /* FSL_FEATURE_PORT_HAS_PIN_CONTROL_LOCK */
} port_pin_config_t;
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
#if defined(FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER
/*! @brief PORT version information. */
typedef struct _port_version_info
{
uint16_t feature; /*!< Feature Specification Number. */
uint8_t minor; /*!< Minor Version Number. */
uint8_t major; /*!< Major Version Number. */
} port_version_info_t;
#endif /* FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER */
#if defined(FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE) && FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE
/*! @brief PORT voltage range. */
typedef enum _port_voltage_range
{
kPORT_VoltageRange1Dot71V_3Dot6V = 0x0U, /*!< Port voltage range is 1.71 V - 3.6 V. */
kPORT_VoltageRange2Dot70V_3Dot6V = 0x1U, /*!< Port voltage range is 2.70 V - 3.6 V. */
} port_voltage_range_t;
#endif /* FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*! @name Configuration */
/*! @{ */
#if defined(FSL_FEATURE_PORT_PCR_MUX_WIDTH) && FSL_FEATURE_PORT_PCR_MUX_WIDTH
#if defined(FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER) && FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER
/*!
* @brief Get PORT version information.
*
* @param base PORT peripheral base pointer
* @param info PORT version information
*/
static inline void PORT_GetVersionInfo(PORT_Type *base, port_version_info_t *info)
{
uint32_t verid = base->VERID;
info->feature = (uint16_t)verid;
info->minor = (uint8_t)(verid >> PORT_VERID_MINOR_SHIFT);
info->major = (uint8_t)(verid >> PORT_VERID_MAJOR_SHIFT);
}
#endif /* FSL_FEATURE_PORT_HAS_VERSION_INFO_REGISTER */
#if defined(FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE) && FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE
/*!
* @brief Get PORT version information.
*
* @note : PORTA_CONFIG[RANGE] controls the voltage ranges of Port A, B, and C. Read or write PORTB_CONFIG[RANGE] and
* PORTC_CONFIG[RANGE] does not take effect.
*
* @param base PORT peripheral base pointer
* @param range port voltage range
*/
static inline void PORT_SecletPortVoltageRange(PORT_Type *base, port_voltage_range_t range)
{
base->CONFIG = (uint32_t)range;
}
#endif /* FSL_FEATURE_PORT_SUPPORT_DIFFERENT_VOLTAGE_RANGE */
/*!
* @brief Sets the port PCR register.
*
* This is an example to define an input pin or output pin PCR configuration.
* @code
* // Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnLockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT PCR register configuration structure.
*/
static inline void PORT_SetPinConfig(PORT_Type *base, uint32_t pin, const port_pin_config_t *config)
{
assert(config);
uint32_t addr = (uint32_t)&base->PCR[pin];
*(volatile uint16_t *)(addr) = *((const uint16_t *)(const void *)config);
}
/*!
* @brief Sets the port PCR register for multiple pins.
*
* This is an example to define input pins or output pins PCR configuration.
* @code
* Define a digital input pin PCR configuration
* port_pin_config_t config = {
* kPORT_PullUp ,
* kPORT_PullEnable,
* kPORT_FastSlewRate,
* kPORT_PassiveFilterDisable,
* kPORT_OpenDrainDisable,
* kPORT_LowDriveStrength,
* kPORT_MuxAsGpio,
* kPORT_UnlockRegister,
* };
* @endcode
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
* @param config PORT PCR register configuration structure.
*/
static inline void PORT_SetMultiplePinsConfig(PORT_Type *base, uint32_t mask, const port_pin_config_t *config)
{
assert(config);
uint16_t pcrl = *((const uint16_t *)(const void *)config);
if (0U != (mask & 0xffffU))
{
base->GPCLR = ((mask & 0xffffU) << 16) | pcrl;
}
if (0U != (mask >> 16))
{
base->GPCHR = (mask & 0xffff0000U) | pcrl;
}
}
#if defined(FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG) && FSL_FEATURE_PORT_HAS_MULTIPLE_IRQ_CONFIG
/*!
* @brief Sets the port interrupt configuration in PCR register for multiple pins.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
* @param config PORT pin interrupt configuration.
* - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
* - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kPORT_InterruptLogicZero : Interrupt when logic zero.
* - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
* - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
* - #kPORT_InterruptEitherEdge : Interrupt on either edge.
* - #kPORT_InterruptLogicOne : Interrupt when logic one.
* - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit)..
*/
static inline void PORT_SetMultipleInterruptPinsConfig(PORT_Type *base, uint32_t mask, port_interrupt_t config)
{
assert(config);
if (0U != ((uint32_t)mask & 0xffffU))
{
base->GICLR = ((uint32_t)config << 16U) | ((uint32_t)mask & 0xffffU);
}
mask = mask >> 16;
if (0U != mask)
{
base->GICHR = ((uint32_t)config << 16U) | ((uint32_t)mask & 0xffffU);
}
}
#endif
/*!
* @brief Configures the pin muxing.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param mux pin muxing slot selection.
* - #kPORT_PinDisabledOrAnalog: Pin disabled or work in analog function.
* - #kPORT_MuxAsGpio : Set as GPIO.
* - #kPORT_MuxAlt2 : chip-specific.
* - #kPORT_MuxAlt3 : chip-specific.
* - #kPORT_MuxAlt4 : chip-specific.
* - #kPORT_MuxAlt5 : chip-specific.
* - #kPORT_MuxAlt6 : chip-specific.
* - #kPORT_MuxAlt7 : chip-specific.
* @note : This function is NOT recommended to use together with the PORT_SetPinsConfig, because
* the PORT_SetPinsConfig need to configure the pin mux anyway (Otherwise the pin mux is
* reset to zero : kPORT_PinDisabledOrAnalog).
* This function is recommended to use to reset the pin mux
*
*/
static inline void PORT_SetPinMux(PORT_Type *base, uint32_t pin, port_mux_t mux)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(mux);
}
#endif /* FSL_FEATURE_PORT_PCR_MUX_WIDTH */
#if defined(FSL_FEATURE_PORT_HAS_DIGITAL_FILTER) && FSL_FEATURE_PORT_HAS_DIGITAL_FILTER
/*!
* @brief Enables the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
* @param enable PORT digital filter configuration.
*/
static inline void PORT_EnablePinsDigitalFilter(PORT_Type *base, uint32_t mask, bool enable)
{
if (enable == true)
{
base->DFER |= mask;
}
else
{
base->DFER &= ~mask;
}
}
/*!
* @brief Sets the digital filter in one port, each bit of the 32-bit register represents one pin.
*
* @param base PORT peripheral base pointer.
* @param config PORT digital filter configuration structure.
*/
static inline void PORT_SetDigitalFilterConfig(PORT_Type *base, const port_digital_filter_config_t *config)
{
assert(config);
base->DFCR = PORT_DFCR_CS(config->clockSource);
base->DFWR = PORT_DFWR_FILT(config->digitalFilterWidth);
}
#endif /* FSL_FEATURE_PORT_HAS_DIGITAL_FILTER */
/*! @} */
/*! @name Interrupt */
/*! @{ */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
/*!
* @brief Configures the port pin interrupt/DMA request.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param config PORT pin interrupt configuration.
* - #kPORT_InterruptOrDMADisabled: Interrupt/DMA request disabled.
* - #kPORT_DMARisingEdge : DMA request on rising edge(if the DMA requests exit).
* - #kPORT_DMAFallingEdge: DMA request on falling edge(if the DMA requests exit).
* - #kPORT_DMAEitherEdge : DMA request on either edge(if the DMA requests exit).
* - #kPORT_FlagRisingEdge : Flag sets on rising edge(if the Flag states exit).
* - #kPORT_FlagFallingEdge : Flag sets on falling edge(if the Flag states exit).
* - #kPORT_FlagEitherEdge : Flag sets on either edge(if the Flag states exit).
* - #kPORT_InterruptLogicZero : Interrupt when logic zero.
* - #kPORT_InterruptRisingEdge : Interrupt on rising edge.
* - #kPORT_InterruptFallingEdge: Interrupt on falling edge.
* - #kPORT_InterruptEitherEdge : Interrupt on either edge.
* - #kPORT_InterruptLogicOne : Interrupt when logic one.
* - #kPORT_ActiveHighTriggerOutputEnable : Enable active high-trigger output (if the trigger states exit).
* - #kPORT_ActiveLowTriggerOutputEnable : Enable active low-trigger output (if the trigger states exit).
*/
static inline void PORT_SetPinInterruptConfig(PORT_Type *base, uint32_t pin, port_interrupt_t config)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | PORT_PCR_IRQC(config);
}
#endif
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH
/*!
* @brief Configures the port pin drive strength.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param strength PORT pin drive strength
* - #kPORT_LowDriveStrength = 0U - Low-drive strength is configured.
* - #kPORT_HighDriveStrength = 1U - High-drive strength is configured.
*/
static inline void PORT_SetPinDriveStrength(PORT_Type *base, uint32_t pin, uint8_t strength)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_DSE_MASK) | PORT_PCR_DSE(strength);
}
#endif
#if defined(FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1) && FSL_FEATURE_PORT_HAS_DRIVE_STRENGTH1
/*!
* @brief Enables the port pin double drive strength.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param enable PORT pin drive strength configuration.
*/
static inline void PORT_EnablePinDoubleDriveStrength(PORT_Type *base, uint32_t pin, bool enable)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_DSE1_MASK) | PORT_PCR_DSE1(enable);
}
#endif
#if defined(FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE) && FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE
/*!
* @brief Configures the port pin pull value.
*
* @param base PORT peripheral base pointer.
* @param pin PORT pin number.
* @param value PORT pin pull value
* - #kPORT_LowPullResistor = 0U - Low internal pull resistor value is selected.
* - #kPORT_HighPullResistor = 1U - High internal pull resistor value is selected.
*/
static inline void PORT_SetPinPullValue(PORT_Type *base, uint32_t pin, uint8_t value)
{
base->PCR[pin] = (base->PCR[pin] & ~PORT_PCR_PV_MASK) | PORT_PCR_PV(value);
}
#endif /* FSL_FEATURE_PORT_PCR_HAS_PULL_VALUE */
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
/*!
* @brief Reads the whole port status flag.
*
* If a pin is configured to generate the DMA request, the corresponding flag
* is cleared automatically at the completion of the requested DMA transfer.
* Otherwise, the flag remains set until a logic one is written to that flag.
* If configured for a level sensitive interrupt that remains asserted, the flag
* is set again immediately.
*
* @param base PORT peripheral base pointer.
* @return Current port interrupt status flags, for example, 0x00010001 means the
* pin 0 and 16 have the interrupt.
*/
static inline uint32_t PORT_GetPinsInterruptFlags(PORT_Type *base)
{
return base->ISFR;
}
/*!
* @brief Clears the multiple pin interrupt status flag.
*
* @param base PORT peripheral base pointer.
* @param mask PORT pin number macro.
*/
static inline void PORT_ClearPinsInterruptFlags(PORT_Type *base, uint32_t mask)
{
base->ISFR = mask;
}
#endif
#if defined(FSL_FEATURE_PORT_SUPPORT_EFT) && FSL_FEATURE_PORT_SUPPORT_EFT
/*!
* @brief Get EFT detect flags.
*
* @param base PORT peripheral base pointer
* @return EFT detect flags
*/
static inline uint32_t PORT_GetEFTDetectFlags(PORT_Type *base)
{
return base->EDFR;
}
/*!
* @brief Enable EFT detect interrupts.
*
* @param base PORT peripheral base pointer
* @param interrupt EFT detect interrupt
*/
static inline void PORT_EnableEFTDetectInterrupts(PORT_Type *base, uint32_t interrupt)
{
base->EDIER |= interrupt;
}
/*!
* @brief Disable EFT detect interrupts.
*
* @param base PORT peripheral base pointer
* @param interrupt EFT detect interrupt
*/
static inline void PORT_DisableEFTDetectInterrupts(PORT_Type *base, uint32_t interrupt)
{
base->EDIER &= ~interrupt;
}
/*!
* @brief Clear all low EFT detector.
*
* @note : Port B and Port C pins share the same EFT detector clear control from PORTC_EDCR register. Any write to the
* PORTB_EDCR does not take effect.
* @param base PORT peripheral base pointer
* @param interrupt EFT detect interrupt
*/
static inline void PORT_ClearAllLowEFTDetectors(PORT_Type *base)
{
base->EDCR |= PORT_EDCR_EDLC_MASK;
base->EDCR &= ~PORT_EDCR_EDLC_MASK;
}
/*!
* @brief Clear all high EFT detector.
*
* @param base PORT peripheral base pointer
* @param interrupt EFT detect interrupt
*/
static inline void PORT_ClearAllHighEFTDetectors(PORT_Type *base)
{
base->EDCR |= PORT_EDCR_EDHC_MASK;
base->EDCR &= ~PORT_EDCR_EDHC_MASK;
}
#endif /* FSL_FEATURE_PORT_SUPPORT_EFT */
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* FSL_PORT_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,141 @@
/*
* Copyright 2023, NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#include "fsl_reset.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.reset"
#endif
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
#define GET_REG_INDEX(x) ((uint32_t)(((uint32_t)(x) & 0xFF00U) >> 8))
#define GET_BIT_INDEX(x) ((uint32_t)((uint32_t)(x) & 0x00FFU))
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief Assert reset to peripheral.
*
* Asserts reset signal to specified peripheral module.
*
* param peripheral Assert reset to this peripheral. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_SetPeripheralReset(reset_ip_name_t peripheral)
{
uint32_t regIndex = GET_REG_INDEX(peripheral);
uint32_t bitPos = GET_BIT_INDEX(peripheral);
uint32_t bitMask = 1UL << bitPos;
volatile uint32_t *pResetCtrl = &(MRCC0->MRCC_GLB_RST0);
if (peripheral == NotAvail_RSTn)
{
return;
}
assert(bitPos < 32u);
assert(regIndex < 2u);
/* Unlock clock configuration */
SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK;
/* reset register is in MRCC */
/* set bit */
if (regIndex == 0U)
{
MRCC0->MRCC_GLB_RST0_SET = bitMask;
pResetCtrl = &(MRCC0->MRCC_GLB_RST0);
}
else if (regIndex == 1U)
{
MRCC0->MRCC_GLB_RST1_SET = bitMask;
pResetCtrl = &(MRCC0->MRCC_GLB_RST1);
}
else
{
/* Added comments to prevent the violation of MISRA C-2012 rule 15.7 */
}
/* wait until it reads 0b1 */
while (0u == ((*pResetCtrl) & bitMask))
{
}
/* Freeze clock configuration */
SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK;
}
/*!
* brief Clear reset to peripheral.
*
* Clears reset signal to specified peripheral module, allows it to operate.
*
* param peripheral Clear reset to this peripheral. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_ClearPeripheralReset(reset_ip_name_t peripheral)
{
uint32_t regIndex = GET_REG_INDEX(peripheral);
uint32_t bitPos = GET_BIT_INDEX(peripheral);
uint32_t bitMask = 1UL << bitPos;
volatile uint32_t *pResetCtrl = &(MRCC0->MRCC_GLB_RST0);
assert(bitPos < 32u);
/* Unlock clock configuration */
SYSCON->CLKUNLOCK &= ~SYSCON_CLKUNLOCK_UNLOCK_MASK;
/* reset register is in MRCC */
/* clear bit */
if (regIndex == 0U)
{
MRCC0->MRCC_GLB_RST0_CLR = bitMask;
pResetCtrl = &(MRCC0->MRCC_GLB_RST0);
}
else if (regIndex == 1U)
{
MRCC0->MRCC_GLB_RST1_CLR = bitMask;
pResetCtrl = &(MRCC0->MRCC_GLB_RST1);
}
else
{
/* Added comments to prevent the violation of MISRA C-2012 rule 15.7 */
}
/* wait until it reads 0b0 */
while (bitMask == ((*pResetCtrl) & bitMask))
{
}
/* Freeze clock configuration */
SYSCON->CLKUNLOCK |= SYSCON_CLKUNLOCK_UNLOCK_MASK;
}
/*!
* brief Reset peripheral module.
*
* Reset peripheral module.
*
* param peripheral Peripheral to reset. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_PeripheralReset(reset_ip_name_t peripheral)
{
RESET_ClearPeripheralReset(peripheral);
RESET_SetPeripheralReset(peripheral);
}

View File

@ -0,0 +1,251 @@
/*
* Copyright 2023, NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_RESET_H_
#define _FSL_RESET_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "fsl_device_registers.h"
/*!
* @addtogroup reset
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*@{*/
/*! @brief reset driver version 2.4.0 */
#define FSL_RESET_DRIVER_VERSION (MAKE_VERSION(2, 4, 0))
/*@}*/
/*!
* @brief Enumeration for peripheral reset control bits
*
* Defines the enumeration for peripheral reset control bits in PRESETCTRL/ASYNCPRESETCTRL registers
*/
typedef enum _SYSCON_RSTn
{
kINPUTMUX0_RST_SHIFT_RSTn = (0U | (0U)), /*!< INPUTMUX0 reset control */
kI3C0_RST_SHIFT_RSTn = (0U | (1U)), /*!< I3C0 reset control */
kCTIMER0_RST_SHIFT_RSTn = (0U | (2U)), /*!< CTIMER0 reset control */
kCTIMER1_RST_SHIFT_RSTn = (0U | (3U)), /*!< CTIMER1 reset control */
kCTIMER2_RST_SHIFT_RSTn = (0U | (4U)), /*!< CTIMER2 reset control */
kCTIMER3_RST_SHIFT_RSTn = (0U | (5U)), /*!< CTIMER3 reset control */
kCTIMER4_RST_SHIFT_RSTn = (0U | (6U)), /*!< CTIMER4 reset control */
kFREQME_RST_SHIFT_RSTn = (0U | (7U)), /*!< FREQME reset control */
kUTICK0_RST_SHIFT_RSTn = (0U | (8U)), /*!< UTICK0 reset control */
kDMA_RST_SHIFT_RSTn = (0U | (10U)), /*!< DMA reset control */
kAOI0_RST_SHIFT_RSTn = (0U | (11U)), /*!< AOI0 reset control */
kCRC0_RST_SHIFT_RSTn = (0U | (12U)), /*!< CRC0 reset control */
kEIM0_RST_SHIFT_RSTn = (0U | (13U)), /*!< EIM0 reset control */
kERM0_RST_SHIFT_RSTn = (0U | (14U)), /*!< ERM0 reset control */
kAOI1_RST_SHIFT_RSTn = (0U | (16U)), /*!< AOI1 reset control */
kFLEXIO0_RST_SHIFT_RSTn = (0U | (17U)), /*!< FLEXIO0 reset control */
kLPI2C0_RST_SHIFT_RSTn = (0U | (18U)), /*!< LPI2C0 reset control */
kLPI2C1_RST_SHIFT_RSTn = (0U | (19U)), /*!< LPI2C1 reset control */
kLPSPI0_RST_SHIFT_RSTn = (0U | (20U)), /*!< LPSPI0 reset control */
kLPSPI1_RST_SHIFT_RSTn = (0U | (21U)), /*!< LPSPI1 reset control */
kLPUART0_RST_SHIFT_RSTn = (0U | (22U)), /*!< LPUART0 reset control */
kLPUART1_RST_SHIFT_RSTn = (0U | (23U)), /*!< LPUART1 reset control */
kLPUART2_RST_SHIFT_RSTn = (0U | (24U)), /*!< LPUART2 reset control */
kLPUART3_RST_SHIFT_RSTn = (0U | (25U)), /*!< LPUART3 reset control */
kLPUART4_RST_SHIFT_RSTn = (0U | (26U)), /*!< LPUART4 reset control */
kUSB0_RST_SHIFT_RSTn = (0U | (27U)), /*!< USB0 reset control */
kQDC0_RST_SHIFT_RSTn = (0U | (28U)), /*!< QDC0 reset control */
kQDC1_RST_SHIFT_RSTn = (0U | (29U)), /*!< QDC1 reset control */
kFLEXPWM0_RST_SHIFT_RSTn = (0U | (30U)), /*!< FLEXPWM0 reset control */
kFLEXPWM1_RST_SHIFT_RSTn = (0U | (31U)), /*!< FLEXPWM1 reset control */
kOSTIMER0_RST_SHIFT_RSTn = ((1U << 8U) | (0U)), /*!< OSTIMER0 reset control */
kADC0_RST_SHIFT_RSTn = ((1U << 8U) | (1U)), /*!< ADC0 reset control */
kADC1_RST_SHIFT_RSTn = ((1U << 8U) | (2U)), /*!< ADC1 reset control */
kCMP1_RST_SHIFT_RSTn = ((1U << 8U) | (4U)), /*!< CMP1 reset control */
kDAC0_RST_SHIFT_RSTn = ((1U << 8U) | (5U)), /*!< DAC0 reset control */
kOPAMP0_RST_SHIFT_RSTn = ((1U << 8U) | (6U)), /*!< OPAMP0 reset control */
kPORT0_RST_SHIFT_RSTn = ((1U << 8U) | (7U)), /*!< PORT0 reset control */
kPORT1_RST_SHIFT_RSTn = ((1U << 8U) | (8U)), /*!< PORT1 reset control */
kPORT2_RST_SHIFT_RSTn = ((1U << 8U) | (9U)), /*!< PORT2 reset control */
kPORT3_RST_SHIFT_RSTn = ((1U << 8U) | (10U)), /*!< PORT3 reset control */
kPORT4_RST_SHIFT_RSTn = ((1U << 8U) | (11U)), /*!< PORT4 reset control */
kFLEXCAN0_RST_SHIFT_RSTn = ((1U << 8U) | (12U)), /*!< FLEXCAN0 reset control */
kLPI2C2_RST_SHIFT_RSTn = ((1U << 8U) | (13U)), /*!< LPI2C2 reset control */
kLPI2C3_RST_SHIFT_RSTn = ((1U << 8U) | (14U)), /*!< LPI2C3 reset control */
kGPIO0_RST_SHIFT_RSTn = ((1U << 8U) | (20U)), /*!< GPIO0 reset control */
kGPIO1_RST_SHIFT_RSTn = ((1U << 8U) | (21U)), /*!< GPIO1 reset control */
kGPIO2_RST_SHIFT_RSTn = ((1U << 8U) | (22U)), /*!< GPIO2 reset control */
kGPIO3_RST_SHIFT_RSTn = ((1U << 8U) | (23U)), /*!< GPIO3 reset control */
kGPIO4_RST_SHIFT_RSTn = ((1U << 8U) | (24U)), /*!< GPIO4 reset control */
NotAvail_RSTn = (0xFFFFU), /*!< No reset control */
} SYSCON_RSTn_t;
/** Array initializers with peripheral reset bits **/
#define AOI_RSTS \
{ \
kAOI0_RST_SHIFT_RSTn, kAOI1_RST_SHIFT_RSTn \
} /* Reset bits for ADC peripheral */
#define ADC_RSTS \
{ \
kADC0_RST_SHIFT_RSTn, kADC1_RST_SHIFT_RSTn \
} /* Reset bits for ADC peripheral */
#define CRC_RSTS \
{ \
kCRC0_RST_SHIFT_RSTn \
} /* Reset bits for CRC peripheral */
#define CTIMER_RSTS \
{ \
kCTIMER0_RST_SHIFT_RSTn, kCTIMER1_RST_SHIFT_RSTn, kCTIMER2_RST_SHIFT_RSTn, kCTIMER3_RST_SHIFT_RSTn, \
kCTIMER4_RST_SHIFT_RSTn \
} /* Reset bits for CTIMER peripheral */
#define DAC_RSTS_N \
{ \
kDAC0_RST_SHIFT_RSTn \
} /* Reset bits for DAC peripheral */
#define DMA_RSTS_N \
{ \
kDMA_RST_SHIFT_RSTn \
} /* Reset bits for DMA peripheral */
#define EIM_RSTS_N \
{ \
kEIM0_RST_SHIFT_RSTn \
} /* Reset bits for EIM peripheral */
#define ERM_RSTS_N \
{ \
kERM0_RST_SHIFT_RSTn \
} /* Reset bits for ERM peripheral */
#define FLEXCAN_RSTS_N \
{ \
kFLEXCAN0_RST_SHIFT_RSTn \
} /* Reset bits for FLEXCAN peripheral */
#define FLEXIO_RSTS_N \
{ \
kFLEXIO0_RST_SHIFT_RSTn \
} /* Reset bits for FLEXIO peripheral */
#define FLEXPWM_RSTS_N \
{ \
kFLEXPWM0_RST_SHIFT_RSTn, kFLEXPWM1_RST_SHIFT_RSTn \
} /* Reset bits for FLEXPWM peripheral */
#define FREQME_RSTS_N \
{ \
kFREQME_RST_SHIFT_RSTn \
} /* Reset bits for FREQME peripheral */
#define GPIO_RSTS_N \
{ \
kGPIO0_RST_SHIFT_RSTn, kGPIO1_RST_SHIFT_RSTn, kGPIO2_RST_SHIFT_RSTn, kGPIO3_RST_SHIFT_RSTn, \
kGPIO4_RST_SHIFT_RSTn \
} /* Reset bits for GPIO peripheral */
#define I3C_RSTS \
{ \
kI3C0_RST_SHIFT_RSTn \
} /* Reset bits for I3C peripheral */
#define INPUTMUX_RSTS \
{ \
kINPUTMUX0_RST_SHIFT_RSTn \
} /* Reset bits for INPUTMUX peripheral */
#define LPUART_RSTS \
{ \
kLPUART0_RST_SHIFT_RSTn, kLPUART1_RST_SHIFT_RSTn, kLPUART2_RST_SHIFT_RSTn, kLPUART3_RST_SHIFT_RSTn, \
kLPUART4_RST_SHIFT_RSTn \
} /* Reset bits for LPUART peripheral */
#define LPSPI_RSTS \
{ \
kLPSPI0_RST_SHIFT_RSTn, kLPSPI1_RST_SHIFT_RSTn \
} /* Reset bits for LPSPI peripheral */
#define LPI2C_RSTS \
{ \
kLPI2C0_RST_SHIFT_RSTn, kLPI2C1_RST_SHIFT_RSTn, kLPI2C2_RST_SHIFT_RSTn, kLPI2C3_RST_SHIFT_RSTn \
} /* Reset bits for LPI2C peripheral */
#define LPCMP_RSTS \
{ \
NotAvail_RSTn, kCMP1_RST_SHIFT_RSTn \
} /* Reset bits for LPCMP peripheral */
#define OPAMP_RSTS \
{ \
kOPAMP0_RST_SHIFT_RSTn \
} /* Reset bits for OPAMP peripheral */
#define OSTIMER_RSTS \
{ \
kOSTIMER0_RST_SHIFT_RSTn \
} /* Reset bits for OSTIMER peripheral */
#define PORT_RSTS_N \
{ \
kPORT0_RST_SHIFT_RSTn, kPORT1_RST_SHIFT_RSTn, kPORT2_RST_SHIFT_RSTn, kPORT3_RST_SHIFT_RSTn, \
kPORT4_RST_SHIFT_RSTn \
} /* Reset bits for PORT peripheral */
#define EQDC_RSTS \
{ \
kQDC0_RST_SHIFT_RSTn, kQDC1_RST_SHIFT_RSTn \
} /* Reset bits for EQDC peripheral */
#define UTICK_RSTS \
{ \
kUTICK0_RST_SHIFT_RSTn \
} /* Reset bits for UTICK peripheral */
typedef SYSCON_RSTn_t reset_ip_name_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Assert reset to peripheral.
*
* Asserts reset signal to specified peripheral module.
*
* @param peripheral Assert reset to this peripheral. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_SetPeripheralReset(reset_ip_name_t peripheral);
/*!
* @brief Clear reset to peripheral.
*
* Clears reset signal to specified peripheral module, allows it to operate.
*
* @param peripheral Clear reset to this peripheral. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_ClearPeripheralReset(reset_ip_name_t peripheral);
/*!
* @brief Reset peripheral module.
*
* Reset peripheral module.
*
* @param peripheral Peripheral to reset. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
void RESET_PeripheralReset(reset_ip_name_t peripheral);
/*!
* @brief Release peripheral module.
*
* Release peripheral module.
*
* @param peripheral Peripheral to release. The enum argument contains encoding of reset register
* and reset bit position in the reset register.
*/
static inline void RESET_ReleasePeripheralReset(reset_ip_name_t peripheral)
{
RESET_SetPeripheralReset(peripheral);
}
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_RESET_H_ */

View File

@ -0,0 +1,507 @@
/*
* Copyright 2023, NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_ROMAPI_H_
#define FSL_ROMAPI_H_
#include "fsl_common.h"
/*!
* @addtogroup romapi
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.romapi"
#endif
/*! @name Driver version */
/*@{*/
/*! @brief romapi driver version 2.0.0. */
#define FSL_ROMAPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/*!
* @name Flash status
* @{
*/
/*! @brief Flash driver status group. */
#if defined(kStatusGroup_FlashDriver)
#define kStatusGroupGeneric kStatusGroup_Generic
#define kStatusGroupFlashDriver kStatusGroup_FlashDriver
#elif defined(kStatusGroup_FLASHIAP)
#define kStatusGroupGeneric kStatusGroup_Generic
#define kStatusGroupFlashDriver kStatusGroup_FLASH
#else
#define kStatusGroupGeneric 0
#define kStatusGroupFlashDriver 1
#endif
/*! @brief Constructs a status code value from a group and a code number. */
#if !defined(MAKE_STATUS)
#define MAKE_STATUS(group, code) ((((group) * 100) + (code)))
#endif
/*!
* @brief Flash driver status codes.
*/
enum
{
kStatus_FLASH_Success = MAKE_STATUS(kStatusGroupGeneric, 0), /*!< API is executed successfully*/
kStatus_FLASH_InvalidArgument = MAKE_STATUS(kStatusGroupGeneric, 4), /*!< Invalid argument*/
kStatus_FLASH_SizeError = MAKE_STATUS(kStatusGroupFlashDriver, 0), /*!< Error size*/
kStatus_FLASH_AlignmentError =
MAKE_STATUS(kStatusGroupFlashDriver, 1), /*!< Parameter is not aligned with the specified baseline*/
kStatus_FLASH_AddressError = MAKE_STATUS(kStatusGroupFlashDriver, 2), /*!< Address is out of range */
kStatus_FLASH_AccessError =
MAKE_STATUS(kStatusGroupFlashDriver, 3), /*!< Invalid instruction codes and out-of bound addresses */
kStatus_FLASH_ProtectionViolation = MAKE_STATUS(
kStatusGroupFlashDriver, 4), /*!< The program/erase operation is requested to execute on protected areas */
kStatus_FLASH_CommandFailure =
MAKE_STATUS(kStatusGroupFlashDriver, 5), /*!< Run-time error during command execution. */
kStatus_FLASH_UnknownProperty = MAKE_STATUS(kStatusGroupFlashDriver, 6), /*!< Unknown property.*/
kStatus_FLASH_EraseKeyError = MAKE_STATUS(kStatusGroupFlashDriver, 7) /*!< API erase key is invalid.*/
};
/*@}*/
/*!
* @brief Enumeration for various flash properties.
*/
typedef enum _flash_property_tag
{
kFLASH_PropertyPflashSectorSize = 0x00U, /*!< Pflash sector size property.*/
kFLASH_PropertyPflashTotalSize = 0x01U, /*!< Pflash total size property.*/
kFLASH_PropertyPflashBlockSize = 0x02U, /*!< Pflash block size property.*/
kFLASH_PropertyPflashBlockCount = 0x03U, /*!< Pflash block count property.*/
kFLASH_PropertyPflashBlockBaseAddr = 0x04U, /*!< Pflash block base address property.*/
kFLASH_PropertyPflashPageSize = 0x30U, /*!< Pflash page size property.*/
kFLASH_PropertyPflashSystemFreq = 0x31U, /*!< System Frequency property.*/
kFLASH_PropertyFfrSectorSize = 0x40U, /*!< FFR sector size property.*/
kFLASH_PropertyFfrTotalSize = 0x41U, /*!< FFR total size property.*/
kFLASH_PropertyFfrBlockBaseAddr = 0x42U, /*!< FFR block base address property.*/
kFLASH_PropertyFfrPageSize = 0x43U, /*!< FFR page size property.*/
} flash_property_tag_t;
/*! @brief Flash controller paramter config. */
typedef struct _flash_ffr_config
{
uint32_t ffrBlockBase;
uint32_t ffrTotalSize;
uint32_t ffrPageSize;
uint32_t sectorSize;
uint32_t cfpaPageVersion;
uint32_t cfpaPageOffset;
} flash_ffr_config_t;
/*! @brief Flash driver state information.
*
* An instance of this structure is allocated by the user of the flash driver and
* passed into each of the driver APIs.
*/
typedef struct _flash_config
{
uint32_t PFlashBlockBase; /*!< A base address of the first PFlash block */
uint32_t PFlashTotalSize; /*!< The size of the combined PFlash block. */
uint32_t PFlashBlockCount; /*!< A number of PFlash blocks. */
uint32_t PFlashPageSize; /*!< The size in bytes of a page of PFlash. */
uint32_t PFlashSectorSize; /*!< The size in bytes of a sector of PFlash. */
flash_ffr_config_t ffrConfig;
} flash_config_t;
/*! @brief Interface for the flash driver. */
typedef struct _flash_driver_interface
{
/* Flash driver */
status_t (*flash_init)(flash_config_t *config);
status_t (*flash_erase_sector)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key);
status_t (*flash_program_phrase)(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes);
status_t (*flash_program_page)(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes);
status_t (*flash_verify_program)(flash_config_t *config,
uint32_t start,
uint32_t lengthInBytes,
const uint8_t *expectedData,
uint32_t *failedAddress,
uint32_t *failedData);
status_t (*flash_verify_erase_phrase)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*flash_verify_erase_page)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*flash_verify_erase_sector)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*flash_get_property)(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value);
/* IFR driver */
status_t (*ifr_verify_erase_phrase)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*ifr_verify_erase_page)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*ifr_verify_erase_sector)(flash_config_t *config, uint32_t start, uint32_t lengthInBytes);
status_t (*flash_read)(flash_config_t *config, uint32_t start, uint8_t *dest, uint32_t lengthInBytes);
/* version */
uint32_t version;
} flash_driver_interface_t;
/*! @brief Constructs the four character code for the Flash driver API key. */
#if !defined(FOUR_CHAR_CODE)
#define FOUR_CHAR_CODE(a, b, c, d) (((d) << 24) | ((c) << 16) | ((b) << 8) | ((a)))
#endif
/*!
* @brief Enumeration for Flash driver API keys.
*
* @note The resulting value is built with a byte order such that the string
* being readable in expected order when viewed in a hex editor, if the value
* is treated as a 32-bit little endian value.
*/
enum _flash_driver_api_keys
{
kFLASH_ApiEraseKey = FOUR_CHAR_CODE('l', 'f', 'e', 'k') /*!< Key value used to validate all flash erase APIs.*/
};
/* API prototype fields definition.
| 31 : 24 | 23 : 20 | 19 : 16 | 15 : 12 | 11 : 8 | 7 0 |
| Tag | Boot mode | bootloader periphal| Instance | Image Index| Reserved |
| | | | Used For Boot mode 0| | |
| | 0: Passive mode | 0 - Auto detection | | | |
| | 1: ISP mode | 1 - USB-HID | | | |
| | | 2 - UART | | | |
| | | 3 - SPI | | | |
| | | 4 - I2C | | | |
| | | 5 - CAN | | | |
*/
typedef struct
{
union
{
struct
{
uint32_t reserved : 8;
uint32_t boot_image_index : 4;
uint32_t instance : 4;
uint32_t boot_interface : 4;
uint32_t mode : 4;
uint32_t tag : 8;
} B;
uint32_t U;
} option;
} user_app_boot_invoke_option_t;
/*! @brief Root of the bootloader API tree.
*
* An instance of this struct resides in read-only memory in the bootloader. It
* provides a user application access to APIs exported by the bootloader.
*
*/
typedef struct _bootloader_tree
{
void (*run_bootloader)(void *arg); /*!< Function to start the bootloader executing. */
const flash_driver_interface_t *flash_driver; /*!< Internal Flash driver API. */
void (*jump)(void *arg);
} bootloader_tree_t;
/** ROM API base address */
#define ROM_API_BASE (0x03003fe0u)
/** ROM API base pointer */
#define ROM_API ((bootloader_tree_t *)ROM_API_BASE)
/** FLASH API base pointer */
#define FLASH_API (ROM_API->flash_driver)
/*!
* @name Flash API
* @{
*/
/*!
* @brief Initializes the global flash properties structure members
*
* This function checks and initializes the Flash module for the other Flash APIs.
*
* @param config Pointer to the storage for the driver runtime state.
*
*/
static inline status_t FLASH_Init(flash_config_t *config)
{
return FLASH_API->flash_init(config);
}
/*!
* @brief Erases the flash sectors encompassed by parameters passed into function
*
* This function erases the appropriate number of flash sectors based on the
* desired start address and length.
*
* @param config The pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be erased.
* NOTE: The start address need to be 4 Bytes-aligned.
*
* @param lengthInBytes The length, given in bytes need be 4 Bytes-aligned.
*
* @param key The value used to validate all flash erase APIs.
*
*/
static inline status_t FLASH_EraseSector(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key)
{
return FLASH_API->flash_erase_sector(config, start, lengthInBytes, key);
}
/*!
* @brief Programs flash phrases with data at locations passed in through parameters
*
* This function programs the flash memory with the desired data for a given
* flash area as determined by the start address and the length.
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be programmed. Must be
* word-aligned.
* @param src A pointer to the source buffer of data that is to be programmed
* into the flash.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be programmed. Must be word-aligned.
*
*/
static inline status_t FLASH_ProgramPhrase(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
{
return FLASH_API->flash_program_phrase(config, start, src, lengthInBytes);
}
/*!
* @brief Programs flash page with data at locations passed in through parameters
*
* This function programs the flash memory with the desired data for a given
* flash area as determined by the start address and the length.
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be programmed. Must be
* word-aligned.
* @param src A pointer to the source buffer of data that is to be programmed
* into the flash.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be programmed. Must be word-aligned.
*
*/
static inline status_t FLASH_ProgramPage(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes)
{
return FLASH_API->flash_program_page(config, start, src, lengthInBytes);
}
/*!
* @brief Verifies programming of the desired flash area
*
* This function verifies the data programed in the flash memory using the
* Flash Program Check Command and compares it to the expected data for a given
* flash area as determined by the start address and length.
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified. Must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
* @param expectedData A pointer to the expected data that is to be
* verified against.
* @param failedAddress A pointer to the returned failing address.
* @param failedData A pointer to the returned failing data. Some derivatives do
* not include failed data as part of the FCCOBx registers. In this
* case, zeros are returned upon failure.
*
*/
static inline status_t FLASH_VerifyProgram(flash_config_t *config,
uint32_t start,
uint32_t lengthInBytes,
const uint8_t *expectedData,
uint32_t *failedAddress,
uint32_t *failedData)
{
return FLASH_API->flash_verify_program(config, start, lengthInBytes, expectedData, failedAddress, failedData);
}
/*!
* @brief Verify that the flash phrases are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t FLASH_VerifyErasePhrase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->flash_verify_erase_phrase(config, start, lengthInBytes);
}
/*!
* @brief Verify that the flash pages are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t FLASH_VerifyErasePage(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->flash_verify_erase_page(config, start, lengthInBytes);
}
/*!
* @brief Verify that the flash sectors are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t FLASH_VerifyEraseSector(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->flash_verify_erase_sector(config, start, lengthInBytes);
}
/*!
* @brief Returns the desired flash property
*
* @param config A pointer to the storage for the driver runtime state.
* @param whichProperty The desired property from the list of properties in
* enum flash_property_tag_t
* @param value A pointer to the value returned for the desired flash property.
*
*/
static inline status_t FLASH_GetProperty(flash_config_t *config, flash_property_tag_t whichProperty, uint32_t *value)
{
return FLASH_API->flash_get_property(config, whichProperty, value);
}
/*!
* @brief Verify that the IFR0 phrases are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t IFR_VerifyErasePhrase(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->ifr_verify_erase_phrase(config, start, lengthInBytes);
}
/*!
* @brief Verify that the IFR0 pages are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t IFR_VerifyErasePage(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->ifr_verify_erase_page(config, start, lengthInBytes);
}
/*!
* @brief Verify that the IFR0 sectors are erased
*
* This function checks the appropriate number of flash sectors based on
* the desired start address and length to check whether the flash is erased
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be verified.
* The start address does not need to be sector-aligned but must be word-aligned.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be verified. Must be word-aligned.
*
*/
static inline status_t IFR_VerifyEraseSector(flash_config_t *config, uint32_t start, uint32_t lengthInBytes)
{
return FLASH_API->ifr_verify_erase_sector(config, start, lengthInBytes);
}
/*!
* @brief Reads flash at locations passed in through parameters
*
* This function read the flash memory from a given flash area as determined
* by the start address and the length.
*
* @param config A pointer to the storage for the driver runtime state.
* @param start The start address of the desired flash memory to be read.
* @param dest A pointer to the dest buffer of data that is to be read
* from the flash.
* @param lengthInBytes The length, given in bytes (not words or long-words),
* to be read.
*
*/
static inline status_t FLASH_Read(flash_config_t *config, uint32_t start, uint8_t *dest, uint32_t lengthInBytes)
{
return FLASH_API->flash_read(config, start, dest, lengthInBytes);
}
/*!
* @brief Get ROM API version.
*
* This function read the ROM API version.
*
*/
static inline uint32_t ROMAPI_GetVersion(void)
{
return FLASH_API->version;
}
/*!
* @brief Run the Bootloader API to force into the ISP mode base on the user arg
*
* @param arg Indicates API prototype fields definition.
* Refer to the above #user_app_boot_invoke_option_t structure
*/
static inline void ROMAPI_RunBootloader(void *arg)
{
ROM_API->run_bootloader(arg);
}
/*!
* @brief Get the UUID
*
* @param uuid UUID data array
*
*/
static inline void ROMAPI_GetUUID(uint8_t *uuid)
{
#define MCXA_UUID_ADDR (0x01100800U)
#define MCXA_UUID_SIZE (16U)
uint8_t *p = (uint8_t *)MCXA_UUID_ADDR;
for (uint8_t i = 0; i < MCXA_UUID_SIZE; i++)
{
*uuid = *p;
uuid++;
p++;
}
}
/* @} */
/*! @} */
#endif /* FSL_ROMAPI_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More