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
Bob S
Principal

I think those defines are not usually used except inside the SMBus STACK code. Where are you trying to use these, and with what SMBus function calls?

Usually you use the st_command_t structure, and in that structure you set the "query" member to something like "READ", "WRITE", "READ_OR_WRITE", "BLOCK_READ", etc. (search for "STM32_SMBUS_STACK_Defines" [EDIT: fixed spelling of search term] way down in Middlewares\ST\STM32_SMBus_Stack\in\stm32_SMBUS_stack.h. Then you call STACK_SMBUS_HostCommand(). Or pass an array of these commands to STACK_SMBUS_Init().

GrantW
Associate II

The simple answer is I'm trying to use the HAL_SMBUS_Master_Transmit_IT() call. The last argument is "uint32_t XferOptions" which seems to determine the message characteristics, so kind of important.

Specifically, I am sending READ_WORD and WRITE_WORD commands to a Texas Instruments fuel gauge chip (bq40z80) mainly to capture data from it.

I have looked at the stm32_SMBUS_stack code. I'm really not interested in trying to decipher that unless I am forced to. A user guide would be nice. Or if you are willing to answer lots of questions.

Bob S
Principal

> I'm really not interested in trying to decipher that unless I am forced to.

Wow... so you would rather spend HOW much time trying to figure out how to use a lower level function?

Quick snippet that I got from 10 or 20 minutes of looking at the sample SM and PMBus files from the ST app note code. Warning, this was typed, not copied from actual code. It may have typos and not be entirely correct. But you should get the gist.

st_command_t BatteryModeCmd = {
   0x03,   // SmartBattery "BatteryMode" command code
   READ_OR_WRITE,  // This command can read current mode or write (some) new mode bits
   3,   // WRITE sends 3 bytes: cmd code plus 16 bits of data
   2   // READ receives 2 bytes of data
};
 
SMBusStackHandleTypeDef smbusContext = { /*Your cfg data here*/ };
HAL_StatusTypeDef sts;
 
// This code presumes your fuel gauge response to the SmartBattery address 0x16
// Read current battery mode
sts = STACK_SMBUS_HostCommand( &smbusContext, &BatteryModeCmd, SMBUS_ADDR_SB, READ );
if ( sts == HAL_OK ) {
   // Wait for transaction to finish.  SMBus uses I2C interrupt functions
   while ( STACK_SMBUS_IsBusy(&smbusContext) ) {
      // twiddle your thumbs and check for timeout
   }
   uint8_t *pBuf = STACK_SMBUS_GetBuffer( &smbusContext );
   if ( pBuf != NULL ) {
      // 16-bit data is stored little-endian (LSB first).  This matches the STM32 byte order.
      uint16_t mode = *(uint16_t *)pBuf;
      printf( "Battery mode 0x%x\n", mode );
   }
   else {
      // Oops, some error or SMBus still busy
   }
}
else {
   // REPORT ERROR HERE
}

To write data, get the buffer pointer as above and write the 16-bit data using the same kind of cast as above. The call STACK_SMBUS_HostCommand() with WRITE instead of READ.

GrantW
Associate II

I appreciate your help Bob. I didn't think of the HAL_SMBUS functions as low-level. Am trying to get them to do something for me. Right now I am tracing through this call. Its returning HAL_ERROR. hsmbus3 has initialized successfully. We have tested the gas gauge with another device and it is responding.

uint32_t busStatus = HAL_SMBUS_IsDeviceReady(&hsmbus3, cmdAddr, 10U, 500U);

BThar.1
Associate II

i have the same doubt , please share if you found the solution .

JCai.2
Associate II

1.When I was debugging mlx90615, I used smbus to communicate. The reading function was as follows:

uint32_t I2C_Read_Cmd_Data (SMBUS_HandleTypeDef *hsmbus1, uint16_t chip, uint8_t *cmdBuffer, int32_t cmdBufferLen, uint8_t *dataBuffer, int32_t dataBufferLen)

{

 uint32_t ret_code = I2C_OK;

 if(HAL_SMBUS_Master_Transmit_IT(hsmbus1, (uint16_t)chip, (uint8_t*)cmdBuffer, 1, SMBUS_FIRST_FRAME)!= HAL_OK)

 {

while(1);

 }

while(HAL_SMBUS_GetState(hsmbus1) != HAL_SMBUS_STATE_READY);

 if(HAL_SMBUS_Master_Receive_IT(hsmbus1, (uint16_t)chip, (uint8_t*)dataBuffer, 3,SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) != HAL_OK)

 {

while(1);

 }

while(HAL_SMBUS_GetState(hsmbus1) != HAL_SMBUS_STATE_READY);

  return ret_code;

}

but the measurement waveform found that there was always no ack in the last byte (pec), as shown below

0693W000000UgI7QAK.jpg

Would like to ask where the problem is, please answer, thank you very much

2.As shown above, I have the following options for the last parameter(XferOptions) when using the HAL_SMBUS_Master_Transmit_IT function, the waveform will change when I modify it, I would like to ask how to configure this parameter, thank you!

/* 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))

/* List of XferOptions in usage of :

 * 1- Restart condition in all use cases (direction change or not)

 */

#define SMBUS_OTHER_FRAME_NO_PEC        (0x000000AAU)

#define SMBUS_OTHER_FRAME_WITH_PEC       (0x0000AA00U)

#define SMBUS_OTHER_AND_LAST_FRAME_NO_PEC   (0x00AA0000U)

#define SMBUS_OTHER_AND_LAST_FRAME_WITH_PEC  (0xAA000000U)

Bob S
Principal

First off - according to the SMBus spec, the PEC byte is ALWAYS NACKed to signal the end of the transmission (or the last data byte if not using PEC).

Second - go find AN4502 and look at the STACK_SMBUS_HostCommand() function. That function encapsulates all the code for the entire transfer. You can use that function instead of stitching together lower-level SMBus function calls yourself, or just see which flags it sets.

Bob:

Thank you very much�?

I have rewritten my code with reference to AN4502, I have a question, refer to the chip manual, after SCL produces a drop edge, there must be at least 300ns, SDA can be changed, but my measurement result is only 240ns, how should I set it here?

0693W000000UrUxQAK.png0693W000000UrV2QAK.png

Bob S
Principal

What clock freq to you have feeding the I2C peripheral, and what have you programmed into the I2C_TIMINGR register? If you came up with these values on your own you might try using CubeMX to generate a dummy project and see what values it programs into I2C_TIMINGR (make sure to configure the clock tree in CubeMX to match your code).