STM32, ADCs, Timing Problem

Hello Everyone,

these days I encountered a serious timing problem using the ADCs, twice. Because of this the ADC interrupt used up all computing power, leading to a not or *very* slow running application and, if activated, a watchdog reset.

What happend: The first time the error occured sometimes when I tried to write new parameters into the flash, just after erasing the page. After I disabled the watchdog is was just a bit harder to get the error. And every time I stopped the device I landed somewhere in the ADC interrupt. Other interrupts or the main loop where not serviced. Sometimes, after restarting the device, it worked propper again.

The second time the error occured at nearly every startup, after I added some lines of code. After commenting them out everything was fine again, but these lines where never called before the error. Also, commenting out some old line fixed the problem. Ok, I disabled the watchdog to figure out, what the program is doing, but guess what - yes, everything worked fine. So I replaced the watchdog code by code writing to SFRs of some unused peripherals, same amount of code, same timing, and the error occured again. Stopping the device now also led to the ADC interrupt. But this time the application was *very* slow, a heartbeat LED, normaly lit for something between 100ms and 200ms, now was lit for about 30s.

Ok, both times I did a workaround which at least seems to work, but I never found the reason for the error, so I can't be sure that it will not happen again. And now, in the hope of getting some hint, I'm posting here.

For those who are still interested, some technical data:

- I'm using all 3 ADCs,

- triggered by timer 1 with a frequency of 10kHz,

- only the injected conversion is used.

- ADC clock is 12MHz

- Core clock is 72MHZ

- ADC1 sampling 3 channels with sampling times of 28.5, 28.5, and 239.5 ADC clock cycles, overall conversion time 334 (27.8us)

- ADC2 and ADC3 each samling 4 channels with sampling times of 3 * 7.5 and 239.5 ADC clock cycles, overall converion time 312 (26us)

- after I first encountered the error, I changed the sampling time for the last channel of ADC2 and ADC3 to 71.5 clock cycles (sum: 144, 12us)

- I implemented some cod to measure the time used by the ADC interrupt using timer 4, running with the core clock frequency

- the interrupt is generated by ADC1

- at the beginning the ADC interrupt waits for the other ADCs

Times measured the first time (using gcc 4.1.1, in core clock cycles, values rounded):

- when everything was ok: whole interrupt: min: 1050 (14.6us) max: 4100 (56.9us) waiting for ADCs: min: 30 ( 0.24us) max: 32 ( 0.26us)

- when the error occured: whole interrupt: min: 4030 (56.0us) max: 10100 (140.3us) waiting for ADCs: min: 3000 (41.7us) max: 6050 (84.0us) The second time (using gcc 4.3.3, in core clock cycles):

- when everything was ok: whole interrupt: min: 1042 (14.5us) max: 3554 (49.4us) waiting for ADCs: min: 30 ( 0.24us) max: 32 ( 0.26us)

- when the error occured: whole interrupt: min: 4662 (64.8us) max: 9352 (129.9us) waiting for ADCs: min: 3620 (50.3us) max: 5932 (82.4us)

The only thing I can ascertain out of these numbers is, that the additional time is spent waiting for ADC2. I check the ADCs configuration, they where always ok.

Some code: void init1_ADCs(void) { // ADC1 ADC1->CR1 = 0x00000180; // scan mode, interrupt injected on ADC1->CR2 = 0x00808000; // temp sensor on, // start inj. group with ext. trigger ADC1->SMPR1 = 0x001C0000; // sample times ADC1->SMPR2 = 0x006C0000; ADC1->JOFR1 = 0x00008000; // offsets ADC1->JSQR = 0x00281CC0; // sampling sequence

// ADC2 ADC2->CR1 = 0x00000100; // scan mode ADC2->CR2 = 0x00808000; // temp sensor on, // start inj. group with ext. trigger ADC2->SMPR1 = 0x00000E00; // sample times ADC2->SMPR2 = 0x00000000; ADC2->JOFR1 = 0x00000800 + offset1; // offsets ADC2->JOFR2 = 0x00000800 + offset2; ADC2->JOFR3 = 0x00000800 + offset3; ADC2->JSQR = 0x0036B16A; // sampling sequence

// ADC3 ADC3->CR1 = 0x00000100; // scan mode ADC3->CR2 = 0x00808000; // temp sensor on // start inj. group with ext. trigger ADC3->SMPR1 = 0x00000000; // sample times ADC3->SMPR2 = 0x00000E00; ADC3->JOFR1 = 0x00000800 + offset4; // offsets ADC3->JOFR2 = 0x00000800 + offset5; ADC3->JOFR3 = 0x00000800 + offset6; ADC3->JSQR = 0x00318820; // sampling sequence }

// switch ADCs on and calibrate void enable_ADCs(void) { ADC1->CR2 |= ADC_CR2_ADON; ADC1->CR2 |= ADC_CR2_CAL; ADC2->CR2 |= ADC_CR2_ADON; ADC2->CR2 |= ADC_CR2_CAL; ADC3->CR2 |= ADC_CR2_ADON; ADC3->CR2 |= ADC_CR2_CAL; while(ADC1->CR2 & ADC_CR2_CAL) { } while(ADC2->CR2 & ADC_CR2_CAL) { } while(ADC3->CR2 & ADC_CR2_CAL) { } }

void adc_irq(void) { u16 te;

TIM4->PSC = 0; // for time measurement TIM4->CNT = 0; TIM4->CR1 = 1;

while((ADC2->SR & ADC_SR_JEOC) == 0) { } // TIM4->CR1 = 0; // activated to measure time for waiting on ADC2 while((ADC3->SR & ADC_SR_JEOC) == 0) { } ADC1->SR = 0x00000000; // resetting flags ADC2->SR = 0x00000000; ADC3->SR = 0x00000000; NVIC->ICPR[0] |= 0x00040000;

/* skipped lots of calculation stuff */

TIM4->CR1 = 0; // activated to measure time of whole interrupt te = TIM4->CNT; if(te > sums->time) sums->maxtime = te; if(te < sums->time) sums->mintime = te; }

The workarounds: Due to the findings during debugging it looks like the error occures after ADC interrupts could not be serviced for some reason.

So in the first case I just deactivated the ADC interrupt and timer 1 before erasing the flash page and reenabled them afterwards. I also decreased the sampling time for the 4th channel of ADCs 2 and 3. But this probably doesn't do the trick, because the error occured again.

In the second case ADCs and timer were enabled before initialising variables and so long before enabling the interrupts. Now ADCs and timer are enabled just after the interrupts.

Thanks in advance for any hint realy solving the problem.

By, Mike

Reply to
Mike Kaufmann
Loading thread data ...

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.