CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Interrupts and SPI Slaves

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Matthew Aurand



Joined: 20 Dec 2007
Posts: 9

View user's profile Send private message

Interrupts and SPI Slaves
PostPosted: Thu Dec 20, 2007 10:54 pm     Reply with quote

Hello,

I have a few basic questions for which I have had a hard time trying to find answers to.

First, I have been using software spi support (spi_xfer()) for a setup in which I have two PIC's. One is the master (and is working fine) and the other is the slave to the master. The slave spi_xfer function works fine when I am only transferring one variable, but when I have several variables to pass (therefore I have several spi_xfers execute consecutively) the slave function always hangs as if it has not received enough clocks to complete the transfer. I have added extra clock outs from the master to see if this is the case, but it does not help. I am passing int8 vars, and all samples (according to diagnostic pin analysis) are where they should be. I am quite confused and wish the documentation for this function was a bit more descriptive. Any ideas? I am sure it is something simple, what is obvious to check (I must have missed something easy...).

Second, I am a little confused about interrupts. If disable_interrupt(xxx) is called within that ISR(xxx), what does that mean? If I disable an interrupt of higher priority within another ISR, can the higher priority interrupt still fire? I assume not, but that is not clear. Why exactly should you clear the interrupt flags?

I really have exhausted the resources I have here, and am desperately trying the learn the fundamentals. The manual and websites I have looked at don't really make it very apparent. They are either remarkably trivial and don't address my questions or they are over my head.

Can anyone point me in the right direction?



I really appreciate any advice,


-Matt
_________________
-Matthew A. Aurand
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 21, 2007 12:47 am     Reply with quote

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=31165

If that doesn't help, then:

1. Post your compiler version.

2. Post very short, but complete test programs for the master and
slave PICs that demonstrate the problem.
Ttelmah
Guest







PostPosted: Fri Dec 21, 2007 9:25 am     Reply with quote

For the interrupt part, you need to understand the suprisingly large number of parts associated with the 'interrupt'.

For each interrupt source, there is an interrupt 'flag', and interrupt 'enable', (and for the 18F chips, a 'priority' flag as well). Then globally, there is another interrupt 'enable' for all the interrupts (and a second for the high priority ones on the 18F chips).

To actually trigger an interrupt, the 'flag' has to be set, the 'enable' has to be set, and the corresponding global 'enable' has to be set.

When the interrupt triggers, this _automatically_ turns off the corresponding global enable.

When the hardware event corresponding to an interrupt source occurs, the interrupt 'flag' is automatically set. Once set, this remains set, till cleared (and also, till the event causing it is cleared, so for RB changed interrupts, you must also read the port as well).

So the sequence is:
Hardware event happens.

Interrupt flag is set.

If both the interrupt enable is set, and the corresponding global enable is set, the global interrupt handler is called at the start of the _next_ program instruction.

The global handler, then saves the registers, and _polls_ the interrupt flags, in the order defined by the order in which they were defined, _or_ as specified in the #priority statement. For the first interrupt, which has both it's flag, and it's enable set, the corresponding 'handler' sub is called. This must clear the hardware event involved (read a byte for a serial routine, read the port for the B changed interrupt etc..). Then the compiler automatically adds the code at the end of the routine, to clear the _flag_. The _enable_, is distinct, and may also need to be cleared (so for example, in a 'serial transmit' interrupt, if no more bytes are waiting to be sent, then the enable will need to be cleared, or the interrupt will continuously retrigger (since the transmit buffer is empty). It'd need to be turned back on, as soon as more data becomes available to send.
The subroutine then returns to the global handler, which restores the registers, and performs a 'retfie' instruction. This returns to the point where the interrupt triggered, _and automatically resets the 'global' enable bit_ after the return.
The 18F 'high priority' interrupts behave exactly the same way, except that their global bit, also disables the low priority interrupts, while the enable for the low priority interrupts, does not disable the high priority ones.
So disabling the interrupt inside a routine, makes perfect sense. It doesn't stop the other interrupts _flag_ bit from setting, but does stop the handler from being called. If latter the interrupt is again enabled, and a trigger has occured in the meantime, since the flag has been set, it'll be called straight away.
One 'must never be done' thing, is to enable/disable the _global_ enable inside an interrupt. The reason is that enabling it, can ptentially allow another interrupt to trigger inside the routine (causing problems with 're-entrancy'), while disabling it, is pointless, since it is already disabled by the hardware...

For the SPI, I posted some routines here in the past. Unfortunately, the inbuilt routines, are not really designed for use with interrupts, especialy for the 'slave' and while they can be made to work, it doesn't make good use of the SPI hardware...

Best Wishes
Matthew Aurand



Joined: 20 Dec 2007
Posts: 9

View user's profile Send private message

PostPosted: Fri Dec 21, 2007 11:41 am     Reply with quote

Wow, thanks guys!

PCM programmer: I read the thread you linked to and it is indeed a very similar problem to mine. Can you elaborate on reading the spi port between writes? I need to call a read function between sends? I know that the port sends/receives at the same time, but I am having the slave just send 0x00 per write from the master. The master is generating all clocks for the consecutive transfers, but for some reason the slave is not interpretting them properly.

Ttelmah: GREAT! So I always need to clear the interrupt flag after servicing it, or it will continuously trigger. This explains some problems I was having with the ext interrupt. Then I need to re-enable global. Thanks so much for your time!
_________________
-Matthew A. Aurand
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 21, 2007 11:54 am     Reply with quote

1. Post your compiler version.

2. Post very short, but complete test programs for the master and
slave PICs that demonstrate the problem.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group