Author Topic: flushing IIC  (Read 9230 times)

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
flushing IIC
« on: September 23, 2010, 01:53:49 PM »
Hi Mark,
  I have 3 IIC devices connected to 1 port and have a routine deciding which routine reads the incoming string .  I understand that there should never be a reason for flushing the IIC, but as the 3 devices reads in different lengths of data I want to make sure that there is nothing ready to be read when the port is idle. Is it desable to do the following:

    unsigned char   Clear[2];                 
    while ( fnRead( PortID, Clear, 1 ))
        ;

Thanks
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: flushing IIC
« Reply #1 on: September 24, 2010, 09:06:33 PM »
Hi Neil

1) fnRead() is ignored when there are no I2C input messages (that is, when an I2C bus read is still in operation). The reason is to avoid a part of a message from being read before the complete message is ready.
2) fnMsgs() returns the number of bytes in the input buffer when there is a complete message waiting (before the message is complete it returns 0).
3) Therefore reading the input has no have effect until there is a complete message ready.
4) Reading just one byte will read one byte of the waiting message but reduce the message count also by 1. This means that reads should always be performed of the size of the waiting message - reading less will result in remaining input still being there but no further reads being allowed until the next message is complete - thus the loop to read one byte at a time will fail to clear more than one byte of a waiting message(!!)

This means that only complete messages should be read and also only then when there is a complete message ready (fnMsg() > 0).

There is no flush operation available and, assuming no operation error which can leave bytes in the input buffer without a message count value associated with then, there should be no need to flush the input. If the case arises when there is no message count but the input still really needs to be flushed it would be necessary to add a flush command that unconditionally removes everything.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: flushing IIC
« Reply #2 on: September 24, 2010, 09:45:00 PM »
Hi Mark,
  What is defined as a message? Is it simply the number of bytes in the buffer when the bus is idle?
I know when the bus is idle, so I can check if there is bytes there to be flushed.  So would I do the following?

//bus idle
int NoBytes=fnMsg();
while(NoBytes--)
 fnRead( PortID, Clear, 1 )

Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: flushing IIC
« Reply #3 on: September 24, 2010, 10:05:40 PM »
Hi Neil

A message is the number of bytes which the master reads. The length is determined by the master, so is known.

You must however avoid reading just 1 byte when NoBytes is > 1 since it will otherwaise leave bytes in the buffer and so cause corruption to later messages (the length will include the remaining bytes).

You have to read
fnRead( PortID, Clear, NoBytes); so Clear also has to be large enough for the worst case.

Regards

Mark

Offline neil

  • Sr. Member
  • ****
  • Posts: 438
    • View Profile
Re: flushing IIC
« Reply #4 on: September 24, 2010, 10:40:34 PM »
Hi Mark,
  Thanks for the reply.

If there are 2 slaves and 2 reads are performed , one on each with say first requesting 5 bytes and the second 10, would there be 2 messages in the buffer (if there wasnt a read in the task) with 5 bytes and 10 bytes?

If so, am I better doing a fnMsg() first to see how many characters in a message , then read this amount of bytes? Then continue doing a fnMsg() until 0 returned?

Thanks
Neil

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: flushing IIC
« Reply #5 on: September 24, 2010, 11:01:13 PM »
Hi Neil

If there are two received message waiting, fnMsgs() will return the total length of them both (15 in your example).
Unfortunately, if you now read 15 bytes you will read both messages but there will in fact be still 1 message left since the read decrements the message counter by only 1. fnMsgs() will then return 0 since it returns the length of the characters waiting - even though the message counter is 1. It will thus cause problems.

This means that the total number of bytes read by the master needs to be read in the correct sizes to ensure that everything works correctly.

Assuming you were polling fnMsgs() while the two slave ready were taking place:
- initially fnMsgs() would return 0 since the first message has not yet been fully received.
- then it will return 5 since the first message is ready and has this content length
- later it will return 15 once the second is also ready.

Since it is know that the master reads 5 and then 10, the reads also need to match. A single read of 15 would cause the problem as explained above.

Due to the nature of the master operation it would also not be advisable to flush the queues (by adding such a routine) when the transfers are still in operation. This is because queue content is also controlling the transfers - if it were to be reset during this it could result in problems in the interrupt driven driver.

Therefore it is best to ensure that all expected reception is read from the input when it is available, that all reads use the expected message size if multiple reads are performed together, after which the queues will be empty. Since this is master mode of operation you will never receive any data from the slaves that you didn't explicitly request.

Regards

Mark