cancel
Showing results for 
Search instead for 
Did you mean: 

STMH755 and HAL_SMBUS_Master_Transmit_IT functionality

TOlli
Senior

Hi,

I've been trying to get the SMBus working as a master, writing a few commands to a slave device to control some LEDs.

I have managed to get the code working, but I don't quite understand why it is working.

The code I currently have (which fails):

	uint8_t statusBuffer[] = {
		TCA6507_COMMAND_AUTOINC_SELECT,	// Start from SELECT0 and auto-increment
		0x60,	// LED 6 and 7 should blink
		0x60,	// LED 6 and 7 should blink
		0x60	// LED 6 and 7 should blink
	};
 
	// Transmit the data to the device
	if (HAL_SMBUS_Master_Transmit_IT(&hsmbus2, TCA6507_ADDRESS, statusBuffer,
			sizeof(statusBuffer), SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK) {
		// production code should return an error
	}
 
//	// Wait for the transmission to end
//	while (HAL_SMBUS_GetState(&hsmbus2) != HAL_SMBUS_STATE_READY) {
//		// Wait here
//	}

Because I have rows 14-17 commented out, the code does not work and the LEDs do not light up. If I uncomment the lines, everything works as expected. But why do I have to wait there like that?

A little bit about the setup:

I'm using FreeRTOS and this is the only function in a task that is run every 5 seconds or so. Also the call to this function is gated with an if-clause and a boolean type variable, allowing it to be called only once.

	uint8_t bDone = 0;
	TCA6507_ControlDef ledControl;
 
	for(;;) {
		if (bDone == 0) {
			updateLedControl(ledControl);
			bDone = 1;
		}
		vTaskDelay(5000);
	}

So the call is made only once (just to make sure there are no issues with an ongoing transmission when a new call is made.

I only have the H7 and the TCA6507 connected together.

This is from an example for STM32091C_EVAL in the FW package for F0 V1.11.0

  if (HAL_SMBUS_Master_Transmit_IT(&SmbusHandle, DeviceAddr, &buffertx[0], /*sizeof(buffertx)*/2, SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) != HAL_OK)
  {
    return TSENSOR_ERROR;
  }
  while(HAL_SMBUS_GetState(&SmbusHandle) != HAL_SMBUS_STATE_READY);

It has the same kind of code (this is what I used as an example actually). But there is no explanation why that while() -loop is required after calling the transmit function.

Anyone have an answer?

Also, my interrupts for the SMBus are mostly empty, apart from CubeMX generated code:

void I2C2_EV_IRQHandler(void)
{
  /* USER CODE BEGIN I2C2_EV_IRQn 0 */
 
  /* USER CODE END I2C2_EV_IRQn 0 */
  HAL_SMBUS_EV_IRQHandler(&hsmbus2);
  /* USER CODE BEGIN I2C2_EV_IRQn 1 */
 
  /* USER CODE END I2C2_EV_IRQn 1 */
}
 
/**
  * @brief This function handles I2C2 error interrupt.
  */
void I2C2_ER_IRQHandler(void)
{
  /* USER CODE BEGIN I2C2_ER_IRQn 0 */
 
  /* USER CODE END I2C2_ER_IRQn 0 */
  HAL_SMBUS_ER_IRQHandler(&hsmbus2);
  /* USER CODE BEGIN I2C2_ER_IRQn 1 */
 
  /* USER CODE END I2C2_ER_IRQn 1 */
}

Since I don't need any error or event handling at this moment specifically. I think.

Also, I found this (it's not advertised among the regular Cube packages in CubeMX) from the ST website:

https://www.st.com/en/embedded-software/x-cube-smbus.html

Am I supposed to be using this? And if one looks inside a file called:

stm32_SMBUS_stack.c , on row 1751 is this:

      result = HAL_SMBUS_Master_Transmit_IT( pStackContext->Device, address, com_buffer, size, xFerOptions );
      if (result != HAL_OK )
      {
        pStackContext->StateMachine |= SMBUS_SMS_ERROR;
      }

But now, the while() loop we saw previously is not there. How come?

Best regards

2 REPLIES 2
DFuchs
Associate III

Hi,

the TCA6507 looks like a I2C device to me. Did you connect the SMBA of STM32 with EN of the TCA6507?

Did you try to use I2C functions?

Kind regards

Daniel

Hi,

TCA6507 can operate in both modes, SMbus and I2C. I haven't tried I2C functions since the SMBus functions seem to work.

I'm just wondering about the questions I had in the original post:

  1. Why is the while-loop required?
  2. Should I be using the stack primarily even though I found it only by accident?

In my boot code, I do enable the device through a GPIO.

Best regards​