This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

External SPO memory interface 25LC256



Hi,

I am thrying to interface external spi memory 25LC256 to MSP430  development kit.

The things that i have achieved so far is:

1)SPI INIT

2)send dummy data in spi tx buff abd recieve the same in rx buff

3)then i warite data to the memory (16 bit addr 8 bit data 0xa0).Each and every byte is echoed in rx buff

4) then i try to read mem by sending dummy data 0x00.but i dont recieve and data from memory. what i rx always is dummy data written.

My issue is how do i confirm the communication is through and data is written to SPI memory.

I follow all the instruction,steps to do write as well as read data.

I am attaching the spec and my code.Kindly let me know if anything can be done about this. or anybody has faced any similar issues.

Looking foraward for your kind support.

Thanks and Regards

Manisha

// code

 

//unsigned int UART_Data = 0;
UInt8 SPI_RxData = 0;
UInt8 SPI_TxData = 0;
UInt16 SPI_MemAddr = 0x0002;

void main(void)
{
   WDTCTL = WDTPW + WDTHOLD;                    // Stop WDT
   SPI_Initialization();                       // Initialize SPI
  while (1)
   {
     __bis_SR_register(GIE);       // enable interrupts
      RESET_BUSY_FLAG();
       UCB0TXBUF = 0x55;                 //WRITE DATA
       while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?
       SPI_RxData = UCB0RXBUF;
       SET_BUSY_FLAG();
      
      
        while((P3IN & 0x01));             // Verifies busy flag
        RESET_BUSY_FLAG ();               // CS bought to low to start
        IFG2 &= ~UCB0RXIFG;   
        UCB0TXBUF = SET_WRITE_LATCH;      // latch write enable sequence
        while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
        SPI_RxData = UCB0RXBUF;
     
        SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
        __no_operation();              //one wait state
        RESET_BUSY_FLAG();                // CS bought to low to start
       // start write instruction
        IFG2 &= ~UCB0RXIFG;   
        UCB0TXBUF = WRITE_INSTR;          //  write instr
        while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
        SPI_RxData = UCB0RXBUF;
       //WRITE HIGHER ADDR FIRST
       UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08;       
       while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?
       SPI_RxData = UCB0RXBUF;
       UCB0TXBUF = (SPI_MemAddr & 0x00ff); // WRITE LOWER 16 BIT ADDR
       while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?
       SPI_RxData = UCB0RXBUF;
       UCB0TXBUF = 0x55;                 //WRITE DATA
       while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?
       SPI_RxData = UCB0RXBUF;
      __no_operation();                //wait one cycle
      SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
      
     
       RESET_BUSY_FLAG();
       while((P3IN & 0x01));             // Verifies busy flag
       IFG2 &= ~UCB0RXIFG;   
       RESET_BUSY_FLAG  ();             // CS en
       UCB0TXBUF = READ_INSTR;           //Send read inst to SPI
       while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?
       SPI_RxData = UCB0RXBUF;
           
      UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08;        // Send 16 bit memory Higher addr
      //UCB0TXBUF = (SPI_MemAddr & 0xff00);        // Send 16 bit memory Higher addr
      while (!(IFG2 & UCB0RXIFG));                     // USCI_B0 TX buffer ready?
      SPI_RxData = UCB0RXBUF;
     
      UCB0TXBUF = (SPI_MemAddr & 0x00ff);            // Send 16 bit memory lower addr
     while (!(IFG2 & UCB0RXIFG));                    // USCI_B0 TX buffer ready?
      SPI_RxData = UCB0RXBUF;
      
     
      UCB0TXBUF = 0x00; 
      while (!(IFG2 & UCB0RXIFG));                    // USCI_B0 TX buffer ready?
      SPI_RxData = UCB0RXBUF;
     
     SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
       
       
  }
}

 

 

void SPI_Initialization(void)
{
 
  //1) -> initialization/re-configuration process <-BEGIN
  UCB0CTL1 |= UCSWRST;//Set UCSWRST -- needed for re-configuration process
  //1) END
 
  //2) -> Initialize all USCI registers Set <- BEGIN
  // CONTROL REGISTERS
  //UCB0CTL0 -> Control Register 0
  //  7   |  6  |  5  |  4   |  3  |  2-1   |  0   |
  //-------------------------------------------------------------------------
  //UCCKPH|UCCKPL|UCMSB|UC7BIT|UCMST|UCMODEx|UCSYNC|
  //UCCKPH (Clock phase)              = 0b  ->  Data is changed on the first UCLK edge and captured on the following edge.
  //UCCKPL (Clock polarity)           = 0b  ->  The inactive state is low
  //UCMSB (MSB first select)          = 1b  ->  MSB first
  //UC7BIT (Character length)         = 0b  ->  8-bit data
  //UCMST (Master mode)               = 1b  ->  Master mode
  //UCMODEx (USCI mode)               = 00b ->  3-Pin SPI
  //UCSYNC (Synchronous mode enable)  = 1b  ->  Synchronous mode
  UCB0CTL0 = 0x29;
  //-------------------------------------------------------------------------
  //-------------------------------------------------------------------------
  //UCA0CTL1 -> Control Register 1
  //   6-7  |   5   |   4   |   3  |   2    |   1   |    0  |
  //---------------------------------------------------------
  //UCSSELx |                  Unused               |UCSWRST|
  //---------------------------------------------------------
  //UCSSELx (USCI clock source select)= 10b ->  SMCLK
  //UCSWRST (Software reset)          = 1b  ->  normally set by a PUC
  UCB0CTL1 = 0x81;                    
  //-------------------------------------------------------------------------
  // DATA RATE
  // Data rate = SMCLK/2 ~= 500kHz
  // UCA0BR1 = 0x00 & UCA0BR0 = 0x02
  //-------------------------------------------------------------------------
  UCB0BR0 = 0x02;                          
  UCB0BR1 = 0x00;
  //-------------------------------------------------------------------------
  //2) END
 
  //3) Configure ports <-BEGIN
  P3SEL |= 0x0E; // P3.1,P3.2,P3.3 option select
 
  //3) END 
 
  //4) Clear UCSWRST via software -> BEGIN                     
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  //4) ->END
 
  //5) Enable interrupts -> BEGIN
  // Not used
  //5) -> END
 
 //  IE2 |= UCB0TXIE;                          // Enable USCI_A0 TX interrupt
 // IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt
}

 

  • I don't know the internal protocol of the RAM you're writing to, but I think that you got some details of the SPI wrong in your code flow.

    manisha patravali said:
    while (!(IFG2 & UCB0RXIFG));      // USCI_B0 TX buffer ready?

    Not exactly. It means data ready in RX buffer. This is, of course, only possible if the byte in TXBUF had been send too. Nevertheless, TXBUF is ready as soon as the first bit of the TX data is being sent, Which is almost immediately after the previous byte has been written into TXBUF. The transfer is double-buffered, this means you can prepare and write the next outgoinf byte while the previous is still being sent. This maximizes throughput as the transfer can seamlessly continue from one byte to the next without waiting for the processor.

    The other thing is, the byte you received after sending the first (dummy) byte is actually sent by the slave before receiving your first byte. Therefore it cannot be the response to your request.

    I don't know what SET_BUSY_FLAG() does. Is it related to the busy flag test on P3.1? Or should it rather be named 'SELECT_CHIP()' or 'CS_LOW()' instead? I think so from the comments later on.

    Anyway, you call it immediately after reading RXBUF. Depending on the MCLK speed this might be before the transmission has been finished (it happens during and not after the last clock cycle). To ensure the transfer is finished, check the UCBUSY bit instead.

    manisha patravali said:
            UCB0TXBUF = SET_WRITE_LATCH;      // latch write enable sequence
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            SPI_RxData = UCB0RXBUF;

    Here TXIFG is almost immediately set, and TXBUF ready to receive the next byte. But there has been noting received yet. Wait for RXIFG instead before reading RXBUF. Or don't read it at all if it isn't used anyway. Nevertheless, when you now call SET_BUSY_FLAG, this happens whiel the first or second bit of the command is being sent and you probably switch the slave off before it got anything.

  • Thank you Jens-Michael.

    With your i/p I have changed my code. I see  some improvement but not achieved fully memory read with SPI.

    Things that I am observing now are with changed code is Rx interrupt is fired only once when I fill tx buffer first time.

    Rest of loading tx buffer is not generating any Rx intr.

    Why is there only once interrupt fired.

     

    Do I really need a Rx Interrput?

     

    When I actually need to read data there is no rx interrupt seen. Why?

    Also I am seeing in UCBOSTAT register that UCOE is set if I run application without break point.

    Which means that Rx buff was not read and some data is transferred to it.

    But if I single step the code I don’t see UCOE as set. What is the difference?

    To read data from Rx buff there is interrupt function. Which is not getting trigerred.

    Do I need to manually “SPI_RxData = UCB0RXBUF” do this to clear that UCOE error?

    Is this data which is come on Rx buff from the SPI slave or data transmitted echoed back?

     

    Also attached is my new code fully.

     

    #include "msp430xG46x.h"


    typedef unsigned char UInt8;
    typedef char          Int8;
    typedef unsigned int  UInt16;
    typedef int           Int16;


    #define READ_INSTR              0x03
    #define WRITE_INSTR             0x02
    #define RESET_WRITE_LATCH       0x04
    #define SET_WRITE_LATCH         0x06
    #define READ_STATUS_REG         0x05
    #define WRITE_STATUS_REG        0x01

    #define PAGE_LEN      0x40           //64
    #define MEM_SIZE      0x8000         //32768
    #define NOS_OF_PAGES  0x200          //512
    #define MEM_ADDR      0x0001         // 16 bit address


    #define SET_BUSY_FLAG()   P3OUT |= 0x01; // port 3 bit 0 CS as 1
    #define RESET_BUSY_FLAG() P3OUT &= ~0x01; // port 3 bit 0 CS as 0


    //void UART_Initialization(void);
    void SPI_Initialization(void);
    void SPIMemWriteSeq(void);
    void SPIMemReadSeq(void);
    void SPI_PortInitlaization(void);
    void BasicTimerCfg(void);

    UInt8 SPI_ReadData(UInt16 address);
    void SPI_WriteData(UInt16 address,UInt8 data);


    //unsigned int UART_Data = 0;
    UInt8 SPI_RxData = 0;
    UInt8 SPI_TxData = 0;
    UInt16 SPI_MemAddr = 0x0002;

    void main(void)
    {
       WDTCTL = WDTPW + WDTHOLD;                    // Stop WDT
       SPI_Initialization();                       // Initialize SPI
      while (1)
       {
         __bis_SR_register(GIE);       // enable interrupts
         
         /* write memory starts:
          1)First make  CS low
          2)send  data latch  0x06  command
          3)on transmission complete make CS high
          4)Nake CS low
          5)send write command 0x02
          6)Send 16 byte mem address
          7)send data
          8) wait for transmission complete
          9)make cs high */
         
            // send write latch command
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            RESET_BUSY_FLAG ();               // CS bought to low to start
            UCB0TXBUF = SET_WRITE_LATCH;      // latch write enable sequence
            while(UCB0STAT & UCBUSY);
            SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
            
           
            // start write instruction
            RESET_BUSY_FLAG();                // CS bought to low to start
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            UCB0TXBUF = WRITE_INSTR;          //  write instr
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08;        
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            UCB0TXBUF = (SPI_MemAddr & 0x00ff); // WRITE LOWER 16 BIT ADDR
            while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
            UCB0TXBUF = 0x55;                 //WRITE DATA
            while(UCB0STAT & UCBUSY);
            SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
           
            /* read memory starts:
             First make  CS low then 16 bit addr ,Then u get data from mem make CS high*/
             RESET_BUSY_FLAG();
             while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
             UCB0TXBUF = READ_INSTR;           //Send read inst to SPI
             
             while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
             UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08;        // Send 16 bit memory Higher addr
            
             while (!(IFG2 & UCB0TXIFG));                     // USCI_B0 TX buffer ready?
             UCB0TXBUF = (SPI_MemAddr & 0x00ff);            // Send 16 bit memory lower addr
            
             while (!(IFG2 & UCB0TXIFG));                    // USCI_B0 TX buffer ready?
             UCB0TXBUF = 0x00;                               // send dummy data
         
             while(UCB0STAT & UCBUSY);     // check there is no tx and rx happening
             SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
            
            
      }
    }

    void SPI_Initialization(void)
    {
     
      //1) -> initialization/re-configuration process <-BEGIN
      UCB0CTL1 |= UCSWRST;//Set UCSWRST -- needed for re-configuration process
      //1) END
     
      //2) -> Initialize all USCI registers Set <- BEGIN
      // CONTROL REGISTERS
      //UCB0CTL0 -> Control Register 0
      //  7   |  6  |  5  |  4   |  3  |  2-1   |  0   |
      //-------------------------------------------------------------------------
      //UCCKPH|UCCKPL|UCMSB|UC7BIT|UCMST|UCMODEx|UCSYNC|
      //UCCKPH (Clock phase)              = 0b  ->  Data is changed on the first UCLK edge and captured on the following edge.
      //UCCKPL (Clock polarity)           = 0b  ->  The inactive state is low
      //UCMSB (MSB first select)          = 1b  ->  MSB first
      //UC7BIT (Character length)         = 0b  ->  8-bit data
      //UCMST (Master mode)               = 1b  ->  Master mode
      //UCMODEx (USCI mode)               = 00b ->  3-Pin SPI
      //UCSYNC (Synchronous mode enable)  = 1b  ->  Synchronous mode
      UCB0CTL0 = 0x29;
      //-------------------------------------------------------------------------
      //-------------------------------------------------------------------------
      //UCA0CTL1 -> Control Register 1
      //   6-7  |   5   |   4   |   3  |   2    |   1   |    0  |
      //---------------------------------------------------------
      //UCSSELx |                  Unused               |UCSWRST|
      //---------------------------------------------------------
      //UCSSELx (USCI clock source select)= 10b ->  SMCLK
      //UCSWRST (Software reset)          = 1b  ->  normally set by a PUC
      UCB0CTL1 = 0x81;                     
      //-------------------------------------------------------------------------
      // DATA RATE
      // Data rate = SMCLK/2 ~= 500kHz
      // UCA0BR1 = 0x00 & UCA0BR0 = 0x02
      //-------------------------------------------------------------------------
      UCB0BR0 = 0x02;                           
      UCB0BR1 = 0x00;
      //-------------------------------------------------------------------------
      //2) END
     
      //3) Configure ports <-BEGIN
      P3SEL |= 0x0E; // P3.1,P3.2,P3.3 option select
     
      //3) END  
     
      //4) Clear UCSWRST via software -> BEGIN                      
      UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      //4) ->END
     
      //5) Enable interrupts -> BEGIN
      // Not used
      //5) -> END
     
     //  IE2 |= UCB0TXIE;                          // Enable USCI_A0 TX interrupt
      IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt
    }

    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCIAB0RX_ISR (void)
    {
      while (!(IFG2 & UCB0RXIFG));              // USCI_A0 TX buffer ready?
        SPI_RxData = UCB0RXBUF;
     
       __bic_SR_register_on_exit(LPM3_bits + GIE);      // Exit LPM0
    }

  • manisha patravali said:
           SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
         
            // start write instruction
            RESET_BUSY_FLAG();                // CS bought to low to start

    This might be too quick. between setting and resetting the flag, only a few MCLK cycles pass. This might be too fast for the slave. Happens twice. It is not necessarily causing a problem, but I can imagine that between the write instruction and teh subsequent read, some delay is necessary.

    manisha patravali said:
    UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08; 

    No need to mask the upper 8 bit. the shift will discard the lower 8 bits anyway. Just an optimization, nothing critical. It is possible that the compiler will discard this part of the instruction anyway on assembly level.

    manisha patravali said:
    UCB0TXBUF = (SPI_MemAddr & 0x00ff); // WRITE LOWER 16 BIT ADDR

    No need for masking here too. The write is to an unsigned char register, so the upper 8 bits will be discarded during the write anyway. Again, maybe the compiler is already optimizing the mask away.

    manisha patravali said:
    Things that I am observing now are with changed code is Rx interrupt is fired only once when I fill tx buffer first time.

    How do you detect it? Debugger breakpoint? If the debugger isn't stopping the clocks (debugger setting), the transfers will continue while the cpu is stopped. And the clock stopping part of the debugger is a bit buggy (the the option names do not match the clocks/timers they are affecting for some MSPs)

    manisha patravali said:
    Why is there only once interrupt fired.

    Interrupts don't stack. So if the same interrupt happens while you didn't handle the first, there' sno way of thelling that there was a second one. In case of the RX interrupt, however, there's the OV bit set (and anothe rinterrupt generated) telling you that the latest byte couldn't be moved into the RX buffer because you didn't read the previous one.

    Anyway, the main problem is this line:

    manisha patravali said:
    __bic_SR_register_on_exit(LPM3_bits + GIE);      // Exit LPM0

    Here you clear the GIE bit unpon return to main. This means, after the first interrupt has been handled (and this ISR has been called the first time) GIE is clear and no more interrupts will be generated. Until your main loop set the GIE bit again, which it doesn't.
    I don' tknow why you have this line anyway, as you never enter LPM3 in main. And LPM3 may disable clocks (see device description) and may halt SPI transfer, causing a deadlock (no SPI, no interrupt and no ISR that wakes up the CPU again).
    At least don't include the GIE bit in the bic_SR instruction, unless you don't want further interrupts.

  • thnaks once again Jens!

    As per your input i commented that "//__bic_SR_register_on_exit(LPM3_bits + GIE);      // Exit LPM0"

    Which is successfuly giving all interrupts.

    I add even more delay in between before making CS signal change.

    But i am still not able to read anything from Memory.

    I am seeing that Slave In and Slave out (SDA, SCL) are always same. is this the behavior?

    I ahve connected Memory SI to SDA and Memory SO to SCL, CS to P3.0 and clk to clk. I hope there is no issue here.

    Is there anything else that i need to take care?

  • I also see that clk generated has some pattern.

    After i send Read Instruction there is some delay (30 micro sec)seen then 16 bit memory addres then delay (32 micro sec) again 0x06 (dummy byte is seen). but i Rx 0x06 only and not read data.

    This observation is for code pasted below:

      RESET_BUSY_FLAG();
             while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
             UCB0TXBUF = READ_INSTR;           //Send read inst to SPI
             __no_operation();  
             __no_operation();  
             __no_operation();
             __no_operation();  
             __no_operation();  
             __no_operation();  
             __no_operation();
             __no_operation();
             __no_operation();  
             __no_operation();
             __no_operation();
             __no_operation();
             __no_operation();  
             __no_operation();
             __no_operation();
             while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
             UCB0TXBUF = (SPI_MemAddr & 0xff00)>>0x08;        // Send 16 bit memory Higher addr
           
             while (!(IFG2 & UCB0TXIFG));                     // USCI_B0 TX buffer ready?
             UCB0TXBUF = (SPI_MemAddr & 0x00ff);            // Send 16 bit memory lower addr
           
             while (!(IFG2 & UCB0TXIFG));                    // USCI_B0 TX buffer ready?
             UCB0TXBUF = 0x06;                               // send dummy data
        
             while(UCB0STAT & UCBUSY);     // check there is no tx and rx happening
             __no_operation();  
              __no_operation();  
              __no_operation();  
              __no_operation();
              __no_operation();
             SET_BUSY_FLAG();                // CS bought to hight to latch the wr instruction
            
              while(UCB0STAT & UCBUSY);     // check there is no tx and rx happening
              __no_operation();  
              __no_operation();  
              __no_operation();  
              __no_operation();
              __no_operation();

     

    But if i reduce the delay to something like this:

      RESET_BUSY_FLAG();
             while (!(IFG2 & UCB0TXIFG));      // USCI_B0 TX buffer ready?
             UCB0TXBUF = READ_INSTR;           //Send read inst to SPI
             __no_operation();  
             __no_operation();  
             __no_operation();
             __no_operation();  

     

    then the pattern seen for clock is : Read Instruction and hiher byte memory go in first 16 clk, Then there is some delay and them we see lower byte and 0x06 going together in next 16 bits.

    what is desirable as per memory spec is :

    Read Instruction forllowed by 16 bit address and then 8 extra clocks for Data to come on the bus.

    Even if i dont add delay i am seeing some delay in how clk cycles are genrated. Can this be controlled? could it be a reason to fail memory read?

     

  • manisha patravali said:
    I am seeing that Slave In and Slave out (SDA, SCL) are always same. is this the behavior?

    Normally not. BTW, it is n't SDA/SCL but rather SOMI and SIMO (Slave Out Master In and Slave In Master Out).

    manisha patravali said:
    I ahve connected Memory SI to SDA and Memory SO to SCL, CS to P3.0 and clk to clk. I hope there is no issue here.

    Other than SDA and SCL are the names for I2C (see above), the wiring seems to be correct.

    What I noticed: I don't see you setting P3.0 as output. There should be a P3DIR|=0x01 somewhere, yet I didn't see it. So if you don't configure P3.0 as output, you cannot pull CS low. And then the memory will simply ignore your efforts.

    Also, some slaves require the UCCKPH or UCCKPL bits set. in UCB0CTL0. UCCKPL being set (incactive state is high) is the required setting for accessing an SD card. Try it with setting this bit. It effectively inverts the clock signal. But looking into the datasheet, it seems that not setting the bit is already the correct setting.

    manisha patravali said:
             UCB0TXBUF = READ_INSTR;           //Send read inst to SPI
             __no_operation();
    ...
    while (!(IFG2 & UCB0TXIFG))

    Well, this doesn'make much sense. You don'T need the NOPs here as you're already waiting for TXIFG after them, (which takes additional time)

    A wait is probably needed AFTER the whole instruction (especially the complete write command including the data) has been sent, before the slave can respond to the readback.

    Also, a quote form the datasheet:

    A read attempt of a memory array location will not be possible during a write cycle. When the write cycle is completed, the write enable latch is reset.

    This means, that after writing the data, you'll have to wait until the write enable latch has been reset in the device status register.

    The required command sequence is:

    CS low
    send WREN instruction
    wait for busy clear
    CS high
    Small delay of >250ns (one cycle@4MHz MCLK)
    CS low
    send write command
    send address
    send data (data may only be sent up to the next page boundary, so no matter at which address you start, you must end writing at the address with the lower 6 bit all one)
    wait for SPi busy bit clear
    CS high
    small delay
    Loop: (this loop will take upto 5ms = 5000 MCLK cycles @1MHz MCLK !!!)
    CS low
    send read status command
    wait for byte receipt
    CS high
    check received status byte for WEL bit clear
    if not: go to Loop again
    CS low
    send read command
    send address
    read as many bytes as you want
    CS high

     

    I just looked even deeper into the datasheet. During the command transmission, the ram is not sending any data, its output is high imedance. So the received 'dummy' byte should be 0xff. Same during write operations such as the destination address, the status write or during data write etc. Since both, slave and master, are high impedance, it may be that the MSP will read the data it is just sending because of crosstalk between the lines.

    It is also possible that you just shortcutted the two lines somehow and the MSP has the stronger output driver.

    Another thing is that the maximum SPI clock frequency depends on the supply voltage. If the slave is powered by 3.3V, the maximum SPI clock is 5MHz. 10MHz is allowed for >4.5V supply (which requires some care when interfacing the MSP) and only 3MHz if run with below 2.5V. Well, your code states that you're using 500kHz, which would be fine if this is really true (your SMCLK is really 1MHz Is it? you don't configure it anywhere)

    Good luck!

**Attention** This is a public forum