From 9ea1d989996775b6e775fb462c7bff143e278ad9 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Sun, 3 Apr 2011 14:26:05 +0000
Subject: [PATCH] New LIS331DL driver and VSN updates from Uros

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3457 42af7a65-404d-4744-a932-0658087f49c3
---
 ChangeLog                             |   9 +
 Documentation/NuttX.html              |  19 +-
 Documentation/NuttxPortingGuide.html  |  32 +-
 Makefile                              |  22 +-
 TODO                                  |  12 +-
 arch/arm/src/lpc313x/lpc313x_i2c.c    |   2 +-
 arch/arm/src/stm32/chip/stm32_i2c.h   |   6 +-
 arch/arm/src/stm32/stm32_i2c.c        | 434 +++++++++++++++++++-------
 arch/arm/src/stm32/stm32_i2c.h        |   2 +-
 arch/z80/src/ez80/ez80_i2c.c          |   4 +-
 arch/z80/src/z8/z8_i2c.c              |   4 +-
 configs/README.txt                    |  14 +-
 configs/demo9s12ne64/ostest/defconfig |   3 +-
 configs/ea3131/locked/Makefile        |   2 +-
 configs/ea3131/pgnsh/defconfig        |   1 +
 configs/ne64badge/ostest/defconfig    |   3 +-
 configs/sam3u-ek/README.txt           |  17 +-
 configs/sam3u-ek/kernel/Makefile      |   2 +
 configs/sam3u-ek/kernel/kernel.ld     |   1 +
 configs/sam3u-ek/knsh/Make.defs       |   2 +-
 configs/sam3u-ek/knsh/defconfig       |   1 +
 configs/vsn/include/nsh_romfsimg.h    |  40 +--
 configs/vsn/include/rcS.template      |   4 +-
 configs/vsn/nsh/defconfig             |  13 +-
 configs/vsn/src/sif.c                 |  47 +--
 drivers/Makefile                      |   7 +
 drivers/i2c/Make.defs                 |  42 +++
 drivers/i2c/st_lis331dl.c             | 270 ++++++++++++++++
 include/nuttx/{ => i2c}/i2c.h         |  31 +-
 include/nuttx/i2c/st_lis331dl.h       | 170 ++++++++++
 30 files changed, 1012 insertions(+), 204 deletions(-)
 create mode 100644 drivers/i2c/Make.defs
 create mode 100644 drivers/i2c/st_lis331dl.c
 rename include/nuttx/{ => i2c}/i2c.h (90%)
 create mode 100644 include/nuttx/i2c/st_lis331dl.h

diff --git a/ChangeLog b/ChangeLog
index b1a1903df9..13e40f3034 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1642,5 +1642,14 @@
 	  unable to replicate the build problems in my environment, but the changes
 	  have be incorporated in hope of correcting the build issues in other
 	  environments.
+	* drivers/i2c/st_lis331dl.c:  I2C-based driver for the LIS331DL MEMS
+	  motion sensor.  Contributed by Uros Platise.
+	* Makefile: The NuttX build system  will now supported building NuttX as two
+	  separately linked images: (1) a kernel-mode RTOS image, and (2) a user-
+	  mode application image that communicates to the RTOS kernel via system
+	  calls.  A lot more still must be done.
+
+
+
  
 
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index 224b1bef81..5721c5eff2 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -8,7 +8,7 @@
   <tr align="center" bgcolor="#e4e4e4">
     <td>
       <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
-      <p>Last Updated: March 30, 2011</p>
+      <p>Last Updated: April 3, 2011</p>
     </td>
   </tr>
 </table>
@@ -2188,11 +2188,28 @@ nuttx-6.1 2011-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
     * syscall/: The beginnings of an optional syscall kernel interface.
     * tools/mksyscall.c:  Add a tool that will auto-generate syscall proxies
       and stubs from a comma-separated-value (CSV) data file.
+    * arch/arm/src/cortexm3/mpu.h: Add a header file describing the Cortex-M3
+      MPU registers.
+    * Numerous modifications to the build system.  Various people have reported
+      build problems since the re-organization and release of NuttX-6.0.  I am
+      unable to replicate the build problems in my environment, but the changes
+      have be incorporated in hope of correcting the build issues in other
+      environments.
+    * drivers/i2c/st_lis331dl.c:  I2C-based driver for the LIS331DL MEMS
+      motion sensor.  Contributed by Uros Platise.
+    * Makefile: The NuttX build system  will now supported building NuttX as two
+      separately linked images: (1) a kernel-mode RTOS image, and (2) a user-
+      mode application image that communicates to the RTOS kernel via system
+      calls.  A lot more still must be done.
 
 apps-6.1 2011-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 
     * Creation of auto-generated header files now occurs during the context
       build phase.
+    * Added sdcard insert and eject, nsh command '?' and some code remarks
+    * Renamed nuttapp to namedapp
+    * namedapp/binfs.c -- Create a tiny filesystem that can be used
+      to show the internal named apps under /bin.
 
 pascal-2.1 2011-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 
diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html
index ef444506f5..eaa603a4a1 100644
--- a/Documentation/NuttxPortingGuide.html
+++ b/Documentation/NuttxPortingGuide.html
@@ -12,7 +12,7 @@
       <h1><big><font color="#3c34ec">
         <i>NuttX RTOS Porting Guide</i>
       </font></big></h1>
-      <p>Last Updated: April 1, 2011</p>
+      <p>Last Updated: April 3, 2011</p>
     </td>
   </tr>
 </table>
@@ -2034,7 +2034,7 @@ extern void up_ledoff(int led);
 <ul>
   <li>
     <p>
-    <b><code>include/nuttx/i2c.h</code></b>.
+    <b><code>include/nuttx/i2c/i2c.h</code></b>.
     All structures and APIs needed to work with I2C drivers are provided in this header file.
     </p>
   </li>
@@ -2790,7 +2790,7 @@ build
   Two-pass Build Options.
   If the 2 pass build option is selected, then these options configure the make system build a extra link object.
   This link object is assumed to be an incremental (relative) link object, but could be a static library (archive)
-  (some modification to this Makefile would be required if CONFIG_PASS1_OBJECT is an archive).
+  (some modification to this Makefile would be required if CONFIG_PASS1_TARGET generates an archive).
   Pass 1 1ncremental (relative) link objects should be put into the processor-specific source directory 
   where other link objects will be created - ff the pass1 obect is an archive, it could	go anywhere.
 </p>
@@ -2805,15 +2805,27 @@ build
 </p>
 <ul>
   <li>
-    <code>CONFIG_PASS1_OBJECT</code>: The name of the first pass object.
+    <p>
+      <code>CONFIG_PASS1_TARGET</code>: The name of the first pass build target.
+    </p>
   </li>
   <li><code>CONFIG_PASS1_BUILDIR</code>:
-  The path, relative to the top NuttX build directory to directory that contains the Makefile to build the first pass object.
-  The Makefile must support the following targets:
-  <ul>
-    <li>The special target <code>arch/$(CONFIG_ARCH)/src/$(CONFIG_PASS1_OBJECT)</code>, and</li>
-    <li>The usual depend, clean, and distclean targets.</li>
-  </ul>
+    <p>
+      The path, relative to the top NuttX build directory to directory that contains the Makefile to build the first pass object.
+      The Makefile must support the following targets:
+    </p>
+    <p>
+      <ul>
+        <li>The special target <code>CONFIG_PASS1_TARGET</code> (if defined), and</li>
+        <li>The usual depend, clean, and distclean targets.</li>
+      </ul>
+    </p>
+  </li>
+  <li>
+    <code>CONFIG_PASS1_OBJECT</code>: May be used to include an extra, pass1 object into the final link.
+    This would probably be the object generated from the <code>CONFIG_PASS1_TARGET</code>. 
+    It may be available at link time in the <code>arch/&lt;architecture&gt;/src</code> directory.
+  </li>
 </ul>
 
 <h2>General OS setup</h2>
diff --git a/Makefile b/Makefile
index dea43c1092..1ecc8563e8 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,6 @@ CLEANDIRS	+= net
 # be created).  If the pass1 obect is an archive, it could go anywhere.
 
 ifeq ($(CONFIG_BUILD_2PASS),y)
-#EXTRA_OBJS	= $(TOPDIR)/$(CONFIG_PASS1_BUILDIR)/$(CONFIG_PASS1_OBJECT)
 EXTRA_OBJS	+= $(CONFIG_PASS1_OBJECT)
 endif
 
@@ -168,11 +167,12 @@ NUTTXLIBS	= sched/libsched$(LIBEXT) $(ARCH_SRC)/libarch$(LIBEXT) mm/libmm$(LIBEX
 		  lib/liblib$(LIBEXT)
 USERLIBS	=
 
-# Add libraries for syscall support.
+# Add libraries for syscall support.  The C library will be needed by
+# both the kernel- and user-space builds.
 
 ifeq ($(CONFIG_NUTTX_KERNEL),y)
 NUTTXLIBS	+= syscall/libstubs$(LIBEXT)
-USERLIBS	+= syscall/libproxies$(LIBEXT)
+USERLIBS	+= syscall/libproxies$(LIBEXT) lib/liblib$(LIBEXT)
 endif
 
 # Add libraries for network support.  CXX, CXXFLAGS, and COMPILEXX must
@@ -334,19 +334,17 @@ syscall/libproxies$(LIBEXT): context
 	@$(MAKE) -C syscall TOPDIR="$(TOPDIR)" libproxies$(LIBEXT)
 
 # If the 2 pass build option is selected, then this pass1 target is
-# configured be build a extra link object. This is assumed to be an
-# incremental (relative) link object, but could be a static library
-# (archive); some modification to this Makefile would be required if
-# CONFIG_PASS1_OBJECT is an archive.
+# configured to built before the pass2 target.  This pass1 target may, as an
+# example, build an extra link object (CONFIG_PASS1_OBJECT) which may be an
+# incremental (relative) link object, but could be a static library (archive);
+# some modification to this Makefile would be required if CONFIG_PASS1_OBJECT
+# is an archive.  Exactly what is performed during pass1 or what it generates
+# is unknown to this makefule unless CONFIG_PASS1_OBJECT is defined.
 
 pass1deps: context depend $(USERLIBS)
 
 pass1: pass1deps
 ifeq ($(CONFIG_BUILD_2PASS),y)
-	@if [ -z "$(CONFIG_PASS1_OBJECT)" ]; then \
-		echo "ERROR: CONFIG_PASS1_OBJECT not defined"; \
-		exit 1; \
-	fi
 	@if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then \
 		echo "ERROR: CONFIG_PASS1_BUILDIR not defined"; \
 		exit 1; \
@@ -359,7 +357,7 @@ ifeq ($(CONFIG_BUILD_2PASS),y)
 		echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR"; \
 		exit 1; \
 	fi
-	@$(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" LINKLIBS="$(NUTTXLIBS)" USERLIBS="$(USERLIBS)" "$(ARCH_SRC)/$(CONFIG_PASS1_OBJECT)"
+	@$(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" LINKLIBS="$(NUTTXLIBS)" USERLIBS="$(USERLIBS)" "$(CONFIG_PASS1_TARGET)"
 endif
 
 pass2deps: context depend $(NUTTXLIBS)
diff --git a/TODO b/TODO
index 99be2df886..d9b2491b0b 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated March 16 2011)
+NuttX TODO List (Last updated April 2 2011)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 nuttx/
@@ -19,7 +19,7 @@ nuttx/
   (1)  Documentation (Documentation/)
   (5)  Build system / Toolchains
   (7)  Linux/Cywgin simulation (arch/sim)
-  (3)  ARM (arch/arm/)
+  (4)  ARM (arch/arm/)
   (1)  ARM/C5471 (arch/arm/src/c5471/)
   (3)  ARM/DM320 (arch/arm/src/dm320/)
   (2)  ARM/i.MX (arch/arm/src/imx/)
@@ -612,6 +612,14 @@ o ARM (arch/arm/)
   Status:      Open
   Priority:    Low
 
+  Description: The ARM interrupt handling (arch/arm/src/arm/up_vectors.S) returns
+               using 'ldmia   sp, {r0-r15}^'  My understanding is that this works
+               fine because everything is in kernel-mode.  In an operating model
+               where applications run in user mode and interrupts/traps run in
+               kernel-mode, I think that there is a problem with this.
+  Status:      Open
+  Priority:    Low until I get around to implement security for the ARM platform.
+
 o ARM/C5471 (arch/arm/src/c5471/)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/arch/arm/src/lpc313x/lpc313x_i2c.c b/arch/arm/src/lpc313x/lpc313x_i2c.c
index 137b2b315d..dc2e454b9d 100644
--- a/arch/arm/src/lpc313x/lpc313x_i2c.c
+++ b/arch/arm/src/lpc313x/lpc313x_i2c.c
@@ -50,7 +50,7 @@
 #include <debug.h>
 
 #include <nuttx/arch.h>
-#include <nuttx/i2c.h>
+#include <nuttx/i2c/i2c.h>
 
 #include <arch/irq.h>
 #include <arch/board/board.h>
diff --git a/arch/arm/src/stm32/chip/stm32_i2c.h b/arch/arm/src/stm32/chip/stm32_i2c.h
index 3510b2f410..00a24b355e 100644
--- a/arch/arm/src/stm32/chip/stm32_i2c.h
+++ b/arch/arm/src/stm32/chip/stm32_i2c.h
@@ -102,7 +102,7 @@
 #define I2C_CR2_FREQ_SHIFT      (0)       /* Bits 5-0: Peripheral Clock Frequency */
 #define I2C_CR2_FREQ_MASK       (0x3f << I2C_CR2_FREQ_SHIFT)
 #define I2C_CR2_ITERREN         (1 << 8)  /* Bit 8: Error Interrupt Enable */
-#define I2C_CR2_ITEVTEN         (1 << 9)  /* Bit 9: Event Interrupt Enable */
+#define I2C_CR2_ITEVFEN         (1 << 9)  /* Bit 9: Event Interrupt Enable */
 #define I2C_CR2_ITBUFEN         (1 << 10) /* Bit 10: Buffer Interrupt Enable */
 #define I2C_CR2_DMAEN           (1 << 11) /* Bit 11: DMA Requests Enable */
 #define I2C_CR2_LAST            (1 << 12) /* Bit 12: DMA Last Transfer */
@@ -135,6 +135,7 @@
 #define I2C_SR1_BTF             (1 << 2)  /* Bit 2: Byte Transfer Finished */
 #define I2C_SR1_ADD10           (1 << 3)  /* Bit 3: 10-bit header sent (Master mode) */
 #define I2C_SR1_STOPF           (1 << 4)  /* Bit 4: Stop detection (Slave mode) */
+                                          /* Bit 5: Reserved */
 #define I2C_SR1_RXNE            (1 << 6)  /* Bit 6: Data Register not Empty (receivers) */
 #define I2C_SR1_TXE             (1 << 7)  /* Bit 7: Data Register Empty (transmitters) */
 #define I2C_SR1_BERR            (1 << 8)  /* Bit 8: Bus Error */
@@ -142,9 +143,12 @@
 #define I2C_SR1_AF              (1 << 10) /* Bit 10: Acknowledge Failure */
 #define I2C_SR1_OVR             (1 << 11) /* Bit 11: Overrun/Underrun */
 #define I2C_SR1_PECERR          (1 << 12) /* Bit 12: PEC Error in reception */
+                                          /* Bit 13: Reserved */
 #define I2C_SR1_TIMEOUT         (1 << 14) /* Bit 14: Timeout or Tlow Error */
 #define I2C_SR1_SMBALERT        (1 << 15) /* Bit 15: SMBus Alert */
 
+#define I2C_SR1_ERRORMASK       (I2C_SR1_BERR|I2C_SR1_ARLO|I2C_SR1_AF|I2C_SR1_OVR|I2C_SR1_PECERR)
+
 /* Status register 2 */
 
 #define I2C_SR2_MSL             (1 << 0)  /* Bit 0: Master/Slave */
diff --git a/arch/arm/src/stm32/stm32_i2c.c b/arch/arm/src/stm32/stm32_i2c.c
index 05afd5a7b8..de9ca60c82 100644
--- a/arch/arm/src/stm32/stm32_i2c.c
+++ b/arch/arm/src/stm32/stm32_i2c.c
@@ -43,14 +43,15 @@
  *  - Interrupt based operation
  * 
  * Structure naming:
- *  - Device: structure as defined by the nuttx/i2c.h
+ *  - Device: structure as defined by the nuttx/i2c/i2c.h
  *  - Instance: represents each individual access to the I2C driver, obtained by
- *      the i2c_init(); it extends the Device structure from the nuttx/i2c.h; 
+ *      the i2c_init(); it extends the Device structure from the nuttx/i2c/i2c.h; 
  *      Instance points to OPS, to common I2C Hardware private data and contains
  *      its own private data, as frequency, address, mode of operation (in the future)
  *  - Private: Private data of an I2C Hardware
  * 
  * \todo
+ *  - Check for all possible deadlocks (as BUSY='1' I2C needs to be reset in HW using the I2C_CR1_SWRST)
  *  - SMBus support (hardware layer timings are already supported) and add SMBA gpio pin
  *  - Slave support with multiple addresses (on multiple instances):
  *      - 2 x 7-bit address or 
@@ -64,9 +65,11 @@
 #include <nuttx/config.h>
 #include <nuttx/arch.h>
 #include <nuttx/irq.h>
+#include <nuttx/i2c/i2c.h>
 #include <arch/board/board.h>
 
 #include <sys/types.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdbool.h>
@@ -79,6 +82,7 @@
 #include "stm32_rcc.h"
 #include "stm32_i2c.h"
 
+
 #if defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2)
 
 /************************************************************************************
@@ -91,10 +95,16 @@
 struct stm32_i2c_priv_s {
     uint32_t    base;
     int         refs;
-    sem_t       sem;
+    sem_t       sem_excl;
+    sem_t       sem_isr;
     
     uint8_t     msgc;
-    FAR struct i2c_msg_s *msgv;
+    struct i2c_msg_s *msgv;
+    uint8_t   * ptr;
+    int         dcnt;
+    uint16_t    flags;
+    
+    uint32_t    status;
 };
 
 
@@ -134,62 +144,72 @@ struct stm32_i2c_priv_s stm32_i2c2_priv = {
  ************************************************************************************/
 
 /** Get register value by offset */
-static inline uint16_t stm32_i2c_getreg(FAR struct i2c_dev_s *dev, uint8_t offset)
+static inline uint16_t stm32_i2c_getreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset)
 {
-    return getreg16( ((struct stm32_i2c_inst_s *)dev)->priv->base + offset);
+    return getreg16(priv->base + offset);
 }
 
 
 /** Put register value by offset */
-static inline void stm32_i2c_putreg(FAR struct i2c_dev_s *dev, uint8_t offset, uint16_t value)
+static inline void stm32_i2c_putreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, uint16_t value)
 {
-    //printf("putreg(%8x)=%4x\n", ((struct stm32_i2c_priv_s *)dev)->base + offset, value );
-    putreg16(value, ((struct stm32_i2c_inst_s *)dev)->priv->base + offset);
+    putreg16(value, priv->base + offset);
 }
 
 
 /** Modify register value by offset */
-static inline void stm32_i2c_modifyreg(FAR struct i2c_dev_s *dev, uint8_t offset, uint16_t clearbits, uint16_t setbits)
+static inline void stm32_i2c_modifyreg(FAR struct stm32_i2c_priv_s *priv, uint8_t offset, uint16_t clearbits, uint16_t setbits)
 {
-    modifyreg16( ((struct stm32_i2c_inst_s *)dev)->priv->base + offset, clearbits, setbits);
+    modifyreg16(priv->base + offset, clearbits, setbits);
 }
 
 
 void inline stm32_i2c_sem_wait(FAR struct i2c_dev_s *dev)
 {
-    while( sem_wait( &((struct stm32_i2c_inst_s *)dev)->priv->sem ) != 0 ) {
+    while( sem_wait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl ) != 0 ) {
         ASSERT(errno == EINTR);
     }
 }
 
 
+int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
+{
+    while( sem_wait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 ) {
+        ASSERT(errno == EINTR);
+    }
+    return OK;
+}
+
+
 void inline stm32_i2c_sem_post(FAR struct i2c_dev_s *dev)
 {
-    sem_post( &((struct stm32_i2c_inst_s *)dev)->priv->sem );
+    sem_post( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl );
 }
 
 
 void inline stm32_i2c_sem_init(FAR struct i2c_dev_s *dev)
 {
-    sem_init( &((struct stm32_i2c_inst_s *)dev)->priv->sem, 0, 1);
+    sem_init( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl, 0, 1);
+    sem_init( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr, 0, 0);
 }
 
 
 void inline stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev)
 {
-    sem_destroy( &((struct stm32_i2c_inst_s *)dev)->priv->sem );
+    sem_destroy( &((struct stm32_i2c_inst_s *)dev)->priv->sem_excl );
+    sem_destroy( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr );
 }
 
 
-static void stm32_i2c_setclock(FAR struct i2c_dev_s *inst, uint32_t frequency)
+static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequency)
 {
     /* Disable Peripheral if rising time is to be changed, 
      * and restore state on return. */
 
-    uint16_t cr1 = stm32_i2c_getreg(inst, STM32_I2C_CR1_OFFSET);
+    uint16_t cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
     
     if (cr1 & I2C_CR1_PE)
-        stm32_i2c_putreg(inst, STM32_I2C_CR1_OFFSET, cr1 ^ I2C_CR1_PE);
+        stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 ^ I2C_CR1_PE);
         
     /* Update timing and control registers */
     
@@ -199,8 +219,8 @@ static void stm32_i2c_setclock(FAR struct i2c_dev_s *inst, uint32_t frequency)
          * Risetime: 1000 ns
          * Duty: t_low / t_high = 1
          */
-        stm32_i2c_putreg(inst, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/200000);
-        stm32_i2c_putreg(inst, STM32_I2C_TRISE_OFFSET, 1 + STM32_BOARD_HCLK/1000000);
+        stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/200000);
+        stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, 1 + STM32_BOARD_HCLK/1000000);
     }
     else {
     
@@ -208,68 +228,206 @@ static void stm32_i2c_setclock(FAR struct i2c_dev_s *inst, uint32_t frequency)
          * Risetime: 1000 ns ??? \todo check rise time for 400 kHz devices
          * Duty: t_low / t_high = 2
          */
-        stm32_i2c_putreg(inst, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/1200000);
-        stm32_i2c_putreg(inst, STM32_I2C_TRISE_OFFSET, 1 + STM32_BOARD_HCLK/1000000); 
+        stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/1200000);
+        stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, 1 + STM32_BOARD_HCLK/1000000); 
     }
         
     /* Restore state */
     
     if (cr1 & I2C_CR1_PE)
-        stm32_i2c_putreg(inst, STM32_I2C_CR1_OFFSET, cr1);
+        stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
 }
 
 
-static inline void stm32_i2c_sendstart(FAR struct i2c_dev_s *inst)
+static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv)
 {
-    stm32_i2c_modifyreg(inst, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_START);
+    /* Disable ACK on receive by default and generate START */
+    stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_START);
 }
 
 
-static inline void stm32_i2c_sendstop(FAR struct i2c_dev_s *inst)
+static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
 {
-    stm32_i2c_modifyreg(inst, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_STOP);
+    stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, I2C_CR1_STOP);
+}
+
+
+static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv)
+{
+   uint32_t status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);
+   status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
+   return status;
 }
 
 
 /************************************************************************************
  * Interrupt Service Routines
  ************************************************************************************/
- 
-static int stm32_i2c_event_isr(struct stm32_i2c_priv_s * priv)
-{
-    return OK;
-}
- 
+//DEBUG TO BE CLEANED
+//#define NON_ISR
 
-static int stm32_i2c_error_isr(struct stm32_i2c_priv_s * priv)
+static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
 {
+    uint32_t status = stm32_i2c_getstatus(priv);
+    
+#ifdef NON_ISR
+    static uint32_t isr_count = 0;
+    static uint32_t old_status = 0xFFFF;
+
+    isr_count++;
+    
+    if (old_status != status) {
+        printf("status = %8x, count=%d\n", status, isr_count); fflush(stdout);
+        old_status = status;
+    }
+#endif
+            
+    /* Was start bit sent */
+    
+    if (status & I2C_SR1_SB) {
+    
+        /* Get run-time data */
+                
+        priv->ptr   = priv->msgv->buffer;
+        priv->dcnt  = priv->msgv->length;
+        priv->flags = priv->msgv->flags;
+
+        /* Send address byte and define addressing mode */
+        
+        stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, (priv->flags & I2C_M_TEN) ?
+            0 :
+            ((priv->msgv->addr << 1) | (priv->flags & I2C_M_READ))
+        );
+        
+        /* Enable RxNE and TxE buffers */
+        
+        stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_ITBUFEN);
+        
+        /* Increment to next pointer and decrement message count */
+        
+        priv->msgv++;
+        priv->msgc--;
+    }
+    
+        /* In 10-bit addressing mode, was first byte sent */
+    
+    else if (status & I2C_SR1_ADD10) {
+        /* \todo Finish 10-bit mode addressing */
+    }
+    
+        /* Was address sent, continue with ether sending or reading data */
+    
+    else if ( !(priv->flags & I2C_M_READ) && 
+               (status & (I2C_SR1_ADDR | I2C_SR1_TXE)) ) {
+
+        if (--priv->dcnt >= 0) {   /* Send a byte */
+#ifdef NON_ISR
+            printf("Send byte: %2x\n", *priv->ptr);
+#endif
+            stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
+        }
+    }
+    
+    else if ( (priv->flags & I2C_M_READ) && (status & I2C_SR1_ADDR) ) {
+
+        /* Acknowledge bytes if there is more than one to be received */
+        
+        if (priv->dcnt > 1) {            
+            stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, 0, I2C_CR1_ACK);
+        }
+    }
+
+        /* More bytes to read */
+
+    else if ( status & I2C_SR1_RXNE ) {
+    
+        /* Read a byte, if dcnt goes < 0, then read dummy bytes to ack ISRs */
+    
+#ifdef NON_ISR
+        printf("dcnt=%d\n", priv->dcnt);
+#endif
+        if (--priv->dcnt >= 0) {
+            *priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
+#ifdef NON_ISR
+            printf("Received: %2x\n", *(priv->ptr-1) );
+#endif
+            /* Disable acknowledge when last byte is to be received */
+            if (priv->dcnt == 1) {
+                stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);  
+            }
+        }
+    }
+    
+    
+    /* Was last byte received or sent? 
+     */
+    
+    if (priv->dcnt<=0 && (status & I2C_SR1_BTF)) {
+#ifdef NON_ISR
+        printf("BTF\n");
+#endif
+        stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);    /* ACK ISR */
+
+        /* Do we need to terminate or restart after this byte */
+        
+        /* If there are more messages to send, then we may:
+         *  - continue with repeated start
+         *  - or just continue sending writeable part
+         *  - or we close down by sending the stop bit 
+         */             
+        if (priv->msgc) {
+
+            if (priv->msgv->flags & I2C_M_NORESTART) {
+                priv->ptr   = priv->msgv->buffer;
+                priv->dcnt  = priv->msgv->length;
+                priv->flags = priv->msgv->flags;
+                priv->msgv++;
+                priv->msgc--;
+            }
+            else {
+                stm32_i2c_sendstart(priv);
+            }
+        }
+        else if (priv->msgv) {
+#ifdef NON_ISR
+            printf("stop2: status = %8x\n", status);
+#endif
+            stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
+            stm32_i2c_sendstop(priv);
+            sem_post( &priv->sem_isr );
+            priv->msgv = NULL;              /* mark that we have stopped with this transaction */
+        }
+    }
+    
+    /* Check for errors, in which case, stop the transfer and return 
+     * Note that in master reception mode AF becomes set on last byte
+     * since ACK is not returned. We should ignore this error.
+     */
+    
+    if (status & I2C_SR1_ERRORMASK) {
+        stm32_i2c_putreg(priv, STM32_I2C_SR1_OFFSET, 0);    /* clear flags */
+        sem_post( &priv->sem_isr );
+    }
+
+    priv->status = status;
     return OK;
 }
+ 
 
 
 /* Decode ***************************************************************************/
 
 #if CONFIG_STM32_I2C1
-static int stm32_i2c1_event_isr(int irq, void *context)
-{
-    return stm32_i2c_event_isr(&stm32_i2c1_priv);
-}
-
-static int stm32_i2c1_error_isr(int irq, void *context)
+static int stm32_i2c1_isr(int irq, void *context)
 {
-    return stm32_i2c_error_isr(&stm32_i2c1_priv);
+    return stm32_i2c_isr(&stm32_i2c1_priv);
 }
 #endif
 
 #if CONFIG_STM32_I2C2
-static int stm32_i2c2_event_isr(int irq, void *context)
-{
-    return stm32_i2c_event_isr(&stm32_i2c2_priv);
-}
-
-static int stm32_i2c2_error_isr(int irq, void *context)
+static int stm32_i2c2_isr(int irq, void *context)
 {
-    return stm32_i2c_error_isr(&stm32_i2c1_priv);
+    return stm32_i2c_isr(&stm32_i2c2_priv);
 }
 #endif
 
@@ -279,11 +437,11 @@ static int stm32_i2c2_error_isr(int irq, void *context)
  ************************************************************************************/
 
 /** Setup the I2C hardware, ready for operation with defaults */
-static int stm32_i2c_init(FAR struct i2c_dev_s *inst)
+static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
 {
     /* Power-up and configure GPIOs */
 
-    switch( ((struct stm32_i2c_inst_s *)inst)->priv->base ) {
+    switch( priv->base ) {
     
 #if CONFIG_STM32_I2C1
         case STM32_I2C1_BASE:
@@ -294,8 +452,8 @@ static int stm32_i2c_init(FAR struct i2c_dev_s *inst)
                 stm32_unconfiggpio(GPIO_I2C1_SCL);
                 return ERROR;
             }
-            irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_event_isr);
-            irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_error_isr);
+            irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr);
+            irq_attach(STM32_IRQ_I2C1ER, stm32_i2c1_isr);
             up_enable_irq(STM32_IRQ_I2C1EV);
             up_enable_irq(STM32_IRQ_I2C1ER);
             break;
@@ -310,8 +468,8 @@ static int stm32_i2c_init(FAR struct i2c_dev_s *inst)
                 stm32_unconfiggpio(GPIO_I2C2_SCL);
                 return ERROR;
             }
-            irq_attach(STM32_IRQ_I2C2EV, stm32_i2c2_event_isr);
-            irq_attach(STM32_IRQ_I2C2ER, stm32_i2c2_error_isr);
+            irq_attach(STM32_IRQ_I2C2EV, stm32_i2c2_isr);
+            irq_attach(STM32_IRQ_I2C2ER, stm32_i2c2_isr);
             up_enable_irq(STM32_IRQ_I2C2EV);
             up_enable_irq(STM32_IRQ_I2C2ER);
             break;
@@ -324,29 +482,31 @@ static int stm32_i2c_init(FAR struct i2c_dev_s *inst)
      * for 100 kHz or 4 MHz for 400 kHz. Enable interrupt generation.
      */
 
-    stm32_i2c_putreg(inst, STM32_I2C_CR2_OFFSET,
-        I2C_CR2_ITERREN | I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN |
+    stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET,
+#ifndef NON_ISR
+        I2C_CR2_ITERREN | I2C_CR2_ITEVFEN | // I2C_CR2_ITBUFEN |
+#endif
         (STM32_BOARD_HCLK / 1000000) 
     );
     
-    stm32_i2c_setclock(inst, 100000);
+    stm32_i2c_setclock(priv, 100000);
         
     /* Enable I2C */
     
-    stm32_i2c_putreg(inst, STM32_I2C_CR1_OFFSET, I2C_CR1_PE);
+    stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE);
     
     return OK;
 }
 
 
 /** Shutdown the I2C hardware  */
-static int stm32_i2c_deinit(FAR struct i2c_dev_s *inst)
+static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
 {
     /* Disable I2C */
 
-    stm32_i2c_putreg(inst, STM32_I2C_CR1_OFFSET, 0);
+    stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0);
 
-    switch( ((struct stm32_i2c_inst_s *)inst)->priv->base ) {
+    switch( priv->base ) {
     
 #if CONFIG_STM32_I2C1
         case STM32_I2C1_BASE:
@@ -387,116 +547,164 @@ static int stm32_i2c_deinit(FAR struct i2c_dev_s *inst)
  * Device Driver OPS - Blocking Type
  ************************************************************************************/
 
-uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *inst, uint32_t frequency)
+uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
 {
-    stm32_i2c_sem_wait(inst);
+    stm32_i2c_sem_wait(dev);
     
 #if STM32_BOARD_HCLK < 4000000
-    ((struct stm32_i2c_inst_s *)inst)->frequency = 100000;
+    ((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
 #else
-    ((struct stm32_i2c_inst_s *)inst)->frequency = frequency;
+    ((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
 #endif
 
-    stm32_i2c_sem_post(inst);    
-    return ((struct stm32_i2c_inst_s *)inst)->frequency;
+    stm32_i2c_sem_post(dev);    
+    return ((struct stm32_i2c_inst_s *)dev)->frequency;
 }
 
 
-int stm32_i2c_setaddress(FAR struct i2c_dev_s *inst, int addr, int nbits)
+int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
 {
-    stm32_i2c_sem_wait(inst);
+    stm32_i2c_sem_wait(dev);
     
-    ((struct stm32_i2c_inst_s *)inst)->address = addr;
-    ((struct stm32_i2c_inst_s *)inst)->flags   = (nbits == 10) ? I2C_M_TEN : 0;
+    ((struct stm32_i2c_inst_s *)dev)->address = addr;
+    ((struct stm32_i2c_inst_s *)dev)->flags   = (nbits == 10) ? I2C_M_TEN : 0;
     
-    stm32_i2c_sem_post(inst);
+    stm32_i2c_sem_post(dev);
     return OK;
 }
 
 
-int stm32_i2c_process(FAR struct i2c_dev_s *inst, FAR struct i2c_msg_s *msgs, int count)
+int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count)
 {
+    struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
+    uint32_t    status = 0;
+    int         status_errno = 0;
+    
+    ASSERT(count);
+    
     /* The semaphore already ensures that I2C is ours, since we do not yet support
      * non-blocking operation.
      */
      
-    ((struct stm32_i2c_inst_s *)inst)->priv->msgv = msgs;
-    ((struct stm32_i2c_inst_s *)inst)->priv->msgc = count;
+    inst->priv->msgv    = msgs;
+    inst->priv->msgc    = count;
     
-    stm32_i2c_setclock(inst, ((struct stm32_i2c_inst_s *)inst)->frequency);
-    stm32_i2c_sendstart(inst);
+    stm32_i2c_setclock(inst->priv, inst->frequency);
      
     /* Trigger start condition, then the process moves into the ISR, 
-     * until semaphore is posted. 
+     * waiting again for the samaphore ... the resulting status is 
+     * found in the local status variable.
      */
     
-    stm32_i2c_sem_wait(inst);   /* wait again for the semaphore and */
-    stm32_i2c_sem_post(inst);   /* release it immediately. */
-    return OK;
+    stm32_i2c_sendstart(inst->priv);
+        
+#ifdef NON_ISR   
+    do {
+        do {
+            stm32_i2c_isr(&stm32_i2c1_priv);
+            status = inst->priv->status;
+        } while( status & (I2C_SR2_BUSY<<16) );
+    } 
+    while( sem_trywait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 );
+#else
+    /* Wait for an ISR, if there was a timeout, fetch latest status to get the BUSY flag */
+
+    if (stm32_i2c_sem_waitisr(dev) == ERROR) {
+        status = stm32_i2c_getstatus(inst->priv);
+    }
+    else status = inst->priv->status & 0xFFFF;  /* clear SR2 (BUSY flag) as we've done successfully */
+#endif        
+
+    if (status & I2C_SR1_BERR) {        /* Bus Error */
+        status_errno = EIO;
+    }
+    else if (status & I2C_SR1_ARLO) {   /* Arbitration Lost (master mode) */
+        status_errno = EAGAIN;
+    }
+    else if (status & I2C_SR1_AF) {     /* Acknowledge Failure */
+        status_errno = ENXIO;
+    }
+    else if (status & I2C_SR1_OVR) {    /* Overrun/Underrun */
+        status_errno = EIO;
+    }
+    else if (status & I2C_SR1_PECERR) { /* PEC Error in reception */
+        status_errno = EPROTO;
+    }
+    else if (status & I2C_SR1_TIMEOUT) {/* Timeout or Tlow Error */
+        status_errno = ETIME;
+    }
+    else if (status & (I2C_SR2_BUSY<<16) ) {    /* I2C Bus is for some reason busy */
+        status_errno = EBUSY;
+    }
+    
+    stm32_i2c_sem_post(dev);
+    
+    errno = status_errno;
+    return -status_errno;
 }
 
   
-int stm32_i2c_write(FAR struct i2c_dev_s *inst, const uint8_t *buffer, int buflen)
+int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen)
 {
-    stm32_i2c_sem_wait(inst);   /* ensure that address or flags don't change meanwhile */
+    stm32_i2c_sem_wait(dev);   /* ensure that address or flags don't change meanwhile */
     
     struct i2c_msg_s msgv = {
-        .addr   = ((struct stm32_i2c_inst_s *)inst)->address,
-        .flags  = ((struct stm32_i2c_inst_s *)inst)->flags,
+        .addr   = ((struct stm32_i2c_inst_s *)dev)->address,
+        .flags  = ((struct stm32_i2c_inst_s *)dev)->flags,
         .buffer = (uint8_t *)buffer,
         .length = buflen
     };
     
-    return stm32_i2c_process(inst, &msgv, 1);
+    return stm32_i2c_process(dev, &msgv, 1);
 }
 
 
-int stm32_i2c_read(FAR struct i2c_dev_s *inst, uint8_t *buffer, int buflen)
+int stm32_i2c_read(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen)
 {
-    stm32_i2c_sem_wait(inst);   /* ensure that address or flags don't change meanwhile */
+    stm32_i2c_sem_wait(dev);   /* ensure that address or flags don't change meanwhile */
     
     struct i2c_msg_s msgv = {
-        .addr   = ((struct stm32_i2c_inst_s *)inst)->address,
-        .flags  = ((struct stm32_i2c_inst_s *)inst)->flags | I2C_M_READ,
+        .addr   = ((struct stm32_i2c_inst_s *)dev)->address,
+        .flags  = ((struct stm32_i2c_inst_s *)dev)->flags | I2C_M_READ,
         .buffer = buffer,
         .length = buflen
     };
     
-    return stm32_i2c_process(inst, &msgv, 1);
+    return stm32_i2c_process(dev, &msgv, 1);
 }
 
 
 #ifdef CONFIG_I2C_WRITEREAD
-int stm32_i2c_writeread(FAR struct i2c_dev_s *inst, const uint8_t *wbuffer, int wbuflen,
-                        uint8_t *rbuffer, int rbuflen)
+int stm32_i2c_writeread(FAR struct i2c_dev_s *dev, const uint8_t *wbuffer, int wbuflen,
+                        uint8_t *buffer, int buflen)
 {
-    stm32_i2c_sem_wait(inst);   /* ensure that address or flags don't change meanwhile */
+    stm32_i2c_sem_wait(dev);   /* ensure that address or flags don't change meanwhile */
 
     struct i2c_msg_s msgv[2] = {
       {
-        .addr   = ((struct stm32_i2c_inst_s *)inst)->address,
-        .flags  = ((struct stm32_i2c_inst_s *)inst)->flags,
+        .addr   = ((struct stm32_i2c_inst_s *)dev)->address,
+        .flags  = ((struct stm32_i2c_inst_s *)dev)->flags,
         .buffer = (uint8_t *)wbuffer,          /* this is really ugly, sorry const ... */
         .length = wbuflen
       },
       {
-        .addr   = ((struct stm32_i2c_inst_s *)inst)->address,
-        .flags  = ((struct stm32_i2c_inst_s *)inst)->flags | I2C_M_READ,
-        .buffer = rbuffer,
-        .length = rbuflen
+        .addr   = ((struct stm32_i2c_inst_s *)dev)->address,
+        .flags  = ((struct stm32_i2c_inst_s *)dev)->flags | ((buflen>0) ? I2C_M_READ : I2C_M_NORESTART),
+        .buffer = buffer,
+        .length = (buflen>0) ? buflen : -buflen
       }
     };
 
-    return stm32_i2c_process(inst, msgv, 2);
+    return stm32_i2c_process(dev, msgv, 2);
 }
 #endif
 
 
 #ifdef CONFIG_I2C_TRANSFER
-int stm32_i2c_transfer(FAR struct i2c_dev_s *inst, FAR struct i2c_msg_s *msgs, int count)
+int stm32_i2c_transfer(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count)
 {
-    stm32_i2c_sem_wait(inst);   /* ensure that address or flags don't change meanwhile */
-    return stm32_i2c_process(inst, msgs, count);
+    stm32_i2c_sem_wait(dev);   /* ensure that address or flags don't change meanwhile */
+    return stm32_i2c_process(dev, msgs, count);
 }
 #endif
 
@@ -574,7 +782,7 @@ FAR struct i2c_dev_s * up_i2cinitialize(int port)
     
     if ((volatile int)priv->refs++ == 0) {
         stm32_i2c_sem_init( (struct i2c_dev_s *)inst );
-        stm32_i2c_init( (struct i2c_dev_s *)inst );
+        stm32_i2c_init( priv );
     }
     
     irqrestore(irqs);
@@ -583,22 +791,22 @@ FAR struct i2c_dev_s * up_i2cinitialize(int port)
 }
 
 
-int up_i2cuninitialize(FAR struct i2c_dev_s * inst)
+int up_i2cuninitialize(FAR struct i2c_dev_s * dev)
 {
     int irqs;
     
-    ASSERT(inst);
+    ASSERT(dev);
     
     /* Decrement refs and check for underflow */
     
-    if ( ((struct stm32_i2c_inst_s *)inst)->priv->refs == 0 ) 
+    if ( ((struct stm32_i2c_inst_s *)dev)->priv->refs == 0 ) 
         return ERROR;
         
     irqs = irqsave();
         
-    if ( --((struct stm32_i2c_inst_s *)inst)->priv->refs ) {
+    if ( --((struct stm32_i2c_inst_s *)dev)->priv->refs ) {
         irqrestore(irqs);
-        free(inst);
+        free(dev);
         return OK;
     }
     
@@ -606,13 +814,13 @@ int up_i2cuninitialize(FAR struct i2c_dev_s * inst)
     
     /* Disable power and other HW resource (GPIO's) */
     
-    stm32_i2c_deinit( (struct i2c_dev_s *)inst );
+    stm32_i2c_deinit( ((struct stm32_i2c_inst_s *)dev)->priv );
     
     /* Release unused resources */
 
-    stm32_i2c_sem_destroy( (struct i2c_dev_s *)inst );
+    stm32_i2c_sem_destroy( (struct i2c_dev_s *)dev );
         
-    free(inst);
+    free(dev);
     return OK;
 }
 
diff --git a/arch/arm/src/stm32/stm32_i2c.h b/arch/arm/src/stm32/stm32_i2c.h
index 23a06bc051..9bb17521a8 100755
--- a/arch/arm/src/stm32/stm32_i2c.h
+++ b/arch/arm/src/stm32/stm32_i2c.h
@@ -41,7 +41,7 @@
  ************************************************************************************/
 
 #include <nuttx/config.h>
-#include <nuttx/i2c.h>
+#include <nuttx/i2c/i2c.h>
 
 #include "chip.h"
 #include "chip/stm32_i2c.h"
diff --git a/arch/z80/src/ez80/ez80_i2c.c b/arch/z80/src/ez80/ez80_i2c.c
index d9defb0cf7..74dc899191 100644
--- a/arch/z80/src/ez80/ez80_i2c.c
+++ b/arch/z80/src/ez80/ez80_i2c.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * arch/z80/src/ez80/ez80_i2c.c
  *
- *   Copyright(C) 2009 Gregory Nutt. All rights reserved.
+ *   Copyright(C) 2009, 2011 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 #include <assert.h>
 #include <debug.h>
 
-#include <nuttx/i2c.h>
+#include <nuttx/i2c/i2c.h>
 #include <arch/io.h>
 #include <arch/board/board.h>
 
diff --git a/arch/z80/src/z8/z8_i2c.c b/arch/z80/src/z8/z8_i2c.c
index 796f389ec8..11825ac596 100755
--- a/arch/z80/src/z8/z8_i2c.c
+++ b/arch/z80/src/z8/z8_i2c.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * arch/z80/src/z8/z8_i2c.c
  *
- *   Copyright(C) 2009 Gregory Nutt. All rights reserved.
+ *   Copyright(C) 2009, 2011 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,7 +47,7 @@
 #include <assert.h>
 #include <debug.h>
 
-#include <nuttx/i2c.h>
+#include <nuttx/i2c/i2c.h>
 #include <arch/board/board.h>
 
 #include <eZ8.h>  /* eZ8 Register definitions */
diff --git a/configs/README.txt b/configs/README.txt
index 152a456458..560aa2a114 100644
--- a/configs/README.txt
+++ b/configs/README.txt
@@ -211,8 +211,8 @@ defconfig -- This is a configuration file similar to the Linux
 	options configure the make system build a extra link object. This link object
 	is assumed to be an incremental (relative) link object, but could be a static
 	library (archive) (some modification to this Makefile would be required if
-	CONFIG_PASS1_OBJECT is an archive). Pass 1 1ncremental (relative) link objects
-	should be put into the processor-specific source directory (where other
+	CONFIG_PASS1_TARGET generates an archive). Pass 1 1ncremental (relative) link
+	objects	should be put into the processor-specific source directory (where other
 	link objects will be created).  If the pass1 obect is an archive, it could
 	go anywhere.
 
@@ -220,12 +220,18 @@ defconfig -- This is a configuration file similar to the Linux
 
 	When the two pass build option is enabled, the following also apply:
 
-		CONFIG_PASS1_OBJECT - The name of the first pass object.
+		CONFIG_PASS1_TARGET - The name of the first pass build target.  This
+		  can be specific build target, a special build target (all, default, etc.)
+		  or may just be left undefined.
 		CONFIG_PASS1_BUILDIR - The path, relative to the top NuttX build
 		  directory to directory that contains the Makefile to build the
 		  first pass object.  The Makefile must support the following targets:
-		  - The special target arch/$(CONFIG_ARCH)/src/$(CONFIG_PASS1_OBJECT)
+		  - The special target CONFIG_PASS1_TARGET (if defined)
 		  - and the usual depend, clean, and distclean targets.
+		CONFIG_PASS1_OBJECT - May be used to include an extra, pass1 object
+		  into the final link.  This would probably be the object generated
+		  from the CONFIG_PASS1_TARGET.  It may be available at link time
+		  in the arch/<architecture>/src directory.
 
 	General OS setup
 
diff --git a/configs/demo9s12ne64/ostest/defconfig b/configs/demo9s12ne64/ostest/defconfig
index 80cec002f1..b5b4327598 100755
--- a/configs/demo9s12ne64/ostest/defconfig
+++ b/configs/demo9s12ne64/ostest/defconfig
@@ -189,7 +189,8 @@ CONFIG_HAVE_LIBM=n
 #
 CONFIG_BUILD_2PASS=n
 CONFIG_PASS1_BUILDIR=configs/demo9s12ne64/initrel
-CONFIG_PASS1_OBJECT=init.r
+CONFIG_PASS1_TARGET=init.r
+CONFIG_PASS1_OBJECT=
 
 #
 # General OS setup
diff --git a/configs/ea3131/locked/Makefile b/configs/ea3131/locked/Makefile
index 0537815780..50c6c8a1d2 100755
--- a/configs/ea3131/locked/Makefile
+++ b/configs/ea3131/locked/Makefile
@@ -77,7 +77,7 @@ PASS1_LIBGCC	= "${shell $(CC) -print-libgcc-file-name}"
 
 # Targets:
 
-all: locked.r
+all: $(PASS1_SRCDIR)/locked.r
 
 .PHONY:	depend clean distclean
 
diff --git a/configs/ea3131/pgnsh/defconfig b/configs/ea3131/pgnsh/defconfig
index 859b606be5..aa18038b99 100755
--- a/configs/ea3131/pgnsh/defconfig
+++ b/configs/ea3131/pgnsh/defconfig
@@ -203,6 +203,7 @@ CONFIG_HAVE_LIBM=n
 #
 CONFIG_BUILD_2PASS=y
 CONFIG_PASS1_BUILDIR=configs/ea3131/locked
+CONFIG_PASS1_TARGET=all
 CONFIG_PASS1_OBJECT=locked.r
 
 #
diff --git a/configs/ne64badge/ostest/defconfig b/configs/ne64badge/ostest/defconfig
index 47ce5e58b1..61f09986d7 100755
--- a/configs/ne64badge/ostest/defconfig
+++ b/configs/ne64badge/ostest/defconfig
@@ -200,7 +200,8 @@ CONFIG_HAVE_LIBM=n
 #
 CONFIG_BUILD_2PASS=n
 CONFIG_PASS1_BUILDIR=configs/ne64badge/initrel
-CONFIG_PASS1_OBJECT=init.r
+CONFIG_PASS1_TARGET=init.r
+CONFIG_PASS1_OBJECT=
 
 #
 # General OS setup
diff --git a/configs/sam3u-ek/README.txt b/configs/sam3u-ek/README.txt
index e077cbfbc0..2a10ddc70a 100755
--- a/configs/sam3u-ek/README.txt
+++ b/configs/sam3u-ek/README.txt
@@ -306,12 +306,25 @@ can be selected as follow:
 	cd -
 	. ./setenv.sh
 
-Where <subdir> is one of the following:
+Before sourcing the setenv.sh file above, you should examine it and perform
+edits as necessary so that BUILDROOT_BIN is the correct path to the directory
+than holds your toolchain binaries.
+
+And then build NuttX by simply typing the following.  At the conclusion of
+the make, the nuttx binary will reside in an ELF file called, simply, nuttx.
+
+	make
+
+The <subdir> that is provided above as an argument to the tools/configure.sh
+must be is one of the following:
 
   knsh:
     This is identical to the nsh configuration below except that NuttX
     is built as a kernel-mode, monolithic module and the user applications
-    are built separately.
+    are built separately.  This build requires a special make command; not
+    just 'make' but make with the following two arguments:
+
+	make pass1 pass2
 
   nsh:
     Configures the NuttShell (nsh) located at examples/nsh.  The
diff --git a/configs/sam3u-ek/kernel/Makefile b/configs/sam3u-ek/kernel/Makefile
index dd3e1892c4..0bffda7c0c 100755
--- a/configs/sam3u-ek/kernel/Makefile
+++ b/configs/sam3u-ek/kernel/Makefile
@@ -67,6 +67,8 @@ all: $(TOPDIR)/nuttx_user.elf $(TOPDIR)/User.map $(BOARD_INCLUDE)/user_map.h
 
 nuttx_user.elf:
 	@echo "LD:  nuttx_user.elf"
+	echo "USER_LDLIBS: $(USER_LDLIBS)"
+	echo "USER_LIBPATHS: $(USER_LIBPATHS)"
 	@$(LD) -o $@ $(USER_LDFLAGS) $(USER_LIBPATHS) --start-group $(USER_LDLIBS) --end-group $(USER_LIBGCC) 
 
 $(TOPDIR)/nuttx_user.elf: nuttx_user.elf
diff --git a/configs/sam3u-ek/kernel/kernel.ld b/configs/sam3u-ek/kernel/kernel.ld
index 88ec560001..72f79d9d71 100644
--- a/configs/sam3u-ek/kernel/kernel.ld
+++ b/configs/sam3u-ek/kernel/kernel.ld
@@ -64,6 +64,7 @@ MEMORY
 
 OUTPUT_ARCH(arm)
 ENTRY(user_start)
+EXTERN(user_start)
 SECTIONS
 {
 	.text : {
diff --git a/configs/sam3u-ek/knsh/Make.defs b/configs/sam3u-ek/knsh/Make.defs
index d735f887a2..83e766d770 100755
--- a/configs/sam3u-ek/knsh/Make.defs
+++ b/configs/sam3u-ek/knsh/Make.defs
@@ -117,7 +117,7 @@ LDNXFLATFLAGS = -e main -s 2048
 
 OBJEXT = .o
 LIBEXT = .a
-EXEEXT = .elf
+EXEEXT =
 
 ifneq ($(CROSSDEV),arm-elf-)
   LDFLAGS += -nostartfiles -nodefaultlibs
diff --git a/configs/sam3u-ek/knsh/defconfig b/configs/sam3u-ek/knsh/defconfig
index b59ac08bf8..b6aa4aba28 100755
--- a/configs/sam3u-ek/knsh/defconfig
+++ b/configs/sam3u-ek/knsh/defconfig
@@ -212,6 +212,7 @@ CONFIG_HAVE_LIBM=n
 #
 CONFIG_BUILD_2PASS=y
 CONFIG_PASS1_BUILDIR=configs/sam3u-ek/kernel
+CONFIG_PASS1_TARGET=all
 CONFIG_PASS1_OBJECT=
 
 #
diff --git a/configs/vsn/include/nsh_romfsimg.h b/configs/vsn/include/nsh_romfsimg.h
index 2ac240ec84..7fa7c28ee7 100755
--- a/configs/vsn/include/nsh_romfsimg.h
+++ b/configs/vsn/include/nsh_romfsimg.h
@@ -1,6 +1,6 @@
 unsigned char romfs_img[] = {
-  0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x02, 0x10,
-  0x85, 0xc5, 0xa3, 0x6a, 0x4e, 0x53, 0x48, 0x49, 0x6e, 0x69, 0x74, 0x56,
+  0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x02, 0x00,
+  0x95, 0x7e, 0x5e, 0x1a, 0x4e, 0x53, 0x48, 0x49, 0x6e, 0x69, 0x74, 0x56,
   0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
   0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97,
   0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -15,12 +15,12 @@ unsigned char romfs_img[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x60,
   0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xfe, 0xe0, 0x2e, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
-  0x8d, 0x9c, 0xab, 0xc6, 0x72, 0x63, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c,
+  0x8d, 0x9c, 0xab, 0xda, 0x72, 0x63, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x63, 0x68, 0x6f,
-  0x20, 0x22, 0x56, 0x53, 0x4e, 0x20, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x20,
-  0x31, 0x2e, 0x32, 0x2c, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x65, 0x74,
-  0x63, 0x6c, 0x61, 0x6d, 0x70, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x0a,
+  0x20, 0x22, 0x56, 0x53, 0x4e, 0x20, 0x4e, 0x75, 0x74, 0x74, 0x58, 0x20,
+  0x36, 0x2e, 0x31, 0x2c, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x6e, 0x65, 0x74,
+  0x43, 0x6c, 0x61, 0x6d, 0x70, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x22, 0x0a,
   0x0a, 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20,
   0x52, 0x41, 0x4d, 0x44, 0x49, 0x53, 0x4b, 0x20, 0x61, 0x6e, 0x64, 0x20,
   0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x20, 0x61, 0x74, 0x20,
@@ -30,19 +30,19 @@ unsigned char romfs_img[] = {
   0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x31, 0x0a, 0x23, 0x6d, 0x6f,
   0x75, 0x6e, 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76, 0x66, 0x61, 0x74, 0x20,
   0x2f, 0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x31, 0x20, 0x2f, 0x74,
-  0x6d, 0x70, 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x22, 0x4d, 0x6f,
-  0x75, 0x6e, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x46, 0x52, 0x41, 0x4d, 0x20,
-  0x74, 0x6f, 0x20, 0x2f, 0x75, 0x73, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20,
-  0x53, 0x44, 0x63, 0x61, 0x72, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x2f, 0x73,
-  0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x0a, 0x0a, 0x72, 0x61, 0x6d, 0x74,
-  0x72, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x33, 0x0a,
-  0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76, 0x66, 0x61,
-  0x74, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6d, 0x74, 0x64, 0x62, 0x6c,
-  0x6f, 0x63, 0x6b, 0x30, 0x20, 0x2f, 0x75, 0x73, 0x72, 0x0a, 0x0a, 0x73,
-  0x64, 0x63, 0x61, 0x72, 0x64, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20,
-  0x30, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76,
-  0x66, 0x61, 0x74, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6d, 0x6d, 0x63,
-  0x73, 0x64, 0x30, 0x20, 0x2f, 0x73, 0x64, 0x63, 0x61, 0x72, 0x64, 0x0a,
+  0x6d, 0x70, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2d, 0x74,
+  0x20, 0x62, 0x69, 0x6e, 0x66, 0x73, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f,
+  0x72, 0x61, 0x6d, 0x30, 0x20, 0x2f, 0x73, 0x62, 0x69, 0x6e, 0x0a, 0x0a,
+  0x72, 0x61, 0x6d, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x72,
+  0x74, 0x20, 0x33, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2d, 0x74,
+  0x20, 0x76, 0x66, 0x61, 0x74, 0x20, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6d,
+  0x74, 0x64, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x30, 0x20, 0x2f, 0x75, 0x73,
+  0x72, 0x0a, 0x0a, 0x73, 0x64, 0x63, 0x61, 0x72, 0x64, 0x20, 0x73, 0x74,
+  0x61, 0x72, 0x74, 0x20, 0x30, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20,
+  0x2d, 0x74, 0x20, 0x76, 0x66, 0x61, 0x74, 0x20, 0x2f, 0x64, 0x65, 0x76,
+  0x2f, 0x6d, 0x6d, 0x63, 0x73, 0x64, 0x30, 0x20, 0x2f, 0x73, 0x64, 0x63,
+  0x61, 0x72, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/configs/vsn/include/rcS.template b/configs/vsn/include/rcS.template
index 32f0df4e13..c7cd93cd46 100755
--- a/configs/vsn/include/rcS.template
+++ b/configs/vsn/include/rcS.template
@@ -1,11 +1,11 @@
-echo "VSN Board 1.2, www.netclamps.com"
+echo "VSN NuttX 6.1, www.netClamps.com"
 
 # Create a RAMDISK and mount it at XXXRDMOUNTPOUNTXXX
 #mkrd -m XXXMKRDMINORXXX -s XXMKRDSECTORSIZEXXX XXMKRDBLOCKSXXX
 #mkfatfs /dev/ramXXXMKRDMINORXXX
 #mount -t vfat /dev/ramXXXMKRDMINORXXX XXXRDMOUNTPOUNTXXX
 
-echo "Mounting FRAM to /usr and SDcard to /sdcard"
+mount -t binfs /dev/ram0 /sbin
 
 ramtron start 3
 mount -t vfat /dev/mtdblock0 /usr
diff --git a/configs/vsn/nsh/defconfig b/configs/vsn/nsh/defconfig
index 1d2bbe0c94..b51342cb52 100755
--- a/configs/vsn/nsh/defconfig
+++ b/configs/vsn/nsh/defconfig
@@ -145,7 +145,7 @@ CONFIG_STM32_FSMC=n
 CONFIG_STM32_SDIO=y
 # APB1:
 CONFIG_STM32_TIM2=n
-CONFIG_STM32_TIM3=n
+CONFIG_STM32_TIM3=y
 CONFIG_STM32_TIM4=n
 CONFIG_STM32_TIM5=n
 CONFIG_STM32_TIM6=n
@@ -157,8 +157,8 @@ CONFIG_STM32_USART2=n
 CONFIG_STM32_USART3=n
 CONFIG_STM32_UART4=n
 CONFIG_STM32_UART5=n
-CONFIG_STM32_I2C1=n
-CONFIG_STM32_I2C2=n
+CONFIG_STM32_I2C1=y
+CONFIG_STM32_I2C2=y
 CONFIG_STM32_USB=n
 CONFIG_STM32_CAN=n
 CONFIG_STM32_BKP=n
@@ -169,7 +169,7 @@ CONFIG_STM32_ADC1=n
 CONFIG_STM32_ADC2=n
 CONFIG_STM32_TIM1=n
 CONFIG_STM32_SPI1=n
-CONFIG_STM32_TIM8=n
+CONFIG_STM32_TIM8=y
 CONFIG_STM32_USART1=y
 CONFIG_STM32_ADC3=n
 
@@ -248,6 +248,11 @@ CONFIG_SSI1_DISABLE=y
 CONFIG_SSI_POLLWAIT=y
 #CONFIG_SSI_TXLIMIT=4
 
+#
+# OS support for I2C
+#
+CONFIG_I2C=y
+
 #
 # General build options
 #
diff --git a/configs/vsn/src/sif.c b/configs/vsn/src/sif.c
index c1813df83e..a10072ac5a 100644
--- a/configs/vsn/src/sif.c
+++ b/configs/vsn/src/sif.c
@@ -70,7 +70,7 @@
 
 #include <nuttx/config.h>
 #include <nuttx/fs.h>
-#include <nuttx/i2c.h>
+#include <nuttx/i2c/i2c.h>
 #include <semaphore.h>
 
 #include <stdio.h>
@@ -80,6 +80,7 @@
 #include <errno.h>
 
 #include "vsn.h"
+#include <nuttx/i2c/st_lis331dl.h>
 
 
 /****************************************************************************
@@ -272,23 +273,6 @@ int sif_gpios_unlock(vsn_sif_state_t peripheral)
 }
 
 
-/****************************************************************************
- * ST LIS331DL
- ****************************************************************************/ 
-
-void st_lis331dl_open(void)
-{
-}
-
-
-void st_lis331dl_config(void)
-{
-}
-
-
-void st_lis331dl_getreadings(void)
-{
-}
 
 
 /****************************************************************************
@@ -518,7 +502,32 @@ int sif_main(int argc, char *argv[])
             STM32_TIM_SETCOMPARE(vsn_sif.tim8, GPIO_OUT_PWRPWM_TIM8_CH, val);
             return 0;
         }
-        else if (!strcmp(argv[1], "c")) {
+        else if (!strcmp(argv[1], "i2c") && argc == 3) {
+            int val = atoi(argv[2]);
+            struct st_lis331dl_dev_s * lis = st_lis331dl_init(vsn_sif.i2c1, val);
+
+            if (lis) {
+                struct st_lis331dl_vector_s * a;
+                int i;
+                
+                /* Sample some values */
+                
+                for (i=0; i<20; i++) {
+                    if ( (a = st_lis331dl_getreadings(lis)) ) 
+                        printf("%d %d %d\n", a->x, a->y, a->z);
+                    else {
+                        printf("Readings errno %d\n", errno);
+                        break;
+                    }
+                    fflush(stdout);
+                    usleep(100000);
+                }
+                
+                st_lis331dl_deinit(lis);
+            }
+            else printf("Exit point: errno=%d\n", errno);
+
+            return 0;
         }
     }
 
diff --git a/drivers/Makefile b/drivers/Makefile
index 7c46280c52..01143a0715 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -94,6 +94,13 @@ include mtd/Make.defs
 ROOTDEPPATH	= --dep-path .
 MTDDEPPATH	= --dep-path mtd
 
+ifeq ($(CONFIG_I2C),y)
+include i2c/Make.defs
+ROOTDEPPATH	= --dep-path .
+I2CDEPPATH	= --dep-path i2c
+CFLAGS		+= ${shell $(TOPDIR)/tools/incdir.sh $(INCDIROPT) "$(CC)" $(TOPDIR)/drivers/i2c}
+endif
+
 ASRCS		= $(SERIAL_ASRCS) $(NET_ASRCS) $(PIPE_ASRCS) $(USBDEV_ASRCS) \
 			  $(USBHOST_ASRCS) $(MMCSD_ASRCS) $(LCD_ASRCS) $(BCH_ASRCS) \
 			  $(MTD_ASRCS)
diff --git a/drivers/i2c/Make.defs b/drivers/i2c/Make.defs
new file mode 100644
index 0000000000..2358d533b9
--- /dev/null
+++ b/drivers/i2c/Make.defs
@@ -0,0 +1,42 @@
+############################################################################
+# drivers/i2c/Make.defs
+#
+#   Copyright (C) 2011 Gregory Nutt. All rights reserved.
+#   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+#    used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+I2C_ASRCS  =
+I2C_CSRCS  = 
+
+ifeq ($(CONFIG_I2C),y)
+I2C_CSRCS  += st_lis331dl.c
+endif
+
diff --git a/drivers/i2c/st_lis331dl.c b/drivers/i2c/st_lis331dl.c
new file mode 100644
index 0000000000..cb1d7f47db
--- /dev/null
+++ b/drivers/i2c/st_lis331dl.c
@@ -0,0 +1,270 @@
+/****************************************************************************
+ * drivers/i2c/st_lis331dl.c
+ *
+ *   Copyright (C) 2011 Uros Platise. All rights reserved.
+ *
+ *   Authors: Uros Platise <uros.platise@isotel.eu>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/** \file
+ *  \author Uros Platise
+ *  \brief ST LIS331DL I2C Device Driver
+ **/ 
+ 
+#include <nuttx/config.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <nuttx/i2c/st_lis331dl.h>
+ 
+/************************************************************************************
+ * Private Data Types
+ ************************************************************************************/
+
+struct st_lis331dl_dev_s {
+    struct i2c_dev_s *          i2c;
+    
+    uint8_t                     address;
+    struct st_lis331dl_vector_s a;
+    uint8_t                     cr1;
+    uint8_t                     cr2;    
+    uint8_t                     cr3;
+};
+
+ 
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/** LIS331DL Access with range check
+ * 
+ * \param dev LIS331 DL Private Structure
+ * \param subaddr LIS331 Sub Address
+ * \param buf Pointer to buffer, either for read or write access
+ * \param length when >0 it denotes read access, when <0 it denotes write access of -length
+ * \return OK on success or errno is set.
+ **/
+int st_lis331dl_access(struct st_lis331dl_dev_s * dev, uint8_t subaddr, uint8_t *buf, int length)
+{
+    uint16_t flags = 0;
+    int      retval;
+    
+    if (length > 0) {
+        flags = I2C_M_READ; 
+    }
+    else {
+        flags = I2C_M_NORESTART;
+        length = -length;
+    }
+
+    /* Check valid address ranges and set auto address increment flag */
+    
+    if (subaddr == 0x0F) {
+        if (length > 1) length = 1;
+    }
+    else if (subaddr >= 0x20 && subaddr < 0x24) {
+        if (length > (0x24 - subaddr) ) length = 0x24 - subaddr;
+    }
+    else if (subaddr >= 0x27 && subaddr < 0x2E) {
+        if (length > (0x2E - subaddr) ) length = 0x2E - subaddr;
+    }
+    else if (subaddr >= 0x30 && subaddr < 0x40) {
+        if (length > (0x40 - subaddr) ) length = 0x40 - subaddr;
+    }
+    else {
+        errno = EFAULT;
+        return ERROR;
+    }
+
+    subaddr |= 0x80;
+    
+    /* Create message and send */
+    
+    struct i2c_msg_s msgv[2] = {
+      {
+        .addr   = dev->address,
+        .flags  = 0,
+        .buffer = &subaddr,
+        .length = 1
+      },
+      {
+        .addr   = dev->address,
+        .flags  = flags,
+        .buffer = buf,
+        .length = length
+      }
+    };
+    
+    if ( (retval = I2C_TRANSFER(dev->i2c, msgv, 2)) == OK )
+        return length;
+        
+    return retval;
+}
+
+
+int st_lis331dl_readregs(struct st_lis331dl_dev_s * dev)
+{
+    if (st_lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, 3) == ERROR) return ERROR;    
+    
+    printf("CR1=%2x, CR2=%2x, CR3=%2x\n", dev->cr1, dev->cr2, dev->cr3 );
+    return OK;
+}
+
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+struct st_lis331dl_dev_s * st_lis331dl_init(struct i2c_dev_s * i2c, uint16_t address)
+{
+    struct st_lis331dl_dev_s * dev;
+    uint8_t retval;
+    
+    ASSERT(i2c);
+    ASSERT(address);
+    
+    if ( (dev = malloc( sizeof(struct st_lis331dl_dev_s) )) == NULL )
+        return NULL;
+        
+    memset(dev, 0, sizeof(struct st_lis331dl_dev_s));
+    dev->i2c     = i2c;
+    dev->address = address;
+    
+    /* Probe device */
+    
+    if (st_lis331dl_access(dev, ST_LIS331DL_WHOAMI, &retval, 1) > 0) {
+    
+        /* Check chip identification, in the future several more compatible parts
+         * may be added here.
+         */
+         
+        if (retval == ST_LIS331DL_WHOAMI_VALUE) {
+        
+            /* Copy LIS331DL registers to our private structure and power-up device */
+            
+            if ( st_lis331dl_readregs(dev)==OK && st_lis331dl_powerup(dev)==OK) {
+      
+                /* Normal exit point */
+                errno = 0;
+                return dev;
+            }
+            retval = errno;
+        }
+        
+        /* Otherwise, we mark an invalid device found at given address */
+        retval = ENODEV;
+    }
+    else {
+        /* No response at given address is marked as */
+        retval = EFAULT;
+    }
+
+    /* Error exit */
+    free(dev);
+    errno = retval;
+    return NULL;
+}
+
+
+int st_lis331dl_deinit(struct st_lis331dl_dev_s * dev)
+{
+    ASSERT(dev);
+    
+//  st_lis331dl_powerdown(dev);
+    free(dev);
+    
+    return OK;
+}
+
+
+int st_lis331dl_powerup(struct st_lis331dl_dev_s * dev)
+{
+    dev->cr1 = ST_LIS331DL_CR1_PD |
+        ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN;
+        
+    st_lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -1);    
+    return OK;
+}
+
+
+int st_lis331dl_powerdown(struct st_lis331dl_dev_s * dev)
+{
+    dev->cr1 = ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN;
+        
+    return st_lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -1);
+}
+
+
+int st_lis331dl_setconversion(struct st_lis331dl_dev_s * dev, bool full, bool fast)
+{
+    dev->cr1 = ST_LIS331DL_CR1_PD | 
+        (full ? ST_LIS331DL_CR1_FS : 0) | (fast ? ST_LIS331DL_CR1_DR : 0) |
+        ST_LIS331DL_CR1_ZEN | ST_LIS331DL_CR1_YEN | ST_LIS331DL_CR1_XEN;
+        
+    st_lis331dl_access(dev, ST_LIS331DL_CTRL_REG1, &dev->cr1, -1);    
+    return OK;
+}
+
+
+float st_lis331dl_getprecision(struct st_lis331dl_dev_s * dev)
+{
+    if (dev->cr1 & ST_LIS331DL_CR1_FS)
+        return 9.0/127.0;   /* ~9g full scale */
+    return 2.0/127.0;       /* ~2g full scale */
+}
+
+
+int st_lis331dl_getsamplerate(struct st_lis331dl_dev_s * dev)
+{   
+    if (dev->cr1 & ST_LIS331DL_CR1_DR)
+        return 400;
+    return 100;
+}
+
+
+const struct st_lis331dl_vector_s * st_lis331dl_getreadings(struct st_lis331dl_dev_s * dev)
+{
+    uint8_t retval[5];
+
+    ASSERT(dev);
+    
+    if (st_lis331dl_access(dev, ST_LIS331DL_OUT_X, retval, 5) == 5) {    
+        dev->a.x = retval[0];
+        dev->a.y = retval[2];
+        dev->a.z = retval[4];
+        return &dev->a;
+    }
+    
+    return NULL;
+}
diff --git a/include/nuttx/i2c.h b/include/nuttx/i2c/i2c.h
similarity index 90%
rename from include/nuttx/i2c.h
rename to include/nuttx/i2c/i2c.h
index 379105fc6e..571c3c4016 100644
--- a/include/nuttx/i2c.h
+++ b/include/nuttx/i2c/i2c.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * include/nuttx/i2c.h
+ * include/nuttx/i2c/i2c.h
  *
  *   Copyright(C) 2009-2011 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -33,8 +33,8 @@
  *
  ****************************************************************************/
 
-#ifndef __NUTTX_I2C_H
-#define __NUTTX_I2C_H
+#ifndef __INCLUDE_NUTTX_I2C_I2C_H
+#define __INCLUDE_NUTTX_I2C_I2C_H
 
 /****************************************************************************
  * Included Files
@@ -75,6 +75,7 @@
 
 #define I2C_M_READ           0x0001          /* read data, from slave to master */
 #define I2C_M_TEN            0x0002          /* ten bit address */
+#define I2C_M_NORESTART      0x0080          /* message should not begin with (re-)start of transfer */
 
 /* Access macros */
 
@@ -183,6 +184,28 @@
 
 #define I2C_READ(d,b,l) ((d)->ops->read(d,b,l))
 
+/****************************************************************************
+ * Name: I2C_WRITEREAD
+ *
+ * Description:
+ *   Send a block of data on I2C using the previously selected I2C
+ *   frequency and slave address, followed by restarted read access. 
+ *   It provides a convenient wrapper to the transfer function.
+ *
+ * Input Parameters:
+ *   dev -    Device-specific state data
+ *   wbuffer - A pointer to the read-only buffer of data to be written to device
+ *   wbuflen - The number of bytes to send from the buffer
+ *   rbuffer - A pointer to a buffer of data to receive the data from the device
+ *   rbuflen - The requested number of bytes to be read
+ *
+ * Returned Value:
+ *   0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+#define I2C_WRITEREAD(d,wb,wl,rb,rl) ((d)->ops->writeread(d,wb,wl,rb,rl))
+
 /****************************************************************************
  * Name: I2C_TRANSFER
  *
@@ -307,4 +330,4 @@ EXTERN int up_i2cuninitialize(FAR struct i2c_dev_s * dev);
 #if defined(__cplusplus)
 }
 #endif
-#endif /* __NUTTX_I2C_H */
+#endif /* __INCLUDE_NUTTX_I2C_I2C_H */
diff --git a/include/nuttx/i2c/st_lis331dl.h b/include/nuttx/i2c/st_lis331dl.h
new file mode 100644
index 0000000000..f3f1373912
--- /dev/null
+++ b/include/nuttx/i2c/st_lis331dl.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+ * include/nuttx/i2c/st_lis331dl.h
+ *
+ *   Copyright (C) 2011 Uros Platise. All rights reserved.
+ *
+ *   Authors: Uros Platise <uros.platise@isotel.eu>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/** \file
+ *  \author Uros Platise
+ *  \brief ST LIS331DL I2C Device Driver
+ **/ 
+
+#ifndef __INCLUDE_NUTTX_I2C_ST_LIS331DL_H
+#define __INCLUDE_NUTTX_I2C_ST_LIS331DL_H
+
+#include <nuttx/i2c/i2c.h>
+#include <stdbool.h>
+
+
+/************************************************************************************
+ * Pre-Processor Declarations
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/************************************************************************************
+ * LIS331DL Internal Registers
+ ************************************************************************************/
+
+#define ST_LIS331DL_WHOAMI          0x0F    /* who am I register */
+#define ST_LIS331DL_WHOAMI_VALUE    0x3B    /* Valid result is 0x3B */
+
+#define ST_LIS331DL_CTRL_REG1       0x20
+#define ST_LIS331DL_CR1_DR          0x80    /* Data-rate selection 0: 100 Hz, 1: 400 Hz */
+#define ST_LIS331DL_CR1_PD          0x40    /* Active Mode (1) / Power-down (0) */
+#define ST_LIS331DL_CR1_FS          0x20    /* Full Scale (1) +-9g or Normal Scale (0) +-2g */
+#define ST_LIS331DL_CR1_ST          0x18    /* Self test enable */
+#define ST_LIS331DL_CR1_ZEN         0x04    /* Z-Axis Enable */
+#define ST_LIS331DL_CR1_YEN         0x02    /* Y-Axis Enable */
+#define ST_LIS331DL_CR1_XEN         0x01    /* X-Axis Enable */
+
+#define ST_LIS331DL_CTRL_REG2       0x21
+#define ST_LIS331DL_CTRL_REG3       0x22
+
+#define ST_LIS331DL_HP_FILTER_RESET 0x23
+
+#define ST_LIS331DL_STATUS_REG      0x27
+
+#define ST_LIS331DL_OUT_X           0x29
+#define ST_LIS331DL_OUT_Y           0x2B
+#define ST_LIS331DL_OUT_Z           0x2D
+
+
+/************************************************************************************
+ * Public Data Types
+ ************************************************************************************/
+
+struct st_lis331dl_dev_s;
+
+struct st_lis331dl_vector_s {
+    int8_t  x, y, z;
+};
+
+
+/************************************************************************************
+ * Public Function Prototypes
+ ************************************************************************************/
+
+/** Initialize ST LIS331DL Chip
+ * 
+ * \param i2c I2C Device Structure
+ * \param address I2C Address of the proposed device
+ * \return Pointer to newly allocated ST LIS331DL structure or NULL on error with errno set.
+ * 
+ * Possible errno as set by this function on error:
+ *  - ENODEV: When device addressed on given address is not compatible or it is not a LIS331DL
+ *  - EFAULT: When there is no device at given address.
+ *  - EBUSY: When device is already addressed by other device driver (not yet supported by low-level driver)
+ **/
+EXTERN struct st_lis331dl_dev_s * st_lis331dl_init(struct i2c_dev_s * i2c, uint16_t address);
+
+/** Deinitialize ST LIS331DL Chip
+ * 
+ * \param dev Device to LIS331DL device structure, as returned by the st_lis331dl_init()
+ * \return OK On success
+ * 
+ **/
+EXTERN int st_lis331dl_deinit(struct st_lis331dl_dev_s * dev);
+
+/** Power up device, start conversion */
+EXTERN int st_lis331dl_powerup(struct st_lis331dl_dev_s * dev);
+
+/** Power down device, stop conversion */
+EXTERN int st_lis331dl_powerdown(struct st_lis331dl_dev_s * dev);
+
+/** Configure conversion 
+ * 
+ * \param dev Device to LIS331DL device structure
+ * \param full When set, range of [-9g, 9g] is selected, otherwise [-2g, +2g]
+ * \param fast When set, conversion operates at 400 Hz, otherwise at 100 Hz
+ * \return OK on success or errno is set
+ **/
+EXTERN int st_lis331dl_setconversion(struct st_lis331dl_dev_s * dev, bool full, bool fast);
+
+/** Get precision
+ * 
+ * \return Precision of 1 LSB in terms of unit [g]
+ **/
+EXTERN float st_lis331dl_getprecision(struct st_lis331dl_dev_s * dev);
+
+/** Get sample rate 
+ * 
+ * \return Sample rate in unit of [Hz]
+ **/
+EXTERN int st_lis331dl_getsamplerate(struct st_lis331dl_dev_s * dev);
+
+/** Get readings, updates internal data structure
+ * 
+ * \param dev Device to LIS331DL device structure
+ * \return Ptr to vector acceleration [x,y,z] on success, or NULL on error with errno set
+ */
+EXTERN const struct st_lis331dl_vector_s * st_lis331dl_getreadings(struct st_lis331dl_dev_s * dev);
+
+
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __INCLUDE_NUTTX_I2C_ST_LIS331DL_H */
+
-- 
GitLab