0

I'm struggling with, probably, a very simple problem. I have a Cypress CY8 controller acting as SPI master, which should communicate with a PIC32mx in slave mode to exchange data packets.

However i cannot even fix simple transmission of multiple bytes from the master to the slave. I've set up the cypress to transmit a char of increasing value (0-255) with a pause (and slave select toggle) in between. The pic should read the incoming byte and then print it over uart to my pc (the uart connection works). But the pic only prints the first character it receives continuously instead of it being updated. If i check my logic sniffer, the cypress does send incrementing values and the pic relays them back over the MISO line (looks like the shift buffer isn't cleared).

What could this be?

The cypress without the pic attached gives proper output: https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-07-28%2015.43.28.png With the pic attached it relays the data over MISO: https://dl.dropboxusercontent.com/u/3264324/Schermafdruk%202015-07-28%2015.43.45.png

And this is my (now) extremely basic code to test it:

TRISBbits.TRISB2 = 1; // make Ra2 pin input (SDI)
TRISBbits.TRISB5 = 0; // make Ra2 pin output (SDO)
TRISBbits.TRISB15 = 1; //make RB14 output (SCK)

ANSELA = 0; // all ports digital
ANSELB = 0; // all ports digital

SYSKEY = 0x00000000;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
CFGCONbits.IOLOCK=0; // unlock configuration
CFGCONbits.PMDLOCK=0;


SDI2R = 0b0100; //SDI2 on pin RB2
SS2R = 0b0011; //SS2 on pin rb10
RPB5R = 0b0100; //SDO2 on pin RB5
// SCLK is connected to pin RB14 (SCK) by default
SYSKEY = 0x00000000;

   SPI2CON = 0; // Stops and resets the SPI1.
   rData=SPI2BUF; // clears the receive buffer
   SPI2BRG=207; // use FPB/4 clock frequency  <-- not important in slave mode right?
   SPI2STATCLR=0x40; // clear the Overflo
    SPI2CON=0x8180;

    unsigned char t;
    while(1){
        t = SpiChnReadC(2);
        //t = SPI2BUF; <== i've tried this also
        sendData(t); <== uart routine
    }

As i do receive a character and the spi data is relayed back to the cypress constantly i think something goed wrong with reading/clearing the spi data structure in the PIC. But i can't figure out why. As i read in the datasheet, reading from SPI2BUFF gives me the received data, and clears the read flags so new data can be received, but it looks like that doesn't happen...

Can someone shine a light on this for me?

Thanks in advance Timberleek

tim kers
  • 1
  • 3
  • Does `SpiChnReadC(2)` block until a byte has been received, or does it just return SPI2BUF? – Sigve Kolbeinson Jul 28 '15 at 14:17
  • SPIChnReadC returns immediately according to the header file. So i would expect maybe a couple of double prints. However it keeps printing the same value for minutes (and probably longer) although the data on the spi bus itself does change (according to the logic sniffer). Restarting the pic results in the same situation, but with a different value being printed – tim kers Jul 28 '15 at 14:28
  • 1) "pic only prints the first character it receives continuously" --> what is that value? 2) If code was `while(1){ sendData(t++);}`, does your receiving system report incrementing data? – chux - Reinstate Monica Jul 28 '15 at 14:37
  • That value depends on the value on the bus at startup of the pic. If i powercycle the pic, a different value gets printed. It simply looks like it reads as it should, but only the first time. After that, the spi buffer keeps returning the same character. using only sendData(t++) with t initialized at 0 before the loop, the printed data increments as expected. t = SpiChnReadC(2); sendData(t++); <== uart routine also continuously prints the same value – tim kers Jul 28 '15 at 14:42
  • Note: use `stdint.h` types if you require a fixed size type! Do not realy on the standard integer types. – too honest for this site Jul 28 '15 at 14:45
  • you mean instead of unsigned char? Why would that be a problem? Serious question as i used unsigned char throughout a lot of code. I've ran it with uint8_t, but no difference – tim kers Jul 28 '15 at 14:51
  • Did you get any further? Just checked PIC32 SPI reference http://ww1.microchip.com/downloads/en/DeviceDoc/61106G.pdf. I know that you clear the overflow flag before entering the loop but are you able to observe the flag during the loop? On a Receive Overflow the SPI will stop updating SPIxBUF unless SPIxCON2.IGNROV is set. Could the PIC be clocked so low compared to the SPI bit rate that it can't keep up? – Sigve Kolbeinson Jul 28 '15 at 22:29
  • No i haven't looked at the problem yesterday. I'm continuing today. I'll try to observer the flags. The clock speed shouldn't be a problem. The spi bus runs at 200khz at the moment with the pic at 50MHz. – tim kers Jul 30 '15 at 07:06
  • It seemed that timing was indeed an issue. I've added some delays between separate communications and it worked. The only problem i am now facing is that i'm not able to send data back from the slave. I try to request data and status from the slave. First i send a byte master->slave to request certain data. the slave should then reply a byte of data back to the master. But it doesn't. It only returns the master's data ( the shift buffer just continues shifting). I do generate clocks (send 0x00 or 0xff by the master). using the SpiChnPutC method or write to SPI2BUF manually makes no difference – tim kers Aug 03 '15 at 08:32

1 Answers1

0

You should try making you SPI handler ISR driven to keep you from constantly polling, can also help the debugging since you'll only get notifications when the SPI is actually transacting.

NOTE: I'm bringing this from my FreeRTOS impl, so my ISR definition is not XC32 exactly...

/* Open SPI */
SPI1CON = 0;
spi_flags = SPICON_MODE32 | SPICON_ON;
SpiChnOpen(1,spi_flags,BRG_VAL);
SpiChnGetRov(1,TRUE);
mSPI1ClearAllIntFlags();
mSPI1SetIntPriority(priority + 1);
mSPI1SetIntSubPriority(0);
mSPI1RXIntEnable(1);


void vSPI1InterruptHandler(void)
{
    unsigned long data;

    if (IFS0bits.SPI1EIF == 1)
    {
       mSPI1EClearIntFlag();
    }
    if (IFS0bits.SPI1RXIF == 1)
    {
        data = SPI1BUF;
        //sendData(data);
    }
    mSPI1RXClearIntFlag();
}
blsmit5728
  • 434
  • 3
  • 11
  • I saved the ISR implementation for later. I have never implemented a spi slave, so i first wanted to play with the protocol and such. In the definitive version i want to use interrupts and possibly DMA – tim kers Jul 30 '15 at 07:07
  • Or he could use DMA to move data directly from SPIxBUF to the UART TX buffer with out any CPU time at all, if all he needs is to relay data to UART. However, I don't think the issue was so much the mechanics of getting data out of SPIxBUF, but rather that SPIxBUF appears to only be updated once, which suggest the solution will have more to do with the setup of the MCU and specifically the SPI peripheral – Sigve Kolbeinson Jul 30 '15 at 07:51
  • The UART is only for debugging purposes at the moment. The pic has a SD card connected to another spi bus. Eventually data from this card needs to be transferred to the cypress, and other data comes back from the cypress to the pic – tim kers Jul 30 '15 at 09:02