KL03 ADC results varying greatly with GCC opt setting?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

KL03 ADC results varying greatly with GCC opt setting?

660 Views
mwp_nxp
Contributor II

Hi all,

I'm finding that if I compile & optimise my firmware with anything other than -O0 (using MCUXpresso), that the ADC readings are massively different... by about a factor of 10.

The ADC is polled, so it's not an interrupt memory being read/written out of order problem.

I've confirmed timing between ADC conversions, and the conversion itself does not change by checking a spare GPIO on a DSO. 

I've tested using "pragma GCC optimize" in the source file handling the ADC conversion, but it makes no difference.

I'm running out of ideas.

The relevant source is below.... it's pretty simple.

void ADC_Init(void)
{
	adc16_config_t ADCInit;
	//init
	ADC16_GetDefaultConfig(&ADCInit);
	//adc clock needs to run between 1 and 18Mhz.
	//options below give sample time of ~30uS
	ADCInit.clockSource = kADC16_ClockSourceAlt1; //bus clock (12Mhz) div by 2 = 6mhz
	ADCInit.clockDivider = kADC16_ClockDivider4; //div by 2 again = 1.5mhz
	ADCInit.longSampleMode = kADC16_LongSampleCycle24; //long sample
	//other
	ADCInit.referenceVoltageSource = kADC16_ReferenceVoltageSourceVref;
	ADCInit.resolution = kADC16_ResolutionSE12Bit; //12bit
	ADC16_Init(ADC0, &ADCInit);
	//software trigger
	ADC16_EnableHardwareTrigger(ADC0, false);
	//self calibrate
	ADC16_DoAutoCalibration(ADC0);
}

uint32_t ADC_DoConversion(uint8_t Channel)
{
	//init
	ADCChannelConfig.channelNumber = Channel;
	ADCChannelConfig.enableInterruptOnConversionCompleted = false;
	//start conversion
	ADC16_SetChannelConfig(ADC0, ADC_CHANNEL_GROUP, &ADCChannelConfig);
	//wait for conversion to complete
	while (!(kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(ADC0, ADC_CHANNEL_GROUP)))
	{
		__NOP();
	};
	//return result
	return ADC16_GetChannelConversionValue(ADC0, ADC_CHANNEL_GROUP);
}

 

Thanks for any help!

 

Labels (1)
Tags (1)
0 Kudos
3 Replies

653 Views
bobpaddock
Senior Contributor III

"I'm finding that if I compile & optimise my firmware with anything other than -O0"
"The ADC is polled, so it's not an interrupt"

That is almost always a sign of 'volatile' being missing from someplace it is needed.
If this is pure polling system then it is missing from a hardware register that can change outside of the compilers awareness.

At non-Zero optimization levels GCC is free to remove code that it thinks is unused because it has no side effects as far as the compiler is concerned.  Looking at the two listings will show what.

"while (!(kADC16_ChannelConversionDoneFlag & ADC16_GetChannelStatusFlags(ADC0, ADC_CHANNEL_GROUP)))"

In a polled system the DoneFlag must be being set by the call to GetChannelStatusFlags.
Is a bit wise AND in '&' really what is wanted here? Switching to logical AND '&&' due to the C shortcut logic won't give the intended results either.

 

0 Kudos

650 Views
mwp_nxp
Contributor II

First, thanks for your reply.

"That is almost always a sign of 'volatile' being missing from someplace it is needed."

All register handling is being taken care of by the FSL lib, which does have volatile attributes where needed.

"Is a bit wise AND in '&' really what is wanted here?"

Yes it is. How else do you check a flag (a specific bit) is set or not set?

 

0 Kudos

628 Views
diego_charles
NXP TechSupport
NXP TechSupport

Hi @mwp_nxp 

What are your results if you test with   the Default ADC16_polling SDK example? (Maybe depending on the board that you are using you won’t be able to use semi host or UART console)

In more details I think that we could check how the code behaves by having everything done in the main function. I wonder if after optimization the channel parameter for your reading function it is not the expected or may the variable or methods that process the ADC reading have some issue.

(Also, please try to use the latest SDK for the KL03 which is  v2.3.1)

Diego.

 

 

0 Kudos