From e41764fceeabb1cdb6a7a299e00f2166a6f6ac32 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Thu, 18 Jun 2020 13:26:56 +0100 Subject: moved stm32 into directory added noddy pcb --- stm32/app/i2c_hw.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 stm32/app/i2c_hw.c (limited to 'stm32/app/i2c_hw.c') diff --git a/stm32/app/i2c_hw.c b/stm32/app/i2c_hw.c new file mode 100644 index 0000000..a17c564 --- /dev/null +++ b/stm32/app/i2c_hw.c @@ -0,0 +1,360 @@ +#include "project.h" + + +#define SCL1 GPIO6 +#define SDA1 GPIO7 +#define SCL1_PORT GPIOB +#define SDA1_PORT GPIOB + +#define SCL2 GPIO10 +#define SDA2 GPIO11 +#define SCL2_PORT GPIOB +#define SDA2_PORT GPIOB + +void +i2c_clear_start (uint32_t i2c) +{ + I2C_CR1 (i2c) &= ~ (uint32_t) I2C_CR1_START; +} + + +int +i2cp_start (uint32_t i2c) +{ + uint32_t timeout = 1000; + i2c_send_start (i2c); + + while (! ((I2C_SR1 (i2c) & I2C_SR1_SB) + & (I2C_SR2 (i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))) && (timeout--)); + + return timeout ? 0 : -1; +} + +void +i2cp_abort_start (uint32_t i2c) +{ + i2c_clear_start (i2c); + delay_us (10); +} + +void +i2cp_stop (uint32_t i2c) +{ + i2c_send_stop (i2c); +} + + +void +i2cp_abort_stop (uint32_t i2c) +{ + i2c_clear_stop (i2c); + delay_us (10); +} + +int +i2cp_send (uint32_t i2c, uint8_t v) +{ + uint32_t reg; + uint32_t timeout = 1000; + + 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)) && (timeout--)); + + I2C_SR1 (i2c) = + reg & ~ (I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_PECERR | + I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT); + + if (!timeout) + return 1; + + + return (reg & I2C_SR1_BTF) ? 0 : -1; +} + +/*0 on success 1 on failure*/ +int +i2cp_start_transaction (uint32_t i2c, uint8_t a, int wnr) +{ + uint32_t reg; + uint32_t __attribute__ ((unused)) dummy; + uint32_t timeout = 1000; + + i2c_send_start (i2c); + + while (! ((I2C_SR1 (i2c) & I2C_SR1_SB) + & (I2C_SR2 (i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))) && (timeout--)); + + if (!timeout) + return -1; + + 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)) && (timeout--)); + + if (!timeout) + return -1; + + 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 */ +void +i2cp1_reset_sm (void) +{ + int i; + + MAP_OUTPUT_PP (SCL1); + MAP_OUTPUT_PP (SDA1); + + SET (SDA1); + SET (SCL1); + delay_us (10); + CLEAR (SDA1); + delay_us (10); + CLEAR (SCL1); + + for (i = 0; i < 9; ++i) { + delay_us (10); + SET (SCL1); + delay_us (10); + CLEAR (SCL1); + delay_us (10); + } + + SET (SCL1); + delay_us (10); + SET (SDA1); + delay_us (10); + + MAP_AF_OD (SCL1); + MAP_AF_OD (SDA1); + +} + +void +i2cp2_reset_sm (void) +{ + int i; + + MAP_OUTPUT_PP (SCL2); + MAP_OUTPUT_PP (SDA2); + + SET (SDA2); + SET (SCL2); + delay_us (10); + CLEAR (SDA2); + delay_us (10); + CLEAR (SCL2); + + for (i = 0; i < 9; ++i) { + delay_us (10); + SET (SCL2); + delay_us (10); + CLEAR (SCL2); + delay_us (10); + } + + SET (SCL2); + delay_us (10); + SET (SDA2); + delay_us (10); + + MAP_AF_OD (SCL2); + MAP_AF_OD (SDA2); + +} + + + +void +i2cp1_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); +} + + +void +i2cp2_start_dma (uint8_t *buf, int len) +{ + dma_channel_reset (DMA1, DMA_CHANNEL4); + dma_set_peripheral_address (DMA1, DMA_CHANNEL4, (uint32_t) & I2C2_DR); + dma_set_memory_address (DMA1, DMA_CHANNEL4, (uint32_t) buf); + dma_set_number_of_data (DMA1, DMA_CHANNEL4, len); + dma_set_read_from_memory (DMA1, DMA_CHANNEL4); + dma_enable_memory_increment_mode (DMA1, DMA_CHANNEL4); + dma_set_peripheral_size (DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT); + dma_set_memory_size (DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT); + dma_set_priority (DMA1, DMA_CHANNEL4, DMA_CCR_PL_MEDIUM); + dma_enable_transfer_complete_interrupt (DMA1, DMA_CHANNEL4); + dma_enable_transfer_error_interrupt (DMA1, DMA_CHANNEL4); + dma_enable_channel (DMA1, DMA_CHANNEL4); + + i2c_enable_dma (I2C2); +} + + +int +i2cp1_dma_in_progress (void) +{ + return ! (DMA1_ISR & (DMA_ISR_TCIF6 | DMA_ISR_TEIF6)); +} + +int +i2cp2_dma_in_progress (void) +{ + return ! (DMA1_ISR & (DMA_ISR_TCIF4 | DMA_ISR_TEIF4)); +} + +void +i2cp1_stop_dma (void) +{ + DMA1_IFCR |= DMA_IFCR_CTCIF6 | 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_CHANNEL6); +} + +void +i2cp2_stop_dma (void) +{ + DMA1_IFCR |= DMA_IFCR_CTCIF4 | DMA_IFCR_CTEIF4 | DMA_IFCR_CGIF4; + + dma_disable_transfer_complete_interrupt (DMA1, DMA_CHANNEL4); + dma_disable_transfer_error_interrupt (DMA1, DMA_CHANNEL4); + + i2c_disable_dma (I2C2); + dma_disable_channel (DMA1, DMA_CHANNEL4); +} + + +void +i2cp_reset (uint32_t i2c) +{ + while (i2c_lock()); + + i2cp_start (i2c); + i2cp_abort_start (i2c); + i2cp_stop (i2c); + i2cp_abort_stop (i2c); + + i2cp_start (i2c); + i2cp_abort_start (i2c); + i2cp_stop (i2c); + i2cp_abort_stop (i2c); + i2c_unlock(); +} + + + +void +i2cp_scan (uint32_t i2c) +{ + int i, r; + + i2cp_reset (i2c); + + printf ("Probing bus\n"); + + for (i = 0; i < 128; ++i) { + printf ("%d\n", i); + + while (i2c_lock()); + + i2cp_start (i2c); + i2cp_abort_start (i2c); + i2cp_stop (i2c); + i2cp_abort_stop (i2c); + delay_ms (10); + r = i2cp_start_transaction (i2c, i, I2C_WRITE); + i2cp_stop (i2c); + i2c_unlock(); + + if (!r) + printf ("Found device at address 0x%x\n", i); + + usart1_drain(); + } + + printf ("Done\n"); + i2cp_reset (i2c); + +} + +static void +i2cp_bringup (uint32_t i2c) +{ + 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; + + + if (i2c == I2C1) + i2cp1_reset_sm(); + else + i2cp2_reset_sm(); + + + 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); +} + + +void +i2cp_init (void) +{ + rcc_periph_clock_enable (RCC_I2C1); + rcc_periph_clock_enable (RCC_I2C2); + rcc_periph_clock_enable (RCC_DMA1); + + while (i2c_lock()); + + i2cp_bringup (I2C1); + i2cp_bringup (I2C2); + + i2c_unlock(); +} -- cgit v1.2.3