cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_SMBUS_Master_Transmit_IT XferOptions

GrantW
Associate II

Can someone explain which XferOptions should be used for which type of SMBUS message? This is what we get in stm32l4xx_hal_smbus.h:

/* List of XferOptions in usage of :

 * 1- Restart condition when direction change

 * 2- No Restart condition in other use cases

 */

#define SMBUS_FIRST_FRAME           SMBUS_SOFTEND_MODE

#define SMBUS_NEXT_FRAME            ((uint32_t)(SMBUS_RELOAD_MODE | SMBUS_SOFTEND_MODE))

#define SMBUS_FIRST_AND_LAST_FRAME_NO_PEC   SMBUS_AUTOEND_MODE

#define SMBUS_LAST_FRAME_NO_PEC        SMBUS_AUTOEND_MODE

#define SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC  ((uint32_t)(SMBUS_AUTOEND_MODE | SMBUS_SENDPEC_MODE))

#define SMBUS_LAST_FRAME_WITH_PEC       ((uint32_t)(SMBUS_AUTOEND_MODE | SMBUS_SENDPEC_MODE))

15 REPLIES 15

I have tried to modify the I2C clock frequency to 100K or 50K (according to the range setting given by the datasheet). The clock frequency of oscilloscope measurement SCL also conforms to the set value (50K or 100K), but the corresponding interval time (falling edge and SDA change) has not changed, which is still not in line with the specification.

My program USES the framework generated automatically by stm32cubeMX.Now there is no train of thought, please help, thank you very much!

Did you ever find out how the SMBus is handled properly?

I'm having to control a simple LED driver over SMBus, and I don't understand why we need some parts for the code to begin with:

	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
//	}

I have commented out lines 14-17. What is their purpose? Why are these needed, because like this, the LEDs do not light up. If I uncomment these lines, everything starts working again.

Best regards

HAL_SMBUS_Master_Transmit_IT() uses interrupts to send the data. It does NOT send the data before it returns to your code, it just starts the process. The lines you have commented out (lines 14-17) wait until the transfer is complete. I suspect that this code that you have shown is part of a function (i.e. not in main()). If you don't wait for the transfer to complete before exiting the function, your statusBuffer[] (which is allocated on the stack) will disappear and be overwritten during other function calls, thereby corrupting the data sent to the SMBus.

Hi,

You are right. It is actually running in a dedicated task that calls this function (only one time, i have if-gated the function call), and the task then waits 5 seconds before the task is executed again (but no function call due to the if-gating).

Your answer makes sense when I think about it. I will try to make the array global, so it is not destroyed. Just for testing purposes.

Thank you.

Best regards

OK, that is one way to solve the issue of the data getting corrupted before it is sent, though globals are often not the best answer. If you can guarantee that the function will never be called before the first transmit has completed, you can keep the declaration in the function and make it "static uint_t". That keeps the name out of the global name space. Even better, if that data never changes, make it "static const uint8_t" which puts it in Flash instead of RAM. Though I would think that LED settings would probably change over time, so stick with just "static uint8_t".

That said, and I realize you are probably just starting this code, but do you check for completion somewhere else in your code? Do you check for errors afterwards? If the only thing on your bus is your CPU and this one peripheral, and that IC can never send anything to you using the SMBus HOST NOTIFY protocol, then the transmit will *probably* always succeed. But I have seen glitches on the I2C bus lines cause the STM32 I2C peripheral to get in a state where it never actually sends any data (not even the START transition). Program defensively. Check status codes. Add timeouts and if the transmission hasn't completed, do something. Don't assume things will work.

You are absolutely right, this is just the first, initial version so I can get something going.

The data will change over time, and it is of course possible that the settings will need to be resent before the previous transaction is done. But I will be adding a little bit more code over time to get the feedback and all the stuff that goes with error handling.

The LED driver will never notify the host, there is no need.

Thanks.