AnsweredAssumed Answered

ADC calibration intermittently freezes

Question asked by dp05 on May 3, 2013
Latest reply on Dec 11, 2013 by Roger Collins

I'm using a modified setup of the ADC from the ch. 11 example of the Kinetis L series peripherals users guide (KLQRUG) to configure a single channel input on the TWR-KL25 platform. I'm running into intermittent unexpected behavior where, as I launch to program through the debug perspective in Codewarrior, it will sometimes freeze during the ADC calibration process. Specifically, it'll freeze a the following while statement in the calibration function (line 11):



uint8 ADC_Cal(ADC_MemMapPtr adcmap)
  unsigned short cal_var;
  ADC_SC2_REG(adcmap) &=  ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process    - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0);   
  ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
  ADC_SC3_REG(adcmap) |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) );  // Turn averaging ON and set at max value ( 32 )
  ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ;      // Start CAL
  while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end
  if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL )
   return(1);    // Check for Calibration fail error and return 
  // Calculate plus-side calibration
  cal_var = 0x00;
  cal_var =  ADC_CLP0_REG(adcmap); 
  cal_var += ADC_CLP1_REG(adcmap);
  cal_var += ADC_CLP2_REG(adcmap);
  cal_var += ADC_CLP3_REG(adcmap);
  cal_var += ADC_CLP4_REG(adcmap);
  cal_var += ADC_CLPS_REG(adcmap);
  cal_var = cal_var/2;
  cal_var |= 0x8000; // Set MSB
  ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
  // Calculate minus-side calibration
  cal_var = 0x00;
  cal_var =  ADC_CLM0_REG(adcmap); 
  cal_var += ADC_CLM1_REG(adcmap);
  cal_var += ADC_CLM2_REG(adcmap);
  cal_var += ADC_CLM3_REG(adcmap);
  cal_var += ADC_CLM4_REG(adcmap);
  cal_var += ADC_CLMS_REG(adcmap);
  cal_var = cal_var/2;
  cal_var |= 0x8000; // Set MSB
  ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var); 
  ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */


This doesn't always happen, and when it does, the only fix that seems to work consistently is to do a full off-on power cycle. Are there any known bugs with the calibration step? If it helps, the general initialization process is:

Clocks and system resources

DMA configuration (for sample transfers to memory)

ADC configuration (including calibration step)

LPTMR (acts as HW trigger to ADC)