Skip to main content
Graduate
May 15, 2024
Question

Struggling to receive messages on SMBUS

  • May 15, 2024
  • 1 reply
  • 2721 views

I am studying the SMBUS stack code to understand how it works. My system has a smart battery. The battery periodically emits two messages intended for the charger (charging voltage and charging current). My software is the host. Sending commands to the battery is working just fine. As an exercise I am trying to receive the two charger messages. Following (more or less) the ST code I do this:

- Set own address to the expected charger address
- Call HAL_SMBUS_EnableListen_IT()
- enables ADDR interrupt, I guess
- On ADDR interrupt, AddrCallback is called
- Call HAL_SMBUS_Slave_Receive_IT() to receive one byte (the command ID)
- On completion, SlaveRxCpltCallback() is called
- Call HAL_SMBUS_Slave_Receive_IT() to receive remaining bytes of the command
- On completion, SlaveRxCpltCallback() is called a second time
- Call HAL_SMBUS_EnableListen_IT() to set up for the next command

This apparently works perfectly for the first command. I get the ADDR interrupt, the command byte and the data bytes, and I see STOP on the bus. But then... For the second command, about 1s later, I don't see the ADDR interrupt. I can see that the bus is held low for a bit, stretching the clock, and then I get the error interrupt.

I'll have to add some code to log the register values upon each interrupt, but was hoping for some insight here. I realise this is a bit vague, but what might I be missing? I have looked at the reference manual and found the interaction of some of the control bits a little unclear. I note that the SBC bit has been set when it wasn't previously, but clearing it after the first command is done has no effect.

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    May 15, 2024

    Hello @unicyclebloke 

     

    Could you please capture the traffic data on the bus using a logic analyzer and send it to us?

    Additionally, could you confirm whether the address is retransmitted by the Master for the second command?

    Graduate
    May 15, 2024

    Thank you for your response. I can confirm that the address is retransmitted for the second command. 

    For comparison, this capture shows the two messages when I use the ST SMBUS stack code with own address set to 0x12 (7-bit address 0x09). This is working fine.

    With-ST-stack.png

    This image shows the two messages when I use my own code to intercept the ADDR interrupt callback and so on as described. The first one appear to do the right thing. The second (and subsequent) message fails. The address appears on the bus but ADDR interrupt callback is not called. It seems that the interrupt does not occur at all. So the clock is held low for 25ms (the configured timeout), and then the next byte appears (presumably when the clock is released), but is NAKed.

     

    With-own-code.png

    Message2-with-own-code-a.PNG

    I'm pretty sure that the ADDRI flag is set to allow the address interrupt, but suspect there is some other settings which I have not got quite right. The initial set up is fine, but perhaps there is a side-effect of receiving a message which I have not dealt with correctly.

    Clearly the ST stack works well enough. I would like to understand the internals because, unfortunately, the callback model used is a bit convoluted and inconsistent with the C++ API I have created for the I2C/SMBUS peripheral. In any case, I only need a small subset of SMBUS features. Sadly, I found the code rather complicated and could not easily identify just the parts I need.

    Thanks again.

    Technical Moderator
    May 15, 2024

    I see that the address is acknowledged by the slave. Check if the address match flag is set in the SR register. If yes, insert a breakpoint in the SMBUS IRQ Handler to observe the behavior during the address interrupt event.