2023-04-03 11:44 AM
Hello, i have the following setup code for i2c and DMA, where i use i2c1 to send some buffer data to a display.
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_BufferSize = DMA_I2C_BUFFER_SIZE;//BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
// DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SSD1306_Buffer;//I2C1_Buffer_Tx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // enable acknoledge
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000; //400kHz (Fast Mode) (
I2C_Init(I2C1, &I2C_InitStructure);
DMA_Cmd(DMA1_Channel6, ENABLE);
And i have the buffer function to send the data via DMA
void I2C_Master_BufferWrite(uint8_t* pBuffer, uint32_t NumByteToWrite, uint8_t SlaveAddress )
{
//__IO uint32_t Adress = 0;
__IO uint32_t temp = 0;
__IO uint32_t Timeout = 0;
/* Configure the DMA channel for I2Cx transmission */
DMA_InitTypeDef I2CDMA_InitStructure;
I2CDMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuffer;
I2CDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
I2CDMA_InitStructure.DMA_BufferSize = (uint32_t)NumByteToWrite;
I2CDMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_Address;
DMA_Cmd(DMA1_Channel6, DISABLE);
DMA_Init(DMA1_Channel6, &I2CDMA_InitStructure);
DMA_Cmd(DMA1_Channel6, ENABLE);
/* Enable the I2Cx DMA requests */
I2C_DMACmd(I2C1, ENABLE);
//I2C1->CR2 |= CR2_DMAEN_Set;
/* Send START condition */
I2C_GenerateSTART(I2C1, ENABLE);
//I2C1->CR1 |= CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2C1->SR1&0x0001) != 0x0001);
/* Send slave address */
I2C_Send7bitAddress(I2C1, SlaveAddress, I2C_Direction_Transmitter);
/* Wait until ADDR is set: EV6 */
while ((I2C1->SR1&0x0002) != 0x0002);
/* Clear ADDR flag by reading SR2 register */
temp = I2C1->SR2;
/* Wait until DMA end of transfer */
while (!DMA_GetFlagStatus(DMA1_FLAG_TC6));
/* Disable the DMA1 Channel 6 */
DMA_Cmd(DMA1_Channel6, DISABLE);
/* Clear the DMA Transfer complete flag */
DMA_ClearFlag(DMA1_FLAG_TC6);
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2C1->SR1 & 0x00004) != 0x000004);
/* Program the STOP */
I2C_GenerateSTOP(I2C1,ENABLE);
/* Make sure that the STOP bit is cleared by Hardware */
while ((I2C1->CR1&0x200) == 0x200);
}
This piece of code is working somehow strange when i try to send more than 1 byte
I have the following example
uint8_t mm[7]={0x11,0x22,0x33,0x44,0x55,0x66, 0x77 };
I2C_Master_BufferWrite(mm, 5, 0x7A );
With a logic analyzer i get the followings.
So i would expect that it sends 5 bytes in order like 0x11 0x22 0x33 0x44 0x55, but it acts like it jumps some certain memory addresses.
What i am doing wrong here?
2023-04-03 11:52 AM
Hmmm,
i later found out that declaring my "mm" array as short mm[7] = { ......} makes the code works as expected.
But i wonder why?
It seems like normal uint8_t is using actually 2 bytes of memory?
This somehow confirms my guessing, that the dma points by 16 bits in the memory counter.
I'm not sure if this is compiler related, and not mcu
2023-04-03 01:46 PM
Maybe not THE answer, but should be changed anyway so the HAL code doesn't use uninitialized structure contents. Change
DMA_InitTypeDef I2CDMA_InitStructure;
to
DMA_InitTypeDef I2CDMA_InitStructure = {0};
This ensures that ALL of the init structure is set to zeros. Your code leaves some fields set to whatever was in RAM (on the stack).
2023-04-08 01:51 AM
Hello, sorry for the delay.
the initial aproach was using standard periph library, i tried also to develop something under hall, but ran in stranger issues.
Unfortunately i abandoned the usage of dma with i2c, and moved everything to spi where i have higher data rates...