예제 #1
0
/**
 * \internal Sets configuration to module
 *
 * \param[out] module  Pointer to software module structure
 * \param[in]  config  Configuration structure with configurations to set
 *
 * \return Status of setting configuration.
 * \retval STATUS_OK                       Module was configured correctly
 * \retval STATUS_ERR_ALREADY_INITIALIZED  If setting other GCLK generator than
 *                                         previously set
 */
static enum status_code _i2c_slave_set_config(
		struct i2c_slave_module *const module,
		const struct i2c_slave_config *const config)
{
	uint32_t tmp_ctrla;

	/* Sanity check arguments. */
	Assert(module);
	Assert(module->hw);
	Assert(config);

	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
	Sercom *const sercom_hw = module->hw;

	module->buffer_timeout = config->buffer_timeout;

	struct system_pinmux_config pin_conf;
	system_pinmux_get_config_defaults(&pin_conf);

	uint32_t pad0 = config->pinmux_pad0;
	uint32_t pad1 = config->pinmux_pad1;

	/* SERCOM PAD0 - SDA */
	if (pad0 == PINMUX_DEFAULT) {
		pad0 = _sercom_get_default_pad(sercom_hw, 0);
	}
	pin_conf.mux_position = pad0 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);

	/* SERCOM PAD1 - SCL */
	if (pad1 == PINMUX_DEFAULT) {
		pad1 = _sercom_get_default_pad(sercom_hw, 1);
	}
	pin_conf.mux_position = pad1 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);

	/* Prepare config to write to register CTRLA */
	if (config->run_in_standby || system_is_debugger_present()) {
		tmp_ctrla = SERCOM_I2CS_CTRLA_RUNSTDBY;
	} else {
		tmp_ctrla = 0;
	}

	tmp_ctrla |= config->sda_hold_time |
			(config->scl_low_timeout << SERCOM_I2CS_CTRLA_LOWTOUT_Pos);

	i2c_hw->CTRLA.reg |= tmp_ctrla;

	/* Set CTRLB configuration */
	i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN | config->address_mode;

	i2c_hw->ADDR.reg = config->address << SERCOM_I2CS_ADDR_ADDR_Pos |
			config->address_mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos |
			config->enable_general_call_address << SERCOM_I2CS_ADDR_GENCEN_Pos;

	return STATUS_OK;
}
예제 #2
0
/**
 * \internal Sets configuration to module
 *
 * \param[out] module  Pointer to software module structure
 * \param[in]  config  Configuration structure with configurations to set
 *
 * \return Status of setting configuration.
 * \retval STATUS_OK                       Module was configured correctly
 * \retval STATUS_ERR_ALREADY_INITIALIZED  If setting other GCLK generator than
 *                                         previously set
 */
static enum status_code _i2c_slave_set_config(
		struct i2c_slave_module *const module,
		const struct i2c_slave_config *const config)
{
	/* Sanity check arguments. */
	Assert(module);
	Assert(module->hw);
	Assert(config);

	SercomI2cs *const i2c_hw = &(module->hw->I2CS);
	Sercom *const sercom_hw = module->hw;

	module->buffer_timeout = config->buffer_timeout;

	struct system_pinmux_config pin_conf;
	system_pinmux_get_config_defaults(&pin_conf);

	uint32_t pad0 = config->pinmux_pad0;
	uint32_t pad1 = config->pinmux_pad1;

	/* SERCOM PAD0 - SDA */
	if (pad0 == PINMUX_DEFAULT) {
		pad0 = _sercom_get_default_pad(sercom_hw, 0);
	}
	pin_conf.mux_position = pad0 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);

	/* SERCOM PAD1 - SCL */
	if (pad1 == PINMUX_DEFAULT) {
		pad1 = _sercom_get_default_pad(sercom_hw, 1);
	}
	pin_conf.mux_position = pad1 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);

	/* Write config to register CTRLA */
	i2c_hw->CTRLA.reg |= (uint32_t)(config->sda_hold_time |
			config->transfer_speed |
			(config->scl_low_timeout << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos) |
			(config->scl_stretch_only_after_ack_bit << SERCOM_I2CS_CTRLA_SCLSM_Pos) |
			(config->slave_scl_low_extend_timeout << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos) |
			(config->run_in_standby << SERCOM_I2CS_CTRLA_RUNSTDBY_Pos));

	/* Set CTRLB configuration */
	i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_SMEN | config->address_mode;

	i2c_hw->ADDR.reg = config->address << SERCOM_I2CS_ADDR_ADDR_Pos |
			config->address_mask << SERCOM_I2CS_ADDR_ADDRMASK_Pos |
			config->enable_general_call_address << SERCOM_I2CS_ADDR_GENCEN_Pos;

	return STATUS_OK;
}
예제 #3
0
파일: spi.c 프로젝트: AndreyMostovov/asf
/**
 * \internal Writes an SPI SERCOM configuration to the hardware module.
 *
 * This function will write out a given configuration to the hardware module.
 * Can only be done when the module is disabled.
 *
 * \param[in]  module  Pointer to the software instance struct
 * \param[in]  config  Pointer to the configuration struct
 *
 * \return The status of the configuration
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided.
 * \retval STATUS_OK               If the configuration was written
 */
static enum status_code _spi_set_config(
		struct spi_module *const module,
		const struct spi_config *const config)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(config);
	Assert(module->hw);

	SercomSpi *const spi_module = &(module->hw->SPI);
	Sercom *const hw = module->hw;

	struct system_pinmux_config pin_conf;
	system_pinmux_get_config_defaults(&pin_conf);
	pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;

	uint32_t pad_pinmuxes[] = {
			config->pinmux_pad0, config->pinmux_pad1,
			config->pinmux_pad2, config->pinmux_pad3
		};

	/* Configure the SERCOM pins according to the user configuration */
	for (uint8_t pad = 0; pad < 4; pad++) {
		uint32_t current_pinmux = pad_pinmuxes[pad];

		if (current_pinmux == PINMUX_DEFAULT) {
			current_pinmux = _sercom_get_default_pad(hw, pad);
		}

		if (current_pinmux != PINMUX_UNUSED) {
			pin_conf.mux_position = current_pinmux & 0xFFFF;
			system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
		}
	}
예제 #4
0
/**
 * \brief Pin MUX configuration helper
 *
 * \param[in] pinmux Pin MUX setting to apply. Special values:
 * \arg \c PINMUX_UNUSED to do nothing.
 * \arg \c PINMUX_DEFAULT to use default pin MUX for the SERCOM pad.
 * \param[in] sercom,padnum SERCOM pad specification, for \ref PINMUX_DEFAULT.
 */
static inline void _spi_master_vec_pinmux_helper(uint32_t pinmux,
		Sercom *const sercom, uint8_t padnum)
{
	struct system_pinmux_config pin_conf;

	if (pinmux == PINMUX_DEFAULT) {
		pinmux = _sercom_get_default_pad(sercom, padnum);
	}

	if (pinmux == PINMUX_UNUSED) {
		return;
	}

	system_pinmux_get_config_defaults(&pin_conf);
	pin_conf.mux_position = pinmux & 0xFFFF;
	system_pinmux_pin_set_config(pinmux >> 16, &pin_conf);
};
예제 #5
0
/**
 * \internal Sets configurations to module
 *
 * \param[out] module  Pointer to software module structure.
 * \param[in]  config  Configuration structure with configurations to set.
 *
 * \return Status of setting configuration.
 * \retval STATUS_OK                        If module was configured correctly
 * \retval STATUS_ERR_ALREADY_INITIALIZED   If setting other GCLK generator than
 *                                          previously set
 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE  If given baud rate is not compatible
 *                                          with set GCLK frequency
 */
static enum status_code _i2c_master_set_config(
		struct i2c_master_module *const module,
		const struct i2c_master_config *const config)
{
	/* Sanity check arguments. */
	Assert(module);
	Assert(module->hw);
	Assert(config);

	/* Temporary variables. */
	uint32_t tmp_ctrla;
	int32_t tmp_baud;
	enum status_code tmp_status_code = STATUS_OK;

	SercomI2cm *const i2c_module = &(module->hw->I2CM);
	Sercom *const sercom_hw = module->hw;

	uint8_t sercom_index = _sercom_get_sercom_inst_index(sercom_hw);

	/* Pin configuration */

	uint32_t pad0 = config->pinmux_pad0;
	uint32_t pad1 = config->pinmux_pad1;

	/* SERCOM PAD0 - SDA */
	if (pad0 == PINMUX_DEFAULT) {
		pad0 = _sercom_get_default_pad(sercom_hw, 0);
	}
	system_pinmux_pin_set_config(pad0 >> 16,
                                     pad0 & 0xFFFF,
                                     SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK,
                                     SYSTEM_PINMUX_PIN_PULL_UP,
                                     false);

	/* SERCOM PAD1 - SCL */
	if (pad1 == PINMUX_DEFAULT) {
		pad1 = _sercom_get_default_pad(sercom_hw, 1);
	}
	system_pinmux_pin_set_config(pad1 >> 16,
                                     pad1 & 0xFFFF,
                                     SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK,
                                     SYSTEM_PINMUX_PIN_PULL_UP,
                                     false);


	/* Save timeout on unknown bus state in software module. */
	module->unknown_bus_state_timeout = config->unknown_bus_state_timeout;

	/* Save timeout on buffer write. */
	module->buffer_timeout = config->buffer_timeout;

	/* Set whether module should run in standby. */
	if (config->run_in_standby || system_is_debugger_present()) {
		tmp_ctrla = SERCOM_I2CM_CTRLA_RUNSTDBY;
	} else {
		tmp_ctrla = 0;
	}

	/* Check and set start data hold timeout. */
	if (config->start_hold_time != I2C_MASTER_START_HOLD_TIME_DISABLED) {
		tmp_ctrla |= config->start_hold_time;
	}

	/* Check and set SCL low timeout. */
	if (config->scl_low_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_LOWTOUT;
	}

	/* Check and set inactive bus timeout. */
	if (config->inactive_timeout != I2C_MASTER_INACTIVE_TIMEOUT_DISABLED) {
		tmp_ctrla |= config->inactive_timeout;
	}

	/* Write config to register CTRLA. */
	i2c_module->CTRLA.reg |= tmp_ctrla;

	/* Set configurations in CTRLB. */
	i2c_module->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;

	/* Find and set baudrate. */
	tmp_baud = (int32_t)(system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index) /
                             (2000*(config->baud_rate)) - 5);

	/* Check that baud rate is supported at current speed. */
	if (tmp_baud > 255 || tmp_baud < 0) {
		/* Baud rate not supported. */
		tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
	} else {
		/* Baud rate acceptable. */
		i2c_module->BAUD.reg = (uint8_t)tmp_baud;
	}

	return tmp_status_code;
}
예제 #6
0
파일: usart.c 프로젝트: Wiredhome/mbed
/**
 * \brief Initializes the device
 *
 * Initializes the USART device based on the setting specified in the
 * configuration struct.
 *
 * \param[out] module  Pointer to USART device
 * \param[in]  hw      Pointer to USART hardware instance
 * \param[in]  config  Pointer to configuration struct
 *
 * \return Status of the initialization.
 *
 * \retval STATUS_OK                       The initialization was successful
 * \retval STATUS_BUSY                     The USART module is busy
 *                                         resetting
 * \retval STATUS_ERR_DENIED               The USART have not been disabled in
 *                                         advance of initialization
 * \retval STATUS_ERR_INVALID_ARG          The configuration struct contains
 *                                         invalid configuration
 * \retval STATUS_ERR_ALREADY_INITIALIZED  The SERCOM instance has already been
 *                                         initialized with different clock
 *                                         configuration
 * \retval STATUS_ERR_BAUD_UNAVAILABLE     The BAUD rate given by the
 *                                         configuration
 *                                         struct cannot be reached with
 *                                         the current clock configuration
 */
enum status_code usart_init(
    struct usart_module *const module,
    Sercom *const hw,
    const struct usart_config *const config)
{
    /* Sanity check arguments */
    Assert(module);
    Assert(hw);
    Assert(config);

    enum status_code status_code = STATUS_OK;

    /* Assign module pointer to software instance struct */
    module->hw = hw;

    /* Get a pointer to the hardware module instance */
    SercomUsart *const usart_hw = &(module->hw->USART);

    uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
#if (SAML21)
    uint32_t pm_index     = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
#else
    uint32_t pm_index     = sercom_index + PM_APBCMASK_SERCOM0_Pos;
#endif
    uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;

    if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
        /* The module is busy resetting itself */
        return STATUS_BUSY;
    }

    if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
        /* Check the module is enabled */
        return STATUS_ERR_DENIED;
    }

    /* Turn on module in PM */
    system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);

    /* Set up the GCLK for the module */
    struct system_gclk_chan_config gclk_chan_conf;
    system_gclk_chan_get_config_defaults(&gclk_chan_conf);
    gclk_chan_conf.source_generator = config->generator_source;
    system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
    system_gclk_chan_enable(gclk_index);
    sercom_set_gclk_generator(config->generator_source, false);

    /* Set character size */
    module->character_size = config->character_size;

    /* Set transmitter and receiver status */
    module->receiver_enabled = config->receiver_enable;
    module->transmitter_enabled = config->transmitter_enable;

#ifdef FEATURE_USART_LIN_SLAVE
    module->lin_slave_enabled = config->lin_slave_enable;
#endif
#ifdef FEATURE_USART_START_FRAME_DECTION
    module->start_frame_detection_enabled = config->start_frame_detection_enable;
#endif
    /* Set configuration according to the config struct */
    status_code = _usart_set_config(module, config);
    if(status_code != STATUS_OK) {
        return status_code;
    }

    struct system_pinmux_config pin_conf;
    system_pinmux_get_config_defaults(&pin_conf);
    pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
    pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;

    uint32_t pad_pinmuxes[] = {
        config->pinmux_pad0, config->pinmux_pad1,
        config->pinmux_pad2, config->pinmux_pad3
    };

    /* Configure the SERCOM pins according to the user configuration */
    for (uint8_t pad = 0; pad < 4; pad++) {
        uint32_t current_pinmux = pad_pinmuxes[pad];

        if (current_pinmux == PINMUX_DEFAULT) {
            current_pinmux = _sercom_get_default_pad(hw, pad);
        }

        if (current_pinmux != PINMUX_UNUSED) {
            pin_conf.mux_position = current_pinmux & 0xFFFF;
            system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
        }
    }
예제 #7
0
파일: dbg_print.c 프로젝트: marekr/asf
/**
 * \brief Initialize and enable debug UART
 *
 * This function sets up the configured SERCOM with the following static
 * features:
 * - asynchronous, internally clocked (UART)
 * - TX only
 * - 1 stop bit
 * - 8-bit data
 * - LSB first
 * - no parity bit
 *
 * The baud rate, SERCOM signal MUX and pin MUX are set up as configured in
 * \ref conf_debug_print.h, which also contains the configuration of which
 * SERCOM to use.
 *
 * The SERCOM UART is left enabled after this function call.
 *
 * \return Indication whether or not initialization succeeded.
 * \retval STATUS_OK if initialization was successful.
 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE if configured baud rate is too high.
 *
 * \note This function is based on \ref usart_init() from ASF, but is modified
 * to use a single instance in order to reduce code size.
 */
enum status_code dbg_init(void)
{
	enum status_code status = STATUS_OK;
	Sercom *const sercom = CONF_DBG_PRINT_SERCOM;
	struct system_gclk_chan_config gclk_chan_conf;
	struct system_pinmux_config pin_conf;
	uint16_t baud;
	uint32_t sercom_index, pm_index, gclk_index;

#if defined(__FREERTOS__) || defined(__DOXYGEN__)
	dbg_is_free = xSemaphoreCreateMutex();
	vSemaphoreCreateBinary(requested_space_is_free);
	xSemaphoreTake(requested_space_is_free, 0);
#else
	requested_space_is_free = false;
#endif

	// Get required indexes
	sercom_index = _sercom_get_sercom_inst_index(sercom);
	pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
	gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;

	// Turn on module in PM
	system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);

	// Set up the GCLK for the module
	system_gclk_chan_get_config_defaults(&gclk_chan_conf);
	gclk_chan_conf.source_generator = CONF_DBG_PRINT_GCLK_SOURCE;
	system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
	system_gclk_chan_enable(gclk_index);
	sercom_set_gclk_generator(CONF_DBG_PRINT_GCLK_SOURCE, false);

#if defined(CONF_DBG_PRINT_BAUD_VALUE)
	baud = CONF_DBG_PRINT_BAUD_VALUE;
#else
	// Compute baud rate, if it is achievable
	status = _sercom_get_async_baud_val(CONF_DBG_PRINT_BAUD_RATE,
			system_gclk_chan_get_hz(gclk_index), &baud);
	if (status != STATUS_OK) {
		return status;
	}
#endif

	sercom_uart->BAUD.reg = baud;
	sercom_uart->CTRLB.reg = SERCOM_USART_CTRLB_TXEN;
	sercom_uart->CTRLA.reg = SERCOM_USART_CTRLA_MODE_USART_INT_CLK
			| SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_ENABLE
			| CONF_DBG_PRINT_SERCOM_MUX | (system_is_debugger_present() ?
					SERCOM_USART_CTRLA_RUNSTDBY : 0);

	// Set up the pin MUXes
	system_pinmux_get_config_defaults(&pin_conf);
	pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
	uint32_t pad_pinmuxes[] = {
			CONF_DBG_PRINT_PINMUX_PAD0,
			CONF_DBG_PRINT_PINMUX_PAD1,
			CONF_DBG_PRINT_PINMUX_PAD2,
			CONF_DBG_PRINT_PINMUX_PAD3,
		};

	for (uint8_t pad = 0; pad < 4; pad++) {
		uint32_t current_pinmux = pad_pinmuxes[pad];

		if (current_pinmux == PINMUX_DEFAULT) {
			current_pinmux = _sercom_get_default_pad(sercom, pad);
		}

		if (current_pinmux != PINMUX_UNUSED) {
			pin_conf.mux_position = current_pinmux & 0xFFFF;
			system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
		}
	}
예제 #8
0
파일: i2c_master.c 프로젝트: InSoonPark/asf
/**
 * \internal Sets configurations to module
 *
 * \param[out] module  Pointer to software module structure
 * \param[in]  config  Configuration structure with configurations to set
 *
 * \return Status of setting configuration.
 * \retval STATUS_OK                        If module was configured correctly
 * \retval STATUS_ERR_ALREADY_INITIALIZED   If setting other GCLK generator than
 *                                          previously set
 * \retval STATUS_ERR_BAUDRATE_UNAVAILABLE  If given baudrate is not compatible
 *                                          with set GCLK frequency
 */
static enum status_code _i2c_master_set_config(
		struct i2c_master_module *const module,
		const struct i2c_master_config *const config)
{
	/* Sanity check arguments. */
	Assert(module);
	Assert(module->hw);
	Assert(config);

	/* Temporary variables. */
	uint32_t tmp_ctrla;
	int32_t tmp_baud;
	int32_t tmp_baud_hs;
	enum status_code tmp_status_code = STATUS_OK;

	SercomI2cm *const i2c_module = &(module->hw->I2CM);
	Sercom *const sercom_hw = module->hw;

	uint8_t sercom_index = _sercom_get_sercom_inst_index(sercom_hw);

	/* Pin configuration */
	struct system_pinmux_config pin_conf;
	system_pinmux_get_config_defaults(&pin_conf);

	uint32_t pad0 = config->pinmux_pad0;
	uint32_t pad1 = config->pinmux_pad1;

	/* SERCOM PAD0 - SDA */
	if (pad0 == PINMUX_DEFAULT) {
		pad0 = _sercom_get_default_pad(sercom_hw, 0);
	}
	pin_conf.mux_position = pad0 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad0 >> 16, &pin_conf);

	/* SERCOM PAD1 - SCL */
	if (pad1 == PINMUX_DEFAULT) {
		pad1 = _sercom_get_default_pad(sercom_hw, 1);
	}
	pin_conf.mux_position = pad1 & 0xFFFF;
	pin_conf.direction    = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK;
	system_pinmux_pin_set_config(pad1 >> 16, &pin_conf);

	/* Save timeout on unknown bus state in software module. */
	module->unknown_bus_state_timeout = config->unknown_bus_state_timeout;

	/* Save timeout on buffer write. */
	module->buffer_timeout = config->buffer_timeout;

	/* Set whether module should run in standby. */
	if (config->run_in_standby || system_is_debugger_present()) {
		tmp_ctrla = SERCOM_I2CM_CTRLA_RUNSTDBY;
	} else {
		tmp_ctrla = 0;
	}

	/* Check and set start data hold timeout. */
	if (config->start_hold_time != I2C_MASTER_START_HOLD_TIME_DISABLED) {
		tmp_ctrla |= config->start_hold_time;
	}

	/* Check and set transfer speed */
	tmp_ctrla |= config->transfer_speed;

	/* Check and set SCL low timeout. */
	if (config->scl_low_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_LOWTOUTEN;
	}

	/* Check and set inactive bus timeout. */
	if (config->inactive_timeout != I2C_MASTER_INACTIVE_TIMEOUT_DISABLED) {
		tmp_ctrla |= config->inactive_timeout;
	}

	/* Check and set SCL clock stretch mode. */
	if (config->scl_stretch_only_after_ack_bit) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_SCLSM;
	}

	/* Check and set slave SCL low extend timeout. */
	if (config->slave_scl_low_extend_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_SEXTTOEN;
	}

	/* Check and set master SCL low extend timeout. */
	if (config->master_scl_low_extend_timeout) {
		tmp_ctrla |= SERCOM_I2CM_CTRLA_MEXTTOEN;
	}

	/* Write config to register CTRLA. */
	i2c_module->CTRLA.reg |= tmp_ctrla;

	/* Set configurations in CTRLB. */
	i2c_module->CTRLB.reg = SERCOM_I2CM_CTRLB_SMEN;

	/* Find and set baudrate. */
	tmp_baud = (int32_t)(div_ceil(
				system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index),
				(2000*(config->baud_rate))) - 5);

	/* Check that baudrate is supported at current speed. */
	if (tmp_baud > 255 || tmp_baud < 0) {
		/* Baud rate not supported. */
		tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
	} else {
		/* Find baudrate for high speed */
		tmp_baud_hs = (int32_t)(div_ceil(
				system_gclk_chan_get_hz(SERCOM0_GCLK_ID_CORE + sercom_index),
				(2000*(config->baud_rate_high_speed))) - 1);

		/* Check that baudrate is supported at current speed. */
		if (tmp_baud_hs > 255 || tmp_baud_hs < 0) {
			/* Baud rate not supported. */
			tmp_status_code = STATUS_ERR_BAUDRATE_UNAVAILABLE;
		}
	}
	if (tmp_status_code != STATUS_ERR_BAUDRATE_UNAVAILABLE) {
		/* Baud rate acceptable. */
		i2c_module->BAUD.reg = SERCOM_I2CM_BAUD_BAUD(tmp_baud) |
			SERCOM_I2CM_BAUD_HSBAUD(tmp_baud_hs);
	}

	return tmp_status_code;
}