cancel
Showing results for 
Search instead for 
Did you mean: 

Long i2c writes > 255 bytes using DMA using I2C_CR2_RELOAD flag gives address in continuation data

JAdol.1
Associate

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();

1 REPLY 1
JAdol.1
Associate

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.