aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/i2c.c16
-rw-r--r--libmaple/i2c_private.h37
-rw-r--r--libmaple/include/libmaple/i2c_common.h19
-rw-r--r--libmaple/stm32f1/i2c.c28
4 files changed, 77 insertions, 23 deletions
diff --git a/libmaple/i2c.c b/libmaple/i2c.c
index 0e6a64c..3c92bef 100644
--- a/libmaple/i2c.c
+++ b/libmaple/i2c.c
@@ -120,29 +120,29 @@ void i2c_bus_reset(const i2c_dev *dev) {
* Make sure the bus is free by clocking it until any slaves release the
* bus.
*/
- while (!gpio_read_bit(dev->gpio_port, dev->sda_pin)) {
+ while (!gpio_read_bit(sda_port(dev), dev->sda_pin)) {
/* Wait for any clock stretching to finish */
- while (!gpio_read_bit(dev->gpio_port, dev->scl_pin))
+ while (!gpio_read_bit(scl_port(dev), dev->scl_pin))
;
delay_us(10);
/* Pull low */
- gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 0);
delay_us(10);
/* Release high again */
- gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
delay_us(10);
}
/* Generate start then stop condition */
- gpio_write_bit(dev->gpio_port, dev->sda_pin, 0);
+ gpio_write_bit(sda_port(dev), dev->sda_pin, 0);
delay_us(10);
- gpio_write_bit(dev->gpio_port, dev->scl_pin, 0);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 0);
delay_us(10);
- gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
delay_us(10);
- gpio_write_bit(dev->gpio_port, dev->sda_pin, 1);
+ gpio_write_bit(sda_port(dev), dev->sda_pin, 1);
}
/**
diff --git a/libmaple/i2c_private.h b/libmaple/i2c_private.h
index 05a293c..5b79516 100644
--- a/libmaple/i2c_private.h
+++ b/libmaple/i2c_private.h
@@ -27,10 +27,15 @@
#ifndef _LIBMAPLE_I2C_PRIVATE_H_
#define _LIBMAPLE_I2C_PRIVATE_H_
-#define I2C_DEV(num, port, sda, scl) \
+#include <libmaple/i2c_common.h>
+
+/* For old-style definitions (SDA/SCL on same GPIO device) */
+#define I2C_DEV_OLD(num, port, sda, scl) \
{ \
.regs = I2C##num##_BASE, \
.gpio_port = port, \
+ .scl_port = NULL, \
+ .sda_port = NULL, \
.sda_pin = sda, \
.scl_pin = scl, \
.clk_id = RCC_I2C##num, \
@@ -39,9 +44,33 @@
.state = I2C_STATE_DISABLED, \
}
-struct i2c_dev;
-void _i2c_irq_handler(struct i2c_dev *dev);
-void _i2c_irq_error_handler(struct i2c_dev *dev);
+/* For new-style definitions (SDA/SCL may be on different GPIO devices) */
+#define I2C_DEV_NEW(num, sdaport, sdabit, sclport, sclbit) \
+ { \
+ .regs = I2C##num##_BASE, \
+ .gpio_port = NULL, \
+ .scl_port = sclport, \
+ .scl_pin = sclbit, \
+ .sda_port = sdaport, \
+ .sda_pin = sdabit, \
+ .clk_id = RCC_I2C##num, \
+ .ev_nvic_line = NVIC_I2C##num##_EV, \
+ .er_nvic_line = NVIC_I2C##num##_ER, \
+ .state = I2C_STATE_DISABLED, \
+ }
+
+void _i2c_irq_handler(i2c_dev *dev);
+void _i2c_irq_error_handler(i2c_dev *dev);
+
+struct gpio_dev;
+
+static inline struct gpio_dev* scl_port(const i2c_dev *dev) {
+ return (dev->gpio_port == NULL) ? dev->scl_port : dev->gpio_port;
+}
+
+static inline struct gpio_dev* sda_port(const i2c_dev *dev) {
+ return (dev->gpio_port == NULL) ? dev->sda_port : dev->gpio_port;
+}
/* Auxiliary procedure for enabling an I2C peripheral; `flags' as for
* i2c_master_enable(). */
diff --git a/libmaple/include/libmaple/i2c_common.h b/libmaple/include/libmaple/i2c_common.h
index 2f36f80..5d99530 100644
--- a/libmaple/include/libmaple/i2c_common.h
+++ b/libmaple/include/libmaple/i2c_common.h
@@ -65,7 +65,24 @@ typedef struct i2c_dev {
struct i2c_msg *msg; /**< Messages */
uint32 error_flags; /**< Error flags, set on I2C error condition */
volatile uint32 timestamp; /**< For internal use */
- struct gpio_dev *gpio_port; /**< SDA, SCL pins' GPIO port */
+
+ /**
+ * @brief Deprecated. Use .scl_port or .sda_port instead.
+ * If non-null, this will be used as SDA, SCL pins' GPIO port. If
+ * null, then .sda_port will be used for SDA, and .sda_port for
+ * SDA. */
+ struct gpio_dev *gpio_port;
+
+ /**
+ * @brief SDA GPIO device (but see .gpio_port).
+ */
+ struct gpio_dev *sda_port;
+
+ /**
+ * @brief SCL GPIO device (but see .gpio_port).
+ */
+ struct gpio_dev *scl_port;
+
uint16 msgs_left; /**< Messages left */
uint8 sda_pin; /**< SDA bit on gpio_port */
uint8 scl_pin; /**< SCL bit on gpio_port */
diff --git a/libmaple/stm32f1/i2c.c b/libmaple/stm32f1/i2c.c
index 5797940..d864464 100644
--- a/libmaple/stm32f1/i2c.c
+++ b/libmaple/stm32f1/i2c.c
@@ -31,8 +31,8 @@
* Devices
*/
-static i2c_dev i2c1 = I2C_DEV(1, &gpiob, 7, 6);
-static i2c_dev i2c2 = I2C_DEV(2, &gpiob, 11, 10);
+static i2c_dev i2c1 = I2C_DEV_OLD(1, &gpiob, 7, 6);
+static i2c_dev i2c2 = I2C_DEV_OLD(2, &gpiob, 11, 10);
/** STM32F1 I2C device 1 */
i2c_dev* const I2C1 = &i2c1;
@@ -43,20 +43,28 @@ i2c_dev* const I2C2 = &i2c2;
* Routines
*/
+static int i2c1_wants_remap(const i2c_dev *dev) {
+ /* Check if we've got I2C1 configured for SDA/SCL remap on PB9/PB8 */
+ return (dev->clk_id == RCC_I2C1) &&
+ (scl_port(dev)->clk_id == RCC_GPIOB) &&
+ (sda_port(dev)->clk_id == RCC_GPIOB) &&
+ (dev->sda_pin == 9) &&
+ (dev->scl_pin == 8);
+}
+
void i2c_config_gpios(const i2c_dev *dev) {
- if ((dev->clk_id == RCC_I2C1) &&
- (dev->sda_pin == 9) && (dev->scl_pin == 8)) {
+ if (i2c1_wants_remap(dev)) {
afio_remap(AFIO_REMAP_I2C1);
}
- gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_AF_OUTPUT_OD);
- gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_AF_OUTPUT_OD);
+ gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_AF_OUTPUT_OD);
+ gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_AF_OUTPUT_OD);
}
void i2c_master_release_bus(const i2c_dev *dev) {
- gpio_write_bit(dev->gpio_port, dev->scl_pin, 1);
- gpio_write_bit(dev->gpio_port, dev->sda_pin, 1);
- gpio_set_mode(dev->gpio_port, dev->scl_pin, GPIO_OUTPUT_OD);
- gpio_set_mode(dev->gpio_port, dev->sda_pin, GPIO_OUTPUT_OD);
+ gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
+ gpio_write_bit(sda_port(dev), dev->sda_pin, 1);
+ gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_OUTPUT_OD);
+ gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_OUTPUT_OD);
}
/*