Take care when you calculate the clock! Freescale engineers, in their infinite wisdom, made a very peculiar clock divider for the i2c.
The value written in the F[ICR] bits is not the actual division factor!
The clock is divided with some other value, which you must look it up in a table in the datasheet, as it can change depending on the part.
Here is a function that will automatically set the best values for the F register, thus giving a working clock.
<code>
void i2c_lld_bus_speed_calc(I2CDriver * i2cp, uint32_t bus_speed, uint32_t module_clk)
{
I2C_F_MUL_Type mul=0;
I2C_F_ICR_Type icr=0;
uint32_t clk=0;
uint32_t bclk=0;
/* start with highest clock */
i2cp->i2c->F=0x00;
/* iterate through multiplier values */
for (mul=0;mul<KINETIS_I2C_MAX_F_MUL_VALUE;mul+=1)
{
/* clock after the multiplier */
clk=module_clk/(1<<mul);
/* iterate through icr values */
for(icr=0; icr<KINETIS_I2C_MAX_F_ICR_VALUE;icr+=1)
{
/* bus clock with current divisors */
bclk=clk/kinetis_i2c_scl_divider[icr];
/* reached target speed ? */
if(bclk<=bus_speed)
{
/* set f register */
i2cp->i2c->F = ( I2C_F_ICR(icr) | I2C_F_MULT(mul) );
/* ready */
return;
}
/* next icr value */
}
/* next mul value */
}
/* Divider calculator will do a best effort calculation.
* If divisor value is too large, then set it to maximum allowed value;
*/
i2cp->i2c->F = I2C_F_ICR_MASK|I2C_F_MULT_MASK;
}
</code>
And these are dependent on the chip type:
<code>
/* data types */
typedef uint16_t I2C_F_ICR_Type;
typedef uint8_t I2C_F_MUL_Type;
/* speed multiplier maximum value */
#define KINETIS_I2C_MAX_F_MUL_VALUE (I2C_F_MULT_MASK>>I2C_F_MULT_SHIFT)
/* scl divider maximum value */
#define KINETIS_I2C_MAX_F_ICR_VALUE (I2C_F_ICR_MASK+1)
/* look up table */
const I2C_F_ICR_Type kinetis_i2c_scl_divider[KINETIS_I2C_MAX_F_ICR_VALUE]=
{
20,22,24,26,28,30,34,40,28,32,36,40,44,48,56,68,48,56,64,72,80,88,104,128,80,96,112,128,144,160,192,240,160,192,224,256,288,320,384,480,320,384,448,512,576,640,768,960,640,768,896,1024,1152,1280,1536,1920,1280,1536,1792,2048,2304,2560,3072,3840
};
</code>