summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-08 17:56:08 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-09-08 17:56:08 +0000
commit577d5456db4d4e5a740208f01362521aeda22aae (patch)
tree3f3758da5a79ed3e03f7cec67bcec8a3d7a3e65b
parentc9e0f9f37ea4d38a26baad8dafbf2e82f73322db (diff)
downloadpx4-nuttx-577d5456db4d4e5a740208f01362521aeda22aae.tar.gz
px4-nuttx-577d5456db4d4e5a740208f01362521aeda22aae.tar.bz2
px4-nuttx-577d5456db4d4e5a740208f01362521aeda22aae.zip
Fix I2C/FSMC conflict for STM32; Fix STM32 clock setup
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3942 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-xapps/system/i2c/README.txt35
-rw-r--r--apps/system/i2c/i2c_main.c2
-rw-r--r--apps/system/i2c/i2ctool.h2
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_i2c.h4
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_rcc.h2
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.c473
-rwxr-xr-xnuttx/configs/stm3210e-eval/README.txt6
-rwxr-xr-xnuttx/configs/stm3210e-eval/RIDE/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/buttons/defconfig5
-rwxr-xr-xnuttx/configs/stm3210e-eval/nsh/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/nsh2/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/nx/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/nxlines/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/nxtext/defconfig5
-rwxr-xr-xnuttx/configs/stm3210e-eval/ostest/defconfig5
-rw-r--r--nuttx/configs/stm3210e-eval/src/up_selectlcd.c2
-rwxr-xr-xnuttx/configs/stm3210e-eval/usbserial/defconfig5
-rwxr-xr-xnuttx/configs/stm3210e-eval/usbstorage/defconfig5
19 files changed, 424 insertions, 156 deletions
diff --git a/apps/system/i2c/README.txt b/apps/system/i2c/README.txt
index 0c004fa34..0435be148 100755
--- a/apps/system/i2c/README.txt
+++ b/apps/system/i2c/README.txt
@@ -7,6 +7,9 @@ will provide usage information for the I2C tools.
CONTENTS
========
+ o System Requirements
+ - I2C Driver
+ - Configuration Options
o Help
o Common Line Form
o Common Command Options
@@ -22,6 +25,34 @@ CONTENTS
- NuttX Configuration Requirements
- I2C Tool Configuration Options
+System Requirements
+===================
+
+I2C Driver
+----------
+In order to use the I2C driver, you system -- in particular, your I2C driver --
+must meet certain requirements:
+
+1. It support calling up_i2cinitialize() numerous times, resetting the I2C
+ hardware on each (initial) time. up_i2cuninitialize() will be called after
+ each call to up_i2cinitialize() to free any resources and disable the I2C.
+2. up_i2cinitialize must accept any interface number without crashing. It
+ must simply return NULL if the device is not supported.
+3. The I2C driver must support the transfer method (CONFIG_I2C_TRANSFER=y).
+
+The I2C tool is designed to be implemented as a NuttShell (NSH) add-on. Read
+the apps/nshlib/README.txt file for information about add-ons.
+
+Configuration Options
+---------------------
+CONFIG_I2CTOOL_BUILTIN - Build the tools as an NSH built-in command
+CONFIG_I2CTOOL_MINBUS - Smallest bus index supported by the hardware (default 0).
+CONFIG_I2CTOOL_MAXBUS - Largest bus index supported by the hardware (default 3)
+CONFIG_I2CTOOL_MINADDR - Minium device address (default: 0x03)
+CONFIG_I2CTOOL_MAXADDR - Largest device address (default: 0x77)
+CONFIG_I2CTOOL_MAXREGADDR - Largest register address (default: 0xff)
+CONFIG_I2CTOOL_DEFFREQ - Default frequency (default: 4000000)
+
HELP
====
@@ -44,7 +75,7 @@ options.
Where <cmd> is one of:
Show help: ?
- List buses: bus [OPTIONS]
+ List buses: bus
List devices: dev [OPTIONS] <first> <last>
Read register: get [OPTIONS]
Show help: help
@@ -56,7 +87,7 @@ options.
[-r regaddr] is the I2C device register address (hex). Default: 00 Current: 00
[-w width] is the data width (8 or 16 decimal). Default: 8 Current: 8
[-s|n], send/don't send start between command and data. Default: -n Current: -n
- [-f freq] I2C frequency. Default: 400000 Current: 400000
+ [-f freq] I2C frequency. Default: 100000 Current: 100000
NOTES:
o An environment variable like $PATH may be used for any argument.
diff --git a/apps/system/i2c/i2c_main.c b/apps/system/i2c/i2c_main.c
index 7e4a0c91b..cb4889c54 100644
--- a/apps/system/i2c/i2c_main.c
+++ b/apps/system/i2c/i2c_main.c
@@ -76,7 +76,7 @@ struct i2ctool_s g_i2ctool;
static const struct cmdmap_s g_i2ccmds[] =
{
{ "?", cmd_help, "Show help", NULL },
- { "bus", cmd_bus, "List busses", "[OPTIONS]" },
+ { "bus", cmd_bus, "List busses", NULL },
{ "dev", cmd_dev, "List devices", "[OPTIONS] <first> <last>" },
{ "get", cmd_get, "Read register", "[OPTIONS]" },
{ "help", cmd_help, "Show help", NULL },
diff --git a/apps/system/i2c/i2ctool.h b/apps/system/i2c/i2ctool.h
index 81b7c0682..56802ffb2 100644
--- a/apps/system/i2c/i2ctool.h
+++ b/apps/system/i2c/i2ctool.h
@@ -87,7 +87,7 @@
#endif
#ifndef CONFIG_I2CTOOL_DEFFREQ
-# define CONFIG_I2CTOOL_DEFFREQ 400000
+# define CONFIG_I2CTOOL_DEFFREQ 100000
#endif
/* This is the maximum number of arguments that will be accepted for a
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 97b90f608..0e168cb6f 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -2060,3 +2060,7 @@
Li Zhuoyi (Lzyy).
* arch/arm/src/lpc17xx/lpc17_i2c.c: I2C driver for the NXP LPC17xx family
submitted by Li Zhuoyi (Lzyy)
+ * arch/arm/src/stm32_i2c.c: Correct two issues with the STM32 I2C driver:
+ (1) Clocking needs to be based on PCLK1, not HCLK and fast speed settings
+ need some additional bits; and (2) Correct a hang that will occur on
+ I2C1 if FSMC is also enabled.
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h
index 8e40a3598..2049ac1f4 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_i2c.h
@@ -82,7 +82,7 @@
/* Control register 1 */
-#define I2C_CR1_PE (1 << 0) /* Bit 0: Peripheral Enable*/
+#define I2C_CR1_PE (1 << 0) /* Bit 0: Peripheral Enable */
#define I2C_CR1_SMBUS (1 << 1) /* Bit 1: SMBus Mode */
#define I2C_CR1_SMBTYPE (1 << 3) /* Bit 3: SMBus Type */
#define I2C_CR1_ENARP (1 << 4) /* Bit 4: ARP Enable */
@@ -167,7 +167,7 @@
#define I2C_CCR_CCR_SHIFT (0) /* Bits 11-0: Clock Control Register in Fast/Standard mode (Master mode) */
#define I2C_CCR_CCR_MASK (0x0fff << I2C_CCR_CCR_SHIFT)
#define I2C_CCR_DUTY (1 << 14) /* Bit 14: Fast Mode Duty Cycle */
-#define I2C_CCR_FS (1 << 15) /* Bit 15: I2C Master Mode Selection */
+#define I2C_CCR_FS (1 << 15) /* Bit 15: Fast Mode Selection */
/* TRISE Register */
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_rcc.h b/nuttx/arch/arm/src/stm32/chip/stm32_rcc.h
index 0f0cc9c27..1ed298d20 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32_rcc.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_rcc.h
@@ -176,7 +176,7 @@
/* APB2 Peripheral reset register */
-#define RCC_APB2RSTR_AFIORST (1 << 0) /* Bit 0: Alternate Function I/O reset */
+#define RCC_APB2RSTR_AFIORST (1 << 0) /* Bit 0: Alternate Function I/O reset */
#define RCC_APB2RSTR_IOPARST (1 << 2) /* Bit 2: I/O port A reset */
#define RCC_APB2RSTR_IOPBRST (1 << 3) /* Bit 3: IO port B reset */
#define RCC_APB2RSTR_IOPCRST (1 << 4) /* Bit 4: IO port C reset */
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c
index 09f61c05c..fb553c7cd 100644
--- a/nuttx/arch/arm/src/stm32/stm32_i2c.c
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c
@@ -94,8 +94,9 @@
* Pre-processor Definitions
************************************************************************************/
/* Configuration ********************************************************************/
-/* Interrupt wait timeout in milliseconds */
+/* Interrupt wait timeout in seconds and milliseconds */
+#undef CONFIG_STM32_I2CTIMEOSEC
#ifndef CONFIG_STM32_I2CTIMEOMS
# define CONFIG_STM32_I2CTIMEOMS 50
#endif
@@ -104,61 +105,65 @@
* Private Types
************************************************************************************/
-/** I2C Device Private Data
- */
-struct stm32_i2c_priv_s {
- uint32_t base;
- int refs;
- sem_t sem_excl;
- sem_t sem_isr;
-
- uint8_t msgc;
- struct i2c_msg_s *msgv;
- uint8_t * ptr;
- int dcnt;
- uint16_t flags;
-
- uint32_t status;
+/* I2C Device Private Data */
+
+struct stm32_i2c_priv_s
+{
+ uint32_t base;
+ int refs;
+ sem_t sem_excl;
+ sem_t sem_isr;
+
+ uint8_t msgc;
+ struct i2c_msg_s *msgv;
+ uint8_t *ptr;
+ int dcnt;
+ uint16_t flags;
+
+ uint32_t status;
};
-/** I2C Device, Instance
- */
-struct stm32_i2c_inst_s {
- struct i2c_ops_s * ops;
- struct stm32_i2c_priv_s * priv;
+/* I2C Device, Instance */
+
+struct stm32_i2c_inst_s
+{
+ struct i2c_ops_s *ops;
+ struct stm32_i2c_priv_s *priv;
- uint32_t frequency;
- int address;
- uint16_t flags;
+ uint32_t frequency;
+ int address;
+ uint16_t flags;
};
/************************************************************************************
* Private Data
************************************************************************************/
-#if CONFIG_STM32_I2C1
-struct stm32_i2c_priv_s stm32_i2c1_priv = {
- .base = STM32_I2C1_BASE,
- .refs = 0,
- .msgc = 0,
- .msgv = NULL,
- .ptr = NULL,
- .dcnt = 0,
- .flags = 0,
- .status = 0
+#ifdef CONFIG_STM32_I2C1
+struct stm32_i2c_priv_s stm32_i2c1_priv =
+{
+ .base = STM32_I2C1_BASE,
+ .refs = 0,
+ .msgc = 0,
+ .msgv = NULL,
+ .ptr = NULL,
+ .dcnt = 0,
+ .flags = 0,
+ .status = 0
};
#endif
-#if CONFIG_STM32_I2C2
-struct stm32_i2c_priv_s stm32_i2c2_priv = {
- .base = STM32_I2C2_BASE,
- .refs = 0,
- .msgc = 0,
- .msgv = NULL,
- .ptr = NULL,
- .dcnt = 0,
- .flags = 0,
- .status = 0
+#ifdef CONFIG_STM32_I2C2
+struct stm32_i2c_priv_s stm32_i2c2_priv =
+{
+ .base = STM32_I2C2_BASE,
+ .refs = 0,
+ .msgc = 0,
+ .msgv = NULL,
+ .ptr = NULL,
+ .dcnt = 0,
+ .flags = 0,
+ .status = 0
};
#endif
@@ -200,13 +205,24 @@ int inline stm32_i2c_sem_waitisr(FAR struct i2c_dev_s *dev)
flags = irqsave();
do
{
+ /* Get the current time */
+
(void)clock_gettime(CLOCK_REALTIME, &abstime);
+
+ /* Calculate a time in the future */
+
+#if defined(CONFIG_STM32_I2CTIMEOSEC) && CONFIG_STM32_I2CTIMEOSEC > 0
+ abstime.tv_sec += CONFIG_STM32_I2CTIMEOSEC;
+#endif
+#if defined(CONFIG_STM32_I2CTIMEOMS) && CONFIG_STM32_I2CTIMEOMS > 0
abstime.tv_nsec += CONFIG_STM32_I2CTIMEOMS * 1000 * 1000;
if (abstime.tv_nsec > 1000 * 1000 * 1000)
{
abstime.tv_sec++;
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
+#endif
+ /* Wait until either the transfer is complete or the timeout expires */
ret = sem_timedwait(&((struct stm32_i2c_inst_s *)dev)->priv->sem_isr, &abstime);
}
@@ -235,58 +251,166 @@ void inline stm32_i2c_sem_destroy(FAR struct i2c_dev_s *dev)
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;
+ uint16_t ccr;
+ uint16_t trise;
+ uint16_t freqmhz;
+ uint16_t speed;
- uint16_t cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
-
- if (cr1 & I2C_CR1_PE)
- stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 ^ I2C_CR1_PE);
-
- /* Update timing and control registers */
-
- if (frequency < 400000) {
-
- /* Speed: 100 kHz
- * Risetime: 1000 ns
- * Duty: t_low / t_high = 1
- */
- stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/200000);
- stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, STM32_BOARD_HCLK/1000000 + 1);
+ /* Disable the selected I2C peripheral to configure TRISE */
+
+ cr1 = stm32_i2c_getreg(priv, STM32_I2C_CR1_OFFSET);
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1 & ~I2C_CR1_PE);
+
+ /* Update timing and control registers */
+
+ freqmhz = (uint16_t)(STM32_PCLK1_FREQUENCY / 1000000);
+ ccr = 0;
+
+ /* Configure speed in standard mode */
+
+ if (frequency <= 100000)
+ {
+ /* Standard mode speed calculation */
+
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency << 1));
+
+ /* The CCR fault must be >= 4 */
+
+ if (speed < 4)
+ {
+ /* Set the minimum allowed value */
+
+ speed = 4;
+ }
+ ccr |= speed;
+
+ /* Set Maximum Rise Time for standard mode */
+
+ trise = freqmhz + 1;
}
- else {
-
- /* Speed: 400 kHz
- * Duty: t_low / t_high = 2
- */
- stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, STM32_BOARD_HCLK/1200000);
- stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, 300*(STM32_BOARD_HCLK / 1000000)/1000 + 1);
+
+ /* Configure speed in fast mode */
+
+ else /* (frequency <= 400000) */
+ {
+ /* Fast mode speed calculation with Tlow/Thigh = 16/9 */
+
+#ifdef CONFIG_I2C_DUTY16_9
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
+
+ /* Set DUTY and fast speed bits */
+
+ ccr |= (I2C_CCR_DUTY|I2C_CCR_FS);
+#else
+ /* Fast mode speed calculation with Tlow/Thigh = 2 */
+
+ speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 3));
+
+ /* Set fast speed bit */
+
+ ccr |= I2C_CCR_FS;
+#endif
+
+ /* Verify that the CCR speed value is nonzero */
+
+ if (speed < 1)
+ {
+ /* Set the minimum allowed value */
+
+ speed = 1;
+ }
+ ccr |= speed;
+
+ /* Set Maximum Rise Time for fast mode */
+
+ trise = (uint16_t)(((freqmhz * 300) / 1000) + 1);
}
-
- /* Restore state */
-
- if (cr1 & I2C_CR1_PE)
- stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
+
+ /* Write the new values of the CCR and TRISE registers */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CCR_OFFSET, ccr);
+ stm32_i2c_putreg(priv, STM32_I2C_TRISE_OFFSET, trise);
+
+ /* Bit 14 of OAR1 must be configured and kept at 1 */
+
+ stm32_i2c_putreg(priv, STM32_I2C_OAR1_OFFSET, I2C_OAR1_ONE);
+
+ /* Re-enable the peripheral (or not) */
+
+ stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, cr1);
}
static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv)
{
- /* Disable ACK on receive by default and generate START */
- stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 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_clrstart(FAR struct stm32_i2c_priv_s *priv)
+{
+ /* "This [START] bit is set and cleared by software and cleared by hardware
+ * when start is sent or PE=0." The bit must be cleared by software if the
+ * START is never sent.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_START, 0);
}
static inline void stm32_i2c_sendstop(FAR struct stm32_i2c_priv_s *priv)
{
- stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 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;
+ uint32_t status = stm32_i2c_getreg(priv, STM32_I2C_SR1_OFFSET);
+ status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
+ return status;
}
+/* FSMC must be disable while accessing I2C1 because it uses a common resource (LBAR) */
+
+#if defined(CONFIG_STM32_FSMC) && defined (CONFIG_STM32_I2C1)
+static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv)
+{
+ uint32_t ret = 0;
+ uint32_t regval;
+
+ /* Is this I2C1 */
+
+#ifdef CONFIG_STM32_I2C2
+ if (priv->base == STM32_I2C1_BASE)
+#endif
+ {
+ /* Disable FSMC unconditionally */
+
+ ret = getreg32( STM32_RCC_AHBENR);
+ regval = ret & ~RCC_AHBENR_FSMCEN;
+ putreg32(regval, STM32_RCC_AHBENR);
+ }
+ return regval;
+}
+
+static inline void stm32_i2c_enablefsmc(uint32_t ahbenr)
+{
+ uint32_t regval;
+
+ /* Enable AHB clocking to the FSMC only if it was previously enabled. */
+
+ if ((ahbenr & RCC_AHBENR_FSMCEN) != 0)
+ {
+ regval = getreg32( STM32_RCC_AHBENR);
+ regval |= RCC_AHBENR_FSMCEN;
+ putreg32(regval, STM32_RCC_AHBENR);
+ }
+}
+#else
+# define stm32_i2c_disablefsmc() (0)
+# define stm32_i2c_enablefsmc(ahbenr)
+#endif
+
/************************************************************************************
* Interrupt Service Routines
************************************************************************************/
@@ -456,14 +580,14 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv)
/* Decode ***************************************************************************/
-#if CONFIG_STM32_I2C1
+#ifdef CONFIG_STM32_I2C1
static int stm32_i2c1_isr(int irq, void *context)
{
return stm32_i2c_isr(&stm32_i2c1_priv);
}
#endif
-#if CONFIG_STM32_I2C2
+#ifdef CONFIG_STM32_I2C2
static int stm32_i2c2_isr(int irq, void *context)
{
return stm32_i2c_isr(&stm32_i2c2_priv);
@@ -481,16 +605,16 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
switch( priv->base ) {
-#if CONFIG_STM32_I2C1
+#ifdef CONFIG_STM32_I2C1
case STM32_I2C1_BASE:
/* enable power and reset the peripheral */
-
- modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN);
+
+ modifyreg32(STM32_RCC_APB1ENR, 0, RCC_APB1ENR_I2C1EN);
modifyreg32(STM32_RCC_APB1RSTR, 0, RCC_APB1RSTR_I2C1RST);
modifyreg32(STM32_RCC_APB1RSTR, RCC_APB1RSTR_I2C1RST, 0);
-
+
/* configure pins */
if (stm32_configgpio(GPIO_I2C1_SCL)==ERROR) return ERROR;
@@ -498,7 +622,7 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
stm32_unconfiggpio(GPIO_I2C1_SCL);
return ERROR;
}
-
+
/* attach ISRs */
irq_attach(STM32_IRQ_I2C1EV, stm32_i2c1_isr);
@@ -508,7 +632,7 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
break;
#endif
-#if CONFIG_STM32_I2C2
+#ifdef CONFIG_STM32_I2C2
case STM32_I2C2_BASE:
/* enable power and reset the peripheral */
@@ -546,7 +670,7 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
#ifndef NON_ISR
I2C_CR2_ITERREN | I2C_CR2_ITEVFEN | // I2C_CR2_ITBUFEN |
#endif
- (STM32_BOARD_HCLK / 1000000)
+ (STM32_PCLK1_FREQUENCY / 1000000)
);
stm32_i2c_setclock(priv, 100000);
@@ -567,7 +691,7 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
switch( priv->base ) {
-#if CONFIG_STM32_I2C1
+#ifdef CONFIG_STM32_I2C1
case STM32_I2C1_BASE:
stm32_unconfiggpio(GPIO_I2C1_SCL);
stm32_unconfiggpio(GPIO_I2C1_SDA);
@@ -581,7 +705,7 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
break;
#endif
-#if CONFIG_STM32_I2C2
+#ifdef CONFIG_STM32_I2C2
case STM32_I2C2_BASE:
stm32_unconfiggpio(GPIO_I2C2_SCL);
stm32_unconfiggpio(GPIO_I2C2_SDA);
@@ -609,7 +733,7 @@ uint32_t stm32_i2c_setfrequency(FAR struct i2c_dev_s *dev, uint32_t frequency)
{
stm32_i2c_sem_wait(dev);
-#if STM32_BOARD_HCLK < 4000000
+#if STM32_PCLK1_FREQUENCY < 4000000
((struct stm32_i2c_inst_s *)dev)->frequency = 100000;
#else
((struct stm32_i2c_inst_s *)dev)->frequency = frequency;
@@ -632,82 +756,135 @@ int stm32_i2c_setaddress(FAR struct i2c_dev_s *dev, int addr, int nbits)
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);
-
- /* wait as stop might still be in progress
- *
- * \todo GET RID OF THIS PERFORMANCE LOSS and for() loop
- */
- for (; stm32_i2c_getreg(inst->priv, STM32_I2C_CR1_OFFSET) & I2C_CR1_STOP; ) up_waste();
-
- /* Old transfers are done */
- inst->priv->msgv = msgs;
- inst->priv->msgc = count;
-
- /* Set clock (on change it toggles I2C_CR1_PE !) */
- stm32_i2c_setclock(inst->priv, inst->frequency);
+ struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev;
+ uint32_t status = 0;
+ uint32_t ahbenr;
+ int status_errno = 0;
- /* Trigger start condition, then the process moves into the ISR */
- stm32_i2c_sendstart(inst->priv);
+ ASSERT(count);
+
+ /* Disable FSMC that shares a pin with I2C1 (LBAR) */
+
+ ahbenr = stm32_i2c_disablefsmc(inst->priv);
+
+ /* wait as stop might still be in progress
+ *
+ * \todo GET RID OF THIS PERFORMANCE LOSS and for() loop
+ */
+
+ for (; stm32_i2c_getreg(inst->priv, STM32_I2C_CR1_OFFSET) & I2C_CR1_STOP; )
+ {
+ up_waste();
+ }
+ /* Old transfers are done */
+
+ inst->priv->msgv = msgs;
+ inst->priv->msgc = count;
+ /* Set clock (on change it toggles I2C_CR1_PE !) */
+
+ stm32_i2c_setclock(inst->priv, inst->frequency);
+
+ /* Trigger start condition, then the process moves into the ISR */
+
+ stm32_i2c_sendstart(inst->priv);
+
#ifdef NON_ISR
- do {
- do {
+ do
+ {
+ do
+ {
stm32_i2c_isr(&stm32_i2c1_priv);
status = inst->priv->status;
- } while( status & (I2C_SR2_BUSY<<16) );
+ }
+ while (status & (I2C_SR2_BUSY << 16));
}
- while( sem_trywait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 );
+ while( sem_trywait( &((struct stm32_i2c_inst_s *)dev)->priv->sem_isr ) != 0 );
#else
#if 1
- /* Wait for an ISR, if there was a timeout, fetch latest status to get the BUSY flag */
+ /* 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);
- status_errno = ETIMEDOUT;
+ if (stm32_i2c_sem_waitisr(dev) == ERROR)
+ {
+ status = stm32_i2c_getstatus(inst->priv);
+ status_errno = ETIMEDOUT;
+
+ /* " Note: When the STOP, START or PEC bit is set, the software must
+ * not perform any write access to I2C_CR1 before this bit is
+ * cleared by hardware. Otherwise there is a risk of setting a
+ * second STOP, START or PEC request."
+ */
+
+ stm32_i2c_clrstart(inst->priv);
+ }
+ else
+ {
+ /* clear SR2 (BUSY flag) as we've done successfully */
+
+ status = inst->priv->status & 0xffff;
}
- else status = inst->priv->status & 0xFFFF; /* clear SR2 (BUSY flag) as we've done successfully */
#else
- do {
- printf("%x, %d\n", inst->priv->status, isr_count );
+ do
+ {
+ printf("%x, %d\n", inst->priv->status, isr_count );
}
- while( sem_trywait( &inst->priv->sem_isr ) != 0 );
+ while( sem_trywait( &inst->priv->sem_isr ) != 0 );
#endif
#endif
- if (status & I2C_SR1_BERR) { /* Bus Error */
- status_errno = EIO;
+ 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_ARLO)
+ {
+ /* Arbitration Lost (master mode) */
+
+ status_errno = EAGAIN;
}
- else if (status & I2C_SR1_AF) { /* Acknowledge Failure */
- status_errno = ENXIO;
+ 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_OVR)
+ {
+ /* Overrun/Underrun */
+
+ status_errno = EIO;
}
- else if (status & I2C_SR1_PECERR) { /* PEC Error in reception */
- status_errno = EPROTO;
+ 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_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;
+ else if (status & (I2C_SR2_BUSY << 16))
+ {
+ /* I2C Bus is for some reason busy */
+
+ status_errno = EBUSY;
}
-
-// printf("end_count = %d, dcnt=%d\n", isr_count, inst->priv->dcnt); fflush(stdout);
-
- stm32_i2c_sem_post(dev);
-
- errno = status_errno;
- return -status_errno;
+
+ /* Re-enable the FSMC */
+
+ stm32_i2c_enablefsmc(ahbenr);
+ stm32_i2c_sem_post(dev);
+
+ errno = status_errno;
+ return -status_errno;
}
int stm32_i2c_write(FAR struct i2c_dev_s *dev, const uint8_t *buffer, int buflen)
@@ -802,11 +979,11 @@ FAR struct i2c_dev_s * up_i2cinitialize(int port)
struct stm32_i2c_inst_s * inst = NULL; /* device, single instance */
int irqs;
-#if STM32_BOARD_HCLK < 4000000
+#if STM32_PCLK1_FREQUENCY < 4000000
# warning STM32_I2C_INIT: Peripheral clock must be at least 4 MHz to support 400 kHz operation.
#endif
-#if STM32_BOARD_HCLK < 2000000
+#if STM32_PCLK1_FREQUENCY < 2000000
# warning STM32_I2C_INIT: Peripheral clock must be at least 2 MHz to support 100 kHz operation.
return NULL;
#endif
@@ -814,10 +991,10 @@ FAR struct i2c_dev_s * up_i2cinitialize(int port)
/* Get I2C private structure */
switch(port) {
-#if CONFIG_STM32_I2C1
+#ifdef CONFIG_STM32_I2C1
case 1: priv = (struct stm32_i2c_priv_s *)&stm32_i2c1_priv; break;
#endif
-#if CONFIG_STM32_I2C2
+#ifdef CONFIG_STM32_I2C2
case 2: priv = (struct stm32_i2c_priv_s *)&stm32_i2c2_priv; break;
#endif
default: return NULL;
diff --git a/nuttx/configs/stm3210e-eval/README.txt b/nuttx/configs/stm3210e-eval/README.txt
index 0224f65a2..772020e96 100755
--- a/nuttx/configs/stm3210e-eval/README.txt
+++ b/nuttx/configs/stm3210e-eval/README.txt
@@ -360,6 +360,12 @@ STM3210E-EVAL-specific Configuration Options
CONFIG_STM32_USART1
CONFIG_STM32_ADC3
+ Timer and I2C devices may need to the following to force power to be applied
+ unconditionally at power up. (Otherwise, the device is powered when it is
+ initialized).
+
+ CONFIG_STM32_FORCEPOWER
+
Alternate pin mappings (should not be used with the STM3210E-EVAL board):
CONFIG_STM32_TIM1_FULL_REMAP
diff --git a/nuttx/configs/stm3210e-eval/RIDE/defconfig b/nuttx/configs/stm3210e-eval/RIDE/defconfig
index 9e31d2bd6..4733a438d 100755
--- a/nuttx/configs/stm3210e-eval/RIDE/defconfig
+++ b/nuttx/configs/stm3210e-eval/RIDE/defconfig
@@ -128,6 +128,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/buttons/defconfig b/nuttx/configs/stm3210e-eval/buttons/defconfig
index bc1c291d2..7a9e636d9 100644
--- a/nuttx/configs/stm3210e-eval/buttons/defconfig
+++ b/nuttx/configs/stm3210e-eval/buttons/defconfig
@@ -142,6 +142,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/nsh/defconfig b/nuttx/configs/stm3210e-eval/nsh/defconfig
index 908aff7f1..97b155ff8 100755
--- a/nuttx/configs/stm3210e-eval/nsh/defconfig
+++ b/nuttx/configs/stm3210e-eval/nsh/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/nsh2/defconfig b/nuttx/configs/stm3210e-eval/nsh2/defconfig
index d49669886..d92fd3773 100644
--- a/nuttx/configs/stm3210e-eval/nsh2/defconfig
+++ b/nuttx/configs/stm3210e-eval/nsh2/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/nx/defconfig b/nuttx/configs/stm3210e-eval/nx/defconfig
index 894f569f5..082452881 100644
--- a/nuttx/configs/stm3210e-eval/nx/defconfig
+++ b/nuttx/configs/stm3210e-eval/nx/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/nxlines/defconfig b/nuttx/configs/stm3210e-eval/nxlines/defconfig
index 6a9ea3979..d41e60415 100644
--- a/nuttx/configs/stm3210e-eval/nxlines/defconfig
+++ b/nuttx/configs/stm3210e-eval/nxlines/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/nxtext/defconfig b/nuttx/configs/stm3210e-eval/nxtext/defconfig
index d48637a1b..9193dd084 100644
--- a/nuttx/configs/stm3210e-eval/nxtext/defconfig
+++ b/nuttx/configs/stm3210e-eval/nxtext/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/ostest/defconfig b/nuttx/configs/stm3210e-eval/ostest/defconfig
index 3fec68871..41aeb41d8 100755
--- a/nuttx/configs/stm3210e-eval/ostest/defconfig
+++ b/nuttx/configs/stm3210e-eval/ostest/defconfig
@@ -140,6 +140,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/src/up_selectlcd.c b/nuttx/configs/stm3210e-eval/src/up_selectlcd.c
index d2b189a09..221834ff5 100644
--- a/nuttx/configs/stm3210e-eval/src/up_selectlcd.c
+++ b/nuttx/configs/stm3210e-eval/src/up_selectlcd.c
@@ -88,7 +88,7 @@
* *JP7 will switch to PD6
*/
-/* GPIO configurations unique to SRAM */
+/* GPIO configurations unique to the LCD */
static const uint16_t g_lcdconfig[] =
{
diff --git a/nuttx/configs/stm3210e-eval/usbserial/defconfig b/nuttx/configs/stm3210e-eval/usbserial/defconfig
index 5680fc74a..362951cd3 100755
--- a/nuttx/configs/stm3210e-eval/usbserial/defconfig
+++ b/nuttx/configs/stm3210e-eval/usbserial/defconfig
@@ -140,6 +140,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the
diff --git a/nuttx/configs/stm3210e-eval/usbstorage/defconfig b/nuttx/configs/stm3210e-eval/usbstorage/defconfig
index da24167c7..5ad7be2eb 100755
--- a/nuttx/configs/stm3210e-eval/usbstorage/defconfig
+++ b/nuttx/configs/stm3210e-eval/usbstorage/defconfig
@@ -138,6 +138,11 @@ CONFIG_STM32_USART1=y
CONFIG_STM32_ADC3=n
#
+# Timer and I2C devices may need to the following to force power to be applied:
+#
+#CONFIG_STM32_FORCEPOWER=y
+
+#
# STM32F103Z specific serial device driver settings
#
# CONFIG_USARTn_SERIAL_CONSOLE - selects the USARTn for the