2020-06-17 03:33 PM
target CPU: STM32F427IG
I set up STM32F427IG as master receiver via DMA.
I wait on "DMA_GetFlagStatus(I2Cx_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG" to figure out if I received what was sent.
After running for 20 minutes or so, I2Cx_RX_DMA_TCFLAG flag does not get set within the timeout period I had defined.
When I2Cx_RX_DMA_TCFLAG does not get set within my timeout period, I want to cancel this transaction. To terminate this transaction I believe I need to send Nack to the transmitter and then generate stop condition.
So far my attempts failed.
Based on TRM, this is what I do:
if(TimeOut ) {
I2C_DMACmd(I2Cx, DISABLE);
DMA_Cmd(I2Cx_DMA_STREAM_RX, DISABLE);
(void)I2C_ReceiveData(I2Cx);
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);
I2C_GenerateSTOP(I2Cx, ENABLE);
(void)I2C_ReceiveData(I2Cx);
}
How could I achieve my goal?
thank you in advance
2020-06-17 03:42 PM
btw, I see that I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) is true, so STM gets the flag that it is in master-receiver mode.
2020-06-20 12:27 AM
I2C peripheral has a software reset bit, which resets the whole internal state machine, but doesn't reset the configuration.
2020-06-30 10:09 AM
Thank you, Piranha.
I am utilizing s/w reset bit as you suggested. and to make life easy, I commented out all I2C related receive or transmit calls on slave MCU.
when timeout occurs below, I generate stop condition and then call I2C_SoftwareResetCmd.
then I check busy flag. result = reset, meaning not busy
then I check master/slave mode flag, result = reset, meaning slave.
so, the flags indicate success to me.
right after, I want to reinit I2C and generate start condition. It fails, please see the second code snippet.
case MS_RX_WAIT_RX_EVENT:
while( (!DMA_GetFlagStatus(I2Cx_DMA_STREAM_RX, I2Cx_RX_DMA_TCFLAG)) &&
(TimeOut != 0) ){};
if(TimeOut == 0) {
i2c_state = MS_GENERATE_START;
I2C_DMACmd(I2Cx, DISABLE);
DMA_Cmd(I2Cx_DMA_STREAM_RX, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);
I2C_SoftwareResetCmd(I2Cx, ENABLE);
TimeOut = 1; // do we need to give time to reset to complete? any flag to check?
while(TimeOut != 0){}
FlagStatus status = I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY); // reset
status = I2C_GetFlagStatus(I2Cx, I2C_FLAG_MSL); // reset
return;
...
I2C_Cmd(I2Cx, ENABLE);
I2C_DeInit(I2Cx);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = SLAVE_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
I2C_Init(I2Cx, &I2C_InitStructure);
I2C_GenerateSTART(I2Cx, ENABLE);
TimeOut = 200;
i2c_state++;
case MS_MODE_TX_SELECTED:
while((!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) &&
(TimeOut !=0))
{};
if(TimeOut == 0) // rework
{
...
any feedback on why generating start condition fails, why I2C_EVENT_MASTER_MODE_SELECT does not happen.