void i2c_set_clock_frequency(u32 i2c, u8 freq) { u16 reg16; reg16 = I2C_CR2(i2c) & 0xffc0; /* Clear bits [5:0]. */ reg16 |= freq; I2C_CR2(i2c) = reg16; }
void i2c3_ev_isr(void) { uint32_t i2c = (uint32_t) i2c3.reg_addr; I2C_CR2(i2c) &= ~I2C_CR2_ITERREN; i2c_irq(&i2c3); i2c3_watchdog_counter = 0; I2C_CR2(i2c) |= I2C_CR2_ITERREN; }
void i2c1_er_isr(void) { uint32_t i2c = (uint32_t) i2c1.reg_addr; I2C_CR2(i2c) &= ~I2C_CR2_ITEVTEN; i2c_irq(&i2c1); i2c1_watchdog_counter = 0; I2C_CR2(i2c) |= I2C_CR2_ITEVTEN; }
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; }
// 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; }
void i2c_set_clock_frequency(uint32_t i2c, uint8_t freq) { uint16_t reg16; reg16 = I2C_CR2(i2c) & 0xffc0; /* Clear bits [5:0]. */ reg16 |= freq; I2C_CR2(i2c) = reg16; }
static inline void stmi2c_clear_pending_interrupts(uint32_t i2c) { uint16_t SR1 = I2C_SR1(i2c); // Certainly do not wait for buffer interrupts: // ------------------------------------------- I2C_CR2(i2c) &= ~ I2C_CR2_ITBUFEN; // Disable TXE, RXNE // Error interrupts are handled separately: // --------------------------------------- // Clear Event interrupt conditions: // -------------------------------- // Start Condition Was Generated if (BIT_X_IS_SET_IN_REG( I2C_SR1_SB, SR1 ) ) { // SB: cleared by software when reading SR1 and writing to DR I2C_DR(i2c) = 0x00; } // Address Was Sent if (BIT_X_IS_SET_IN_REG(I2C_SR1_ADDR, SR1) ) { // ADDR: Cleared by software when reading SR1 and then SR2 uint16_t SR2 __attribute__ ((unused)) = I2C_SR2(i2c); } // Byte Transfer Finished if (BIT_X_IS_SET_IN_REG(I2C_SR1_BTF, SR1) ) { // SB: cleared by software when reading SR1 and reading/writing to DR uint8_t dummy __attribute__ ((unused)) = I2C_DR(i2c); I2C_DR(i2c) = 0x00; } }
void i2c2_hw_init(void) { i2c2.reg_addr = (void *)I2C2; i2c2.init_struct = NULL; i2c2.errors = &i2c2_errors; i2c2_watchdog_counter = 0; /* zeros error counter */ ZEROS_ERR_COUNTER(i2c2_errors); /* reset peripheral to default state ( sometimes not achieved on reset :( ) */ //i2c_reset(I2C2); /* Configure priority grouping 0 bits for pre-emption priority and 4 bits for sub-priority. */ scb_set_priority_grouping(SCB_AIRCR_PRIGROUP_NOGROUP_SUB16); /* Configure and enable I2C2 event interrupt --------------------------------*/ nvic_set_priority(NVIC_I2C2_EV_IRQ, 0); nvic_enable_irq(NVIC_I2C2_EV_IRQ); /* Configure and enable I2C2 err interrupt ----------------------------------*/ nvic_set_priority(NVIC_I2C2_ER_IRQ, 1); nvic_enable_irq(NVIC_I2C2_ER_IRQ); /* Enable peripheral clocks -------------------------------------------------*/ /* Enable I2C2 clock */ rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_I2C2EN); /* Enable GPIO clock */ gpio_enable_clock(I2C2_GPIO_PORT); #if defined(STM32F1) gpio_set_mode(I2C2_GPIO_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C2_GPIO_SCL | I2C2_GPIO_SDA); #elif defined(STM32F4) gpio_mode_setup(I2C2_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C2_GPIO_SCL | I2C2_GPIO_SDA); gpio_set_output_options(I2C2_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, I2C2_GPIO_SCL | I2C2_GPIO_SDA); gpio_set_af(I2C2_GPIO_PORT, GPIO_AF4, I2C2_GPIO_SCL | I2C2_GPIO_SDA); #endif i2c_reset(I2C2); // enable peripheral i2c_peripheral_enable(I2C2); /* * XXX: there is a function to do that already in libopencm3 but I am not * sure if it is correct, using direct register instead (esden) */ //i2c_set_own_7bit_slave_address(I2C2, 0); I2C_OAR1(I2C2) = 0 | 0x4000; // enable error interrupts I2C_CR2(I2C1) |= I2C_CR2_ITERREN; i2c_setbitrate(&i2c2, I2C2_CLOCK_SPEED); }
void i2c3_er_isr(void) { uint32_t i2c = (uint32_t) i2c3.reg_addr; i2c_disable_interrupt(i2c, I2C_CR2_ITEVTEN); I2C_CR2(i2c) &= ~I2C_CR2_ITEVTEN; i2c3.watchdog = 0; // restart watchdog i2c_irq(&i2c3); i2c_enable_interrupt(i2c, I2C_CR2_ITEVTEN); }
uint8_t i2c_is_start(uint32_t i2c) { if ((I2C_CR2(i2c) & I2C_CR2_START) != 0) { return 1; } return 0; }
void i2c3_hw_init(void) { i2c3.reg_addr = (void *)I2C3; i2c3.init_struct = NULL; i2c3.errors = &i2c3_errors; i2c3_watchdog_counter = 0; /* zeros error counter */ ZEROS_ERR_COUNTER(i2c3_errors); /* reset peripheral to default state ( sometimes not achieved on reset :( ) */ //i2c_reset(I2C3); /* Configure and enable I2C3 event interrupt --------------------------------*/ nvic_set_priority(NVIC_I2C3_EV_IRQ, NVIC_I2C3_IRQ_PRIO); nvic_enable_irq(NVIC_I2C3_EV_IRQ); /* Configure and enable I2C3 err interrupt ----------------------------------*/ nvic_set_priority(NVIC_I2C3_ER_IRQ, NVIC_I2C3_IRQ_PRIO+1); nvic_enable_irq(NVIC_I2C3_ER_IRQ); /* Enable peripheral clocks -------------------------------------------------*/ /* Enable I2C3 clock */ rcc_periph_clock_enable(RCC_I2C3); /* Enable GPIO clock */ gpio_enable_clock(I2C3_GPIO_PORT_SCL); gpio_mode_setup(I2C3_GPIO_PORT_SCL, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C3_GPIO_SCL); gpio_set_output_options(I2C3_GPIO_PORT_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, I2C3_GPIO_SCL); gpio_set_af(I2C3_GPIO_PORT_SCL, GPIO_AF4, I2C3_GPIO_SCL); gpio_enable_clock(I2C3_GPIO_PORT_SDA); gpio_mode_setup(I2C3_GPIO_PORT_SDA, GPIO_MODE_AF, GPIO_PUPD_NONE, I2C3_GPIO_SDA); gpio_set_output_options(I2C3_GPIO_PORT_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, I2C3_GPIO_SDA); gpio_set_af(I2C3_GPIO_PORT_SDA, GPIO_AF4, I2C3_GPIO_SDA); i2c_reset(I2C3); // enable peripheral i2c_peripheral_enable(I2C3); /* * XXX: there is a function to do that already in libopencm3 but I am not * sure if it is correct, using direct register instead (esden) */ //i2c_set_own_7bit_slave_address(I2C3, 0); I2C_OAR1(I2C3) = 0 | 0x4000; // enable error interrupts I2C_CR2(I2C1) |= I2C_CR2_ITERREN; i2c_setbitrate(&i2c3, I2C3_CLOCK_SPEED); }
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; }
void i2c_set_7bit_address(uint32_t i2c, uint8_t addr) { I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_7BIT_MASK) | ((addr & 0x7F) << I2C_CR2_SADD_7BIT_SHIFT); }
void i2c_set_10bit_addr_mode(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_ADD10; }
void i2c_set_7bit_addr_mode(uint32_t i2c) { I2C_CR2(i2c) &= ~I2C_CR2_ADD10; }
void i2c_send_stop(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_STOP; }
/** @brief I2C Clear DMA last transfer @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. */ void i2c_clear_dma_last_transfer(uint32_t i2c) { I2C_CR2(i2c) &= ~I2C_CR2_LAST; }
/** @brief I2C Set DMA last transfer @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. */ void i2c_set_dma_last_transfer(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_LAST; }
void i2c_disable_autoend(uint32_t i2c) { I2C_CR2(i2c) &= ~I2C_CR2_AUTOEND; }
/** @brief I2C Disable DMA @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. */ void i2c_disable_dma(u32 i2c) { I2C_CR2(i2c) &= ~I2C_CR2_DMAEN; }
void i2c_set_read_transfer_dir(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_RD_WRN; }
void i2c_set_10bit_address(uint32_t i2c, uint16_t addr) { I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_SADD_10BIT_MASK) | ((addr & 0x3FF) << I2C_CR2_SADD_10BIT_SHIFT); }
void i2c_set_write_transfer_dir(uint32_t i2c) { I2C_CR2(i2c) &= ~I2C_CR2_RD_WRN; }
/** @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_CR2(i2c) |= interrupt; }
void i2c_set_bytes_to_transfer(uint32_t i2c, uint32_t n_bytes) { I2C_CR2(i2c) = (I2C_CR2(i2c) & ~I2C_CR2_NBYTES_MASK) | (n_bytes << I2C_CR2_NBYTES_SHIFT); }
/** @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_CR2(i2c) &= ~interrupt; }
void i2c_enable_autoend(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_AUTOEND; }
/** @brief I2C Enable DMA @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. */ void i2c_enable_dma(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_DMAEN; }
void i2c_send_start(uint32_t i2c) { I2C_CR2(i2c) |= I2C_CR2_START; }
/** @brief I2C Disable DMA @param[in] i2c Unsigned int32. I2C register base address @ref i2c_reg_base. */ void i2c_disable_dma(uint32_t i2c) { I2C_CR2(i2c) &= ~I2C_CR2_DMAEN; }