AnsweredAssumed Answered

KL27 ADC0 Configuration in VLPR Mode using SDK 2.0?

Question asked by Ben Houston on Nov 15, 2016
Latest reply on Nov 15, 2016 by Ben Houston

I have an application that brings together TPM demo code to turn on/off LED's and sample ADC to measure battery voltage. The program works fine when in Normal Run mode, however, when I try to use VLPR mode I get a HardFault_Handler exception when trying to configure the ADC Channel.

 

In VLPR, I have the TPM working fine.  Subtle adjustments to the clock source and clock source identifier, but with the ADC setup, I am at a loss. 

 

Using the default SDK 2.0 adc demo configuration when initializing:

void ADC_HWInit(void){
      // init the Internal Voltage Referrence Signal
      VREF_GetDefaultConfig(&vrefConfigStruct);
      VREF_Init(VREF, &vrefConfigStruct);

// init adc
/*
* adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
* adc16ConfigStruct.clockSource = kADC16_ClockSourceAsynchronousClock;
* adc16ConfigStruct.enableAsynchronousClock = true;
* adc16ConfigStruct.clockDivider = kADC16_ClockDivider8;
* adc16ConfigStruct.resolution = kADC16_ResolutionSE12Bit;
* adc16ConfigStruct.longSampleMode = kADC16_LongSampleDisabled;
* adc16ConfigStruct.enableHighSpeed = false;
* adc16ConfigStruct.enableLowPower = false;
* adc16ConfigStruct.enableContinuousConversion = false;
*/
ADC16_GetDefaultConfig(&adc16ConfigStruct);
ADC16_Init(ADC16_BASE, &adc16ConfigStruct);
ADC16_EnableHardwareTrigger(ADC16_BASE, false); /* Make sure the software trigger is used. */

#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION

if (kStatus_Success == ADC16_DoAutoCalibration(ADC16_BASE))
{
Console_Printf(BOARD_DEBUG_UART_BASEADDR, "\r\nADC16_DoAutoCalibration() Done.\r\n");
}
else
{
Console_Printf(BOARD_DEBUG_UART_BASEADDR, "\r\nADC16_DoAutoCalibration() Failed.\r\n");
//ToDo::save error code and set error transmit flag to report in next packet
}

#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */

//config channels and interrupt
adc16ChannelConfigStruct.channelNumber = ADC16_USER_CHANNEL;
adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = false;

#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE

adc16ChannelConfigStruct.enableDifferentialConversion = false;

#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
}

 

 

The hard fault occurs in fsl_adc16.c, when calling ADC16_SetChannelConfig().

void ADC16_SetChannelConfig(ADC_Type *base, uint32_t channelGroup, const adc16_channel_config_t *config)
{

assert(channelGroup < ADC_SC1_COUNT);
assert(NULL != config);

uint32_t sc1 = ADC_SC1_ADCH(config->channelNumber); /* Set the channel number. */

#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE

/* Enable the differential conversion. */
if (config->enableDifferentialConversion)
{
sc1 |= ADC_SC1_DIFF_MASK;
}

#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */

/* Enable the interrupt when the conversion is done. */
if (config->enableInterruptOnConversionCompleted)
{
sc1 |= ADC_SC1_AIEN_MASK;
}
base->SC1[channelGroup] = sc1;  // Hard Fault Occurs Here!!!

}

 

Like I said, this works perfectly in Normal Run mode. Not so in VLPR. 

 

In VLPR, I've tried changing the clock source to the Bus Clock, which uses the system core clock. I've also played with the dividers.  In my setup, I am using the default code for clock_config.c when calling BOARD_BootClockVLPR().  

 

Any ideas to a path would be greatly appreciated. 

Outcomes