2021-01-27 09:16 AM
I want to do i2c writes > 255 bytes using DMA with an STM32L451, but fail to use the I2C_CR2_RELOAD flag properly it seems.
I end up with an address byte when the transmission continues.
How should it be done using the raw register defines.
Currently I setup a new DMA_I2C1TX for each chunk:
uint32_t cr2 = ( I2C_CR2_AUTOEND | ( i2c.buff_len << 16 ) | (i2c_address & (0x3FF | I2C_CR2_RELOAD)) );
__disable_irq();
_ax_i2c1_reset();
if (i2c_address & I2C_CR2_RELOAD) {
cr2 &= ~I2C_CR2_AUTOEND;
}
// prepare and enable I2C1 transfer
I2C1->CR2 = cr2;
I2C1->CR1 = ( I2C_CR1_TXDMAEN | I2C_CR1_ERRIE | I2C_CR1_STOPIE | I2C_CR1_NACKIE | I2C_CR1_PE );
if (i2c_address & I2C_CR2_RELOAD) {
I2C1->CR1 |= I2C_CR1_TCIE;
}
// Prepare I2C1 DMA for transmit
DMA_I2C1TX->CCR = ( DMA_CCR_PL_0 | DMA_CCR_MINC | DMA_CCR_DIR );
DMA_I2C1TX->CPAR = ( uint32_t )&I2C1->TXDR;
DMA_I2C1TX->CMAR = ( uint32_t )&i2c.tx_buff[ 0 ];
DMA_I2C1TX->CNDTR = ( uint32_t )i2c.buff_len;
DMA_I2C1TX->CCR = ( DMA_CCR_PL_0 | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN );
// start I2C1 transmit
I2C1->CR2 = ( cr2 | I2C_CR2_START );
__enable_irq();
2021-01-27 09:51 AM
Removing the _ax_i2c1_reset(), helped a bit. There is no address in the continuation any more, but there comes a new Write cycle that is NAK:ed immediatly follow the intended write.