Skip to content

Commit

Permalink
Merge pull request #1505 from stevew817/feature/new/fast_i2c
Browse files Browse the repository at this point in the history
[Silicon Labs] Allow faster I2C baudrates
  • Loading branch information
0xc0170 committed Jan 15, 2016
2 parents 170003c + 22c246c commit fa45092
Showing 1 changed file with 27 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
I2CName i2c_scl = (I2CName) pinmap_peripheral(scl, PinMap_I2C_SCL);
obj->i2c.i2c = (I2C_TypeDef*) pinmap_merge(i2c_sda, i2c_scl);
MBED_ASSERT(((int) obj->i2c.i2c) != NC);

/* You need both SDA and SCL for I2C, so configuring one of them to NC is illegal */
MBED_ASSERT((uint32_t)sda != (uint32_t)NC);
MBED_ASSERT((uint32_t)scl != (uint32_t)NC);

/* Enable clock for the peripheral */
CMU_ClockEnable(i2c_get_clock(obj), true);
Expand All @@ -132,6 +136,8 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
#endif

/* Set up the pins for I2C use */
/* Note: Set up pins in higher drive strength to reduce slew rate */
/* Though this requires user knowledge, since drive strength is controlled per port, not pin */
pin_mode(scl, WiredAndPullUp);
pin_mode(sda, WiredAndPullUp);

Expand Down Expand Up @@ -192,7 +198,23 @@ void i2c_frequency(i2c_t *obj, int hz)
{
/* Set frequency. As the second argument is 0,
* HFPER clock frequency is used as reference freq */
I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
if (hz <= 0) return;
/* In I2C Normal mode (50% duty), we can go up to 100kHz */
if (hz <= 100000) {
I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
}
/* In I2C Fast mode (6:3 ratio), we can go up to 400kHz */
else if (hz <= 400000) {
I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRAsymetric);
}
/* In I2C Fast+ mode (11:6 ratio), we can go up to 1 MHz */
else if (hz <= 1000000) {
I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRFast);
}
/* Cap requested frequency at 1MHz */
else {
I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, 1000000, i2cClockHLRFast);
}
}

/* Creates a start condition on the I2C bus */
Expand Down Expand Up @@ -352,11 +374,15 @@ int block_and_wait_for_ack(I2C_TypeDef *i2c)
void i2c_slave_mode(i2c_t *obj, int enable_slave)
{
if(enable_slave) {
/* Reference manual note: DIV must be set to 1 during slave operation */
obj->i2c.i2c->CLKDIV = 1;
obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
} else {
obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
/* function is only called with enable_slave = false through i2c_init(..), so frequency is
already guaranteed to be set */
}
}

Expand Down

0 comments on commit fa45092

Please sign in to comment.