Content originally posted in LPCWare by mathseng on Thu Oct 17 12:59:23 MST 2013
Hi Rob,
Thanks. After studying your code, I remembered that I had not put a taskYIELD() into my timeout loop. (I meant to, but forgot, truly :( )
I didn't feel the need for a semaphore since I am only calling the I2C code from a FreeRTOS task - so conflict is averted by only looping in that task and then delaying to allow other tasks to run if there is nothing pending.
In I2CStart(), I have a hardcoded delay, now reduced to 0xffff - if the state machine has not started in that time, there is definitely a failure, so I bug out.
The ONLY other spin loop, or timeout is in i2CEngine. My I2C code is not yet ready for publication, but here is the code for Engine.
Note: in case 0x50 I chose to test RdIndex+1 against I2CReadLength rather than test RdIndex against I2CReadLength-1, because if for some unknown reason I2CReadLength is 0, the system can die horribly.
Regards,
Bill
<code>
//-----------------------------------------------------------------------------
// External callbacks
// This code uses external callbacks, to allow for unchanged code use under
// FreeRTOS or stand-alone.
// Requirements:
// TimerReset - call with number of milliSeconds before timer times out
// TimerIsTimedOut - returns non-Zero if the timer has timed out
// Yield - IF and ONLY IF there are other tasks which need to be serviced
// then yield to them, else continue in spin loop.
// This prevents this task from starving the other tasks.
//-----------------------------------------------------------------------------
extern void TimerReset(uint32_t timeLeft);
extern int TimerIsTimedOut(void);
extern void Yield(void);
uint32_t I2CEngine(void)
{
I2CMASTERSTATE currentState = I2CMasterState;
I2CMasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;
uint32_t result = FALSE;
uint32_t done = FALSE;
TimerReset(2);
if (I2CStart())
{
while (!done && !TimerIsTimedOut())
{
switch (I2CMasterState)
{
case I2C_RX_COMPLETE:
case I2C_TX_COMPLETE:
result = TRUE;
done = TRUE;
break;
case I2C_FAIL:
case I2C_ARBITRATION_LOST:
done = TRUE;
break;
default:
break;
}
if (currentState != I2CMasterState)
{
currentState = I2CMasterState;
TimerReset(2);
}
Yield();
}
}
I2CStop();
return (result);
}
</code>