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 CCS Technical Support

SPI Enhanced mode

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



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

SPI Enhanced mode
PostPosted: Tue Apr 29, 2014 12:29 am     Reply with quote

Good day

dsPIC33EP32MC202
CCS 5.019

I am trying to get the enhanced mode of the SPI to work, but no luck so far. Probably over looking something stupid.

The standard #use works.
Code:

#use spi(FORCE_HW, SLAVE, SPI1, MODE=3, BITS=8, ENABLE=PIN_B0)

I can't find any CCS functions to enable Enhanced mode, so I tried accessing the registers directly.
Code:

#word SSPBUF = getenv("SFR:SPI1BUF")
#word SSP1STAT = getenv("SFR:SPI1STAT")
#word SSP1CON2 = getenv("SFR:SPI1CON2")

and

  SSP1STAT = 0;
  SSP1CON2 =0x000;
  SSP1STAT = 0x8000;

The above works, if I set SSP1STAT =0 only then SPI does not work, which is correct and thus verified that I am accessing the correct SFR.

If I change to
Code:

  SSP1STAT = 0;
  SSP1CON2 =0x0001; //Enabling Enhanced mode
  SSP1STAT = 0x8000;

then my SPI does not work at all.
Are the enhanced mode so much different from standard mode.
Here are the SPI routine as well.

Code:

#INT_SPI1
void  SSP1_isr(void) {
static uint8_t ValLSB;
uint8_t Command;
  //Read the value from SSPBUF and load next Val
  Command = SSPBUF;
  switch (Command) {
    case  0: SSPBUF = ValLSB; break;
    case VADC: SSBUF = make8(VinADC,1); ValLSB = make8(VinADC,0);
      break;
    default:
  }
}


Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Apr 29, 2014 1:10 am     Reply with quote

Hurrah...
Good start. Smile

Easiest way to enable the enhanced mode is simply to configure using the standard code, and add:
Code:

#bit SPIBEN=getenv("BIT:SPIBEN")

SPIBEN=TRUE;
//then enables the buffer

For normal byte based transfers you probably want SISEL=001. For the fastest block based transfers 010 is better, but then means the interrupt handler will always be handling multiple bytes. See comment at end.

Code in your ISR needs a lot more work.
The standard supplied SPI routines are awful (haven't checked recently if they are still as bad...). They are great for use in 'main' code, but not for use in an ISR. Hence as you have realised, for ISR based transfers, you have to go DIY.
Things missing are the ability to directly write the buffer, and then not wait for a transfer etc..

Now in your code, things to realise:

1) Because you have the buffering enabled, there can be up to eight bytes waiting on an ISR. So your read functions need to loop testing the SRXMPT bit until the buffer is empty. Whether this is likely to apply depends on how fast the data is arriving, and how 'busy' your chip is (other interrupts etc.).
2) When asked to write, you can load up to eight bytes inside one ISR. If multiple bytes are waiting to send, the write needs to loop writing data, until SPITBF goes true (signalling the output buffer is full).
3) The ISR code needs to handle error states. If SPIROV gets set, you have missed a received byte, and may need to have some form of error recovery.

I suspect your biggest problem is the interrupt mode. You have it set to interrupt when RX is empty. For a slave replying to transmissions, you want an interrupt when it has data.

Best Wishes
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Tue Apr 29, 2014 1:26 am     Reply with quote

Thanks Ttelmah,

That is why I want Enhanced mode, to interrupt on when data are in the buffer. But will implement what you have suggested and then give feedback.

Regards

(Edit) You have to disable the SPI first otherwise it does not take the new configuration.
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Thu May 01, 2014 2:34 am     Reply with quote

Given up on this, not worth the effort right now.

Thanks Ttelmah
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Thu May 01, 2014 12:36 pm     Reply with quote

Standard mode, interrupts when a byte has been received. Does what you want....
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri May 02, 2014 12:03 am     Reply with quote

According to the data sheet the MCU interrupts when a byte/word has been shifted out. I need to transmit about 4 words and were hoping to pack it in and forget. But will have a look when time is available (Who am I kidding Laughing ).

Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Fri May 02, 2014 1:19 am     Reply with quote

The slave has nothing to do with 'shifting out'. That interrupt only occurs when you are a master device.

On a slave, everything is effectively controlled by 'shifting in'. When the slave receives a byte, there is an interrupt. At the same time as a byte is shifted in, anything already in the output buffer is shifted out. However remember that this _lags_ the input transaction. At the interrupt, the slave has received a byte, and then has to load the byte to be sent on the _next_ transaction.

Now, depending on the speed involved, you could handle this with the enhanced buffer, but then you need to possibly 'rethink' how the transaction is setup.

What you would do, is program to interrupt on a single byte.
Wait for the interrupt, which then says the master has sent you something.
Look at what the master has sent, and use this to determine the reply.
Disable the interface, and reprogram to interrupt on 'buffer empty'.
Enable the interface, and load the reply to send into the output buffer.
Exit the interrupt.
You'd then get another interrupt when the buffer empties, and can then go back to the single byte interrupt programming.

The master would need to send the 'request' byte, pause a moment (long enough for the slave to work out what the reply is to be, and reprogram the interface), and then clock in eight reply bytes as fast as it can.

The problem is that unless you change the interface 'mode' after the request byte, the chip will interrupt on every byte (so you gain nothing over the standard mode). Alternative is to have another signal say to load the buffer 'in advance' of the data being clocked (this is a fairly common way of working) - so you drop a 'select' line, and use an interrupt from _this_ to signal to load the buffer. The master drops this line, waits a moment for the buffer to be loaded, and just clocks eight bytes in. For this you don't use INT_SPI at all, unless you need to send more than eight bytes, where you interrupt when the buffer is nearly empty, to say 'load the next lot of data'.
This is the easier mode to program, and avoids having to send extra data over the bus.

Best Wishes
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