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