[rtems commit] bsp/stm32f4: Add a simple I2C-driver.

Sebastian Huber sebh at rtems.org
Thu Oct 24 14:23:38 UTC 2013


Module:    rtems
Branch:    master
Commit:    c918737ed3af1491d0ffb883b12a8b70e565d940
Changeset: http://git.rtems.org/rtems/commit/?id=c918737ed3af1491d0ffb883b12a8b70e565d940

Author:    Christian Mauderer <Christian.Mauderer at embedded-brains.de>
Date:      Thu Oct 24 16:26:59 2013 +0200

bsp/stm32f4: Add a simple I2C-driver.

---

 c/src/lib/libbsp/arm/stm32f4/Makefile.am           |    6 +
 c/src/lib/libbsp/arm/stm32f4/configure.ac          |    7 +
 c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c      |   37 +++
 c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c             |  331 ++++++++++++++++++++
 c/src/lib/libbsp/arm/stm32f4/include/i2c.h         |   79 +++++
 c/src/lib/libbsp/arm/stm32f4/include/io.h          |   20 ++
 c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h   |   98 ++++++
 c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h     |    9 +
 c/src/lib/libbsp/arm/stm32f4/preinstall.am         |    8 +
 .../libbsp/arm/stm32f4/startup/start-config-io.c   |   17 +
 10 files changed, 612 insertions(+), 0 deletions(-)

diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am
index e451234..8bdaa5e 100644
--- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am
+++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am
@@ -52,6 +52,8 @@ include_bsp_HEADERS += include/stm32f10xxx_rcc.h
 include_bsp_HEADERS += include/stm32f10xxx_exti.h
 include_bsp_HEADERS += include/stm32f4xxxx_gpio.h
 include_bsp_HEADERS += include/stm32f4xxxx_rcc.h
+include_bsp_HEADERS += include/stm32_i2c.h
+include_bsp_HEADERS += include/i2c.h
 include_bsp_HEADERS += include/stm32_usart.h
 include_bsp_HEADERS += include/io.h
 include_bsp_HEADERS += include/rcc.h
@@ -106,6 +108,10 @@ libbsp_a_SOURCES += ../../shared/console_write.c
 libbsp_a_SOURCES += console/console-config.c
 libbsp_a_SOURCES += console/usart.c
 
+# I2C
+libbsp_a_SOURCES += i2c/i2c.c
+libbsp_a_SOURCES += i2c/i2c-config.c
+
 # Clock
 libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
 libbsp_a_SOURCES += ../shared/armv7m/clock/armv7m-clock-config.c
diff --git a/c/src/lib/libbsp/arm/stm32f4/configure.ac b/c/src/lib/libbsp/arm/stm32f4/configure.ac
index db3175c..0d9b861 100644
--- a/c/src/lib/libbsp/arm/stm32f4/configure.ac
+++ b/c/src/lib/libbsp/arm/stm32f4/configure.ac
@@ -63,6 +63,13 @@ RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_UART_5],[enable UART 5])
 RTEMS_BSPOPTS_SET([STM32F4_ENABLE_USART_6],[*],[])
 RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_USART_6],[enable USART 6])
 
+RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C1],[stm32f1*],[1])
+RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C1],[*],[])
+RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_I2C1],[enable I2C 1])
+
+RTEMS_BSPOPTS_SET([STM32F4_ENABLE_I2C2],[*],[])
+RTEMS_BSPOPTS_HELP([STM32F4_ENABLE_I2C2],[enable I2C 2])
+
 RTEMS_BSP_CLEANUP_OPTIONS(0, 0)
 RTEMS_BSP_LINKCMDS
 
diff --git a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c
new file mode 100644
index 0000000..5853e14
--- /dev/null
+++ b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c-config.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Christian Mauderer.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bspopts.h>
+#include <bsp/i2c.h>
+#include <bsp/irq.h>
+
+#ifdef STM32F4_ENABLE_I2C1
+  static stm32f4_i2c_bus_entry stm32f4_i2c1_entry = {
+    .regs = STM32F4_I2C1,
+    .index = 0,
+    .vector = STM32F4_IRQ_I2C1_EV,
+  };
+
+  stm32f4_i2c_bus_entry *const stm32f4_i2c1 = &stm32f4_i2c1_entry;
+#endif
+
+#ifdef STM32F4_ENABLE_I2C2
+  static stm32f4_i2c_bus_entry stm32f4_i2c2_entry = {
+    .regs = STM32F4_I2C2,
+    .index = 1,
+    .vector = STM32F4_IRQ_I2C2_EV,
+  };
+
+  stm32f4_i2c_bus_entry *const stm32f4_i2c2 = &stm32f4_i2c2_entry;
+#endif
diff --git a/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c
new file mode 100644
index 0000000..631956c
--- /dev/null
+++ b/c/src/lib/libbsp/arm/stm32f4/i2c/i2c.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2013 Christian Mauderer.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/* The I2C-module can not run with libi2c. The reason for this is, that libi2c
+ * needs a possibility to generate a stop condition separately. This controller
+ * wants to generate the condition automatically when sending or receiving data.
+ */
+
+#include <bsp.h>
+#include <bsp/i2c.h>
+#include <bsp/rcc.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <assert.h>
+
+#define RTEMS_STATUS_CHECKS_USE_PRINTK
+
+#include <rtems/status-checks.h>
+
+#define STM32F4_I2C_INITIAL_BITRATE 100000
+
+#define I2C_RW_BIT 0x1
+
+stm32f4_rcc_index i2c_rcc_index [] = {
+  STM32F4_RCC_I2C1,
+  STM32F4_RCC_I2C2,
+};
+
+static stm32f4_rcc_index i2c_get_rcc_index(stm32f4_i2c_bus_entry *e)
+{
+  return i2c_rcc_index [e->index];
+}
+
+static uint32_t i2c_get_pclk(stm32f4_i2c_bus_entry *e)
+{
+  return STM32F4_PCLK1;
+}
+
+rtems_status_code stm32f4_i2c_set_bitrate(
+  stm32f4_i2c_bus_entry *e,
+  uint32_t br
+)
+{
+  volatile stm32f4_i2c *regs = e->regs;
+  uint32_t ccr;
+  uint32_t trise;
+  uint32_t pclk = i2c_get_pclk(e);
+
+  /* Make sure, that the module is disabled */
+  if((regs->cr1 & STM32F4_I2C_CR1_PE) != 0)
+  {
+    return RTEMS_RESOURCE_IN_USE;
+  }
+
+  /* Configure clock control register and rise time register */
+  ccr = regs->ccr;
+  trise = regs->trise;
+
+  if(br <= 100000)
+  {
+    uint32_t ccr_val = pclk / (2 * br);
+    /* according to datasheet, the rise time for standard mode is 1us -> 1MHz */
+    uint32_t trise_val = pclk / 1000000 + 1;
+    trise = STM32F4_I2C_TRISE_SET(trise, trise_val);
+
+    if(ccr_val > STM32F4_I2C_CCR_CCR_MAX)
+    {
+      return RTEMS_INVALID_NUMBER;
+    }
+
+    /* standard mode */
+    ccr &= ~STM32F4_I2C_CCR_FS;
+    ccr = STM32F4_I2C_CCR_CCR_SET(ccr, ccr_val);
+  }
+  else
+  {
+    /* FIXME: Implement speeds 100kHz < f <= 400kHz (fast mode) */
+    return RTEMS_NOT_IMPLEMENTED;
+  }
+
+  regs->ccr = ccr;
+  regs->trise = trise;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static void stm32f4_i2c_handler(void *arg)
+{
+  /* This handler implements the suggested read method from stm32f103xx
+   * reference manual if the handler is not the one with the highest priority */
+  stm32f4_i2c_bus_entry *e = arg;
+  volatile stm32f4_i2c *regs = e->regs;
+  uint32_t sr1 = regs->sr1;
+  uint8_t *data = e->data;
+  uint8_t *last = e->last;
+  bool read = e->read;
+  bool wake_task = false;
+  uint32_t cr1;
+
+  if(sr1 & STM32F4_I2C_SR1_SB) {
+    /* Start condition sent. */
+    regs->dr = e->addr_with_rw;
+  }
+
+  if(read) {
+    size_t len = e->len;
+
+    if(len == 1) {
+      /* special case for one single byte */
+      if(sr1 & STM32F4_I2C_SR1_ADDR) {
+        cr1 = regs->cr1;
+        cr1 &= ~STM32F4_I2C_CR1_ACK;
+        regs->cr1 = cr1;
+
+        /* Read sr2 to clear flag */
+        regs->sr2;
+
+        cr1 = regs->cr1;
+        cr1 |= STM32F4_I2C_CR1_STOP;
+        regs->cr1 = cr1;
+      } else if(sr1 & STM32F4_I2C_SR1_RxNE) {
+        *data = regs->dr;
+        wake_task = true;
+      }
+    } else if (len == 2) {
+      /* special case for two bytes */
+      if(sr1 & STM32F4_I2C_SR1_ADDR) {
+        /* Read sr2 to clear flag */
+        regs->sr2;
+
+        cr1 = regs->cr1;
+        cr1 &= ~STM32F4_I2C_CR1_ACK;
+        regs->cr1 = cr1;
+      } else if(sr1 & STM32F4_I2C_SR1_BTF) {
+        cr1 = regs->cr1;
+        cr1 |= STM32F4_I2C_CR1_STOP;
+        regs->cr1 = cr1;
+
+        *data = regs->dr;
+        ++data;
+        *data = regs->dr;
+        wake_task = true;
+      }
+    } else {
+      /* more than two bytes */
+      if(sr1 & STM32F4_I2C_SR1_ADDR) {
+        /* Read sr2 to clear flag */
+        regs->sr2;
+      } else if(sr1 & STM32F4_I2C_SR1_BTF && data == last - 2) {
+        cr1 = regs->cr1;
+        cr1 &= ~STM32F4_I2C_CR1_ACK;
+        regs->cr1 = cr1;
+
+        *data = regs->dr;
+        ++data;
+
+        cr1 = regs->cr1;
+        cr1 |= STM32F4_I2C_CR1_STOP;
+        regs->cr1 = cr1;
+
+        *data = regs->dr;
+        ++data;
+      } else if((sr1 & STM32F4_I2C_SR1_RxNE) && (data != last - 2)) {
+        *data = regs->dr;
+
+        if(data == last) {
+          wake_task = true;
+        } else {
+          ++data;
+        }
+      }
+    }
+  } else /* write */ {
+    if(sr1 & STM32F4_I2C_SR1_ADDR) {
+      /* Address sent */
+      regs->sr2;
+    }
+
+    if((sr1 & (STM32F4_I2C_SR1_ADDR | STM32F4_I2C_SR1_TxE)) && (data <= last)) {
+      regs->dr = *data;
+      ++data;
+    } else if(sr1 & STM32F4_I2C_SR1_BTF) {
+      uint32_t cr1 = regs->cr1;
+      cr1 |= STM32F4_I2C_CR1_STOP;
+      regs->cr1 = cr1;
+      wake_task = true;
+    }
+  }
+
+  e->data = data;
+
+  if(wake_task) {
+    bsp_interrupt_vector_disable(e->vector);
+    rtems_event_transient_send(e->task_id);
+  }
+}
+
+static rtems_status_code i2c_wait_done(stm32f4_i2c_bus_entry *e)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  bsp_interrupt_vector_enable(e->vector);
+  e->task_id = rtems_task_self();
+  return rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+rtems_status_code stm32f4_i2c_init(stm32f4_i2c_bus_entry *e)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  volatile stm32f4_i2c *regs = e->regs;
+  stm32f4_rcc_index rcc_index = i2c_get_rcc_index(e);
+  uint32_t pclk = i2c_get_pclk(e);
+  uint32_t cr1 = 0;
+  uint32_t cr2 = 0;
+
+  assert(pclk >= 2000000);
+
+  /* Create mutex */
+  sc = rtems_semaphore_create (
+    rtems_build_name ('I', '2', 'C', '1' + e->index),
+    0,
+    RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+    0,
+    &e->mutex
+  );
+  RTEMS_CHECK_SC(sc, "create mutex");
+
+  /* Install interrupt handler and disable this vector */
+  sc = rtems_interrupt_handler_install(
+    e->vector,
+    "I2C",
+    RTEMS_INTERRUPT_UNIQUE,
+    stm32f4_i2c_handler,
+    e
+  );
+  RTEMS_CHECK_SC(sc, "install interrupt handler");
+  bsp_interrupt_vector_disable(e->vector);
+
+  /* Enable module clock */
+  stm32f4_rcc_set_clock(rcc_index, true);
+
+  /* Setup initial bit rate */
+  sc = stm32f4_i2c_set_bitrate(e, STM32F4_I2C_INITIAL_BAUDRATE);
+  RTEMS_CHECK_SC(sc, "set bitrate");
+
+  /* Set config registers */
+  cr2 = regs->cr2;
+  cr2 = STM32F4_I2C_CR2_FREQ_SET(cr2, pclk / 1000000);
+  cr2 |= STM32F4_I2C_CR2_ITEVTEN;
+  cr2 |= STM32F4_I2C_CR2_ITBUFEN;
+  regs->cr2 = cr2;
+
+  cr1 = regs->cr1;
+  cr1 |= STM32F4_I2C_CR1_PE;
+  regs->cr1 = cr1;
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_i2c_process_message(
+  stm32f4_i2c_bus_entry *e,
+  stm32f4_i2c_message *msg
+)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_status_code sc_return = RTEMS_SUCCESSFUL;
+  volatile stm32f4_i2c *regs = e->regs;
+  uint16_t max_7_bit_address = (1 << 7) - 1;
+  uint32_t cr1 = regs->cr1;
+
+  if(msg->addr > max_7_bit_address) {
+    return RTEMS_NOT_IMPLEMENTED;
+  }
+
+  if(msg->len == 0) {
+    return RTEMS_INVALID_SIZE;
+  }
+
+  sc = rtems_semaphore_obtain(e->mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  RTEMS_CHECK_SC(sc, "obtaining mutex");
+
+  e->data = msg->buf;
+  e->last = msg->buf + msg->len - 1;
+  e->len = msg->len;
+
+  e->addr_with_rw = msg->addr << 1;
+  if(msg->read) {
+    e->addr_with_rw |= I2C_RW_BIT;
+  }
+  e->read = msg->read;
+
+  /* Check if no stop is active. */
+  if(cr1 & STM32F4_I2C_CR1_STOP) {
+    return RTEMS_IO_ERROR;
+  }
+
+  /* Start */
+  cr1 = regs->cr1;
+  if(e->len == 2) {
+    cr1 |= STM32F4_I2C_CR1_POS;
+  } else {
+    cr1 &= ~STM32F4_I2C_CR1_POS;
+  }
+  cr1 |= STM32F4_I2C_CR1_ACK;
+  cr1 |= STM32F4_I2C_CR1_START;
+  regs->cr1 = cr1;
+
+  /* Wait for end of message */
+  sc = i2c_wait_done(e);
+
+  if(sc != RTEMS_SUCCESSFUL) {
+    sc_return = sc;
+  }
+
+  sc = rtems_semaphore_release(e->mutex);
+  RTEMS_CHECK_SC(sc, "releasing mutex");
+
+  return sc_return;
+}
+
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/i2c.h b/c/src/lib/libbsp/arm/stm32f4/include/i2c.h
new file mode 100644
index 0000000..d4891c4
--- /dev/null
+++ b/c/src/lib/libbsp/arm/stm32f4/include/i2c.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Christian Mauderer.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+/* The I2C-module can not run with libi2c. The reason for this is, that libi2c
+ * needs a possibility to generate a stop condition separately. This controller
+ * wants to generate the condition automatically when sending or receiving data.
+ */
+
+#ifndef LIBBSP_ARM_STM32F4_I2C_H
+#define LIBBSP_ARM_STM32F4_I2C_H
+
+#include <rtems.h>
+
+#include <bsp/io.h>
+#include <bsp/stm32f4.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct {
+  /* The address of the slave without the read write bit. A 7-Bit address should
+   * be placed in the bits [6..0] */
+  uint16_t addr;
+  /* Read (true) or write (false) data */
+  bool read;
+  /* Size of data to read or write */
+  size_t len;
+  /* Buffer for data */
+  uint8_t *buf;
+} stm32f4_i2c_message;
+
+typedef struct {
+  volatile stm32f4_i2c *regs;
+  size_t index;
+  rtems_vector_number vector;
+  rtems_id mutex;
+  rtems_id task_id;
+  uint8_t *data;
+  uint8_t *last;
+  size_t len;
+  bool read;
+  uint8_t addr_with_rw;
+} stm32f4_i2c_bus_entry;
+
+/* Initialise the i2c module. */
+rtems_status_code stm32f4_i2c_init(stm32f4_i2c_bus_entry *e);
+
+/* Process a i2c message */
+rtems_status_code stm32f4_i2c_process_message(
+  stm32f4_i2c_bus_entry *e,
+  stm32f4_i2c_message *msg
+);
+
+/* Set another baud rate than the default one */
+rtems_status_code stm32f4_i2c_set_bitrate(
+  stm32f4_i2c_bus_entry *e,
+  uint32_t br
+);
+
+extern stm32f4_i2c_bus_entry *const stm32f4_i2c1;
+extern stm32f4_i2c_bus_entry *const stm32f4_i2c2;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_STM32F4_I2C_H */
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/io.h b/c/src/lib/libbsp/arm/stm32f4/include/io.h
index 1d8c512..b97b8c8 100644
--- a/c/src/lib/libbsp/arm/stm32f4/include/io.h
+++ b/c/src/lib/libbsp/arm/stm32f4/include/io.h
@@ -346,6 +346,26 @@ bool stm32f4_gpio_get_input(int pin);
 #define STM32F4_PIN_UART5_TX        STM32F4_PIN_USART_TX(2, 12, STM32F4_GPIO_REMAP_DONT_CHANGE)
 #define STM32F4_PIN_UART5_RX        STM32F4_PIN_USART_RX(3,  2, STM32F4_GPIO_REMAP_DONT_CHANGE)
 
+#define STM32F4_PIN_I2C(port, idx, remapvalue) \
+  { \
+    { \
+      .pin_first = STM32F4_GPIO_PIN(port, idx), \
+      .pin_last = STM32F4_GPIO_PIN(port, idx), \
+      .mode = STM32F4_GPIO_MODE_OUTPUT_2MHz, \
+      .cnf = STM32F4_GPIO_CNF_OUT_AF_OD, \
+      .output = 0, \
+      .remap = remapvalue \
+    } \
+  }
+
+#define STM32F4_PIN_I2C1_SCL_MAP0 STM32F4_PIN_I2C(1, 6, STM32F4_GPIO_REMAP_I2C1_0)
+#define STM32F4_PIN_I2C1_SDA_MAP0 STM32F4_PIN_I2C(1, 7, STM32F4_GPIO_REMAP_I2C1_0)
+#define STM32F4_PIN_I2C1_SCL_MAP1 STM32F4_PIN_I2C(1, 8, STM32F4_GPIO_REMAP_I2C1_1)
+#define STM32F4_PIN_I2C1_SDA_MAP1 STM32F4_PIN_I2C(1, 9, STM32F4_GPIO_REMAP_I2C1_1)
+
+#define STM32F4_PIN_I2C2_SCL      STM32F4_PIN_I2C(1, 10, STM32F4_GPIO_REMAP_DONT_CHANGE)
+#define STM32F4_PIN_I2C2_SDA      STM32F4_PIN_I2C(1, 11, STM32F4_GPIO_REMAP_DONT_CHANGE)
+
 #endif /* STM32F4_FAMILY_F10XXX */
 
 #ifdef __cplusplus
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h
new file mode 100644
index 0000000..68e6941
--- /dev/null
+++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32_i2c.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013 Christian Mauderer.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_STM32F4_STM32_I2C_H
+#define LIBBSP_ARM_STM32F4_STM32_I2C_H
+
+#include <bsp/utility.h>
+
+typedef struct {
+	uint32_t cr1;
+#define STM32F4_I2C_CR1_SWRST BSP_BIT32(15)
+#define STM32F4_I2C_CR1_ALERT BSP_BIT32(13)
+#define STM32F4_I2C_CR1_PEC BSP_BIT32(12)
+#define STM32F4_I2C_CR1_POS BSP_BIT32(11)
+#define STM32F4_I2C_CR1_ACK BSP_BIT32(10)
+#define STM32F4_I2C_CR1_STOP BSP_BIT32(9)
+#define STM32F4_I2C_CR1_START BSP_BIT32(8)
+#define STM32F4_I2C_CR1_NOSTRETCH BSP_BIT32(7)
+#define STM32F4_I2C_CR1_ENGC BSP_BIT32(6)
+#define STM32F4_I2C_CR1_ENPEC BSP_BIT32(5)
+#define STM32F4_I2C_CR1_ENARP BSP_BIT32(4)
+#define STM32F4_I2C_CR1_SMBTYPE BSP_BIT32(3)
+#define STM32F4_I2C_CR1_SMBUS BSP_BIT32(1)
+#define STM32F4_I2C_CR1_PE BSP_BIT32(0)
+	uint32_t cr2;
+#define STM32F4_I2C_CR2_LAST BSP_BIT32(12)
+#define STM32F4_I2C_CR2_DMAEN BSP_BIT32(11)
+#define STM32F4_I2C_CR2_ITBUFEN BSP_BIT32(10)
+#define STM32F4_I2C_CR2_ITEVTEN BSP_BIT32(9)
+#define STM32F4_I2C_CR2_ITERREN BSP_BIT32(8)
+#define STM32F4_I2C_CR2_FREQ(val) BSP_FLD32(val, 0, 5)
+#define STM32F4_I2C_CR2_FREQ_GET(reg) BSP_FLD32GET(reg, 0, 5)
+#define STM32F4_I2C_CR2_FREQ_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5)
+	uint32_t oar1;
+#define STM32F4_I2C_OAR1_ADDMODE BSP_BIT32(15)
+#define STM32F4_I2C_OAR1_ADD(val) BSP_FLD32(val, 0, 9)
+#define STM32F4_I2C_OAR1_ADD_GET(reg) BSP_FLD32GET(reg, 0, 9)
+#define STM32F4_I2C_OAR1_ADD_SET(reg, val) BSP_FLD32SET(reg, val, 0, 9)
+	uint32_t oar2;
+#define STM32F4_I2C_OAR2_ADD2(val) BSP_FLD32(val, 1, 7)
+#define STM32F4_I2C_OAR2_ADD2_GET(reg) BSP_FLD32GET(reg, 1, 7)
+#define STM32F4_I2C_OAR2_ADD2_SET(reg, val) BSP_FLD32SET(reg, val, 1, 7)
+#define STM32F4_I2C_OAR2_ENDUAL BSP_BIT32(0)
+	uint32_t dr;
+#define STM32F4_I2C_DR(val) BSP_FLD32(val, 0, 7)
+#define STM32F4_I2C_DR_GET(reg) BSP_FLD32GET(reg, 0, 7)
+#define STM32F4_I2C_DR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7)
+	uint32_t sr1;
+#define STM32F4_I2C_SR1_SMBALERT BSP_BIT32(15)
+#define STM32F4_I2C_SR1_TIMEOUT BSP_BIT32(14)
+#define STM32F4_I2C_SR1_PECERR BSP_BIT32(12)
+#define STM32F4_I2C_SR1_OVR BSP_BIT32(11)
+#define STM32F4_I2C_SR1_AF BSP_BIT32(10)
+#define STM32F4_I2C_SR1_ARLO BSP_BIT32(9)
+#define STM32F4_I2C_SR1_BERR BSP_BIT32(8)
+#define STM32F4_I2C_SR1_TxE BSP_BIT32(7)
+#define STM32F4_I2C_SR1_RxNE BSP_BIT32(6)
+#define STM32F4_I2C_SR1_STOPF BSP_BIT32(4)
+#define STM32F4_I2C_SR1_ADD10 BSP_BIT32(3)
+#define STM32F4_I2C_SR1_BTF BSP_BIT32(2)
+#define STM32F4_I2C_SR1_ADDR BSP_BIT32(1)
+#define STM32F4_I2C_SR1_SB BSP_BIT32(0)
+	uint32_t sr2;
+#define STM32F4_I2C_SR2_PEC(val) BSP_FLD32(val, 8, 15)
+#define STM32F4_I2C_SR2_PEC_GET(reg) BSP_FLD32GET(reg, 8, 15)
+#define STM32F4_I2C_SR2_PEC_SET(reg, val) BSP_FLD32SET(reg, val, 8, 15)
+#define STM32F4_I2C_SR2_DUALF BSP_BIT32(7)
+#define STM32F4_I2C_SR2_SMBHOST BSP_BIT32(6)
+#define STM32F4_I2C_SR2_SMBDEFAULT BSP_BIT32(5)
+#define STM32F4_I2C_SR2_GENCALL BSP_BIT32(4)
+#define STM32F4_I2C_SR2_TRA BSP_BIT32(2)
+#define STM32F4_I2C_SR2_BUSY BSP_BIT32(1)
+#define STM32F4_I2C_SR2_MSL BSP_BIT32(0)
+	uint32_t ccr;
+#define STM32F4_I2C_CCR_FS BSP_BIT32(15)
+#define STM32F4_I2C_CCR_DUTY BSP_BIT32(14)
+#define STM32F4_I2C_CCR_CCR(val) BSP_FLD32(val, 0, 11)
+#define STM32F4_I2C_CCR_CCR_GET(reg) BSP_FLD32GET(reg, 0, 11)
+#define STM32F4_I2C_CCR_CCR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 11)
+#define STM32F4_I2C_CCR_CCR_MAX STM32F4_I2C_CCR_CCR_GET(BSP_MSK32(0, 11))
+	uint32_t trise;
+#define STM32F4_I2C_TRISE(val) BSP_FLD32(val, 0, 5)
+#define STM32F4_I2C_TRISE_GET(reg) BSP_FLD32GET(reg, 0, 5)
+#define STM32F4_I2C_TRISE_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5)
+} stm32f4_i2c;
+
+#endif /* LIBBSP_ARM_STM32F4_STM32_I2C_H */
diff --git a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
index 19df011..9059d18 100644
--- a/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
+++ b/c/src/lib/libbsp/arm/stm32f4/include/stm32f4.h
@@ -28,6 +28,11 @@
 #include <bsp/stm32f4xxxx_rcc.h>
 #define STM32F4_RCC ((volatile stm32f4_rcc *) (STM32F4_BASE + 0x40023800))
 
+#include <bsp/stm32_i2c.h>
+#define STM32F4_I2C3 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005C00))
+#define STM32F4_I2C2 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005800))
+#define STM32F4_I2C1 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005400))
+
 #include <bsp/stm32_usart.h>
 #define STM32F4_USART_1 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40011000))
 #define STM32F4_USART_2 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40004400))
@@ -50,6 +55,10 @@
 #include <bsp/stm32f10xxx_rcc.h>
 #define STM32F4_RCC ((volatile stm32f4_rcc *) (STM32F4_BASE + 0x40021000))
 
+#include <bsp/stm32_i2c.h>
+#define STM32F4_I2C2 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005800))
+#define STM32F4_I2C1 ((volatile stm32f4_i2c *) (STM32F4_BASE + 0x40005400))
+
 #include <bsp/stm32_usart.h>
 #define STM32F4_USART_1 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40013800))
 #define STM32F4_USART_2 ((volatile stm32f4_usart *) (STM32F4_BASE + 0x40004400))
diff --git a/c/src/lib/libbsp/arm/stm32f4/preinstall.am b/c/src/lib/libbsp/arm/stm32f4/preinstall.am
index 8be8956..a75e3d0 100644
--- a/c/src/lib/libbsp/arm/stm32f4/preinstall.am
+++ b/c/src/lib/libbsp/arm/stm32f4/preinstall.am
@@ -125,6 +125,14 @@ $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h: include/stm32f4xxxx_rcc.h $(PROJECT_IN
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32f4xxxx_rcc.h
 
+$(PROJECT_INCLUDE)/bsp/stm32_i2c.h: include/stm32_i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32_i2c.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32_i2c.h
+
+$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h
+
 $(PROJECT_INCLUDE)/bsp/stm32_usart.h: include/stm32_usart.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/stm32_usart.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/stm32_usart.h
diff --git a/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c
index 2ec8635..39e9db0 100644
--- a/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c
+++ b/c/src/lib/libbsp/arm/stm32f4/startup/start-config-io.c
@@ -41,6 +41,12 @@ const stm32f4_gpio_config stm32f4_start_config_gpio [] = {
     STM32F4_PIN_USART6_TX_PC6,
     STM32F4_PIN_USART6_RX_PC7,
   #endif
+  #ifdef STM32F4_ENABLE_I2C1
+    #error Not implemented.
+  #endif
+  #ifdef STM32F4_ENABLE_I2C2
+    #error Not implemented.
+  #endif
 #endif /* STM32F4_FAMILY_F4XXXX */
 #ifdef STM32F4_FAMILY_F10XXX
   #ifdef STM32F4_ENABLE_USART_1
@@ -63,6 +69,17 @@ const stm32f4_gpio_config stm32f4_start_config_gpio [] = {
     STM32F4_PIN_UART5_TX,
     STM32F4_PIN_UART5_RX,
   #endif
+  #ifdef STM32F4_ENABLE_USART_6
+    #error STM32F10XXX has no USART 6
+  #endif
+  #ifdef STM32F4_ENABLE_I2C1
+    STM32F4_PIN_I2C1_SCL_MAP0,
+    STM32F4_PIN_I2C1_SDA_MAP0,
+  #endif
+  #ifdef STM32F4_ENABLE_I2C2
+    STM32F4_PIN_I2C2_SCL,
+    STM32F4_PIN_I2C2_SDA,
+  #endif
 #endif /* STM32F4_FAMILY_F10XXX */
   STM32F4_GPIO_CONFIG_TERMINAL
 };




More information about the vc mailing list