Skip to content

Commit cc094f5

Browse files
authored
Merge pull request stm32duino#306 from LMESTM/i2c_slave
I2C Slave : rework slave receive data sequence
2 parents e17c30e + c431305 commit cc094f5

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

cores/arduino/stm32/twi.c

+53-9
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@
7575

7676
#define SLAVE_MODE_TRANSMIT 0
7777
#define SLAVE_MODE_RECEIVE 1
78+
#define SLAVE_MODE_LISTEN 2
79+
7880

7981
/**
8082
* @}
@@ -288,6 +290,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
288290
HAL_I2C_Init(handle);
289291

290292
obj->isMaster = master;
293+
/* Initialize default values */
294+
obj->slaveRxNbData = 0;
295+
obj->slaveMode = SLAVE_MODE_LISTEN;
291296
}
292297

293298
/**
@@ -411,9 +416,10 @@ i2c_status_e i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint16_t size)
411416
// Check the communication status
412417
for(i = 0; i < size; i++) {
413418
obj->i2cTxRxBuffer[i] = *(data+i);
414-
obj->i2cTxRxBufferSize++;
415419
}
416420

421+
obj->i2cTxRxBufferSize = size;
422+
417423
return I2C_OK;
418424
}
419425

@@ -536,8 +542,6 @@ void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, ui
536542

537543
if(AddrMatchCode == hi2c->Init.OwnAddress1) {
538544
if(TransferDirection == I2C_DIRECTION_RECEIVE) {
539-
540-
obj->i2cTxRxBufferSize = 0;
541545
obj->slaveMode = SLAVE_MODE_TRANSMIT;
542546

543547
if(obj->i2c_onSlaveTransmit != NULL) {
@@ -546,9 +550,12 @@ void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, ui
546550
HAL_I2C_Slave_Sequential_Transmit_IT(hi2c, obj->i2cTxRxBuffer,
547551
obj->i2cTxRxBufferSize, I2C_LAST_FRAME);
548552
} else {
553+
obj->slaveRxNbData = 0;
549554
obj->slaveMode = SLAVE_MODE_RECEIVE;
550-
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, obj->i2cTxRxBuffer,
551-
I2C_TXRX_BUFFER_SIZE, I2C_LAST_FRAME);
555+
/* We don't know in advance how many bytes will be sent by master so
556+
* we'll fetch one by one until master ends the sequence */
557+
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, &(obj->i2cTxRxBuffer[obj->slaveRxNbData]),
558+
1, I2C_NEXT_FRAME);
552559
}
553560
}
554561
}
@@ -561,19 +568,56 @@ void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, ui
561568
*/
562569
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
563570
{
564-
uint8_t nbData = 0;
565571
i2c_t *obj = get_i2c_obj(hi2c);
566572

573+
/* Previous master transaction now ended, so inform upper layer if needed
574+
* then prepare for listening to next request */
567575
if((obj->i2c_onSlaveReceive != NULL) &&
568576
(obj->slaveMode == SLAVE_MODE_RECEIVE)) {
569-
nbData = I2C_TXRX_BUFFER_SIZE - obj->handle.XferSize;
570-
if(nbData != 0) {
571-
obj->i2c_onSlaveReceive(obj->i2cTxRxBuffer, nbData);
577+
if(obj->slaveRxNbData != 0) {
578+
obj->i2c_onSlaveReceive(obj->i2cTxRxBuffer, obj->slaveRxNbData);
572579
}
573580
}
581+
obj->slaveMode = SLAVE_MODE_LISTEN;
582+
obj->slaveRxNbData = 0;
574583
HAL_I2C_EnableListen_IT(hi2c);
575584
}
576585

586+
/**
587+
* @brief Slave RX complete callback
588+
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
589+
* the configuration information for the specified I2C.
590+
* @retval None
591+
*/
592+
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
593+
{
594+
i2c_t *obj = get_i2c_obj(hi2c);
595+
/* One more byte was received, store it then prepare next */
596+
if(obj->slaveRxNbData < I2C_TXRX_BUFFER_SIZE) {
597+
obj->slaveRxNbData++;
598+
} else {
599+
printf("ERROR: I2C Slave RX overflow\n");
600+
}
601+
/* Restart interrupt mode for next Byte */
602+
if(obj->slaveMode == SLAVE_MODE_RECEIVE) {
603+
HAL_I2C_Slave_Sequential_Receive_IT(hi2c, &(obj->i2cTxRxBuffer[obj->slaveRxNbData]),
604+
1, I2C_NEXT_FRAME);
605+
}
606+
}
607+
608+
/**
609+
* @brief Slave TX complete callback
610+
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
611+
* the configuration information for the specified I2C.
612+
* @retval None
613+
*/
614+
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
615+
{
616+
i2c_t *obj = get_i2c_obj(hi2c);
617+
/* Reset transmit buffer size */
618+
obj->i2cTxRxBufferSize = 0;
619+
}
620+
577621
/**
578622
* @brief I2C error callback.
579623
* @note In master mode, the callback is not used because the error is reported

cores/arduino/stm32/twi.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,13 @@ struct i2c_s {
9191
#if !defined(STM32F0xx) && !defined(STM32L0xx)
9292
IRQn_Type irqER;
9393
#endif //!defined(STM32F0xx) && !defined(STM32L0xx)
94-
uint8_t slaveMode;
94+
volatile uint8_t slaveMode;
9595
uint8_t isMaster;
96+
volatile int slaveRxNbData; // Number of accumulated bytes received in Slave mode
9697
void (*i2c_onSlaveReceive)(uint8_t *, int);
9798
void (*i2c_onSlaveTransmit)(void);
98-
uint8_t i2cTxRxBuffer[I2C_TXRX_BUFFER_SIZE];
99-
uint8_t i2cTxRxBufferSize;
99+
volatile uint8_t i2cTxRxBuffer[I2C_TXRX_BUFFER_SIZE];
100+
volatile uint8_t i2cTxRxBufferSize;
100101
};
101102

102103
///@brief I2C state

0 commit comments

Comments
 (0)