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.

Coordinating SPI Flash N25Q00AA with MSP430FR5728 - cannot read/write

Other Parts Discussed in Thread: MSP430FR5728

I am attempting to coordinate two chips to work together in order to write to a separate memory. The two chips I am working with are the N25Q00AA, a Serial NOR Flash Memory manufactured by Micron, and the MSP430FR5728, a MCU manufactured by TI. While working with these chips, I read through their data sheets as well as the following forum post:

 e2e.ti.com/.../1234741

 

While the discussion present there was somewhat helpful, I am still facing serious problems working with this.

 

The first problem faced is that, when attempting to use either of the following two lines of code, the project is stuck and unable to progress any further:

     while ((UCB0IFG & UCTXIFG)== 0);
     while ((UCB0IFG & UCRXIFG) == 0);

When I remove the “UCB0IFG” the code can run, however then I face a significant problem. The MSP430FR5728 fails to read anything from the N25Q00AA, and always outputs “0” when I attempt to print any values read.

The following is the code that I use when trying to Read the Status Register.

 

char FlashByte(char S)

{

UCB0IFG &= UCRXIFG;                           // Clear RX Interupt

UCB0TXBUF = S;                               // Write Byte

while((UCB0IFG & UCTXIFG) == 0);

while((UCB0IFG & UCRXIFG) == 0);

S = UCB0RXBUF;

return S;

}

int main(void)

{

WDTCTL = WDTPW | WDTHOLD;                                    // Stop watchdog timer

PMMCTL0 = PMMPW;                                        // Open PMM Module

PM5CTL0 &= ~LOCKLPM5;                                                // Clear locked IO Pins

 

PJDIR |= 0x02;

PJOUT |= 0x02;

// Configure SPI

UCB0CTL1 = UCSWRST;                           // Enabled

UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3 pin, 8-bit SPI mode?

UCB0CTL1 |= UCSSEL_2;                         // SMCLK

UCB0BR0 |= 0x00;                             // /2

UCB0BR1 = 0;                                 // 1 MHz, 9600 Baud Rate

UCB0CTL1 &= ~UCSWRST;

 

for(;;)

{

   PJOUT ^= BIT1;

   FlashByte(0x06);                          // Write Enable Command

   PJOUT ^= BIT1;

  

   PJOUT ^= BIT1;

   FlashByte(0x05);                          // Read Status Register Command, should output 0x02?

   printf("check = %X\r\n",FlashByte(0xFF));       // Send dummy Byte, then print Status Register

   PJOUT ^= BIT1;

}

}

 

I will also attach a diagram detailing the connections I have created between the MSP430FR5728, and the N25Q00AA., which can be seen below:

 

I feel like if I could just be able to properly read the status register, I can then progress to the next step of trying to write to and read from the N25Q00AA without significant difficulty. If someone could help me to figure out what I am doing wrong, I would greatly appreciate the help

  • He Chris,

    Your SPI initialization needs some work.  Let's go over it some:

    Chris2 said:

    PMMCTL0 = PMMPW;                                        // Open PMM Module

    PM5CTL0 &= ~LOCKLPM5;                                                // Clear locked IO Pins

    These lines aren't necessary on FR57xx devices.

    Chris2 said:

    // Configure SPI

    UCB0CTL1 = UCSWRST;                           // Enabled

    UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3 pin, 8-bit SPI mode?

    UCB0CTL1 |= UCSSEL_2;                         // SMCLK

    UCB0BR0 |= 0x00;                             // /2

    UCB0BR1 = 0;                                 // 1 MHz, 9600 Baud Rate

    UCB0CTL1 &= ~UCSWRST;

    Pins 1.6, 1.7, and 2.2 are not selected for UCB0 operation.  As far as the MSP430 is concerned these are just I/O pins so they will never operate in SPI mode.  Lines needed:

    P1SEL1 |= BIT6 + BIT7;

    P2SEL1 |= BIT2;

    Use UCB0CTL1 |= UCSWRST; instead of UCB0CTL1 = UCSWRST; so that you don't clear out all register contents, only set the one bit.

    UCB0CTL0 & UCB0CTL1 could be the same register, UCB0CTLW0, but this doesn't matter much.

    I'm going to assume that the rest of the SPI initialization is correct since the example you are pulling from is able to read from the N25Q00AA.  Implement the changes given and try to work from there.

    Chris2 said:

    I will also attach a diagram detailing the connections I have created between the MSP430FR5728, and the N25Q00AA., which can be seen below:

     

    Ground ALL Vss pins on the MSP430 device, you can also supply Vcc to AVcc if you plan on using analog pins.  If using 3-pin mode as initialized in your SPI settings then the blue S# line will not do anything, you can ground S# if you plan on always having the device selected.  Otherwise C, DQ0, and DQ1 all seem correct.

    Regards,

    Ryan

  • Hi Ryan,

    Thank you for the response, I cant believe I forgot to select the pins for SPI. Such a dumb mistake to make on my part. I tried fixing up my code with your suggestions but I am still running into the same consistent problem. When I use the following two lines of code, the device is unable to progress pass that point no matter how much time passes:

    while((UCB0IFG & UCTXIFG) == 0);

    while((UCB0IFG & UCRXIFG) == 0);



    When I change those lines of code by removing the "UCB0IFG" completely, the code is able to run, but it does not correctly. When the code runs, all that is being printed are zero's whenever I try to read the status register after I plug in the write enable command. From what I have read, I should be reading 0x02 instead. To me, this must mean that the device isn't actually able to read from the N25Q00AA.


    I do not understand what the "UCB0IFG" is used for, as the Family User Guide for the MSP430FR5728 makes it sound like using only "UCTXIFG" and "UCRXIFG" should be enough. Clearly it is not, and the UCB0IFG needs to be used.... but something must be missing from my code or system to allow it to progress past those lines of code. Any idea's on what I could be missing?
  • Hey Chris,

    Chris2 said:
    while((UCB0IFG & UCTXIFG) == 0);

    Typically this line is while(!(UCB0IFG & UCTXIFG) == 0); and goes before assigning the character S to UCB0TXBUF to make sure that the buffer is empty before sending a character, but I suppose checking afterwards to make sure that the byte has been sent is okay.  Using while((UCB0IFG & UCRXIFG) == 0); is fine because you want to stay in the loop until the UCRXIFG flag changes to one, indicating a received byte.  Once you assign UCA0RXBUF this flag automatically resets.  Just a comment, no immediate action is required.

    Chris2 said:
    When I change those lines of code by removing the "UCB0IFG" completely, the code is able to run, but it does not correctly. When the code runs, all that is being printed are zero's whenever I try to read the status register after I plug in the write enable command. From what I have read, I should be reading 0x02 instead. To me, this must mean that the device isn't actually able to read from the N25Q00AA.

    You are reading zero because the UCB0RXBUF is always 0x00, it is never receiving any characters.  Removing two essential lines of code will not solve your problems.  The line while((UCB0IFG & UCRXIFG) == 0); is essential for recognizing that a byte has been received.  You need to make sure that the correct character is being sent to the N25Q00AA through the MOSI line (use the register window inside of the debugger to check UCA0TXBUF after assigning it the character S to make sure that the character you expect is the character sent) and likewise that a value of 0x02 is being returned through the SOMI line.  You can do this with an oscilloscope or logic analyzer.

    Chris2 said:
    I do not understand what the "UCB0IFG" is used for, as the Family User Guide for the MSP430FR5728 makes it sound like using only "UCTXIFG" and "UCRXIFG" should be enough. Clearly it is not, and the UCB0IFG needs to be used.... but something must be missing from my code or system to allow it to progress past those lines of code. Any idea's on what I could be missing?

    UCTXIFG and UCRXIFG are status bits that exist inside of the UCB0IFG register, therefore the example UCB0IFG & UCRXIFG is checking the status of the UCRXIFG bit inside of the UCB0IFG register.  Just checking UCRXIFG is pointless since it is only a number representation of a bit within a register, UCB0IFG indicates particularly which register it belongs to.

    Regards,

    Ryan

  • Dear Ryan,

    After running the code again, while looking at the status register, I received the following results:

    These results were from running the code multiple times.  Each time I let the code run for approximately 30 seconds longer than previous, and each time when I break the code it will break at this same point.  This screenshot is from after waiting 2 minutes for my code to run, and shows that it simply will not progress further beyond this point. 

    It can be seen that the UCB0TXBUF is obtaining a value of 0x0006 (which is what it should be getting), while the UCB0IFG has a value of 0x0000.  I also tried to run it as you mentioned, using while(!(UCB0IFG & UCTXIFG) == 0); before assigning UCB0TXBUF the value of S, and it does not run then either.  I simply do not know how to fix this problem.

  • Chris,

    The UCB0IFG should be doing something, as this is IAR you could be in simulator mode. In your project options, under the debugger window, is the driver selected Simulator or FET Debugger?

    Regards,
    Ryan
  • Ryan,

    No, I made sure it was in FET Debugger mode before running these tests.

    Chris
  • Okay, I just had to make sure. Why is the value of UCB0CTL0_SPI set to 1? This is not correct and could be the cause of your issues. You need to set up breakpoints and step through your code line by line to make sure that the initialization of your SPI is correct.

    Ryan
  • After inserting break points throughout the section of code I am having trouble with, I noticed a few things.


    First, I took screenshots of the USCI_B0 Register, both pre and post code running.  These are the results:

    Obviously this isn't enough to work with, so I went step by step and found that after UCB0CTL1 &= ~UCSWRST; runs, the results are as follows:

    Once UCB0CTL1 &= ~UCSWRST; is completed, those two values are all that change, and only by one bit.... I am no expert, but I am pretty sure that more should have been accomplished within my SPI Configuration.

    I then began running the code using breaks within the segment of code where the problem is occurring, and noticed that when running the segment FlashByte(0x06); it does the following:

    First, UCB0IFG &= UCRXIFG; takes the initial UCB0IFG__SPI and changes it from 0x0002 to a value of 0x0000

    Second, UCB0TXBUF = S; takes the the initial UCB0TXBUF__SPI and changes it from 0x0000 to a value of 0x0006

    Finally, the segment while((UCB0IFG & UCTXIFG) == 0); could never work, and the code is stuck within the while loop forever

    Ryan Brown1 said:
    Okay, I just had to make sure. Why is the value of UCB0CTL0_SPI set to 1? This is not correct and could be the cause of your issues. You need to set up breakpoints and step through your code line by line to make sure that the initialization of your SPI is correct.

    Ryan

    So could there be a flaw in my SPI Configuration, or could it be due to the problem you suggested where my UCB0CTL0_SPI is still set to 1?

  • Chris2 said:
    Once UCB0CTL1 &= ~UCSWRST; is completed, those two values are all that change, and only by one bit.... I am no expert, but I am pretty sure that more should have been accomplished within my SPI Configuration.

    Yes, a lot more should have been accomplished.  Updates to registers happen line-by-line, not just after resetting UCSWRST.  You should see UCA0CTL0's contents change the line after you set it.  UCB0CTLW0 should be 0xA980 when all is said and done.

    Chris2 said:
    First, UCB0IFG &= UCRXIFG; takes the initial UCB0IFG__SPI and changes it from 0x0002 to a value of 0x0000

    This is because the line should be UCB0IFG &= ~UCRXIFG;, you're ANDing with zero to get zero.

    Regards,

    Ryan

  • So what can I do to fix this?  Only way I can think to fix this is to force-write this change by using these two lines of code:

    UCB0CTL0 ^= 0xA8;
    UCB0CTL1 ^= 0x40;

  • I do not know what the issue here is. Make sure the following lines have been removed:

    PMMCTL0 = PMMPW; // Open PMM Module
    PM5CTL0 &= ~LOCKLPM5; // Clear locked IO Pins

    And play around with altering the UCB0 registers until you find something that works. Do you have any other FR5728 devices you can test with? Let me know when you fix it and how you were able to do it. I do not have a FR5728 device on hand or else I would help debug the matter from my end.

    Regards,
    Ryan
  • I will have to try it out later.  I appear to have burnt out the last my MSP430 chip while messing with the codes (burnt one out earlier, neither are responding to debugging) and I left my spares at home.  If anyone else out there that is in possession of a MSP430FR57xx, and may have an idea of what I may be doing wrong, I would appreciate it if they could debug my code and determine what I am missing.  I will post my edited code below:

    #include "string.h"
    #include "msp430.h"
    #include <stdio.h>

    /***************************************************
                         Flash Code
    ***************************************************/

    char FlashByte(char S)
    {
      UCB0IFG &= ~UCRXIFG;                           // Clear RX Interupt
      UCB0TXBUF = S;                                // Write Byte
      while((UCB0IFG & UCTXIFG) == 0);
      while((UCB0IFG & UCRXIFG) == 0);
      S = UCB0RXBUF;
      return S;
    }

    /***************************************************
                         Main Code
    ***************************************************/

    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;                // Stop watchdog timer

      PJDIR |= 0x02;                               
      PJOUT |= 0x02;                          

         

      // Clock Setup For SPI
      CSCTL0_H = 0xA5;
      CSCTL1 |= DCOFSEL0 + DCOFSEL1;                // Set DCO = 8MHz
      CSCTL2 = SELA_3 + SELS_3 + SELM_3;            // set ACLK = SMCLK = MCLK = DCO
      CSCTL3 = DIVA_3 + DIVS_3 + DIVM_3;            // set all dividers
                                                                                         // ACLK = SMCLK = MCLK = 1MHz

      // Configure SPI
      P1SEL1 |= BIT6 + BIT7;
      P2SEL1 |= BIT2;
      UCB0CTL1 |= UCSWRST;                          // Enabled
      UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC;  // 3 pin, 8-bit SPI mode
      //UCB0CTL0 |= 0xA9;                           // Caused burnout when tried in place of above line
      UCB0CTL1 |= UCSSEL_2;                         // SMCLK
      UCB0BR0 |= 0x00;                              // /2
      UCB0BR1 = 0;                                  // 1 MHz,  9600 Baud Rate
      UCB0CTL1 &= ~UCSWRST;                         // Disabled

      for(;;)
      {
        PJOUT ^= BIT1;
        FlashByte(0x06);
        PJOUT ^= BIT1;
        
        PJOUT ^= BIT1;
        FlashByte(0x05);
        printf("check = %X\r\n",FlashByte(0xFF));
        PJOUT ^= BIT1;

      }

    }

    I was also running some tests in simulation, and noticed that all of the values of the SPI started as zero's.  However, when running with debugging we saw that I started with 0x01C1 for the UCB0CTLW0.  Looking into the MSP430FR57xx Family document, I saw that this state was the same as that of "Reset" which can be seen in the picture below.

    In fact, all of the segments of the SPI were in there "Reset" state when actually debugging (See previous pictures), but in simulation they all started out at Zero.  I am still fairly new to using the MSP430, so is it appropriate for the system to start in this "Reset" state?

    Thanks,

    Chris

  • Chris,

    One more thought, could you possibly try another e_USCI, perhaps UCA0, just to see what happens?

    Chris2 said:
    I appear to have burnt out the last my MSP430 chip while messing with the codes (burnt one out earlier, neither are responding to debugging)

    Can you provide any more details regarding this?  MSP430 devices should not simply be "burning out."

    Chris2 said:
    In fact, all of the segments of the SPI were in there "Reset" state when actually debugging (See previous pictures), but in simulation they all started out at Zero.  I am still fairly new to using the MSP430, so is it appropriate for the system to start in this "Reset" state?

    In short, yes.  The simulator is unaware of device state so it starts out with all zeros.  A properly connected and programmed MSP430 will have all registers set to the reset state.

    Regards,

    Ryan

  • Ryan Brown1 said:

    Can you provide any more details regarding this?  MSP430 devices should not simply be "burning out."

    I connect my MSP430 to my computer through the use of a launchpad, a QFN24 Socket Adapter, and several wires.  After trying to run a code using this setup, I received a error message basically stating that no connection could be made.  after several attempts to debug, rewiring my setup, and completely restarting my computer, the problem persisted.  I then switched out the MSP with a new one, tried again, and it worked perfectly.  I switched back and the problem happened again and again until I switched once more to the new one.

    Ryan Brown1 said:

    Chris,

    One more thought, could you possibly try another e_USCI, perhaps UCA0, just to see what happens?

    I can try.  If it proves to simply be the UCB0, this could prove problematic for what I wish to do in the future though with this project.

    Thank you by the way for the quick and consistent responses, I do appreciate all the help you are providing me with.

    Regards,

    Chris

  • Chris2 said:
    I connect my MSP430 to my computer through the use of a launchpad, a QFN24 Socket Adapter, and several wires.

    Okay, any number of things could be happening to the MSP430 then.  Not the best setup but I understand if you have no choice otherwise.

    Chris2 said:
    If it proves to simply be the UCB0, this could prove problematic for what I wish to do in the future though with this project.

    I don't think it is the UCB0, I'd just like to get something working (or not working on another e_USCI) and move from there.

    Ryan

  • Ryan,

    I have been trying to test using UCA0, and no successful results. I also noted that when running it in simulation, the following line is not having any effect on the value of UCA0CTLW0__SPI:

    UCA0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC;

    This proves true for USB0CTL0 as well. When running in simulation for either UCA0 or UCB0, however, the value of UCA0BTL1__SPI does change, to the correct value of 0x80. The only way I can successfully change UCA0CTLW0__SPI (in simulation at the least) is to use a line of code like the following:

    UCA0CTL0 |= 0xA9;

    While this seems like a easy workaround, I am worried about what unexpected side effects this may cause. Especially since in order for this to work for debugging, I would need the line of code to be as the following:

    UCA0CTL0 |= 0xA8;
    UCA0CTL0 ^= 0x40;

    Any suggestions as to why the first line of code that I listed in this post does not wish to work?  It cant possibly be the software I am using, IAR Embedded Workbench, that is causing this problem, could it?

    Thanks,
    Chris

    EDIT:

    I ran some more tests, and examined some sample code for the MSP430FR57xx, and found out where my problem was regarding this.  during simulations, I have now been able to successfully write to the UCA0CTLW0__SPI.  It was a matter of simply missing a single letter within the line of code.I will now proceed to test and see if this works in debugging.  more to come soon

  • The system is able to run, but still cannot yet read from the Flash Memory.   Below is the segment of my code in which I set the SPI specifications:

     P1SEL1 |= BIT6 + BIT7;

     P2SEL1 |= BIT2;

     UCB0CTLW0 |= UCSWRST;                     // **Put state machine in reset**

     UCB0CTLW0 |= UCMST+UCSYNC+UCCKPL+UCMSB+UCCKPH;   // 3-pin, 8-bit SPI master

                                               // Clock polarity high, MSB

     UCB0CTLW0 |= UCSSEL_1;                    // ACLK

     UCB0BR0 = 0x02;                           // /2

     UCB0BR1 = 0;                              //

     UCB0CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**

     UCB0IE |= UCRXIE;                         // Enable USCI_A0 RX interrupt

    It is worth noting that, in order for the system to even run, I needed to include "UCCKPL" when declaring variables related to the UCB0CTLW0 register.  I do not, however, understand what this does and why it is needed in the first place.  From what I read on the MSP430FR57xx Family User Guide, it sets the "clock polarity inactive state to high" which I am not sure exactly what this means.  

    EDIT:

    As I looked more into my code, I noticed that my PJ.1 started in LOW this whole time.  I believe that this is fixed, so now it is HIGH at first, and then eventually goes low whenever using FlashByte(#x##).  When testing this, I did confirm that now the system has PJ.1 starting in HIGH, however the system still does not yet work.  This could still have to do with the UCCKPL problem I noted before.

  • Chris,

    UCCKPL and UCCKPH relate to the SPI mode in which the MSP430 is expected to communicate with the slave device, in this case the N25Q00AA whose datasheet on pages 16 and 17 indicate that both UCCKPL and UCCKPH must either be on or off for successful communication to proceed. This could explain why setting UCCKPL causes the system to run, at this point communication has possibly been achieved you could be receiving a response from the slave device.

    Regards,
    Ryan
  • After many failed attempted to try and write to and read from the device, I have since altered my code greatly.  I am setting a new step-goal, to help lead me to my ultimate goal of being able to write to and read from the device.  this goal is to Read the Manufacturer and Device ID of the N25Q00AA.  However, my attempts have all failed and the code simply freezes at a certain point.  I am unable to break the code at that point, and am forced to stop the debugging process each time.  I will post the code below, and highlight the point at which the error occurs. 

    #include "string.h"
    #include "msp430.h"
    #include <stdio.h>

    /***************************************************
                         Flash Code
    ***************************************************/

    int FlashByte(int S)
    {
      UCB0IFG &= ~UCRXIFG;                           // Clear RX Interupt
      UCB0TXBUF = S;                                // Write Byte
      while((UCB0IFG & UCTXIFG) == 0);
      while((UCB0IFG & UCRXIFG) == 0);
      return(UCB0RXBUF);
    }

    /***************************************************
                         Main Code
    ***************************************************/

    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                // Stop watchdog timer

      PJDIR |= BIT1;                                
      PJOUT &= ~BIT1;    
      PJOUT ^= BIT1;                                // Sets CSn to high
     
      // Clock Setup For SPI
      CSCTL0_H = 0xA5;
      CSCTL1 |= DCOFSEL0 + DCOFSEL1;             // Set max. DCO setting
      CSCTL2 = SELA_3 + SELS_3 + SELM_3;        // set ACLK = XT1; MCLK = DCO
      CSCTL3 = DIVA_3 + DIVS_3 + DIVM_3;        // set all dividers

      // Configure SPI

      P1SEL1 |= BIT6 + BIT7;
      P2SEL1 |= BIT2;
      UCB0CTLW0 |= UCSWRST;                     // **Put state machine in reset**
      UCB0CTLW0 |= UCMST+UCSYNC+UCMSB+UCCKPL+UCCKPH;   // 3-pin, 8-bit SPI master
                                                // Clock polarity high, MSB
      UCB0CTLW0 ^= 0x00C0;
      UCB0CTLW0 |= UCSSEL_2;                    // ACLK
      UCB0BR0 = 0x00;                           // /2
      UCB0BR1 = 0;                              //
      UCB0CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**

      for(;;)
      {
        PJOUT ^= BIT1;
        FlashByte(0x20);
        printf("check = %X\r\n",FlashByte(0xFF));
        PJOUT ^= BIT1;
      }
    }

    If anyone has any idea what is causing this new error, then please let me know and I would appreciate the help.

  • Receiving the following Error:

    The stack pointer for stack 'Stack' (currently Memory:0x0) is outside the stack range (Memory:0x1F60 to Memory:0x2000)
  • I have fixed my code up greatly. It is now able to run fully, however there are still difficulties. I am not receiving any output from the slave device, and am not sure why this is. The program appears to be outputting the proper TX, but I am not getting anything back in the RX. I will post the code I am working with below:


    /***********************************************************
    Code Goal: Write a Byte of data to address of N25Q00AA.
    After which, read the same address to prove that the
    data byte was properly recorded to the N25Q00AA.

    Write: Datasheet states need to Enable Write, send 3 address
    bytes, and requires the READ FLAG STATUS REGISTER command being
    issued with at least one byte output.

    Read: send 3 address bytes of where want to read

    Program: IAR Embedded Workbench IDE
    MCU: MSP430FR5728
    SPI: B0 mode selected from device
    UCB0SIMO: P1.6
    UCB0S0MI: P1.7
    UCB0CLK: P2.2
    CSn: PJ.1
    ***********************************************************/

    #include "string.h"
    #include "msp430.h"
    #include <stdio.h>

    char b1 = 0x03; // Flash Addr Part 1 for Write
    char b2 = 0xFF; // Flash Addr Part 2 for Write
    char b3 = 0xFF; // Flash Addr Part 3 for Write

    char b4 = 0x03; // Flash Addr Part 1 for Read
    char b5 = 0xFF; // Flash Addr Part 2 for Read
    char b6 = 0xFF; // Flash Addr Part 3 for Read

    char Q;

    /***************************************************
    Flash Code
    ***************************************************/

    char FlashByte(char S){ // General FlashByte Transmit
    UCB0TXBUF = S;
    while (!(UCB0IFG & UCTXIFG));
    return (UCB0RXBUF);
    }

    char FlashComW(char x) // Write Command and Address
    {
    FlashByte(x); // Send Command and Address
    FlashByte(b1);
    FlashByte(b2);
    FlashByte(b3);
    Q = FlashByte(0xAA); // Send value to write
    return(Q);
    }

    char FlashComR(char x) // Read Command and Address
    {
    FlashByte(x); // Send Command and Address
    FlashByte(b4);
    FlashByte(b5);
    FlashByte(b6);
    Q = FlashByte(0xFF); // Send dummy value so read
    return(Q);
    }

    /***************************************************
    Main Code
    ***************************************************/

    int main(void){
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    PJDIR |= 0x02;
    PJOUT |= 0x02;

    // Clock Setup For SPI
    CSCTL0_H = 0xA5;
    CSCTL1 |= DCOFSEL0 + DCOFSEL1; // Set DCO = 8MHz
    CSCTL2 = SELA_3 + SELS_3 + SELM_3; // set ACLK = SMCLK = MCLK = DCO
    CSCTL3 = DIVA_3 + DIVS_3 + DIVM_3; // ACLK = SMCLK = MCLK = 1MHz

    // Configure SPI
    P1SEL1 |= BIT6 + BIT7; // Set pins for primary purpose
    P2SEL1 |= BIT2; // Set pin for primary purpose
    UCB0CTLW0 |= UCSWRST; // **Put state machine in reset**
    UCB0BR0 = 0x02; // /2
    UCB0BR1 = 0; //
    UCB0CTLW0 = UCMST|UCSYNC|UCMSB|UCSSEL_2|UCSWRST;


    for(;;){

    /****** Write ******/
    // Write Enable Command
    PJOUT ^= BIT1;
    FlashByte(0x06);
    PJOUT ^= BIT1;
    // Write Command/Address
    PJOUT ^= BIT1;
    FlashComW(0x02);
    PJOUT ^= BIT1;
    // Write Disabled
    PJOUT ^= BIT1;
    FlashByte(0x04);
    PJOUT ^= BIT1;
    // Read Flag Status Register
    PJOUT ^= BIT1;
    FlashByte(0x70);
    PJOUT ^= BIT1;

    /****** Read ******/
    // Read Command/Address
    PJOUT ^= BIT1;
    printf("check = %X\r\n",FlashComR(0x03));
    PJOUT ^= BIT1;

    /****** Erase ******/
    // Write Enable Command
    PJOUT ^= BIT1;
    FlashByte(0x06);
    PJOUT ^= BIT1;
    // Erase Command/Address
    PJOUT ^= BIT1;
    FlashComW(0x20);
    PJOUT ^= BIT1;
    // Write Disabled
    PJOUT ^= BIT1;
    FlashByte(0x04);
    PJOUT ^= BIT1;
    }
    }
  • I don't like that you are using PJOUT ^= BIT1. How do you know that it was in correct state to begin with and always is in the state you want.
    You should use PJOUT |= BIT1; to set it high when you want it high.
    You should use PJOUT &= ~BIT1 to set it low when you want it low.

    Are you capturing the signals with a logic analyzer or oscilloscope to verify the signalling between the MSP and the FLASH chip is correct per the requirements in the FLASH datasheet?

    Also, please select the "Use rich formatting" link right below the reply box to bring up the rich editor and then use the [<>] button to post code. It is very difficult to try to read the unformatted/unindented code you've been posting.
  • Your FlashByte function probably does not do what you want. After writing to TXBUF, it waits for TXIFG being set again. Then you read RXBUF. However, if you start an operation, TXIFG is set again immediately. Nothing has been received yet. Maybe you should wait for TXIFG before you write to TXBUF and wait for RXIFG before reading. This is safe, but of course does not provide maximum throughput. But with your high SPI clock speed, you're already much slower with calling FlashByte than the USCI needs for sending a byte.

    In your original code, you did set UCPH. In most (but by far not all) cases, UCPL is the one to set (clock is active-low). In your current code, you don't set any of the two. You should double-check the required signals and not rely on option names (TI and Motorola differ in the meaning of the options)

    Since your FlashByte returns before the byte is completely sent, you might de-assert CS far too soon. Which will make the slave ignoring the byte that is just coming in (missing the last bits), and maybe the whole command sequence. Before de-asserting CD, you should wait for UCBUSY to clear, which means the current transmission is complete, independent of clock phase (with UCPH set, RXIFG is set 1/2 clock cycle before the transmission really ended, so on slower clock speeds, this is important, even if you already wait for RXIFG).

**Attention** This is a public forum