summaryrefslogtreecommitdiffstats
path: root/app/i2c_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/i2c_hw.c')
-rw-r--r--app/i2c_hw.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/app/i2c_hw.c b/app/i2c_hw.c
new file mode 100644
index 0000000..b709af0
--- /dev/null
+++ b/app/i2c_hw.c
@@ -0,0 +1,261 @@
+#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\n", (unsigned) I2C_CR1 (i2c),
+ (unsigned) I2C_CR2 (i2c));
+ printf ("SR1=%08x SR2=%08x\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 (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;
+}
+
+
+ /*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 (i2c_lock ());
+ i2cp_start ();
+ i2cp_abort_start ();
+ i2cp_stop ();
+ i2cp_abort_stop ();
+
+ i2cp_start ();
+ i2cp_abort_start ();
+ i2cp_stop ();
+ i2cp_abort_stop ();
+ i2c_unlock ();
+}
+
+
+
+void
+i2cp_scan (void)
+{
+ int i, r;
+
+ i2cp_reset ();
+
+ printf ("Probing bus\n");
+ for (i = 0; i < 128; ++i)
+ {
+ printf ("%d\n", i);
+ while (i2c_lock ());
+ i2cp_start ();
+ i2cp_abort_start ();
+ i2cp_stop ();
+ i2cp_abort_stop ();
+ delay_ms (10);
+ r = i2cp_start_transaction (i, I2C_WRITE);
+ i2cp_stop ();
+ i2c_unlock ();
+ if (!r)
+ printf ("Found device at address 0x%x\n", i);
+ usart1_drain ();
+ }
+ printf ("Done\n");
+ i2cp_reset ();
+
+}
+
+void
+i2cp_init (void)
+{
+ rcc_periph_clock_enable (RCC_I2C1);
+ rcc_periph_clock_enable (RCC_DMA1);
+
+ while (i2c_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, 0x80); /* t_high=t_high=CCR * Tpclk1 */
+ i2c_set_trise (I2C, 0x0b);
+
+ i2c_set_own_7bit_slave_address (I2C, 0x00);
+
+ i2c_peripheral_enable (I2C);
+ i2c_unlock ();
+}