Exemplo n.º 1
0
// Doc ID 13902 Rev 11 p 714/1072
// Transfer Sequence Diagram for Master Receiver for N=1
static inline enum STMI2CSubTransactionStatus stmi2c_read1(uint32_t i2c, struct i2c_periph *periph, struct i2c_transaction *trans)
{
  uint16_t SR1 = I2C_SR1(i2c);

  // Start Condition Was Just Generated
  if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) )
  {
    I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN;
    I2C_DR(i2c) = trans->slave_addr | 0x01;

    // Document the current Status
    periph->status = I2CAddrRdSent;
  }
  // Address Was Sent
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) )
  {
    // First Clear the ACK bit: after the next byte we do not want new bytes
    I2C_CR1(i2c) &= ~ I2C_CR1_POS;
    I2C_CR1(i2c) &= ~ I2C_CR1_ACK;

    // --- next to steps MUST be executed together to avoid missing the stop
    __I2C_REG_CRITICAL_ZONE_START;

    // Only after setting ACK, read SR2 to clear the ADDR (next byte will start arriving)
    uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c);

    // Schedule a Stop
    PPRZ_I2C_SEND_STOP(i2c);

    __I2C_REG_CRITICAL_ZONE_STOP;
    // --- end of critical zone -----------

    // Enable the RXNE: it will trigger as soon as the 1 byte is received to get the result
    I2C_CR2(i2c) |= I2C_CR2_ITBUFEN;

    // Document the current Status
    periph->status = I2CReadingLastByte;
  }
  // As soon as there is 1 byte ready to read, we have our byte
  else if (BIT_X_IS_SET_IN_REG(I2C_SR1_RxNE, SR1) )
  {
    I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN;
    trans->buf[0] = I2C_DR(i2c);

    // We got all the results (stop condition might still be in progress but this is the last interrupt)
    trans->status = I2CTransSuccess;

    // Document the current Status:
    // -the stop was actually already requested in the previous step
    periph->status = I2CStopRequested;

    return STMI2C_SubTra_Ready_StopRequested;
  }
  else // Event Logic Error
  {
    return STMI2C_SubTra_Error;
  }

  return STMI2C_SubTra_Busy;
}
Exemplo n.º 2
0
void i2c_transmit(const i2c_channel *cp, const uint8_t *data, size_t count)
{
    uint32_t base = cp->i_base_address;

    if (cp->i_is_master) {

        // Send start condition.
        I2C_CR1(base) |= I2C_CR1_START;
        uint32_t t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_SB)) {
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on SB\n");
                return;
            }
        }

        // Send slave address.
        I2C_DR(base) = cp->i_address & ~0x01;
        t0 = system_millis;
        while (!(I2C_SR1(base) & I2C_SR1_ADDR)) {
            if (I2C_SR1(base) & I2C_SR1_AF) {
                I2C_CR1(base) |= I2C_CR1_STOP;
                I2C_SR1(base) = ~I2C_SR1_AF;
                fprintf(stderr,
                        "i2c @ %ld: ack failure on addr\n",
                        system_millis / 1000);
                return;
            }
            if (system_millis >= t0 + TIMEOUT_MSEC) {
                fprintf(stderr, "i2c: timeout on ADDR\n");
                return;
            }
        }

        // Clear ADDR flag by reading SR1 and SR2 registers.
        uint16_t unused;
        unused = I2C_SR1(base);
        unused = I2C_SR2(base);
        unused = unused;

        // Write each data byte; wait for BTF.
        for (size_t i = 0; i < count; i++) {
            I2C_DR(base) = data[i];
            t0 = system_millis;
            while (!(I2C_SR1(base) & I2C_SR1_BTF)) {
                if (system_millis >= t0 + TIMEOUT_MSEC) {
                    fprintf(stderr, "i2c: timeout on BTF\n");
                    return;
                }
            }
        }
        I2C_CR1(base) |= I2C_CR1_STOP;
        fprintf(stderr, "i2c @ %lu: transmit complete\n", system_millis / 1000);
    } else {
        assert(false && "slave transmission not implemented");
    }
}
Exemplo n.º 3
0
void i2c_setup(void)
{
	rcc_periph_clock_enable(RCC_I2C1);
	rcc_periph_clock_enable(RCC_GPIOB);

	//clock from 48 MHz
	RCC_CFGR3 |= RCC_CFGR3_I2C1SW;

	//i2c_reset(I2C_BUS);
	RCC_APB1RSTR |= RCC_APB1RSTR_I2C1RST;
	RCC_APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;

	gpio_mode_setup(I2C_PIN_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C_PINS);
	gpio_set_af(I2C_PIN_PORT, I2C_PIN_AF, I2C_PINS);

	//i2c_peripheral_disable(I2C_BUS);
	I2C_CR1(I2C_BUS) &= ~I2C_CR1_PE;

	//configure ANFOFF DNF[3:0] in CR1
	//i2c_enable_analog_filter(I2C_BUS);
	I2C_CR1(I2C_BUS) &= ~I2C_CR1_ANFOFF;

	//i2c_set_digital_filter(I2C_BUS, I2C_CR1_DNF_DISABLED); //default is good

	//Configure PRESC[3:0] SDADEL[3:0] SCLDEL[3:0] SCLH[7:0] SCLL[7:0]
	// in TIMINGR
	//i2c_100khz_i2cclk8mhz(I2C_BUS); //let's assume this is good :)

	//I don't think the timing matters when we're slave
	I2C_TIMINGR(I2C_BUS) = 0;

	//configure No-Stretch CR1 (only relevant in slave mode)
	//i2c_enable_stretching(I2C_BUS);

	//addressing mode
	//i2c_set_7bit_addr_mode(I2C_BUS); //default is good

	//slave address
	I2C_OAR1(I2C_BUS) = I2C_OAR1_OA1EN + (I2C_SLAVE_ADDRESS << 1);

	//enable all interrupts
	I2C_CR1(I2C_BUS) |= 0xfe;

	//i2c_peripheral_enable(I2C_BUS);
	I2C_CR1(I2C_BUS) |= I2C_CR1_PE;

	nvic_enable_irq(NVIC_I2C1_IRQ);
}
Exemplo n.º 4
0
static inline void PPRZ_I2C_SEND_START(struct i2c_periph *periph)
{
  uint32_t i2c = (uint32_t) periph->reg_addr;

  // Reset the buffer pointer to the first byte
  periph->idx_buf = 0;

#ifdef I2C_DEBUG_LED
  LED_SHOW_ACTIVE_BITS(regs);

  LED2_ON();
  LED1_ON();
  LED1_OFF();
  LED1_ON();
  LED1_OFF();
  LED1_ON();
  LED1_OFF();
  LED2_OFF();
#endif

  // Enable Error IRQ, Event IRQ but disable Buffer IRQ
  I2C_CR2(i2c) |= I2C_CR2_ITERREN;
  I2C_CR2(i2c) |= I2C_CR2_ITEVTEN;
  I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN;

  // Issue a new start
  I2C_CR1(i2c) =  (I2C_CR1_START | I2C_CR1_PE);
  periph->status = I2CStartRequested;

}
Exemplo n.º 5
0
/* In the event of a bus error (start or stop detected during data transfer),
 * the peripheral continues as normal, but the slave has likely cancelled
 * communication, leaving the peripheral expecting communication that won't
 * occur.  The only solution is to reset the peripheral. */
static int i2c_reset(struct i2c_dev *i2c) {
    if (!i2c) {
        return -1;
    }

    i2c->ready = 0;

    /* Software reset */
    *I2C_CR1(i2c->port) |= I2C_CR1_SWRST;

    /* Wait until peripheral is disabled */
    while (*I2C_CR1(i2c->port) & I2C_CR1_PE);

    /* Re-enable */
    *I2C_CR1(i2c->port) &= ~(I2C_CR1_SWRST);

    /* Re-initialize */
    i2c->init();

    return 0;
}
Exemplo n.º 6
0
static inline void PPRZ_I2C_SEND_STOP(uint32_t i2c)
{
  // Man: p722:  Stop generation after the current byte transfer or after the current Start condition is sent.
  I2C_CR1(i2c) |= I2C_CR1_STOP;

#ifdef I2C_DEBUG_LED
  LED2_ON();
  LED1_ON();
  LED1_OFF();
  LED2_OFF();
#endif
}
Exemplo n.º 7
0
void reset_i2c_pins(void)
{
	// reseting I2C pins [errata_sheet CD00197763.pdf section 2.14.7]
	i2c_peripheral_disable(I2C_PORT);
	gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, I2C_SCL_PIN | I2C_SDA_PIN);
	gpio_set(GPIOB, I2C_SCL_PIN | I2C_SDA_PIN);
	while (!gpio_get(GPIOB, I2C_SCL_PIN | I2C_SDA_PIN));
	gpio_clear(GPIOB, I2C_SCL_PIN | I2C_SDA_PIN);
	while (gpio_get(GPIOB, I2C_SCL_PIN | I2C_SDA_PIN));
	gpio_set(GPIOB, I2C_SDA_PIN);
	while (!gpio_get(GPIOB, I2C_SDA_PIN));
	gpio_clear(GPIOB, I2C_SDA_PIN);
	while (gpio_get(GPIOB, I2C_SDA_PIN));
	gpio_set(GPIOB, I2C_SCL_PIN);
	while (!gpio_get(GPIOB, I2C_SCL_PIN));
	gpio_clear(GPIOB, I2C_SCL_PIN);
	while (gpio_get(GPIOB, I2C_SCL_PIN));
	gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C_SCL_PIN | I2C_SDA_PIN);
	I2C_CR1(I2C_PORT) |= I2C_CR1_SWRST;
	I2C_CR1(I2C_PORT) &= ~I2C_CR1_SWRST;
	i2c_peripheral_enable(I2C_PORT);
}
int tda18219_read_reg(uint8_t reg, uint8_t* value)
{
	uint32_t __attribute__((unused)) reg32;

	/* Send START condition. */
	i2c_send_start(I2C1);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(I2C1) & I2C_SR1_SB)
		& (I2C_SR2(I2C1) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	/* Yes, WRITE is correct - for selecting register in STTS75. */
	i2c_send_7bit_address(I2C1, TDA18219_I2C_ADDR, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(I2C1) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(I2C1);

	i2c_send_data(I2C1, reg);
	while (!(I2C_SR1(I2C1) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/* Send re-START condition. */
	i2c_send_start(I2C1);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(I2C1) & I2C_SR1_SB)
		& (I2C_SR2(I2C1) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	i2c_send_7bit_address(I2C1, TDA18219_I2C_ADDR, I2C_READ); 

	I2C_CR1(I2C1) &= ~I2C_CR1_ACK;

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(I2C1) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(I2C1);

	i2c_send_stop(I2C1);

	while (!(I2C_SR1(I2C1) & I2C_SR1_RxNE));

	*value = I2C_DR(I2C1);

	return 0;
}
Exemplo n.º 9
0
static void init_i2c2(void) {
    *RCC_APB1ENR |= RCC_APB1ENR_I2C2EN;     /* Enable I2C2 Clock */
    *RCC_AHB1ENR |= RCC_AHB1ENR_GPIOBEN;    /* Enable GPIOB Clock */

    /* Set PB8 and PB9 to alternative function I2C
     * See stm32f4_ref.pdf pg 141 and stm32f407.pdf pg 51 */

    /* I2C2_SCL */
    gpio_moder(GPIOB, I2C2_SCL, GPIO_MODER_ALT);
    gpio_afr(GPIOB, I2C2_SCL, GPIO_AF_I2C);
    gpio_otyper(GPIOB, I2C2_SCL, GPIO_OTYPER_OD);
    gpio_pupdr(GPIOB, I2C2_SCL, GPIO_PUPDR_NONE);
    gpio_ospeedr(GPIOB, I2C2_SCL, GPIO_OSPEEDR_50M);

    /* I2C2_SDA */
    gpio_moder(GPIOB, I2C2_SDA, GPIO_MODER_ALT);
    gpio_afr(GPIOB, I2C2_SDA, GPIO_AF_I2C);
    gpio_otyper(GPIOB, I2C2_SDA, GPIO_OTYPER_OD);
    gpio_pupdr(GPIOB, I2C2_SDA, GPIO_PUPDR_NONE);
    gpio_ospeedr(GPIOB, I2C2_SDA, GPIO_OSPEEDR_50M);

    /* Configure peripheral */
    *I2C_CR2(2) |= I2C_CR2_FREQ(42);

    /* Set I2C to 300kHz */
    *I2C_CCR(2) |= I2C_CCR_CCR(140);
    *I2C_TRISE(2) = 43;

    /* Enable */
    *I2C_CR1(2) |= I2C_CR1_PE;

    /* Pre-initialized */
    //init_semaphore(&i2c2_semaphore);

    i2c2.ready = 1;
}
Exemplo n.º 10
0
void init_i2c(const i2c_config *ip)
{
    // Enable periph clock.
    // Configure GPIO.
    // Reset I²C.

    uint32_t base = ip->i_base_address;

    enum rcc_periph_clken clken;
    switch (base) {
    case I2C1:
        clken = RCC_I2C1;
        break;
    case I2C2:
        clken = RCC_I2C2;
        break;
    default:
        assert(false && "unknown I2C base address");
    }
    rcc_periph_clock_enable(clken);

    gpio_init_pins(ip->i_pins, (&ip->i_pins)[1] - ip->i_pins);

    uint32_t i2c_freq_mhz = rcc_apb1_frequency / 1000000;
    uint32_t ccr = rcc_apb1_frequency / I2C_BAUD / 2 + 1;
    if (ccr < 4)
        ccr = 4;

    i2c_peripheral_disable(base);
    i2c_set_clock_frequency(base, i2c_freq_mhz);
    i2c_set_trise(base, i2c_freq_mhz + 1);
    i2c_set_ccr(base, ccr);
    I2C_CR1(base) = 0;
    I2C_OAR1(base) = ip->i_own_address;
    i2c_peripheral_enable(base);
}
Exemplo n.º 11
0
/** @brief I2C NACK Next Byte

Causes the I2C controller to NACK the reception of the current byte

@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_current(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_POS;
}
Exemplo n.º 12
0
void i2c_enable_analog_filter(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_ANFOFF;
}
Exemplo n.º 13
0
/** @brief I2C NACK Next Byte

Causes the I2C controller to NACK the reception of the next byte
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_nack_next(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_POS;
}
Exemplo n.º 14
0
void i2c_peripheral_disable(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_PE;
}
Exemplo n.º 15
0
/** @brief I2C Disable transmission DMA
 *
 * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
 */
void i2c_disable_txdma(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_TXDMAEN;
}
Exemplo n.º 16
0
/** @brief I2C Disable Interrupt
 *
 * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
 * @param[in] interrupt Unsigned int32. Interrupt to disable.
 */
void i2c_disable_interrupt(uint32_t i2c, uint32_t interrupt)
{
	I2C_CR1(i2c) &= ~interrupt;
}
Exemplo n.º 17
0
void i2c_disable_stretching(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_NOSTRETCH;
}
Exemplo n.º 18
0
void i2c_set_digital_filter(uint32_t i2c, uint8_t dnf_setting)
{
	I2C_CR1(i2c) = (I2C_CR1(i2c) & ~I2C_CR1_DNF_MASK) | dnf_setting;
}
Exemplo n.º 19
0
void i2c_disable_analog_filter(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_ANFOFF;
}
Exemplo n.º 20
0
void i2c_send_start(u32 i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_START;
}
Exemplo n.º 21
0
void i2c_enable_stretching(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_NOSTRETCH;
}
Exemplo n.º 22
0
void i2c_send_start(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_START;
}
Exemplo n.º 23
0
/** @brief I2C Enable Interrupt
 *
 * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
 * @param[in] interrupt Unsigned int32. Interrupt to enable.
 */
void i2c_enable_interrupt(uint32_t i2c, uint32_t interrupt)
{
	I2C_CR1(i2c) |= interrupt;
}
Exemplo n.º 24
0
void i2c_send_stop(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_STOP;
}
Exemplo n.º 25
0
/** @brief I2C Enable transmission DMA
 *
 * @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
 */
void i2c_enable_txdma(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_TXDMAEN;
}
Exemplo n.º 26
0
/** @brief I2C Clear Stop Flag.

Clear the "Send Stop" flag in the I2C config register

@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_clear_stop(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_STOP;
}
Exemplo n.º 27
0
void i2c_peripheral_enable(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_PE;
}
Exemplo n.º 28
0
/** @brief I2C Enable ACK

Enables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_enable_ack(uint32_t i2c)
{
	I2C_CR1(i2c) |= I2C_CR1_ACK;
}
uint16_t stts75_read_temperature(uint32_t i2c, uint8_t sensor)
{
	uint32_t reg32 __attribute__((unused));
	uint16_t temperature;

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	/* Yes, WRITE is correct - for selecting register in STTS75. */
	i2c_send_7bit_address(i2c, sensor, I2C_WRITE);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	i2c_send_data(i2c, 0x0); /* temperature register */
	while (!(I2C_SR1(i2c) & (I2C_SR1_BTF | I2C_SR1_TxE)));

	/*
	 * Now we transferred that we want to ACCESS the temperature register.
	 * Now we send another START condition (repeated START) and then
	 * transfer the destination but with flag READ.
	 */

	/* Send START condition. */
	i2c_send_start(i2c);

	/* Waiting for START is send and switched to master mode. */
	while (!((I2C_SR1(i2c) & I2C_SR1_SB)
		& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));

	/* Say to what address we want to talk to. */
	i2c_send_7bit_address(i2c, sensor, I2C_READ);

	/* 2-byte receive is a special case. See datasheet POS bit. */
	I2C_CR1(i2c) |= (I2C_CR1_POS | I2C_CR1_ACK);

	/* Waiting for address is transferred. */
	while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));

	/* Cleaning ADDR condition sequence. */
	reg32 = I2C_SR2(i2c);

	/* Cleaning I2C_SR1_ACK. */
	I2C_CR1(i2c) &= ~I2C_CR1_ACK;

	/* Now the slave should begin to send us the first byte. Await BTF. */
	while (!(I2C_SR1(i2c) & I2C_SR1_BTF));
	temperature = (uint16_t)(I2C_DR(i2c) << 8); /* MSB */

	/*
	 * Yes they mean it: we have to generate the STOP condition before
	 * saving the 1st byte.
	 */
	I2C_CR1(i2c) |= I2C_CR1_STOP;

	temperature |= I2C_DR(i2c); /* LSB */

	/* Original state. */
	I2C_CR1(i2c) &= ~I2C_CR1_POS;

	return temperature;
}
Exemplo n.º 30
0
/** @brief I2C Disable ACK

Disables acking of own 7/10 bit address
@param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base.
*/
void i2c_disable_ack(uint32_t i2c)
{
	I2C_CR1(i2c) &= ~I2C_CR1_ACK;
}