Page 1 of 1

How to properly activate the analog watchdog

Posted: Sun Apr 16, 2017 12:08 pm
by rreignier
Hello,

I have tried to use the analog watchdog on a STM32F303K8, so it uses the ADCv3 driver.
I have managed to use it by setting the AWD1EN bit of the CFGR register manually.
Either with :

Code: Select all

adcStartConversion(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
ADCD1.adcm->CFGR |= ADC_CFGR_AWD1EN;

Or with a ChibiOS define:

Code: Select all

adcStartConversion(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
ADCD1.adcm->CFGR |= ADC_CFGR_AWD1_ALL;

So it works but I wonder if there is a nicer way to do it without having to manipulate directly the configuration registers?

A simple example application:

Code: Select all

#include "ch.h"
#include "hal.h"

#include "chprintf.h"
static BaseSequentialStream* serial = (BaseSequentialStream*)&SD2;

#define ADC_GRP1_NUM_CHANNELS 2
#define ADC_GRP1_BUF_DEPTH 1
static adcsample_t samples[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];

static void adccallback(ADCDriver* adcp, adcsample_t* buffer, size_t n)
{
  (void)adcp;
  (void)buffer;
  (void)n;
}

bool watchdogTriggered = false;
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
{
  if(adcp == &ADCD1 && err == ADC_ERR_AWD1)
  {
    watchdogTriggered = true;
  }
}

static const ADCConversionGroup adcgrpcfg = {
  TRUE,
  ADC_GRP1_NUM_CHANNELS,
  adccallback,
  adcerrorcallback,
  ADC_CFGR_CONT, /* CFGR */
  ADC_TR(0, 3000), /* TR1 */
  {
    /* SMPR[2] */
    0,
    ADC_SMPR2_SMP_AN11(ADC_SMPR_SMP_601P5) |
      ADC_SMPR2_SMP_AN12(ADC_SMPR_SMP_601P5),
  },
  {
    /* SQR[4]  */
    ADC_SQR1_SQ1_N(ADC_CHANNEL_IN11) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN12),
    0,
    0,
    0
  }
};

int main(void)
{
  halInit();
  chSysInit();

  // Setting up analog inputs.
  palSetGroupMode(
    GPIOB, PAL_PORT_BIT(0) | PAL_PORT_BIT(1), 0, PAL_MODE_INPUT_ANALOG);

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

  // Activate Serial Driver
  sdStart(&SD2, NULL);

  // Starts an ADC continuous conversion.
  adcStartConversion(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
  // Activate the analog Watchdog
  //ADCD1.adcm->CFGR |= ADC_CFGR_AWD1_ALL;
  ADCD1.adcm->CFGR |= ADC_CFGR_AWD1EN;

  chprintf(serial, "Test program of the analog watchdog.\n");

  while(true)
  {
    chprintf(serial, "IN11 = %u IN12 = %u\n", samples[0], samples[1]);
    if(watchdogTriggered)
    {
      chprintf(serial, "Analog Watchdog Triggered!\n");

      // Handle the error...
      chThdSleepMilliseconds(500);

      // Start the conversion again
      watchdogTriggered = false;
      adcStartConversion(&ADCD1, &adcgrpcfg, samples, ADC_GRP1_BUF_DEPTH);
      // Activatye the analog watchdog
      ADCD1.adcm->CFGR |= ADC_CFGR_AWD1_ALL;

    }
    chThdSleepMilliseconds(200);
  }
}


Thanks

Re: How to properly activate the analog watchdog

Posted: Sun Apr 16, 2017 1:07 pm
by rreignier
Actually, I have just realized that it is only needed to add the ADC_CFGR_AWD1_ALL flag in the ADCConversionGroup structure!
So something like that do the job:

Code: Select all

static const ADCConversionGroup adcgrpcfg = {
  TRUE,
  ADC_GRP1_NUM_CHANNELS,
  adccallback,
  adcerrorcallback,
  ADC_CFGR_CONT | ADC_CFGR_AWD1_ALL, /* CFGR */
  ADC_TR(0, 3000), /* TR1 */
  {
    /* SMPR[2] */
    0,
    ADC_SMPR2_SMP_AN11(ADC_SMPR_SMP_601P5) |
      ADC_SMPR2_SMP_AN12(ADC_SMPR_SMP_601P5),
  },
  {
    /* SQR[4]  */
    ADC_SQR1_SQ1_N(ADC_CHANNEL_IN11) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN12),
    0,
    0,
    0
  }
};


Sorry for the disturbance. But I hope that it could help someone else in the future :)