SPI2 Read from external memory issue

Author
Vincent44
New Member
  • Total Posts : 24
  • Reward points : 0
  • Joined: 2014/09/19 03:41:47
  • Location: 0
  • Status: offline
2018/10/10 04:08:05 (permalink)
0

SPI2 Read from external memory issue

Hello,
 
I am trying to get the communication between an IS25LP128 flash memory and my PIC32MX350F128H to work with SPI2, but there must something that I am missing.
 
After several attempts, I managed to get the WRITING to the memory to work. But when I try to read the data back, I can see on the scope that the IS25LP128 responds, but I do not get any data in the PIC32 registers.
Attached, a scope of reading the value 0x55, that I previsouly stored at the address 266 (0x10A).
 
I already trying many different option that I could find out there for the reception, but nothing worked.I always endup reading 0x00 or 0xFF.
I also check the soldering on the board. Everything is fine.
 
Here is my code.

void main(void)
{
    //--- INIT SYSTEM ---//
    // Disable the watchdog
    DisableWDT();
    INTDisableInterrupts();           
    OSCSetPBDIV(OSC_PB_DIV_2);
    SYSTEMConfig(SYSFREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
    INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
 
    //--- INIT IO ---//
    ANSELB = 0x00000000 ;
    ANSELC = 0x00000000 ;
    ANSELD = 0x00000000 ;
    ANSELE = 0x00000000 ;
    ANSELF = 0x00000000 ;
    ANSELG = 0x00000000 ;
  
    // Set all PORTs to 0 (just in case)
    LATB = 0 ;
    LATC = 0 ;
    LATD = 0 ;
    LATE = 0 ;
    LATF = 0 ;
    LATG = 0 ;

{ .. Only showing usefull init .. }
    //-----------------------------------------
    // PIN 4 : RG6
    // NVM SCK / SCK2
    PORTSetPinsDigitalOut(IOPORT_G, BIT_6);
 
    //-----------------------------------------
    // PIN 50 : RD2
    // NVM MOSI (SDO2)
    PORTSetPinsDigitalOut(IOPORT_D, BIT_2);
    RPD2R = 0b0110 ;

    //-----------------------------------------
    // PIN 51 : RD3
    // NVM MISO (SDI2)
    PORTSetPinsDigitalIn(IOPORT_D, BIT_3);
    SDI2R = 0b0000 ;
    //CNPDDbits.CNPDD3 = true ;   // TODO : Test
  
 
    initExternalNVM() ;
    while(1)
    {
        //ExternalNVMWriteBytes(266, 0x55, 1) ;
        ExternalNVMReadSingleByte(266) ;
    }
 
}

 
 
Where the SPI functions are :
 

void initExternalNVM(void)
{
    // Make sure the external NVM is disabled
    DisableNVMChip_data() ;
   
    SPI2CONbits.SIDL = 1 ;  // Stop in IDLE
    //SPI2CONbits.SMP = 1 ;   // Input data is sampled at the end of data out time
    SPI2CONbits.CKP = 0 ;   // Idle state of the clock is LOW level
    SPI2CONbits.CKE = 1 ;   // Data changes on falling edge of clock (this is good, because the IC will read a stable state at the folowing RISING edge)
    SPI2CONbits.MSTEN = 1 ; // Master Mode
    SPI2CONbits.ON = 1 ;    // Enable SPI
    
    SpiChnSetBrg(SPI_CHANNEL_EXTERNAL_MEMORY, SpiBrgVal(PBCLK, 100000));
  
    // Make sure the HOLD is not set
    UnholdDataNVMChip_data();
    ClearWriteProtectStatusRegisterNVMChip_data() ;
}

uint8_t ExternalNVMReadSingleByte(uint32_t address)
{
    uint8_t data ;
       
    // Enable the Chip Select
    EnableNVMChip_data() ;
    
    // Send the NORMAL_OPERATION_READ code
    sendSPIByte(0x03) ;
   
    // Send the address we want to read
    sendSPIByte(address >> 16) ;
    sendSPIByte(address >> 8) ;
    sendSPIByte(address) ;
    
    // Wait for some data, and read it when it's ready
    data = readSPIByte() ;     
         
    // Close the communication by disabling the Chip
    DisableNVMChip_data() ;
    
    return data ;
}

void sendSPIByte(uint8_t data)
{
    SPI2BUF = data ;
    while(SpiChnIsBusy(SPI_CHANNEL_EXTERNAL_MEMORY));          
}

uint8_t readSPIByte(void)
{
    uint8_t data ;

     // Sent a dummy data OUT, to generate some CLOCK
    // The external memory needs this clock to send a byte
    SPI2BUF = 0x00 ;
    while(SpiChnIsBusy(SPI_CHANNEL_EXTERNAL_MEMORY));       
    
   
    // Ths input data is read from SPI2BUF
    data = SPI2BUF;    
    return data;
}

Attached Image(s)

#1

8 Replies Related Threads

    Aussie Susan
    Super Member
    • Total Posts : 3326
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/10 18:30:21 (permalink)
    +1 (1)
    The SDI signal looks really bad to me - it should be a nice clean signal (although I can understand the tail-off at the end when the slave goes tri-state).
    What is the code for the 'SpiChnIsBusy' function - specifically what is bit is it blocking on.
    I'm guessing that it is waiting for the wrong status bit and therefore returning too early.
    (For a peripheral as straight forward as the SPI one, library functions - I assume that the SpiChnIsBusy function is from a library - only serve to confuse and confound in my opinion. Just interact directly with the device and you *know* what is happening in your code.)
    Susan
    #2
    Vincent44
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2014/09/19 03:41:47
    • Location: 0
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/11 07:37:57 (permalink)
    0
    Thanks for your feedback Susan.
     
    Yes, the SDI does not look the best. As you can see in my initial post, I commented out the activation the internal pull-down.
    When activated, the signal was better looking, but did not help with the reception from the PIC32's point of view.
     
    I assumed that the SDI was set high impedance, and only driven by the external memory when needed.
    Using external pull up/down on the SPI does not seem to be very common... Should I try it ?
     
     
     
    Concerning the SpiChnIsBusy(), it comes indeed from PLIB. I would guess that it returns the state of the register SPI2STAT.SPIBUSY.
    This function works fine when I want to send out some data, but it might not be correct one to use for reading ?
     
     
    #3
    Aussie Susan
    Super Member
    • Total Posts : 3326
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/11 18:32:33 (permalink)
    +1 (1)
    Vincent44
    I would guess that it returns the state of the register SPI2STAT.SPIBUSY.
     

    (My emphasis added)
    You have the source for PLIB so why guess - look.
    The SPIRBF bit is the best one to make sure that there is something to read and SPITBF or SPITBE are the best to use to make sure that it is safe to write (which you use depends on the use of the FIFO).
    Susan
    #4
    NorthGuy
    Super Member
    • Total Posts : 5045
    • Reward points : 0
    • Joined: 2014/02/23 14:23:23
    • Location: Northern Canada
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/11 20:32:45 (permalink)
    +1 (1)
    In your "sendSPIByte()", you need to read SPI2BUF. The SPI transaction puts data into the buffer, and it must be read. Otherwise, the data will hang in there and that's what you're reading in the end.
    #5
    qhb
    Superb Member
    • Total Posts : 7090
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI2 Read from external memory issue 2018/10/11 21:14:55 (permalink)
    +1 (1)
    NorthGuy
    In your "sendSPIByte()", you need to read SPI2BUF. The SPI transaction puts data into the buffer, and it must be read. Otherwise, the data will hang in there and that's what you're reading in the end.


    Agreed.
    That is why it's silly having separate "read" and "write" functions.
    Just implement a single "Exchange" function that does both, because that is precisely what the hardware is always doing.
     

    Worst forum problems are now fixed, but the damn firewall is still there.
    #6
    Vincent44
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2014/09/19 03:41:47
    • Location: 0
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/15 00:37:31 (permalink)
    0
    Thank you guys for your feedback. Smile: Smile
     
    I believe this what I was missing !
    NorthGuy
    In your "sendSPIByte()", you need to read SPI2BUF. The SPI transaction puts data into the buffer, and it must be read. Otherwise, the data will hang in there and that's what you're reading in the end.



    I already tryied some stuff with the SPIRBF flag, but with no result. In think it is because I was not reading the SPI2BUF after each write.
     
    Changed my code to the following, and everything is working as expected.
    Next step is DMA, but this will be implemented later.
     

    uint8_t sendSPIByte(uint8_t data)
    {
        uint8_t read ;
        
        while(!SPI2STATbits.SPITBE) ;   // Make sure TX buffer is ready
        SPI2BUF = data ;                // Send data
        while(!SPI2STATbits.SPIRBF) ;   // Wait for data IN
        read = SPI2BUF ;
        return read ;
    }

     
    #7
    qhb
    Superb Member
    • Total Posts : 7090
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: SPI2 Read from external memory issue 2018/10/15 01:04:19 (permalink)
    0
    You are now doing precisely what I recommended in post#6, so you should rename this routine to something sensible, as it is now doing a write and read.
    sendrecvSPIByte
    writereadSPIByte
    xferSPIbyte
    would be good options.
     
     

    Worst forum problems are now fixed, but the damn firewall is still there.
    #8
    Vincent44
    New Member
    • Total Posts : 24
    • Reward points : 0
    • Joined: 2014/09/19 03:41:47
    • Location: 0
    • Status: offline
    Re: SPI2 Read from external memory issue 2018/10/15 01:54:53 (permalink)
    0
    qhb, sound like a good idea to prevent misunderstanding. ;)
    #9
    Jump to:
    © 2018 APG vNext Commercial Version 4.5