aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Eltchaninov <anton.eltchaninov@gmail.com>2011-04-11 18:17:09 +0700
committerAnton Eltchaninov <anton.eltchaninov@gmail.com>2011-04-12 13:21:15 +0700
commit1d97a8e7c55db7d9d52acefa90f66c19b3908b2d (patch)
tree2b9c4aa36a4fd953bbcaa1401ce79925e1aa3408
parent2ffc87ca9b47bd605e5630a33b36f83e5e8486da (diff)
downloadlibrambutan-1d97a8e7c55db7d9d52acefa90f66c19b3908b2d.tar.gz
librambutan-1d97a8e7c55db7d9d52acefa90f66c19b3908b2d.zip
Adding i2c2 and i2c fast mode
Signed-off-by: Anton Eltchaninov <anton.eltchaninov@gmail.com>
-rw-r--r--libmaple/i2c.c54
-rw-r--r--libmaple/i2c.h5
-rw-r--r--libmaple/rcc.c2
-rw-r--r--libmaple/rcc.h2
4 files changed, 48 insertions, 15 deletions
diff --git a/libmaple/i2c.c b/libmaple/i2c.c
index a6638be..efe4dce 100644
--- a/libmaple/i2c.c
+++ b/libmaple/i2c.c
@@ -49,6 +49,19 @@ static i2c_dev i2c_dev1 = {
i2c_dev* const I2C1 = &i2c_dev1;
+static i2c_dev i2c_dev2 = {
+ .regs = I2C2_BASE,
+ .gpio_port = &gpiob,
+ .sda_pin = 11,
+ .scl_pin = 10,
+ .clk_line = RCC_I2C2,
+ .ev_nvic_line = NVIC_I2C2_EV,
+ .er_nvic_line = NVIC_I2C2_ER,
+ .state = I2C_STATE_IDLE
+};
+
+i2c_dev* const I2C2 = &i2c_dev2;
+
struct crumb {
uint32 event;
uint32 sr1;
@@ -140,7 +153,8 @@ static void i2c_irq_handler(i2c_dev *dev) {
* Master transmitter: write first byte to fill shift register.
* We should get another TXE interrupt immediately to fill DR again.
*/
- i2c_write(dev, msg->data[msg->xferred++]);
+ if (msg->length != 1)
+ i2c_write(dev, msg->data[msg->xferred++]);
}
sr1 = sr2 = 0;
}
@@ -243,6 +257,10 @@ void __irq_i2c1_ev(void) {
i2c_irq_handler(&i2c_dev1);
}
+void __irq_i2c2_ev(void) {
+ i2c_irq_handler(&i2c_dev2);
+}
+
static void i2c_irq_error_handler(i2c_dev *dev) {
uint32 sr1 = dev->regs->SR1;
uint32 sr2 = dev->regs->SR2;
@@ -257,6 +275,10 @@ void __irq_i2c1_er(void) {
i2c_irq_error_handler(&i2c_dev1);
}
+void __irq_i2c2_er(void) {
+ i2c_irq_error_handler(&i2c_dev2);
+}
+
static void i2c_bus_reset(const i2c_dev *dev) {
/* Release both lines */
gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
@@ -301,8 +323,11 @@ static void i2c_bus_reset(const i2c_dev *dev) {
* I2C_10BIT_ADDRESSING: Enable 10-bit addressing
*/
void i2c_master_enable(i2c_dev *dev, uint32 flags) {
+#define I2C_CLK (PCLK1/1000000)
#define STANDARD_CCR (PCLK1/(100000*2))
-#define STANDARD_TRISE 37
+#define STANDARD_TRISE (I2C_CLK+1)
+#define FAST_CCR (I2C_CLK/10)
+#define FAST_TRISE ((I2C_CLK*3)/10+1)
/* Reset the bus. Clock out any hung slaves. */
i2c_bus_reset(dev);
@@ -313,17 +338,24 @@ void i2c_master_enable(i2c_dev *dev, uint32 flags) {
gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_AF_OUTPUT_OD);
/* I2C1 and I2C2 are fed from APB1, clocked at 36MHz */
- i2c_set_input_clk(dev, 36);
+ i2c_set_input_clk(dev, I2C_CLK);
- /* 100 khz only for now */
- i2c_set_clk_control(dev, STANDARD_CCR);
+ if(flags & I2C_FAST_MODE) {
- /*
- * Set scl rise time, standard mode for now.
- * Max rise time in standard mode: 1000 ns
- * Max rise time in fast mode: 300ns
- */
- i2c_set_trise(dev, STANDARD_TRISE);
+ /* 400 kHz for fast mode, set DUTY and F/S bits */
+ i2c_set_clk_control(dev, FAST_CCR|I2C_CCR_DUTY|I2C_CCR_FS);
+
+ /* Set scl rise time, max rise time in fast mode: 300ns */
+ i2c_set_trise(dev, FAST_TRISE);
+
+ } else {
+
+ /* 100 kHz for standard mode */
+ i2c_set_clk_control(dev, STANDARD_CCR);
+
+ /* Max rise time in standard mode: 1000 ns */
+ i2c_set_trise(dev, STANDARD_TRISE);
+ }
/* Enable event and buffer interrupts */
nvic_irq_enable(dev->ev_nvic_line);
diff --git a/libmaple/i2c.h b/libmaple/i2c.h
index a17e144..07ee260 100644
--- a/libmaple/i2c.h
+++ b/libmaple/i2c.h
@@ -71,8 +71,8 @@ typedef struct i2c_dev {
i2c_msg *msg;
} i2c_dev;
-
extern i2c_dev* const I2C1;
+extern i2c_dev* const I2C2;
#define I2C1_BASE (i2c_reg_map*)0x40005400
#define I2C2_BASE (i2c_reg_map*)0x40005800
@@ -100,7 +100,8 @@ extern i2c_dev* const I2C1;
#define I2C_CR2_FREQ 0xFFF // Peripheral input frequency
/* Clock control register bits */
-#define I2C_CCR_FS BIT(15) // Master mode selection
+#define I2C_CCR_FS BIT(15) // Fast mode selection
+#define I2C_CCR_DUTY BIT(14) // 16/9 duty ratio
#define I2C_CCR_CCR 0xFFF // Clock control bits
/* Status register 1 bits */
diff --git a/libmaple/rcc.c b/libmaple/rcc.c
index 327e3ad..78abbcf 100644
--- a/libmaple/rcc.c
+++ b/libmaple/rcc.c
@@ -67,6 +67,7 @@ static const struct rcc_dev_info rcc_dev_table[] = {
[RCC_PWR] = { .clk_domain = APB1, .line_num = 28},
[RCC_BKP] = { .clk_domain = APB1, .line_num = 27},
[RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 },
+ [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 },
[RCC_CRC] = { .clk_domain = AHB, .line_num = 6},
[RCC_FLITF] = { .clk_domain = AHB, .line_num = 4},
[RCC_SRAM] = { .clk_domain = AHB, .line_num = 2},
@@ -83,7 +84,6 @@ static const struct rcc_dev_info rcc_dev_table[] = {
[RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 },
[RCC_DAC] = { .clk_domain = APB1, .line_num = 29 },
[RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 },
- [RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 },
[RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 },
#endif
#ifdef STM32_XL_DENSITY
diff --git a/libmaple/rcc.h b/libmaple/rcc.h
index e6fa196..91f77d0 100644
--- a/libmaple/rcc.h
+++ b/libmaple/rcc.h
@@ -449,6 +449,7 @@ typedef enum {
RCC_PWR,
RCC_BKP,
RCC_I2C1,
+ RCC_I2C2,
RCC_CRC,
RCC_FLITF,
RCC_SRAM,
@@ -465,7 +466,6 @@ typedef enum {
RCC_FSMC,
RCC_DAC,
RCC_DMA2,
- RCC_I2C2,
RCC_SDIO,
#endif
#ifdef STM32_XL_DENSITY