AnsweredAssumed Answered

STM32F030 - I2C Master read with DMA first byte wrong

Question asked by scholz.florian on May 19, 2015
I use STM32F030x8 as I2C-Master with StdLib V1.5.0.
First i write 6 Bytes to a slave device with DMA and it is working like expected. Then a restart with Read-Address is generated to read back the 6 Byte Response from this slave.
Sometimes the error occur that the first Byte in my RxBuffer is 0x00 and the second Byte is the expected first. I checked the bus with an oscilloscope and the data stream is ok.

Have any other also made this experience an exists an Workaround?
Can you also please check my code because something could be wrong:

 

001.void test(void)
002.{
003.case eI2CTask_Idle:        
004.        /* Check if new message to transmit is in fifo */
005.        if(fifoRead(&master_MessageList, &master_Message)) 
006.        {    
007.            //Fill I2C TxBuffer
008.            master_TxBuffer[0] = master_Message.Command;   
009.            master_TxBuffer[1] = master_Message.Data>>24;
010.            master_TxBuffer[2] = master_Message.Data>>16;  
011.            master_TxBuffer[3] = master_Message.Data>>8;
012.            master_TxBuffer[4] = master_Message.Data;  
013.            master_TxBuffer[5] = CRC_GetValue((void *)&master_TxBuffer, bufferSize-1);              
014.                                
015.              
016.            //Start to Write without StopCondition
017.            DMA_Cmd(I2C_DMA_TxCHANNEL, DISABLE);
018.            DMA_SetCurrDataCounter(I2C_DMA_TxCHANNEL, bufferSize);
019.            DMA_Cmd(I2C_DMA_TxCHANNEL, ENABLE);               
020.            //Enable Tx DMA request
021.            I2C_DMACmd(I2C_PERIPH, I2C_DMAReq_Tx, ENABLE);   
022.              
023.            I2C_TransferHandling(I2C_PERIPH, master_Message.Address<<1, bufferSize, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);  
024.              
025.            i2c_Task = eI2CTask_MasterWrite;
026.        }
027.        break;
028.    case eI2CTask_MasterWrite:
029.        if(I2C_GetFlagStatus(I2C_PERIPH, I2C_FLAG_TC) == SET)
030.        {                
031.            //Start to Read with StopCondition       
032.            DMA_Cmd(I2C_DMA_RxCHANNEL, DISABLE); 
033.            DMA_SetCurrDataCounter(I2C_DMA_RxCHANNEL, bufferSize);
034.            DMA_Cmd(I2C_DMA_RxCHANNEL, ENABLE);
035.            //Enable RX DMA request
036.            I2C_DMACmd(I2C_PERIPH, I2C_DMAReq_Rx, ENABLE);  
037.            I2C_TransferHandling(I2C_PERIPH, master_Message.Address<<1, bufferSize, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);    
038.  
039.            i2c_Task = eI2CTask_MasterRead;  
040.        }
041.        break;
042.    case eI2CTask_MasterRead: 
043.        if(I2C_GetFlagStatus(I2C_PERIPH, I2C_FLAG_BUSY) == RESET)
044.        {   
045.            I2C_GenerateSTOP(I2C_PERIPH, ENABLE);
046.              
047.            /* Check CRC-Byte of received buffer*/ 
048.            if(master_Message.Command != master_RxBuffer[0])
049.            {   
050.                i2c_Task = eI2CTask_Error;
051.            }      
052.            else
053.            {                                  
054.                i2c_Task = eI2CTask_Finished;
055.            }
056.        }
057.        break;        
058.    }      
059.}
060.  
061.void configure_GPIO(void)
062.{
063.    /* Initialize CLK */ 
064.    RCC_AHBPeriphClockCmd(I2C_SDA_GPIO_CLK|I2C_SCL_GPIO_CLK, ENABLE);
065.      
066.    /* Initialize GPIO */ 
067.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);       //SDA
068.    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);       //SCL
069.      
070.    GPIO_InitTypeDef GPIO_InitStructure;
071.    GPIO_InitStructure.GPIO_Pin = I2C_SDA_GPIO_PIN; 
072.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;
073.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
074.    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
075.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;     
076.    GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure); 
077.      
078.    GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN; 
079.    GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);     
080.}
081.void configure_DMA(void)
082.{
083.    /* Initialize CLK */ 
084.    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
085.    /* Initialize DMA */
086.    DMA_DeInit(I2C_DMA_TxCHANNEL);
087.    DMA_DeInit(I2C_DMA_RxCHANNEL); 
088.      
089.    DMA_InitTypeDef DMA_InitStructure;
090.    DMA_StructInit(&DMA_InitStructure);
091.    DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;
092.    DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte;
093.    DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;
094.    DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_Byte;
095.    DMA_InitStructure.DMA_Mode                  = DMA_Mode_Normal;  
096.    DMA_InitStructure.DMA_Priority              = DMA_Priority_VeryHigh;
097.    DMA_InitStructure.DMA_M2M                   = DMA_M2M_Disable;
098.      
099.    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralSRC; 
100.    DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&(I2C_PERIPH->RXDR);
101.    DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)&master_RxBuffer;
102.    DMA_InitStructure.DMA_BufferSize            = sizeof(master_RxBuffer);  
103.    DMA_Init(I2C_DMA_RxCHANNEL, &DMA_InitStructure);
104.  
105.    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralDST;   
106.    DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&(I2C_PERIPH->TXDR);
107.    DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)&master_TxBuffer;
108.    DMA_InitStructure.DMA_BufferSize            = sizeof(master_TxBuffer);  
109.    DMA_Init(I2C_DMA_TxCHANNEL, &DMA_InitStructure); 
110.          
111.    DMA_Cmd(I2C_DMA_TxCHANNEL, DISABLE);
112.    DMA_Cmd(I2C_DMA_RxCHANNEL, DISABLE);
113.}
114.void configure_I2C(void)
115.{        
116.    /* Initialize CLK */        
117.    RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE); 
118.  
119.    /* Initialize I2C */
120.    I2C_DeInit(I2C_PERIPH);      
121.    I2C_Cmd(I2C_PERIPH, DISABLE);
122.      
123.    I2C_InitTypeDef I2C_InitStructure;
124.    I2C_StructInit(&I2C_InitStructure);
125.    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
126.    I2C_InitStructure.I2C_Timing = 0x0040D4FF; // 50 kHz at 24 MHz, normal mode
127.    I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
128.    I2C_InitStructure.I2C_DigitalFilter = 1;
129.    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
130.    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
131.    I2C_InitStructure.I2C_OwnAddress1 = I2C_OWNADDRESS<<1;
132.    I2C_Init(I2C_PERIPH, &I2C_InitStructure);    
133.      
134.    I2C_ITConfig(I2C_PERIPH, I2C_IT_ADDRI, ENABLE);   // Enable Address IT   
135.    I2C_ITConfig(I2C_PERIPH, I2C_IT_ERRI, ENABLE);    // Enable Error IT 
136.      
137.    //NVIC_SetPriority(I2C1_IRQn, 0); 
138.    //NVIC_EnableIRQ(I2C1_IRQn);  
139.      
140.    I2C_DMACmd(I2C_PERIPH, I2C_DMAReq_Tx, DISABLE);
141.    I2C_DMACmd(I2C_PERIPH, I2C_DMAReq_Rx, DISABLE);
142.    I2C_Cmd(I2C_PERIPH, ENABLE);
143.}

Best regards

Outcomes