aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/stm32f1/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple/stm32f1/i2c.c')
-rw-r--r--libmaple/stm32f1/i2c.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/libmaple/stm32f1/i2c.c b/libmaple/stm32f1/i2c.c
index 4e918ad..4c9af30 100644
--- a/libmaple/stm32f1/i2c.c
+++ b/libmaple/stm32f1/i2c.c
@@ -110,3 +110,39 @@ void _i2c_irq_priority_fixup(i2c_dev *dev) {
nvic_irq_set_priority(dev->ev_nvic_line, 0);
nvic_irq_set_priority(dev->er_nvic_line, 0);
}
+
+void _i2c_set_ccr_trise(i2c_dev *dev, uint32 flags) {
+#define I2C_CLK (STM32_PCLK1/1000000)
+ uint32 ccr = 0;
+ uint32 trise = 0;
+
+ /* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */
+ i2c_set_input_clk(dev, I2C_CLK);
+
+ if (flags & I2C_FAST_MODE) {
+ ccr |= I2C_CCR_FS;
+
+ if (flags & I2C_DUTY_16_9) {
+ /* Tlow/Thigh = 16/9 */
+ ccr |= I2C_CCR_DUTY;
+ ccr |= STM32_PCLK1/(400000 * 25);
+ } else {
+ /* Tlow/Thigh = 2 */
+ ccr |= STM32_PCLK1/(400000 * 3);
+ }
+
+ trise = (300 * (I2C_CLK)/1000) + 1;
+ } else {
+ /* Tlow/Thigh = 1 */
+ ccr = STM32_PCLK1/(100000 * 2);
+ trise = I2C_CLK + 1;
+ }
+
+ /* Set minimum required value if CCR < 1*/
+ if ((ccr & I2C_CCR_CCR) == 0) {
+ ccr |= 0x1;
+ }
+
+ i2c_set_clk_control(dev, ccr);
+ i2c_set_trise(dev, trise);
+}