aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/i2c.c
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 /libmaple/i2c.c
parent2ffc87ca9b47bd605e5630a33b36f83e5e8486da (diff)
downloadlibrambutan-1d97a8e7c55db7d9d52acefa90f66c19b3908b2d.tar.gz
librambutan-1d97a8e7c55db7d9d52acefa90f66c19b3908b2d.zip
Adding i2c2 and i2c fast mode
Signed-off-by: Anton Eltchaninov <anton.eltchaninov@gmail.com>
Diffstat (limited to 'libmaple/i2c.c')
-rw-r--r--libmaple/i2c.c54
1 files changed, 43 insertions, 11 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);