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>