2022-09-13 05:54 PM
I am trying to communicate with SMBUS Master and Slave configuration on both STM32G070RB (NUCLEO Boards). So the master sends the address signal correctly to the slave. I can see the slave address on the address match code register on the slave. But the slave couldn't get the data from the master because the master is also stuck on the address stage because it couldn't get the ack signal from the slave. You can check the graph below. After sending the address SCL pin stays low until the timeout. So HAL_SMBUS_GetState is never returning HAL_SMBUS_STATE_READY. How can I solve this issue?
Master Code:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_SMBUS_Init();
while (1)
{
if (HAL_SMBUS_Master_Transmit_IT(&hsmbus1, (125U << 1), &txData,
1, SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK) {
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
}
while (HAL_SMBUS_GetState(&hsmbus1) != HAL_SMBUS_STATE_READY);
HAL_Delay(500);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 8;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2C1_SMBUS_Init(void)
{
hsmbus1.Instance = I2C1;
hsmbus1.Init.Timing = 0xE010A9FF;
hsmbus1.Init.AnalogFilter = SMBUS_ANALOGFILTER_ENABLE;
hsmbus1.Init.OwnAddress1 = 2;
hsmbus1.Init.AddressingMode = SMBUS_ADDRESSINGMODE_7BIT;
hsmbus1.Init.DualAddressMode = SMBUS_DUALADDRESS_DISABLE;
hsmbus1.Init.OwnAddress2 = 0;
hsmbus1.Init.OwnAddress2Masks = SMBUS_OA2_NOMASK;
hsmbus1.Init.GeneralCallMode = SMBUS_GENERALCALL_DISABLE;
hsmbus1.Init.NoStretchMode = SMBUS_NOSTRETCH_DISABLE;
hsmbus1.Init.PacketErrorCheckMode = SMBUS_PEC_DISABLE;
hsmbus1.Init.PeripheralMode = SMBUS_PERIPHERAL_MODE_SMBUS_HOST;
hsmbus1.Init.SMBusTimeout = 0x0000830D;
if (HAL_SMBUS_Init(&hsmbus1) != HAL_OK)
{
Error_Handler();
}
if (HAL_SMBUS_ConfigDigitalFilter(&hsmbus1, 0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = LED_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct);
}
Slave Code:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_SMBUS_Init();
HAL_SMBUS_EnableListen_IT(&hsmbus1);
while (1)
{
if(HAL_SMBUS_Slave_Receive_IT(&hsmbus1, &rxData, 1, SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK)
{
Error_Handler();
}
while (hsmbus1.State != HAL_SMBUS_STATE_READY);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 8;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2C1_SMBUS_Init(void)
{
hsmbus1.Instance = I2C1;
hsmbus1.Init.Timing = 0xE010A9FF;
hsmbus1.Init.AnalogFilter = SMBUS_ANALOGFILTER_ENABLE;
hsmbus1.Init.OwnAddress1 = 250;
hsmbus1.Init.AddressingMode = SMBUS_ADDRESSINGMODE_7BIT;
hsmbus1.Init.DualAddressMode = SMBUS_DUALADDRESS_DISABLE;
hsmbus1.Init.OwnAddress2 = 0;
hsmbus1.Init.OwnAddress2Masks = SMBUS_OA2_NOMASK;
hsmbus1.Init.GeneralCallMode = SMBUS_GENERALCALL_DISABLE;
hsmbus1.Init.NoStretchMode = SMBUS_NOSTRETCH_DISABLE;
hsmbus1.Init.PacketErrorCheckMode = SMBUS_PEC_DISABLE;
hsmbus1.Init.PeripheralMode = SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE;
hsmbus1.Init.SMBusTimeout = 0x0000830D;
if (HAL_SMBUS_Init(&hsmbus1) != HAL_OK)
{
Error_Handler();
}
if (HAL_SMBUS_ConfigDigitalFilter(&hsmbus1, 0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = LED_GREEN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct);
}
Solved! Go to Solution.
2022-09-14 11:05 AM
I solved this issue by adding this code into while(1).
HAL_SMBUS_EnableListen_IT(&hsmbus1);
while(SlaveAddrMatchCode != 250);
SlaveAddrMatchCode = 0;
And adding this callback.
void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus,uint8_t TransferDirection, uint16_t AddrMatchCode)
{
SlaveAddrMatchCode = (AddrMatchCode << 1);
UNUSED(TransferDirection);
}
2022-09-14 11:05 AM
I solved this issue by adding this code into while(1).
HAL_SMBUS_EnableListen_IT(&hsmbus1);
while(SlaveAddrMatchCode != 250);
SlaveAddrMatchCode = 0;
And adding this callback.
void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus,uint8_t TransferDirection, uint16_t AddrMatchCode)
{
SlaveAddrMatchCode = (AddrMatchCode << 1);
UNUSED(TransferDirection);
}
2022-10-19 06:50 PM
Hi @Selim Coşkun Güler , I am following your code.
I was curious as to what the difference is between using SMBUS_STACK and HAL_SMBUS for SMBUS communication?
If possible could we have a discussion on an alternate platform that's more convenient?
2023-01-28 12:17 AM
@Selim Coşkun Güler One may think that SMBus HAL driver works the same way on all MCUs, but it does not. Take a look at AN4502-STM32 SMBus/PMBus Expansion Package for STM32Cube and the source code. Comments in code clearly indicate that Even ST engineers at times are not certain how to use HAL, many times direct registry operations are required. That is the reality. Moreover, this stack is not supported on some MCUs, e.g. F4 or G4. SMBus HAL is written like it was meant to reproduce hardware bugs described in ES0431 STM32G431xx/441xx device errata (2.11.5 Transmission stalled after first byte transfer). ST does not really support HAL and, what is far worse, release it untested (!). Has anyone ever seen HAL test suite? Frankly, it is a piece of... not a very good software.
My sincere advice: learn the hardware and write your driver from scratch. I am sure you will do much better job or at least will be able to produce something working, it is not that hard, hardware is well-thought. This is my conclusion and advice after several days lost trying to use SMBus HAL and studding reference manual RMxxxx like it was some holly text.