Skip to content

Commit

Permalink
Merge pull request #21001 from benpicco/backport/2024.10/cpu/sam0_com…
Browse files Browse the repository at this point in the history
…mon/periph_adc/errata-2.1.6

cpu/sam0_common/periph_adc: add work around for errata 2.1.6 [backport 2024.10]
  • Loading branch information
maribu authored Nov 19, 2024
2 parents a54faa7 + 3b9a36e commit 660a3e6
Showing 1 changed file with 46 additions and 7 deletions.
53 changes: 46 additions & 7 deletions cpu/sam0_common/periph/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,36 @@
*
* @}
*/

#include <stdint.h>
#include "cpu.h"
#include "periph/gpio.h"
#include "periph/adc.h"
#include "periph_conf.h"

#include "macros/utils.h"
#include "mutex.h"
#include "periph/adc.h"
#include "periph/gpio.h"
#include "periph_conf.h"

#if CPU_COMMON_SAMD5X && (ADC_REFCTRL_REFSEL_INTREF == ADC_REF_DEFAULT)
# if MODULE_ZTIMER_USEC || MODULE_ZTIMER_MSEC
# include "ztimer.h"
# else
# include "busy_wait.h"
# endif
#endif

#define ENABLE_DEBUG 0
#include "debug.h"

#ifndef ADC_GCLK_SRC
#define ADC_GCLK_SRC SAM0_GCLK_MAIN
# define ADC_GCLK_SRC SAM0_GCLK_MAIN
#endif

#ifndef ADC_GAIN_FACTOR_DEFAULT
#define ADC_GAIN_FACTOR_DEFAULT (0)
# define ADC_GAIN_FACTOR_DEFAULT (0)
#endif

#ifndef ADC_NEG_INPUT
#define ADC_NEG_INPUT (0)
# define ADC_NEG_INPUT (0)
#endif

/* Prototypes */
Expand Down Expand Up @@ -239,6 +248,36 @@ static int _adc_configure(Adc *dev, adc_res_t res)
/* Enable ADC Module */
dev->CTRLA.reg |= ADC_CTRLA_ENABLE;
_wait_syncbusy(dev);

#if CPU_COMMON_SAMD5X && (ADC_REFCTRL_REFSEL_INTREF == ADC_REF_DEFAULT)
/* From the errata
* > 2.1.6 Internal Bandgap Reference
* > ================================
* >
* > If the internal bandgap voltage reference is selected
* > (REFCTRL.REFSEL = 0x0), ADC conversions may never complete
* > (INTFLAG.RESRDY = 0).
* >
* > Workaround
* > ----------
* >
* > If CTRLA.ONDEMAND = 0: Add a delay of minimum 40 μs between the
* > enable of the ADC (CTRLA.ENABLE) and the start of the first conversion.
* > [...]
*
* We do so using ztimer if used anyway, or busy waiting otherwise.
*/
# if MODULE_ZTIMER_USEC
ztimer_sleep(ZTIMER_USEC, 40);
# elif MODULE_ZTIMER_MSEC
ztimer_sleep(ZTIMER_MSEC, 1);
# else
/* busy_wait_us() is not super accurate. We just wait for twice the
* time to be extra sure the delay is enough. */
busy_wait_us(2 * 40);
# endif
#endif

return 0;
}

Expand Down

0 comments on commit 660a3e6

Please sign in to comment.