Question
How HAL I2C slave works?
I'm trying to do I2C Slave but I totally don't understand how to implement it using HAL.
I have a good record of data in Slave.
But but when I use HAL_I2C_Slave_Sequential_Transmit_IT I get a HAL_BUSY error.
What should I do? I looked at the examples but it didn't help me.
enum class State { stop, waiting, getRegisterAddress, getData, sendData };
State transferState = State::stop;
uint8 registerAddress = 0;
uint8 transmitBuffer = 0;
uint8 receiveBuffer = 0;
bool(*registerReadEvent)(uint16 address, uint8 &data);
bool(*registerWriteEvent)(uint16 address, uint8 data);
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8 direction, uint16 addrMatchCode) {
switch (direction) {
case I2C_DIRECTION_TRANSMIT:
transferState = State::getRegisterAddress;
if (HAL_I2C_Slave_Sequential_Receive_IT(hi2c, &receiveBuffer, 1, I2C_FIRST_FRAME) != HAL_OK) {
Error();
}
break;
case I2C_DIRECTION_RECEIVE:
transferState = State::sendData;
if (!registerReadEvent(registerAddress, transmitBuffer)) {
Error();
}
if (HAL_I2C_Slave_Sequential_Transmit_IT(hi2c, &transmitBuffer, 1, I2C_LAST_FRAME) != HAL_OK) {
// Error here!!! (HAL_BUSY)
Error();
}
break;
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
switch (transferState) {
case State::getRegisterAddress:
registerAddress = receiveBuffer;
transferState = State::getData;
if (HAL_I2C_Slave_Sequential_Receive_IT(hi2c, &receiveBuffer, 1, I2C_FIRST_FRAME) != HAL_OK) {
Error();
}
break;
case State::getData:
if (!registerWriteEvent(registerAddress, receiveBuffer)) {
Error();
}
if (HAL_I2C_Slave_Sequential_Receive_IT(hi2c, &receiveBuffer, 1, I2C_FIRST_FRAME) != HAL_OK) {
Error();
}
break;
}
}
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) {
HAL_I2C_EnableListen_IT(hi2c); // Restart
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) {
if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) {
Error();
}
}
void main() {
static uint8 memoryArray[0xFF] = { 0 };
registerReadEvent = [](uint16 address, uint8 &data) {
data = memoryArray[address];
return true;
};
registerWriteEvent = [](uint16 address, uint8 data) {
memoryArray[address] = data;
return true;
};
// Start Listen
HAL_I2C_EnableListen_IT(&hi2c1);
transferState = State::waiting;
}