aboutsummaryrefslogtreecommitdiff
path: root/driver_fw/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver_fw/i2c.c')
-rw-r--r--driver_fw/i2c.c236
1 files changed, 0 insertions, 236 deletions
diff --git a/driver_fw/i2c.c b/driver_fw/i2c.c
deleted file mode 100644
index bab1a16..0000000
--- a/driver_fw/i2c.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inter-integrated circuit (I2C) management
-
-
-#include "i2c.h"
-
-
-// I2C timeout, about 2ms
-#define I2C_TIMEOUT 200U
-
-// Maximum NBYTES value
-#define I2C_NBYTES_MAX 255U
-
-
-// Count rough delay for timeouts
-static uint32_t i2c_calc_delay(uint32_t delay) {
- uint32_t cnt;
-
- if (SystemCoreClock > 1000000U) {
- cnt = (delay * ((SystemCoreClock / 1000000U) + 1U));
- } else {
- cnt = (((delay / 100U) + 1U) * ((SystemCoreClock / 10000U) + 1U));
- }
-
- return cnt;
-}
-
-// Check if target device is ready for communication
-// input:
-// I2Cx - pointer to the I2C peripheral (I2C1, etc.)
-// devAddr - target device address
-// trials - number of trials (must not be zero)
-// return:
-// I2C_ERROR if there was a timeout during I2C operations, I2C_SUCCESS otherwise
-I2CSTATUS i2c_is_device_ready(I2C_TypeDef* I2Cx, uint8_t devAddr, uint32_t trials) {
- volatile uint32_t wait;
- uint32_t delay_val = i2c_calc_delay(I2C_TIMEOUT);
- uint32_t reg;
-
- while (trials--) {
- // Clear all flags
- I2Cx->ICR = I2C_ICR_ALL;
-
- // Generate START
- i2c_genstart(I2Cx, devAddr);
-
- // Wait for STOP, NACK or BERR
- wait = delay_val;
- while (!((reg = I2Cx->ISR) & (I2C_ISR_STOPF | I2C_ISR_NACKF | I2C_ISR_BERR)) && --wait);
- if (wait == 0) { return I2C_ERROR; }
-
- // Wait while STOP flag is reset
- wait = delay_val;
- while (!(I2Cx->ISR & I2C_ISR_STOPF) && --wait);
- if (wait == 0) { return I2C_ERROR; }
-
- // Clear the NACK, STOP and BERR flags
- I2Cx->ICR = I2C_ICR_STOPCF | I2C_ICR_NACKCF | I2C_ICR_BERRCF;
-
- // Check for BERR flag
- if (reg & I2C_ISR_BERR) {
- // Misplaced START/STOP? Perform a software reset of I2C
- i2c_disable(I2Cx);
- i2c_enable(I2Cx);
- } else {
- // Device responded if NACK flag is not set
- if (!(reg & I2C_ISR_NACKF)) { return I2C_SUCCESS; }
- }
- }
-
- return I2C_ERROR;
-}
-
-// Transmit an amount of data in master mode
-// input:
-// I2Cx - pointer to the I2C peripheral (I2C1, etc.)
-// pBbuf - pointer to the data buffer
-// nbytes - number of bytes to transmit
-// devAddr - address of target device
-// flags - options for transmission, combination of I2C_TX_xx values:
-// I2C_TX_NOSTART - don't generate START condition
-// I2C_TX_NOSTOP - don't generate STOP condition
-// I2C_TX_CONT - this flag indicates that transmission will be continued
-// e.g. by calling this function again with NOSTART flag
-// zero value - generate both START and STOP conditions
-// return:
-// I2C_ERROR if there was a timeout during I2C operations, I2C_SUCCESS otherwise
-I2CSTATUS i2c_transmit(I2C_TypeDef* I2Cx, const uint8_t *pBuf, uint32_t nbytes, uint8_t devAddr, uint32_t flags) {
- uint32_t reg;
- uint32_t tx_count;
- uint32_t delay_val = i2c_calc_delay(I2C_TIMEOUT);
- volatile uint32_t wait;
-
- // Clear all flags
- I2Cx->ICR = I2C_ICR_ALL;
-
- // Everything regarding to the transmission is in the CR2 register
- reg = I2Cx->CR2;
- reg &= ~I2C_CR2_ALL;
-
- // Slave device address
- reg |= (devAddr & I2C_CR2_SADD);
-
- // Whether it need to generate START condition
- if (!(flags & I2C_TX_NOSTART)) { reg |= I2C_CR2_START; }
-
- // Whether it need to generate STOP condition
- if ((flags & I2C_TX_CONT) || (nbytes > I2C_NBYTES_MAX)) {
- reg |= I2C_CR2_RELOAD;
- } else {
- if (!(flags & I2C_TX_NOSTOP)) { reg |= I2C_CR2_AUTOEND; }
- }
-
- // Transfer length
- tx_count = (nbytes > I2C_NBYTES_MAX) ? I2C_NBYTES_MAX : nbytes;
- nbytes -= tx_count;
- reg |= tx_count << I2C_CR2_NBYTES_Pos;
-
- // Write a composed value to the I2C register
- I2Cx->CR2 = reg;
-
- // Transmit data
- while (tx_count) {
- // Wait until either TXIS or NACK flag is set
- wait = delay_val;
- while (!((reg = I2Cx->ISR) & (I2C_ISR_TXIS | I2C_ISR_NACKF)) && --wait);
- if ((reg & I2C_ISR_NACKF) || (wait == 0)) { return I2C_ERROR; }
-
- // Transmit byte
- I2Cx->TXDR = *pBuf++;
- tx_count--;
-
- if ((tx_count == 0) && (nbytes != 0)) {
- // Wait until TCR flag is set (Transfer Complete Reload)
- wait = delay_val;
- while (!(I2Cx->ISR & I2C_ISR_TCR) && --wait);
- if (wait == 0) { return I2C_ERROR; }
-
- // Configure next (or last) portion transfer
- reg = I2Cx->CR2;
- reg &= ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND);
- if ((flags & I2C_TX_CONT) || (nbytes > I2C_NBYTES_MAX)) {
- reg |= I2C_CR2_RELOAD;
- } else {
- if (!(flags & I2C_TX_NOSTOP)) { reg |= I2C_CR2_AUTOEND; }
- }
- tx_count = (nbytes > I2C_NBYTES_MAX) ? I2C_NBYTES_MAX : nbytes;
- nbytes -= tx_count;
- reg |= tx_count << I2C_CR2_NBYTES_Pos;
- I2Cx->CR2 = reg;
- }
- }
-
- // End of transmission
- wait = delay_val;
- while (!(I2Cx->ISR & (I2C_ISR_TC | I2C_ISR_TCR | I2C_ISR_STOPF)) && --wait);
-
- return (wait) ? I2C_SUCCESS : I2C_ERROR;
-}
-
-// Receive an amount of data in master mode
-// input:
-// I2Cx - pointer to the I2C peripheral (I2C1, etc.)
-// buf - pointer to the data buffer
-// nbytes - number of bytes to receive
-// devAddr - address of target device
-// return:
-// I2C_ERROR if there was a timeout during I2C operations, I2C_SUCCESS otherwise
-I2CSTATUS i2c_receive(I2C_TypeDef* I2Cx, uint8_t *pBuf, uint32_t nbytes, uint8_t devAddr) {
- uint32_t reg;
- uint32_t rx_count;
- uint32_t delay_val = i2c_calc_delay(I2C_TIMEOUT);
- volatile uint32_t wait;
-
- // Clear all flags
- I2Cx->ICR = I2C_ICR_ALL;
-
- // Everything regarding to the transmission is in the CR2 register
- reg = I2Cx->CR2;
- reg &= ~I2C_CR2_ALL;
-
- // Configure slave device address, enable START condition and set direction to READ
- reg |= (devAddr & I2C_CR2_SADD) | I2C_CR2_START | I2C_CR2_RD_WRN;
-
- // Transfer length
- if (nbytes > I2C_NBYTES_MAX) {
- rx_count = I2C_NBYTES_MAX;
- reg |= I2C_CR2_RELOAD;
- } else {
- rx_count = nbytes;
- reg |= I2C_CR2_AUTOEND;
- }
- reg |= rx_count << I2C_CR2_NBYTES_Pos;
- nbytes -= rx_count;
-
- // Write a composed value to the I2C register
- I2Cx->CR2 = reg;
-
- // Receive data
- while (rx_count) {
- // Wait until either RXNE or NACK flag is set
- wait = delay_val;
- while (!((reg = I2Cx->ISR) & (I2C_ISR_RXNE | I2C_ISR_NACKF)) && --wait);
- if ((reg & I2C_ISR_NACKF) || (wait == 0)) { return I2C_ERROR; }
-
- // Read received data
- *pBuf++ = I2Cx->RXDR;
- rx_count--;
-
- if ((rx_count == 0) && (nbytes != 0)) {
- // Wait until TCR flag is set (Transfer Complete Reload)
- wait = delay_val;
- while (!(I2Cx->ISR & I2C_ISR_TCR) && --wait);
- if (wait == 0) { return I2C_ERROR; }
-
- // Configure next (or last) portion transfer
- reg = I2Cx->CR2;
- reg &= ~(I2C_CR2_NBYTES | I2C_CR2_AUTOEND | I2C_CR2_RELOAD);
- if (nbytes > I2C_NBYTES_MAX) {
- rx_count = I2C_NBYTES_MAX;
- reg |= I2C_CR2_RELOAD;
- } else {
- rx_count = nbytes;
- reg |= I2C_CR2_AUTOEND;
- }
- reg |= rx_count << I2C_CR2_NBYTES_Pos;
- nbytes -= rx_count;
- I2Cx->CR2 = reg;
- }
- }
-
- // Wait for the STOP flag
- wait = delay_val;
- while (!(I2Cx->ISR & I2C_ISR_STOPF) && --wait);
-
- return (wait) ? I2C_SUCCESS : I2C_ERROR;
-}