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

PIC18LF8723 hanging during spi_write

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



Joined: 16 Oct 2010
Posts: 31
Location: Florissant, CO

View user's profile Send private message

PIC18LF8723 hanging during spi_write
PostPosted: Fri Mar 03, 2017 3:43 pm     Reply with quote

Hello everyone,

I am having a weird problem that according to this forum "shouldn't exist", but it does. My issue is with the hardware SPI2 port.

Here are the pertinent portions of the setup code:
Code:

setup_oscillator(OSC_16MHZ|OSC_INTRC);   //  Setup the internal oscillator
disable_interrupts(INT_SSP2);            //  Make sure that the SSP2 port interrupt is turned off
//  Since we are about to start talking to the thermocouple ADCs, let's set up the SPI2 port for business
setup_spi2(SPI_MASTER | SPI_SCK_IDLE_LOW | SPI_CLK_DIV_64);   //  Make SPI2 the master of the board

Here is the routine that I wrote to write the configuration registers to the unit. Note that I put some test code at the end to read it back:
Code:

void  WriteBothADC_Config (void)
{
//  Get ready to write to two ADCs at the same time...since we are only writing and not reading
int8  SPI_Temp;   //  Register used to hold the temporary SPI in/out as needed
   
output_low(TC_CS1);   //  Make the chip select lines low for the first two ADCs
output_low(TC_CS2);
SPI_Temp = (TCADC_Config0_Address | TCADC_WriteMask);    //  Make the SPI Temp register equal to the Configuration 0 address ORed with the write mask
spi_write2(SPI_Temp);       //  Send that we want to start writing with the zero configuration register over to the ADC
SPI_Temp = TCADC_Cfg0_Reg;  //  Load the lower config register with our default
spi_write2(SPI_Temp);       //  Send the first configuration register over to the ADCs
SPI_Temp = TCADC_Cfg1_Re;   //  Load the upper config register with our default
spi_write2(SPI_Temp);       //  Send the second configuration register over to the ADCs (Note that this is the second write of a multi-byte write)
output_high(TC_CS1);        //  Make both of the chip selects high again
output_high(TC_CS2);

output_low(TC_CS1);  //  Make the chip select low so that we can read the result
SPI_Temp = TCADC_Config0_Address;   //  Make the SPI_Temp equal to the address of the data register in the ADC and don't mask it with the write bit since we want to read the ADC
spi_write2(SPI_Temp);      //  Send that we want to start reading the data registers over to the ADC   
SPI_Temp = spi_read2(0);   //  Read the MSByte of the result and save it in the shift register
SPI_Temp = spi_read2(0);   //  **Duplicate for testing**
output_high(TC_CS1);       //  Return the chip select high so that we can look at something else

output_high(TC_CS1);       //**Duplicate (Place for trigger)
                           //  Return the chip select high so that we can look at something else
return;    //  Return since we are done
}


The system will hang up on the spi_read statement. What happens, if I read two registers, it will always hang on the second transaction if I use only spi_read(), but if I replace the read-only with a bi-directional transaction of spi_read(0); it will hang on the first statement. Looking at the scope, all write transactions appear to be going through without a hitch. On the read, I can send the MAX31856 the address byte, but it won't generate the clock to read the register in either scenario. Here is the part of the list file that it loses its mind on:
Code:
....................       SPI_Temp = spi_read2(0);                                              //  Read the MSByte of the result and save it in the shift register
001FA:  MOVF   F66,W
001FC:  CLRF   F66
001FE:  RRCF   F64,W
00200:  BNC   01FE
00202:  MOVFF  F66,3E


It gets stuck on 001FE and 0020. It is looking at the Buffer Full bit of the SSPCON2_Stat register. The bit is never getting set because the clocks are never generated, so it sits there waiting forever. Unusual is it that if I try to output a 0 with the read, it get latched on the first statement, but otherwise it will get lost on the second read. The fact that neither of them generate a clock would make you think that it should always hang on the first one.

Looking at the rest of the SFRs during this anomaly, the BufferFull bit(SSP2STAT.0) is set after the write operation. When I do a read, the clocks never get sent. The Write Collision bit gets set on the second failed transaction when spi_read(); is used and it is set on the first write when spi_read(0) is used.

I guess the question is, why is the BufferFull bit staying set after a Master Write operation?

I am about ready to give up on the hardware SPI module on this one and try the USE_SPI# for software support. I have total control of the I/O on this chip, so I am sure I can just bit-bang the thing entirely...but I would like to know why this is occurring. I hope that my doing this deep of an investigation will help us either nail it, or write it off to the errata.

I am using compiler Version 5.055. Let me know if you need any more information to make an assessment or tell me to forget it and "bang" my way through it. Thanks!
_________________
Life is too short to only write code in assembly...
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 03, 2017 3:56 pm     Reply with quote

dumb question(?) but if you cut IDENTICAL code for the 1st SPI port, does it work ?

If so, I'd dump out that listing as well and compare line by line as they _should_ be the same,except for SPI port registers( I'm assuming the bits are the same......)

just thinking out loud here.....

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 03, 2017 5:32 pm     Reply with quote

You have this mode selection:
Quote:

setup_spi2(SPI_MASTER | SPI_SCK_IDLE_LOW | SPI_CLK_DIV_64);


The PIC's .h file has this:
Quote:

#define SPI_L_TO_H SPI_SCK_IDLE_LOW
#define SPI_H_TO_L SPI_SCK_IDLE_HIGH


Which means you are using SPI Mode 1, based on the following table:
Code:
// SPI mode definitions (for 16F and 18F PICs).
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


The diagram on this website shows that in Mode 1, SCK idles low
and samples on the falling edge.
http://www.totalphase.com/support/articles/200349236-SPI-Background#modes

The Maxim datasheet shows on page 6 that they are using Mode 3.
https://datasheets.maximintegrated.com/en/ds/MAX31856.pdf
There is a note that says SCLK can be either polarity. But in my estimate
this means it must still sample on the rising edge, which means it can use
Mode 3 or Mode 0. But not Mode 1.
So I suggest that you add those four #define statements for the SPI mode
above main(), and change your setup_spi2() statement as shown below:
Quote:

setup_spi2(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_64);
SkeeterHawk



Joined: 16 Oct 2010
Posts: 31
Location: Florissant, CO

View user's profile Send private message

PostPosted: Fri Mar 03, 2017 5:52 pm     Reply with quote

Thanks for the thought, Jay. I appreciate any fresh ideas at this point. That is something that I can't try on the current hardware easily. I can build it and look at the List and see if there was any difference.

I've been pouring over the datasheet and am wondering if I should try to "force" a dummy read of the SSP2BUF register after each read/write in hopes to clear the Buffer Full flag before I initiate the next command. What would be the best way to test that...using the #byte pre-processor command?

Any guidance is appreciated.
_________________
Life is too short to only write code in assembly...
SkeeterHawk



Joined: 16 Oct 2010
Posts: 31
Location: Florissant, CO

View user's profile Send private message

PostPosted: Fri Mar 03, 2017 6:18 pm     Reply with quote

You nailed it PCM!!! I must say that I am very surprised that such a configuration would completely "hose" the communication. I would expect gibberish before no clock.

I got an assembly error with using SPI_Mode_3 within the setup_spi2 statement. I "forced it in, and found that I still had to invert the sense of the SPI_XMIT option, and it worked. Here is the complete statement:
Code:
   setup_spi2(SPI_MASTER | (SPI_SCK_IDLE_HIGH | SPI_XMIT_H_TO_L) | SPI_CLK_DIV_64);     


Again, this worked, and I sincerely appreciate your input. I hope that someone else can benefit from this post as I have been reading the forum for the last two days and didn't find this exact problem.

Thanks again, and have an awesome weekend!!
_________________
Life is too short to only write code in assembly...
SkeeterHawk



Joined: 16 Oct 2010
Posts: 31
Location: Florissant, CO

View user's profile Send private message

PostPosted: Fri Mar 03, 2017 6:27 pm     Reply with quote

It turns out that when inverting the sense it works too. Here is the statement:

Code:
   setup_spi2(SPI_MASTER | (SPI_SCK_IDLE_LOW | SPI_XMIT_L_TO_H) | SPI_CLK_DIV_64);


Thanks again for your help
_________________
Life is too short to only write code in assembly...
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Mar 04, 2017 2:16 am     Reply with quote

It is an interesting behaviour.

Have to agree, it "shouldn't happen". Whatever clock edge you set or read on, the master should always be able to complete the transaction.
That setting things up right, fixes it, is good news, and obviously solves this for now.
However I suspect you may well have found an undocumented 'errata' with the chip. There are a couple of others in the family, where there is an erratum on the SPI, which could cause the hang behaviour.
SkeeterHawk



Joined: 16 Oct 2010
Posts: 31
Location: Florissant, CO

View user's profile Send private message

PostPosted: Sat Mar 04, 2017 2:51 am     Reply with quote

Thank you for your reply, Ttelmah.

You were one of the more out-spoken people on the anticipated behavior of this port over the years and I feel a bit vindicated that you think that it may be an errata issue as well. Most of the errata for this particular chip deal with the MSSP port, but not this behavior. It is a weird one indeed.

I am grateful that once-again, you all on the CCS Forum were able to get me "over the hump" on what seemed to be an insurmountable problem. Though I could have "bullied" through this one, I am glad to be able to use the hardware functions.

Thanks again everyone. A prosperous 2017 to you all!!
_________________
Life is too short to only write code in assembly...
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