cancel
Showing results for 
Search instead for 
Did you mean: 

Hardfault on ADC voltage change

Nickelgrass
Senior

Hello,

I have a strange problem on an STM32G071. I get ADC values every 25 ms from ADC1 channel 0 to 3 without DMA as speed is no issue. Strangely when one of the canels reaches about 1.2 V the CPU sometimes goes in a hard fault lock. There is a potentiometer connected to the channels with a voltage divider. The SCB->ICSR value is 0x00422003 (put out over a UART in the default handler). I tried to interpret it via the programming manual but I could not figure out anything.

Here is my ADC function

uint16_t get_adc(uint8_t channel)	// 24 µs
{
	while((ADC1->CR&ADC_CR_ADSTART)!=0);							// wait in case conversion is in progress
	ADC1->CHSELR = (1<<channel);									// set channel
	while((ADC1->ISR&ADC_ISR_CCRDY)==0);							// wait for channel changed
	while((ADC1->ISR&ADC_ISR_ADRDY)==0);							// wait for ADC ready
	ADC1->CR |= ADC_CR_ADSTART;										// start the conversion
	while((ADC1->CR&ADC_CR_ADSTART)!=0);							// wait for conversion finished
	volatile uint16_t temp = ADC1->DR;								// load ADC
	return temp;
}

The only interrupt that is enabled is TIM7 to generate an interval. What could cause this?

Thanks

Kind regards

1 ACCEPTED SOLUTION

Accepted Solutions
Nickelgrass
Senior

Thanks for the answers.

I finally found it. Turns out I was barking up the wrong tree. It was a routine that used the adc values that iterated past the size of an array only when the adc value was fairly large. Obviously when not getting the value it never got to large. Thus me stupidly thinking it was the adc.

What a bloody mistake to make :dizzy_face:

View solution in original post

6 REPLIES 6
TDK
Guru

This indicates you're in the HardFault_IRQn handler with the ADC_IRQn handler up next.

Debug your code, pause when the hard fault occurs and view the SCB registers to determine the cause.

I doubt the ADC reaching 1.2V has anything to do with the hard fault.

If you feel a post has answered your question, please click "Accept as Solution".
Nickelgrass
Senior

Thanks for the answer TDK. But I do not understand it. The SCB_ICSR has the value 0x422003. It means the pending interrupt is 0x22 or 34 in dec. But the STM32G071 only has interrupts up to 30. Also what does the 0x3 mean VECTACTIVE? 3 is the Flash_IRQn that I am not using.

The fault only occurs when I call the get_adc() function and change the potmeter. Specifically if I switch the channel from CH3 bit3 to CH0 bit0 and only then. If I use Ch1 to CH4 instead of CH0 to CH3 it works too. If I comment out

ADC1->CHSELR = (1<<channel);									// set channel
while((ADC1->ISR&ADC_ISR_CCRDY)==0);                                       // wait for channel changed

the code runs ok.

So the hard fault occurs when I change the channel from CH3 to CH0 and the adc value gets above a certain value.

TDK
Guru

>  Also what does the 0x3 mean VECTACTIVE?

Take the value and subtract 16. You get -13. This corresponds to a value in IRQn_Type. In this case, the hard fault handler.

Can't see the lines you linked causing a hard fault unless channel is >= 32.

If you feel a post has answered your question, please click "Accept as Solution".

If it's hardfault, debug as usually - read out the stacked PC, look at and slightly before that address in the binary (disasm, preferrably mixed with C-source), look at these instructions in the context of the processor's registers' content, trace back the offending instruction into its C source.

JW

Nickelgrass
Senior

Thanks for the answers.

I finally found it. Turns out I was barking up the wrong tree. It was a routine that used the adc values that iterated past the size of an array only when the adc value was fairly large. Obviously when not getting the value it never got to large. Thus me stupidly thinking it was the adc.

What a bloody mistake to make :dizzy_face:

Thanks for coming back with the solution. Please select your post as "Best" so that the thread is marked as solved.

JW