From 139456d3cb1a8c7be9e48d765eda23b15d8c8bad Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 3 Apr 2011 14:26:05 +0000 Subject: 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 --- apps/examples/ostest/mqueue.c | 6 +- apps/examples/ostest/sighand.c | 6 +- apps/examples/ostest/timedmqueue.c | 12 +- apps/namedapp/binfs.c | 2 +- apps/netutils/dhcpc/dhcpc.c | 4 +- apps/netutils/thttpd/thttpd_cgi.c | 2 +- apps/nshlib/nsh_apps.c | 7 +- nuttx/ChangeLog | 9 + nuttx/Documentation/NuttX.html | 19 +- nuttx/Documentation/NuttxPortingGuide.html | 32 +- nuttx/Makefile | 22 +- nuttx/TODO | 12 +- nuttx/arch/arm/src/lpc313x/lpc313x_i2c.c | 2 +- nuttx/arch/arm/src/stm32/chip/stm32_i2c.h | 6 +- nuttx/arch/arm/src/stm32/stm32_i2c.c | 434 ++++++++++++++++++++-------- nuttx/arch/arm/src/stm32/stm32_i2c.h | 2 +- nuttx/arch/z80/src/ez80/ez80_i2c.c | 4 +- nuttx/arch/z80/src/z8/z8_i2c.c | 4 +- nuttx/configs/README.txt | 14 +- nuttx/configs/demo9s12ne64/ostest/defconfig | 3 +- nuttx/configs/ea3131/locked/Makefile | 2 +- nuttx/configs/ea3131/pgnsh/defconfig | 1 + nuttx/configs/ne64badge/ostest/defconfig | 3 +- nuttx/configs/sam3u-ek/README.txt | 17 +- nuttx/configs/sam3u-ek/kernel/Makefile | 2 + nuttx/configs/sam3u-ek/kernel/kernel.ld | 1 + nuttx/configs/sam3u-ek/knsh/Make.defs | 2 +- nuttx/configs/sam3u-ek/knsh/defconfig | 1 + nuttx/configs/vsn/include/nsh_romfsimg.h | 40 +-- nuttx/configs/vsn/include/rcS.template | 4 +- nuttx/configs/vsn/nsh/defconfig | 13 +- nuttx/configs/vsn/src/sif.c | 47 +-- nuttx/drivers/Makefile | 7 + nuttx/drivers/i2c/Make.defs | 42 +++ nuttx/drivers/i2c/st_lis331dl.c | 270 +++++++++++++++++ nuttx/include/nuttx/i2c.h | 310 -------------------- nuttx/include/nuttx/i2c/i2c.h | 333 +++++++++++++++++++++ nuttx/include/nuttx/i2c/st_lis331dl.h | 170 +++++++++++ 38 files changed, 1340 insertions(+), 527 deletions(-) create mode 100644 nuttx/drivers/i2c/Make.defs create mode 100644 nuttx/drivers/i2c/st_lis331dl.c delete mode 100644 nuttx/include/nuttx/i2c.h create mode 100644 nuttx/include/nuttx/i2c/i2c.h create mode 100644 nuttx/include/nuttx/i2c/st_lis331dl.h diff --git a/apps/examples/ostest/mqueue.c b/apps/examples/ostest/mqueue.c index e68cfc012..95e6bbfc8 100644 --- a/apps/examples/ostest/mqueue.c +++ b/apps/examples/ostest/mqueue.c @@ -1,5 +1,5 @@ /************************************************************************** - * mqueue.c + * apps/examples/ostest/mqueue.c * * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -212,9 +212,9 @@ static void *receiver_thread(void *arg) * it is not a failure. */ - if (*get_errno_ptr() != EINTR) + if (errno != EINTR) { - printf("receiver_thread: ERROR mq_receive failure on msg %d, errno=%d\n", i, *get_errno_ptr()); + printf("receiver_thread: ERROR mq_receive failure on msg %d, errno=%d\n", i, errno); nerrors++; } else diff --git a/apps/examples/ostest/sighand.c b/apps/examples/ostest/sighand.c index 46650be1c..66f98cb58 100644 --- a/apps/examples/ostest/sighand.c +++ b/apps/examples/ostest/sighand.c @@ -1,7 +1,7 @@ /*********************************************************************** - * examples/ostest/sighand.c + * apps/examples/ostest/sighand.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -160,7 +160,7 @@ static int waiter_main(int argc, char *argv[]) status = sem_wait(&sem); if (status != 0) { - int error = *get_errno_ptr(); + int error = errno; if (error == EINTR) { printf("waiter_main: sem_wait() successfully interrupted by signal\n" ); diff --git a/apps/examples/ostest/timedmqueue.c b/apps/examples/ostest/timedmqueue.c index 9c14ec414..49fe1c4c6 100644 --- a/apps/examples/ostest/timedmqueue.c +++ b/apps/examples/ostest/timedmqueue.c @@ -1,7 +1,7 @@ /************************************************************************** - * examples/ostest/mqueue.c + * apps/examples/ostest/mqueue.c * - * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -157,13 +157,13 @@ static void *sender_thread(void *arg) status = mq_timedsend(mqfd, msg_buffer, TEST_MSGLEN, 42, &time); if (status < 0) { - if (i == TEST_SEND_NMSGS-1 && *get_errno_ptr() == ETIMEDOUT) + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) { printf("sender_thread: mq_timedsend %d timed out as expected\n", i); } else { - printf("sender_thread: ERROR mq_timedsend failure=%d on msg %d\n", *get_errno_ptr(), i); + printf("sender_thread: ERROR mq_timedsend failure=%d on msg %d\n", errno, i); nerrors++; } } @@ -248,13 +248,13 @@ static void *receiver_thread(void *arg) nbytes = mq_timedreceive(mqfd, msg_buffer, TEST_MSGLEN, 0, &time); if (nbytes < 0) { - if (i == TEST_SEND_NMSGS-1 && *get_errno_ptr() == ETIMEDOUT) + if (i == TEST_SEND_NMSGS-1 && errno == ETIMEDOUT) { printf("receiver_thread: Receive %d timed out as expected\n", i); } else { - printf("receiver_thread: ERROR mq_timedreceive failure=%d on msg %d\n", *get_errno_ptr(), i); + printf("receiver_thread: ERROR mq_timedreceive failure=%d on msg %d\n", errno, i); nerrors++; } } diff --git a/apps/namedapp/binfs.c b/apps/namedapp/binfs.c index 15ed4cc88..a2f14dd75 100644 --- a/apps/namedapp/binfs.c +++ b/apps/namedapp/binfs.c @@ -156,7 +156,7 @@ static void binfs_semtake(struct binfs_state_s *bm) * the wait was awakened by a signal. */ - ASSERT(*get_errno_ptr() == EINTR); + ASSERT(errno == EINTR); } } diff --git a/apps/netutils/dhcpc/dhcpc.c b/apps/netutils/dhcpc/dhcpc.c index dc80988bb..b5551c6f1 100644 --- a/apps/netutils/dhcpc/dhcpc.c +++ b/apps/netutils/dhcpc/dhcpc.c @@ -492,7 +492,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult) * Then loop and send the DISCOVER command again. */ - else if (*get_errno_ptr() != EAGAIN) + else if (errno != EAGAIN) { /* An error other than a timeout was received -- error out */ @@ -570,7 +570,7 @@ int dhcpc_request(void *handle, struct dhcpc_state *presult) * 3 times). */ - else if (*get_errno_ptr() != EAGAIN) + else if (errno != EAGAIN) { /* An error other than a timeout was received */ diff --git a/apps/netutils/thttpd/thttpd_cgi.c b/apps/netutils/thttpd/thttpd_cgi.c index ee126795a..3d2eb57b8 100755 --- a/apps/netutils/thttpd/thttpd_cgi.c +++ b/apps/netutils/thttpd/thttpd_cgi.c @@ -152,7 +152,7 @@ static inline void cgi_semtake(void) * awakened by a signal. */ - ASSERT(*get_errno_ptr() == EINTR); + ASSERT(errno == EINTR); } } diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_apps.c index a8f9eb9bf..c41f2448a 100644 --- a/apps/nshlib/nsh_apps.c +++ b/apps/nshlib/nsh_apps.c @@ -46,6 +46,7 @@ #include #include +#include #include @@ -98,7 +99,8 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, { int err = -errno; int i; - + +#ifndef CONFIG_APPS_BINDIR /* On failure, list the set of available built-in commands */ nsh_output(vtbl, "Builtin Apps: "); @@ -116,6 +118,9 @@ int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, } return OK; +#else + return err; +#endif } #ifdef CONFIG_SCHED_WAITPID diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index b1a1903df..13e40f303 100644 --- a/nuttx/ChangeLog +++ b/nuttx/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/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index 224b1bef8..5721c5eff 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: March 30, 2011

+

Last Updated: April 3, 2011

@@ -2188,11 +2188,28 @@ nuttx-6.1 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * 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 <spudmonkey@racsa.co.cr> * 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 <spudmonkey@racsa.co.cr> diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index ef444506f..eaa603a4a 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@

NuttX RTOS Porting Guide

-

Last Updated: April 1, 2011

+

Last Updated: April 3, 2011

@@ -2034,7 +2034,7 @@ extern void up_ledoff(int led);
  • - include/nuttx/i2c.h. + include/nuttx/i2c/i2c.h. All structures and APIs needed to work with I2C drivers are provided in this header file.

  • @@ -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.

    @@ -2805,15 +2805,27 @@ build

    • - CONFIG_PASS1_OBJECT: The name of the first pass object. +

      + CONFIG_PASS1_TARGET: The name of the first pass build target. +

    • 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), and
      • -
      • The usual depend, clean, and distclean targets.
      • -
      +

      + 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 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/nuttx/Makefile b/nuttx/Makefile index dea43c109..1ecc8563e 100644 --- a/nuttx/Makefile +++ b/nuttx/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/nuttx/TODO b/nuttx/TODO index 99be2df88..d9b2491b0 100644 --- a/nuttx/TODO +++ b/nuttx/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/nuttx/arch/arm/src/lpc313x/lpc313x_i2c.c b/nuttx/arch/arm/src/lpc313x/lpc313x_i2c.c index 137b2b315..dc2e454b9 100644 --- a/nuttx/arch/arm/src/lpc313x/lpc313x_i2c.c +++ b/nuttx/arch/arm/src/lpc313x/lpc313x_i2c.c @@ -50,7 +50,7 @@ #include #include -#include +#include #include #include diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h index 3510b2f41..00a24b355 100644 --- a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h +++ b/nuttx/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/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c index 05afd5a7b..de9ca60c8 100644 --- a/nuttx/arch/arm/src/stm32/stm32_i2c.c +++ b/nuttx/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 #include #include +#include #include #include +#include #include #include #include @@ -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/nuttx/arch/arm/src/stm32/stm32_i2c.h b/nuttx/arch/arm/src/stm32/stm32_i2c.h index 23a06bc05..9bb17521a 100755 --- a/nuttx/arch/arm/src/stm32/stm32_i2c.h +++ b/nuttx/arch/arm/src/stm32/stm32_i2c.h @@ -41,7 +41,7 @@ ************************************************************************************/ #include -#include +#include #include "chip.h" #include "chip/stm32_i2c.h" diff --git a/nuttx/arch/z80/src/ez80/ez80_i2c.c b/nuttx/arch/z80/src/ez80/ez80_i2c.c index d9defb0cf..74dc89919 100644 --- a/nuttx/arch/z80/src/ez80/ez80_i2c.c +++ b/nuttx/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 * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include diff --git a/nuttx/arch/z80/src/z8/z8_i2c.c b/nuttx/arch/z80/src/z8/z8_i2c.c index 796f389ec..11825ac59 100755 --- a/nuttx/arch/z80/src/z8/z8_i2c.c +++ b/nuttx/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 * * Redistribution and use in source and binary forms, with or without @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include /* eZ8 Register definitions */ diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt index 152a45645..560aa2a11 100644 --- a/nuttx/configs/README.txt +++ b/nuttx/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//src directory. General OS setup diff --git a/nuttx/configs/demo9s12ne64/ostest/defconfig b/nuttx/configs/demo9s12ne64/ostest/defconfig index 80cec002f..b5b432759 100755 --- a/nuttx/configs/demo9s12ne64/ostest/defconfig +++ b/nuttx/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/nuttx/configs/ea3131/locked/Makefile b/nuttx/configs/ea3131/locked/Makefile index 053781578..50c6c8a1d 100755 --- a/nuttx/configs/ea3131/locked/Makefile +++ b/nuttx/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/nuttx/configs/ea3131/pgnsh/defconfig b/nuttx/configs/ea3131/pgnsh/defconfig index 859b606be..aa18038b9 100755 --- a/nuttx/configs/ea3131/pgnsh/defconfig +++ b/nuttx/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/nuttx/configs/ne64badge/ostest/defconfig b/nuttx/configs/ne64badge/ostest/defconfig index 47ce5e58b..61f09986d 100755 --- a/nuttx/configs/ne64badge/ostest/defconfig +++ b/nuttx/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/nuttx/configs/sam3u-ek/README.txt b/nuttx/configs/sam3u-ek/README.txt index e077cbfbc..2a10ddc70 100755 --- a/nuttx/configs/sam3u-ek/README.txt +++ b/nuttx/configs/sam3u-ek/README.txt @@ -306,12 +306,25 @@ can be selected as follow: cd - . ./setenv.sh -Where 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 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/nuttx/configs/sam3u-ek/kernel/Makefile b/nuttx/configs/sam3u-ek/kernel/Makefile index dd3e1892c..0bffda7c0 100755 --- a/nuttx/configs/sam3u-ek/kernel/Makefile +++ b/nuttx/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/nuttx/configs/sam3u-ek/kernel/kernel.ld b/nuttx/configs/sam3u-ek/kernel/kernel.ld index 88ec56000..72f79d9d7 100644 --- a/nuttx/configs/sam3u-ek/kernel/kernel.ld +++ b/nuttx/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/nuttx/configs/sam3u-ek/knsh/Make.defs b/nuttx/configs/sam3u-ek/knsh/Make.defs index d735f887a..83e766d77 100755 --- a/nuttx/configs/sam3u-ek/knsh/Make.defs +++ b/nuttx/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/nuttx/configs/sam3u-ek/knsh/defconfig b/nuttx/configs/sam3u-ek/knsh/defconfig index b59ac08bf..b6aa4aba2 100755 --- a/nuttx/configs/sam3u-ek/knsh/defconfig +++ b/nuttx/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/nuttx/configs/vsn/include/nsh_romfsimg.h b/nuttx/configs/vsn/include/nsh_romfsimg.h index 2ac240ec8..7fa7c28ee 100755 --- a/nuttx/configs/vsn/include/nsh_romfsimg.h +++ b/nuttx/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/nuttx/configs/vsn/include/rcS.template b/nuttx/configs/vsn/include/rcS.template index 32f0df4e1..c7cd93cd4 100755 --- a/nuttx/configs/vsn/include/rcS.template +++ b/nuttx/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/nuttx/configs/vsn/nsh/defconfig b/nuttx/configs/vsn/nsh/defconfig index 1d2bbe0c9..b51342cb5 100755 --- a/nuttx/configs/vsn/nsh/defconfig +++ b/nuttx/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/nuttx/configs/vsn/src/sif.c b/nuttx/configs/vsn/src/sif.c index c1813df83..a10072ac5 100644 --- a/nuttx/configs/vsn/src/sif.c +++ b/nuttx/configs/vsn/src/sif.c @@ -70,7 +70,7 @@ #include #include -#include +#include #include #include @@ -80,6 +80,7 @@ #include #include "vsn.h" +#include /**************************************************************************** @@ -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/nuttx/drivers/Makefile b/nuttx/drivers/Makefile index 7c46280c5..01143a071 100644 --- a/nuttx/drivers/Makefile +++ b/nuttx/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/nuttx/drivers/i2c/Make.defs b/nuttx/drivers/i2c/Make.defs new file mode 100644 index 000000000..2358d533b --- /dev/null +++ b/nuttx/drivers/i2c/Make.defs @@ -0,0 +1,42 @@ +############################################################################ +# drivers/i2c/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# 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/nuttx/drivers/i2c/st_lis331dl.c b/nuttx/drivers/i2c/st_lis331dl.c new file mode 100644 index 000000000..cb1d7f47d --- /dev/null +++ b/nuttx/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 + * + * 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 +#include +#include +#include +#include +#include + +#include + +/************************************************************************************ + * 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/nuttx/include/nuttx/i2c.h b/nuttx/include/nuttx/i2c.h deleted file mode 100644 index 379105fc6..000000000 --- a/nuttx/include/nuttx/i2c.h +++ /dev/null @@ -1,310 +0,0 @@ -/**************************************************************************** - * include/nuttx/i2c.h - * - * Copyright(C) 2009-2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * 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. - * - ****************************************************************************/ - -#ifndef __NUTTX_I2C_H -#define __NUTTX_I2C_H - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* I2C address calculation. Convert 7- and 10-bit address to 8-bit and - * 16-bit read/write address - */ - -#define I2C_READBIT 0x01 - -/* Conver 7- to 8-bit address */ - -#define I2C_ADDR8(a) ((a) << 1) -#define I2C_WRITEADDR8(a) I2C_ADDR8(a) -#define I2C_READADDR8(a) (I2C_ADDR8(a) | I2C_READBIT) - -/* Convert 10- to 16-bit address */ - -#define I2C_ADDR10H(a) (0xf0 | (((a) >> 7) & 0x06)) -#define I2C_ADDR10L(a) ((a) & 0xff) - -#define I2C_WRITEADDR10H(a) I2C_ADDR10H(a) -#define I2C_WRITEADDR10L(a) I2C_ADDR10L(a) - -#define I2C_READADDR10H(a) (I2C_ADDR10H(a) | I2C_READBIT) -#define I2C_READADDR10L(a) I2C_ADDR10L(a) - -/* Bit definitions for the flags field in struct i2c_ops_s */ - -#define I2C_M_READ 0x0001 /* read data, from slave to master */ -#define I2C_M_TEN 0x0002 /* ten bit address */ - -/* Access macros */ - -/**************************************************************************** - * Name: I2C_SETFREQUENCY - * - * Description: - * Set the I2C frequency. This frequency will be retained in the struct - * i2c_dev_s instance and will be used with all transfers. Required. - * - * Input Parameters: - * dev - Device-specific state data - * frequency - The I2C frequency requested - * - * Returned Value: - * Returns the actual frequency selected - * - ****************************************************************************/ - -#define I2C_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f)) - -/**************************************************************************** - * Name: I2C_SETADDRESS - * - * Description: - * Set the I2C slave address. This frequency will be retained in the struct - * i2c_dev_s instance and will be used with all transfers. Required. - * - * Input Parameters: - * dev - Device-specific state data - * address - The I2C slave address - * nbits - The number of address bits provided (7 or 10) - * - * Returned Value: - * Returns OK on success; a negated errno on failure. - * - ****************************************************************************/ - -#define I2C_SETADDRESS(d,f,b) ((d)->ops->setaddress(d,f,b)) - -/**************************************************************************** - * Name: I2C_SETOWNADDRESS - * - * Description: - * Set our own I2C address. Calling this function enables Slave mode and - * disables Master mode on given instance (note that I2C is a bus, where - * multiple masters and slave may be handled by one device driver). - * - * One may register callback to be notifyed about reception. During the - * slave mode reception, the function READ and WRITE must be used to - * to handle reads and writes from a master. - * - * Input Parameters: - * dev - Device-specific state data - * address - Our own slave address; If it is 0x00, then the device driver - * listens to general call - * nbits - The number of address bits provided (7 or 10) - * - * Returned Value: - * OK on valid address and if the same address has not been assigned - * to other existance sharing the same port. Otherwise ERROR is returned. - * - ****************************************************************************/ - -#define I2C_SETOWNADDRESS(d,f,b) ((d)->ops->setownaddress(d,f,b)) - -/**************************************************************************** - * Name: I2C_WRITE - * - * Description: - * Send a block of data on I2C using the previously selected I2C - * frequency and slave address. Each write operational will be an 'atomic' - * operation in the sense that any other I2C actions will be serialized - * and pend until this write completes. Required. - * - * Input Parameters: - * dev - Device-specific state data - * buffer - A pointer to the read-only buffer of data to be written to device - * buflen - The number of bytes to send from the buffer - * - * Returned Value: - * 0: success, <0: A negated errno - * - ****************************************************************************/ - -#define I2C_WRITE(d,b,l) ((d)->ops->write(d,b,l)) - -/**************************************************************************** - * Name: I2C_READ - * - * Description: - * Receive a block of data from I2C using the previously selected I2C - * frequency and slave address. Each read operational will be an 'atomic' - * operation in the sense that any other I2C actions will be serialized - * and pend until this read completes. Required. - * - * Input Parameters: - * dev - Device-specific state data - * buffer - A pointer to a buffer of data to receive the data from the device - * buflen - The requested number of bytes to be read - * - * Returned Value: - * 0: success, <0: A negated errno - * - ****************************************************************************/ - -#define I2C_READ(d,b,l) ((d)->ops->read(d,b,l)) - -/**************************************************************************** - * Name: I2C_TRANSFER - * - * Description: - * Perform a sequence of I2C transfers, each transfer is started with a - * START and the final transfer is completed with a STOP. Each sequence - * will be an 'atomic' operation in the sense that any other I2C actions - * will be serialized and pend until this read completes. Optional. - * - * Input Parameters: - * dev - Device-specific state data - * msgs - A pointer to a set of message descriptors - * msgcount - The number of transfers to perform - * - * Returned Value: - * The number of transfers completed - * - ****************************************************************************/ - -#define I2C_TRANSFER(d,m,c) ((d)->ops->transfer(d,m,c)) - -/**************************************************************************** - * Public Types - ****************************************************************************/ - -/* The I2C vtable */ - -struct i2c_dev_s; -struct i2c_msg_s; -struct i2c_ops_s -{ - uint32_t (*setfrequency)(FAR struct i2c_dev_s *dev, uint32_t frequency); - int (*setaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); - int (*write)(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen); - int (*read)(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen); -#ifdef CONFIG_I2C_WRITEREAD - int (*writeread)(FAR struct i2c_dev_s *inst, const uint8_t *wbuffer, int wbuflen, - uint8_t *rbuffer, int rbuflen); -#endif -#ifdef CONFIG_I2C_TRANSFER - int (*transfer)(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count); -#endif -#ifdef CONFIG_I2C_SLAVE - int (*setownaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); - int (*registercallback)(FAR struct i2c_dev_s *dev, int (*callback)(void) ); -#endif -}; - -/* I2C transaction segment beginning with a START. A number of these can - * be transfered together to form an arbitrary sequence of write/read transfer - * to an I2C slave device. - */ - -struct i2c_msg_s -{ - uint16_t addr; /* Slave address */ - uint16_t flags; /* See I2C_M_* definitions */ - uint8_t *buffer; - int length; -}; - -/* I2C private data. This structure only defines the initial fields of the - * structure visible to the I2C client. The specific implementation may - * add additional, device specific fields after the vtable. - */ - -struct i2c_dev_s -{ - const struct i2c_ops_s *ops; /* I2C vtable */ -}; - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" { -#else -#define EXTERN extern -#endif - -/**************************************************************************** - * Name: up_i2cinitialize - * - * Description: - * Initialize the selected I2C port. And return a unique instance of struct - * struct i2c_dev_s. This function may be called to obtain multiple - * instances of the interface, each of which may be set up with a - * different frequency and slave address. - * - * Input Parameter: - * Port number (for hardware that has mutiple I2C interfaces) - * - * Returned Value: - * Valid I2C device structre reference on succcess; a NULL on failure - * - ****************************************************************************/ - -EXTERN FAR struct i2c_dev_s *up_i2cinitialize(int port); - - -/**************************************************************************** - * Name: up_i2cuninitialize - * - * Description: - * De-initialize the selected I2C port, and power down the device. - * - * Input Parameter: - * Device structure as returned by the up_i2cinitalize() - * - * Returned Value: - * OK on success, ERROR when internal reference count missmatch or dev - * points to invalid hardware device. - * - ****************************************************************************/ - -EXTERN int up_i2cuninitialize(FAR struct i2c_dev_s * dev); - -#undef EXTERN -#if defined(__cplusplus) -} -#endif -#endif /* __NUTTX_I2C_H */ diff --git a/nuttx/include/nuttx/i2c/i2c.h b/nuttx/include/nuttx/i2c/i2c.h new file mode 100644 index 000000000..571c3c401 --- /dev/null +++ b/nuttx/include/nuttx/i2c/i2c.h @@ -0,0 +1,333 @@ +/**************************************************************************** + * include/nuttx/i2c/i2c.h + * + * Copyright(C) 2009-2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_I2C_I2C_H +#define __INCLUDE_NUTTX_I2C_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* I2C address calculation. Convert 7- and 10-bit address to 8-bit and + * 16-bit read/write address + */ + +#define I2C_READBIT 0x01 + +/* Conver 7- to 8-bit address */ + +#define I2C_ADDR8(a) ((a) << 1) +#define I2C_WRITEADDR8(a) I2C_ADDR8(a) +#define I2C_READADDR8(a) (I2C_ADDR8(a) | I2C_READBIT) + +/* Convert 10- to 16-bit address */ + +#define I2C_ADDR10H(a) (0xf0 | (((a) >> 7) & 0x06)) +#define I2C_ADDR10L(a) ((a) & 0xff) + +#define I2C_WRITEADDR10H(a) I2C_ADDR10H(a) +#define I2C_WRITEADDR10L(a) I2C_ADDR10L(a) + +#define I2C_READADDR10H(a) (I2C_ADDR10H(a) | I2C_READBIT) +#define I2C_READADDR10L(a) I2C_ADDR10L(a) + +/* Bit definitions for the flags field in struct i2c_ops_s */ + +#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 */ + +/**************************************************************************** + * Name: I2C_SETFREQUENCY + * + * Description: + * Set the I2C frequency. This frequency will be retained in the struct + * i2c_dev_s instance and will be used with all transfers. Required. + * + * Input Parameters: + * dev - Device-specific state data + * frequency - The I2C frequency requested + * + * Returned Value: + * Returns the actual frequency selected + * + ****************************************************************************/ + +#define I2C_SETFREQUENCY(d,f) ((d)->ops->setfrequency(d,f)) + +/**************************************************************************** + * Name: I2C_SETADDRESS + * + * Description: + * Set the I2C slave address. This frequency will be retained in the struct + * i2c_dev_s instance and will be used with all transfers. Required. + * + * Input Parameters: + * dev - Device-specific state data + * address - The I2C slave address + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * Returns OK on success; a negated errno on failure. + * + ****************************************************************************/ + +#define I2C_SETADDRESS(d,f,b) ((d)->ops->setaddress(d,f,b)) + +/**************************************************************************** + * Name: I2C_SETOWNADDRESS + * + * Description: + * Set our own I2C address. Calling this function enables Slave mode and + * disables Master mode on given instance (note that I2C is a bus, where + * multiple masters and slave may be handled by one device driver). + * + * One may register callback to be notifyed about reception. During the + * slave mode reception, the function READ and WRITE must be used to + * to handle reads and writes from a master. + * + * Input Parameters: + * dev - Device-specific state data + * address - Our own slave address; If it is 0x00, then the device driver + * listens to general call + * nbits - The number of address bits provided (7 or 10) + * + * Returned Value: + * OK on valid address and if the same address has not been assigned + * to other existance sharing the same port. Otherwise ERROR is returned. + * + ****************************************************************************/ + +#define I2C_SETOWNADDRESS(d,f,b) ((d)->ops->setownaddress(d,f,b)) + +/**************************************************************************** + * Name: I2C_WRITE + * + * Description: + * Send a block of data on I2C using the previously selected I2C + * frequency and slave address. Each write operational will be an 'atomic' + * operation in the sense that any other I2C actions will be serialized + * and pend until this write completes. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to the read-only buffer of data to be written to device + * buflen - The number of bytes to send from the buffer + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +#define I2C_WRITE(d,b,l) ((d)->ops->write(d,b,l)) + +/**************************************************************************** + * Name: I2C_READ + * + * Description: + * Receive a block of data from I2C using the previously selected I2C + * frequency and slave address. Each read operational will be an 'atomic' + * operation in the sense that any other I2C actions will be serialized + * and pend until this read completes. Required. + * + * Input Parameters: + * dev - Device-specific state data + * buffer - A pointer to a buffer of data to receive the data from the device + * buflen - The requested number of bytes to be read + * + * Returned Value: + * 0: success, <0: A negated errno + * + ****************************************************************************/ + +#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 + * + * Description: + * Perform a sequence of I2C transfers, each transfer is started with a + * START and the final transfer is completed with a STOP. Each sequence + * will be an 'atomic' operation in the sense that any other I2C actions + * will be serialized and pend until this read completes. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * msgs - A pointer to a set of message descriptors + * msgcount - The number of transfers to perform + * + * Returned Value: + * The number of transfers completed + * + ****************************************************************************/ + +#define I2C_TRANSFER(d,m,c) ((d)->ops->transfer(d,m,c)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The I2C vtable */ + +struct i2c_dev_s; +struct i2c_msg_s; +struct i2c_ops_s +{ + uint32_t (*setfrequency)(FAR struct i2c_dev_s *dev, uint32_t frequency); + int (*setaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); + int (*write)(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen); + int (*read)(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen); +#ifdef CONFIG_I2C_WRITEREAD + int (*writeread)(FAR struct i2c_dev_s *inst, const uint8_t *wbuffer, int wbuflen, + uint8_t *rbuffer, int rbuflen); +#endif +#ifdef CONFIG_I2C_TRANSFER + int (*transfer)(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, int count); +#endif +#ifdef CONFIG_I2C_SLAVE + int (*setownaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); + int (*registercallback)(FAR struct i2c_dev_s *dev, int (*callback)(void) ); +#endif +}; + +/* I2C transaction segment beginning with a START. A number of these can + * be transfered together to form an arbitrary sequence of write/read transfer + * to an I2C slave device. + */ + +struct i2c_msg_s +{ + uint16_t addr; /* Slave address */ + uint16_t flags; /* See I2C_M_* definitions */ + uint8_t *buffer; + int length; +}; + +/* I2C private data. This structure only defines the initial fields of the + * structure visible to the I2C client. The specific implementation may + * add additional, device specific fields after the vtable. + */ + +struct i2c_dev_s +{ + const struct i2c_ops_s *ops; /* I2C vtable */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_i2cinitialize + * + * Description: + * Initialize the selected I2C port. And return a unique instance of struct + * struct i2c_dev_s. This function may be called to obtain multiple + * instances of the interface, each of which may be set up with a + * different frequency and slave address. + * + * Input Parameter: + * Port number (for hardware that has mutiple I2C interfaces) + * + * Returned Value: + * Valid I2C device structre reference on succcess; a NULL on failure + * + ****************************************************************************/ + +EXTERN FAR struct i2c_dev_s *up_i2cinitialize(int port); + + +/**************************************************************************** + * Name: up_i2cuninitialize + * + * Description: + * De-initialize the selected I2C port, and power down the device. + * + * Input Parameter: + * Device structure as returned by the up_i2cinitalize() + * + * Returned Value: + * OK on success, ERROR when internal reference count missmatch or dev + * points to invalid hardware device. + * + ****************************************************************************/ + +EXTERN int up_i2cuninitialize(FAR struct i2c_dev_s * dev); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_NUTTX_I2C_I2C_H */ diff --git a/nuttx/include/nuttx/i2c/st_lis331dl.h b/nuttx/include/nuttx/i2c/st_lis331dl.h new file mode 100644 index 000000000..f3f137391 --- /dev/null +++ b/nuttx/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 + * + * 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 +#include + + +/************************************************************************************ + * 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 */ + -- cgit v1.2.3