#include "main.h" /** * @brief Check I2C for errors. * @retval I2C return code */ int8_t i2c_check_err(void) { int8_t r = I2C_RET_OK; if ((I2C1->ISR & I2C_ISR_NACKF) != 0) { /* device not present */ r = I2C_RET_NACK; } else if ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR)) != 0) { /* other error */ r = I2C_RET_ERR; } if (r != I2C_RET_OK) { /* restart I2C and clear flags */ I2C1->CR1 &= ~I2C_CR1_PE; while ((I2C1->CR1 & I2C_CR1_PE) != 0); I2C1->CR1 |= I2C_CR1_PE; } return r; } /** * @brief Read len bytes from I2C bus to data by reg_addr. * @retval I2C return code */ int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) { int8_t r = I2C_RET_OK; Flag.I2C_RX_End = 0; Flag.I2C_RX_Err = 0; Flag.I2C_TX_Err = 0; /* wait for i2c */ while ( I2C1->ISR & I2C_ISR_BUSY ) { __NOP(); }; /* prepare i2c for sending reg addr */ I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN); I2C1->CR2 |= ( id | 1 << I2C_CR2_NBYTES_Pos ); /* gen START */ I2C1->CR2 |= ( I2C_CR2_START ); /* wait for byte request or any error */ while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); }; if ((I2C1->ISR & I2C_ISR_TXE) != 0) { /* device ok, send reg addr */ I2C1->TXDR = reg_addr; } else { r = i2c_check_err(); if (r != I2C_RET_OK) { Flag.I2C_TX_Err = 1; return r; } } /* wait for i2c or any error */ while (((I2C1->ISR & I2C_ISR_BUSY) != 0) && ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF)) == 0)) { __NOP(); }; r = i2c_check_err(); if (r != I2C_RET_OK) { Flag.I2C_TX_Err = 1; return r; } /* prepare dma channel for receiving data */ DMA1_Channel2->CMAR = (uint32_t)data; DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR); DMA1_Channel2->CNDTR = len; DMA1_Channel2->CCR |= DMA_CCR_EN; /* prepare i2c for receiving data */ I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN); I2C1->CR2 |= ( id | len << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN); /* launch receiving */ I2C1->CR1 |= ( I2C_CR1_RXDMAEN ); I2C1->CR2 |= ( I2C_CR2_START ); /* wait for receiving data */ while ((Flag.I2C_RX_End == 0) && (Flag.I2C_RX_Err == 0)) { __NOP(); }; return r; } /** * @brief Write len bytes to I2C bus from data by reg_addr. * @retval I2C return code */ int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) { int8_t r = I2C_RET_OK; Flag.I2C_TX_End = 0; Flag.I2C_TX_Err = 0; DMA1_Channel3->CMAR = (uint32_t)data; DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR); DMA1_Channel3->CNDTR = len; while ( I2C1->ISR & I2C_ISR_BUSY ); I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN); I2C1->CR2 |= ( id | (len + 1) << I2C_CR2_NBYTES_Pos ); I2C1->CR2 |= ( I2C_CR2_START ); while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); }; if ((I2C1->ISR & I2C_ISR_TXE) != 0) { I2C1->TXDR = reg_addr; } else { r = i2c_check_err(); if (r != I2C_RET_OK) { Flag.I2C_TX_Err = 1; return r; } } DMA1_Channel3->CCR |= DMA_CCR_EN; I2C1->CR1 |= ( I2C_CR1_TXDMAEN ); return r; }