Page 1 of 1

STM32 - ADC Callback not invoked

Posted: Thu Aug 01, 2019 12:08 pm
by fpolicastrese
Hi to all, I'm new in the forum.

I need help using the ADCConversionGroup and ADC HAL for the STM32F303VCT microcontroller.

My target is to acquire from analog input IN10, and sample in dual mode(ADC1 master, ADC2 slave) interleaved, with a total of 140*2 sample, naturally through DMA..

I have configured the group for the ADC1, in this manner:

Code: Select all

/*
 * ADC conversion group.
 * Mode:        single, NUM_SAMPLE=2 samples of 1 channels, interleaved, SW triggered.
 * Channels:    IN10
 */
static const ADCConversionGroup adcgrpcfg =   {
   FALSE,
   NUM_CHANNELS,
   adcCallback,
   adcErrorCallback,
   ADC_CFGR_RES_12BITS,                   /* CFGR     */
   ADC_TR(0, 4095),                      /* TR1      */
   ADC_CCR_DELAY(7) | ADC_CCR_DUAL(7),          /* CCR      */
   {                                 /* SMPR[2]  */
      0,
      ADC_SMPR2_SMP_AN10(ADC_SMPR_SMP_1P5),
   },
   {                                 /* SQR[4]   */
      ADC_SQR1_SQ1_N(ADC_CHANNEL_IN10),       /* SQR[0]   */
      0,                           /* SQR[1]   */
      0,                           /* SQR[2]   */
      0                           /* SQR[3]   */
   },
   {                                 /* SSMPR[2]  */
      0,
      ADC_SMPR2_SMP_AN10(ADC_SMPR_SMP_1P5),
   },
   {                                 /* SSQR[4]  */
      ADC_SQR1_SQ1_N(ADC_CHANNEL_IN10),
      0,
      0,
      0
   }
};


ADC callback function:

Code: Select all

/*
 * ADC streaming callback.
 * la priorità dell'interrupt da trigger è più alta di quella dell'ADC
 * in questo modo può partire una nuova acquisizione anche durante
 * l'elaborazione di quella precedente, una volta che quella corrente è completata
 */
static void adcCallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {

   (void)adcp;
   (void)n;

   // ping pong buffer
   if (buffer == samplesA){
      samples = samplesB;
   }
   else{
      samples = samplesA;
   }

   // riabilito il trigger ADC, da questo momento potrà partire
   // un'altra acquizione sull'altro buffer, durante l'elaborazione
   chSysLockFromIsr();
   adcStopConversionI(&ADCD1);
   extChannelEnableI(&EXTD1, 6);
   chSysUnlockFromIsr();

   //my handling of data in..
   energyEventPush(calculateEnergy((dualAdcSample_t *)buffer));

}


After config.. I call:

Code: Select all

void daqInit(void) {
   daqError = 0;

   //inizializzo puntatori per la coda
   eventFill = 0, eventRet = 0;

   /*
    * Setting up analog inputs used by the RaMonA.
    */
   palSetGroupMode(GPIOF, PAL_PORT_BIT(2),
                   0, PAL_MODE_INPUT_ANALOG);


   /*
    * Activates the ADC1 driver
    */
   adcStart(&ADCD1, NULL);
   chThdSleepMilliseconds(500);

   
}


And in the end the ADC is invoked from:

Code: Select all

/*
 * External Trigger Interrupt.
 * @brief:
 * Evento di trigger per iniziare l'acquisizone
 * la priorità dell'interrupt da trigger è più alta di quella dell'ADC
 * in questo modo può partire una nuova acquisizione anche durante
 * l'elaborazione di quella precedente
 *
 */
void daqExtTrigger(EXTDriver *extp, expchannel_t channel) {

   (void)extp;
   (void)channel;

   // disabilito il trigger
   chSysLockFromIsr();
   
   //attenzione avviare prima l'ADC e poi disabilitare il trigger è un rischio calcolato
   adcStartConversionI(&ADCD1, &adcgrpcfg, samples, BUF_DEPTH);            //BUF_DEPTH = 140 campioni per ogni ADC
                                                   //in totale 280 campioni (dual mode)
   extChannelDisableI(&EXTD1, 6);
   chSysUnlockFromIsr();

}


When the ext trigger go in the function daqExtTrigger(...) and invoke adcStartConversionI(...), the callback function adcCallback(...) not is invoked.
Where is the problem, naturally, first I have enable in mcuconf.h:

Code: Select all

/*
 * ADC driver system settings.
 */
#define STM32_ADC_USE_ADC1                  TRUE
#define STM32_ADC_USE_ADC3                  TRUE
#define STM32_ADC_ADC12_DMA_PRIORITY        3
#define STM32_ADC_ADC34_DMA_PRIORITY        2
#define STM32_ADC_ADC12_IRQ_PRIORITY        5
#define STM32_ADC_ADC34_IRQ_PRIORITY        5
#define STM32_ADC_ADC12_DMA_IRQ_PRIORITY    5
#define STM32_ADC_ADC34_DMA_IRQ_PRIORITY    5
#define STM32_ADC_ADC12_CLOCK_MODE          ADC_CCR_CKMODE_ADCCK    //ADC_CCR_CKMODE_AHB_DIV1
#define STM32_ADC_ADC34_CLOCK_MODE          ADC_CCR_CKMODE_ADCCK   //ADC_CCR_CKMODE_AHB_DIV4

#define STM32_ADC_DUAL_MODE                 TRUE


Another info regarding ChibiOS, this project is created with 2.6.9 version and Eclipse LUNA.

Please, someone can help me?
Thanks in advance.

Best regards.
Francesco.

Re: STM32 - ADC Callback not invoked

Posted: Thu Aug 01, 2019 12:12 pm
by Giovanni
Hi,

Very old version, you should really update.

Have you tested the F3 ADC demo? there is an ADC callback in there.

Giovanni

Re: STM32 - ADC Callback not invoked

Posted: Thu Aug 01, 2019 12:51 pm
by fpolicastrese
Hi Giovanni, thanks a lot for your reply.
In this project I also use STM32_ADC_USE_ADC3, and the callback work correctly... see code.

In the previous code, do you see a problem?
For the ADC12, the clock source is 72/4=18 MHz, is too speed?
Any suggest?

Thanks in advance.
Regards.

Francesco.


Code: Select all

/*
 * ADC streaming callback.
 */
static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
   (void)adcp;
   (void)n;

   // put here in structure
   sensors.analog_pressure = (buffer[1]  * 2500 / 4095);
   sensors.pcb_temp        = (buffer[2]  * 2500 / 4095);

   //NOTE: (voltage divider by 2 and ADC reference to 2,5V)
   //battery goes from
   //Full Charge    4,2V --> 3440 digit  to
   //Critical level 3,58V --> 2928 digit
   //an interval of 512 digit
   if (buffer[0] <= 2928) {
      sensors.v_batt = 0;
      return;
   }

   sensors.v_batt = (buffer[0] - 2928)/64;
}

static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
  (void)adcp;
  (void)err;
}


/*
 * ADC conversion group.
 * Mode:        Continuous, 3 samples of 3 channels, SW triggered.
 * Channels:    IN2, IN14, IN16 --> VBATT, PRESSURE, PCB_TEMP
 */
static const ADCConversionGroup slow_adcgrpcfg =
{
   FALSE,                     /* Enables the circular buffer mode for the group */
   4,                        /* number of channel */
   adccallback,
   adcerrorcallback,
   ADC_CFGR_RES_12BITS,         /* CFGR    */
   ADC_TR(0, 4095),             /* TR1     */
   0,                         /* CCR     */
   {    /* SMPR[2] */
      ADC_SMPR1_SMP_AN2(ADC_SMPR_SMP_61P5),
      ADC_SMPR2_SMP_AN14(ADC_SMPR_SMP_61P5) |
      ADC_SMPR2_SMP_AN16(ADC_SMPR_SMP_61P5),
   },
   {  /* SQR[4]  */
      ADC_SQR1_SQ1_N(ADC_CHANNEL_IN2)|
      ADC_SQR1_SQ2_N(ADC_CHANNEL_IN14) |
      ADC_SQR1_SQ3_N(ADC_CHANNEL_IN16) |
      ADC_SQR1_SQ4_N(ADC_CHANNEL_IN17),
      0,
      0,
      0
   },
};

Re: STM32 - ADC Callback not invoked

Posted: Thu Aug 01, 2019 12:57 pm
by Giovanni
It should work unless you hit a bug fixed in later versions which is quite possible considering you are using something 5+ years old...

Giovanni

Re: STM32 - ADC Callback not invoked

Posted: Thu Aug 01, 2019 2:59 pm
by fpolicastrese
Hi Giovanni.

The project is too complex, migrating to the new ChibiOS would take up too much time.
Do I do other tests, can we update ourselves tomorrow or later?

Thanks a lot.

Ragards.
Francesco.

Re: STM32 - ADC Callback not invoked

Posted: Fri Aug 02, 2019 9:16 am
by mikeprotts
It's probably worth migrating, it's not easy but will make things simpler in future. I upgraded from 3 to 18, and it wasn't too painful.

Can you test without slave ADC, which would simplify debugging.

Mike

Re: STM32 - ADC Callback not invoked

Posted: Tue Aug 06, 2019 4:26 pm
by fpolicastrese
Hi Mike, thanks for your reply.

These days, I investigated.
If I start the ADC12 group, in "single conversion mode"(see the CFGR register):

Code: Select all

        ...   
   FALSE,
   NUM_CHANNELS,
   adcCallback,
   adcErrorCallback,
   ADC_CFGR_RES_12BITS,             /* CFGR     */
   ADC_TR(0, 4095),                /* TR1      */
   ADC_CCR_DELAY(7) | ADC_CCR_DUAL(7),  /* CCR      */
   ...


the end adc callback function is not called.

But, if I set it to "continuous conversion mode"(see the CFGR register):

Code: Select all


        ...   
   FALSE,
   NUM_CHANNELS,
   adcCallback,
   adcErrorCallback,
   ADC_CFGR_RES_12BITS | ADC_CFGR_CONT,    /* CFGR     */
   ADC_TR(0, 4095),                   /* TR1      */
   ADC_CCR_DELAY(7) | ADC_CCR_DUAL(7),       /* CCR      */
   ...



the callback is called. I do not understand..
In any case, I need to invoke ADC12 in single conversion mode.

I continue to investigate in the LLD etc. etc.

Best regards.
Francesco