How is the group doing interrupt driven SPI or I2C? It seems like we
either need to wait for BF to go true inside the ISR (not a great idea) or
have a really complicated state machine where each SIP/I2C device is
handled by several states. It then appears you'd need an input FIFO and an
output FIFO for each device. And how wide should the FIFO be? For example,
the MAX3100 UART does 16 bits per transaction. Some devices have variable
widths (ie, a memory chip may use the first few bytes to set the address,
then an unlimited number of bytes can be read from the chip). If the FIFO
width does not match the width of the transaction, how does the ISR know
when to drive chip select high or low? On I2C, if the FIFO just holds
data, how do you know when to put in a start, stop, ack, etc.? It SEEMS to
get messy very quickly.
So... how are people doing interrupt driven SPI and I2C?
> how are people doing interrupt driven SPI and I2C?
I haven't come across a situation that needed it. Generally, the
ratio between CPU speed and SPI/I2C bus speed is small enough that an
interrupt-driven master SPI or I2C doesn't buy you anything, since
you'll use more CPU cycles handling an interrupt on every byte than
you will busy-waiting on the completion of the transaction.
> On Fri, 4 Apr 2008, Harold Hallikainen wrote:
>
>> how are people doing interrupt driven SPI and I2C?
>
> I haven't come across a situation that needed it. Generally, the
> ratio between CPU speed and SPI/I2C bus speed is small enough that an
> interrupt-driven master SPI or I2C doesn't buy you anything, since
> you'll use more CPU cycles handling an interrupt on every byte than
> you will busy-waiting on the completion of the transaction.
>
> --
> John W. Temples, III
Thanks for the comments! The main problem here is that I ran out of UARTs,
so we added a MAX3100 SPI UART. This has a pretty small fifo (I think it's
8 bytes), so you have to get to it pretty frequently. This worked fine at
first (when designed 5 to 6 years ago). Due to creeping featurism, the
main loop is now not guaranteed to get around in time when using polling.
It would be nice if the MAX3100 would do RTS/CTS handshaking on its own so
it's stop the host from sending when the fifo got full, but, instead,
RTS/CTS is under control of the PIC over SPI. If I have time to tell the
host not to send, I have time to just get the data and stuff it in my own
fifo. So... I'm doing SPI and I2C in an ISR. I'm using a timer interrupt
to call the ISR and a big state machine to deal with the various devices.
Right now the ISR handles a complete SPI or I2C transaction in a single
state. Since each transaction (from CS low to CS high) involves a few
bytes, I have some wait loops where I wait for BF to go high. During that
time, I'm calling other ISRs to make sure I don't miss something there.
It's really not very pretty.
In future hardware designs I'm pushing for any SPI I/O devices to do their
own buffering and handshake to the outside world so I can just poll them
when I'm ready. Stuff that has to be dealt with in an interrupt because it
does not have sufficient buffering on its own will be some sort of
parallel interface so I can read or write it in a couple instructions with
no wait loops.
> Thanks for the comments! The main problem here is that I ran out of UARTs,
> so we added a MAX3100 SPI UART. This has a pretty small fifo (I think it's
> 8 bytes), so you have to get to it pretty frequently.
Yeah, but it's an icky device. I did an 8 port device several years ago.
I'd use AVRs with usarts for the ports today, MUCH smarter, more buffer, etc.
>
> > On Fri, 4 Apr 2008, Harold Hallikainen wrote:
> >
> >> how are people doing interrupt driven SPI and I2C?
> >
> > I haven't come across a situation that needed it. Generally, the
> > ratio between CPU speed and SPI/I2C bus speed is small enough that an
> > interrupt-driven master SPI or I2C doesn't buy you anything, since
> > you'll use more CPU cycles handling an interrupt on every byte than
> > you will busy-waiting on the completion of the transaction.
> >
> > --
> > John W. Temples, III
>
>
> Thanks for the comments! The main problem here is that I ran out of UARTs,
> so we added a MAX3100 SPI UART. This has a pretty small fifo (I think it's
> 8 bytes), so you have to get to it pretty frequently. This worked fine at
> first (when designed 5 to 6 years ago). Due to creeping featurism, the
> main loop is now not guaranteed to get around in time when using polling.
> It would be nice if the MAX3100 would do RTS/CTS handshaking on its own so
> it's stop the host from sending when the fifo got full, but, instead,
> RTS/CTS is under control of the PIC over SPI. If I have time to tell the
> host not to send, I have time to just get the data and stuff it in my own
> fifo. So... I'm doing SPI and I2C in an ISR. I'm using a timer interrupt
> to call the ISR and a big state machine to deal with the various devices.
> Right now the ISR handles a complete SPI or I2C transaction in a single
> state. Since each transaction (from CS low to CS high) involves a few
> bytes, I have some wait loops where I wait for BF to go high. During that
> time, I'm calling other ISRs to make sure I don't miss something there.
> It's really not very pretty.
>
> In future hardware designs I'm pushing for any SPI I/O devices to do their
> own buffering and handshake to the outside world so I can just poll them
> when I'm ready. Stuff that has to be dealt with in an interrupt because it
> does not have sufficient buffering on its own will be some sort of
> parallel interface so I can read or write it in a couple instructions with
> no wait loops.
>
> Meanwhile, back to debugging the ISR!
>
> Harold
One of the beuties of going FULLY state machine is that the state
transition and monitor functions can be very short and allow polling in
the state machine engine itself or via a back ground task or as a seperate
parallel state machine. The ISR become trivial merely used to service I/O
rather than understand and comply with complex time comsuming protocols.
Of course this redesign may not be practicle at this stage in your
products life, but since you state you are looking at a redesign in the
future, a different software approach on the same hardware may get you
much more milage.
The thing to be weary of is trying to keep the state machine simple
(some number of events and states) by having complex state transition
and monitor functions. This tends to hamper the true benefits of a REAL
state machine design and brings back the ugly problems you seem to be
facing now.
There is software out there that will help you create complex state
machines with minimum effort. It's like using a CAD package to design a
PCB, you wouldn't want to waste your time with paper an pencil when there
is good software that can do the work for you reliably and produce
something that is easily maintainable.
On Sat, Apr 5, 2008 at 3:31 AM, John Temples <spam_OUTpiclist3TakeThisOuTxargs.com> wrote:
> On Fri, 4 Apr 2008, Harold Hallikainen wrote:
>
> > how are people doing interrupt driven SPI and I2C?
>
> I haven't come across a situation that needed it. Generally, the
> ratio between CPU speed and SPI/I2C bus speed is small enough that an
> interrupt-driven master SPI or I2C doesn't buy you anything, since
> you'll use more CPU cycles handling an interrupt on every byte than
> you will busy-waiting on the completion of the transaction.
>
Just wondering how to you deal with time out issue? For example,
if you have SPI connected ADC and for some reason the communication
is down due to excess noise (say during EMC testing), you want it
to fail gracefully and use the last result instead of waiting forever.
>> On Fri, 4 Apr 2008, Harold Hallikainen wrote:
>>
>>
>>> how are people doing interrupt driven SPI and I2C?
>>>
>> I haven't come across a situation that needed it. Generally, the
>> ratio between CPU speed and SPI/I2C bus speed is small enough that an
>> interrupt-driven master SPI or I2C doesn't buy you anything, since
>> you'll use more CPU cycles handling an interrupt on every byte than
>> you will busy-waiting on the completion of the transaction.
>>
>> --
>> John W. Temples, III
>>
>
>
> Thanks for the comments! The main problem here is that I ran out of UARTs,
> so we added a MAX3100 SPI UART. This has a pretty small fifo (I think it's
> 8 bytes), so you have to get to it pretty frequently. This worked fine at
> first (when designed 5 to 6 years ago). Due to creeping featurism, the
> main loop is now not guaranteed to get around in time when using polling.
> It would be nice if the MAX3100 would do RTS/CTS handshaking on its own so
> it's stop the host from sending when the fifo got full, but, instead,
> RTS/CTS is under control of the PIC over SPI. If I have time to tell the
> host not to send, I have time to just get the data and stuff it in my own
> fifo. So... I'm doing SPI and I2C in an ISR. I'm using a timer interrupt
> to call the ISR and a big state machine to deal with the various devices.
> Right now the ISR handles a complete SPI or I2C transaction in a single
> state. Since each transaction (from CS low to CS high) involves a few
> bytes, I have some wait loops where I wait for BF to go high. During that
> time, I'm calling other ISRs to make sure I don't miss something there.
> It's really not very pretty.
>
> In future hardware designs I'm pushing for any SPI I/O devices to do their
> own buffering and handshake to the outside world so I can just poll them
> when I'm ready. Stuff that has to be dealt with in an interrupt because it
> does not have sufficient buffering on its own will be some sort of
> parallel interface so I can read or write it in a couple instructions with
> no wait loops.
>
> Meanwhile, back to debugging the ISR!
>
> Harold
>
>
>
Harold, maybe you can speed up the oscillator..? I was astonished one
day when I increased speed
from 16 to 20Mhz, and suddenly things began to FIT.
Yes, I used that Max3100 UART- in fact I used two. I used the pin-change
interrupt. Are you having
strange problems with the MAX3100s? The problem is that the oscillator
must be driven a certain way;
I THINK I had to cut down the drive, because overdriving it caused the
uart to stumble when receiving
bytes...
>> On Fri, 4 Apr 2008, Harold Hallikainen wrote:
>>
>>
>>> how are people doing interrupt driven SPI and I2C?
>>>
>> I haven't come across a situation that needed it. Generally, the
>> ratio between CPU speed and SPI/I2C bus speed is small enough that an
>> interrupt-driven master SPI or I2C doesn't buy you anything, since
>> you'll use more CPU cycles handling an interrupt on every byte than
>> you will busy-waiting on the completion of the transaction.
>>
>> --
>> John W. Temples, III
>>
>
>
> Thanks for the comments! The main problem here is that I ran out of UARTs,
> so we added a MAX3100 SPI UART. This has a pretty small fifo (I think it's
> 8 bytes), so you have to get to it pretty frequently. This worked fine at
> first (when designed 5 to 6 years ago). Due to creeping featurism, the
> main loop is now not guaranteed to get around in time when using polling.
> It would be nice if the MAX3100 would do RTS/CTS handshaking on its own so
> it's stop the host from sending when the fifo got full, but, instead,
> RTS/CTS is under control of the PIC over SPI. If I have time to tell the
> host not to send, I have time to just get the data and stuff it in my own
> fifo. So... I'm doing SPI and I2C in an ISR. I'm using a timer interrupt
> to call the ISR and a big state machine to deal with the various devices.
> Right now the ISR handles a complete SPI or I2C transaction in a single
> state. Since each transaction (from CS low to CS high) involves a few
> bytes, I have some wait loops where I wait for BF to go high. During that
> time, I'm calling other ISRs to make sure I don't miss something there.
> It's really not very pretty.
>
> In future hardware designs I'm pushing for any SPI I/O devices to do their
> own buffering and handshake to the outside world so I can just poll them
> when I'm ready. Stuff that has to be dealt with in an interrupt because it
> does not have sufficient buffering on its own will be some sort of
> parallel interface so I can read or write it in a couple instructions with
> no wait loops.
>
> Meanwhile, back to debugging the ISR!
>
> Harold
>
>
>
My solution NOW would be to use a smaller PIC, like the PIC16F676 and
make firmware UARTS
between the outside and your standard device. With a 20M clock you
should be capable of at least
19.2K with 32-byte FIFO buffer between 'em without loss...I really
didn't care for the MAX3100,
it had a cranky oscillator. But I thought it DID have a DTR
holdoff.... have to look it up again.
>One of the beuties of going FULLY state machine is that the state
>transition and monitor functions can be very short and allow polling in
>the state machine engine itself or via a back ground task or as a seperate
>parallel state machine. The ISR become trivial merely used to service I/O
>rather than understand and comply with complex time comsuming protocols.
I used the AN734 and AN735 code in interrupts. Works well reading/writing
FIFO buffers for the background tasks to deal with the data. IIRC I used
extra flags set by the interrupt routine to say transfer finished, so the
non-interrupt task knew when the transfer had completed.
> >One of the beuties of going FULLY state machine is that the state
> >transition and monitor functions can be very short and allow
> polling in
> >the state machine engine itself or via a back ground task or
> as a seperate
> >parallel state machine.
If a non-degreed, un-educated hillbilly like myself wanted to research
"State Machines, Definition and application"..
What resources would you suggest?
>
>> >One of the beuties of going FULLY state machine is that the state
>> >transition and monitor functions can be very short and allow
>> polling in
>> >the state machine engine itself or via a back ground task or
>> as a seperate
>> >parallel state machine.
>
> If a non-degreed, un-educated hillbilly like myself wanted to research
> "State Machines, Definition and application"..
> What resources would you suggest?
>
> Thanks,
> Lyle