diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/TARGET_LPC54114_M4/LPC54114_cm4_features.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/TARGET_LPC54114_M4/LPC54114_cm4_features.h index b1cf887ac7..42ef5ab1f2 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/TARGET_LPC54114_M4/LPC54114_cm4_features.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/device/TARGET_LPC54114_M4/LPC54114_cm4_features.h @@ -1,41 +1,19 @@ /* ** ################################################################### ** Version: rev. 1.0, 2016-05-09 -** Build: b160802 +** Build: b190225 ** ** Abstract: ** Chip specific module features. ** -** Copyright (c) 2016 Freescale Semiconductor, Inc. +** Copyright 2016 Freescale Semiconductor, Inc. +** Copyright 2016-2019 NXP ** All rights reserved. ** -** Redistribution and use in source and binary forms, with or without modification, -** are permitted provided that the following conditions are met: +** SPDX-License-Identifier: BSD-3-Clause ** -** o Redistributions of source code must retain the above copyright notice, this list -** of conditions and the following disclaimer. -** -** o Redistributions in binary form must reproduce the above copyright notice, this -** list of conditions and the following disclaimer in the documentation and/or -** other materials provided with the distribution. -** -** o Neither the name of Freescale Semiconductor, Inc. nor the names of its -** contributors may be used to endorse or promote products derived from this -** software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -** http: www.freescale.com -** mail: support@freescale.com +** http: www.nxp.com +** mail: support@nxp.com ** ** Revisions: ** - rev. 1.0 (2016-05-09) @@ -55,6 +33,8 @@ #define FSL_FEATURE_SOC_ASYNC_SYSCON_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 DMA availability on the SoC. */ #define FSL_FEATURE_SOC_DMA_COUNT (1) /* @brief DMIC availability on the SoC. */ @@ -89,8 +69,6 @@ #define FSL_FEATURE_SOC_SPIFI_COUNT (1) /* @brief SYSCON availability on the SoC. */ #define FSL_FEATURE_SOC_SYSCON_COUNT (1) -/* @brief CTIMER availability on the SoC. */ -#define FSL_FEATURE_SOC_CTIMER_COUNT (5) /* @brief USART availability on the SoC. */ #define FSL_FEATURE_SOC_USART_COUNT (8) /* @brief USB availability on the SoC. */ @@ -100,16 +78,139 @@ /* @brief WWDT availability on the SoC. */ #define FSL_FEATURE_SOC_WWDT_COUNT (1) +/* ADC module features */ + +/* @brief Do not has input select (register INSEL). */ +#define FSL_FEATURE_ADC_HAS_NO_INSEL (0) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE (1) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_RESOL (1) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL (1) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_TSAMP (1) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE (0) +/* @brief Has ASYNMODE bitfile in CTRL reigster. */ +#define FSL_FEATURE_ADC_HAS_CTRL_CALMODE (0) +/* @brief Has startup register. */ +#define FSL_FEATURE_ADC_HAS_STARTUP_REG (1) +/* @brief Has ADTrim register */ +#define FSL_FEATURE_ADC_HAS_TRIM_REG (0) +/* @brief Has Calibration register. */ +#define FSL_FEATURE_ADC_HAS_CALIB_REG (1) + /* DMA module features */ /* @brief Number of channels */ #define FSL_FEATURE_DMA_NUMBER_OF_CHANNELS (20) +/* @brief Align size of DMA descriptor */ +#define FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE (512) +/* @brief DMA head link descriptor table align size */ +#define FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE (16U) + +/* FLEXCOMM module features */ + +/* @brief FLEXCOMM0 USART INDEX 0 */ +#define FSL_FEATURE_FLEXCOMM0_USART_INDEX (0) +/* @brief FLEXCOMM0 SPI INDEX 0 */ +#define FSL_FEATURE_FLEXCOMM0_SPI_INDEX (0) +/* @brief FLEXCOMM0 I2C INDEX 0 */ +#define FSL_FEATURE_FLEXCOMM0_I2C_INDEX (0) +/* @brief FLEXCOMM1 USART INDEX 1 */ +#define FSL_FEATURE_FLEXCOMM1_USART_INDEX (1) +/* @brief FLEXCOMM1 SPI INDEX 1 */ +#define FSL_FEATURE_FLEXCOMM1_SPI_INDEX (1) +/* @brief FLEXCOMM1 I2C INDEX 1 */ +#define FSL_FEATURE_FLEXCOMM1_I2C_INDEX (1) +/* @brief FLEXCOMM2 USART INDEX 2 */ +#define FSL_FEATURE_FLEXCOMM2_USART_INDEX (2) +/* @brief FLEXCOMM2 SPI INDEX 2 */ +#define FSL_FEATURE_FLEXCOMM2_SPI_INDEX (2) +/* @brief FLEXCOMM2 I2C INDEX 2 */ +#define FSL_FEATURE_FLEXCOMM2_I2C_INDEX (2) +/* @brief FLEXCOMM3 USART INDEX 3 */ +#define FSL_FEATURE_FLEXCOMM3_USART_INDEX (3) +/* @brief FLEXCOMM3 SPI INDEX 3 */ +#define FSL_FEATURE_FLEXCOMM3_SPI_INDEX (3) +/* @brief FLEXCOMM3 I2C INDEX 3 */ +#define FSL_FEATURE_FLEXCOMM3_I2C_INDEX (3) +/* @brief FLEXCOMM4 USART INDEX 4 */ +#define FSL_FEATURE_FLEXCOMM4_USART_INDEX (4) +/* @brief FLEXCOMM4 SPI INDEX 4 */ +#define FSL_FEATURE_FLEXCOMM4_SPI_INDEX (4) +/* @brief FLEXCOMM4 I2C INDEX 4 */ +#define FSL_FEATURE_FLEXCOMM4_I2C_INDEX (4) +/* @brief FLEXCOMM5 USART INDEX 5 */ +#define FSL_FEATURE_FLEXCOMM5_USART_INDEX (5) +/* @brief FLEXCOMM5 SPI INDEX 5 */ +#define FSL_FEATURE_FLEXCOMM5_SPI_INDEX (5) +/* @brief FLEXCOMM5 I2C INDEX 5 */ +#define FSL_FEATURE_FLEXCOMM5_I2C_INDEX (5) +/* @brief FLEXCOMM6 USART INDEX 6 */ +#define FSL_FEATURE_FLEXCOMM6_USART_INDEX (6) +/* @brief FLEXCOMM6 SPI INDEX 6 */ +#define FSL_FEATURE_FLEXCOMM6_SPI_INDEX (6) +/* @brief FLEXCOMM6 I2C INDEX 6 */ +#define FSL_FEATURE_FLEXCOMM6_I2C_INDEX (6) +/* @brief FLEXCOMM7 I2S INDEX 0 */ +#define FSL_FEATURE_FLEXCOMM6_I2S_INDEX (0) +/* @brief FLEXCOMM7 USART INDEX 7 */ +#define FSL_FEATURE_FLEXCOMM7_USART_INDEX (7) +/* @brief FLEXCOMM7 SPI INDEX 7 */ +#define FSL_FEATURE_FLEXCOMM7_SPI_INDEX (7) +/* @brief FLEXCOMM7 I2C INDEX 7 */ +#define FSL_FEATURE_FLEXCOMM7_I2C_INDEX (7) +/* @brief FLEXCOMM7 I2S INDEX 1 */ +#define FSL_FEATURE_FLEXCOMM7_I2S_INDEX (1) +/* @brief I2S has DMIC interconnection */ +#define FSL_FEATURE_FLEXCOMM_INSTANCE_I2S_HAS_DMIC_INTERCONNECTIONn(x) \ + (((x) == FLEXCOMM0) ? (0) : \ + (((x) == FLEXCOMM1) ? (0) : \ + (((x) == FLEXCOMM2) ? (0) : \ + (((x) == FLEXCOMM3) ? (0) : \ + (((x) == FLEXCOMM4) ? (0) : \ + (((x) == FLEXCOMM5) ? (0) : \ + (((x) == FLEXCOMM6) ? (0) : \ + (((x) == FLEXCOMM7) ? (1) : (-1))))))))) + +/* I2S module features */ + +/* @brief I2S support dual channel transfer */ +#define FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL (0) +/* @brief I2S has DMIC interconnection */ +#define FSL_FEATURE_FLEXCOMM_I2S_HAS_DMIC_INTERCONNECTION (1) + +/* MAILBOX module features */ + +/* @brief Mailbox side for current core */ +#define FSL_FEATURE_MAILBOX_SIDE_A (1) +/* @brief Mailbox has no reset control */ +#define FSL_FEATURE_MAILBOX_HAS_NO_RESET (1) + +/* MRT module features */ + +/* @brief number of channels. */ +#define FSL_FEATURE_MRT_NUMBER_OF_CHANNELS (4) + +/* interrupt module features */ + +/* @brief Lowest interrupt request number. */ +#define FSL_FEATURE_INTERRUPT_IRQ_MIN (-14) +/* @brief Highest interrupt request number. */ +#define FSL_FEATURE_INTERRUPT_IRQ_MAX (105) /* PINT module features */ /* @brief Number of connected outputs */ #define FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS (8) +/* RTC module features */ + +/* @brief RTC has no reset control */ +#define FSL_FEATURE_RTC_HAS_NO_RESET (1) + /* SCT module features */ /* @brief Number of events */ @@ -118,6 +219,8 @@ #define FSL_FEATURE_SCT_NUMBER_OF_STATES (10) /* @brief Number of match capture */ #define FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE (10) +/* @brief Number of outputs */ +#define FSL_FEATURE_SCT_NUMBER_OF_OUTPUTS (8) /* SYSCON module features */ @@ -129,6 +232,24 @@ #define FSL_FEATURE_SYSCON_FLASH_SECTOR_SIZE_BYTES (32768) /* @brief Flash size in bytes */ #define FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES (262144) +/* @brief IAP has Flash read & write function */ +#define FSL_FEATURE_IAP_HAS_FLASH_FUNCTION (1) +/* @brief IAP has read Flash signature function */ +#define FSL_FEATURE_IAP_HAS_FLASH_SIGNATURE_READ (1) +/* @brief IAP has read extended Flash signature function */ +#define FSL_FEATURE_IAP_HAS_FLASH_EXTENDED_SIGNATURE_READ (0) + +/* SysTick module features */ + +/* @brief Systick has external reference clock. */ +#define FSL_FEATURE_SYSTICK_HAS_EXT_REF (0) +/* @brief Systick external reference clock is core clock divided by this value. */ +#define FSL_FEATURE_SYSTICK_EXT_REF_CORE_DIV (0) + +/* USB module features */ + +/* @brief Number of the endpoint in USB FS */ +#define FSL_FEATURE_USB_EP_NUM (5) #endif /* _LPC54114_cm4_FEATURES_H_ */ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.c index 2bdd60d72f..9dda535e6f 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.c @@ -1,45 +1,32 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_adc.h" #include "fsl_clock.h" +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.lpc_adc" +#endif + static ADC_Type *const s_adcBases[] = ADC_BASE_PTRS; +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) static const clock_ip_name_t s_adcClocks[] = ADC_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +#define FREQUENCY_1MHZ (1000000U) static uint32_t ADC_GetInstance(ADC_Type *base) { uint32_t instance; /* Find the instance index from base address mappings. */ - for (instance = 0; instance < FSL_FEATURE_SOC_ADC_COUNT; instance++) + for (instance = 0; instance < ARRAY_SIZE(s_adcBases); instance++) { if (s_adcBases[instance] == base) { @@ -47,19 +34,27 @@ static uint32_t ADC_GetInstance(ADC_Type *base) } } - assert(instance < FSL_FEATURE_SOC_ADC_COUNT); + assert(instance < ARRAY_SIZE(s_adcBases)); return instance; } +/*! + * brief Initialize the ADC module. + * + * param base ADC peripheral base address. + * param config Pointer to configuration structure, see to #adc_config_t. + */ void ADC_Init(ADC_Type *base, const adc_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 clock. */ CLOCK_EnableClock(s_adcClocks[ADC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ /* Disable the interrupts. */ base->INTEN = 0U; /* Quickly disable all the interrupts. */ @@ -67,6 +62,7 @@ void ADC_Init(ADC_Type *base, const adc_config_t *config) /* Configure the ADC block. */ tmp32 = ADC_CTRL_CLKDIV(config->clockDividerNumber); +#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE /* Async or Sync clock mode. */ switch (config->clockMode) { @@ -76,84 +72,236 @@ void ADC_Init(ADC_Type *base, const adc_config_t *config) default: /* kADC_ClockSynchronousMode */ break; } +#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL /* Resolution. */ - tmp32 |= ADC_CTRL_RESOL(config->resolution); + tmp32 |= ADC_CTRL_RESOL(config->resolution); +#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) & FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL /* Bypass calibration. */ if (config->enableBypassCalibration) { tmp32 |= ADC_CTRL_BYPASSCAL_MASK; } +#endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL. */ - /* Sample time clock count. */ - tmp32 |= ADC_CTRL_TSAMP(config->sampleTimeNumber); +#if defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) & FSL_FEATURE_ADC_HAS_CTRL_TSAMP +/* Sample time clock count. */ +#if (defined(FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) && FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) + if (config->clockMode == kADC_ClockAsynchronousMode) + { +#endif /* FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL */ + tmp32 |= ADC_CTRL_TSAMP(config->sampleTimeNumber); +#if (defined(FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) && FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL) + } +#endif /* FSL_FEATURE_ADC_SYNCHRONOUS_USE_GPADC_CTRL */ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) & FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE + if (config->enableLowPowerMode) + { + tmp32 |= ADC_CTRL_LPWRMODE_MASK; + } +#endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE. */ base->CTRL = tmp32; + +#if defined(FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN) && FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN + base->GPADC_CTRL0 |= ADC_GPADC_CTRL0_LDO_POWER_EN_MASK; + if (config->clockMode == kADC_ClockSynchronousMode) + { + base->GPADC_CTRL0 |= ADC_GPADC_CTRL0_PASS_ENABLE(config->sampleTimeNumber); + } +#endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL0_LDO_POWER_EN */ + +#if defined(FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL) && FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL + tmp32 = *(uint32_t *)FSL_FEATURE_FLASH_ADDR_OF_TEMP_CAL; + if (tmp32 & FSL_FEATURE_FLASH_ADDR_OF_TEMP_CAL_VALID) + { + base->GPADC_CTRL1 = (tmp32 >> 1); + } +#if !(defined(FSL_FEATURE_ADC_HAS_STARTUP_ADC_INIT) && FSL_FEATURE_ADC_HAS_STARTUP_ADC_INIT) + base->STARTUP = ADC_STARTUP_ADC_ENA_MASK; /* Set the ADC Start bit */ +#endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL */ +#endif /* FSL_FEATURE_ADC_HAS_GPADC_CTRL1_OFFSET_CAL */ + +#if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG + base->TRM &= ~ADC_TRM_VRANGE_MASK; + base->TRM |= ADC_TRM_VRANGE(config->voltageRange); +#endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ } +/*! + * brief Gets an available pre-defined settings for initial configuration. + * + * This function initializes the initial configuration structure with an available settings. The default values are: + * code + * config->clockMode = kADC_ClockSynchronousMode; + * config->clockDividerNumber = 0U; + * config->resolution = kADC_Resolution12bit; + * config->enableBypassCalibration = false; + * config->sampleTimeNumber = 0U; + * endcode + * param config Pointer to configuration structure. + */ void ADC_GetDefaultConfig(adc_config_t *config) { + /* Initializes the configure structure to zero. */ + memset(config, 0, sizeof(*config)); + +#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE + config->clockMode = kADC_ClockSynchronousMode; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ + config->clockDividerNumber = 0U; +#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL config->resolution = kADC_Resolution12bit; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) & FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL config->enableBypassCalibration = false; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) & FSL_FEATURE_ADC_HAS_CTRL_TSAMP config->sampleTimeNumber = 0U; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) & FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE + config->enableLowPowerMode = false; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE. */ +#if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG + config->voltageRange = kADC_HighVoltageRange; +#endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ } +/*! + * brief Deinitialize the ADC module. + * + * param base ADC peripheral base address. + */ void ADC_Deinit(ADC_Type *base) { +#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) /* Disable the clock. */ CLOCK_DisableClock(s_adcClocks[ADC_GetInstance(base)]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ } +#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) +#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) & FSL_FEATURE_ADC_HAS_CALIB_REG +/*! + * brief Do the self calibration. To calibrate the ADC, set the ADC clock to 1 mHz. + * In order to achieve the specified ADC accuracy, the A/D converter must be recalibrated, at a minimum, + * following every chip reset before initiating normal ADC operation. + * + * param base ADC peripheral base address. + * retval true Calibration succeed. + * retval false Calibration failed. + */ bool ADC_DoSelfCalibration(ADC_Type *base) { - uint32_t i; + uint32_t frequency = 0U; + uint32_t delayUs = 0U; /* Enable the converter. */ /* This bit acn only be set 1 by software. It is cleared automatically whenever the ADC is powered down. This bit should be set after at least 10 ms after the ADC is powered on. */ base->STARTUP = ADC_STARTUP_ADC_ENA_MASK; - for (i = 0U; i < 0x10; i++) /* Wait a few clocks to startup up. */ - { - __ASM("NOP"); - } + SDK_DelayAtLeastUs(1U); if (!(base->STARTUP & ADC_STARTUP_ADC_ENA_MASK)) { return false; /* ADC is not powered up. */ } + /* Get the ADC clock frequency in synchronous mode. */ + frequency = CLOCK_GetFreq(kCLOCK_BusClk) / (((base->CTRL & ADC_CTRL_CLKDIV_MASK) >> ADC_CTRL_CLKDIV_SHIFT) + 1); + base->CTRL |= ADC_CTRL_CLKDIV((frequency / 1000000U) - 1U); + frequency = 1000000U; +#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) && FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE + /* Get the ADC clock frequency in asynchronous mode. */ + if (ADC_CTRL_ASYNMODE_MASK == (base->CTRL & ADC_CTRL_ASYNMODE_MASK)) + { + frequency = CLOCK_GetAdcClkFreq(); + } +#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE */ + assert(0U != frequency); + /* If not in by-pass mode, do the calibration. */ if ((ADC_CALIB_CALREQD_MASK == (base->CALIB & ADC_CALIB_CALREQD_MASK)) && (0U == (base->CTRL & ADC_CTRL_BYPASSCAL_MASK))) { + /* A calibration cycle requires approximately 81 ADC clocks to complete. */ + delayUs = (120 * FREQUENCY_1MHZ) / frequency + 1; /* Calibration is needed, do it now. */ base->CALIB = ADC_CALIB_CALIB_MASK; - i = 0xF0000; - while ((ADC_CALIB_CALIB_MASK == (base->CALIB & ADC_CALIB_CALIB_MASK)) && (--i)) - { - } - if (i == 0U) + SDK_DelayAtLeastUs(delayUs); + if (ADC_CALIB_CALIB_MASK == (base->CALIB & ADC_CALIB_CALIB_MASK)) { return false; /* Calibration timeout. */ } } - /* A dummy conversion cycle will be performed. */ + /* A “dummy” conversion cycle requires approximately 6 ADC clocks */ + delayUs = (10 * FREQUENCY_1MHZ) / frequency + 1; base->STARTUP |= ADC_STARTUP_ADC_INIT_MASK; - i = 0x7FFFF; - while ((ADC_STARTUP_ADC_INIT_MASK == (base->STARTUP & ADC_STARTUP_ADC_INIT_MASK)) && (--i)) - { - } - if (i == 0U) + SDK_DelayAtLeastUs(delayUs); + if (ADC_STARTUP_ADC_INIT_MASK == (base->STARTUP & ADC_STARTUP_ADC_INIT_MASK)) { return false; } return true; } +#else +/*! + * brief Do the self calibration. To calibrate the ADC, set the ADC clock to 1 mHz. + * In order to achieve the specified ADC accuracy, the A/D converter must be recalibrated, at a minimum, + * following every chip reset before initiating normal ADC operation. + * + * param base ADC peripheral base address. + * param frequency The ststem clock frequency to ADC. + * retval true Calibration succeed. + * retval false Calibration failed. + */ +bool ADC_DoSelfCalibration(ADC_Type *base, uint32_t frequency) +{ + uint32_t tmp32; + /* Store the current contents of the ADC CTRL register. */ + tmp32 = base->CTRL; + + /* Start ADC self-calibration. */ + base->CTRL |= ADC_CTRL_CALMODE_MASK; + + /* Divide the system clock to yield an ADC clock of about 1 mHz. */ + base->CTRL &= ~ADC_CTRL_CLKDIV_MASK; + base->CTRL |= ADC_CTRL_CLKDIV((frequency / 1000000U) - 1U); + + /* Clear the LPWR bit. */ + base->CTRL &= ~ADC_CTRL_LPWRMODE_MASK; + /* Delay for 120 uSec @ 1 mHz ADC clock */ + SDK_DelayAtLeastUs(120U); + + /* Check the completion of calibration. */ + if (ADC_CTRL_CALMODE_MASK == (base->CTRL & ADC_CTRL_CALMODE_MASK)) + { + /* Restore the contents of the ADC CTRL register. */ + base->CTRL = tmp32; + return false; /* Calibration timeout. */ + } + /* Restore the contents of the ADC CTRL register. */ + base->CTRL = tmp32; + + return true; +} +#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */ +#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC*/ + +/*! + * brief Configure the conversion sequence A. + * + * param base ADC peripheral base address. + * param config Pointer to configuration structure, see to #adc_conv_seq_config_t. + */ void ADC_SetConvSeqAConfig(ADC_Type *base, const adc_conv_seq_config_t *config) { assert(config != NULL); @@ -198,6 +346,12 @@ void ADC_SetConvSeqAConfig(ADC_Type *base, const adc_conv_seq_config_t *config) base->SEQ_CTRL[0] = tmp32; } +/*! + * brief Configure the conversion sequence B. + * + * param base ADC peripheral base address. + * param config Pointer to configuration structure, see to #adc_conv_seq_config_t. + */ void ADC_SetConvSeqBConfig(ADC_Type *base, const adc_conv_seq_config_t *config) { assert(config != NULL); @@ -242,6 +396,14 @@ void ADC_SetConvSeqBConfig(ADC_Type *base, const adc_conv_seq_config_t *config) base->SEQ_CTRL[1] = tmp32; } +/*! + * brief Get the global ADC conversion infomation of sequence A. + * + * param base ADC peripheral base address. + * param info Pointer to information structure, see to #adc_result_info_t; + * retval true The conversion result is ready. + * retval false The conversion result is not ready yet. + */ bool ADC_GetConvSeqAGlobalConversionResult(ADC_Type *base, adc_result_info_t *info) { assert(info != NULL); @@ -259,11 +421,19 @@ bool ADC_GetConvSeqAGlobalConversionResult(ADC_Type *base, adc_result_info_t *in info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT; - info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); + info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); return true; } +/*! + * brief Get the global ADC conversion infomation of sequence B. + * + * param base ADC peripheral base address. + * param info Pointer to information structure, see to #adc_result_info_t; + * retval true The conversion result is ready. + * retval false The conversion result is not ready yet. + */ bool ADC_GetConvSeqBGlobalConversionResult(ADC_Type *base, adc_result_info_t *info) { assert(info != NULL); @@ -281,11 +451,20 @@ bool ADC_GetConvSeqBGlobalConversionResult(ADC_Type *base, adc_result_info_t *in info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)((tmp32 & ADC_SEQ_GDAT_THCMPCROSS_MASK) >> ADC_SEQ_GDAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_SEQ_GDAT_CHN_MASK) >> ADC_SEQ_GDAT_CHN_SHIFT; - info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); + info->overrunFlag = ((tmp32 & ADC_SEQ_GDAT_OVERRUN_MASK) == ADC_SEQ_GDAT_OVERRUN_MASK); return true; } +/*! + * brief Get the channel's ADC conversion completed under each conversion sequence. + * + * param base ADC peripheral base address. + * param channel The indicated channel number. + * param info Pointer to information structure, see to #adc_result_info_t; + * retval true The conversion result is ready. + * retval false The conversion result is not ready yet. + */ bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result_info_t *info) { assert(info != NULL); @@ -299,12 +478,51 @@ bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result } info->result = (tmp32 & ADC_DAT_RESULT_MASK) >> ADC_DAT_RESULT_SHIFT; +#if (defined(FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) && FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) + switch ((base->CTRL & ADC_CTRL_RESOL_MASK) >> ADC_CTRL_RESOL_SHIFT) + { + case kADC_Resolution10bit: + info->result >>= kADC_Resolution10bitInfoResultShift; + break; + case kADC_Resolution8bit: + info->result >>= kADC_Resolution8bitInfoResultShift; + break; + case kADC_Resolution6bit: + info->result >>= kADC_Resolution6bitInfoResultShift; + break; + default: + break; + } +#endif info->thresholdCompareStatus = (adc_threshold_compare_status_t)((tmp32 & ADC_DAT_THCMPRANGE_MASK) >> ADC_DAT_THCMPRANGE_SHIFT); info->thresholdCorssingStatus = (adc_threshold_crossing_status_t)((tmp32 & ADC_DAT_THCMPCROSS_MASK) >> ADC_DAT_THCMPCROSS_SHIFT); info->channelNumber = (tmp32 & ADC_DAT_CHANNEL_MASK) >> ADC_DAT_CHANNEL_SHIFT; - info->overrunFlag = ((tmp32 & ADC_DAT_OVERRUN_MASK) == ADC_DAT_OVERRUN_MASK); + info->overrunFlag = ((tmp32 & ADC_DAT_OVERRUN_MASK) == ADC_DAT_OVERRUN_MASK); return true; } +#if defined(FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) && (FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) +void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable) +{ + if (enable) + { + SYSCON->ASYNCAPBCTRL = SYSCON_ASYNCAPBCTRL_ENABLE_MASK; + ASYNC_SYSCON->TEMPSENSORCTRL = kADC_NoOffsetAdded; + ASYNC_SYSCON->TEMPSENSORCTRL |= ASYNC_SYSCON_TEMPSENSORCTRL_ENABLE_MASK; + base->GPADC_CTRL0 |= (kADC_ADCInUnityGainMode | kADC_Impedance87kOhm); + } + else + { + /* if the temperature sensor is not turned on then ASYNCAPBCTRL is likely to be zero + * and accessing the registers will cause a memory access error. Test for this */ + if (SYSCON->ASYNCAPBCTRL == SYSCON_ASYNCAPBCTRL_ENABLE_MASK) + { + ASYNC_SYSCON->TEMPSENSORCTRL = 0x0; + base->GPADC_CTRL0 &= ~(kADC_ADCInUnityGainMode | kADC_Impedance87kOhm); + base->GPADC_CTRL0 |= kADC_Impedance55kOhm; + } + } +} +#endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.h index 23dcf68d77..e1679580bd 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_adc.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016-2019 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __FSL_ADC_H__ @@ -46,25 +24,26 @@ /*! @name Driver version */ /*@{*/ -/*! @brief ADC driver version 1.0.0. */ -#define LPC_ADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief ADC driver version 2.3.1. */ +#define FSL_ADC_DRIVER_VERSION (MAKE_VERSION(2, 3, 1)) /*@}*/ /*! * @brief Flags */ + enum _adc_status_flags { - kADC_ThresholdCompareFlagOnChn0 = 1U << 0U, /*!< Threshold comparison event on Channel 0. */ - kADC_ThresholdCompareFlagOnChn1 = 1U << 1U, /*!< Threshold comparison event on Channel 1. */ - kADC_ThresholdCompareFlagOnChn2 = 1U << 2U, /*!< Threshold comparison event on Channel 2. */ - kADC_ThresholdCompareFlagOnChn3 = 1U << 3U, /*!< Threshold comparison event on Channel 3. */ - kADC_ThresholdCompareFlagOnChn4 = 1U << 4U, /*!< Threshold comparison event on Channel 4. */ - kADC_ThresholdCompareFlagOnChn5 = 1U << 5U, /*!< Threshold comparison event on Channel 5. */ - kADC_ThresholdCompareFlagOnChn6 = 1U << 6U, /*!< Threshold comparison event on Channel 6. */ - kADC_ThresholdCompareFlagOnChn7 = 1U << 7U, /*!< Threshold comparison event on Channel 7. */ - kADC_ThresholdCompareFlagOnChn8 = 1U << 8U, /*!< Threshold comparison event on Channel 8. */ - kADC_ThresholdCompareFlagOnChn9 = 1U << 9U, /*!< Threshold comparison event on Channel 9. */ + kADC_ThresholdCompareFlagOnChn0 = 1U << 0U, /*!< Threshold comparison event on Channel 0. */ + kADC_ThresholdCompareFlagOnChn1 = 1U << 1U, /*!< Threshold comparison event on Channel 1. */ + kADC_ThresholdCompareFlagOnChn2 = 1U << 2U, /*!< Threshold comparison event on Channel 2. */ + kADC_ThresholdCompareFlagOnChn3 = 1U << 3U, /*!< Threshold comparison event on Channel 3. */ + kADC_ThresholdCompareFlagOnChn4 = 1U << 4U, /*!< Threshold comparison event on Channel 4. */ + kADC_ThresholdCompareFlagOnChn5 = 1U << 5U, /*!< Threshold comparison event on Channel 5. */ + kADC_ThresholdCompareFlagOnChn6 = 1U << 6U, /*!< Threshold comparison event on Channel 6. */ + kADC_ThresholdCompareFlagOnChn7 = 1U << 7U, /*!< Threshold comparison event on Channel 7. */ + kADC_ThresholdCompareFlagOnChn8 = 1U << 8U, /*!< Threshold comparison event on Channel 8. */ + kADC_ThresholdCompareFlagOnChn9 = 1U << 9U, /*!< Threshold comparison event on Channel 9. */ kADC_ThresholdCompareFlagOnChn10 = 1U << 10U, /*!< Threshold comparison event on Channel 10. */ kADC_ThresholdCompareFlagOnChn11 = 1U << 11U, /*!< Threshold comparison event on Channel 11. */ kADC_OverrunFlagForChn0 = @@ -93,10 +72,10 @@ enum _adc_status_flags 1U << 23U, /*!< Mirror the OVERRUN status flag from the result register for ADC channel 11. */ kADC_GlobalOverrunFlagForSeqA = 1U << 24U, /*!< Mirror the glabal OVERRUN status flag for conversion sequence A. */ kADC_GlobalOverrunFlagForSeqB = 1U << 25U, /*!< Mirror the global OVERRUN status flag for conversion sequence B. */ - kADC_ConvSeqAInterruptFlag = 1U << 28U, /*!< Sequence A interrupt/DMA trigger. */ - kADC_ConvSeqBInterruptFlag = 1U << 29U, /*!< Sequence B interrupt/DMA trigger. */ - kADC_ThresholdCompareInterruptFlag = 1U << 30U, /*!< Threshold comparision interrupt flag. */ - kADC_OverrunInterruptFlag = 1U << 31U, /*!< Overrun interrupt flag. */ + kADC_ConvSeqAInterruptFlag = 1U << 28U, /*!< Sequence A interrupt/DMA trigger. */ + kADC_ConvSeqBInterruptFlag = 1U << 29U, /*!< Sequence B interrupt/DMA trigger. */ + kADC_ThresholdCompareInterruptFlag = 1U << 30U, /*!< Threshold comparision interrupt flag. */ + kADC_OverrunInterruptFlag = (int)(1U << 31U), /*!< Overrun interrupt flag. */ }; /*! @@ -110,10 +89,11 @@ enum _adc_interrupt_enable kADC_ConvSeqBInterruptEnable = ADC_INTEN_SEQB_INTEN_MASK, /*!< Enable interrupt upon completion of each individual conversion in sequence B, or entire sequence. */ kADC_OverrunInterruptEnable = ADC_INTEN_OVR_INTEN_MASK, /*!< Enable the detection of an overrun condition on any of - the channel data registers will cause an overrun - interrupt/DMA trigger. */ + the channel data registers will cause an overrun + interrupt/DMA trigger. */ }; +#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE /*! * @brief Define selection of clock mode. */ @@ -123,17 +103,44 @@ typedef enum _adc_clock_mode 0U, /*!< The ADC clock would be derived from the system clock based on "clockDividerNumber". */ kADC_ClockAsynchronousMode = 1U, /*!< The ADC clock would be based on the SYSCON block's divider. */ } adc_clock_mode_t; +#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ +#if defined(FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) && (FSL_FEATURE_ADC_DAT_OF_HIGH_ALIGNMENT) /*! * @brief Define selection of resolution. */ typedef enum _adc_resolution { - kADC_Resolution6bit = 0U, /*!< 6-bit resolution. */ - kADC_Resolution8bit = 1U, /*!< 8-bit resolution. */ + kADC_Resolution6bit = 3U, + /*!< 6-bit resolution. */ /* This is a HW issue that the ADC resolution enum configure not align with HW implement, + ES2 chip already fixed the issue, Currently, update ADC enum define as a workaround */ + kADC_Resolution8bit = 2U, /*!< 8-bit resolution. */ + kADC_Resolution10bit = 1U, /*!< 10-bit resolution. */ + kADC_Resolution12bit = 0U, /*!< 12-bit resolution. */ +} adc_resolution_t; +#elif defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL +/*! + * @brief Define selection of resolution. + */ +typedef enum _adc_resolution +{ + kADC_Resolution6bit = 0U, /*!< 6-bit resolution. */ + kADC_Resolution8bit = 1U, /*!< 8-bit resolution. */ kADC_Resolution10bit = 2U, /*!< 10-bit resolution. */ kADC_Resolution12bit = 3U, /*!< 12-bit resolution. */ } adc_resolution_t; +#endif + +#if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG +/*! + * @brief Definfe range of the analog supply voltage VDDA. + */ +typedef enum _adc_voltage_range +{ + kADC_HighVoltageRange = 0U, /* High voltage. VDD = 2.7 V to 3.6 V. */ + kADC_LowVoltageRange = 1U, /* Low voltage. VDD = 2.4 V to 2.7 V. */ +} adc_vdda_range_t; +#endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ /*! * @brief Define selection of polarity of selected input trigger for conversion sequence. @@ -149,8 +156,8 @@ typedef enum _adc_trigger_polarity */ typedef enum _adc_priority { - kADC_PriorityLow = 0U, /*!< This sequence would be preempted when another sequence is started. */ - kADC_PriorityHigh = 1U, /*!< This sequence would preempt other sequence even when is is started. */ + kADC_PriorityLow = 0U, /*!< This sequence would be preempted when another sequence is started. */ + kADC_PriorityHigh = 1U, /*!< This sequence would preempt other sequence even when it is started. */ } adc_priority_t; /*! @@ -169,7 +176,7 @@ typedef enum _adc_seq_interrupt_mode */ typedef enum _adc_threshold_compare_status { - kADC_ThresholdCompareInRange = 0U, /*!< LOW threshold <= conversion value <= HIGH threshold. */ + kADC_ThresholdCompareInRange = 0U, /*!< LOW threshold <= conversion value <= HIGH threshold. */ kADC_ThresholdCompareBelowRange = 1U, /*!< conversion value < LOW threshold. */ kADC_ThresholdCompareAboveRange = 2U, /*!< conversion value > HIGH threshold. */ } adc_threshold_compare_status_t; @@ -199,27 +206,84 @@ typedef enum _adc_threshold_crossing_status */ typedef enum _adc_threshold_interrupt_mode { - kADC_ThresholdInterruptDisabled = 0U, /*!< Threshold comparison interrupt is disabled. */ - kADC_ThresholdInterruptOnOutside = 1U, /*!< Threshold comparison interrupt is enabled on outside threshold. */ + kADC_ThresholdInterruptDisabled = 0U, /*!< Threshold comparison interrupt is disabled. */ + kADC_ThresholdInterruptOnOutside = 1U, /*!< Threshold comparison interrupt is enabled on outside threshold. */ kADC_ThresholdInterruptOnCrossing = 2U, /*!< Threshold comparison interrupt is enabled on crossing threshold. */ } adc_threshold_interrupt_mode_t; +/*! + * @brief Define the info result mode of different resolution. + */ +typedef enum _adc_inforesultshift +{ + kADC_Resolution12bitInfoResultShift = 0U, /*!< Info result shift of Resolution12bit. */ + kADC_Resolution10bitInfoResultShift = 2U, /*!< Info result shift of Resolution10bit. */ + kADC_Resolution8bitInfoResultShift = 4U, /*!< Info result shift of Resolution8bit. */ + kADC_Resolution6bitInfoResultShift = 6U, /*!< Info result shift of Resolution6bit. */ +} adc_inforesult_t; + +/*! + * @brief Define common modes for Temerature sensor. + */ +typedef enum _adc_tempsensor_common_mode +{ + kADC_HighNegativeOffsetAdded = 0x0U, /*!< Temerature sensor common mode: high negative offset added. */ + kADC_IntermediateNegativeOffsetAdded = + 0x4U, /*!< Temerature sensor common mode: intermediate negative offset added. */ + kADC_NoOffsetAdded = 0x8U, /*!< Temerature sensor common mode: no offset added. */ + kADC_LowPositiveOffsetAdded = 0xcU, /*!< Temerature sensor common mode: low positive offset added. */ +} adc_tempsensor_common_mode_t; + +/*! + * @brief Define source impedance modes for GPADC control. + */ +typedef enum _adc_second_control +{ + kADC_Impedance621Ohm = 0x1U << 9U, /*!< Extand ADC sampling time according to source impedance 1: 0.621 kOhm. */ + kADC_Impedance55kOhm = + 0x14U << 9U, /*!< Extand ADC sampling time according to source impedance 20 (default): 55 kOhm. */ + kADC_Impedance87kOhm = 0x1fU << 9U, /*!< Extand ADC sampling time according to source impedance 31: 87 kOhm. */ + + kADC_NormalFunctionalMode = 0x0U << 14U, /*!< TEST mode: Normal functional mode. */ + kADC_MultiplexeTestMode = 0x1U << 14U, /*!< TEST mode: Multiplexer test mode. */ + kADC_ADCInUnityGainMode = 0x2U << 14U, /*!< TEST mode: ADC in unity gain mode. */ +} adc_second_control_t; + /*! * @brief Define structure for configuring the block. */ typedef struct _adc_config { - adc_clock_mode_t clockMode; /*!< Select the clock mode for ADC converter. */ - uint32_t clockDividerNumber; /*!< This field is only available when using kADC_ClockSynchronousMode for "clockMode" - field. The divider would be plused by 1 based on the value in this field. The - available range is in 8 bits. */ - adc_resolution_t resolution; /*!< Select the conversion bits. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE) & FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE + adc_clock_mode_t clockMode; /*!< Select the clock mode for ADC converter. */ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_ASYNMODE. */ + uint32_t clockDividerNumber; /*!< This field is only available when using kADC_ClockSynchronousMode for "clockMode" + field. The divider would be plused by 1 based on the value in this field. The + available range is in 8 bits. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_RESOL) & FSL_FEATURE_ADC_HAS_CTRL_RESOL + adc_resolution_t resolution; /*!< Select the conversion bits. */ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_RESOL. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL) & FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL bool enableBypassCalibration; /*!< By default, a calibration cycle must be performed each time the chip is powered-up. Re-calibration may be warranted periodically - especially if operating conditions have changed. To enable this option would avoid the need to calibrate if offset error is not a concern in the application. */ - uint32_t sampleTimeNumber; /*!< By default, with value as "0U", the sample period would be 2.5 ADC clocks. Then, - to plus the "sampleTimeNumber" value here. The available value range is in 3 bits.*/ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_BYPASSCAL. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_TSAMP) & FSL_FEATURE_ADC_HAS_CTRL_TSAMP + uint32_t sampleTimeNumber; /*!< By default, with value as "0U", the sample period would be 2.5 ADC clocks. Then, + to plus the "sampleTimeNumber" value here. The available value range is in 3 bits.*/ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_TSAMP. */ +#if defined(FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE) & FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE + bool enableLowPowerMode; /*!< If disable low-power mode, ADC remains activated even when no conversions are + requested. + If enable low-power mode, The ADC is automatically powered-down when no conversions are + taking place. */ +#endif /* FSL_FEATURE_ADC_HAS_CTRL_LPWRMODE. */ +#if defined(FSL_FEATURE_ADC_HAS_TRIM_REG) & FSL_FEATURE_ADC_HAS_TRIM_REG + adc_vdda_range_t + voltageRange; /*!< Configure the ADC for the appropriate operating range of the analog supply voltage VDDA. + Failure to set the area correctly causes the ADC to return incorrect conversion results. */ +#endif /* FSL_FEATURE_ADC_HAS_TRIM_REG. */ } adc_config_t; /*! @@ -228,17 +292,17 @@ typedef struct _adc_config typedef struct _adc_conv_seq_config { uint32_t channelMask; /*!< Selects which one or more of the ADC channels will be sampled and converted when this - sequence is launched. The masked channels would be involved in current conversion - sequence, beginning with the lowest-order. The available range is in 12-bit. */ + sequence is launched. The masked channels would be involved in current conversion + sequence, beginning with the lowest-order. The available range is in 12-bit. */ uint32_t triggerMask; /*!< Selects which one or more of the available hardware trigger sources will cause this - conversion sequence to be initiated. The available range is 6-bit.*/ + conversion sequence to be initiated. The available range is 6-bit.*/ adc_trigger_polarity_t triggerPolarity; /*!< Select the trigger to lauch conversion sequence. */ bool enableSyncBypass; /*!< To enable this feature allows the hardware trigger input to bypass synchronization - flip-flop stages and therefore shorten the time between the trigger input signal and the - start of a conversion. */ + flip-flop stages and therefore shorten the time between the trigger input signal and the + start of a conversion. */ bool enableSingleStep; /*!< When enabling this feature, a trigger will launch a single conversion on the next - channel in the sequence instead of the default response of launching an entire sequence - of conversions. */ + channel in the sequence instead of the default response of launching an entire sequence + of conversions. */ adc_seq_interrupt_mode_t interruptMode; /*!< Select the interrpt/DMA trigger mode. */ } adc_conv_seq_config_t; @@ -247,7 +311,7 @@ typedef struct _adc_conv_seq_config */ typedef struct _adc_result_info { - uint32_t result; /*!< Keey the conversion data value. */ + uint32_t result; /*!< Keep the conversion data value. */ adc_threshold_compare_status_t thresholdCompareStatus; /*!< Keep the threshold compare status. */ adc_threshold_crossing_status_t thresholdCorssingStatus; /*!< Keep the threshold crossing status. */ uint32_t channelNumber; /*!< Keep the channel number for this conversion. */ @@ -298,6 +362,8 @@ void ADC_Deinit(ADC_Type *base); */ void ADC_GetDefaultConfig(adc_config_t *config); +#if !(defined(FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) && FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC) +#if defined(FSL_FEATURE_ADC_HAS_CALIB_REG) && FSL_FEATURE_ADC_HAS_CALIB_REG /*! * @brief Do the self hardware calibration. * @@ -306,7 +372,22 @@ void ADC_GetDefaultConfig(adc_config_t *config); * @retval false Calibration failed. */ bool ADC_DoSelfCalibration(ADC_Type *base); +#else +/*! + * @brief Do the self calibration. To calibrate the ADC, set the ADC clock to 500 kHz. + * In order to achieve the specified ADC accuracy, the A/D converter must be recalibrated, at a minimum, + * following every chip reset before initiating normal ADC operation. + * + * @param base ADC peripheral base address. + * @param frequency The ststem clock frequency to ADC. + * @retval true Calibration succeed. + * @retval false Calibration failed. + */ +bool ADC_DoSelfCalibration(ADC_Type *base, uint32_t frequency); +#endif /* FSL_FEATURE_ADC_HAS_CALIB_REG */ +#endif /* FSL_FEATURE_ADC_HAS_NO_CALIB_FUNC */ +#if !(defined(FSL_FEATURE_ADC_HAS_NO_INSEL) && FSL_FEATURE_ADC_HAS_NO_INSEL) /*! * @brief Enable the internal temperature sensor measurement. * @@ -316,6 +397,9 @@ bool ADC_DoSelfCalibration(ADC_Type *base); * @param base ADC peripheral base address. * @param enable Switcher to enable the feature or not. */ +#if defined(FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) && (FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP) +void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable); +#else static inline void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable) { if (enable) @@ -327,8 +411,9 @@ static inline void ADC_EnableTemperatureSensor(ADC_Type *base, bool enable) base->INSEL = (base->INSEL & ~ADC_INSEL_SEL_MASK) | ADC_INSEL_SEL(0); } } - -/* @} */ +#endif /* FSL_FEATURE_ADC_ASYNC_SYSCON_TEMP. */ +#endif /* FSL_FEATURE_ADC_HAS_NO_INSEL. */ + /* @} */ /*! * @name Control conversion sequence A. @@ -542,7 +627,7 @@ bool ADC_GetChannelConversionResult(ADC_Type *base, uint32_t channel, adc_result */ static inline void ADC_SetThresholdPair0(ADC_Type *base, uint32_t lowValue, uint32_t highValue) { - base->THR0_LOW = ADC_THR0_LOW_THRLOW(lowValue); + base->THR0_LOW = ADC_THR0_LOW_THRLOW(lowValue); base->THR0_HIGH = ADC_THR0_HIGH_THRHIGH(highValue); } @@ -555,7 +640,7 @@ static inline void ADC_SetThresholdPair0(ADC_Type *base, uint32_t lowValue, uint */ static inline void ADC_SetThresholdPair1(ADC_Type *base, uint32_t lowValue, uint32_t highValue) { - base->THR1_LOW = ADC_THR1_LOW_THRLOW(lowValue); + base->THR1_LOW = ADC_THR1_LOW_THRLOW(lowValue); base->THR1_HIGH = ADC_THR1_HIGH_THRHIGH(highValue); } @@ -611,13 +696,24 @@ static inline void ADC_DisableInterrupts(ADC_Type *base, uint32_t mask) } /*! - * @brief Enable the interrupt of shreshold compare event for each channel. + * @brief Enable the interrupt of threshold compare event for each channel. + * @deprecated Do not use this function. It has been superceded by @ADC_EnableThresholdCompareInterrupt + */ +static inline void ADC_EnableShresholdCompareInterrupt(ADC_Type *base, + uint32_t channel, + adc_threshold_interrupt_mode_t mode) +{ + base->INTEN = (base->INTEN & ~(0x3U << ((channel << 1U) + 3U))) | ((uint32_t)(mode) << ((channel << 1U) + 3U)); +} + +/*! + * @brief Enable the interrupt of threshold compare event for each channel. * * @param base ADC peripheral base address. * @param channel Channel number. * @param mode Interrupt mode for threshold compare event, see to #adc_threshold_interrupt_mode_t. */ -static inline void ADC_EnableShresholdCompareInterrupt(ADC_Type *base, +static inline void ADC_EnableThresholdCompareInterrupt(ADC_Type *base, uint32_t channel, adc_threshold_interrupt_mode_t mode) { diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.c index 84398ccbab..d00bc2a1f9 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.c @@ -1,39 +1,21 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019 , NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ -#include "fsl_common.h" #include "fsl_clock.h" #include "fsl_power.h" /******************************************************************************* * Definitions ******************************************************************************/ +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.clock" +#endif #define NVALMAX (0x100U) #define PVALMAX (0x20U) #define MVALMAX (0x8000U) @@ -51,7 +33,7 @@ #define PLL_NDEC_VAL_P (0U) /* NDEC is in bits 9:0 */ #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P) #define PLL_PDEC_VAL_P (0U) /* PDEC is in bits 6:0 */ -#define PLL_PDEC_VAL_M (0x3FFUL << PLL_PDEC_VAL_P) +#define PLL_PDEC_VAL_M (0x7FUL << PLL_PDEC_VAL_P) #define PLL_MIN_CCO_FREQ_MHZ (75000000U) #define PLL_MAX_CCO_FREQ_MHZ (150000000U) @@ -85,12 +67,13 @@ computation on each call to retrive the PLL rate. */ static uint32_t s_Pll_Freq; -uint32_t g_I2S_Mclk_Freq = 0U; +/* I2S mclk. */ +static uint32_t s_I2S_Mclk_Freq = 0U; /** External clock rate on the CLKIN pin in Hz. If not used, set this to 0. Otherwise, set it to the exact rate in Hz this pin is being driven at. */ -const uint32_t g_Ext_Clk_Freq = 0U; +static const uint32_t s_Ext_Clk_Freq = 0U; /******************************************************************************* * Variables @@ -133,39 +116,106 @@ static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30 * Code ******************************************************************************/ +/** + * brief Configure the clock selection muxes. + * param connection : Clock to be configured. + * return Nothing + */ void CLOCK_AttachClk(clock_attach_id_t connection) { - bool final_descriptor = false; uint8_t mux; - uint8_t pos; + uint8_t sel; + uint16_t item; + uint32_t tmp32 = (uint32_t)connection; uint32_t i; volatile uint32_t *pClkSel; pClkSel = &(SYSCON->MAINCLKSELA); - for (i = 0U; (i <= 2U) && (!final_descriptor); i++) + if (kNONE_to_NONE != connection) { - connection = (clock_attach_id_t)(connection >> (i * 12U)); /* pick up next descriptor */ - mux = (uint8_t)connection; - if (connection) + for (i = 0U; i < 2U; i++) { - pos = ((connection & 0xf00U) >> 8U) - 1U; - if (mux == CM_ASYNCAPB) + if (tmp32 == 0U) { - ASYNC_SYSCON->ASYNCAPBCLKSELA = pos; + break; } - else + item = (uint16_t)GET_ID_ITEM(tmp32); + if (item) { - pClkSel[mux] = pos; + mux = GET_ID_ITEM_MUX(item); + sel = GET_ID_ITEM_SEL(item); + if (mux == CM_ASYNCAPB) + { + ASYNC_SYSCON->ASYNCAPBCLKSELA = sel; + } + else + { + pClkSel[mux] = sel; + } } - } - else - { - final_descriptor = true; + tmp32 = GET_ID_NEXT_ITEM(tmp32); /* pick up next descriptor */ } } } +/* Return the actual clock attach id */ +/** + * 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 attachId : Clock attach id to get. + * return Clock source value. + */ +clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId) +{ + uint8_t mux; + uint8_t actualSel; + uint32_t tmp32 = (uint32_t)attachId; + uint32_t i; + uint32_t actualAttachId = 0U; + uint32_t selector = GET_ID_SELECTOR(tmp32); + volatile uint32_t *pClkSel; + + pClkSel = &(SYSCON->MAINCLKSELA); + + if (kNONE_to_NONE == attachId) + { + return kNONE_to_NONE; + } + + for (i = 0U; i < 2U; i++) + { + mux = GET_ID_ITEM_MUX(tmp32); + if (tmp32) + { + if (mux == CM_ASYNCAPB) + { + actualSel = ASYNC_SYSCON->ASYNCAPBCLKSELA; + } + else + { + actualSel = pClkSel[mux]; + } + + /* Consider the combination of two registers */ + actualAttachId |= CLK_ATTACH_ID(mux, actualSel, i); + } + tmp32 = GET_ID_NEXT_ITEM(tmp32); /*!< pick up next descriptor */ + } + + actualAttachId |= selector; + + return (clock_attach_id_t)actualAttachId; +} + +/** + * brief Setup peripheral clock dividers. + * param div_name : Clock divider name + * param divided_by_value: Value to be divided + * param reset : Whether to reset the divider counter. + * return Nothing + */ void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset) { volatile uint32_t *pClkDiv; @@ -186,6 +236,13 @@ void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool } /* Set FRO Clocking */ +/** + * brief Initialize the Core clock to given frequency (12, 48 or 96 MHz). + * Turns on FRO and uses default CCO, if freq is 12000000, then high speed output is off, else high speed output is + * enabled. + * param iFreq : Desired frequency (must be one of CLK_FRO_12MHZ or CLK_FRO_48MHZ or CLK_FRO_96MHZ) + * return returns success or fail status. + */ status_t CLOCK_SetupFROClocking(uint32_t iFreq) { uint32_t usb_adj; @@ -220,19 +277,28 @@ status_t CLOCK_SetupFROClocking(uint32_t iFreq) return 0U; } +/*! brief Return Frequency of FRO 12MHz + * return Frequency of FRO 12MHz + */ uint32_t CLOCK_GetFro12MFreq(void) { return (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) ? 0U : 12000000U; } +/*! brief Return Frequency of External Clock + * return Frequency of External Clock. If no external clock is used returns 0. + */ uint32_t CLOCK_GetExtClkFreq(void) { - return (g_Ext_Clk_Freq); + return (s_Ext_Clk_Freq); } +/*! brief Return Frequency of Watchdog Oscillator + * return Frequency of Watchdog Oscillator + */ uint32_t CLOCK_GetWdtOscFreq(void) { uint8_t freq_sel, div_sel; - if (SYSCON->PDRUNCFG[kPDRUNCFG_PD_WDT_OSC >> 8UL] & (1UL << (kPDRUNCFG_PD_WDT_OSC & 0xffU)) ) + if (SYSCON->PDRUNCFG[kPDRUNCFG_PD_WDT_OSC >> 8UL] & (1UL << (kPDRUNCFG_PD_WDT_OSC & 0xffU))) { return 0U; } @@ -245,41 +311,97 @@ uint32_t CLOCK_GetWdtOscFreq(void) } } +/* Get HF FRO Clk */ +/*! brief Return Frequency of High-Freq output of FRO + * return Frequency of High-Freq output of FRO + */ uint32_t CLOCK_GetFroHfFreq(void) { - return (SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) ? 0 : !(SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK) ? - 0 : - (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) ? 96000000U : - 48000000U; + if ((SYSCON->PDRUNCFG[0] & SYSCON_PDRUNCFG_PDEN_FRO_MASK) || !(SYSCON->FROCTRL & SYSCON_FROCTRL_HSPDCLK_MASK)) + { + return 0U; + } + + if (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK) + { + return 96000000U; + } + else + { + return 48000000U; + } } +/*! brief Return Frequency of PLL + * return Frequency of PLL + */ uint32_t CLOCK_GetPllOutFreq(void) { return s_Pll_Freq; } +/*! brief Return Frequency of 32kHz osc + * return Frequency of 32kHz osc + */ uint32_t CLOCK_GetOsc32KFreq(void) { return CLK_RTC_32K_CLK; /* Needs to be corrected to check that RTC Clock is enabled */ } +/*! brief Return Frequency of Core System + * return Frequency of Core System + */ uint32_t CLOCK_GetCoreSysClkFreq(void) { - return ((SYSCON->MAINCLKSELB == 0U) && (SYSCON->MAINCLKSELA == 0U)) ? - CLOCK_GetFro12MFreq() : - ((SYSCON->MAINCLKSELB == 0U) && (SYSCON->MAINCLKSELA == 1U)) ? - CLOCK_GetExtClkFreq() : - ((SYSCON->MAINCLKSELB == 0U) && (SYSCON->MAINCLKSELA == 2U)) ? - CLOCK_GetWdtOscFreq() : - ((SYSCON->MAINCLKSELB == 0U) && (SYSCON->MAINCLKSELA == 3U)) ? - CLOCK_GetFroHfFreq() : - (SYSCON->MAINCLKSELB == 2U) ? CLOCK_GetPllOutFreq() : - (SYSCON->MAINCLKSELB == 3U) ? CLOCK_GetOsc32KFreq() : 0U; + uint32_t freq = 0U; + + switch (SYSCON->MAINCLKSELB) + { + case 0U: + if (SYSCON->MAINCLKSELA == 0U) + { + freq = CLOCK_GetFro12MFreq(); + } + else if (SYSCON->MAINCLKSELA == 1U) + { + freq = CLOCK_GetExtClkFreq(); + } + else if (SYSCON->MAINCLKSELA == 2U) + { + freq = CLOCK_GetWdtOscFreq(); + } + else if (SYSCON->MAINCLKSELA == 3U) + { + freq = CLOCK_GetFroHfFreq(); + } + else + { + } + break; + case 2U: + freq = CLOCK_GetPllOutFreq(); + break; + + case 3U: + freq = CLOCK_GetOsc32KFreq(); + break; + + default: + break; + } + + return freq; } +/*! brief Return Frequency of I2S MCLK Clock + * return Frequency of I2S MCLK Clock + */ uint32_t CLOCK_GetI2SMClkFreq(void) { - return g_I2S_Mclk_Freq; + return s_I2S_Mclk_Freq; } +/*! brief Return Frequency of Asynchronous APB Clock + * return Frequency of Asynchronous APB Clock Clock + */ uint32_t CLOCK_GetAsyncApbClkFreq(void) { async_clock_src_t clkSrc; @@ -303,26 +425,138 @@ uint32_t CLOCK_GetAsyncApbClkFreq(void) return clkRate; } +/* Get FLEXCOMM Clk */ +/*! brief Return Frequency of Flexcomm functional Clock + * return Frequency of Flexcomm functional Clock + */ uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id) { - return (SYSCON->FXCOMCLKSEL[id] == 0U) ? CLOCK_GetFro12MFreq() : (SYSCON->FXCOMCLKSEL[id] == 1U) ? - CLOCK_GetFroHfFreq() : - (SYSCON->FXCOMCLKSEL[id] == 2U) ? - CLOCK_GetPllOutFreq() : - (SYSCON->FXCOMCLKSEL[id] == 3U) ? - CLOCK_GetI2SMClkFreq() : - (SYSCON->FXCOMCLKSEL[id] == 4U) ? CLOCK_GetFreq(kCLOCK_Frg) : 0U; + uint32_t freq = 0U; + + switch (SYSCON->FXCOMCLKSEL[id]) + { + case 0U: + freq = CLOCK_GetFro12MFreq(); + break; + case 1U: + freq = CLOCK_GetFroHfFreq(); + break; + case 2U: + freq = CLOCK_GetPllOutFreq(); + break; + case 3U: + freq = CLOCK_GetI2SMClkFreq(); + break; + case 4U: + freq = CLOCK_GetFrgClkFreq(); + break; + + default: + break; + } + + return freq; } +/* Get ADC Clk */ +/*! brief Return Frequency of Adc Clock + * return Frequency of Adc Clock. + */ +uint32_t CLOCK_GetAdcClkFreq(void) +{ + uint32_t freq = 0U; + + switch (SYSCON->ADCCLKSEL) + { + case 0U: + freq = CLOCK_GetCoreSysClkFreq(); + break; + case 1U: + freq = CLOCK_GetPllOutFreq(); + break; + case 2U: + freq = CLOCK_GetFroHfFreq(); + break; + case 7U: + freq = 0U; + break; + default: + break; + } + + return freq / ((SYSCON->ADCCLKDIV & 0xffU) + 1U); +} + +/* Get FRG Clk */ +/*! brief Return Input frequency for the Fractional baud rate generator + * return Input Frequency for FRG + */ uint32_t CLOCK_GetFRGInputClock(void) { - return (SYSCON->FRGCLKSEL == 0U) ? CLOCK_GetCoreSysClkFreq() : (SYSCON->FRGCLKSEL == 1U) ? - CLOCK_GetPllOutFreq() : - (SYSCON->FRGCLKSEL == 2U) ? CLOCK_GetFro12MFreq() : (SYSCON->FRGCLKSEL == 3U) ? - CLOCK_GetFroHfFreq() : - 0U; + uint32_t freq = 0U; + + switch (SYSCON->FRGCLKSEL) + { + case 0U: + freq = CLOCK_GetCoreSysClkFreq(); + break; + case 1U: + freq = CLOCK_GetPllOutFreq(); + break; + case 2U: + freq = CLOCK_GetFro12MFreq(); + break; + case 3U: + freq = CLOCK_GetFroHfFreq(); + break; + + default: + break; + } + + return freq; } +/* Get DMIC Clk */ +/*! brief Return Input frequency for the DMIC + * return Input Frequency for DMIC + */ +uint32_t CLOCK_GetDmicClkFreq(void) +{ + uint32_t freq = 0U; + + switch (SYSCON->DMICCLKSEL) + { + case 0U: + freq = CLOCK_GetFro12MFreq(); + break; + case 1U: + freq = CLOCK_GetFroHfFreq(); + break; + case 2U: + freq = CLOCK_GetPllOutFreq(); + break; + case 3U: + freq = CLOCK_GetI2SMClkFreq(); + break; + case 4U: + freq = CLOCK_GetCoreSysClkFreq(); + break; + case 5U: + freq = CLOCK_GetWdtOscFreq(); + break; + default: + break; + } + + return freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U); + ; +} + +/*! brief Set output of the Fractional baud rate generator + * param freq : Desired output frequency + * return Error Code 0 - fail 1 - success + */ uint32_t CLOCK_SetFRGClock(uint32_t freq) { uint32_t input = CLOCK_GetFRGInputClock(); @@ -335,12 +569,59 @@ uint32_t CLOCK_SetFRGClock(uint32_t freq) } else { - mul = ((uint64_t)(input - freq) * 256) / ((uint64_t)freq); + mul = ((uint64_t)(input - freq) * 256) / ((uint64_t)freq); SYSCON->FRGCTRL = (mul << SYSCON_FRGCTRL_MULT_SHIFT) | SYSCON_FRGCTRL_DIV_MASK; return 1; } } +/* Get FRG Clk */ +/*! brief Return Input frequency for the FRG + * return Input Frequency for FRG + */ +uint32_t CLOCK_GetFrgClkFreq(void) +{ + uint32_t freq = 0U; + + if ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK) + { + freq = ((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1)) / + ((SYSCON_FRGCTRL_DIV_MASK + 1) + + ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)); + } + else + { + freq = 0U; + } + + return freq; +} + +/*! brief Return Frequency of USB + * return Frequency of USB + */ +uint32_t CLOCK_GetUsbClkFreq(void) +{ + uint32_t freq = 0U; + + if (SYSCON->USBCLKSEL == 0U) + { + freq = CLOCK_GetFroHfFreq(); + } + else if (SYSCON->USBCLKSEL == 1) + { + freq = CLOCK_GetPllOutFreq(); + } + else + { + } + + return freq / ((SYSCON->USBCLKDIV & 0xffU) + 1U); +} + +/*! brief Return Frequency of selected clock + * return Frequency of selected clock + */ uint32_t CLOCK_GetFreq(clock_name_t clockName) { uint32_t freq; @@ -362,31 +643,16 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) freq = CLOCK_GetPllOutFreq(); break; case kCLOCK_UsbClk: - freq = (SYSCON->USBCLKSEL == 0U) ? CLOCK_GetFroHfFreq() : (SYSCON->USBCLKSEL == 1) ? CLOCK_GetPllOutFreq() : - 0U; - freq = freq / ((SYSCON->USBCLKDIV & 0xffU) + 1U); + freq = CLOCK_GetUsbClkFreq(); break; - case kClock_WdtOsc: + case kCLOCK_WdtOsc: freq = CLOCK_GetWdtOscFreq(); break; case kCLOCK_Frg: - freq = ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_DIV_MASK) == SYSCON_FRGCTRL_DIV_MASK) ? - ((uint64_t)CLOCK_GetFRGInputClock() * (SYSCON_FRGCTRL_DIV_MASK + 1)) / - ((SYSCON_FRGCTRL_DIV_MASK + 1) + - ((SYSCON->FRGCTRL & SYSCON_FRGCTRL_MULT_MASK) >> SYSCON_FRGCTRL_MULT_SHIFT)) : - 0; + freq = CLOCK_GetFrgClkFreq(); break; case kCLOCK_Dmic: - freq = (SYSCON->DMICCLKSEL == 0U) ? CLOCK_GetFro12MFreq() : (SYSCON->DMICCLKSEL == 1U) ? - CLOCK_GetFroHfFreq() : - (SYSCON->DMICCLKSEL == 2U) ? - CLOCK_GetPllOutFreq() : - (SYSCON->DMICCLKSEL == 3U) ? - CLOCK_GetI2SMClkFreq() : - (SYSCON->DMICCLKSEL == 4U) ? - CLOCK_GetCoreSysClkFreq() : - (SYSCON->DMICCLKSEL == 5U) ? CLOCK_GetWdtOscFreq() : 0U; - freq = freq / ((SYSCON->DMICCLKDIV & 0xffU) + 1U); + freq = CLOCK_GetDmicClkFreq(); break; case kCLOCK_AsyncApbClk: @@ -430,28 +696,37 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName) } /* Set the FLASH wait states for the passed frequency */ +/** + * brief Set the flash wait states for the input freuqency. + * param iFreq : Input frequency + * return Nothing + */ void CLOCK_SetFLASHAccessCyclesForFreq(uint32_t iFreq) { if (iFreq <= 12000000U) { CLOCK_SetFLASHAccessCycles(kCLOCK_Flash1Cycle); } - else if (iFreq <= 30000000U) + else if (iFreq <= 24000000U) { CLOCK_SetFLASHAccessCycles(kCLOCK_Flash2Cycle); } - else if (iFreq <= 60000000U) + else if (iFreq <= 48000000U) { CLOCK_SetFLASHAccessCycles(kCLOCK_Flash3Cycle); } - else if (iFreq <= 85000000U) + else if (iFreq <= 72000000U) { CLOCK_SetFLASHAccessCycles(kCLOCK_Flash4Cycle); } - else + else if (iFreq <= 84000000U) { CLOCK_SetFLASHAccessCycles(kCLOCK_Flash5Cycle); } + else + { + CLOCK_SetFLASHAccessCycles(kCLOCK_Flash6Cycle); + } } /* Find encoded NDEC value for raw N value, max N = NVALMAX */ @@ -463,7 +738,7 @@ static uint32_t pllEncodeN(uint32_t N) switch (N) { case 0U: - x = 0xFFFU; + x = 0x3FFU; break; case 1U: @@ -494,7 +769,7 @@ static uint32_t pllDecodeN(uint32_t NDEC) /* Find NDec */ switch (NDEC) { - case 0xFFFU: + case 0x3FFU: n = 0U; break; @@ -533,7 +808,7 @@ static uint32_t pllEncodeP(uint32_t P) switch (P) { case 0U: - x = 0xFFU; + x = 0x7FU; break; case 1U: @@ -564,7 +839,7 @@ static uint32_t pllDecodeP(uint32_t PDEC) /* Find PDec */ switch (PDEC) { - case 0xFFU: + case 0x7FU: p = 0U; break; @@ -603,7 +878,7 @@ static uint32_t pllEncodeM(uint32_t M) switch (M) { case 0U: - x = 0xFFFFFU; + x = 0x1FFFFU; break; case 1U: @@ -634,7 +909,7 @@ static uint32_t pllDecodeM(uint32_t MDEC) /* Find MDec */ switch (MDEC) { - case 0xFFFFFU: + case 0x1FFFFU: m = 0U; break; @@ -737,7 +1012,7 @@ static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg) uint32_t postDiv = 1U; /* Direct input is not used? */ - if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_SHIFT) == 0U) + if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0U) { /* Decode PDEC value to get (P) post divider */ postDiv = 2U * pllDecodeP(pDecReg & 0x7FU); @@ -760,7 +1035,7 @@ static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg) mMult = pllDecodeM(mDecReg & 0x1FFFFU); /* Extra multiply by 2 needed? */ - if ((ctrlReg & (1UL << SYSCON_SYSPLLCTRL_BYPASSCCODIV2_SHIFT)) == 0U) + if ((ctrlReg & (SYSCON_SYSPLLCTRL_BYPASSCCODIV2_MASK)) == 0U) { mMult = mMult << 1U; } @@ -780,15 +1055,20 @@ static uint32_t FindGreatestCommonDivisor(uint32_t m, uint32_t n) while (n != 0U) { tmp = n; - n = m % n; - m = tmp; + n = m % n; + m = tmp; } return m; } -/* Set PLL output based on desired output rate */ -static pll_error_t CLOCK_GetPllConfig( +/* + * Set PLL output based on desired output rate. + * In this function, the it calculates the PLL setting for output frequency from input clock + * frequency. The calculation would cost a few time. So it is not recommaned to use it frequently. + * the "pllctrl", "pllndec", "pllpdec", "pllmdec" would updated in this function. + */ +static pll_error_t CLOCK_GetPllConfigInternal( uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS) { uint32_t nDivOutHz, fccoHz, multFccoDiv; @@ -797,8 +1077,8 @@ static pll_error_t CLOCK_GetPllConfig( uint32_t pllSelP, pllSelI, pllSelR, bandsel, uplimoff; /* Baseline parameters (no input or output dividers) */ - pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */ - pllPostDivider = 0U; /* 0 implies post-divider will be disabled */ + pllPreDivider = 1U; /* 1 implies pre-divider will be disabled */ + pllPostDivider = 0U; /* 0 implies post-divider will be disabled */ pllDirectOutput = 1U; if (useFeedbackDiv2) { @@ -865,7 +1145,7 @@ static pll_error_t CLOCK_GetPllConfig( } /* Target CCO goes up, PLL output goes down */ - fccoHz = foutHz * (pllPostDivider * 2U); + fccoHz = foutHz * (pllPostDivider * 2U); pllDirectOutput = 0U; } @@ -895,7 +1175,7 @@ static pll_error_t CLOCK_GetPllConfig( } /* Determine PLL multipler */ - nDivOutHz = (finHz / pllPreDivider); + nDivOutHz = (finHz / pllPreDivider); pllMultiplier = (fccoHz / nDivOutHz) / multFccoDiv; /* Find optimal values for filter */ @@ -909,7 +1189,7 @@ static pll_error_t CLOCK_GetPllConfig( /* Setup filtering */ pllFindSel(pllMultiplier, pllBypassFBDIV2, &pllSelP, &pllSelI, &pllSelR); - bandsel = 1U; + bandsel = 1U; uplimoff = 0U; /* Get encoded value for M (mult) and use manual filter, disable SS mode */ @@ -925,8 +1205,8 @@ static pll_error_t CLOCK_GetPllConfig( /* Filtering will be handled by SSC */ pllSelR = pllSelI = pllSelP = 0U; - bandsel = 0U; - uplimoff = 1U; + bandsel = 0U; + uplimoff = 1U; /* The PLL multiplier will get very close and slightly under the desired target frequency. A small fractional component can be @@ -958,6 +1238,69 @@ static pll_error_t CLOCK_GetPllConfig( return kStatus_PLL_Success; } +#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) +/* Alloct the static buffer for cache. */ +static pll_setup_t s_PllSetupCacheStruct[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT]; +static uint32_t s_FinHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0}; +static uint32_t s_FoutHzCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {0}; +static bool s_UseFeedbackDiv2Cache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false}; +static bool s_UseSSCache[CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT] = {false}; +static uint32_t s_PllSetupCacheIdx = 0U; +#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ + +/* + * Calculate the PLL setting values from input clock freq to output freq. + */ +static pll_error_t CLOCK_GetPllConfig( + uint32_t finHz, uint32_t foutHz, pll_setup_t *pSetup, bool useFeedbackDiv2, bool useSS) +{ + pll_error_t retErr; +#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) + uint32_t i; + + for (i = 0U; i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; i++) + { + if ((finHz == s_FinHzCache[i]) && (foutHz == s_FoutHzCache[i]) && + (useFeedbackDiv2 == s_UseFeedbackDiv2Cache[i]) && (useSS == s_UseSSCache[i])) + { + /* Hit the target in cache buffer. */ + pSetup->syspllctrl = s_PllSetupCacheStruct[i].syspllctrl; + pSetup->syspllndec = s_PllSetupCacheStruct[i].syspllndec; + pSetup->syspllpdec = s_PllSetupCacheStruct[i].syspllpdec; + pSetup->syspllssctrl[0] = s_PllSetupCacheStruct[i].syspllssctrl[0]; + pSetup->syspllssctrl[1] = s_PllSetupCacheStruct[i].syspllssctrl[1]; + retErr = kStatus_PLL_Success; + break; + } + } + + if (i < CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) + { + return retErr; + } +#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ + + retErr = CLOCK_GetPllConfigInternal(finHz, foutHz, pSetup, useFeedbackDiv2, useSS); + +#if (defined(CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) && CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT) + /* Cache the most recent calulation result into buffer. */ + s_FinHzCache[s_PllSetupCacheIdx] = finHz; + s_FoutHzCache[s_PllSetupCacheIdx] = foutHz; + s_UseFeedbackDiv2Cache[s_PllSetupCacheIdx] = useFeedbackDiv2; + s_UseSSCache[s_PllSetupCacheIdx] = useSS; + + s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllctrl = pSetup->syspllctrl; + s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllndec = pSetup->syspllndec; + s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllpdec = pSetup->syspllpdec; + s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[0] = pSetup->syspllssctrl[0]; + s_PllSetupCacheStruct[s_PllSetupCacheIdx].syspllssctrl[1] = pSetup->syspllssctrl[1]; + /* Update the index for next available buffer. */ + s_PllSetupCacheIdx = (s_PllSetupCacheIdx + 1U) % CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT; +#endif /* CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT */ + + return retErr; +} + /* Update local PLL rate variable */ static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup) { @@ -965,6 +1308,9 @@ static void CLOCK_GetSystemPLLOutFromSetupUpdate(pll_setup_t *pSetup) } /* Return System PLL input clock rate */ +/*! brief Return System PLL input clock rate + * return System PLL input clock rate + */ uint32_t CLOCK_GetSystemPLLInClockRate(void) { uint32_t clkRate = 0U; @@ -996,26 +1342,47 @@ uint32_t CLOCK_GetSystemPLLInClockRate(void) } /* Return System PLL output clock rate from setup structure */ +/*! brief Return System PLL output clock rate from setup structure + * param pSetup : Pointer to a PLL setup structure + * return System PLL output clock rate calculated from the setup structure + */ uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup) { uint32_t prediv, postdiv, mMult, inPllRate; uint64_t workRate; + /* Get the input clock frequency of PLL. */ inPllRate = CLOCK_GetSystemPLLInClockRate(); - if ((pSetup->syspllctrl & (1UL << SYSCON_SYSPLLCTRL_BYPASS_SHIFT)) == 0U) - { - /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */ - prediv = findPllPreDiv(pSetup->syspllctrl, pSetup->syspllndec); - postdiv = findPllPostDiv(pSetup->syspllctrl, pSetup->syspllpdec); + /* + * If the PLL is bypassed, PLL would not be used and the output of PLL module would just be the input clock. + */ + if ((pSetup->syspllctrl & (SYSCON_SYSPLLCTRL_BYPASS_MASK)) == 0U) + { + /* PLL is not in bypass mode, get pre-divider, and M divider, post-divider. */ + /* + * 1. Pre-divider + * Pre-divider is only available when the DIRECTI is disabled. + */ + if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTI_MASK)) + { + prediv = findPllPreDiv(pSetup->syspllctrl, pSetup->syspllndec); + } + else + { + prediv = 1U; /* The pre-divider is bypassed. */ + } /* Adjust input clock */ inPllRate = inPllRate / prediv; - /* If using the SS, use the multiplier */ - if (pSetup->syspllssctrl[1] & (1U << SYSCON_SYSPLLSSCTRL1_PD_SHIFT)) + /* + * 2. M divider + * If using the SS, use the multiplier. + */ + if (pSetup->syspllssctrl[1] & (SYSCON_SYSPLLSSCTRL1_PD_MASK)) { /* MDEC used for rate */ - mMult = findPllMMult(pSetup->syspllctrl, pSetup->syspllssctrl[0]); + mMult = findPllMMult(pSetup->syspllctrl, pSetup->syspllssctrl[0]); workRate = (uint64_t)inPllRate * (uint64_t)mMult; } else @@ -1023,14 +1390,26 @@ uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup) uint64_t fract; /* SS multipler used for rate */ - mMult = (pSetup->syspllssctrl[1] & PLL_SSCG1_MD_INT_M) >> PLL_SSCG1_MD_INT_P; + mMult = (pSetup->syspllssctrl[1] & PLL_SSCG1_MD_INT_M) >> PLL_SSCG1_MD_INT_P; workRate = (uint64_t)inPllRate * (uint64_t)mMult; /* Adjust by fractional */ - fract = (uint64_t)(pSetup->syspllssctrl[1] & PLL_SSCG1_MD_FRACT_M) >> PLL_SSCG1_MD_FRACT_P; + fract = (uint64_t)(pSetup->syspllssctrl[1] & PLL_SSCG1_MD_FRACT_M) >> PLL_SSCG1_MD_FRACT_P; workRate = workRate + ((inPllRate * fract) / 0x800U); } + /* + * 3. Post-divider + * Post-divider is only available when the DIRECTO is disabled. + */ + if (0U == (pSetup->syspllctrl & SYSCON_SYSPLLCTRL_DIRECTO_MASK)) + { + postdiv = findPllPostDiv(pSetup->syspllctrl, pSetup->syspllpdec); + } + else + { + postdiv = 1U; /* The post-divider is bypassed. */ + } workRate = workRate / ((uint64_t)postdiv); } else @@ -1043,12 +1422,23 @@ uint32_t CLOCK_GetSystemPLLOutFromSetup(pll_setup_t *pSetup) } /* Set the current PLL Rate */ +/*! brief Store the current PLL rate + * param rate: Current rate of the PLL + * return Nothing + **/ void CLOCK_SetStoredPLLClockRate(uint32_t rate) { s_Pll_Freq = rate; } /* Return System PLL output clock rate */ +/*! brief Return System PLL output clock rate + * param recompute : Forces a PLL rate recomputation if true + * return System PLL output clock rate + * note The PLL rate is cached in the driver in a variable as + * the rate computation function can take some time to perform. It + * is recommended to use 'false' with the 'recompute' parameter. + */ uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute) { pll_setup_t Setup; @@ -1056,9 +1446,9 @@ uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute) if ((recompute) || (s_Pll_Freq == 0U)) { - Setup.syspllctrl = SYSCON->SYSPLLCTRL; - Setup.syspllndec = SYSCON->SYSPLLNDEC; - Setup.syspllpdec = SYSCON->SYSPLLPDEC; + Setup.syspllctrl = SYSCON->SYSPLLCTRL; + Setup.syspllndec = SYSCON->SYSPLLNDEC; + Setup.syspllpdec = SYSCON->SYSPLLPDEC; Setup.syspllssctrl[0] = SYSCON->SYSPLLSSCTRL0; Setup.syspllssctrl[1] = SYSCON->SYSPLLSSCTRL1; @@ -1071,10 +1461,19 @@ uint32_t CLOCK_GetSystemPLLOutClockRate(bool recompute) } /* Set PLL output based on the passed PLL setup data */ +/*! brief Set PLL output based on the passed PLL setup data + * param pControl : Pointer to populated PLL control structure to generate setup with + * param pSetup : Pointer to PLL setup structure to be filled + * return PLL_ERROR_SUCCESS on success, or PLL setup error code + * note Actual frequency for setup may vary from the desired frequency based on the + * accuracy of input clocks, rounding, non-fractional PLL mode, etc. + */ pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup) { uint32_t inRate; bool useSS = (bool)((pControl->flags & PLL_CONFIGFLAG_FORCENOFRACT) == 0U); + bool useFbDiv2; + pll_error_t pllError; /* Determine input rate for the PLL */ @@ -1087,8 +1486,17 @@ pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup) inRate = CLOCK_GetSystemPLLInClockRate(); } + if ((pSetup->flags & PLL_SETUPFLAG_USEFEEDBACKDIV2) != 0U) + { + useFbDiv2 = true; + } + else + { + useFbDiv2 = false; + } + /* PLL flag options */ - pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, false, useSS); + pllError = CLOCK_GetPllConfig(inRate, pControl->desiredRate, pSetup, useFbDiv2, useSS); if ((useSS) && (pllError == kStatus_PLL_Success)) { /* If using SS mode, then some tweaks are made to the generated setup */ @@ -1103,6 +1511,16 @@ pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup) } /* Set PLL output from PLL setup structure */ +/*! brief Set PLL output from PLL setup structure (precise frequency) + * param pSetup : Pointer to populated PLL setup structure + * param flagcfg : Flag configuration for PLL config structure + * return PLL_ERROR_SUCCESS on success, or PLL setup error code + * note This function will power off the PLL, setup the PLL with the + * new setup data, and then optionally powerup the PLL, wait for PLL lock, + * and adjust system voltages to the new PLL rate. The function will not + * alter any source clocks (ie, main systen clock) that may use the PLL, + * so these should be setup prior to and after exiting the function. + */ pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) { /* Power off PLL during setup changes */ @@ -1111,11 +1529,11 @@ pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) pSetup->flags = flagcfg; /* Write PLL setup data */ - SYSCON->SYSPLLCTRL = pSetup->syspllctrl; - SYSCON->SYSPLLNDEC = pSetup->syspllndec; - SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1U << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ - SYSCON->SYSPLLPDEC = pSetup->syspllpdec; - SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1U << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ + SYSCON->SYSPLLCTRL = pSetup->syspllctrl; + SYSCON->SYSPLLNDEC = pSetup->syspllndec; + SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1U << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ + SYSCON->SYSPLLPDEC = pSetup->syspllpdec; + SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1U << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0]; SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1U << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */ SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1]; @@ -1126,7 +1544,7 @@ pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) { /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ volatile uint32_t delayX; - uint32_t maxCCO = (1U << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ + uint32_t maxCCO = (1U << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1U << 17U); /* Initialize and power up PLL */ @@ -1170,17 +1588,27 @@ pll_error_t CLOCK_SetupSystemPLLPrec(pll_setup_t *pSetup, uint32_t flagcfg) } /* Setup PLL Frequency from pre-calculated value */ +/** + * brief Set PLL output from PLL setup structure (precise frequency) + * param pSetup : Pointer to populated PLL setup structure + * return kStatus_PLL_Success on success, or PLL setup error code + * note This function will power off the PLL, setup the PLL with the + * new setup data, and then optionally powerup the PLL, wait for PLL lock, + * and adjust system voltages to the new PLL rate. The function will not + * alter any source clocks (ie, main systen clock) that may use the PLL, + * so these should be setup prior to and after exiting the function. + */ pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup) { /* Power off PLL during setup changes */ POWER_EnablePD(kPDRUNCFG_PD_SYS_PLL0); /* Write PLL setup data */ - SYSCON->SYSPLLCTRL = pSetup->syspllctrl; - SYSCON->SYSPLLNDEC = pSetup->syspllndec; - SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1U << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ - SYSCON->SYSPLLPDEC = pSetup->syspllpdec; - SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1U << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ + SYSCON->SYSPLLCTRL = pSetup->syspllctrl; + SYSCON->SYSPLLNDEC = pSetup->syspllndec; + SYSCON->SYSPLLNDEC = pSetup->syspllndec | (1U << SYSCON_SYSPLLNDEC_NREQ_SHIFT); /* latch */ + SYSCON->SYSPLLPDEC = pSetup->syspllpdec; + SYSCON->SYSPLLPDEC = pSetup->syspllpdec | (1U << SYSCON_SYSPLLPDEC_PREQ_SHIFT); /* latch */ SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0]; SYSCON->SYSPLLSSCTRL0 = pSetup->syspllssctrl[0] | (1U << SYSCON_SYSPLLSSCTRL0_MREQ_SHIFT); /* latch */ SYSCON->SYSPLLSSCTRL1 = pSetup->syspllssctrl[1]; @@ -1191,12 +1619,12 @@ pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup) { /* If turning the PLL back on, perform the following sequence to accelerate PLL lock */ volatile uint32_t delayX; - uint32_t maxCCO = (1U << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ + uint32_t maxCCO = (1U << 18U) | 0x5dd2U; /* CCO = 1.6Ghz + MDEC enabled*/ uint32_t curSSCTRL = SYSCON->SYSPLLSSCTRL0 & ~(1U << 17U); /* Initialize and power up PLL */ SYSCON->SYSPLLSSCTRL0 = maxCCO; - SYSCON->PDRUNCFGCLR[0] = SYSCON_PDRUNCFG_PDEN_SYS_PLL_MASK; + POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); /* Set mreq to activate */ SYSCON->SYSPLLSSCTRL0 = maxCCO | (1U << 17U); @@ -1213,7 +1641,7 @@ pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup) SYSCON->SYSPLLSSCTRL0 = curSSCTRL | (1U << 17U); /* Enable peripheral states by setting low */ - SYSCON->PDRUNCFGCLR[0] = SYSCON_PDRUNCFG_PDEN_SYS_PLL_MASK; + POWER_DisablePD(kPDRUNCFG_PD_SYS_PLL0); } if ((pSetup->flags & PLL_SETUPFLAG_WAITLOCK) != 0U) { @@ -1229,16 +1657,27 @@ pll_error_t CLOCK_SetPLLFreq(const pll_setup_t *pSetup) } /* Set System PLL clock based on the input frequency and multiplier */ +/*! brief Set PLL output based on the multiplier and input frequency + * param multiply_by : multiplier + * param input_freq : Clock input frequency of the PLL + * return Nothing + * note Unlike the Chip_Clock_SetupSystemPLLPrec() function, this + * function does not disable or enable PLL power, wait for PLL lock, + * or adjust system voltages. These must be done in the application. + * The function will not alter any source clocks (ie, main systen clock) + * that may use the PLL, so these should be setup prior to and after + * exiting the function. + */ void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq) { uint32_t cco_freq = input_freq * multiply_by; - uint32_t pdec = 1U; + uint32_t pdec = 1U; uint32_t selr; uint32_t seli; uint32_t selp; uint32_t mdec, ndec; - uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO_SHIFT; + uint32_t directo = SYSCON_SYSPLLCTRL_DIRECTO(1); while (cco_freq < 75000000U) { @@ -1279,9 +1718,9 @@ void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq) if (pdec > 1U) { - directo = 0U; /* use post divider */ - pdec = pdec / 2U; /* Account for minus 1 encoding */ - /* Translate P value */ + directo = 0U; /* use post divider */ + pdec = pdec / 2U; /* Account for minus 1 encoding */ + /* Translate P value */ switch (pdec) { case 1U: @@ -1311,7 +1750,7 @@ void CLOCK_SetupSystemPLLMult(uint32_t multiply_by, uint32_t input_freq) mdec = PLL_SSCG0_MDEC_VAL_SET(pllEncodeM(multiply_by)); ndec = 0x302U; /* pre divide by 1 (hardcoded) */ - SYSCON->SYSPLLCTRL = SYSCON_SYSPLLCTRL_BANDSEL_SHIFT | directo | SYSCON_SYSPLLCTRL_BYPASSCCODIV2_SHIFT | + SYSCON->SYSPLLCTRL = SYSCON_SYSPLLCTRL_BANDSEL(1) | directo | SYSCON_SYSPLLCTRL_BYPASSCCODIV2(1) | (selr << SYSCON_SYSPLLCTRL_SELR_SHIFT) | (seli << SYSCON_SYSPLLCTRL_SELI_SHIFT) | (selp << SYSCON_SYSPLLCTRL_SELP_SHIFT); SYSCON->SYSPLLPDEC = pdec | (1U << 7U); /* set Pdec value and assert preq */ @@ -1355,3 +1794,79 @@ bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq) return ret; } + +#if (defined(__CORTEX_M) && (__CORTEX_M == 0U)) +/*! + * brief Delay at least for several microseconds. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + + uint32_t count = (uint32_t)USEC_TO_COUNT(delay_us, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); + + /* + * Calculate the real delay count depend on the excute instructions cycles, + * users can change the divider value to adapt to the real IDE optimise level. + */ + count = (count / 4U); + + for (; count > 0UL; count--) + { + __NOP(); + } +} +#else +/*! + * brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum devices + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * param delay_us Delay time in unit of microsecond. + */ +__attribute__((weak)) void SDK_DelayAtLeastUs(uint32_t delay_us) +{ + assert(0U != delay_us); + uint64_t count = 0U; + uint32_t period = SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; + + /* 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)); + + /* If CYCCENT has already been enabled, read directly, otherwise, need enable it. */ + if (DWT_CTRL_CYCCNTENA_Msk != (DWT_CTRL_CYCCNTENA_Msk & DWT->CTRL)) + { + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + } + + /* Calculate the count ticks. */ + count = DWT->CYCCNT; + count += (uint64_t)period * delay_us; + + if (count > 0xFFFFFFFFUL) + { + count -= 0xFFFFFFFFUL; + /* wait for cyccnt overflow. */ + while (count < DWT->CYCCNT) + { + } + } + + /* Wait for cyccnt reach count value. */ + while (count > DWT->CYCCNT) + { + } +} +#endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.h index f41754098d..15ca58bb42 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC54114/drivers/fsl_clock.h @@ -1,40 +1,16 @@ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2016 - 2019 , NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_CLOCK_H_ #define _FSL_CLOCK_H_ -#include "fsl_device_registers.h" -#include -#include -#include +#include "fsl_common.h" /*! @addtogroup clock */ /*! @{ */ @@ -44,11 +20,34 @@ /******************************************************************************* * Definitions *****************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +/*! @brief CLOCK driver version 2.2.0. */ +#define FSL_CLOCK_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) +/*@}*/ + +/*! + * @brief User-defined the size of cache for CLOCK_PllGetConfig() function. + * + * Once define this MACRO to be non-zero value, CLOCK_PllGetConfig() function + * would cache the recent calulation and accelerate the execution to get the + * right settings. + */ +#ifndef CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT +#define CLOCK_USR_CFG_PLL_CONFIG_CACHE_COUNT 2U +#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 (96000000UL) +#endif + /*! @brief Clock ip name array for FLEXCOMM. */ -#define FLEXCOMM_CLOCKS \ - { \ - kCLOCK_FlexComm0, kCLOCK_FlexComm1, kCLOCK_FlexComm2, kCLOCK_FlexComm3, \ - kCLOCK_FlexComm4, kCLOCK_FlexComm5, kCLOCK_FlexComm6, kCLOCK_FlexComm7 \ +#define FLEXCOMM_CLOCKS \ + { \ + kCLOCK_FlexComm0, kCLOCK_FlexComm1, kCLOCK_FlexComm2, kCLOCK_FlexComm3, kCLOCK_FlexComm4, kCLOCK_FlexComm5, \ + kCLOCK_FlexComm6, kCLOCK_FlexComm7 \ } /*! @brief Clock ip name array for LPUART. */ #define LPUART_CLOCKS \ @@ -166,31 +165,31 @@ typedef enum _clock_ip_name { kCLOCK_IpInvalid = 0U, - kCLOCK_Rom = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 1), - kCLOCK_Sram1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 3), - kCLOCK_Sram2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 4), - kCLOCK_Regfile = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 6), - kCLOCK_Flash = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 7), - kCLOCK_Fmc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 8), - kCLOCK_InputMux = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 11), - kCLOCK_Iocon = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 13), - kCLOCK_Gpio0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 14), - kCLOCK_Gpio1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 15), - kCLOCK_Gpio2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 16), - kCLOCK_Gpio3 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 17), - kCLOCK_Pint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 18), - kCLOCK_Gint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 19), /* GPIO_GLOBALINT0 and GPIO_GLOBALINT1 share the same slot */ - kCLOCK_Dma = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 20), - kCLOCK_Crc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 21), - kCLOCK_Wwdt = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 22), - kCLOCK_Rtc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 23), + kCLOCK_Rom = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 1), + kCLOCK_Sram1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 3), + kCLOCK_Sram2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 4), + kCLOCK_Regfile = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 6), + kCLOCK_Flash = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 7), + kCLOCK_Fmc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 8), + kCLOCK_InputMux = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 11), + kCLOCK_Iocon = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 13), + kCLOCK_Gpio0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 14), + kCLOCK_Gpio1 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 15), + kCLOCK_Gpio2 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 16), + kCLOCK_Gpio3 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 17), + kCLOCK_Pint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 18), + kCLOCK_Gint = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 19), /* GPIO_GLOBALINT0 and GPIO_GLOBALINT1 share the same slot */ + kCLOCK_Dma = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 20), + kCLOCK_Crc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 21), + kCLOCK_Wwdt = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 22), + kCLOCK_Rtc = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 23), kCLOCK_Mailbox = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 26), - kCLOCK_Adc0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 27), - kCLOCK_Mrt = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 0), - kCLOCK_Sct0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 2), + kCLOCK_Adc0 = CLK_GATE_DEFINE(AHB_CLK_CTRL0, 27), + kCLOCK_Mrt = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 0), + kCLOCK_Sct0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 2), kCLOCK_SctIpu0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 6), - kCLOCK_Utick = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 10), - kCLOCK_FlexComm0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), + kCLOCK_Utick = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 10), + kCLOCK_FlexComm0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), kCLOCK_FlexComm1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), kCLOCK_FlexComm2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), kCLOCK_FlexComm3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), @@ -198,45 +197,45 @@ typedef enum _clock_ip_name kCLOCK_FlexComm5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), kCLOCK_FlexComm6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), kCLOCK_FlexComm7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), - kCLOCK_MinUart0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), - kCLOCK_MinUart1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), - kCLOCK_MinUart2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), - kCLOCK_MinUart3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), - kCLOCK_MinUart4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), - kCLOCK_MinUart5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), - kCLOCK_MinUart6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), - kCLOCK_MinUart7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), - kCLOCK_LSpi0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), - kCLOCK_LSpi1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), - kCLOCK_LSpi2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), - kCLOCK_LSpi3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), - kCLOCK_LSpi4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), - kCLOCK_LSpi5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), - kCLOCK_LSpi6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), - kCLOCK_LSpi7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), - kCLOCK_BI2c0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), - kCLOCK_BI2c1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), - kCLOCK_BI2c2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), - kCLOCK_BI2c3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), - kCLOCK_BI2c4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), - kCLOCK_BI2c5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), - kCLOCK_BI2c6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), - kCLOCK_BI2c7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), - kCLOCK_FlexI2s0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), - kCLOCK_FlexI2s1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), - kCLOCK_FlexI2s2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), - kCLOCK_FlexI2s3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), - kCLOCK_FlexI2s4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), - kCLOCK_FlexI2s5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), - kCLOCK_FlexI2s6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), - kCLOCK_FlexI2s7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), - kCLOCK_DMic = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 19), - kCLOCK_Ct32b2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 22), - kCLOCK_Usbd0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 25), - kCLOCK_Ct32b0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 26), - kCLOCK_Ct32b1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 27), - kCLOCK_Pvtvf0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28), - kCLOCK_Pvtvf1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28), + kCLOCK_MinUart0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), + kCLOCK_MinUart1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), + kCLOCK_MinUart2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), + kCLOCK_MinUart3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), + kCLOCK_MinUart4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), + kCLOCK_MinUart5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), + kCLOCK_MinUart6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), + kCLOCK_MinUart7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), + kCLOCK_LSpi0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), + kCLOCK_LSpi1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), + kCLOCK_LSpi2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), + kCLOCK_LSpi3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), + kCLOCK_LSpi4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), + kCLOCK_LSpi5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), + kCLOCK_LSpi6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), + kCLOCK_LSpi7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), + kCLOCK_BI2c0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), + kCLOCK_BI2c1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), + kCLOCK_BI2c2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), + kCLOCK_BI2c3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), + kCLOCK_BI2c4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), + kCLOCK_BI2c5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), + kCLOCK_BI2c6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), + kCLOCK_BI2c7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), + kCLOCK_FlexI2s0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 11), + kCLOCK_FlexI2s1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 12), + kCLOCK_FlexI2s2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 13), + kCLOCK_FlexI2s3 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 14), + kCLOCK_FlexI2s4 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 15), + kCLOCK_FlexI2s5 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 16), + kCLOCK_FlexI2s6 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 17), + kCLOCK_FlexI2s7 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 18), + kCLOCK_DMic = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 19), + kCLOCK_Ct32b2 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 22), + kCLOCK_Usbd0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 25), + kCLOCK_Ct32b0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 26), + kCLOCK_Ct32b1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 27), + kCLOCK_Pvtvf0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28), + kCLOCK_Pvtvf1 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 28), kCLOCK_BodyBias0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 29), kCLOCK_EzhArchB0 = CLK_GATE_DEFINE(AHB_CLK_CTRL1, 31), @@ -254,7 +253,7 @@ typedef enum _clock_name kCLOCK_ExtClk, /*!< External Clock */ kCLOCK_PllOut, /*!< PLL Output */ kCLOCK_UsbClk, /*!< USB input */ - kClock_WdtOsc, /*!< Watchdog Oscillator */ + kCLOCK_WdtOsc, /*!< Watchdog Oscillator */ kCLOCK_Frg, /*!< Frg Clock */ kCLOCK_Dmic, /*!< Digital Mic clock */ kCLOCK_AsyncApbClk, /*!< Async APB clock */ @@ -279,18 +278,22 @@ typedef enum _async_clock_src } async_clock_src_t; /*! @brief Clock Mux Switches -* The encoding is as follows each connection identified is 64bits wide -* starting from LSB upwards -* -* [4 bits for choice, where 1 is A, 2 is B, 3 is C and 4 is D, 0 means end of descriptor] [8 bits mux ID]* -* -*/ + * 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 MUX_A(m, choice) (((m) << 0) | ((choice + 1) << 8)) -#define MUX_B(m, choice) (((m) << 12) | ((choice + 1) << 20)) -#define MUX_C(m, choice) (((m) << 24) | ((choice + 1) << 32)) -#define MUX_D(m, choice) (((m) << 36) | ((choice + 1) << 44)) -#define MUX_E(m, choice) (((m) << 48) | ((choice + 1) << 56)) +#define CLK_ATTACH_ID(mux, sel, pos) (((mux << 0U) | ((sel + 1) & 0xFU) << 8U) << (pos * 12U)) +#define MUX_A(mux, sel) CLK_ATTACH_ID(mux, sel, 0U) +#define MUX_B(mux, sel, selector) (CLK_ATTACH_ID(mux, sel, 1U) | (selector << 24U)) + +#define GET_ID_ITEM(connection) ((connection)&0xFFFU) +#define GET_ID_NEXT_ITEM(connection) ((connection) >> 12U) +#define GET_ID_ITEM_MUX(connection) ((connection)&0xFFU) +#define GET_ID_ITEM_SEL(connection) ((((connection)&0xF00U) >> 8U) - 1U) +#define GET_ID_SELECTOR(connection) ((connection)&0xF000000U) #define CM_MAINCLKSELA 0 #define CM_MAINCLKSELB 1 @@ -326,134 +329,136 @@ typedef enum _async_clock_src typedef enum _clock_attach_id { - kFRO12M_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 0), - kEXT_CLK_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 1) | MUX_B(CM_MAINCLKSELB, 0), - kWDT_OSC_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 2) | MUX_B(CM_MAINCLKSELB, 0), - kFRO_HF_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 3) | MUX_B(CM_MAINCLKSELB, 0), - kSYS_PLL_to_MAIN_CLK = MUX_A(CM_MAINCLKSELB, 2), - kOSC32K_to_MAIN_CLK = MUX_A(CM_MAINCLKSELB, 3), + kFRO12M_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 0, 0), + kEXT_CLK_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 1) | MUX_B(CM_MAINCLKSELB, 0, 0), + kWDT_OSC_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 2) | MUX_B(CM_MAINCLKSELB, 0, 0), + kFRO_HF_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 3) | MUX_B(CM_MAINCLKSELB, 0, 0), + kSYS_PLL_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 2, 0), + kOSC32K_to_MAIN_CLK = MUX_A(CM_MAINCLKSELA, 0) | MUX_B(CM_MAINCLKSELB, 3, 0), - kFRO12M_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 0), + kFRO12M_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 0), kEXT_CLK_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 1), kWDT_OSC_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 2), - kOSC32K_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 3), - kNONE_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 7), + kOSC32K_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 3), + kNONE_to_SYS_PLL = MUX_A(CM_SYSPLLCLKSEL, 7), kMAIN_CLK_to_ASYNC_APB = MUX_A(CM_ASYNCAPB, 0), - kFRO12M_to_ASYNC_APB = MUX_A(CM_ASYNCAPB, 1), + kFRO12M_to_ASYNC_APB = MUX_A(CM_ASYNCAPB, 1), kMAIN_CLK_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 0), - kSYS_PLL_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 1), - kFRO_HF_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 2), - kNONE_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 7), + kSYS_PLL_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 1), + kFRO_HF_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 2), + kNONE_to_ADC_CLK = MUX_A(CM_ADCASYNCCLKSEL, 7), kMAIN_CLK_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 0), - kSYS_PLL_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 1), - kFRO_HF_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 3), - kNONE_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 7), + kSYS_PLL_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 1), + kFRO_HF_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 3), + kNONE_to_SPIFI_CLK = MUX_A(CM_SPIFICLKSEL, 7), - kFRO12M_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 0), - kFRO_HF_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 1), + kFRO12M_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 0), + kFRO_HF_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 1), kSYS_PLL_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 2), - kMCLK_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 3), - kFRG_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 4), - kNONE_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 7), + kMCLK_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 3), + kFRG_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 4), + kNONE_to_FLEXCOMM0 = MUX_A(CM_FXCOMCLKSEL0, 7), - kFRO12M_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 0), - kFRO_HF_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 1), + kFRO12M_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 0), + kFRO_HF_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 1), kSYS_PLL_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 2), - kMCLK_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 3), - kFRG_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 4), - kNONE_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 7), + kMCLK_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 3), + kFRG_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 4), + kNONE_to_FLEXCOMM1 = MUX_A(CM_FXCOMCLKSEL1, 7), - kFRO12M_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 0), - kFRO_HF_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 1), + kFRO12M_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 0), + kFRO_HF_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 1), kSYS_PLL_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 2), - kMCLK_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 3), - kFRG_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 4), - kNONE_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 7), + kMCLK_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 3), + kFRG_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 4), + kNONE_to_FLEXCOMM2 = MUX_A(CM_FXCOMCLKSEL2, 7), - kFRO12M_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 0), - kFRO_HF_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 1), + kFRO12M_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 0), + kFRO_HF_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 1), kSYS_PLL_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 2), - kMCLK_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 3), - kFRG_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 4), - kNONE_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 7), + kMCLK_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 3), + kFRG_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 4), + kNONE_to_FLEXCOMM3 = MUX_A(CM_FXCOMCLKSEL3, 7), - kFRO12M_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 0), - kFRO_HF_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 1), + kFRO12M_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 0), + kFRO_HF_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 1), kSYS_PLL_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 2), - kMCLK_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 3), - kFRG_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 4), - kNONE_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 7), + kMCLK_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 3), + kFRG_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 4), + kNONE_to_FLEXCOMM4 = MUX_A(CM_FXCOMCLKSEL4, 7), - kFRO12M_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 0), - kFRO_HF_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 1), + kFRO12M_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 0), + kFRO_HF_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 1), kSYS_PLL_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 2), - kMCLK_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 3), - kFRG_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 4), - kNONE_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 7), + kMCLK_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 3), + kFRG_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 4), + kNONE_to_FLEXCOMM5 = MUX_A(CM_FXCOMCLKSEL5, 7), - kFRO12M_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 0), - kFRO_HF_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 1), + kFRO12M_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 0), + kFRO_HF_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 1), kSYS_PLL_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 2), - kMCLK_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 3), - kFRG_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 4), - kNONE_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 7), + kMCLK_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 3), + kFRG_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 4), + kNONE_to_FLEXCOMM6 = MUX_A(CM_FXCOMCLKSEL6, 7), - kFRO12M_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 0), - kFRO_HF_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 1), + kFRO12M_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 0), + kFRO_HF_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 1), kSYS_PLL_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 2), - kMCLK_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 3), - kFRG_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 4), - kNONE_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 7), + kMCLK_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 3), + kFRG_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 4), + kNONE_to_FLEXCOMM7 = MUX_A(CM_FXCOMCLKSEL7, 7), kMAIN_CLK_to_FRG = MUX_A(CM_FRGCLKSEL, 0), - kSYS_PLL_to_FRG = MUX_A(CM_FRGCLKSEL, 1), - kFRO12M_to_FRG = MUX_A(CM_FRGCLKSEL, 2), - kFRO_HF_to_FRG = MUX_A(CM_FRGCLKSEL, 3), - kNONE_to_FRG = MUX_A(CM_FRGCLKSEL, 7), + kSYS_PLL_to_FRG = MUX_A(CM_FRGCLKSEL, 1), + kFRO12M_to_FRG = MUX_A(CM_FRGCLKSEL, 2), + kFRO_HF_to_FRG = MUX_A(CM_FRGCLKSEL, 3), + kNONE_to_FRG = MUX_A(CM_FRGCLKSEL, 7), - kFRO_HF_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 0), - kSYS_PLL_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 1), - kNONE_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 7), + kFRO_HF_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 0), + kSYS_PLL_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 1), + kMAIN_CLK_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 2), + kNONE_to_MCLK = MUX_A(CM_FXI2S0MCLKCLKSEL, 7), - kFRO12M_to_DMIC = MUX_A(CM_DMICCLKSEL, 0), - kFRO_HF_to_DMIC = MUX_A(CM_DMICCLKSEL, 1), - kSYS_PLL_to_DMIC = MUX_A(CM_DMICCLKSEL, 2), - kMCLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 3), + kFRO12M_to_DMIC = MUX_A(CM_DMICCLKSEL, 0), + kFRO_HF_to_DMIC = MUX_A(CM_DMICCLKSEL, 1), + kSYS_PLL_to_DMIC = MUX_A(CM_DMICCLKSEL, 2), + kMCLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 3), kMAIN_CLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 4), - kWDT_CLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 5), - kNONE_to_DMIC = MUX_A(CM_DMICCLKSEL, 7), + kWDT_CLK_to_DMIC = MUX_A(CM_DMICCLKSEL, 5), + kNONE_to_DMIC = MUX_A(CM_DMICCLKSEL, 7), - kFRO_HF_to_USB_CLK = MUX_A(CM_USBCLKSEL, 0), - kSYS_PLL_to_USB_CLK = MUX_A(CM_USBCLKSEL, 1), - kNONE_to_USB_CLK = MUX_A(CM_USBCLKSEL, 7), + kFRO_HF_to_USB_CLK = MUX_A(CM_USBCLKSEL, 0), + kSYS_PLL_to_USB_CLK = MUX_A(CM_USBCLKSEL, 1), + kMAIN_CLK_to_USB_CLK = MUX_A(CM_USBCLKSEL, 2), + kNONE_to_USB_CLK = MUX_A(CM_USBCLKSEL, 7), kMAIN_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 0), - kEXT_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 1), - kWDT_OSC_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 2), - kFRO_HF_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 3), - kSYS_PLL_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 4), - kFRO12M_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 5), - kOSC32K_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 6), - kNONE_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 7), - kNONE_to_NONE = 0x80000000U, + kEXT_CLK_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 1), + kWDT_OSC_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 2), + kFRO_HF_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 3), + kSYS_PLL_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 4), + kFRO12M_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 5), + kOSC32K_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 6), + kNONE_to_CLKOUT = MUX_A(CM_CLKOUTCLKSELA, 7), + kNONE_to_NONE = (int)0x80000000U, } clock_attach_id_t; /* Clock dividers */ typedef enum _clock_div_name { - kCLOCK_DivSystickClk = 0, - kCLOCK_DivTraceClk = 1, - kCLOCK_DivAhbClk = 32, - kCLOCK_DivClkOut = 33, - kCLOCK_DivSpifiClk = 36, + kCLOCK_DivSystickClk = 0, + kCLOCK_DivTraceClk = 1, + kCLOCK_DivAhbClk = 32, + kCLOCK_DivClkOut = 33, + kCLOCK_DivSpifiClk = 36, kCLOCK_DivAdcAsyncClk = 37, - kCLOCK_DivUsbClk = 38, - kCLOCK_DivFrg = 40, - kCLOCK_DivDmicClk = 42, - kCLOCK_DivFxI2s0MClk = 43 + kCLOCK_DivUsbClk = 38, + kCLOCK_DivFrg = 40, + kCLOCK_DivDmicClk = 42, + kCLOCK_DivFxI2s0MClk = 43 } clock_div_name_t; /******************************************************************************* @@ -500,8 +505,6 @@ typedef enum _clock_flashtim kCLOCK_Flash4Cycle, /*!< Flash accesses use 4 CPU clocks */ kCLOCK_Flash5Cycle, /*!< Flash accesses use 5 CPU clocks */ kCLOCK_Flash6Cycle, /*!< Flash accesses use 6 CPU clocks */ - kCLOCK_Flash7Cycle, /*!< Flash accesses use 7 CPU clocks */ - kCLOCK_Flash8Cycle /*!< Flash accesses use 8 CPU clocks */ } clock_flashtim_t; /** @@ -533,6 +536,14 @@ status_t CLOCK_SetupFROClocking(uint32_t iFreq); * @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 attachId : Clock attach id to get. + * @return Clock source value. + */ +clock_attach_id_t CLOCK_GetClockAttachId(clock_attach_id_t attachId); /** * @brief Setup peripheral clock dividers. * @param div_name : Clock divider name @@ -556,13 +567,23 @@ uint32_t CLOCK_GetFreq(clock_name_t clockName); * @return Input Frequency for FRG */ uint32_t CLOCK_GetFRGInputClock(void); - + +/*! @brief Return Input frequency for the DMIC + * @return Input Frequency for DMIC + */ +uint32_t CLOCK_GetDmicClkFreq(void); + +/*! @brief Return Input frequency for the FRG + * @return Input Frequency for FRG + */ +uint32_t CLOCK_GetFrgClkFreq(void); + /*! @brief Set output of the Fractional baud rate generator * @param freq : Desired output frequency * @return Error Code 0 - fail 1 - success */ uint32_t CLOCK_SetFRGClock(uint32_t freq); - + /*! @brief Return Frequency of FRO 12MHz * @return Frequency of FRO 12MHz */ @@ -579,6 +600,10 @@ uint32_t CLOCK_GetWdtOscFreq(void); * @return Frequency of High-Freq output of FRO */ uint32_t CLOCK_GetFroHfFreq(void); +/*! @brief Return Frequency of USB + * @return Frequency of USB + */ +uint32_t CLOCK_GetUsbClkFreq(void); /*! @brief Return Frequency of PLL * @return Frequency of PLL */ @@ -599,6 +624,10 @@ uint32_t CLOCK_GetI2SMClkFreq(void); * @return Frequency of Flexcomm functional Clock */ uint32_t CLOCK_GetFlexCommClkFreq(uint32_t id); +/*! @brief Return Frequency of Adc Clock + * @return Frequency of Adc Clock. + */ +uint32_t CLOCK_GetAdcClkFreq(void); /*! @brief Return Asynchronous APB Clock source * @return Asynchronous APB CLock source */ @@ -670,12 +699,14 @@ void CLOCK_SetStoredPLLClockRate(uint32_t rate); */ #define PLL_CONFIGFLAG_USEINRATE (1 << 0) /*!< Flag to use InputRate in PLL configuration structure for setup */ #define PLL_CONFIGFLAG_FORCENOFRACT \ - (1 \ - << 2) /*!< Force non-fractional output mode, PLL output will not use the fractional, automatic bandwidth, or SS \ \ - \ \ \ \ - \ \ \ \ \ \ - \ \ \ \ \ \ \ \ - hardware */ + (1 << 2) /*!< Force non-fractional output mode, PLL output will not use the fractional, automatic bandwidth, or SS \ + \ \ \ + \ \ \ \ \ + \ \ \ \ \ \ \ + \ \ \ \ \ \ \ \ \ + \ \ \ \ \ \ \ \ \ \ \ + \ \ \ \ \ \ \ \ \ \ \ \ \ + hardware */ /*! @brief PLL Spread Spectrum (SS) Programmable modulation frequency * See (MF) field in the SYSPLLSSCTRL1 register in the UM. @@ -686,10 +717,10 @@ typedef enum _ss_progmodfm kSS_MF_384 = (1 << 20), /*!< Nss ?= 384 (fm ? 5.2 - 10.4 kHz) */ kSS_MF_256 = (2 << 20), /*!< Nss = 256 (fm ? 7.8 - 15.6 kHz) */ kSS_MF_128 = (3 << 20), /*!< Nss = 128 (fm ? 15.6 - 31.3 kHz) */ - kSS_MF_64 = (4 << 20), /*!< Nss = 64 (fm ? 32.3 - 64.5 kHz) */ - kSS_MF_32 = (5 << 20), /*!< Nss = 32 (fm ? 62.5- 125 kHz) */ - kSS_MF_24 = (6 << 20), /*!< Nss ?= 24 (fm ? 83.3- 166.6 kHz) */ - kSS_MF_16 = (7 << 20) /*!< Nss = 16 (fm ? 125- 250 kHz) */ + kSS_MF_64 = (4 << 20), /*!< Nss = 64 (fm ? 32.3 - 64.5 kHz) */ + kSS_MF_32 = (5 << 20), /*!< Nss = 32 (fm ? 62.5- 125 kHz) */ + kSS_MF_24 = (6 << 20), /*!< Nss ?= 24 (fm ? 83.3- 166.6 kHz) */ + kSS_MF_16 = (7 << 20) /*!< Nss = 16 (fm ? 125- 250 kHz) */ } ss_progmodfm_t; /*! @brief PLL Spread Spectrum (SS) Programmable frequency modulation depth @@ -697,14 +728,14 @@ typedef enum _ss_progmodfm */ typedef enum _ss_progmoddp { - kSS_MR_K0 = (0 << 23), /*!< k = 0 (no spread spectrum) */ - kSS_MR_K1 = (1 << 23), /*!< k = 1 */ + kSS_MR_K0 = (0 << 23), /*!< k = 0 (no spread spectrum) */ + kSS_MR_K1 = (1 << 23), /*!< k = 1 */ kSS_MR_K1_5 = (2 << 23), /*!< k = 1.5 */ - kSS_MR_K2 = (3 << 23), /*!< k = 2 */ - kSS_MR_K3 = (4 << 23), /*!< k = 3 */ - kSS_MR_K4 = (5 << 23), /*!< k = 4 */ - kSS_MR_K6 = (6 << 23), /*!< k = 6 */ - kSS_MR_K8 = (7 << 23) /*!< k = 8 */ + kSS_MR_K2 = (3 << 23), /*!< k = 2 */ + kSS_MR_K3 = (4 << 23), /*!< k = 3 */ + kSS_MR_K4 = (5 << 23), /*!< k = 4 */ + kSS_MR_K6 = (6 << 23), /*!< k = 6 */ + kSS_MR_K8 = (7 << 23) /*!< k = 8 */ } ss_progmoddp_t; /*! @brief PLL Spread Spectrum (SS) Modulation waveform control @@ -714,7 +745,7 @@ typedef enum _ss_progmoddp */ typedef enum _ss_modwvctrl { - kSS_MC_NOC = (0 << 26), /*!< no compensation */ + kSS_MC_NOC = (0 << 26), /*!< no compensation */ kSS_MC_RECC = (2 << 26), /*!< recommended setting */ kSS_MC_MAXC = (3 << 26), /*!< max. compensation */ } ss_modwvctrl_t; @@ -742,19 +773,20 @@ typedef struct _pll_config } pll_config_t; /*! @brief PLL setup structure flags for 'flags' field -* These flags control how the PLL setup function sets up the PLL -*/ -#define PLL_SETUPFLAG_POWERUP (1 << 0) /*!< Setup will power on the PLL after setup */ -#define PLL_SETUPFLAG_WAITLOCK (1 << 1) /*!< Setup will wait for PLL lock, implies the PLL will be pwoered on */ -#define PLL_SETUPFLAG_ADGVOLT (1 << 2) /*!< Optimize system voltage for the new PLL rate */ + * These flags control how the PLL setup function sets up the PLL + */ +#define PLL_SETUPFLAG_POWERUP (1 << 0) /*!< Setup will power on the PLL after setup */ +#define PLL_SETUPFLAG_WAITLOCK (1 << 1) /*!< Setup will wait for PLL lock, implies the PLL will be pwoered on */ +#define PLL_SETUPFLAG_ADGVOLT (1 << 2) /*!< Optimize system voltage for the new PLL rate */ +#define PLL_SETUPFLAG_USEFEEDBACKDIV2 (1 << 3) /*!< Use feedback divider by 2 in divider path */ /*! @brief PLL setup structure -* This structure can be used to pre-build a PLL setup configuration -* at run-time and quickly set the PLL to the configuration. It can be -* populated with the PLL setup function. If powering up or waiting -* for PLL lock, the PLL input clock source should be configured prior -* to PLL setup. -*/ + * This structure can be used to pre-build a PLL setup configuration + * at run-time and quickly set the PLL to the configuration. It can be + * populated with the PLL setup function. If powering up or waiting + * for PLL lock, the PLL input clock source should be configured prior + * to PLL setup. + */ typedef struct _pll_setup { uint32_t syspllctrl; /*!< PLL control register SYSPLLCTRL */ @@ -769,21 +801,21 @@ typedef struct _pll_setup */ typedef enum _pll_error { - kStatus_PLL_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< PLL operation was successful */ - kStatus_PLL_OutputTooLow = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< PLL output rate request was too low */ - kStatus_PLL_OutputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< PLL output rate request was too high */ - kStatus_PLL_InputTooLow = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< PLL input rate is too low */ - kStatus_PLL_InputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< PLL input rate is too high */ - kStatus_PLL_OutsideIntLimit = MAKE_STATUS(kStatusGroup_Generic, 5) /*!< Requested output rate isn't possible */ + kStatus_PLL_Success = MAKE_STATUS(kStatusGroup_Generic, 0), /*!< PLL operation was successful */ + kStatus_PLL_OutputTooLow = MAKE_STATUS(kStatusGroup_Generic, 1), /*!< PLL output rate request was too low */ + kStatus_PLL_OutputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 2), /*!< PLL output rate request was too high */ + kStatus_PLL_InputTooLow = MAKE_STATUS(kStatusGroup_Generic, 3), /*!< PLL input rate is too low */ + kStatus_PLL_InputTooHigh = MAKE_STATUS(kStatusGroup_Generic, 4), /*!< PLL input rate is too high */ + kStatus_PLL_OutsideIntLimit = MAKE_STATUS(kStatusGroup_Generic, 5) /*!< Requested output rate isn't possible */ } pll_error_t; /*! @brief USB clock source definition. */ typedef enum _clock_usb_src { - kCLOCK_UsbSrcFro = (uint32_t)kCLOCK_FroHf, /*!< Use FRO 96 or 48 MHz. */ + kCLOCK_UsbSrcFro = (uint32_t)kCLOCK_FroHf, /*!< Use FRO 96 or 48 MHz. */ kCLOCK_UsbSrcSystemPll = (uint32_t)kCLOCK_PllOut, /*!< Use System PLL output. */ kCLOCK_UsbSrcMainClock = (uint32_t)kCLOCK_CoreSysClk, /*!< Use Main clock. */ - kCLOCK_UsbSrcNone = SYSCON_USBCLKSEL_SEL( + kCLOCK_UsbSrcNone = SYSCON_USBCLKSEL_SEL( 7) /*!< Use None, this may be selected in order to reduce power when no output is needed. */ } clock_usb_src_t; @@ -804,7 +836,7 @@ pll_error_t CLOCK_SetupPLLData(pll_config_t *pControl, pll_setup_t *pSetup); /*! @brief Set PLL output from PLL setup structure (precise frequency) * @param pSetup : Pointer to populated PLL setup structure -* @param flagcfg : Flag configuration for PLL config structure + * @param flagcfg : Flag configuration for PLL config structure * @return PLL_ERROR_SUCCESS on success, or PLL setup error code * @note This function will power off the PLL, setup the PLL with the * new setup data, and then optionally powerup the PLL, wait for PLL lock, @@ -848,6 +880,17 @@ static inline void CLOCK_DisableUsbfs0Clock(void) CLOCK_DisableClock(kCLOCK_Usbd0); } bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq); + +/*! + * @brief Use DWT to delay at least for some time. + * Please note that, this API will calculate the microsecond period with the maximum + * supported CPU frequency, so this API will only delay for at least the given microseconds, if precise + * delay count was needed, please implement a new timer count to achieve this function. + * + * @param delay_us Delay time in unit of microsecond. + */ +void SDK_DelayAtLeastUs(uint32_t delay_us); + #if defined(__cplusplus) } #endif /* __cplusplus */