diff --git a/Documentation/README.html b/Documentation/README.html
index 2f9ba9066b2..4430ef211f7 100644
--- a/Documentation/README.html
+++ b/Documentation/README.html
@@ -8,7 +8,7 @@
NuttX README Files
- Last Updated: February 19, 2017
+ Last Updated: March 21, 2017
|
@@ -297,6 +297,8 @@ nuttx/
| | `- README.txt
| |- viewtool-stm32f107/
| | `- README.txt
+ | |- xmc4500-relax/
+ | | `- README.txt
| |- xtrs/
| | `- README.txt
| |- z16f2800100zcog/
diff --git a/README.txt b/README.txt
index ed3d41c30f8..4bab1306ff7 100644
--- a/README.txt
+++ b/README.txt
@@ -1681,6 +1681,8 @@ nuttx/
| | `- README.txt
| |- viewtool-stm32f107/
| | `- README.txt
+ | |- xmc5400-relax/
+ | | `- README.txt
| |- xtrs/
| | `- README.txt
| |- z16f2800100zcog/
diff --git a/arch/arm/include/xmc4/chip.h b/arch/arm/include/xmc4/chip.h
index 5c3fcdabfa2..6507917fe6b 100644
--- a/arch/arm/include/xmc4/chip.h
+++ b/arch/arm/include/xmc4/chip.h
@@ -51,23 +51,23 @@
#if defined(CONFIG_ARCH_CHIP_XMC4500)
# define XMC4_NUSIC 3 /* Three USIC modules: USCI0-2 */
# undef XMC4_SCU_GATING /* No clock gating registers */
-# define XMC4_NECATN 0 /* No EtherCAT support */
+# define XMC4_NECAT 0 /* No EtherCAT support */
#elif defined(CONFIG_ARCH_CHIP_XMC4700)
# define XMC4_NUSIC 3 /* Three USIC modules: USCI0-2 */
# define XMC4_SCU_GATING 1 /* Has clock gating registers */
-# define XMC4_NECATN 0 /* No EtherCAT support */
+# define XMC4_NECAT 0 /* No EtherCAT support */
#elif defined(CONFIG_ARCH_CHIP_XMC4700)
# define XMC4_NUSIC 3 /* Three USIC modules: USCI0-2 */
# define XMC4_SCU_GATING 1 /* Has clock gating registers */
-# define XMC4_NECATN 1 /* One EtherCAT module */
+# define XMC4_NECAT 1 /* One EtherCAT module */
#else
# error "Unsupported XMC4xxx chip"
#endif
/* NVIC priority levels *************************************************************/
-/* Each priority field holds a priority value, 0-15. The lower the value, the greater
- * the priority of the corresponding interrupt. The XMC4500 implements only
- * bits[7:2] of this field, bits[1:0] read as zero and ignore writes.
+/* Each priority field holds a priority value. The lower the value, the greater the
+ * priority of the corresponding interrupt. The XMC4500 implements only bits[7:2]
+ * of this field, bits[1:0] read as zero and ignore writes.
*/
#define NVIC_SYSH_PRIORITY_MIN 0xfc /* All bits[7:2] set is minimum priority */
diff --git a/arch/arm/include/xmc4/xmc4500_irq.h b/arch/arm/include/xmc4/xmc4500_irq.h
index dfd21d6c21d..b35a1b3f8a2 100644
--- a/arch/arm/include/xmc4/xmc4500_irq.h
+++ b/arch/arm/include/xmc4/xmc4500_irq.h
@@ -184,7 +184,7 @@
#define XMC4_IRQ_SDMMC_SR0 (XMC4_IRQ_FIRST+106) /* 106: SDMMC, SR0 */
#define XMC4_IRQ_USB0_SR0 (XMC4_IRQ_FIRST+107) /* 107: USB, SR0 */
#define XMC4_IRQ_ETH0_SR0 (XMC4_IRQ_FIRST+108) /* 108: Ethernet, module 0, SR0 */
-#define XMC4_IRQ_RESVD109 (XMC4_IRQ_FIRST+109) /* 109: Reserved */
+#define XMC4_IRQ_ECAT0_SR0 (XMC4_IRQ_FIRST+109) /* 109: EtherCAT, module 0, SR0 */
#define XMC4_IRQ_GPCMA1_SR0 (XMC4_IRQ_FIRST+110) /* 110: GPDMA1, SR0 */
#define XMC4_IRQ_RESVD111 (XMC4_IRQ_FIRST+111) /* 111: Reserved */
diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig
index 8dea045fda5..de2c8fe23be 100644
--- a/arch/arm/src/stm32/Kconfig
+++ b/arch/arm/src/stm32/Kconfig
@@ -6190,6 +6190,16 @@ config STM32_I2C_DUTY16_9
default n
depends on STM32_I2C
+config STM32_I2C_DMA
+ bool "I2C DMA Support"
+ default n
+ depends on STM32_I2C && STM32_STM32F40XX && STM32_DMA1
+ ---help---
+ This option enables the DMA for I2C transfers.
+ Note: The user can define CONFIG_I2C_DMAPRIO: a custom priority value for the
+ I2C dma streams, else the default priority level is set to medium.
+ Note: This option is compatible with CONFIG_I2C_POLLED.
+
endmenu
menu "SDIO Configuration"
diff --git a/arch/arm/src/stm32/stm32f40xxx_i2c.c b/arch/arm/src/stm32/stm32f40xxx_i2c.c
index c0d1a2d6fd0..3d7d5567f89 100644
--- a/arch/arm/src/stm32/stm32f40xxx_i2c.c
+++ b/arch/arm/src/stm32/stm32f40xxx_i2c.c
@@ -63,7 +63,6 @@
* - 1 x 10 bit addresses + 1 x 7 bit address (?)
* - plus the broadcast address (general call)
* - Multi-master support
- * - DMA (to get rid of too many CPU wake-ups and interventions)
* - Be ready for IPMI
*/
@@ -95,6 +94,7 @@
#include "stm32_rcc.h"
#include "stm32_i2c.h"
#include "stm32_waste.h"
+#include "stm32_dma.h"
/* At least one I2C peripheral must be enabled */
@@ -162,6 +162,21 @@
#define MKI2C_OUTPUT(p) (((p) & (GPIO_PORT_MASK | GPIO_PIN_MASK)) | I2C_OUTPUT)
+/* I2C DMA priority */
+
+#ifdef CONFIG_STM32_I2C_DMA
+
+# if defined(CONFIG_I2C_DMAPRIO)
+# if (CONFIG_I2C_DMAPRIO & ~DMA_SCR_PL_MASK) != 0
+# error "Illegal value for CONFIG_I2C_DMAPRIO"
+# endif
+# define I2C_DMA_PRIO CONFIG_I2C_DMAPRIO
+# else
+# define I2C_DMA_PRIO DMA_SCR_PRIMED
+# endif
+
+#endif
+
/* Debug ****************************************************************************/
/* I2C event trace logic. NOTE: trace uses the internal, non-standard, low-level
@@ -253,7 +268,7 @@ struct stm32_i2c_priv_s
struct i2c_msg_s *msgv; /* Message list */
uint8_t *ptr; /* Current message buffer */
uint32_t frequency; /* Current I2C frequency */
- int dcnt; /* Current message length */
+ volatile int dcnt; /* Current message length */
uint16_t flags; /* Current message flags */
bool check_addr_ACK; /* Flag to signal if on next interrupt address has ACKed */
uint8_t total_msg_len; /* Flag to signal a short read sequence */
@@ -270,6 +285,15 @@ struct stm32_i2c_priv_s
#endif
uint32_t status; /* End of transfer SR2|SR1 status */
+
+ /* I2C DMA support */
+
+#ifdef CONFIG_STM32_I2C_DMA
+ DMA_HANDLE txdma; /* TX DMA handle */
+ DMA_HANDLE rxdma; /* RX DMA handle */
+ uint8_t txch; /* TX DMA channel */
+ uint8_t rxch; /* RX DMA channel */
+#endif
};
/************************************************************************************
@@ -337,6 +361,13 @@ static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
static int stm32_i2c_reset(FAR struct i2c_master_s *dev);
#endif
+/* DMA support */
+
+#ifdef CONFIG_STM32_I2C_DMA
+static void stm32_i2c_dmarxcallback(DMA_HANDLE handle, uint8_t isr, void *arg);
+static void stm32_i2c_dmatxcallback(DMA_HANDLE handle, uint8_t isr, void *arg);
+#endif
+
/************************************************************************************
* Private Data
************************************************************************************/
@@ -398,7 +429,16 @@ static struct stm32_i2c_priv_s stm32_i2c1_priv =
.ptr = NULL,
.dcnt = 0,
.flags = 0,
- .status = 0
+ .status = 0,
+#ifdef CONFIG_STM32_I2C_DMA
+# ifndef CONFIG_STM32_DMA1
+# error "I2C1 enabled with DMA but corresponding DMA controller 1 is not enabled!"
+# endif
+ /* TODO: ch for i2c 1 and 2 could be *X_2 based on stream priority */
+
+ .rxch = DMAMAP_I2C1_RX,
+ .txch = DMAMAP_I2C1_TX,
+#endif
};
#endif
@@ -428,7 +468,14 @@ static struct stm32_i2c_priv_s stm32_i2c2_priv =
.ptr = NULL,
.dcnt = 0,
.flags = 0,
- .status = 0
+ .status = 0,
+#ifdef CONFIG_STM32_I2C_DMA
+# ifndef CONFIG_STM32_DMA1
+# error "I2C2 enabled with DMA but corresponding DMA controller 1 is not enabled!"
+# endif
+ .rxch = DMAMAP_I2C2_RX,
+ .txch = DMAMAP_I2C2_TX,
+#endif
};
#endif
@@ -458,7 +505,14 @@ static struct stm32_i2c_priv_s stm32_i2c3_priv =
.ptr = NULL,
.dcnt = 0,
.flags = 0,
- .status = 0
+ .status = 0,
+#ifdef CONFIG_STM32_I2C_DMA
+# ifndef CONFIG_STM32_DMA1
+# error "I2C3 enabled with DMA but corresponding DMA controller 1 is not enabled!"
+# endif
+ .rxch = DMAMAP_I2C3_RX,
+ .txch = DMAMAP_I2C3_TX,
+#endif
};
#endif
@@ -521,7 +575,7 @@ static inline void stm32_i2c_sem_wait(FAR struct stm32_i2c_priv_s *priv)
{
while (sem_wait(&priv->sem_excl) != 0)
{
- ASSERT(errno == EINTR);
+ DEBUGASSERT(errno == EINTR);
}
}
@@ -1185,6 +1239,12 @@ static inline void stm32_i2c_enablefsmc(uint32_t ahbenr)
static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
{
uint32_t status;
+#ifndef CONFIG_I2C_POLLED
+ uint32_t regval;
+#endif
+#ifdef CONFIG_STM32_I2C_DMA
+ uint16_t cr2;
+#endif
i2cinfo("I2C ISR called\n");
@@ -1228,6 +1288,23 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
* stm32_i2c_sem_waitdone() waiting process.
*/
+#ifdef CONFIG_STM32_I2C_DMA
+ /* If ISR gets called (ex. polling mode) while DMA is still in
+ * progress, we should just return and let the DMA finish.
+ */
+
+ cr2 = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ if ((cr2 & I2C_CR2_DMAEN) != 0)
+ {
+#ifdef CONFIG_DEBUG_I2C_INFO
+ size_t left = stm32_dmaresidual(priv->rxdma);
+
+ i2cinfo("DMA in progress: %ld [bytes] remainining. Returning.\n", left);
+#endif
+ return OK;
+ }
+#endif
+
if (priv->dcnt == -1 && priv->msgc > 0)
{
i2cinfo("Switch to new message\n");
@@ -1484,6 +1561,46 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
/* Trace */
stm32_i2c_traceevent(priv, I2CEVENT_ADDRESS_ACKED, 0);
+
+#ifdef CONFIG_STM32_I2C_DMA
+ /* DMA only when not doing a short read */
+
+ i2cinfo("Starting dma transfer and disabling interrupts\n");
+
+ /* The DMA must be initialized and enabled before the I2C data transfer.
+ * The DMAEN bit must be set in the I2C_CR2 register before the ADDR event.
+ */
+
+ stm32_dmasetup(priv->rxdma, priv->config->base+STM32_I2C_DR_OFFSET,
+ (uint32_t) priv->ptr, priv->dcnt,
+ DMA_SCR_DIR_P2M |
+ DMA_SCR_MSIZE_8BITS |
+ DMA_SCR_PSIZE_8BITS |
+ DMA_SCR_MINC |
+ I2C_DMA_PRIO);
+
+ /* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
+ * used.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
+
+#ifndef CONFIG_I2C_POLLED
+ /* Now let DMA do all the work, disable i2c interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval &= ~I2C_CR2_ALLINTS;
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+#endif
+
+ /* The user can generate a Stop condition in the DMA Transfer Complete
+ * interrupt routine if enabled. This will be done in the dma rx callback
+ * Start DMA.
+ */
+
+ stm32_dmastart(priv->rxdma, stm32_i2c_dmarxcallback, priv, false);
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_DMAEN);
+#endif
}
}
@@ -1520,19 +1637,67 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
if (priv->dcnt >= 1)
{
- /* Transmitting message. Send byte == write data into write register */
+#ifdef CONFIG_STM32_I2C_DMA
+ /* if DMA is enabled, only makes sense to make use of it for longer
+ than 1 B transfers.. */
- stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
+ if (priv->dcnt > 1)
+ {
+ i2cinfo("Starting dma transfer and disabling interrupts\n");
- /* Decrease current message length */
+ /* The DMA must be initialized and enabled before the I2C data transfer.
+ * The DMAEN bit must be set in the I2C_CR2 register before the ADDR event.
+ */
- stm32_i2c_traceevent(priv, I2CEVENT_WRITE_TO_DR, priv->dcnt);
- priv->dcnt--;
+ stm32_dmasetup(priv->txdma, priv->config->base+STM32_I2C_DR_OFFSET,
+ (uint32_t) priv->ptr, priv->dcnt,
+ DMA_SCR_DIR_M2P |
+ DMA_SCR_MSIZE_8BITS |
+ DMA_SCR_PSIZE_8BITS |
+ DMA_SCR_MINC |
+ I2C_DMA_PRIO );
+ /* Do not enable the ITBUFEN bit in the I2C_CR2 register if DMA is
+ * used.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_ITBUFEN, 0);
+
+#ifndef CONFIG_I2C_POLLED
+ /* Now let DMA do all the work, disable i2c interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval &= ~I2C_CR2_ALLINTS;
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+#endif
+
+ /* In the interrupt routine after the EOT interrupt, disable DMA
+ * requests then wait for a BTF event before programming the Stop
+ * condition. To do this, we'll just call the ISR again in
+ * dma tx callback, in which point we fall into the msgc==0 case
+ * which ultimately sends the stop..TODO: but we don't explicitly
+ * wait for BTF bit being set...
+ * Start DMA.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, 0, I2C_CR2_DMAEN);
+ stm32_dmastart(priv->txdma, stm32_i2c_dmatxcallback, priv, false);
+ }
+ else
+#endif /* CONFIG_STM32_I2C_DMA */
+ {
+ /* Transmitting message. Send byte == write data into write register */
+
+ stm32_i2c_putreg(priv, STM32_I2C_DR_OFFSET, *priv->ptr++);
+
+ /* Decrease current message length */
+
+ stm32_i2c_traceevent(priv, I2CEVENT_WRITE_TO_DR, priv->dcnt);
+ priv->dcnt--;
+ }
}
else if (priv->dcnt == 0)
{
-
/* After last byte, check what to do based on next message flags */
if (priv->msgc == 0)
@@ -1678,6 +1843,7 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
stm32_i2c_traceevent(priv, I2CEVENT_READ_2, 0);
}
+#ifndef CONFIG_STM32_I2C_DMA
/* Case total message length >= 3 */
else if (priv->dcnt >= 4 && priv->total_msg_len >= 3)
@@ -1757,6 +1923,7 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
priv->dcnt = -1;
}
+#endif /* CONFIG_STM32_I2C_DMA */
/* Error handling for read mode */
@@ -1765,7 +1932,8 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
i2cinfo("I2C read mode no correct state detected\n");
i2cinfo(" state %i, dcnt=%i\n", status, priv->dcnt);
- /* set condition to terminate ISR and wake waiting thread */
+ /* Set condition to terminate ISR and wake waiting thread */
+
priv->dcnt = -1;
priv->msgc = 0;
stm32_i2c_traceevent(priv, I2CEVENT_READ_ERROR, 0);
@@ -1804,9 +1972,9 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
else
{
- #ifdef CONFIG_I2C_POLLED
+#ifdef CONFIG_I2C_POLLED
stm32_i2c_traceevent(priv, I2CEVENT_POLL_DEV_NOT_RDY, 0);
- #else
+#else
/* Read rest of the state */
status |= (stm32_i2c_getreg(priv, STM32_I2C_SR2_OFFSET) << 16);
@@ -1814,12 +1982,12 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
i2cinfo(" No correct state detected(start bit, read or write) \n");
i2cinfo(" state %i\n", status);
- /* set condition to terminate ISR and wake waiting thread */
+ /* Set condition to terminate ISR and wake waiting thread */
priv->dcnt = -1;
priv->msgc = 0;
stm32_i2c_traceevent(priv, I2CEVENT_STATE_ERROR, 0);
- #endif
+#endif
}
/* Messages handling(2/2)
@@ -1842,9 +2010,9 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
priv->msgv = NULL;
- #ifdef CONFIG_I2C_POLLED
+#ifdef CONFIG_I2C_POLLED
priv->intstate = INTSTATE_DONE;
- #else
+#else
/* Clear all interrupts */
uint32_t regval;
@@ -1863,12 +2031,98 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
sem_post(&priv->sem_isr);
priv->intstate = INTSTATE_DONE;
}
- #endif
+#endif
}
return OK;
}
+/*****************************************************************************
+ * Name: stm32_i2c_dmarxcallback
+ *
+ * Description:
+ * Called when the RX DMA completes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_STM32_I2C_DMA
+static void stm32_i2c_dmarxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+#ifndef CONFIG_I2C_POLLED
+ uint32_t regval;
+#endif
+
+ i2cinfo("DMA rx callback, status = %d \n", status);
+
+ FAR struct stm32_i2c_priv_s *priv = (FAR struct stm32_i2c_priv_s *)arg;
+
+ priv->dcnt = -1;
+
+ /* The user can generate a Stop condition in the DMA Transfer Complete
+ * interrupt routine if enabled.
+ */
+
+ stm32_i2c_sendstop(priv);
+
+ /* Let the I2C periph know to stop DMA transfers, also is used by ISR to check
+ * if DMA is done.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_DMAEN, 0);
+
+#ifndef CONFIG_I2C_POLLED
+ /* Re-enable interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval |= (I2C_CR2_ITERREN | I2C_CR2_ITEVFEN);
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+#endif
+
+ /* let the ISR routine take care of shutting down or switching to next msg */
+
+ stm32_i2c_isr(priv);
+}
+#endif /* ifdef CONFIG_STM32_I2C_DMA */
+
+/*****************************************************************************
+ * Name: stm32_i2c_dmarxcallback
+ *
+ * Description:
+ * Called when the RX DMA completes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_STM32_I2C_DMA
+static void stm32_i2c_dmatxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+#ifndef CONFIG_I2C_POLLED
+ uint32_t regval;
+#endif
+
+ i2cinfo("DMA tx callback, status = %d \n", status);
+
+ FAR struct stm32_i2c_priv_s *priv = (FAR struct stm32_i2c_priv_s *)arg;
+
+ priv->dcnt = 0;
+
+ /* In the interrupt routine after the EOT interrupt, disable DMA requests */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_DMAEN, 0);
+
+#ifndef CONFIG_I2C_POLLED
+ /* re-enable interrupts */
+
+ regval = stm32_i2c_getreg(priv, STM32_I2C_CR2_OFFSET);
+ regval |= (I2C_CR2_ITERREN | I2C_CR2_ITEVFEN);
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, regval);
+#endif
+
+ /* let the ISR routine take care of shutting down or switching to next msg */
+
+ stm32_i2c_isr(priv);
+}
+#endif /* ifdef CONFIG_STM32_I2C_DMA */
+
/************************************************************************************
* Name: stm32_i2c1_isr
*
@@ -1914,7 +2168,7 @@ static int stm32_i2c3_isr(int irq, void *context, FAR void *arg)
return stm32_i2c_isr(&stm32_i2c3_priv);
}
#endif
-#endif
+#endif /* CONFIG_I2C_POLLED */
/************************************************************************************
* Private Initialization and Deinitialization
@@ -1972,6 +2226,15 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
stm32_i2c_setclock(priv, 100000);
+#ifdef CONFIG_STM32_I2C_DMA
+ /* If, in the I2C_CR2 register, the LAST bit is set, I2C automatically
+ * sends a NACK after the next byte following EOT_1.
+ * Clear DMA en just in case.
+ */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_DMAEN, I2C_CR2_LAST);
+#endif
+
/* Enable I2C */
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_PE);
@@ -1991,6 +2254,7 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
/* Disable I2C */
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0);
+ stm32_i2c_putreg(priv, STM32_I2C_CR2_OFFSET, 0);
/* Unconfigure GPIO pins */
@@ -2006,6 +2270,13 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
irq_detach(priv->config->er_irq);
#endif
+#ifdef CONFIG_STM32_I2C_DMA
+ /* Disable DMA */
+
+ stm32_dmastop(priv->txdma);
+ stm32_dmastop(priv->rxdma);
+#endif
+
/* Disable clocking */
modifyreg32(STM32_RCC_APB1ENR, priv->config->clk_bit, 0);
@@ -2035,7 +2306,15 @@ static int stm32_i2c_transfer(FAR struct i2c_master_s *dev, FAR struct i2c_msg_s
#endif
int ret = 0;
- ASSERT(count);
+ DEBUGASSERT(count);
+
+#ifdef CONFIG_STM32_I2C_DMA
+ /* stop DMA just in case */
+
+ stm32_i2c_modifyreg(priv, STM32_I2C_CR2_OFFSET, I2C_CR2_DMAEN, 0);
+ stm32_dmastop(priv->rxdma);
+ stm32_dmastop(priv->txdma);
+#endif
#ifdef I2C1_FSMC_CONFLICT
/* Disable FSMC that shares a pin with I2C1 (LBAR) */
@@ -2246,11 +2525,11 @@ static int stm32_i2c_reset(FAR struct i2c_master_s *dev)
uint32_t frequency;
int ret = ERROR;
- ASSERT(dev);
+ DEBUGASSERT(dev);
/* Our caller must own a ref */
- ASSERT(priv->refs > 0);
+ DEBUGASSERT(priv->refs > 0);
/* Lock out other clients */
@@ -2412,6 +2691,19 @@ FAR struct i2c_master_s *stm32_i2cbus_initialize(int port)
{
stm32_i2c_sem_init(priv);
stm32_i2c_init(priv);
+
+#ifdef CONFIG_STM32_I2C_DMA
+ /* Get DMA channels. NOTE: stm32_dmachannel() will always assign the DMA channel.
+ * if the channel is not available, then stm32_dmachannel() will block and wait
+ * until the channel becomes available. WARNING: If you have another device sharing
+ * a DMA channel with SPI and the code never releases that channel, then the call
+ * to stm32_dmachannel() will hang forever in this function! Don't let your
+ * design do that!
+ */
+ priv->rxdma = stm32_dmachannel(priv->rxch);
+ priv->txdma = stm32_dmachannel(priv->txch);
+ DEBUGASSERT(priv->rxdma && priv->txdma);
+#endif /* #ifdef CONFIG_STM32_I2C_DMA */
}
leave_critical_section(flags);
@@ -2431,7 +2723,7 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
FAR struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev;
irqstate_t flags;
- ASSERT(dev);
+ DEBUGASSERT(dev);
/* Decrement reference count and check for underflow */
@@ -2454,6 +2746,11 @@ int stm32_i2cbus_uninitialize(FAR struct i2c_master_s *dev)
stm32_i2c_deinit(priv);
+#ifdef CONFIG_STM32_I2C_DMA
+ stm32_dmafree(priv->rxdma);
+ stm32_dmafree(priv->txdma);
+#endif
+
/* Release unused resources */
stm32_i2c_sem_destroy(priv);
diff --git a/arch/arm/src/xmc4/chip/xmc4_memorymap.h b/arch/arm/src/xmc4/chip/xmc4_memorymap.h
index a2df7e405ce..a326460cc7b 100644
--- a/arch/arm/src/xmc4/chip/xmc4_memorymap.h
+++ b/arch/arm/src/xmc4/chip/xmc4_memorymap.h
@@ -221,7 +221,7 @@
#define XMC4_USB0_EP4_BASE 0x50040980
#define XMC4_USB0_EP5_BASE 0x500409a0
#define XMC4_USB0_EP6_BASE 0x500409c0
-#define XMC4_USB0_EP6_BASE 0x50100000 /* ECAT0 */
+#define XMC4_ECAT0_BASE 0x50100000 /* ECAT0 */
#define XMC4_PMU0_BASE 0x58000000 /* PMU0 registers */
#define XMC4_FLASH0_BASE 0x58001000
diff --git a/arch/arm/src/xmc4/chip/xmc4_ports.h b/arch/arm/src/xmc4/chip/xmc4_ports.h
index bdd90c2902b..a769ddf73c9 100644
--- a/arch/arm/src/xmc4/chip/xmc4_ports.h
+++ b/arch/arm/src/xmc4/chip/xmc4_ports.h
@@ -71,7 +71,7 @@
#define XMC4_PORT_OUT_OFFSET 0x0000 /* Port Output Register */
#define XMC4_PORT_OMR_OFFSET 0x0004 /* Port Output Modification Register */
-#define XMC4_PORT_IOCR_OFFSET(n) (0x0010 + ((n) & 3))
+#define XMC4_PORT_IOCR_OFFSET(n) (0x0010 + ((n) & ~3))
#define XMC4_PORT_IOCR0_OFFSET 0x0010 /* Port Input/Output Control Register 0 */
#define XMC4_PORT_IOCR4_OFFSET 0x0014 /* Port Input/Output Control Register 4 */
#define XMC4_PORT_IOCR8_OFFSET 0x0018 /* Port Input/Output Control Register 8 */
@@ -79,7 +79,7 @@
#define XMC4_PORT_IN_OFFSET 0x0024 /* Port Input Register */
-#define XMC4_PORT_PDR_OFFSET(n) (0x0010 + (((n) >> 1) & 3))
+#define XMC4_PORT_PDR_OFFSET(n) (0x0040 + (((n) >> 1) & ~3))
#define XMC4_PORT_PDR0_OFFSET 0x0040 /* Port Pad Driver Mode 0 Register */
#define XMC4_PORT_PDR1_OFFSET 0x0044 /* Port Pad Driver Mode 1 Register */
@@ -399,19 +399,19 @@
#define PORT_PDR0_PD2_SHIFT (8) /* Bit 8-10: Pad Driver Mode for Port n Pin 2 */
#define PORT_PDR0_PD2_MASK (7 << PORT_PDR0_PD2_SHIFT)
# define PORT_PDR0_PD2(n) ((uint32_t)(n) << PORT_PDR0_PD2_SHIFT)
-#define PORT_PDR0_PD3_SHIFT (12) /* Bit 12-14: Pad Driver Mode for Port 0 Pin 3 */
+#define PORT_PDR0_PD3_SHIFT (12) /* Bit 12-14: Pad Driver Mode for Port n Pin 3 */
#define PORT_PDR0_PD3_MASK (7 << PORT_PDR0_PD3_SHIFT)
# define PORT_PDR0_PD3(n) ((uint32_t)(n) << PORT_PDR0_PD3_SHIFT)
-#define PORT_PDR0_PD4_SHIFT (16) /* Bit 16-18: Pad Driver Mode for Port 0 Pin 4 */
+#define PORT_PDR0_PD4_SHIFT (16) /* Bit 16-18: Pad Driver Mode for Port n Pin 4 */
#define PORT_PDR0_PD4_MASK (7 << PORT_PDR0_PD4_SHIFT)
# define PORT_PDR0_PD4(n) ((uint32_t)(n) << PORT_PDR0_PD4_SHIFT)
-#define PORT_PDR0_PD5_SHIFT (20) /* Bit 20-22: Pad Driver Mode for Port 0 Pin 5 */
+#define PORT_PDR0_PD5_SHIFT (20) /* Bit 20-22: Pad Driver Mode for Port n Pin 5 */
#define PORT_PDR0_PD5_MASK (7 << PORT_PDR0_PD5_SHIFT)
# define PORT_PDR0_PD5(n) ((uint32_t)(n) << PORT_PDR0_PD5_SHIFT)
-#define PORT_PDR0_PD6_SHIFT (24) /* Bit 24-26: Pad Driver Mode for Port 0 Pin 6 */
+#define PORT_PDR0_PD6_SHIFT (24) /* Bit 24-26: Pad Driver Mode for Port n Pin 6 */
#define PORT_PDR0_PD6_MASK (7 << PORT_PDR0_PD6_SHIFT)
# define PORT_PDR0_PD6(n) ((uint32_t)(n) << PORT_PDR0_PD6_SHIFT)
-#define PORT_PDR0_PD7_SHIFT (28) /* Bit 28-30: Pad Driver Mode for Port 0 Pin 7 */
+#define PORT_PDR0_PD7_SHIFT (28) /* Bit 28-30: Pad Driver Mode for Port n Pin 7 */
#define PORT_PDR0_PD7_MASK (7 << PORT_PDR0_PD7_SHIFT)
# define PORT_PDR0_PD7(n) ((uint32_t)(n) << PORT_PDR0_PD7_SHIFT)
@@ -429,19 +429,19 @@
#define PORT_PDR1_PD10_SHIFT (8) /* Bit 8-10: Pad Driver Mode for Port n Pin 10 */
#define PORT_PDR1_PD10_MASK (7 << PORT_PDR1_PD10_SHIFT)
# define PORT_PDR1_PD10(n) ((uint32_t)(n) << PORT_PDR1_PD10_SHIFT)
-#define PORT_PDR1_PD11_SHIFT (12) /* Bit 12-14: Pad Driver Mode for Port 0 Pin 11 */
+#define PORT_PDR1_PD11_SHIFT (12) /* Bit 12-14: Pad Driver Mode for Port n Pin 11 */
#define PORT_PDR1_PD11_MASK (7 << PORT_PDR1_PD11_SHIFT)
# define PORT_PDR1_PD11(n) ((uint32_t)(n) << PORT_PDR1_PD11_SHIFT)
-#define PORT_PDR1_PD12_SHIFT (16) /* Bit 16-18: Pad Driver Mode for Port 0 Pin 12 */
+#define PORT_PDR1_PD12_SHIFT (16) /* Bit 16-18: Pad Driver Mode for Port n Pin 12 */
#define PORT_PDR1_PD12_MASK (7 << PORT_PDR1_PD12_SHIFT)
# define PORT_PDR1_PD12(n) ((uint32_t)(n) << PORT_PDR1_PD12_SHIFT)
-#define PORT_PDR1_PD13_SHIFT (20) /* Bit 20-22: Pad Driver Mode for Port 0 Pin 13 */
+#define PORT_PDR1_PD13_SHIFT (20) /* Bit 20-22: Pad Driver Mode for Port n Pin 13 */
#define PORT_PDR1_PD13_MASK (7 << PORT_PDR1_PD13_SHIFT)
# define PORT_PDR1_PD13(n) ((uint32_t)(n) << PORT_PDR1_PD13_SHIFT)
-#define PORT_PDR1_PD14_SHIFT (24) /* Bit 24-26: Pad Driver Mode for Port 0 Pin 14 */
+#define PORT_PDR1_PD14_SHIFT (24) /* Bit 24-26: Pad Driver Mode for Port n Pin 14 */
#define PORT_PDR1_PD14_MASK (7 << PORT_PDR1_PD14_SHIFT)
# define PORT_PDR1_PD14(n) ((uint32_t)(n) << PORT_PDR1_PD14_SHIFT)
-#define PORT_PDR1_PD15_SHIFT (28) /* Bit 28-30: Pad Driver Mode for Port 0 Pin 15 */
+#define PORT_PDR1_PD15_SHIFT (28) /* Bit 28-30: Pad Driver Mode for Port n Pin 15 */
#define PORT_PDR1_PD15_MASK (7 << PORT_PDR1_PD15_SHIFT)
# define PORT_PDR1_PD15(n) ((uint32_t)(n) << PORT_PDR1_PD15_SHIFT)
diff --git a/arch/arm/src/xmc4/chip/xmc4_scu.h b/arch/arm/src/xmc4/chip/xmc4_scu.h
index 38d26051b77..2d22084252d 100644
--- a/arch/arm/src/xmc4/chip/xmc4_scu.h
+++ b/arch/arm/src/xmc4/chip/xmc4_scu.h
@@ -889,7 +889,7 @@
#define SCU_PBCLKCR_PBDIV (1 << 0) /* Bit 0: PB Clock Divider Enable */
# define SCU_PBCLKCR_PBDIV_FCPU (0) /* 0=fCPU */
-# define SCU_PBCLKCR_PBDIV_DIV2 ((1 << 0) /* 1=fCPU/2 */
+# define SCU_PBCLKCR_PBDIV_DIV2 (1 << 0) /* 1=fCPU/2 */
/* USB Clock Control */
diff --git a/arch/arm/src/xmc4/chip/xmc4_usic.h b/arch/arm/src/xmc4/chip/xmc4_usic.h
index 462ac44c955..274d0fae53b 100644
--- a/arch/arm/src/xmc4/chip/xmc4_usic.h
+++ b/arch/arm/src/xmc4/chip/xmc4_usic.h
@@ -563,7 +563,7 @@
# define USIC_SCTR_TRM_ACTIVE (3 << USIC_SCTR_TRM_SHIFT) /* Active without regard to signal level */
#define USIC_SCTR_FLE_SHIFT (16) /* Bits 16-21: Frame Length */
#define USIC_SCTR_FLE_MASK (0x3f << USIC_SCTR_FLE_SHIFT)
-# define USIC_SCTR_FLE(n) ((uint32_t)(n) << USIC_SCTR_FLE_SHIFT)
+# define USIC_SCTR_FLE(n) ((uint32_t)((n)-1) << USIC_SCTR_FLE_SHIFT)
#define USIC_SCTR_WLE_SHIFT (24) /* Bits 24-27: Word Length */
#define USIC_SCTR_WLE_MASK (15 << USIC_SCTR_WLE_SHIFT)
# define USIC_SCTR_WLE(n) ((uint32_t)((n)-1) << USIC_SCTR_WLE_SHIFT)
diff --git a/arch/arm/src/xmc4/xmc4_clockconfig.c b/arch/arm/src/xmc4/xmc4_clockconfig.c
index db72a3cdf9c..519276f2cdc 100644
--- a/arch/arm/src/xmc4/xmc4_clockconfig.c
+++ b/arch/arm/src/xmc4/xmc4_clockconfig.c
@@ -105,13 +105,18 @@
#define CLKSET_VALUE (0x00000000)
#define SYSCLKCR_VALUE (0x00010001)
#define CPUCLKCR_VALUE (0x00000000)
-#define PBCLKCR_VALUE (0x00000000)
#define CCUCLKCR_VALUE (0x00000000)
#define WDTCLKCR_VALUE (0x00000000)
#define EBUCLKCR_VALUE (0x00000003)
#define USBCLKCR_VALUE (0x00010000)
#define EXTCLKCR_VALUE (0x01200003)
+#if BOARD_PBDIV == 1
+# define PBCLKCR_VALUE SCU_PBCLKCR_PBDIV_FCPU
+#else /* BOARD_PBDIV == 2 */
+# define PBCLKCR_VALUE SCU_PBCLKCR_PBDIV_DIV2
+#endif
+
#if ((USBCLKCR_VALUE & SCU_USBCLKCR_USBSEL) == SCU_USBCLKCR_USBSEL_USBPLL)
# define USB_DIV 3
#else
@@ -182,9 +187,9 @@ void xmc4_clock_configure(void)
regval = getreg32(XMC4_SCU_PWRSTAT);
if ((regval & SCU_PWR_HIBEN) == 0)
{
- regval = getreg32(XMC4_SCU_PWRSET);
- regval |= SCU_PWR_HIBEN;
- putreg32(regval, XMC4_SCU_PWRSTAT);
+ /* Enable the HIB domain */
+
+ putreg32(SCU_PWR_HIBEN, XMC4_SCU_PWRSET);
/* Wait until HIB domain is enabled */
@@ -193,7 +198,7 @@ void xmc4_clock_configure(void)
}
}
- /* Remove the reset only if HIB domain were in a state of reset */
+ /* Remove the reset only if HIB domain was in a state of reset */
regval = getreg32(XMC4_SCU_RSTSTAT);
if ((regval & SCU_RSTSTAT_HIBRS) != 0)
@@ -387,7 +392,7 @@ void xmc4_clock_configure(void)
/* Before scaling to final frequency we need to setup the clock dividers */
putreg32(SYSCLKCR_VALUE, XMC4_SCU_SYSCLKCR);
- putreg32(PBCLKCR_VALUE, XMC4_SCU_PBCLKCR);
+ putreg32(PBCLKCR_VALUE, XMC4_SCU_PBCLKCR);
putreg32(CPUCLKCR_VALUE, XMC4_SCU_CPUCLKCR);
putreg32(CCUCLKCR_VALUE, XMC4_SCU_CCUCLKCR);
putreg32(WDTCLKCR_VALUE, XMC4_SCU_WDTCLKCR);
diff --git a/arch/arm/src/xmc4/xmc4_clockutils.c b/arch/arm/src/xmc4/xmc4_clockutils.c
index 4d334eaef53..2a391ca3861 100644
--- a/arch/arm/src/xmc4/xmc4_clockutils.c
+++ b/arch/arm/src/xmc4/xmc4_clockutils.c
@@ -161,6 +161,7 @@ uint32_t xmc4_get_coreclock(void)
uint32_t xmc4_get_periphclock(void)
{
uint32_t periphclock;
+ uint32_t regval;
/* Get the CPU clock frequency. Unless it is divided down, this also the
* peripheral clock frequency.
@@ -170,12 +171,12 @@ uint32_t xmc4_get_periphclock(void)
/* Get the peripheral clock divider */
- periphclock = getreg32(XMC4_SCU_PBCLKCR);
- if ((periphclock & SCU_PBCLKCR_PBDIV) != 0)
+ regval = getreg32(XMC4_SCU_PBCLKCR);
+ if ((regval & SCU_PBCLKCR_PBDIV) != 0)
{
/* The peripheral clock is fCPU/2 */
- periphclock <<= 1;
+ periphclock >>= 1;
}
return periphclock;
diff --git a/arch/arm/src/xmc4/xmc4_gpio.c b/arch/arm/src/xmc4/xmc4_gpio.c
index e26967f06f3..d88e73c7adc 100644
--- a/arch/arm/src/xmc4/xmc4_gpio.c
+++ b/arch/arm/src/xmc4/xmc4_gpio.c
@@ -234,7 +234,7 @@ static inline void xmc4_gpio_hwsel(uintptr_t portbase, unsigned int pin,
****************************************************************************/
static inline void xmc4_gpio_pdisc(uintptr_t portbase, unsigned int pin,
- bool value)
+ bool enable)
{
uint32_t regval;
uint32_t mask;
@@ -243,16 +243,21 @@ static inline void xmc4_gpio_pdisc(uintptr_t portbase, unsigned int pin,
regval = xmc4_gpio_getreg(portbase, XMC4_PORT_PDISC_OFFSET);
- /* Set/clear the enable/disable (or analg) value for this field */
+ /* Set or clear the pin field in the PDISC register.
+ *
+ * Disable = set
+ * Analog = set
+ * Enable = clear
+ */
mask = PORT_PIN(pin);
- if (value)
+ if (enable)
{
- regval |= mask;
+ regval &= ~mask;
}
else
{
- regval &= ~mask;
+ regval |= mask;
}
xmc4_gpio_putreg(portbase, XMC4_PORT_PDISC_OFFSET, regval);
@@ -267,7 +272,7 @@ static inline void xmc4_gpio_pdisc(uintptr_t portbase, unsigned int pin,
****************************************************************************/
static inline void xmc4_gpio_pps(uintptr_t portbase, unsigned int pin,
- bool value)
+ bool powersave)
{
uint32_t regval;
uint32_t mask;
@@ -276,10 +281,10 @@ static inline void xmc4_gpio_pps(uintptr_t portbase, unsigned int pin,
regval = xmc4_gpio_getreg(portbase, XMC4_PORT_PPS_OFFSET);
- /* Set/clear the enable/disable (or analg) value for this field */
+ /* Set/clear the enable/disable power save value for this field */
mask = PORT_PIN(pin);
- if (value)
+ if (powersave)
{
regval |= mask;
}
@@ -307,7 +312,7 @@ static void xmc4_gpio_pdr(uintptr_t portbase, unsigned int pin,
unsigned int offset;
unsigned int shift;
- /* Read the PDRregister */
+ /* Read the PDR register */
offset = XMC4_PORT_PDR_OFFSET(pin);
regval = xmc4_gpio_getreg(portbase, offset);
@@ -412,18 +417,18 @@ int xmc4_gpio_config(gpioconfig_t pinconfig)
value = xmc4_gpio_pinctrl(pinconfig);
xmc4_gpio_hwsel(portbase, pin, value);
- /* Select drive strength */
+ /* Select drive strength (PDR) */
value = xmc4_gpio_padtype(pinconfig);
xmc4_gpio_pdr(portbase, pin, value);
/* Enable/enable pad or Analog only (PDISC) */
- xmc4_gpio_pdisc(portbase, pin, ((pinconfig & GPIO_PAD_DISABLE) != 0));
+ xmc4_gpio_pdisc(portbase, pin, ((pinconfig & GPIO_PAD_DISABLE) == 0));
- /* Make sure pin is not in power save mode (PDR) */
+ /* Make sure pin is not in power save mode (PPS) */
- xmc4_gpio_pdisc(portbase, pin, false);
+ xmc4_gpio_pps(portbase, pin, false);
leave_critical_section(flags);
return OK;
diff --git a/arch/arm/src/xmc4/xmc4_gpio.h b/arch/arm/src/xmc4/xmc4_gpio.h
index 4595fe6a795..0dce7af73cd 100644
--- a/arch/arm/src/xmc4/xmc4_gpio.h
+++ b/arch/arm/src/xmc4/xmc4_gpio.h
@@ -79,8 +79,8 @@
# define GPIO_OUTPUT_ALT4 (IOCR_OUTPUT_ALT4 << GPIO_PINTYPE_SHIFT)
# define _GPIO_OUTPUT_BIT (16 << GPIO_PINTYPE_SHIFT)
-# define GPIO_ISINPUT(p) (((p) & _GPIO_OUTPUT_BIT) != 0)
-# define GPIO_ISOUTPUT(p) (((p) & _GPIO_OUTPUT_BIT) == 0)
+# define GPIO_ISINPUT(p) (((p) & _GPIO_OUTPUT_BIT) == 0)
+# define GPIO_ISOUTPUT(p) (((p) & _GPIO_OUTPUT_BIT) != 0)
/* Pin type modifier:
*
@@ -160,7 +160,7 @@
*/
#define GPIO_PORT_SHIFT (4) /* Bit 4-7: Port number */
-#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT)
+#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT)
# define GPIO_PORT0 (0 << GPIO_PORT_SHIFT)
# define GPIO_PORT1 (1 << GPIO_PORT_SHIFT)
# define GPIO_PORT2 (2 << GPIO_PORT_SHIFT)
@@ -180,7 +180,7 @@
*/
#define GPIO_PIN_SHIFT (0) /* Bits 0-3: GPIO pin: 0-15 */
-#define GPIO_PIN_MASK (31 << GPIO_PIN_SHIFT)
+#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT)
#define GPIO_PIN0 (0 << GPIO_PIN_SHIFT)
#define GPIO_PIN1 (1 << GPIO_PIN_SHIFT)
#define GPIO_PIN2 (2 << GPIO_PIN_SHIFT)
diff --git a/arch/arm/src/xmc4/xmc4_lowputc.c b/arch/arm/src/xmc4/xmc4_lowputc.c
index fcb930d1b90..c1416194fc3 100644
--- a/arch/arm/src/xmc4/xmc4_lowputc.c
+++ b/arch/arm/src/xmc4/xmc4_lowputc.c
@@ -275,7 +275,7 @@ int xmc4_uart_configure(enum usic_channel_e channel,
* the config structure.
*/
- ret = xmc4_uisc_baudrate(channel, config->baud, UART_OVERSAMPLING);
+ ret = xmc4_usic_baudrate(channel, config->baud, UART_OVERSAMPLING);
/* Configure frame format.
*
diff --git a/arch/arm/src/xmc4/xmc4_usic.c b/arch/arm/src/xmc4/xmc4_usic.c
index dd69cf318dd..925c9c0f411 100644
--- a/arch/arm/src/xmc4/xmc4_usic.c
+++ b/arch/arm/src/xmc4/xmc4_usic.c
@@ -121,12 +121,12 @@ int xmc4_enable_usic(enum usic_e usic)
putreg32(SCU_CGAT0_USIC0, XMC4_SCU_CGATCLR0);
- /* De-assert peripheral reset USIC0 */
+ /* Set bit in PRCLR0 to de-assert USIC0 peripheral reset */
putreg32(SCU_PR0_USIC0RS, XMC4_SCU_PRCLR0);
}
#else
- /* De-assert peripheral reset USIC0 */
+ /* Set bit in PRCLR0 to de-assert USIC0 peripheral reset */
putreg32(SCU_PR0_USIC0RS, XMC4_SCU_PRCLR0);
#endif
@@ -143,12 +143,12 @@ int xmc4_enable_usic(enum usic_e usic)
putreg32(SCU_CGAT1_USIC1, XMC4_SCU_CGATCLR1);
- /* De-assert peripheral reset USIC1 */
+ /* Set bit in PRCLR1 to de-assert USIC1 peripheral reset */
putreg32(SCU_PR1_USIC1RS, XMC4_SCU_PRCLR1);
}
#else
- /* De-assert peripheral reset USIC1 */
+ /* Set bit in PRCLR1 to de-assert USIC1 peripheral reset */
putreg32(SCU_PR1_USIC1RS, XMC4_SCU_PRCLR1);
#endif
@@ -165,12 +165,12 @@ int xmc4_enable_usic(enum usic_e usic)
putreg32(SCU_CGAT1_USIC2, XMC4_SCU_CGATCLR1);
- /* De-assert peripheral reset USIC2 */
+ /* Set bit in PRCLR1 to de-assert USIC2 peripheral reset */
putreg32(SCU_PR1_USIC2RS, XMC4_SCU_PRCLR1);
}
#else
- /* De-assert peripheral reset USIC2 */
+ /* Set bit in PRCLR1 to de-assert USIC2 peripheral reset */
putreg32(SCU_PR1_USIC2RS, XMC4_SCU_PRCLR1);
#endif
@@ -203,7 +203,7 @@ int xmc4_disable_usic(enum usic_e usic)
switch (usic)
{
case USIC0:
- /* Assert peripheral reset USIC0 */
+ /* Set bit in PRSET0 to assert USIC0 peripheral reset */
putreg32(SCU_PR0_USIC0RS, XMC4_SCU_PRSET0);
@@ -216,7 +216,7 @@ int xmc4_disable_usic(enum usic_e usic)
#if XMC4_NUSIC > 1
case USIC1:
- /* Assert peripheral reset USIC0 */
+ /* Set bit in PRSET1 to assert USIC1 peripheral reset */
putreg32(SCU_PR1_USIC1RS, XMC4_SCU_PRSET1);
@@ -229,7 +229,7 @@ int xmc4_disable_usic(enum usic_e usic)
#if XMC4_NUSIC > 2
case USIC2:
- /* Assert peripheral reset USIC0 */
+ /* Set bit in PRSET1 to assert USIC2 peripheral reset */
putreg32(SCU_PR1_USIC2RS, XMC4_SCU_PRSET1);
@@ -385,7 +385,7 @@ int xmc4_disable_usic_channel(enum usic_channel_e channel)
}
/****************************************************************************
- * Name: xmc4_uisc_baudrate
+ * Name: xmc4_usic_baudrate
*
* Description:
* Set the USIC baudrate for the USIC channel
@@ -396,7 +396,7 @@ int xmc4_disable_usic_channel(enum usic_channel_e channel)
*
****************************************************************************/
-int xmc4_uisc_baudrate(enum usic_channel_e channel, uint32_t baud,
+int xmc4_usic_baudrate(enum usic_channel_e channel, uint32_t baud,
uint32_t oversampling)
{
uintptr_t base;
@@ -448,14 +448,14 @@ int xmc4_uisc_baudrate(enum usic_channel_e channel, uint32_t baud,
/* Select and setup the fractional divider */
- regval = USIC_FDR_DM_FRACTIONAL | (clkdiv_min << USIC_FDR_STEP_SHIFT);
+ regval = USIC_FDR_DM_FRACTIONAL | USIC_FDR_STEP(clkdiv_min);
putreg32(regval, base + XMC4_USIC_FDR_OFFSET);
/* Setup and enable the baud rate generator */
regval = getreg32(base + XMC4_USIC_BRG_OFFSET);
regval &= ~(USIC_BRG_DCTQ_MASK | USIC_BRG_PDIV_MASK | USIC_BRG_PCTQ_MASK | USIC_BRG_PPPEN);
- regval |= (USIC_BRG_DCTQ(oversampling - 1) | USIC_BRG_PDIV(pdiv_int_min - 1));
+ regval |= (USIC_BRG_DCTQ(oversampling - 1) | USIC_BRG_PDIV(pdiv_int_min - 1));
putreg32(regval, base + XMC4_USIC_BRG_OFFSET);
ret = OK;
diff --git a/arch/arm/src/xmc4/xmc4_usic.h b/arch/arm/src/xmc4/xmc4_usic.h
index 910846bc85e..291fb81fb01 100644
--- a/arch/arm/src/xmc4/xmc4_usic.h
+++ b/arch/arm/src/xmc4/xmc4_usic.h
@@ -177,7 +177,7 @@ int xmc4_enable_usic_channel(enum usic_channel_e channel);
int xmc4_disable_usic_channel(enum usic_channel_e channel);
/****************************************************************************
- * Name: xmc4_uisc_baudrate
+ * Name: xmc4_usic_baudrate
*
* Description:
* Set the USIC baudrate for the USIC channel
@@ -188,7 +188,7 @@ int xmc4_disable_usic_channel(enum usic_channel_e channel);
*
****************************************************************************/
-int xmc4_uisc_baudrate(enum usic_channel_e channel, uint32_t baud,
+int xmc4_usic_baudrate(enum usic_channel_e channel, uint32_t baud,
uint32_t oversampling);
#endif /* __ARCH_ARM_SRC_XMC4_XMC4_USIC_H */
diff --git a/configs/xmc4500-relax/README.txt b/configs/xmc4500-relax/README.txt
new file mode 100644
index 00000000000..e1fd46fa839
--- /dev/null
+++ b/configs/xmc4500-relax/README.txt
@@ -0,0 +1,168 @@
+README for the XMC4500 Relax
+============================
+
+ The directory provides board support for the Infinion XMC4500 Relax v1
+ boards. There are to variants of this board: There is a Lite version
+ that has fewer features, for example, no 32.768KHz crystal.
+
+ The current configurations support only the Lite version of the board.
+
+Status
+======
+
+ 2017-03-21: The XMC4500 Relax boots into NSH, provides the NSH prompt,
+ and the LEDs are working. But there is a problem with the USIC baud
+ (probably); I get garbage on the serial console. This probably means
+ that either the peripheral clocking is wrong or the baud configuration
+ is wrong.
+
+Serial Console
+==============
+
+ Be default, UART0 (aka, USIC0, channel 0) is used as the serial console.
+ The RX and TX pins is available:
+
+ RX - P1.4, Connector X2, pin 17
+ TX - P1.5, Connector X2, pin 16
+ GND - Available on pins 1-4 of either connector X1 or X2
+ VDD3.3 - Available on pins 37-38 of either connector X1 or X2
+ VDD5 - Available on pins 39-40 of either connector X1 or X2
+
+ A TTL to RS-232 convertor or a USB TTL-to-USB serial adaptor is required.
+ The notion of what is TX and what is RX depends on your point of view.
+ With the TTL to RS-232 converter, I connect pin 17 to the pin labeled
+ TX on the converter and pin 16 to the RX pin on the converter.
+
+LEDs
+====
+
+ The XMC4500 Relax Lite v1 board has two LEDs:
+
+ LED1 P1.1 High output illuminates
+ LED2 P1.0 High output illuminates
+
+ If CONFIG_ARCH_LEDS is not defined, then the user can control the LEDs in
+ any way. The definitions provided in the board.h header file can be used
+ to access individual LEDs.
+
+ These LEDs are not used by the board port unless CONFIG_ARCH_LEDS is
+ defined. In that case, the usage by the board port is defined in
+ include/board.h and src/sam_autoleds.c. The LEDs are used to encode
+ OS-related events as follows:
+
+ SYMBOL Meaning LED state
+ LED1 LED2
+ ------------------ ------------------------ ------ ------
+ LED_STARTED NuttX has been started OFF OFF
+ LED_HEAPALLOCATE Heap has been allocated OFF OFF
+ LED_IRQSENABLED Interrupts enabled OFF OFF
+ LED_STACKCREATED Idle stack created ON OFF
+ LED_INIRQ In an interrupt No change
+ LED_SIGNAL In a signal handler No change
+ LED_ASSERTION An assertion failed No change
+ LED_PANIC The system has crashed N/C Blinking
+ LED_IDLE MCU is is sleep mode Not used
+
+ Thus if LED1 is statically on, NuttX has successfully booted and is,
+ apparently, running normally. If LED2 is flashing at approximately
+ 2Hz, then a fatal error has been detected and the system has halted.
+
+Buttons
+=======
+
+ The XMC4500 Relax Lite v1 board has two buttons:
+
+ BUTTON1 P1.14 Low input sensed when button pressed
+ BUTTON2 P1.15 Low input sensed when button pressed
+
+Configurations
+==============
+
+ Information Common to All Configurations
+ ----------------------------------------
+ Each XMC4500 Relax configuration is maintained in a sub-directory and
+ can be selected as follow:
+
+ cd tools
+ ./configure.sh xmc5400-relax/
+ cd -
+ . ./setenv.sh
+
+ Before sourcing the setenv.sh file above, you should examine it and
+ perform edits as necessary so that TOOLCHAIN_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 oldconfig
+ make
+
+ The that is provided above as an argument to the tools/configure.sh
+ must be is one of the following.
+
+ NOTES:
+
+ 1. These configurations use the mconf-based configuration tool. To
+ change any of these configurations using that tool, you should:
+
+ a. Build and install the kconfig-mconf tool. See nuttx/README.txt
+ see additional README.txt files in the NuttX tools repository.
+
+ b. Execute 'make menuconfig' in nuttx/ in order to start the
+ reconfiguration process.
+
+ 2. Unless stated otherwise, all configurations generate console
+ output on UART0 (aka USIC0, channel 0) as described above under
+ "Serial Console". The relevant configuration settings are listed
+ below:
+
+ CONFIG_XMC4_USIC0=y
+ CONFIG_XMC4_USIC0_CHAN0_ISUART=y
+ CONFIG_XMC4_USIC0_CHAN1_NONE=y
+
+ CONFIG_UART0_SERIALDRIVER=y
+ CONFIG_UART0_SERIAL_CONSOLE=y
+
+ CONFIG_UART0_RXBUFSIZE=256
+ CONFIG_UART0_TXBUFSIZE=256
+ CONFIG_UART0_BAUD=115200
+ CONFIG_UART0_BITS=8
+ CONFIG_UART0_PARITY=0
+ CONFIG_UART0_2STOP=0
+
+
+ 3. All of these configurations are set up to build under Windows using the
+ "GNU Tools for ARM Embedded Processors" that is maintained by ARM
+ (unless stated otherwise in the description of the configuration).
+
+ https://launchpad.net/gcc-arm-embedded
+
+ That toolchain selection can easily be reconfigured using
+ 'make menuconfig'. Here are the relevant current settings:
+
+ Build Setup:
+ CONFIG_HOST_WINDOWS=y : Window environment
+ CONFIG_WINDOWS_CYGWIN=y : Cywin under Windows
+
+ System Type -> Toolchain:
+ CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIW=y : GNU ARM EABI toolchain
+
+ Configuration sub-directories
+ -----------------------------
+
+ nsh:
+
+ Configures the NuttShell (nsh) located at examples/nsh. This
+ configuration is focused on low level, command-line driver testing. It
+ has no network.
+
+ NOTES:
+
+ 1. NSH built-in applications are supported.
+
+ Binary Formats:
+ CONFIG_BUILTIN=y : Enable support for built-in programs
+
+ Application Configuration:
+ CONFIG_NSH_BUILTIN_APPS=y : Enable starting apps from NSH command line
diff --git a/configs/xmc4500-relax/include/board.h b/configs/xmc4500-relax/include/board.h
index 6be8e787f23..751e8031703 100644
--- a/configs/xmc4500-relax/include/board.h
+++ b/configs/xmc4500-relax/include/board.h
@@ -53,16 +53,21 @@
/* Clocking *************************************************************************/
/* Default clock initialization
- * fPLL = 288MHz => fSYS = 288MHz => fCPU = 144MHz
- * => fPB = 144MHz
- * => fCCU = 144MHz
- * => fETH = 72MHz
- * => fUSB = 48MHz
- * => fEBU = 72MHz
+ *
+ * fXTAL = 12Mhz
+ * -> fPLL = (fXTAL / (2 * 1) * 48) = 288MHz
+ * -> fSYS = (fPLL / 1) = 288MHz
+ * -> fCPU = (fSYS / 2) = 144MHz
+ * -> fPERIPH = (fCPU / 1) = 144MHz
+ * -> fCCU = (fSYS / 2) = 144MHz
+ * -> fETH = 72MHz (REVISIT)
+ * -> fUSB = 48MHz (REVISIT)
+ * -> fEBU = 72MHz (REVISIT)
*
* fUSBPLL Disabled, only enabled if SCU_CLK_USBCLKCR_USBSEL_USBPLL is selected
*
- * fOFI = 24MHz => fWDT = 24MHz
+ * fOFI = 24MHz
+ * -> fWDT = 24MHz (REVISIT)
*/
#undef BOARD_FOFI_CALIBRATION /* Enable factory calibration */
@@ -79,7 +84,7 @@
/* Select the external crystal as the PLL clock source */
#define BOARD_PLL_CLOCKSRC_XTAL 1 /* PLL Clock source == extnernal crystal */
-#undef BOARD_PLL_CLOCKSRC_OFI /* PLL Clock source != internal fast oscillator */
+#undef BOARD_PLL_CLOCKSRC_OFI /* PLL Clock source != internal fast oscillator */
/* PLL Configuration:
*
@@ -95,16 +100,21 @@
#define BOARD_PLL_K2DIV 1
#define BOARD_PLL_FREQUENCY 288000000
-/* System frequency is divided down from PLL output */
+/* System frequency, fSYS, is divided down from PLL output */
#define BOARD_SYSDIV 1 /* PLL Output divider to get fSYS */
#define BOARD_SYS_FREQUENCY 288000000
-/* CPU frequency may be divided down from system frequency */
+/* CPU frequency, fCPU, may be divided down from system frequency */
#define BOARD_CPUDIV_ENABLE 1 /* Enable PLL dive by 2 for fCPU */
#define BOARD_CPU_FREQUENCY 144000000
+/* The peripheral clock, fPERIPH, derives from fCPU with no division */
+
+#define BOARD_PBDIV 1 /* No division */
+#define BOARD_PERIPH_FREQUENCY 144000000
+
/* Standby clock source selection
*
* BOARD_STDBY_CLOCKSRC_OSI - Internal 32.768KHz slow oscillator
@@ -112,7 +122,7 @@
*/
#define BOARD_STDBY_CLOCKSRC_OSI 1
-#undef BOARD_STDBY_CLOCKSRC_OSCULP
+#undef BOARD_STDBY_CLOCKSRC_OSCULP
#define BOARD_STDBY_FREQUENCY 32768
/* USB PLL settings.
@@ -171,12 +181,9 @@
#define LED_PANIC 3 /* The system has crashed N/C Blinking */
#undef LED_IDLE /* MCU is is sleep mode Not used */
-/* Thus if LED0 is statically on, NuttX has successfully booted and is,
- * apparently, running normally. If LED1 is flashing at approximately
+/* Thus if LED1 is statically on, NuttX has successfully booted and is,
+ * apparently, running normally. If LED2 is flashing at approximately
* 2Hz, then a fatal error has been detected and the system has halted.
- *
- * NOTE: That LED0 is not used after completion of booting and may
- * be used by other board-specific logic.
*/
/* Button definitions ***************************************************************/
diff --git a/configs/xmc4500-relax/src/xmc4_autoleds.c b/configs/xmc4500-relax/src/xmc4_autoleds.c
index 694007c5e5e..69eda6dee93 100644
--- a/configs/xmc4500-relax/src/xmc4_autoleds.c
+++ b/configs/xmc4500-relax/src/xmc4_autoleds.c
@@ -43,19 +43,19 @@
* include/board.h and src/sam_autoleds.c. The LEDs are used to encode
* OS-related events as follows:
*
- * SYMBOL Meaning LED state
- * LED2 LED1
- * --------------------- -------------------------- ------ ------ */
-
-#define LED_STARTED 0 /* NuttX has been started OFF OFF */
-#define LED_HEAPALLOCATE 0 /* Heap has been allocated OFF OFF */
-#define LED_IRQSENABLED 0 /* Interrupts enabled OFF OFF */
-#define LED_STACKCREATED 1 /* Idle stack created ON OFF */
-#define LED_INIRQ 2 /* In an interrupt No change */
-#define LED_SIGNAL 2 /* In a signal handler No change */
-#define LED_ASSERTION 2 /* An assertion failed No change */
-#define LED_PANIC 3 /* The system has crashed N/C Blinking */
-#undef LED_IDLE /* MCU is is sleep mode Not used */
+ * SYMBOL Meaning LED state
+ * LED1 LED2
+ * ------------------ ------------------------ ------ ------
+ * LED_STARTED NuttX has been started OFF OFF
+ * LED_HEAPALLOCATE Heap has been allocated OFF OFF
+ * LED_IRQSENABLED Interrupts enabled OFF OFF
+ * LED_STACKCREATED Idle stack created ON OFF
+ * LED_INIRQ In an interrupt No change
+ * LED_SIGNAL In a signal handler No change
+ * LED_ASSERTION An assertion failed No change
+ * LED_PANIC The system has crashed N/C Blinking
+ * LED_IDLE MCU is is sleep mode Not used
+ */
/****************************************************************************
* Included Files
diff --git a/drivers/audio/wm8904.c b/drivers/audio/wm8904.c
index 4489ae0f221..23da3ce9a9d 100644
--- a/drivers/audio/wm8904.c
+++ b/drivers/audio/wm8904.c
@@ -3,7 +3,7 @@
*
* Audio device driver for Wolfson Microelectronics WM8904 Audio codec.
*
- * Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt
*
* References:
@@ -73,6 +73,14 @@
#include "wm8904.h"
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Maximum number of retries */
+
+#define MAX_RETRIES 3
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -251,7 +259,7 @@ uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
/* Try up to three times to read the register */
- for (retries = 1; retries <= 3; retries++)
+ for (retries = 1; retries <= MAX_RETRIES; retries++)
{
struct i2c_msg_s msg[2];
uint8_t data[2];
@@ -281,15 +289,20 @@ uint16_t wm8904_readreg(FAR struct wm8904_dev_s *priv, uint8_t regaddr)
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
- /* Perhaps the I2C bus is locked up? Try to shake the bus free */
+ /* Perhaps the I2C bus is locked up? Try to shake the bus free.
+ * Don't bother with the reset if this was the last attempt.
+ */
- audwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
-
- ret = I2C_RESET(priv->i2c);
- if (ret < 0)
+ if (retries < MAX_RETRIES)
{
- auderr("ERROR: I2C_RESET failed: %d\n", ret);
- break;
+ audwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
+
+ ret = I2C_RESET(priv->i2c);
+ if (ret < 0)
+ {
+ auderr("ERROR: I2C_RESET failed: %d\n", ret);
+ break;
+ }
}
#else
auderr("ERROR: I2C_TRANSFER failed: %d\n", ret);
@@ -338,7 +351,7 @@ static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
/* Try up to three times to read the register */
- for (retries = 1; retries <= 3; retries++)
+ for (retries = 1; retries <= MAX_RETRIES; retries++)
{
uint8_t data[3];
int ret;
@@ -357,15 +370,20 @@ static void wm8904_writereg(FAR struct wm8904_dev_s *priv, uint8_t regaddr,
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
- /* Perhaps the I2C bus is locked up? Try to shake the bus free */
+ /* Perhaps the I2C bus is locked up? Try to shake the bus free.
+ * Don't bother with the reset if this was the last attempt.
+ */
- audwarn("WARNING: i2c_write failed: %d ... Resetting\n", ret);
-
- ret = I2C_RESET(priv->i2c);
- if (ret < 0)
+ if (retries < MAX_RETRIES)
{
- auderr("ERROR: I2C_RESET failed: %d\n", ret);
- break;
+ audwarn("WARNING: i2c_write failed: %d ... Resetting\n", ret);
+
+ ret = I2C_RESET(priv->i2c);
+ if (ret < 0)
+ {
+ auderr("ERROR: I2C_RESET failed: %d\n", ret);
+ break;
+ }
}
#else
auderr("ERROR: I2C_TRANSFER failed: %d\n", ret);
diff --git a/drivers/input/mxt.c b/drivers/input/mxt.c
index f19c2bb0be5..e1152851719 100644
--- a/drivers/input/mxt.c
+++ b/drivers/input/mxt.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/input/mxt.c
*
- * Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt
*
* Redistribution and use in source and binary forms, with or without
@@ -88,6 +88,10 @@
#define INVALID_POSITION 0x1000
+/* Maximum number of retries */
+
+#define MAX_RETRIES 3
+
/* Get a 16-bit value in little endian order (not necessarily aligned). The
* source data is in little endian order. The host byte order does not
* matter in this case.
@@ -311,7 +315,7 @@ static int mxt_getreg(FAR struct mxt_dev_s *priv, uint16_t regaddr,
/* Try up to three times to read the register */
- for (retries = 1; retries <= 3; retries++)
+ for (retries = 1; retries <= MAX_RETRIES; retries++)
{
iinfo("retries=%d regaddr=%04x buflen=%d\n", retries, regaddr, buflen);
@@ -342,15 +346,20 @@ static int mxt_getreg(FAR struct mxt_dev_s *priv, uint16_t regaddr,
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
- /* Perhaps the I2C bus is locked up? Try to shake the bus free */
+ /* Perhaps the I2C bus is locked up? Try to shake the bus free.
+ * Don't bother with the reset if this was the last attempt.
+ */
- iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
-
- ret = I2C_RESET(priv->i2c);
- if (ret < 0)
+ if (retries < MAX_RETRIES)
{
- ierr("ERROR: I2C_RESET failed: %d\n", ret);
- break;
+ iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
+
+ ret = I2C_RESET(priv->i2c);
+ if (ret < 0)
+ {
+ ierr("ERROR: I2C_RESET failed: %d\n", ret);
+ break;
+ }
}
#else
ierr("ERROR: I2C_TRANSFER failed: %d\n", ret);
@@ -385,7 +394,7 @@ static int mxt_putreg(FAR struct mxt_dev_s *priv, uint16_t regaddr,
/* Try up to three times to read the register */
- for (retries = 1; retries <= 3; retries++)
+ for (retries = 1; retries <= MAX_RETRIES; retries++)
{
iinfo("retries=%d regaddr=%04x buflen=%d\n", retries, regaddr, buflen);
@@ -416,14 +425,19 @@ static int mxt_putreg(FAR struct mxt_dev_s *priv, uint16_t regaddr,
if (ret < 0)
{
#ifdef CONFIG_I2C_RESET
- /* Perhaps the I2C bus is locked up? Try to shake the bus free */
+ /* Perhaps the I2C bus is locked up? Try to shake the bus free.
+ * Don't bother with the reset if this was the last attempt.
+ */
- iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
-
- ret = I2C_RESET(priv->i2c);
- if (ret < 0)
+ if (retries < MAX_RETRIES)
{
- ierr("ERROR: I2C_RESET failed: %d\n", ret);
+ iwarn("WARNING: I2C_TRANSFER failed: %d ... Resetting\n", ret);
+
+ ret = I2C_RESET(priv->i2c);
+ if (ret < 0)
+ {
+ ierr("ERROR: I2C_RESET failed: %d\n", ret);
+ }
}
#else
ierr("ERROR: I2C_TRANSFER failed: %d\n", ret);
diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig
index b3abcaeabd8..565ab07301b 100644
--- a/drivers/lcd/Kconfig
+++ b/drivers/lcd/Kconfig
@@ -48,6 +48,7 @@ config LCD_NOGETRUN
config LCD_MAXCONTRAST
int "LCD maximum contrast"
+ default 31 if AQM_1248A
default 63 if NOKIA6100_S1D15G10 || LCD_SHARP_MEMLCD
default 127 if NOKIA6100_PCF8833
default 255 if LCD_P14201 || LCD_LCD1602
@@ -596,6 +597,9 @@ config NHD_C12864KGZ
config ERC_12864_3
bool "like ERC12864-3"
+config AQM_1248A
+ bool "like AQM1248A"
+
endchoice
config ST7565_NINTERFACES
@@ -613,6 +617,7 @@ config ST7565_XRES
config ST7565_YRES
int "ST7565 Y Resolution"
+ default 48 if AQM_1248A
default 64
---help---
Specifies the Y resolution of the LCD.
@@ -625,6 +630,7 @@ config ST7565_MIRROR_X
config ST7565_MIRROR_Y
bool "ST7565 apply mirror on Y"
+ default y if AQM_1248A
default n
---help---
Mirror Y on LCD.
diff --git a/drivers/lcd/st7565.c b/drivers/lcd/st7565.c
index 0e52b58a3ec..d25583a7452 100644
--- a/drivers/lcd/st7565.c
+++ b/drivers/lcd/st7565.c
@@ -1030,6 +1030,27 @@ FAR struct lcd_dev_s *st7565_initialize(FAR struct st7565_lcd_s *lcd,
(void)st7565_send_one_data(priv, ST7565_SETEVREG(0x24));
(void)st7565_send_one_data(priv, ST7565_SETSTARTLINE);
+#elif defined(CONFIG_AQM_1248A)
+
+ (void)st7565_send_one_data(priv, ST7565_DISPOFF);
+ (void)st7565_send_one_data(priv, ST7565_ADCNORMAL);
+ (void)st7565_send_one_data(priv, ST7565_SETCOMREVERSE);
+ (void)st7565_send_one_data(priv, ST7565_BIAS_1_7);
+
+ (void)st7565_send_one_data(priv, ST7565_POWERCTRL_B);
+ up_mdelay(2);
+ (void)st7565_send_one_data(priv, ST7565_POWERCTRL_BR);
+ up_mdelay(2);
+ (void)st7565_send_one_data(priv, ST7565_POWERCTRL_INT);
+
+ (void)st7565_send_one_data(priv, ST7565_REG_RES_4_5);
+ (void)st7565_send_one_data(priv, ST7565_SETEVMODE);
+ (void)st7565_send_one_data(priv, ST7565_SETEVREG(0x1c));
+ (void)st7565_send_one_data(priv, ST7565_DISPRAM);
+ (void)st7565_send_one_data(priv, ST7565_SETSTARTLINE);
+ (void)st7565_send_one_data(priv, ST7565_DISPNORMAL);
+ (void)st7565_send_one_data(priv, ST7565_DISPON);
+
#else
# error "No initialization sequence selected"
#endif
diff --git a/drivers/lcd/st7565.h b/drivers/lcd/st7565.h
index 0855f5e8ecc..cc9d17dd0f4 100644
--- a/drivers/lcd/st7565.h
+++ b/drivers/lcd/st7565.h
@@ -100,6 +100,8 @@
#define ST7565_POWERCTRL_VR 0x2b /* 0x2b: Only the voltage regulator circuit and the
* voltage follower circuit are used
*/
+#define ST7565_POWERCTRL_B 0x2c /* 0x2c: Booster=ON */
+#define ST7565_POWERCTRL_BR 0x2e /* 0x2e: Booster=ON V/R=ON */
#define ST7565_POWERCTRL_INT 0x2f /* 0x2f: Only the internal power supply is used */
/* Regulation Resistior ratio V0 = (1+Rb/Ra)*Vev */
diff --git a/net/udp/udp_psock_send.c b/net/udp/udp_psock_send.c
index e3e2eb0c881..c701fe064d7 100644
--- a/net/udp/udp_psock_send.c
+++ b/net/udp/udp_psock_send.c
@@ -78,7 +78,7 @@ ssize_t psock_udp_send(FAR struct socket *psock, FAR const void *buf,
socklen_t tolen;
DEBUGASSERT(psock != NULL && psock->s_crefs > 0);
- DEBUGASSERT(psock->s_type != SOCK_DGRAM);
+ DEBUGASSERT(psock->s_type == SOCK_DGRAM);
conn = (FAR struct udp_conn_s *)psock->s_conn;
DEBUGASSERT(conn);
diff --git a/sched/semaphore/sem_holder.c b/sched/semaphore/sem_holder.c
index bc5c186e6bf..a46cf3a8be4 100644
--- a/sched/semaphore/sem_holder.c
+++ b/sched/semaphore/sem_holder.c
@@ -156,7 +156,7 @@ static FAR struct semholder_s *sem_findholder(sem_t *sem,
int i;
pholder = NULL;
- /* We have two hard-allocated holder structuse in sem_t */
+ /* We have two hard-allocated holder structures in sem_t */
for (i = 0; i < 2; i++)
{
@@ -338,7 +338,7 @@ static int sem_boostholderprio(FAR struct semholder_s *pholder,
if (!sched_verifytcb(htcb))
{
serr("ERROR: TCB 0x%08x is a stale handle, counts lost\n", htcb);
- DEBUGASSERT(!sched_verifytcb(htcb));
+ DEBUGPANIC();
sem_freeholder(sem, pholder);
}
@@ -498,7 +498,7 @@ static int sem_restoreholderprio(FAR struct tcb_s *htcb,
if (!sched_verifytcb(htcb))
{
serr("ERROR: TCB 0x%08x is a stale handle, counts lost\n", htcb);
- DEBUGASSERT(!sched_verifytcb(htcb));
+ DEBUGPANIC();
pholder = sem_findholder(sem, htcb);
if (pholder != NULL)
{
@@ -787,7 +787,6 @@ static inline void sem_restorebaseprio_task(FAR struct tcb_s *stcb,
FAR sem_t *sem)
{
FAR struct tcb_s *rtcb = this_task();
- FAR struct semholder_s *pholder;
/* Perform the following actions only if a new thread was given a count.
* The thread that received the count should be the highest priority
@@ -831,7 +830,6 @@ static inline void sem_restorebaseprio_task(FAR struct tcb_s *stcb,
*/
sem_findandfreeholder(sem, rtcb);
-
}
/****************************************************************************
@@ -905,14 +903,15 @@ void sem_destroyholder(FAR sem_t *sem)
if (sem->hhead != NULL)
{
serr("ERROR: Semaphore destroyed with holders\n");
- DEBUGASSERT(sem->hhead != NULL);
+ DEBUGPANIC();
(void)sem_foreachholder(sem, sem_recoverholders, NULL);
}
+
#else
- if (sem->holder[0].htcb != NULL || sem->holder[0].htcb != NULL)
+ if (sem->holder[0].htcb != NULL || sem->holder[1].htcb != NULL)
{
- DEBUGASSERT(sem->holder[0].htcb != NULL || sem->holder[0].htcb != NULL);
serr("ERROR: Semaphore destroyed with holder\n");
+ DEBUGPANIC();
}
sem->holder[0].htcb = NULL;