STM32F103 and I2C TX using DMA, byte array issue
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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?
- Labels:
-
DMA
-
I2C
-
STM32F1 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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...