aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-04-17 13:12:09 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-04-17 13:12:09 +0000
commit7d92e6daae943988c9ecaeb84693f31ef59aa344 (patch)
tree71bd5f6e75fa95342a224c040528c05520a2d3ad /os/hal
parent7ff77cde76baacf00fbfff68da625ad72f7c50f2 (diff)
downloadChibiOS-7d92e6daae943988c9ecaeb84693f31ef59aa344.tar.gz
ChibiOS-7d92e6daae943988c9ecaeb84693f31ef59aa344.tar.bz2
ChibiOS-7d92e6daae943988c9ecaeb84693f31ef59aa344.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7902 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal')
-rw-r--r--os/hal/ports/STM32/LLD/I2Cv2/i2c_lld.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/os/hal/ports/STM32/LLD/I2Cv2/i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv2/i2c_lld.c
index 2ea78ca89..37a4b97b7 100644
--- a/os/hal/ports/STM32/LLD/I2Cv2/i2c_lld.c
+++ b/os/hal/ports/STM32/LLD/I2Cv2/i2c_lld.c
@@ -89,6 +89,41 @@ I2CDriver I2CD2;
/*===========================================================================*/
/**
+ * @brief I2C transfer setup.
+ * @note The RW bit is not handled internally.
+ *
+ * @param[in] i2cp pointer to the @p I2CDriver object
+ * @param[in] addr slave device address
+ * @param[in] n size of the transfer
+ *
+ * @notapi
+ */
+static void i2c_lld_setup_transfer(I2CDriver *i2cp, i2caddr_t addr, size_t n) {
+ I2C_TypeDef *dp = i2cp->i2c;
+ uint32_t cr2;
+
+ /* Adjust slave address (master mode) for 7-bit address mode */
+ if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U)
+ cr2 = ((uint32_t)addr & 0x7FU) << 1U;
+ else
+ cr2 = (uint32_t)addr;
+
+ /* The unit can transfer 255 bytes maximum in a single operation.*/
+ if (n > 255U) {
+ cr2 |= I2C_CR2_RELOAD;
+ n = 255U;
+ }
+
+ /* Configures the CR2 registers with both the calculated and static
+ settings.*/
+ dp->CR2 = (i2cp->config->cr2 & ~(I2C_CR2_NBYTES | I2C_CR2_SADD)) |
+ (n << 16U) | cr2;
+
+ /* Transfer complete interrupt enabled.*/
+ dp->CR1 |= I2C_CR1_TCIE;
+}
+
+/**
* @brief Aborts an I2C transaction.
*
* @param[in] i2cp pointer to the @p I2CDriver object
@@ -570,7 +605,6 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
- uint32_t addr_cr2 = addr & I2C_CR2_SADD;
systime_t start, end;
/* Resetting error flags for this transfer.*/
@@ -607,13 +641,8 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
osalSysUnlock();
}
- /* Adjust slave address (master mode) for 7-bit address mode */
- if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0)
- addr_cr2 = (addr_cr2 & 0x7f) << 1;
-
- /* Set slave address field (master mode) */
- dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES);
- dp->CR2 |= (rxbytes << 16) | addr_cr2;
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_transfer(i2cp, addr, rxbytes);
/* Enable RX DMA */
dmaStreamEnable(i2cp->dmarx);
@@ -656,7 +685,6 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
I2C_TypeDef *dp = i2cp->i2c;
- uint32_t addr_cr2 = addr & I2C_CR2_SADD;
systime_t start, end;
/* Resetting error flags for this transfer.*/
@@ -670,7 +698,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
dmaStreamSetMemory0(i2cp->dmatx, txbuf);
dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
- /* RX DMA setup.*/
+ /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/
dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
@@ -698,22 +726,14 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
osalSysUnlock();
}
- /* Adjust slave address (master mode) for 7-bit address mode */
- if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0)
- addr_cr2 = (addr_cr2 & 0x7f) << 1;
-
- /* Set slave address field (master mode) */
- dp->CR2 &= ~(I2C_CR2_SADD | I2C_CR2_NBYTES);
- dp->CR2 |= (txbytes << 16) | addr_cr2;
+ /* Setting up the peripheral.*/
+ i2c_lld_setup_transfer(i2cp, addr, txbytes);
/* Enable TX DMA */
dmaStreamEnable(i2cp->dmatx);
- /* Transmission complete interrupt enabled.*/
- dp->CR1 |= I2C_CR1_TCIE;
-
- /* Starts the operation as the very last thing.*/
- dp->CR2 &= ~I2C_CR2_RD_WRN;
+ /* Starts the operation as the very last thing, I2C_CR2_RD_WRN is already
+ zero.*/
dp->CR2 |= I2C_CR2_START;
/* Waits for the operation completion or a timeout.*/