diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/analogin_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/analogin_api.c index bbdcf8e1c9..417f841930 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/analogin_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/analogin_api.c @@ -16,7 +16,7 @@ #include "mbed_assert.h" #include "analogin_api.h" -#if DEVICE_ANALOGIN +#if DEVICE_ANALOGIN && !defined(NXP_LPADC) #include "cmsis.h" #include "pinmap.h" diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/lp_analogin_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/lp_analogin_api.c new file mode 100644 index 0000000000..be610f79a4 --- /dev/null +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC/lp_analogin_api.c @@ -0,0 +1,148 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "mbed_assert.h" +#include "analogin_api.h" + +#if DEVICE_ANALOGIN && defined(NXP_LPADC) + +#include "cmsis.h" +#include "pinmap.h" +#include "gpio_api.h" +#include "PeripheralNames.h" +#include "fsl_lpadc.h" +#include "fsl_power.h" +#include "PeripheralPins.h" + +/* Array of ADC peripheral base address. */ +static ADC_Type *const adc_addrs[] = ADC_BASE_PTRS; +extern void ADC_ClockPower_Configuration(void); + +#define LPADC_USER_CMDID 1U /* CMD1 */ + +void analogin_init(analogin_t *obj, PinName pin) +{ + gpio_t gpio; + + obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); + MBED_ASSERT(obj->adc != (ADCName)NC); + + uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT; + lpadc_config_t adc_config; + uint32_t reg; + uint32_t pin_number = pin & 0x1F; + uint8_t port_number = pin / 32; + + ADC_ClockPower_Configuration(); + + LPADC_GetDefaultConfig(&adc_config); + adc_config.enableAnalogPreliminary = true; +#if defined(LPADC_VREF_SOURCE) + adc_config.referenceVoltageSource = LPADC_VREF_SOURCE; +#endif +#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS + adc_config.conversionAverageMode = kLPADC_ConversionAverage128; +#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_AVGS */ + LPADC_Init(adc_addrs[instance], &adc_config); + +#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS +#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM + /* Request offset calibration. */ + if (true == LPADC_DO_OFFSET_CALIBRATION) { + LPADC_DoOffsetCalibration(adc_addrs[instance]); + } else { + LPADC_SetOffsetValue(adc_addrs[instance], LPADC_OFFSET_VALUE_A, LPADC_OFFSET_VALUE_B); + } +#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */ + /* Request gain calibration. */ + LPADC_DoAutoCalibration(adc_addrs[instance]); +#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */ + +#if (defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS) + /* Do auto calibration. */ + LPADC_DoAutoCalibration(adc_addrs[instance]); +#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */ + + pinmap_pinout(pin, PinMap_ADC); + + reg = IOCON->PIO[port_number][pin_number]; + /* Clear the DIGIMODE bit */ + reg &= ~IOCON_PIO_DIGIMODE_MASK; + /* For pins PIO0_9, PIO0_11, PIO0_12, PIO0_15, PIO0_18, PIO0_31, PIO1_0 and + PIO1_9, leave ASW bit at '0' in the related IOCON register. */ + if (((port_number == 0) && ((pin_number == 9) || (pin_number == 11) || (pin_number == 12) || + (pin_number == 15) || (pin_number == 18) || (pin_number == 31))) || + ((port_number == 1) && ((pin_number == 0) || (pin_number == 9)))) { + /* Disable Analog Switch Input control */ + reg &= ~IOCON_PIO_ASW_MASK; + } else { + /* Enable Analog Switch Input control */ + reg |= IOCON_PIO_ASW_MASK; + } + IOCON->PIO[port_number][pin_number] = reg; + + /* Need to ensure the pin is in input mode */ + gpio_init(&gpio, pin); + gpio_dir(&gpio, PIN_INPUT); +} + +uint16_t analogin_read_u16(analogin_t *obj) +{ + uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT; + uint32_t channel = obj->adc & 0xF; + lpadc_conv_trigger_config_t mLpadcTriggerConfigStruct; + lpadc_conv_command_config_t mLpadcCommandConfigStruct; + lpadc_conv_result_t mLpadcResultConfigStruct; + + memset(&mLpadcTriggerConfigStruct, 0, sizeof(mLpadcTriggerConfigStruct)); + memset(&mLpadcCommandConfigStruct, 0, sizeof(mLpadcCommandConfigStruct)); + memset(&mLpadcResultConfigStruct, 0, sizeof(mLpadcResultConfigStruct)); + + /* Set conversion CMD configuration. */ + LPADC_GetDefaultConvCommandConfig(&mLpadcCommandConfigStruct); + mLpadcCommandConfigStruct.channelNumber = channel; + LPADC_SetConvCommandConfig(adc_addrs[instance], LPADC_USER_CMDID, &mLpadcCommandConfigStruct); + + /* Set trigger configuration. */ + LPADC_GetDefaultConvTriggerConfig(&mLpadcTriggerConfigStruct); + mLpadcTriggerConfigStruct.targetCommandId = LPADC_USER_CMDID; + mLpadcTriggerConfigStruct.enableHardwareTrigger = false; + LPADC_SetConvTriggerConfig(adc_addrs[instance], 0U, &mLpadcTriggerConfigStruct); /* Configurate the trigger0. */ + + LPADC_DoSoftwareTrigger(adc_addrs[instance], 1U); /* 1U is trigger0 mask. */ + +#if (defined(FSL_FEATURE_LPADC_FIFO_COUNT) && (FSL_FEATURE_LPADC_FIFO_COUNT == 2U)) + while (!LPADC_GetConvResult(adc_addrs[instance], &mLpadcResultConfigStruct, 0U)) { + } +#else + while (!LPADC_GetConvResult(adc_addrs[instance], &mLpadcResultConfigStruct)) { + } +#endif /* FSL_FEATURE_LPADC_FIFO_COUNT */ + + return ((mLpadcResultConfigStruct.convValue) >> 3U); +} + +float analogin_read(analogin_t *obj) +{ + uint16_t value = analogin_read_u16(obj); + return (float)value * (1.0f / (float)0xFFFF); +} + +const PinMap *analogin_pinmap() +{ + return PinMap_ADC; +} + +#endif diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/device.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/device.h index 589f793b28..8b41c56891 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/device.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/device.h @@ -20,6 +20,11 @@ #define NUMBER_OF_GPIO_INTS 8 +#define LPADC_VREF_SOURCE kLPADC_ReferenceVoltageAlt2 +#define LPADC_DO_OFFSET_CALIBRATION false +#define LPADC_OFFSET_VALUE_A 10U +#define LPADC_OFFSET_VALUE_B 10U + #define APP_EXCLUDE_FROM_DEEPSLEEP (kPDRUNCFG_PD_DCDC | kPDRUNCFG_PD_FRO192M | kPDRUNCFG_PD_FRO32K) /* Defines used by the sleep code */ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/mbed_overrides.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/mbed_overrides.c index 44d28887fa..003959fee0 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/mbed_overrides.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_LPCXpresso/mbed_overrides.c @@ -36,16 +36,26 @@ void rtc_setup_oscillator(void) uint32_t us_ticker_get_clock() { #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) - /* Use 12 MHz clock us ticker timer */ + /* Use 96 MHz clock us ticker timer */ CLOCK_AttachClk(kFRO_HF_to_CTIMER0); return CLOCK_GetFreq(kCLOCK_CTmier0);; #else - /* Use 12 MHz clock us ticker timer */ + /* Use 96 MHz clock us ticker timer */ CLOCK_AttachClk(kFRO_HF_to_CTIMER1); return CLOCK_GetFreq(kCLOCK_CTmier1);; #endif } +void ADC_ClockPower_Configuration(void) +{ + /* Set clock source for ADC0 */ + CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk, 16U, true); + CLOCK_AttachClk(kMAIN_CLK_to_ADC_CLK); + + /* Disable LDOGPADC power down */ + POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC); +} + void sdio_clock_setup(void) { /* Attach main clock to SDIF */ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.c index 0ed4376ac2..46a1309391 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.c @@ -554,6 +554,19 @@ void LPADC_DoAutoCalibration(ADC_Type *base) #endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS +/*! + * brief Do offset calibration. + * + * param base LPADC peripheral base address. + */ +void LPADC_DoOffsetCalibration(ADC_Type *base) +{ + LPADC_EnableOffsetCalibration(base, true); + while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK)) + { + } +} + #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ /*! * brief Do auto calibration. @@ -569,12 +582,6 @@ void LPADC_DoAutoCalibration(ADC_Type *base) uint32_t GCRa; uint32_t GCRb; - /* Request offset calibration. */ - LPADC_EnableOffsetCalibration(base, true); - while (ADC_STAT_CAL_RDY_MASK != (base->STAT & ADC_STAT_CAL_RDY_MASK)) - { - } - /* Request gain calibration. */ base->CTRL |= ADC_CTRL_CAL_REQ_MASK; while ((ADC_GCC_RDY_MASK != (base->GCC[0] & ADC_GCC_RDY_MASK)) || diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.h index fb34364e45..3507c08af8 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.h +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_lpadc.h @@ -23,8 +23,8 @@ /*! @name Driver version */ /*@{*/ -/*! @brief LPADC driver version 2.0.2. */ -#define FSL_LPADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) +/*! @brief LPADC driver version 2.0.3. */ +#define FSL_LPADC_DRIVER_VERSION (MAKE_VERSION(2, 0, 3)) /*@}*/ /*! @@ -750,9 +750,6 @@ void LPADC_GetDefaultConvCommandConfig(lpadc_conv_command_config_t *config); * @bool enable switcher to the calibration function. */ void LPADC_EnableCalibration(ADC_Type *base, bool enable); -#endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */ - -#if !(defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) #if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM /*! * @brief Set proper offset value to trim ADC. @@ -767,11 +764,7 @@ static inline void LPADC_SetOffsetValue(ADC_Type *base, uint32_t value) { base->OFSTRIM = (value & ADC_OFSTRIM_OFSTRIM_MASK) >> ADC_OFSTRIM_OFSTRIM_SHIFT; } -#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */ -#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */ -#if defined(FSL_FEATURE_LPADC_HAS_CFG_CALOFS) && FSL_FEATURE_LPADC_HAS_CFG_CALOFS -#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM /*! * @brief Do auto calibration. * @@ -789,6 +782,23 @@ void LPADC_DoAutoCalibration(ADC_Type *base); #endif /* FSL_FEATURE_LPADC_HAS_CFG_CALOFS */ #if defined(FSL_FEATURE_LPADC_HAS_CTRL_CALOFS) && FSL_FEATURE_LPADC_HAS_CTRL_CALOFS +#if defined(FSL_FEATURE_LPADC_HAS_OFSTRIM) && FSL_FEATURE_LPADC_HAS_OFSTRIM +/*! + * @brief Set proper offset value to trim ADC. + * + * Set the offset trim value for offset calibration manually. + * + * @param base LPADC peripheral base address. + * @param valueA Setting offset value A. + * @param valueB Setting offset value B. + * @note In normal adc sequence, the values are automatically calculated by LPADC_EnableOffsetCalibration. + */ +static inline void LPADC_SetOffsetValue(ADC_Type *base, uint32_t valueA, uint32_t valueB) +{ + base->OFSTRIM = ADC_OFSTRIM_OFSTRIM_A(valueA) | ADC_OFSTRIM_OFSTRIM_B(valueB); +} +#endif /* FSL_FEATURE_LPADC_HAS_OFSTRIM */ + /*! * @brief Enable the offset calibration function. * @@ -807,14 +817,22 @@ static inline void LPADC_EnableOffsetCalibration(ADC_Type *base, bool enable) } } +/*! + * @brief Do offset calibration. + * + * @param base LPADC peripheral base address. + */ +void LPADC_DoOffsetCalibration(ADC_Type *base); + +#if defined(FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ) && FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ /*! * brief Do auto calibration. * * param base LPADC peripheral base address. */ void LPADC_DoAutoCalibration(ADC_Type *base); - #endif /* FSL_FEATURE_LPADC_HAS_CTRL_CAL_REQ */ +#endif /* FSL_FEATURE_LPADC_HAS_CTRL_CALOFS */ /* @} */ #if defined(__cplusplus) diff --git a/targets/targets.json b/targets/targets.json index f43137b344..1791683e57 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -2075,6 +2075,7 @@ "device_has_add": [ "USTICKER", "RTC", + "ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN",