Пример #1
0
static void
i2c_init(uint32_t bus, SercomI2cm *si)
{
    static uint8_t have_run_init;
    if (have_run_init & (1<<bus))
        return;
    have_run_init |= 1<<bus;

    // Configure i2c
    si->CTRLA.reg = 0;
    uint32_t areg = (SERCOM_I2CM_CTRLA_LOWTOUTEN
                     | SERCOM_I2CM_CTRLA_INACTOUT(3)
                     | SERCOM_I2CM_STATUS_SEXTTOUT
                     | SERCOM_I2CM_STATUS_MEXTTOUT
                     | SERCOM_I2CM_CTRLA_MODE(5));
    si->CTRLA.reg = areg;
    uint32_t freq = sercom_get_pclock_frequency(bus);
    uint32_t baud = (freq/I2C_FREQ - 10 - freq*TIME_RISE/1000000000) / 2;
    si->BAUD.reg = baud;
    si->CTRLA.reg = areg | SERCOM_I2CM_CTRLA_ENABLE;
    while (si->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_ENABLE)
        ;

    // Go into idle mode
    si->STATUS.reg = SERCOM_I2CM_STATUS_BUSSTATE(1);
    while (si->SYNCBUSY.reg & SERCOM_I2CM_SYNCBUSY_SYSOP)
        ;
}
Пример #2
0
void SERCOM::initMasterWIRE( uint32_t baudrate )
{
    // Initialize the peripheral clock and interruption
    initClockNVIC() ;

    resetWIRE() ;

    // Set master mode and enable SCL Clock Stretch mode (stretch after ACK bit)
    sercom->I2CM.CTRLA.reg =  SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* |
                            SERCOM_I2CM_CTRLA_SCLSM*/ ;

    // Enable Smart mode and Quick Command
    //sercom->I2CM.CTRLB.reg =  SERCOM_I2CM_CTRLB_SMEN /*| SERCOM_I2CM_CTRLB_QCEN*/ ;


    // Enable all interrupts
//  sercom->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ;

    // Synchronous arithmetic baudrate
    sercom->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * baudrate) - 1 ;
}
Пример #3
0
/**
 * \brief Initializes the requested I<SUP>2</SUP>C hardware module
 *
 * Initializes the SERCOM I<SUP>2</SUP>C master device requested and sets the provided
 * software module struct. Run this function before any further use of
 * the driver.
 *
 * \param[out] module  Pointer to software module struct
 * \param[in]  hw      Pointer to the hardware instance
 * \param[in]  config  Pointer to the configuration struct
 *
 * \return Status of initialization.
 * \retval STATUS_OK                        Module initiated correctly
 * \retval STATUS_ERR_DENIED                If module is enabled
 * \retval STATUS_BUSY                      If module is busy resetting
 * \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
 *
 */
enum status_code i2c_master_init(
		struct i2c_master_module *const module,
		Sercom *const hw,
		const struct i2c_master_config *const config)
{
	/* Sanity check arguments. */
	Assert(module);
	Assert(hw);
	Assert(config);

	/* Initialize software module */
	module->hw = hw;

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

	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;

	/* 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);

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

	/* Check if reset is in progress. */
	if (i2c_module->CTRLA.reg & SERCOM_I2CM_CTRLA_SWRST) {
		return STATUS_BUSY;
	}

#if I2C_MASTER_CALLBACK_MODE == true
	/* Get sercom instance index and register callback. */
	uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
	_sercom_set_handler(instance_index, _i2c_master_interrupt_handler);
	_sercom_instances[instance_index] = module;

	/* Initialize values in module. */
	module->registered_callback = 0;
	module->enabled_callback = 0;
	module->buffer_length = 0;
	module->buffer_remaining = 0;

	module->status = STATUS_OK;
	module->buffer = NULL;
#endif

	/* Set sercom module to operate in I2C master mode. */
	i2c_module->CTRLA.reg = SERCOM_I2CM_CTRLA_MODE(0x5);

	/* Set config and return status. */
	return _i2c_master_set_config(module, config);
}