From f317cf42a8f0078940edeaabcac0df8cc3007ea0 Mon Sep 17 00:00:00 2001 From: Joakim Gebart Date: Sat, 21 Feb 2015 14:31:59 +0100 Subject: [PATCH] kinetis: Add configuration macros for I2C bus speed parameters. --- cpu/kinetis_common/doc.txt | 31 +++++++++++++++++++-------- cpu/kinetis_common/i2c.c | 44 +++++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/cpu/kinetis_common/doc.txt b/cpu/kinetis_common/doc.txt index 2bf6fe4853..12cc405f63 100644 --- a/cpu/kinetis_common/doc.txt +++ b/cpu/kinetis_common/doc.txt @@ -14,7 +14,7 @@ * #define ADC_NUMOF (1U) * #define ADC_0_EN 1 * #define ADC_MAX_CHANNELS 1 - * + * * // ADC 0 configuration * #define ADC_0_DEV ADC0 * #define ADC_0_MODULE_CLOCK CLOCK_CORECLOCK @@ -22,7 +22,7 @@ * #define ADC_0_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_ADC0_MASK)) * #define ADC_0_CLKDIS() (SIM->SCGC6 &= ~(SIM_SCGC6_ADC0_MASK)) * #define ADC_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTE_MASK)) - * + * * #define ADC_0_CH5 11 * #define ADC_0_CH5_PIN 1 * #define ADC_0_CH5_PIN_AF 0 @@ -65,7 +65,20 @@ * #define I2C_CLK (48e6) * #define I2C_0_EN 1 * #define I2C_IRQ_PRIO 1 - * + * + * / * Low (10 kHz): MUL = 4, SCL divider = 2560, total: 10240 * / + * #define KINETIS_I2C_F_ICR_LOW (0x3D) + * #define KINETIS_I2C_F_MULT_LOW (2) + * / * Normal (100 kHz): MUL = 2, SCL divider = 240, total: 480 * / + * #define KINETIS_I2C_F_ICR_NORMAL (0x1F) + * #define KINETIS_I2C_F_MULT_NORMAL (1) + * / * Fast (400 kHz): MUL = 1, SCL divider = 128, total: 128 * / + * #define KINETIS_I2C_F_ICR_FAST (0x17) + * #define KINETIS_I2C_F_MULT_FAST (0) + * / * Fast plus (1000 kHz): MUL = 1, SCL divider = 48, total: 48 * / + * #define KINETIS_I2C_F_ICR_FAST_PLUS (0x10) + * #define KINETIS_I2C_F_MULT_FAST_PLUS (0) + * * // I2C 0 device configuration * #define I2C_0_DEV I2C1 * #define I2C_0_CLKEN() (SIM->SCGC4 |= (SIM_SCGC4_I2C1_MASK)) @@ -91,7 +104,7 @@ * #define PWM_NUMOF (1U) * #define PWM_0_EN 1 * #define PWM_MAX_CHANNELS 2 - * + * * // PWM 0 device configuration * #define PWM_0_DEV FTM0 * #define PWM_0_CHANNELS 2 @@ -100,12 +113,12 @@ * #define PWM_0_CLKDIS() (SIM->SCGC6 &= ~(SIM_SCGC6_FTM0_MASK)) * // PWM 0 pin configuration * #define PWM_0_PORT_CLKEN() (SIM->SCGC5 |= (SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTA_MASK)) - * + * * #define PWM_0_PIN_CH0 4 * #define PWM_0_FTMCHAN_CH0 1 * #define PWM_0_PORT_CH0 PORTA * #define PWM_0_PIN_AF_CH0 3 - * + * * #define PWM_0_PIN_CH1 4 * #define PWM_0_FTMCHAN_CH1 4 * #define PWM_0_PORT_CH1 PORTD @@ -257,7 +270,7 @@ * @defgroup cpu_kinetis_common_timer Kinetis Timer * @ingroup cpu_kinetis_common * @brief Periodic Interrupt Timer (PIT) driver. - * Implementation of riot-os low level timer interface + * Implementation of riot-os low level timer interface * for the Kinetis Periodic Interrupt Timer. * The PIT is a count down timer, in order to use it with riot-os * a count up timer will be simulated. The PIT has four channels, @@ -275,8 +288,8 @@ * #define TIMER_MAX_VALUE (0xffffffff) * #define TIMER_CLOCK CLOCK_CORECLOCK * #define TIMER_CLKEN() (SIM->SCGC6 |= (SIM_SCGC6_PIT_MASK)) - * - * // Timer 0 configuration + * + * // Timer 0 configuration * #define TIMER_0_PRESCALER_CH 0 * #define TIMER_0_COUNTER_CH 1 * #define TIMER_0_ISR isr_pit1 diff --git a/cpu/kinetis_common/i2c.c b/cpu/kinetis_common/i2c.c index 8ba6626e3b..d958e0b75b 100644 --- a/cpu/kinetis_common/i2c.c +++ b/cpu/kinetis_common/i2c.c @@ -78,16 +78,46 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed) PORT_Type *i2c_port; int pin_scl = 0; int pin_sda = 0; + uint32_t baudrate_flags = 0; - /* TODO: read speed configuration */ + /** @todo Kinetis I2C: Add automatic baud rate flags selection function */ + /* + * See the Chapter "I2C divider and hold values": + * Kinetis K60 Reference Manual, section 51.4.1.10, Table 51-41. + * Kinetis MKW2x Reference Manual, section 52.4.1.10, Table 52-41. + * + * baud rate = I2C_module_clock / (mul × ICR) + */ switch (speed) { + case I2C_SPEED_LOW: + baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_LOW) | + I2C_F_ICR(KINETIS_I2C_F_ICR_LOW); + break; + case I2C_SPEED_NORMAL: + baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_NORMAL) | + I2C_F_ICR(KINETIS_I2C_F_ICR_NORMAL); break; case I2C_SPEED_FAST: + baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_FAST) | + I2C_F_ICR(KINETIS_I2C_F_ICR_FAST); + break; + + case I2C_SPEED_FAST_PLUS: + baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_FAST_PLUS) | + I2C_F_ICR(KINETIS_I2C_F_ICR_FAST_PLUS); break; default: + /* + * High speed mode is not supported on Kinetis devices, + * see: https://community.freescale.com/thread/316371 + * + * Hardware allows setting the baud rate high enough but the + * capacitance of the bus and lacking a proper high speed mode SCL + * driver will make the signals go out of spec. + */ return -2; } @@ -113,17 +143,7 @@ int i2c_init_master(i2c_t dev, i2c_speed_t speed) i2c_port->PCR[pin_scl] = I2C_0_PORT_CFG; i2c_port->PCR[pin_sda] = I2C_0_PORT_CFG; - /* - * TODO: Add baud rate selection function - * See the Chapter "I2C divider and hold values": - * Kinetis K60 Reference Manual, section 51.4.1.10, Table 51-41. - * Kinetis MKW2x Reference Manual, section 52.4.1.10, Table 52-41. - * - * baud rate = I2C_module_clock / (mul × ICR) - * - * The assignment below will set baud rate to I2C_module_clock / (240 x 2). - */ - i2c->F = I2C_F_MULT(1) | I2C_F_ICR(0x1f); + i2c->F = baudrate_flags; /* enable i2c-module and interrupt */ i2c->C1 = I2C_C1_IICEN_MASK | I2C_C1_IICIE_MASK | I2C_C1_TXAK_MASK;