#include "project.h" #define I2C I2C1 #define SCL GPIO6 #define SDA GPIO7 void i2c_clear_start (uint32_t i2c) { I2C_CR1 (i2c) &= ~(uint32_t) I2C_CR1_START; } #if 0 static void i2cp_ds (void) { uint32_t i2c = I2C; printf ("CR1=%08x CR2=%08x\r\n", (unsigned) I2C_CR1 (i2c), (unsigned) I2C_CR2 (i2c)); printf ("SR1=%08x SR2=%08x\r\n", (unsigned) I2C_SR1 (i2c), (unsigned) I2C_SR2 (i2c)); usart1_drain (); } #endif void i2cp_start (void) { i2c_send_start (I2C); while (!((I2C_SR1 (I2C) & I2C_SR1_SB) & (I2C_SR2 (I2C) & (I2C_SR2_MSL | I2C_SR2_BUSY)))); } void i2cp_abort_start (void) { i2c_clear_start (I2C); delay_us (10); } void i2cp_stop (void) { i2c_send_stop (I2C); } void i2cp_abort_stop (void) { i2c_clear_stop (I2C); delay_us (10); } int i2cp_send_data (uint8_t v) { uint32_t reg; i2c_send_data (I2C, v); while (! ((reg = I2C_SR1 (I2C)) & (I2C_SR1_BTF | I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT))); I2C_SR1 (I2C) = reg & ~(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT); return (reg & I2C_SR1_BTF) ? 0 : -1; } /*0 on success 1 on failure*/ int i2cp_start_transaction (uint8_t a, int wnr) { uint32_t reg; uint32_t __attribute__ ((unused)) dummy; i2c_send_start (I2C); while (!((I2C_SR1 (I2C) & I2C_SR1_SB) & (I2C_SR2 (I2C) & (I2C_SR2_MSL | I2C_SR2_BUSY)))); i2c_send_7bit_address (I2C, a, wnr); while (! ((reg = I2C_SR1 (I2C)) & (I2C_SR1_ADDR | I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT))); dummy = I2C_SR2 (I2C); I2C_SR1 (I2C) = reg & ~(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT); return (reg == 0x82) ? 0 : -1; } static int mutex = 0; int i2cp_lock (void) { if (__sync_add_and_fetch (&mutex, 1) != 1) { __sync_sub_and_fetch (&mutex, 1); return -1; } return 0; } void i2cp_unlock (void) { __sync_sub_and_fetch (&mutex, 1); } /*This is stupid, it bit bangs a dummy transaction to get the host i2c controller back in the game */ static void i2cp_reset_sm (void) { int i; gpio_set_mode (GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_I2C1_SCL | GPIO_I2C1_SDA); gpio_set (GPIOB, GPIO_I2C1_SDA); gpio_set (GPIOB, GPIO_I2C1_SCL); delay_us (10); gpio_clear (GPIOB, GPIO_I2C1_SDA); delay_us (10); gpio_clear (GPIOB, GPIO_I2C1_SCL); for (i = 0; i < 9; ++i) { delay_us (10); gpio_set (GPIOB, GPIO_I2C1_SCL); delay_us (10); gpio_clear (GPIOB, GPIO_I2C1_SCL); delay_us (10); } gpio_set (GPIOB, GPIO_I2C1_SCL); delay_us (10); gpio_set (GPIOB, GPIO_I2C1_SDA); delay_us (10); } void i2cp_start_dma (uint8_t * buf, int len) { dma_channel_reset (DMA1, DMA_CHANNEL6); dma_set_peripheral_address (DMA1, DMA_CHANNEL6, (uint32_t) & I2C1_DR); dma_set_memory_address (DMA1, DMA_CHANNEL6, (uint32_t) buf); dma_set_number_of_data (DMA1, DMA_CHANNEL6, len); dma_set_read_from_memory (DMA1, DMA_CHANNEL6); dma_enable_memory_increment_mode (DMA1, DMA_CHANNEL6); dma_set_peripheral_size (DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_8BIT); dma_set_memory_size (DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_8BIT); dma_set_priority (DMA1, DMA_CHANNEL6, DMA_CCR_PL_MEDIUM); dma_enable_transfer_complete_interrupt (DMA1, DMA_CHANNEL6); dma_enable_transfer_error_interrupt (DMA1, DMA_CHANNEL6); dma_enable_channel (DMA1, DMA_CHANNEL6); i2c_enable_dma (I2C1); } int i2cp_dma_in_progress (void) { return !(DMA1_ISR & (DMA_ISR_TCIF6 | DMA_ISR_TEIF6)); } void i2cp_stop_dma (void) { DMA1_IFCR |= DMA_IFCR_CTCIF7 | DMA_IFCR_CTEIF6 | DMA_IFCR_CGIF6; dma_disable_transfer_complete_interrupt (DMA1, DMA_CHANNEL6); dma_disable_transfer_error_interrupt (DMA1, DMA_CHANNEL6); i2c_disable_dma (I2C1); dma_disable_channel (DMA1, DMA_CHANNEL7); } void i2cp_reset (void) { while (i2cp_lock ()); i2cp_start (); i2cp_abort_start (); i2cp_stop (); i2cp_abort_stop (); i2cp_start (); i2cp_abort_start (); i2cp_stop (); i2cp_abort_stop (); i2cp_unlock (); } void i2cp_scan (void) { int i, r; return; i2cp_reset (); printf ("Probing bus\r\n"); for (i = 0; i < 128; ++i) { while (i2cp_lock ()); i2cp_start (); i2cp_abort_start (); i2cp_stop (); i2cp_abort_stop (); r = i2cp_start_transaction (i, I2C_WRITE); i2cp_stop (); i2cp_unlock (); if (!r) printf ("Found device at address 0x%x\r\n", i); usart1_drain (); } printf ("Done\r\n"); i2cp_reset (); } void i2cp_init (void) { rcc_periph_clock_enable (RCC_I2C1); rcc_periph_clock_enable (RCC_DMA1); while (i2cp_lock ()); i2c_peripheral_enable (I2C); i2c_clear_start (I2C); i2c_clear_stop (I2C); i2c_reset (I2C); i2c_peripheral_enable (I2C); I2C_CR1 (I2C) |= I2C_CR1_SWRST; delay_us (1000); I2C_CR1 (I2C) &= ~I2C_CR1_SWRST; i2cp_reset_sm (); gpio_set_mode (GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO_I2C1_SCL | GPIO_I2C1_SDA); i2c_set_clock_frequency (I2C, I2C_CR2_FREQ_36MHZ); i2c_set_standard_mode (I2C); i2c_set_ccr (I2C, 0x200); /* t_high=t_high=CCR * Tpclk1 */ i2c_set_trise (I2C, 0x0b); i2c_set_own_7bit_slave_address (I2C, 0x00); i2c_peripheral_enable (I2C); i2cp_unlock (); }