Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 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.

### 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);