Hello,
On Monday evening ISRs are still tough, but I think I have tracked down the problem:
I guess that the masters’s i2c stop condition is reported to the i2c ISR (beginning of i2c.cpp) by an i2c status @I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX@
lpc43xx_i2c.h
/** A STOP condition or repeated START condition has
* been received while still addressed as SLV/REC
* (Slave Receive) or SLV/TRX (Slave Transmit) */
#define I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX ((0xA0))
But this one isn’t caught in the ISR’s switch-case. Thus in the default case
default:
m_i2c->CONCLR = I2C_I2CONCLR_AAC | I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;
break;
the “Assert acknowledge Clear"-bit @I2C_I2CONCLR_AAC@ is set, and so from now on Pixy responds to requests with a NoACKs. I don’t know if the ISR is still being called, as I didn’t found an according status “addressed but rejected with a NACK”-in the lpc4300 user manual.
I guess Pixy stays in this status until @I2c::update()@ is called. As @I2C_I2CONCLR_AAC@ is set, @I2c::update()@ calls @I2c::startSlave()@ that re-enables ACKnowledges by setting the @I2C_I2CONSET_AA@ config bit and Pixy is back and online again.
@I2c::update()@ is called once after sending the blobs in function @blobsLoop()@ in progblobs.cpp. This is kind of compatible with my 20ms (one frame length) recovery from NACK observation.
Possible solution:
If we add a @case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX@ to the i2c ISR and just do a
case I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX:
m_i2c->CONSET = I2C_I2CONSET_AA;
m_i2c->CONCLR = I2C_I2CONCLR_SIC;
break;
as in the other cases (see also table 1001 “Slave Receiver mode” page 1130 in the LPC43xx manual), the Pixy i2c receive should be fine … hopefully.
A quick and dirty solution would be to add another @ser_getSerial()->update();@ just behind the two @handleRecv()@ calls in @blobsLoop()@. But that would be rather ugly.
I’m not really sure if the above is correct and as I don’t have the Keil MDK-ARM, I can’t test this on my own (looking forward to the gcc build environment).
It would be great if you could check and fix this.
I have spotted another potential issue (or just a cosmetic glitch) in the functions @Blobs::getBlock (…)@ and @Blobs::getCCBlock(…)@, the callbacks that fill the serial transmission queue, when it runs empty in the ISR:
if (m_mutex || m_blobReadIndex>=m_numBlobs) // we're copying, so no blocks for now....
{ // return a couple null words to give us time to copy
// (otherwise we may spend too much time in the ISR)
buf16[0] = 0;
buf16[1] = 0;
return 2;
}
It looks like that there are written 2 words to the transmission queue in order to keep the ISR quite and happy, i.e. to suppress unwanted expensive callbacks. But in fact only one word is written to the queue, as the unit of the return value is bytes not words.
So if you aren’t facing timing problem just remove one of the buf16 assignments to make it less confusing. If you really need both words, replace the 2 by a 4 in the return. As my i2c link is awfully slow, I’m happy with only one dummy null word.
Cheers,
Helmut