mbed library sources
Fork of mbed-src by
Diff: targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/adc/adc_sam_d_r/adc.c
- Revision:
- 613:bc40b8d2aec4
- Parent:
- 612:fba1c7dc54c0
- Child:
- 614:9d86c2ae5de0
--- a/targets/hal/TARGET_Atmel/TARGET_SAM21/drivers/adc/adc_sam_d_r/adc.c Tue Aug 18 15:00:09 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,638 +0,0 @@ -#include "adc.h" - -#if SAMD20 -/* The Die revision D number */ -#define REVISON_D_NUM 3 -#endif - -/** - * \brief Initializes an ADC configuration structure to defaults - * - * Initializes a given ADC configuration struct to a set of known default - * values. This function should be called on any new instance of the - * configuration struct before being modified by the user application. - * - * The default configuration is as follows: - * \li GCLK generator 0 (GCLK main) clock source - * \li 1V from internal bandgap reference - * \li Div 4 clock prescaler - * \li 12 bit resolution - * \li Window monitor disabled - * \li No gain - * \li Positive input on ADC PIN 0 - * \li Negative input on ADC PIN 1 - * \li Averaging disabled - * \li Oversampling disabled - * \li Right adjust data - * \li Single-ended mode - * \li Free running disabled - * \li All events (input and generation) disabled - * \li Sleep operation disabled - * \li No reference compensation - * \li No gain/offset correction - * \li No added sampling time - * \li Pin scan mode disabled - * - * \param[out] config Pointer to configuration struct to initialize to - * default values - */ -void adc_get_config_defaults(struct adc_config *const config) -{ - Assert(config); - config->clock_source = GCLK_GENERATOR_0; - config->reference = ADC_REFERENCE_INT1V; - config->clock_prescaler = ADC_CLOCK_PRESCALER_DIV4; - config->resolution = ADC_RESOLUTION_12BIT; - config->window.window_mode = ADC_WINDOW_MODE_DISABLE; - config->window.window_upper_value = 0; - config->window.window_lower_value = 0; - config->gain_factor = ADC_GAIN_FACTOR_1X; -#if SAMR21 - config->positive_input = ADC_POSITIVE_INPUT_PIN6 ; -#else - config->positive_input = ADC_POSITIVE_INPUT_PIN0 ; -#endif - config->negative_input = ADC_NEGATIVE_INPUT_GND ; - config->accumulate_samples = ADC_ACCUMULATE_DISABLE; - config->divide_result = ADC_DIVIDE_RESULT_DISABLE; - config->left_adjust = false; - config->differential_mode = false; - config->freerunning = false; - config->event_action = ADC_EVENT_ACTION_DISABLED; - config->run_in_standby = false; - config->reference_compensation_enable = false; - config->correction.correction_enable = false; - config->correction.gain_correction = ADC_GAINCORR_RESETVALUE; - config->correction.offset_correction = ADC_OFFSETCORR_RESETVALUE; - config->sample_length = 0; - config->pin_scan.offset_start_scan = 0; - config->pin_scan.inputs_to_scan = 0; -} - -/** - * \brief Sets the ADC window mode - * - * Sets the ADC window mode to a given mode and value range. - * - * \param[in] module_inst Pointer to the ADC software instance struct - * \param[in] window_mode Window monitor mode to set - * \param[in] window_lower_value Lower window monitor threshold value - * \param[in] window_upper_value Upper window monitor threshold value - */ -void adc_set_window_mode( - struct adc_module *const module_inst, - const enum adc_window_mode window_mode, - const int16_t window_lower_value, - const int16_t window_upper_value) -{ - /* Sanity check arguments */ - Assert(module_inst); - Assert(module_inst->hw); - - Adc *const adc_module = module_inst->hw; - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Set window mode */ - adc_module->WINCTRL.reg = window_mode << ADC_WINCTRL_WINMODE_Pos; - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Set lower window monitor threshold value */ - adc_module->WINLT.reg = window_lower_value << ADC_WINLT_WINLT_Pos; - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Set upper window monitor threshold value */ - adc_module->WINUT.reg = window_upper_value << ADC_WINUT_WINUT_Pos; -} - -/** -* \internal Configure MUX settings for the analog pins -* -* This function will set the given ADC input pins -* to the analog function in the pinmux, giving -* the ADC access to the analog signal -* -* \param [in] pin AINxx pin to configure -*/ -static inline void _adc_configure_ain_pin(uint32_t pin) -{ -#define PIN_INVALID_ADC_AIN 0xFFFFUL - - /* Pinmapping table for AINxx -> GPIO pin number */ - const uint32_t pinmapping[] = { -#if (SAMD20E | SAMD21E) - PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5, - PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17, - PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19, -#elif (SAMD20G | SAMD21G) - PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1, - PIN_PB08B_ADC_AIN2, PIN_PB09B_ADC_AIN3, - PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5, - PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17, - PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19, -#elif (SAMD20J | SAMD21J) - PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1, - PIN_PB08B_ADC_AIN2, PIN_PB09B_ADC_AIN3, - PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5, - PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7, - PIN_PB00B_ADC_AIN8, PIN_PB01B_ADC_AIN9, - PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11, - PIN_PB04B_ADC_AIN12, PIN_PB05B_ADC_AIN13, - PIN_PB06B_ADC_AIN14, PIN_PB07B_ADC_AIN15, - PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17, - PIN_PA10B_ADC_AIN18, PIN_PA11B_ADC_AIN19, -#elif SAMR21E - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, -#elif SAMR21G - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA04B_ADC_AIN4, PIN_PA05B_ADC_AIN5, - PIN_PA06B_ADC_AIN6, PIN_PA07B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PB02B_ADC_AIN10, PIN_PB03B_ADC_AIN11, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA08B_ADC_AIN16, PIN_PA09B_ADC_AIN17, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, -#elif (SAMD10C | SAMD11C) - PIN_PA02B_ADC_AIN0, PIN_INVALID_ADC_AIN, - PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, -#elif (SAMD10DS | SAMD11DS) - PIN_PA02B_ADC_AIN0, PIN_INVALID_ADC_AIN, - PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3, - PIN_PA06B_ADC_AIN4, PIN_PA07B_ADC_AIN5, - PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, -#elif (SAMD10DM | SAMD11DM) - PIN_PA02B_ADC_AIN0, PIN_PA03B_ADC_AIN1, - PIN_PA04B_ADC_AIN2, PIN_PA05B_ADC_AIN3, - PIN_PA06B_ADC_AIN4, PIN_PA07B_ADC_AIN5, - PIN_PA14B_ADC_AIN6, PIN_PA15B_ADC_AIN7, - PIN_PA10B_ADC_AIN8, PIN_PA11B_ADC_AIN9, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, - PIN_INVALID_ADC_AIN, PIN_INVALID_ADC_AIN, -#else -# error ADC pin mappings are not defined for this device. -#endif - }; - - uint32_t pin_map_result = PIN_INVALID_ADC_AIN; - - if (pin <= ADC_EXTCHANNEL_MSB) { - pin_map_result = pinmapping[pin >> ADC_INPUTCTRL_MUXPOS_Pos]; - - Assert(pin_map_result != PIN_INVALID_ADC_AIN); - - struct system_pinmux_config config; - system_pinmux_get_config_defaults(&config); - - /* Analog functions are all on MUX setting B */ - config.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE; - config.mux_position = 1; - - system_pinmux_pin_set_config(pin_map_result, &config); - } -} - -/** - * \internal Writes an ADC configuration to the hardware module - * - * Writes out a given ADC module configuration to the hardware module. - * - * \param[out] module_inst Pointer to the ADC software instance struct - * \param[in] config Pointer to configuration struct - * - * \return Status of the configuration procedure - * \retval STATUS_OK The configuration was successful - * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) were provided - */ -static enum status_code _adc_set_config( - struct adc_module *const module_inst, - struct adc_config *const config) -{ - uint8_t adjres = 0; - uint32_t resolution = ADC_RESOLUTION_16BIT; - enum adc_accumulate_samples accumulate = ADC_ACCUMULATE_DISABLE; -#if SAMD20 - uint8_t revision_num = ((REG_DSU_DID & DSU_DID_DIE_Msk) >> DSU_DID_DIE_Pos); -#endif - - /* Get the hardware module pointer */ - Adc *const adc_module = module_inst->hw; - - /* Configure GCLK channel and enable clock */ - struct system_gclk_chan_config gclk_chan_conf; - system_gclk_chan_get_config_defaults(&gclk_chan_conf); - gclk_chan_conf.source_generator = config->clock_source; - system_gclk_chan_set_config(ADC_GCLK_ID, &gclk_chan_conf); - system_gclk_chan_enable(ADC_GCLK_ID); - - /* Setup pinmuxing for analog inputs */ - if (config->pin_scan.inputs_to_scan != 0) { - uint8_t offset = config->pin_scan.offset_start_scan; - uint8_t start_pin = - offset +(uint8_t)config->positive_input; - uint8_t end_pin = - start_pin + config->pin_scan.inputs_to_scan; - - while (start_pin < end_pin) { - _adc_configure_ain_pin((offset % 16)+(uint8_t)config->positive_input); - start_pin++; - offset++; - } - _adc_configure_ain_pin(config->negative_input); - } else { - _adc_configure_ain_pin(config->positive_input); - _adc_configure_ain_pin(config->negative_input); - } - - /* Configure run in standby */ - adc_module->CTRLA.reg = (config->run_in_standby << ADC_CTRLA_RUNSTDBY_Pos); - - /* Configure reference */ - adc_module->REFCTRL.reg = - (config->reference_compensation_enable << ADC_REFCTRL_REFCOMP_Pos) | - (config->reference); - - /* Set adjusting result and number of samples */ - switch (config->resolution) { - - case ADC_RESOLUTION_CUSTOM: - adjres = config->divide_result; - accumulate = config->accumulate_samples; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; - - case ADC_RESOLUTION_13BIT: - /* Increase resolution by 1 bit */ - adjres = ADC_DIVIDE_RESULT_2; - accumulate = ADC_ACCUMULATE_SAMPLES_4; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; - - case ADC_RESOLUTION_14BIT: - /* Increase resolution by 2 bit */ - adjres = ADC_DIVIDE_RESULT_4; - accumulate = ADC_ACCUMULATE_SAMPLES_16; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; -#if SAMD20 - /* See $35.1.8 for ADC errata of SAM D20. - The revisions before D have this issue.*/ - case ADC_RESOLUTION_15BIT: - /* Increase resolution by 3 bit */ - if(revision_num < REVISON_D_NUM) { - adjres = ADC_DIVIDE_RESULT_8; - } else { - adjres = ADC_DIVIDE_RESULT_2; - } - accumulate = ADC_ACCUMULATE_SAMPLES_64; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; - - case ADC_RESOLUTION_16BIT: - if(revision_num < REVISON_D_NUM) { - /* Increase resolution by 4 bit */ - adjres = ADC_DIVIDE_RESULT_16; - } else { - adjres = ADC_DIVIDE_RESULT_DISABLE; - } - accumulate = ADC_ACCUMULATE_SAMPLES_256; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; -#else - case ADC_RESOLUTION_15BIT: - /* Increase resolution by 3 bit */ - adjres = ADC_DIVIDE_RESULT_2; - accumulate = ADC_ACCUMULATE_SAMPLES_64; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; - - case ADC_RESOLUTION_16BIT: - /* Increase resolution by 4 bit */ - adjres = ADC_DIVIDE_RESULT_DISABLE; - accumulate = ADC_ACCUMULATE_SAMPLES_256; - /* 16-bit result register */ - resolution = ADC_RESOLUTION_16BIT; - break; -#endif - case ADC_RESOLUTION_8BIT: - /* 8-bit result register */ - resolution = ADC_RESOLUTION_8BIT; - break; - case ADC_RESOLUTION_10BIT: - /* 10-bit result register */ - resolution = ADC_RESOLUTION_10BIT; - break; - case ADC_RESOLUTION_12BIT: - /* 12-bit result register */ - resolution = ADC_RESOLUTION_12BIT; - break; - - default: - /* Unknown. Abort. */ - return STATUS_ERR_INVALID_ARG; - } - - adc_module->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(adjres) | accumulate; - - /* Check validity of sample length value */ - if (config->sample_length > 63) { - return STATUS_ERR_INVALID_ARG; - } else { - /* Configure sample length */ - adc_module->SAMPCTRL.reg = - (config->sample_length << ADC_SAMPCTRL_SAMPLEN_Pos); - } - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Configure CTRLB */ - adc_module->CTRLB.reg = - config->clock_prescaler | - resolution | - (config->correction.correction_enable << ADC_CTRLB_CORREN_Pos) | - (config->freerunning << ADC_CTRLB_FREERUN_Pos) | - (config->left_adjust << ADC_CTRLB_LEFTADJ_Pos) | - (config->differential_mode << ADC_CTRLB_DIFFMODE_Pos); - - /* Check validity of window thresholds */ - if (config->window.window_mode != ADC_WINDOW_MODE_DISABLE) { - switch (resolution) { - case ADC_RESOLUTION_8BIT: - if (config->differential_mode && - (config->window.window_lower_value > 127 || - config->window.window_lower_value < -128 || - config->window.window_upper_value > 127 || - config->window.window_upper_value < -128)) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } else if (config->window.window_lower_value > 255 || - config->window.window_upper_value > 255) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } - break; - case ADC_RESOLUTION_10BIT: - if (config->differential_mode && - (config->window.window_lower_value > 511 || - config->window.window_lower_value < -512 || - config->window.window_upper_value > 511 || - config->window.window_upper_value > -512)) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } else if (config->window.window_lower_value > 1023 || - config->window.window_upper_value > 1023) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } - break; - case ADC_RESOLUTION_12BIT: - if (config->differential_mode && - (config->window.window_lower_value > 2047 || - config->window.window_lower_value < -2048 || - config->window.window_upper_value > 2047 || - config->window.window_upper_value < -2048)) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } else if (config->window.window_lower_value > 4095 || - config->window.window_upper_value > 4095) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } - break; - case ADC_RESOLUTION_16BIT: - if (config->differential_mode && - (config->window.window_lower_value > 32767 || - config->window.window_lower_value < -32768 || - config->window.window_upper_value > 32767 || - config->window.window_upper_value < -32768)) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } else if (config->window.window_lower_value > 65535 || - config->window.window_upper_value > 65535) { - /* Invalid value */ - return STATUS_ERR_INVALID_ARG; - } - break; - } - } - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Configure window mode */ - adc_module->WINCTRL.reg = config->window.window_mode; - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Configure lower threshold */ - adc_module->WINLT.reg = - config->window.window_lower_value << ADC_WINLT_WINLT_Pos; - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Configure lower threshold */ - adc_module->WINUT.reg = config->window.window_upper_value << - ADC_WINUT_WINUT_Pos; - - uint8_t inputs_to_scan = config->pin_scan.inputs_to_scan; - if (inputs_to_scan > 0) { - /* - * Number of input sources included is the value written to INPUTSCAN - * plus 1. - */ - inputs_to_scan--; - } - - if (inputs_to_scan > (ADC_INPUTCTRL_INPUTSCAN_Msk >> ADC_INPUTCTRL_INPUTSCAN_Pos) || - config->pin_scan.offset_start_scan > (ADC_INPUTCTRL_INPUTOFFSET_Msk >> ADC_INPUTCTRL_INPUTOFFSET_Pos)) { - /* Invalid number of input pins or input offset */ - return STATUS_ERR_INVALID_ARG; - } - - while (adc_is_syncing(module_inst)) { - /* Wait for synchronization */ - } - - /* Configure pin scan mode and positive and negative input pins */ - adc_module->INPUTCTRL.reg = - config->gain_factor | - (config->pin_scan.offset_start_scan << - ADC_INPUTCTRL_INPUTOFFSET_Pos) | - (inputs_to_scan << ADC_INPUTCTRL_INPUTSCAN_Pos) | - config->negative_input | - config->positive_input; - - /* Configure events */ - adc_module->EVCTRL.reg = config->event_action; - - /* Disable all interrupts */ - adc_module->INTENCLR.reg = - (1 << ADC_INTENCLR_SYNCRDY_Pos) | (1 << ADC_INTENCLR_WINMON_Pos) | - (1 << ADC_INTENCLR_OVERRUN_Pos) | (1 << ADC_INTENCLR_RESRDY_Pos); - - if (config->correction.correction_enable) { - /* Make sure gain_correction value is valid */ - if (config->correction.gain_correction > ADC_GAINCORR_GAINCORR_Msk) { - return STATUS_ERR_INVALID_ARG; - } else { - /* Set gain correction value */ - adc_module->GAINCORR.reg = config->correction.gain_correction << - ADC_GAINCORR_GAINCORR_Pos; - } - - /* Make sure offset correction value is valid */ - if (config->correction.offset_correction > 2047 || - config->correction.offset_correction < -2048) { - return STATUS_ERR_INVALID_ARG; - } else { - /* Set offset correction value */ - adc_module->OFFSETCORR.reg = config->correction.offset_correction << - ADC_OFFSETCORR_OFFSETCORR_Pos; - } - } - - /* Load in the fixed device ADC calibration constants */ - adc_module->CALIB.reg = - ADC_CALIB_BIAS_CAL( - (*(uint32_t *)ADC_FUSES_BIASCAL_ADDR >> ADC_FUSES_BIASCAL_Pos) - ) | - ADC_CALIB_LINEARITY_CAL( - (*(uint64_t *)ADC_FUSES_LINEARITY_0_ADDR >> ADC_FUSES_LINEARITY_0_Pos) - ); - - return STATUS_OK; -} - -/** - * \brief Initializes the ADC - * - * Initializes the ADC device struct and the hardware module based on the - * given configuration struct values. - * - * \param[out] module_inst Pointer to the ADC software instance struct - * \param[in] hw Pointer to the ADC module instance - * \param[in] config Pointer to the configuration struct - * - * \return Status of the initialization procedure. - * \retval STATUS_OK The initialization was successful - * \retval STATUS_ERR_INVALID_ARG Invalid argument(s) were provided - * \retval STATUS_BUSY The module is busy with a reset operation - * \retval STATUS_ERR_DENIED The module is enabled - */ -enum status_code adc_init( - struct adc_module *const module_inst, - Adc *hw, - struct adc_config *config) -{ - /* Sanity check arguments */ - Assert(module_inst); - Assert(hw); - Assert(config); - - /* Associate the software module instance with the hardware module */ - module_inst->hw = hw; - - /* Turn on the digital interface clock */ - system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, PM_APBCMASK_ADC); - - if (hw->CTRLA.reg & ADC_CTRLA_SWRST) { - /* We are in the middle of a reset. Abort. */ - return STATUS_BUSY; - } - - if (hw->CTRLA.reg & ADC_CTRLA_ENABLE) { - /* Module must be disabled before initialization. Abort. */ - return STATUS_ERR_DENIED; - } - - /* Store the selected reference for later use */ - module_inst->reference = config->reference; - - /* Make sure bandgap is enabled if requested by the config */ - if (module_inst->reference == ADC_REFERENCE_INT1V) { - system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP); - } - -#if ADC_CALLBACK_MODE == true - for (uint8_t i = 0; i < ADC_CALLBACK_N; i++) { - module_inst->callback[i] = NULL; - }; - - module_inst->registered_callback_mask = 0; - module_inst->enabled_callback_mask = 0; - module_inst->remaining_conversions = 0; - module_inst->job_status = STATUS_OK; - - _adc_instances[0] = module_inst; - - if (config->event_action == ADC_EVENT_ACTION_DISABLED && - !config->freerunning) { - module_inst->software_trigger = true; - } else { - module_inst->software_trigger = false; - } -#endif - - /* Write configuration to module */ - return _adc_set_config(module_inst, config); -}