Skip to content
Snippets Groups Projects
i2c_hack.md 1.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • yannick's avatar
    yannick committed
    # STM32 I2C Slave dirty trick
    
    ## Context
    The STM32L451 HAL doesn't directly support variable length message RX/TX. 
    
    ### Default HAL behavior
    The defaut behavior is described in the GraphViz render.
    ![](./i2c_hack.svg)
    
    ### Modification
    ```C
    void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) {
      /* Slave matched his address */
      if (TransferDirection != 0) {
    	  /* I2C Transmit buffer */
    	  CSKB_I2C_Dir = I2C_TX; // Save in a global the current direction
    	  uint8_t framesize = (CSKB_I2C_NXT_FrameSize == 0) ? I2C_BUFFER_SIZE : CSKB_I2C_NXT_FrameSize;
    	  if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, (uint8_t *)CSKB_I2C_TX_BUFFER, framesize, I2C_FIRST_AND_LAST_FRAME) != HAL_OK) {
    		/* Transfer error in transmission process */
    		Error_Handler();
    	  }
      } else {
    	  CSKB_I2C_Dir = I2C_RX; // Save in a global the current direction
          /* I2C Receive on the rx buffer BUT we don't know the size beforehand */
    	  if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, (uint8_t *)CSKB_I2C_RX_BUFFER, I2C_BUFFER_SIZE, I2C_FIRST_AND_LAST_FRAME) != HAL_OK) {
    		/* Transfer error in reception process */
    		Error_Handler();
    	  }
      }
    }
    ```
    Once we have those information we can try to use the final callback to handle everything we need.
    ```C
    void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
    {
    	/* Handling here incomplete RX/TX with dirty hack */
    	if (CSKB_I2C_Dir == I2C_TX) {
    		CSKB_I2C_TX_Complete = 1;
    		CSKB_I2C_TX_Size = (CSKB_I2C_NXT_FrameSize == 0) ? I2C_BUFFER_SIZE - hi2c->XferSize : CSKB_I2C_NXT_FrameSize - hi2c->XferSize;
    	} else if (CSKB_I2C_Dir == I2C_RX) {
    		CSKB_I2C_RX_Complete = 1;
    		CSKB_I2C_RX_Size = I2C_BUFFER_SIZE - hi2c->XferSize;
    	}
    	CSKB_I2C_Dir = I2C_NONE;
    }
    ```
    For some reason it appears that XferSize member of the I2C handle has the remaining count of byte (starting from the buffer size declared while calling HAL_I2C_Slave_Seq_Receive_IT or HAL_I2C_Slave_Seq_Transmit_IT);