Exemplo n.º 1
0
void serial_baud(serial_t *obj, int baudrate)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    MBED_ASSERT((baudrate == 110) || (baudrate == 150) || (baudrate == 300) || (baudrate == 1200) ||
                (baudrate == 2400) || (baudrate == 4800) || (baudrate == 9600) || (baudrate == 19200) || (baudrate == 38400) ||
                (baudrate == 57600) || (baudrate == 115200) || (baudrate == 230400) || (baudrate == 460800) || (baudrate == 921600) );

    struct system_gclk_chan_config gclk_chan_conf;
    uint32_t gclk_index;
    uint16_t baud  = 0;
    uint32_t sercom_index = 0;
    enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
    enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;

    pSERIAL_S(obj)->baudrate = baudrate;
    disable_usart(obj);

    sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj));
#if (SAML21) || (SAMC20) || (SAMC21)
#if (SAML21)
    if (sercom_index == 5) {
        gclk_index   = SERCOM5_GCLK_ID_CORE;
    } else {
        gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
    }
#else
    gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
#endif
#else
    gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
#endif
    gclk_chan_conf.source_generator = GCLK_GENERATOR_0;
    system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
    system_gclk_chan_enable(gclk_index);
    sercom_set_gclk_generator(GCLK_GENERATOR_0, false);

    /* Get baud value from mode and clock */
    _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate, system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);

    /* Wait until synchronization is complete */
    usart_syncing(obj);

    /*Set baud val */
    _USART(obj).BAUD.reg = baud;
    /* Wait until synchronization is complete */
    usart_syncing(obj);

    enable_usart(obj);
}
Exemplo n.º 2
0
Arquivo: spi.c Projeto: InSoonPark/asf
/**
 * \brief Set the baudrate of the SPI module
 *
 * This function will set the baudrate of the SPI module.
 *
 * \param[in]  module  Pointer to the software instance struct
 * \param[in]  baudrate  The baudrate wanted
 *
 * \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
 */
enum status_code spi_set_baudrate(
		struct spi_module *const module,
		uint32_t baudrate)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(baudrate);
	Assert(module->hw);

	/* Value to write to BAUD register */
	uint16_t baud = 0;

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

	/* Disable the module */
	spi_disable(module);

	while (spi_is_syncing(module)) {
		/* Wait until the synchronization is complete */
	}

	/* Find frequency of the internal SERCOMi_GCLK_ID_CORE */
	uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
	uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;
	uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);

	/* Get baud value, based on baudrate and the internal clock frequency */
	enum status_code error_code = _sercom_get_sync_baud_val(
			baudrate, internal_clock, &baud);

	if (error_code != STATUS_OK) {
		/* Baud rate calculation error, return status code */
		return STATUS_ERR_INVALID_ARG;
	}

	spi_module->BAUD.reg = (uint8_t)baud;

	while (spi_is_syncing(module)) {
		/* Wait until the synchronization is complete */
	}

	/* Enable the module */
	spi_enable(module);

	while (spi_is_syncing(module)) {
		/* Wait until the synchronization is complete */
	}

	return STATUS_OK;
}
Exemplo n.º 3
0
/** Configures and starts the DFLL in closed loop mode with the given reference
 *  generator.
 *
 *  \param[in]  source_generator  Reference generator to use for the DFLL
 */
static void init_dfll(
		const enum system_clock_source source_generator)
{
	struct system_gclk_gen_config cpu_clock_conf;
	system_gclk_gen_get_config_defaults(&cpu_clock_conf);
	cpu_clock_conf.output_enable = ENABLE_CPU_CLOCK_OUT;

	/* Switch to OSC8M/OSC16M while the DFLL is being reconfigured */
#if SAML21
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC16M;
#else
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC8M;
#endif
	system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf);

	/* Turn off DFLL before adjusting its configuration */
	system_clock_source_disable(SYSTEM_CLOCK_SOURCE_DFLL);

	/* Configure DFLL reference clock, use raw register write to
	 * force-configure the channel even if the currently selected generator
	 * clock has failed */
#if SAML21
        GCLK->PCHCTRL[SYSCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN(source_generator);      
#else
	GCLK->CLKCTRL.reg =
			GCLK_CLKCTRL_ID(SYSCTRL_GCLK_ID_DFLL48) |
			GCLK_CLKCTRL_GEN(source_generator);
#endif
	system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48);

	/* Configure DFLL */
	struct system_clock_source_dfll_config config_dfll;
	system_clock_source_dfll_get_config_defaults(&config_dfll);
	config_dfll.on_demand = false;
	config_dfll.loop_mode = SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED;
	config_dfll.multiply_factor =
			(48000000UL / system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48));
	system_clock_source_dfll_set_config(&config_dfll);

	/* Restart DFLL */
	system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL);
	while (system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DFLL) == false) {
		/* Wait for DFLL to be stable before switch back */
	}

	/* Switch back to the DFLL as the CPU clock source */
	cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_DFLL;
	system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf);
};
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
/**
 * \internal
 * Set Configuration of the USART module
 */
static enum status_code _usart_set_config(
    struct usart_module *const module,
    const struct usart_config *const config)
{
    /* Sanity check arguments */
    Assert(module);
    Assert(module->hw);

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

    /* Index for generic clock */
    uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
    uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;

    /* Cache new register values to minimize the number of register writes */
    uint32_t ctrla = 0;
    uint32_t ctrlb = 0;
    uint16_t baud  = 0;

    enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
    enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;

#ifdef FEATURE_USART_OVER_SAMPLE
    switch (config->sample_rate) {
        case USART_SAMPLE_RATE_16X_ARITHMETIC:
            mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
            sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
            break;
        case USART_SAMPLE_RATE_8X_ARITHMETIC:
            mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
            sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
            break;
        case USART_SAMPLE_RATE_3X_ARITHMETIC:
            mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
            sample_num = SERCOM_ASYNC_SAMPLE_NUM_3;
            break;
        case USART_SAMPLE_RATE_16X_FRACTIONAL:
            mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
            sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
            break;
        case USART_SAMPLE_RATE_8X_FRACTIONAL:
            mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
            sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
            break;
    }
#endif

    /* Set data order, internal muxing, and clock polarity */
    ctrla = (uint32_t)config->data_order |
            (uint32_t)config->mux_setting |
#ifdef FEATURE_USART_OVER_SAMPLE
            config->sample_adjustment |
            config->sample_rate |
#endif
#ifdef FEATURE_USART_IMMEDIATE_BUFFER_OVERFLOW_NOTIFICATION
            (config->immediate_buffer_overflow_notification << SERCOM_USART_CTRLA_IBON_Pos) |
#endif
            (config->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos);

    enum status_code status_code = STATUS_OK;

    /* Get baud value from mode and clock */
    switch (config->transfer_mode) {
        case USART_TRANSFER_SYNCHRONOUSLY:
            if (!config->use_external_clock) {
                status_code = _sercom_get_sync_baud_val(config->baudrate,
                                                        system_gclk_chan_get_hz(gclk_index), &baud);
            }

            break;

        case USART_TRANSFER_ASYNCHRONOUSLY:
            if (config->use_external_clock) {
                status_code =
                    _sercom_get_async_baud_val(config->baudrate,
                                               config->ext_clock_freq, &baud, mode, sample_num);
            } else {
                status_code =
                    _sercom_get_async_baud_val(config->baudrate,
                                               system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
            }

            break;
    }

    /* Check if calculating the baudrate failed */
    if (status_code != STATUS_OK) {
        /* Abort */
        return status_code;
    }

#ifdef FEATURE_USART_IRDA
    if(config->encoding_format_enable) {
        usart_hw->RXPL.reg = config->receive_pulse_length;
    }
#endif

    /* Wait until synchronization is complete */
    _usart_wait_for_sync(module);

    /*Set baud val */
    usart_hw->BAUD.reg = baud;

    /* Set sample mode */
    ctrla |= config->transfer_mode;

    if (config->use_external_clock == false) {
        ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
    } else {
        ctrla |= SERCOM_USART_CTRLA_MODE(0x0);
    }

    /* Set stopbits, character size and enable transceivers */
    ctrlb = (uint32_t)config->stopbits | (uint32_t)config->character_size |
#ifdef FEATURE_USART_IRDA
            (config->encoding_format_enable << SERCOM_USART_CTRLB_ENC_Pos) |
#endif
#ifdef FEATURE_USART_START_FRAME_DECTION
            (config->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) |
#endif
#ifdef FEATURE_USART_COLLISION_DECTION
            (config->collision_detection_enable << SERCOM_USART_CTRLB_COLDEN_Pos) |
#endif
            (config->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
            (config->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);

    /* Check parity mode bits */
    if (config->parity != USART_PARITY_NONE) {
#ifdef FEATURE_USART_LIN_SLAVE
        if(config->lin_slave_enable) {
            ctrla |= SERCOM_USART_CTRLA_FORM(0x5);
        } else {
            ctrla |= SERCOM_USART_CTRLA_FORM(1);
        }
#else
        ctrla |= SERCOM_USART_CTRLA_FORM(1);
#endif
        ctrlb |= config->parity;
    } else {
#ifdef FEATURE_USART_LIN_SLAVE
        if(config->lin_slave_enable) {
            ctrla |= SERCOM_USART_CTRLA_FORM(0x4);
        } else {
            ctrla |= SERCOM_USART_CTRLA_FORM(0);
        }
#else
        ctrla |= SERCOM_USART_CTRLA_FORM(0);
#endif
    }

    /* Set whether module should run in standby. */
    if (config->run_in_standby || system_is_debugger_present()) {
        ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
    }

    /* Wait until synchronization is complete */
    _usart_wait_for_sync(module);

    /* Write configuration to CTRLB */
    usart_hw->CTRLB.reg = ctrlb;

    /* Wait until synchronization is complete */
    _usart_wait_for_sync(module);

    /* Write configuration to CTRLA */
    usart_hw->CTRLA.reg = ctrla;

    return STATUS_OK;
}
Exemplo n.º 6
0
/**
 * \brief Initialize hardware and driver instance
 *
 * This function configures the clock system for the specified SERCOM module,
 * sets up the related pins and their MUX, initializes the SERCOM in SPI master
 * mode, and prepares the driver instance for operation.
 *
 * \pre \ref system_init() must have been called prior to this function.
 *
 * The SERCOM SPI module is left disabled after initialization, and must be
 * enabled with \ref spi_master_vec_enable() before a transfer can be done.
 *
 * \param[out] module Driver instance to initialize.
 * \param[in,out] sercom SERCOM module to initialize and associate driver
 * instance with.
 * \param[in] config Driver configuration to use.
 *
 * \return Status of initialization.
 * \retval STATUS_OK if initialization succeeded.
 * \retval STATUS_ERR_INVALID_ARG if driver has been misconfigured.
 */
enum status_code spi_master_vec_init(struct spi_master_vec_module *const module,
		Sercom *const sercom, const struct spi_master_vec_config *const config)
{
	Assert(module);
	Assert(sercom);
	Assert(config);

	enum status_code status;
	SercomSpi *const spi_hw = &(sercom->SPI);
	struct system_gclk_chan_config gclk_chan_conf;
	uint16_t tmp_baud;
	uint32_t sercom_index = _sercom_get_sercom_inst_index((Sercom *)spi_hw);
#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || (SAMR30)
	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;
	uint32_t gclk_hz;

	module->sercom = sercom;

	/* Enable clock for the module interface */
	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 = config->gclk_generator;
	system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
	system_gclk_chan_enable(gclk_index);
	sercom_set_gclk_generator(config->gclk_generator, false);

	_spi_master_vec_wait_for_sync(spi_hw);

	/* Set up the SERCOM SPI module as master */
	spi_hw->CTRLA.reg = SERCOM_SPI_CTRLA_MODE(0x3);
	spi_hw->CTRLA.reg |= (uint32_t)config->mux_setting
			| config->transfer_mode
			| config->data_order
			| ((config->run_in_standby || system_is_debugger_present()) ?
					SERCOM_SPI_CTRLA_RUNSTDBY : 0);

	/* Get baud value from configured baudrate and internal clock rate */
	gclk_hz = system_gclk_chan_get_hz(gclk_index);
	status = _sercom_get_sync_baud_val(config->baudrate, gclk_hz, &tmp_baud);

	if (status != STATUS_OK) {
		/* Baud rate calculation error! */
		return STATUS_ERR_INVALID_ARG;
	}

	spi_hw->BAUD.reg = (uint8_t)tmp_baud;

	/* Configure the pin multiplexers */
	_spi_master_vec_pinmux_helper(config->pinmux_pad0, sercom, 0);
	_spi_master_vec_pinmux_helper(config->pinmux_pad3, sercom, 3);

	/* SERCOM PAD1 and PAD2 are used for slave SS.
	 * This is a SPI master driver, so control of slave SS must be left to
	 * the PORT module, i.e., peripheral MUX should not be set for that pin.
	 * DOPO controls which PAD is used for slave SS:
	 * If DOPO is odd, SERCOM_PAD1 is SS: SERCOM_PAD2 can be MUXed.
	 * If DOPO is even, SERCOM_PAD2 is SS: SERCOM_PAD1 can be MUXed.
	 */
	if (config->mux_setting & (1 << SERCOM_SPI_CTRLA_DOPO_Pos)) {
		_spi_master_vec_pinmux_helper(config->pinmux_pad2, sercom, 2);
	} else {
		_spi_master_vec_pinmux_helper(config->pinmux_pad1, sercom, 1);
	}

	/* Initialize our instance and register interrupt handler + data */
	module->rx_bufdesc_ptr = NULL;
	module->tx_bufdesc_ptr = NULL;
	module->direction = SPI_MASTER_VEC_DIRECTION_IDLE;
	module->status = STATUS_OK;
#ifdef CONF_SPI_MASTER_VEC_OS_SUPPORT
	CONF_SPI_MASTER_VEC_CREATE_SEMAPHORE(module->busy_semaphore);
#endif

	_sercom_set_handler(sercom_index, _spi_master_vec_int_handler);
	_sercom_instances[sercom_index] = module;

	return STATUS_OK;
}
Exemplo n.º 7
0
/**
 * \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);
		}
	}
Exemplo n.º 8
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 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;
}
Exemplo n.º 9
0
/**
 * \internal
 * Set Configuration of the USART module
 */
static enum status_code _usart_set_config(
		struct usart_module *const module,
		const struct usart_config *const config)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

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

	/* Index for generic clock */
	uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
	uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;

	/* Cache new register values to minimize the number of register writes */
	uint32_t ctrla = 0;
	uint32_t ctrlb = 0;
#ifdef FEATURE_USART_ISO7816
	uint32_t ctrlc = 0;
#endif
	uint16_t baud  = 0;
	uint32_t transfer_mode;

	enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
	enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;

#ifdef FEATURE_USART_OVER_SAMPLE
	switch (config->sample_rate) {
		case USART_SAMPLE_RATE_16X_ARITHMETIC:
			mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
			sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
			break;
		case USART_SAMPLE_RATE_8X_ARITHMETIC:
			mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
			sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
			break;
		case USART_SAMPLE_RATE_3X_ARITHMETIC:
			mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
			sample_num = SERCOM_ASYNC_SAMPLE_NUM_3;
			break;
		case USART_SAMPLE_RATE_16X_FRACTIONAL:
			mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
			sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
			break;
		case USART_SAMPLE_RATE_8X_FRACTIONAL:
			mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
			sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
			break;
	}
#endif

	/* Set data order, internal muxing, and clock polarity */
	ctrla = (uint32_t)config->data_order |
		(uint32_t)config->mux_setting |
	#ifdef FEATURE_USART_OVER_SAMPLE
		config->sample_adjustment |
		config->sample_rate |
	#endif
	#ifdef FEATURE_USART_IMMEDIATE_BUFFER_OVERFLOW_NOTIFICATION
		(config->immediate_buffer_overflow_notification << SERCOM_USART_CTRLA_IBON_Pos) |
	#endif
		(config->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos);

	enum status_code status_code = STATUS_OK;

	transfer_mode = (uint32_t)config->transfer_mode;
#ifdef FEATURE_USART_ISO7816
	if(config->iso7816_config.enabled) {
		transfer_mode = config->iso7816_config.protocol_t;
	}
#endif
	/* Get baud value from mode and clock */
#ifdef FEATURE_USART_ISO7816
	if(config->iso7816_config.enabled) {
		baud = config->baudrate;
	} else {
#endif
	switch (transfer_mode)
	{
		case USART_TRANSFER_SYNCHRONOUSLY:
			if (!config->use_external_clock) {
				status_code = _sercom_get_sync_baud_val(config->baudrate,
						system_gclk_chan_get_hz(gclk_index), &baud);
			}

			break;

		case USART_TRANSFER_ASYNCHRONOUSLY:
			if (config->use_external_clock) {
				status_code =
						_sercom_get_async_baud_val(config->baudrate,
							config->ext_clock_freq, &baud, mode, sample_num);
			} else {
				status_code =
						_sercom_get_async_baud_val(config->baudrate,
							system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
			}

			break;
	}

	/* Check if calculating the baudrate failed */
	if (status_code != STATUS_OK) {
		/* Abort */
		return status_code;
	}
#ifdef FEATURE_USART_ISO7816
	}
#endif

#ifdef FEATURE_USART_IRDA
	if(config->encoding_format_enable) {
		usart_hw->RXPL.reg = config->receive_pulse_length;
	}
#endif

	/* Wait until synchronization is complete */
	_usart_wait_for_sync(module);

	/*Set baud val */
	usart_hw->BAUD.reg = baud;

	/* Set sample mode */
	ctrla |= transfer_mode;

	if (config->use_external_clock == false) {
		ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
	}
	else {
		ctrla |= SERCOM_USART_CTRLA_MODE(0x0);
	}

	/* Set stopbits and enable transceivers */
	ctrlb =  
		#ifdef FEATURE_USART_IRDA
			(config->encoding_format_enable << SERCOM_USART_CTRLB_ENC_Pos) |
		#endif
		#ifdef FEATURE_USART_START_FRAME_DECTION
			(config->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) |
		#endif
		#ifdef FEATURE_USART_COLLISION_DECTION
			(config->collision_detection_enable << SERCOM_USART_CTRLB_COLDEN_Pos) |
		#endif
			(config->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
			(config->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);

#ifdef FEATURE_USART_ISO7816
	if(config->iso7816_config.enabled) {
		ctrla |= SERCOM_USART_CTRLA_FORM(0x07);
		if (config->iso7816_config.enable_inverse) {
			ctrla |= SERCOM_USART_CTRLA_TXINV | SERCOM_USART_CTRLA_RXINV;
		}
		ctrlb |=  USART_CHARACTER_SIZE_8BIT;
		
		switch(config->iso7816_config.protocol_t) {
			case ISO7816_PROTOCOL_T_0:
				ctrlb |= (uint32_t)config->stopbits;	
				ctrlc |= SERCOM_USART_CTRLC_GTIME(config->iso7816_config.guard_time) | \
						(config->iso7816_config.inhibit_nack) | \
						(config->iso7816_config.successive_recv_nack) | \
						SERCOM_USART_CTRLC_MAXITER(config->iso7816_config.max_iterations);
				break;	
			case ISO7816_PROTOCOL_T_1:
				ctrlb |= USART_STOPBITS_1;
				break;		
		}
	} else {
#endif
	ctrlb |= (uint32_t)config->character_size;
	/* Check parity mode bits */
	if (config->parity != USART_PARITY_NONE) {
		ctrla |= SERCOM_USART_CTRLA_FORM(1);
		ctrlb |= config->parity;
	} else {
#ifdef FEATURE_USART_LIN_SLAVE
		if(config->lin_slave_enable) {
			ctrla |= SERCOM_USART_CTRLA_FORM(0x4);
		} else {
			ctrla |= SERCOM_USART_CTRLA_FORM(0);
		}
#else
		ctrla |= SERCOM_USART_CTRLA_FORM(0);
#endif
	}
#ifdef FEATURE_USART_ISO7816
	}
#endif

#ifdef FEATURE_USART_LIN_MASTER
	usart_hw->CTRLC.reg = ((usart_hw->CTRLC.reg) & SERCOM_USART_CTRLC_GTIME_Msk)
						| config->lin_header_delay
						| config->lin_break_length;

	if (config->lin_node != LIN_INVALID_MODE) {
		ctrla &= ~(SERCOM_USART_CTRLA_FORM(0xf));
		ctrla |= config->lin_node;
	}
#endif

	/* Set whether module should run in standby. */
	if (config->run_in_standby || system_is_debugger_present()) {
		ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
	}

	/* Wait until synchronization is complete */
	_usart_wait_for_sync(module);

	/* Write configuration to CTRLB */
	usart_hw->CTRLB.reg = ctrlb;

	/* Wait until synchronization is complete */
	_usart_wait_for_sync(module);

	/* Write configuration to CTRLA */
	usart_hw->CTRLA.reg = ctrla;

#ifdef FEATURE_USART_RS485
	if ((usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_FORM_Msk) != \
		SERCOM_USART_CTRLA_FORM(0x07)) {
		usart_hw->CTRLC.reg &= ~(SERCOM_USART_CTRLC_GTIME(0x7));
		usart_hw->CTRLC.reg |= SERCOM_USART_CTRLC_GTIME(config->rs485_guard_time);
	}
#endif

#ifdef FEATURE_USART_ISO7816
	if(config->iso7816_config.enabled) {
		_usart_wait_for_sync(module);
		usart_hw->CTRLC.reg = ctrlc;
	}
#endif

	return STATUS_OK;
}
Exemplo n.º 10
0
    uint32_t pad_pinmuxes[] = {
        EXT1_SPI_SERCOM_PINMUX_PAD0, EXT1_SPI_SERCOM_PINMUX_PAD1,
        EXT1_SPI_SERCOM_PINMUX_PAD2, EXT1_SPI_SERCOM_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_UNUSED) {
            pin_conf.mux_position = current_pinmux & 0xFFFF;
            system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
        }
    }

    /* Get baud value, based on baudrate and the internal clock frequency */
    uint32_t internal_clock = system_gclk_chan_get_hz(gclk_index);
    //internal_clock = 8000000;
    error_code = _sercom_get_sync_baud_val(SPI_DEFAULT_BAUD, internal_clock, &baud);
    if (error_code != STATUS_OK) {
        /* Baud rate calculation error */
        return;
    }
    _SPI(obj).BAUD.reg = (uint8_t)baud;

    /* Set MUX setting */
    ctrla |= EXT1_SPI_SERCOM_MUX_SETTING; /* TODO: Change this to appropriate Settings */

    /* Set SPI character size */
    ctrlb |= SERCOM_SPI_CTRLB_CHSIZE(0);

    /* Enable receiver */
Exemplo n.º 11
0
static enum status_code usart_set_config_default(serial_t *obj)
{
    /* Sanity check arguments */
    MBED_ASSERT(obj);
    /* Index for generic clock */
    uint32_t sercom_index = _sercom_get_sercom_inst_index(pUSART_S(obj));
    uint32_t gclk_index   = sercom_index + SERCOM0_GCLK_ID_CORE;

    /* Cache new register values to minimize the number of register writes */
    uint32_t ctrla = 0;
    uint32_t ctrlb = 0;
    uint16_t baud  = 0;

    enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
    enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;

    /* Set data order, internal muxing, and clock polarity */
    ctrla = (uint32_t)USART_DATAORDER_LSB |         // data order
            (uint32_t)pSERIAL_S(obj)->mux_setting;  // mux setting  // clock polarity is not used


    /* Get baud value from mode and clock */
    _sercom_get_async_baud_val(pSERIAL_S(obj)->baudrate,system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);  // for asynchronous transfer mode

    /* Wait until synchronization is complete */
    usart_syncing(obj);

    /*Set baud val */
    _USART(obj).BAUD.reg = baud;

    /* Set sample mode */
    ctrla |= USART_TRANSFER_ASYNCHRONOUSLY;

    /* for disabled external clock source */
    ctrla |= SERCOM_USART_CTRLA_MODE(0x1);

    /* Set stopbits, character size and enable transceivers */
    ctrlb = (uint32_t)pSERIAL_S(obj)->stopbits | (uint32_t)pSERIAL_S(obj)->character_size |
            SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN;  /*transmitter and receiver enable*/
    if (pSERIAL_S(obj)->pins[USART_RX_INDEX] == NC) { /* if pin is NC, have to disable the corresponding transmitter/receiver part */
        ctrlb &= ~SERCOM_USART_CTRLB_RXEN;  /* receiver disable */
    }
    if (pSERIAL_S(obj)->pins[USART_TX_INDEX] == NC) {
        ctrlb &= ~SERCOM_USART_CTRLB_TXEN;  /* transmitter disable  */
    }

    /* Check parity mode bits */
    if (pSERIAL_S(obj)->parity != USART_PARITY_NONE) {
        ctrla |= SERCOM_USART_CTRLA_FORM(1);
        ctrlb |= pSERIAL_S(obj)->parity;
    } else {
        ctrla |= SERCOM_USART_CTRLA_FORM(0);
    }

    /* Wait until synchronization is complete */
    usart_syncing(obj);

    /* Write configuration to CTRLB */
    _USART(obj).CTRLB.reg = ctrlb;

    /* Wait until synchronization is complete */
    usart_syncing(obj);

    /* Write configuration to CTRLA */
    _USART(obj).CTRLA.reg = ctrla;

    return STATUS_OK;
}