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.

Problem interfacing MSP430 with EE Prom SST25VF016B

Other Parts Discussed in Thread: MSP430F5529

Hi all,

My name is Kevin Meyer and I am a student at Boston University. One component of my senior design project involves interfacing an MSP430 with an EEProm, specifically the SST25VF016B. Right all I am trying to do is read the status register of the EE prom. Thus far, I have been unsuccessful in this task. The status reigster is either all zeros or all ones. (it should read 0x1C) If you could offer any insight into my problem it would be greatly appreciated. Below are relevant portions of code and the schematic I am using to connect the device. Most of my code is based on an application note. I am using the USCI_B1 communications module (SPI).

Thank you for your time,

Kevin 

#include <msp430f5529.h>

#define SCLK BIT3 //P4.3 Slave Clock
#define SOMI BIT2 //P4.2 Slave out master in
#define SIMO BIT1 //P4.1 Slave in master out
#define CE BIT0 //P4.0 Clock of system


#define READ 0x03 // READ instruction
#define WRITE 0x02 // WRITE instruction
#define WREN 0x06 // WRITE ENABLE instruction
#define RDSR 0x05 // READ STATUS register instruction
#define WRSR 0x01 // WRITE STATUS REGISTER instruction
#define NOPROT 0x00 // disable all write protections


unsigned int i=0;
unsigned char status_register=0x00;

void flash_init_gpio(void)
{
P4SEL |= SOMI + SIMO + SCLK; // P3.3,4 use special function
P4DIR |= CE; //Set P3.0 Gpio as chip enable
P4OUT |= CE;
}
void flash_init_module(void)
{
UCB1CTL1 |= UCSWRST; // **Put state machine in reset**
/*
Bit 7: Clock phase select
Clear UCCKPH...data is changed on first UCLK edge and captured on following
Bit 6: Clock polarity select
Clear UCCKPL...inactive state is low
Bit 5: Direction of recieve and transmt shift register
Set UCMSB...MSB first
Bit 4: Character Length
Clear UC7BIT...8-bit data
Bit 3: Master mode select
Set UCMST...Master mode (msp430 provides clock)
Bit 2-1: 4-pin SPI with CE (UCxSTE active low) (slave enabled when UCxSTE=0)
UCMODEx=00 or set UCMODE_0
Bit 0: Synchronous mode enable
Set UCSYNC Bit...Synchronous mode
*/
UCB1CTL0 &= ~(UCCKPH + UUCKPL + UC7BIT);
UCB1CTL0 |= UCMSB + UCMST + UCMODE_0 + UCSYNC;
UCB1CTL1 |= UCSSEL_2; // SMCLK
UCB1BR0 = 0x02; // /2
UCB1BR1 = 0; //
UCB1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
UCB1IE |= UCRXIE; // Enable USCI_A0 RX interrupt
}
/*Basic Function: Chip enable/diable, basic write, basic read */

void chip_enable(void)//enable chip through SS line
{
P3OUT |= CE;
P3OUT &= ~CE;
}
void chip_disable(void)//disable chip through
{
P3OUT &= ~CE;
P3OUT |= CE;
}
void write(unsigned char byte)
{
while (!(UCB1IFG & UCTXIFG)); // USCI_A0 TX buffer ready?
UCB1TXBUF = byte; // Transmit message
while (!(UCB1IFG & UCRXIFG)); // wait until something receives. This also means that sending is completed
UCB1IFG &= ~ UCRXIFG; //clear flag
}
unsigned char read(void) //read a 8bit character
{
write(0xFF);//clear buffer
return UCB1RXBUF;
}
/* write enable, write protect, and Status Register Functions */

void write_enable(void)//enable writng
{
chip_enable();
write(WREN);
chip_diable();
}
void disable_writeprotect(void)
{
write_enable();
write_status_register(0x00);//write no protection
}
void write_status_register(unsigned char status)//write to status register
{
chip_enable();
write(WRSR);
write(status);
chip_disable();
_delay_cycles(10000);//should be 5 ms ...try using timers
is_busy();
}
unsigned char read_status_register(void)
{
unsigned char status_reg;
chip_enable();
write(0x05);
status_reg=read();
chip_disable();
return status_reg;
}
void is_busy(void)//polls to see if status register bit is still busy
{
while(read_status_register() & 0x01);//stuck in this function while the flash is busy
}

void main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
flash_init_gpio();
flash_init_module();
_delay_cycles(100000);//wait for flash to power up
read_status_register();//read status register
__bis_SR_register(LPM4_bits + GIE); // Enter LPM4, enable interrupts
}

  • First, let me acknowledge that you did a good job of asking a question and documenting your setup. I wish everyone who posted here knew how to do this.

    Now, I didn't go through your code with a fine toothed comb, because I wonder if you've put scope probes on the interface pins and taken a look at what happens when when you try to access the memory device. Do you see /CS go low? Do clock pulses come out? Do you see the correct command bits going to the memory? These are basic questions to look at when debugging embedded hardware systems.

  • Kevin Meyer2 said:
    void chip_enable(void)//enable chip through SS line
    {
    P3OUT |= CE;
    P3OUT &= ~CE;
    }
    void chip_disable(void)//disable chip through
    {
    P3OUT &= ~CE;
    P3OUT |= CE;
    }

    Both functions toggle the CE line. Many slaves don't like short pulses on CE.  Just do what the function says: enable it or disable it.  But doN't shortly enable it when you call disable and v.v.
    Also, ensure the proper time after enabling (or rather asserting) CE and start of transmission, and also ensure that the transmission ahs actually ended, before you de-assert CE.

    Your code doesn't synhronize with the transfer. If you write to TXBUF, the CPU doesn't wait until the data is actually sent. Also, if you write to TXBUF and then immediately read RXBUF, you'll get the result from the last transfer because the current transfer isn't done yet. And if you then imemdiately de-assert CS, the slave will be disabled before the current transfer even completes (shiftign the remaining data into the void and fetchign the remaining input bit from the void)

    The USCI module signals with the RXIFG and TXIFG bits when TXBUF is empty (which means that you can write a new byte to TXBUF but doesn't mean that the previous byte has been sent) and RXIFG means that a new byte has arrived in RXBUF. Due to the buffers, you have an interleave between the poutgoing and incoming data:

    If you write to TXBUF and then (after TXIFG is set) immediately write to TXBUF again, it means that

    • the byte previously written to TXBUF is currently being sent
    • the answer to the command before this previously written byte is being received
    • RXBUF still holds a byte received as result to the data sent three bytes before (in this case the power-on value as the slave never received a byte yet)

    Once the first byte is sent, the second byte moves from TXBUF to the output shift register, TXIFG is set and at the same time RXIFG is set indicating that a byte was received. Which still is a dummy, as the slave has just received the first byte and has to send an answer now.

    If the bytes you send are not commands but just dummy bytes to generate a clock, still you have to wait until the byte is sent before you can read the incoming data from RXBUF.

**Attention** This is a public forum