#include "bsp.h" #include "i2c.h" #include "libs/utils.h" static int _shark_i2c_rw_bytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *buffer, int length, int write); #define iic_device(id) ((id == 0)?I2C0:I2C1) static uint32_t i2c_clk[2]; static uint8_t i2c_busy_count[2]; static volatile uint8_t i2c_lock[2]; /* * 当读写i2c slave设备的时候,MCU复位,有概率会导致slave设备永远会锁住总线,导致永远busy,复位MCU无效 * 这里,需要通过i2c的reset位配合sda,sck拉高,强行让slave释放总线 */ static void shark_i2c_busy_recovery(uint32_t i2c_periph){ if (i2c_periph == I2C0) { gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); gpio_bit_set(GPIOB, GPIO_PIN_6); gpio_bit_set(GPIOB, GPIO_PIN_7); } else { gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11); gpio_bit_set(GPIOB, GPIO_PIN_10); gpio_bit_set(GPIOB, GPIO_PIN_11); } i2c_software_reset_config(i2c_periph, 1); delay_us(10); i2c_software_reset_config(i2c_periph, 0); } void shark_i2c_init(uint32_t i2c_index, uint32_t rate){ uint32_t device = iic_device(i2c_index); i2c_clk[i2c_index] = rate; i2c_lock[i2c_index] = 0; rcu_periph_clock_enable(RCU_GPIOB); if (device == I2C0) { rcu_periph_clock_enable(RCU_I2C0); shark_i2c_busy_recovery(I2C0); i2c_deinit(I2C0); gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); } else { rcu_periph_clock_enable(RCU_I2C1); shark_i2c_busy_recovery(I2C1); i2c_deinit(I2C1); gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11); } i2c_clock_config(device, rate, I2C_DTCY_2); i2c_enable(device); } void shark_i2c_deinit(uint32_t i2c_index){ uint32_t device = iic_device(i2c_index); i2c_disable(device); i2c_deinit(device); if (device == I2C0){ rcu_periph_clock_disable(RCU_I2C0); }else { rcu_periph_clock_disable(RCU_I2C1); } } static int shark_i2c_write_address(uint32_t deivce, uint8_t address, uint8_t write){ uint32_t times; if (!write){ address |= 1; } I2C_DATA((deivce)) = address; for (times = 1000; times > 0; times--) { if (i2c_flag_get((deivce), I2C_FLAG_ADDSEND)) { return 0; } } return -1; } int shark_i2c_read_byte(uint32_t index, uint8_t address, uint8_t reg, uint8_t *value){ return _shark_i2c_rw_bytes(index, address, reg, value, 1, 0); } int shark_i2c_read_nbytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *buffer, int length){ return _shark_i2c_rw_bytes(index, address, reg, buffer, length, 0); } int shark_i2c_write_byte(uint32_t index, uint8_t address, uint8_t reg, uint8_t value){ return _shark_i2c_rw_bytes(index, address, reg, &value, 1, 1); } int shark_i2c_write_nbytes(uint32_t index, uint8_t address, uint8_t reg, uint8_t *value, int length){ return _shark_i2c_rw_bytes(index, address, reg, value, length, 1); } static int shark_i2c_wait_flags(uint32_t i2c_periph, i2c_flag_enum flag, FlagStatus status){ int remain = 1000; while (i2c_flag_get(i2c_periph, flag) != status) { if (remain-- <= 0){ return -1; } } return 0; } static void shark_i2c_wait_stop(uint32_t i2c_periph){ int remain = 1000; while(I2C_CTL0(i2c_periph) & 0x0200){ if (remain-- <= 0){ break; } }; } static int lock_i2c(int i2c_index){ return 0; } static int unlock_i2c(int i2c_index){ return 0; } static int _shark_i2c_rw_bytes(uint32_t i2c_index, uint8_t address, uint8_t reg, uint8_t *buffer, int length, int write){ int ret = length; uint32_t device = iic_device(i2c_index); if (lock_i2c(i2c_index) == 1) { return -100; } i2c_ackpos_config(device, length == 2?I2C_ACKPOS_NEXT:I2C_ACKPOS_CURRENT); i2c_ack_config(device, I2C_ACK_ENABLE); if (shark_i2c_wait_flags(device, I2C_FLAG_I2CBSY, RESET) < 0){ i2c_busy_count[i2c_index]++; if (i2c_busy_count[i2c_index] >= 10) { shark_i2c_deinit(i2c_index); shark_i2c_init(i2c_index, i2c_clk[i2c_index]); i2c_busy_count[i2c_index] = 0; } ret = -1; goto out_i2c_stop_on_bus; } i2c_busy_count[i2c_index] = 0; //send reg i2c_start_on_bus(device); if (shark_i2c_wait_flags(device, I2C_FLAG_SBSEND, SET) < 0){ ret = -2; goto out_i2c_stop_on_bus; } if (shark_i2c_write_address(device, address, 1) < 0){ ret = -3; goto out_i2c_stop_on_bus; } i2c_flag_clear(device, I2C_FLAG_ADDSEND); /* wait until the transmit data buffer is empty */ if (shark_i2c_wait_flags(device, I2C_FLAG_TBE, SET) < 0){ ret = -4; goto out_i2c_stop_on_bus; } i2c_data_transmit(device, reg); if (shark_i2c_wait_flags(device, I2C_FLAG_BTC, SET) < 0){ ret = -5; goto out_i2c_stop_on_bus; } if (write){ int index = 0; for (; index < length; index++){ if (shark_i2c_wait_flags(device, I2C_FLAG_TBE, SET) < 0){ ret = -6; goto out_i2c_stop_on_bus; } i2c_data_transmit(device, buffer[index]); } if (shark_i2c_wait_flags(device, I2C_FLAG_BTC, SET) < 0){ ret = -7; goto out_i2c_stop_on_bus; } ret = length; goto out_i2c_stop_on_bus; } //begin read i2c_start_on_bus(device); if (shark_i2c_wait_flags(device, I2C_FLAG_SBSEND, SET) < 0){ ret = -8; goto out_i2c_stop_on_bus; } if (shark_i2c_write_address(device, address, 0) < 0){ ret = -9; goto out_i2c_stop_on_bus; } i2c_flag_clear(device, I2C_FLAG_ADDSEND); if (length< 3) { i2c_ack_config(device, I2C_ACK_DISABLE); } else { while (length > 3) { if (shark_i2c_wait_flags(device, I2C_FLAG_RBNE, SET) < 0){ ret = -10; goto out_i2c_stop_on_bus; } *buffer++ = i2c_data_receive(device); length--; } if (shark_i2c_wait_flags(device, I2C_FLAG_BTC, SET) < 0){ ret = -11; goto out_i2c_stop_on_bus; } i2c_ack_config(device, I2C_ACK_DISABLE); } while (length > 0) { if (shark_i2c_wait_flags(device, I2C_FLAG_RBNE, SET) < 0){ ret = -12; goto out_i2c_stop_on_bus; } *buffer++ = i2c_data_receive(device); length--; } if (length != 0){ ret = -13; } out_i2c_stop_on_bus: if (ret != -1) { i2c_stop_on_bus(device); shark_i2c_wait_stop(device); } unlock_i2c(i2c_index); return ret; }