2023-12-19 11:10 PM - edited 2023-12-19 11:23 PM
I am using Stm32L431Rbt6 for page writing on EEPROM M2456.
When using HAL_I2C_Mem_Write_DMA , I am getting interrupt HAL_MemTxCpltCallback , but data is not written on EEPROM when I do page read on EEPROM.
I am using I2C1, dma channel 6. I have enabled I2c event and error interrupt. I2C clock freq = 100 Khz., EEPROM page size is 64 bytes.
I am setting the I2C_CR2_STOP bit in HAL_MemTxCpltCallback for generating stop condition.
Please guide if I am doing anything wrong or provide any reference code using HAL_I2C_Mem_Write_DMA .
2023-12-21 09:56 AM - edited 2023-12-21 09:57 AM
You shouldn't have to set the STOP bit int he callback - the HAL interrupt handler should do that.
Are you waiting for the "write" operation to finish before trying to read back from the EEPROM? [EDIT: Not just for the HAL write call to finish, but the EEPROM itself to store the new data]
Show our relevant code - code that calls HAL_I2C_Mem_Write_DMA(), code that reads back, and your callback functions. Please paste you code here in the chat using the "code" formatting button (click on "..." then "</>").
2023-12-23 04:55 AM - edited 2023-12-25 08:14 PM
I have checked using breakpoints HAL_I2C_MemTxCpltCallback is called and HAL_I2C_EV_IRQHandler is called.
Page write and page read done seperately by commenting write and read enable macros.
After doing page write , then page read data is not correct in the page.
HAL_I2C_MemTxCpltCallback => i2c_dma_tf_cplt is set , / This flag tells us DMA has completed transmission of data to i2c_tx data register
In HAL_I2C_EV_IRQHandler
I2C_TransferConfig(hi2c, 0xA0, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP); // stop condition sent
tmr_EEPROM_wr = 0; // starting timer counts for waiting 5ms EEPROM internal write
i2c_pg_wr_done = 1; // flag for page write done to eeprom
"code"
@Bob S wrote:You shouldn't have to set the STOP bit int he callback - the HAL interrupt handler should do that.
Are you waiting for the "write" operation to finish before trying to read back from the EEPROM? [EDIT: Not just for the HAL write call to finish, but the EEPROM itself to store the new data]
Show our relevant code - code that calls HAL_I2C_Mem_Write_DMA(), code that reads back, and your callback functions. Please paste you code here in the chat using the "code" formatting button (click on "..." then "</>").
volatile uint32_t tmr_EEPROM_wr = 0; // timer variable for EEPROM internal page write delay
DMA_HandleTypeDef hdma_i2c1_tx;
uint8_t EEPROM_data_buff[64];
uint8_t EEPROM_read_data_buff[64];
#define EEPROM_page_write_enabled // Read and write done seperately . First doing page write by commenting EEPROM_page_read_enabled
//#define EEPROM_page_read_enabled
main()
{
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_I2C1_Init(void);
HAL_delay(100);
Feed_dummy_Data_EEPROM();
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); //enabling the WR pin of EEPROM
HAL_I2C_Mem_Write_DMA(&hi2c1, 0xA0, 0x140,2, EEPROM_data_buff, 64);
while(1)
{
#ifdef EEPROM_page_write_enabled
if((i2c_pg_wr_done == 1) && (tmr_EEPROM_wr >= 5))
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //disabling the WR pin of EEPROM
i2c_pg_wr_done = 0;
}
#endif
#ifdef EEPROM_page_read_enabled
M24256_Read(6, EEPROM_read_data_buff);
#endif
// other code
}
}
void Feed_dummy_Data_EEPROM(void)
{
int16_t temp_var_signed;
uint16_t temp_var_2;
uint32_t temp_var_4;
for(i= 0 ; i<64; i++)
{
EEPROM_data_buff[i]= 12;
}
}
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x007075B1;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_DISABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
(I2C1->CR1)|= (I2C_CR1_TXDMAEN);
/* USER CODE END I2C1_Init 2 */
}
static void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* I2C1 DMA Init */
/* I2C1_TX Init */
hdma_i2c1_tx.Instance = DMA1_Channel6;
hdma_i2c1_tx.Init.Request = DMA_REQUEST_3;
hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hi2c,hdmatx,hdma_i2c1_tx);
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE END I2C1_MspInit 1 */
}
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
UNUSED(hi2c);
i2c_dma_tf_cplt = 1; // This flag tells us DMA has completed transmission of data to i2c_tx data register
}
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
{
/* Get current IT Flags and IT sources value */
uint32_t itflags = READ_REG(hi2c->Instance->ISR);
uint32_t itsources = READ_REG(hi2c->Instance->CR1);
/* I2C events treatment -------------------------------------*/
if (hi2c->XferISR != NULL)
{
hi2c->XferISR(hi2c, itflags, itsources);
}
if((itsources)&(I2C_ISR_TC))
{
if(i2c_dma_tf_cplt)
{
I2C_TransferConfig(hi2c, 0xA0, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP);
tmr_EEPROM_wr = 0; // starting timer counts for waiting 5ms EEPROM internal write
i2c_pg_wr_done = 1; // flag for page write done to eeprom
}
}
}
void SysTick_Handler(void)
{
HAL_IncTick();
tmr_EEPROM_wr++;
}
// Doing page read in seperate code
void M24256_Read(uint16_t page, uint8_t *data)
{
uint16_t MemAddr = page << 8;
HAL_I2C_Mem_Read(&hi2c1, 0xA0, MemAddr, 2, &data[position], remainingbytes, 100);
}
2023-12-23 05:10 AM
The read function at the end uses variables unrelated to parameters passed in.
Does the part work as expected in polled mode, ie without IT and DMA usage?
2023-12-25 08:06 PM
yes, it's working fine with polling method