EmbeddedRelated.com
Forums
Memfault Beyond the Launch

at45db read write not working

Started by Onur Yildirim November 21, 2005
Hi,

I have an AT45DB161 flash memory chip connected to our msp430F1611
running at 8Mhz. Here is the connection scheme.

P5.1  ->  SI
P5.2  <-  SO
P5.3  ->  SCLK
P5.4  ->  /CS
P5.5  ->  /RST

P1.0  ->  RDY-/BUSY

After power up, initialize clocks and etc, AT45 is initialized with
the fFlash_InitHW_Active().

The AT45 is reset with fFlash_Reset().

Then to check if the flash memory is ok, fFlash_RStatus_Once() is
called. But this function returns an unexpected 0x00.

I am sure there is a simple mistake in the software. I have checked
the soldering and pin configuration but everything seems to be ok.

If you can spot any mistakes in the below pasted code I would be grateful.

Thanks in advance.
Onur Yildirim.

void fFlash_InitHW_Active(void)
{
  P5OUT |=  0x30;	// /CS and /RST high
  P5DIR |=  0x30;	// /CS and /RST output
  P5SEL &= ~0x30;	// P5.5 and P5.4 IO function

  P5DIR |=  0x0A;	// P5.1(SIMO) and P5.3 (CLK) ouput
  P5DIR &= ~0x04;	// P5.2(SOMI) input
  P5SEL |=  0x0E;	// P5.1 P5.2 P5.3 UART functns

  U1CTL  = 0x17;	// 8bit SPI in master mode
  U1TCTL = 0x23;	// SPI mode?, ACLK 3 pin mode
  U1BR0  = 2;	// Clock divider=2 -> SPI clock = ACLK/2
  U1BR1  = 0;
  U1MCTL = 0;

  ME2_bit.USPIE1  = 1;      // enable SPI channel1
  U1CTL_bit.SWRST = 0;   // end reset

  IE2_bit.UTXIE1  = 0;	// disable tx interrupt for now
  IE2_bit.URXIE1  = 0;	// disable rx interrupt for now
}

void fFlash_Reset(void)
{
  // ASSUMES 8MHz MCLK for 10 microsec delay
  // (more than 2.5 millisec if 32 kHz)
  // reset pulse (at least 10 microsec)

  P5OUT &= ~P5OUT_5;	//set low
  for (volatile int i=0; i<20; i++) {};

  P5OUT |=  P5OUT_5;	//set high
  for (volatile int i=0; i<20; i++) {};
}

unsigned char fFlash_RStatus_Once(void)
{
  // Reads status register from flash

  fFlash_CSHi();
  fFlash_CSLo();

  fFlash_W(kFlash_Cmnd_ReadStatus);  // kFlash_Cmnd_ReadStatus = 0xB7

  return fFlash_RW(0x00);
}

inline void fFlash_CSHi(void)
{
  //programmed io , assume tx register empty

  P5OUT |= 0x10;	// /CS high

  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  return;
}

inline void fFlash_CSLo(void)
{
  //programmed io , assume tx register empty

  P5OUT &= ~(0x10);	// /CS high

  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
  return;
}

inline void fFlash_W(unsigned char outbyte)
{
  // Writes a byte if TX register empty.
  // Does not wait for received byte.
  // Programmed IO, assume TX register empty.

  while (!(IFG2_bit.UTXIFG1)){};      // wait for txreg to empty
  U1TXBUF=outbyte;                    // write byte
}

inline unsigned char fFlash_RW(unsigned char outbyte)
{
  // Programmed IO, assume TX register empty

  unsigned char res;
  while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for last data

  res		= U1RXBUF;    // get byte
  U1TXBUF	= outbyte;	      // write byte
  return res;
}

Beginning Microcontrollers with the MSP430

The data sheet says that opcode 0xD7 returns device status.  Your code says
that 0xB7 returns status (albeit in a comment only)...

/Bill


> Hi,
> 
> I have an AT45DB161 flash memory chip connected to our msp430F1611
> running at 8Mhz. Here is the connection scheme.
> 
> P5.1  ->  SI
> P5.2  <-  SO
> P5.3  ->  SCLK
> P5.4  ->  /CS
> P5.5  ->  /RST
> 
> P1.0  ->  RDY-/BUSY
> 
> After power up, initialize clocks and etc, AT45 is initialized with
> the fFlash_InitHW_Active().
> 
> The AT45 is reset with fFlash_Reset().
> 
> Then to check if the flash memory is ok, fFlash_RStatus_Once() is
> called. But this function returns an unexpected 0x00.
> 
> I am sure there is a simple mistake in the software. I have checked
> the soldering and pin configuration but everything seems to be ok.
> 
> If you can spot any mistakes in the below pasted code I would be grateful.
> 
> Thanks in advance.
> Onur Yildirim.
> 
> void fFlash_InitHW_Active(void)
> {
>   P5OUT |=  0x30;	// /CS and /RST high
>   P5DIR |=  0x30;	// /CS and /RST output
>   P5SEL &= ~0x30;	// P5.5 and P5.4 IO function
> 
>   P5DIR |=  0x0A;	// P5.1(SIMO) and P5.3 (CLK) ouput
>   P5DIR &= ~0x04;	// P5.2(SOMI) input
>   P5SEL |=  0x0E;	// P5.1 P5.2 P5.3 UART functns
> 
>   U1CTL  = 0x17;	// 8bit SPI in master mode
>   U1TCTL = 0x23;	// SPI mode?, ACLK 3 pin mode
>   U1BR0  = 2;	// Clock divider=2 -> SPI clock = ACLK/2
>   U1BR1  = 0;
>   U1MCTL = 0;
> 
>   ME2_bit.USPIE1  = 1;      // enable SPI channel1
>   U1CTL_bit.SWRST = 0;   // end reset
> 
>   IE2_bit.UTXIE1  = 0;	// disable tx interrupt for now
>   IE2_bit.URXIE1  = 0;	// disable rx interrupt for now
> }
> 
> void fFlash_Reset(void)
> {
>   // ASSUMES 8MHz MCLK for 10 microsec delay
>   // (more than 2.5 millisec if 32 kHz)
>   // reset pulse (at least 10 microsec)
> 
>   P5OUT &= ~P5OUT_5;	//set low
>   for (volatile int i=0; i<20; i++) {};
> 
>   P5OUT |=  P5OUT_5;	//set high
>   for (volatile int i=0; i<20; i++) {};
> }
> 
> unsigned char fFlash_RStatus_Once(void)
> {
>   // Reads status register from flash
> 
>   fFlash_CSHi();
>   fFlash_CSLo();
> 
>   fFlash_W(kFlash_Cmnd_ReadStatus);  // kFlash_Cmnd_ReadStatus = 0xB7
> 
>   return fFlash_RW(0x00);
> }
> 
> inline void fFlash_CSHi(void)
> {
>   //programmed io , assume tx register empty
> 
>   P5OUT |= 0x10;	// /CS high
> 
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   return;
> }
> 
> inline void fFlash_CSLo(void)
> {
>   //programmed io , assume tx register empty
> 
>   P5OUT &= ~(0x10);	// /CS high
> 
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation();	// minimum CS high time%0 nsec (about 2 MCLK)
>   return;
> }
> 
> inline void fFlash_W(unsigned char outbyte)
> {
>   // Writes a byte if TX register empty.
>   // Does not wait for received byte.
>   // Programmed IO, assume TX register empty.
> 
>   while (!(IFG2_bit.UTXIFG1)){};      // wait for txreg to empty
>   U1TXBUF=outbyte;                    // write byte
> }
> 
> inline unsigned char fFlash_RW(unsigned char outbyte)
> {
>   // Programmed IO, assume TX register empty
> 
>   unsigned char res;
>   while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for last
data
> 
>   res		= U1RXBUF;    // get byte
>   U1TXBUF	= outbyte;	      // write byte
>   return res;
> }
> 
> 
> 
> .
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  

Hi Bill,

--- In msp430@msp4..., w.sell@c... wrote:
>
> The data sheet says that opcode 0xD7 returns device status.  Your code says
that 0xB7 returns status (albeit in a comment only)...
>
> /Bill

Yes, you are most definetely correct but I checked that constants
value and it was set as 0xD7 in the header file. So I guess that was
only a wrongly typed comment.

Thank you very much for your time though.
Onur Yildirim.

Onur,

Perhaps you should modify your fFlash_RW function to read as follows:

    inline unsigned char fFlash_RW(unsigned char outbyte)
    {
      // Programmed IO, assume TX register empty

      unsigned char res;
      while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for last
data
      U1TXBUF = outbyte;       // write byte

      while( !(IFG2 & URXIFG1)) {}; //wait for rx data
      res = U1RXBUF;    // get byte

      return res;
    }

The response from the DataFlash comes through on the empty ( 0x00 ) byte
being transmitted, so you want to read after it has been sent.

HTH,


Matt Sabino


----- Original Message ----- 
From: "Onur Yildirim" <onur.yildirim@onur...>
To: <msp430@msp4...>
Sent: Monday, November 21, 2005 1:29 PM
Subject: [msp430] at45db read write not working


> Hi,
>
> I have an AT45DB161 flash memory chip connected to our msp430F1611
> running at 8Mhz. Here is the connection scheme.
>
> P5.1  ->  SI
> P5.2  <-  SO
> P5.3  ->  SCLK
> P5.4  ->  /CS
> P5.5  ->  /RST
>
> P1.0  ->  RDY-/BUSY
>
> After power up, initialize clocks and etc, AT45 is initialized with
> the fFlash_InitHW_Active().
>
> The AT45 is reset with fFlash_Reset().
>
> Then to check if the flash memory is ok, fFlash_RStatus_Once() is
> called. But this function returns an unexpected 0x00.
>
> I am sure there is a simple mistake in the software. I have checked
> the soldering and pin configuration but everything seems to be ok.
>
> If you can spot any mistakes in the below pasted code I would be grateful.
>
> Thanks in advance.
> Onur Yildirim.
>
> void fFlash_InitHW_Active(void)
> {
>   P5OUT |=  0x30; // /CS and /RST high
>   P5DIR |=  0x30; // /CS and /RST output
>   P5SEL &= ~0x30; // P5.5 and P5.4 IO function
>
>   P5DIR |=  0x0A; // P5.1(SIMO) and P5.3 (CLK) ouput
>   P5DIR &= ~0x04; // P5.2(SOMI) input
>   P5SEL |=  0x0E; // P5.1 P5.2 P5.3 UART functns
>
>   U1CTL  = 0x17; // 8bit SPI in master mode
>   U1TCTL = 0x23; // SPI mode?, ACLK 3 pin mode
>   U1BR0  = 2; // Clock divider=2 -> SPI clock = ACLK/2
>   U1BR1  = 0;
>   U1MCTL = 0;
>
>   ME2_bit.USPIE1  = 1;      // enable SPI channel1
>   U1CTL_bit.SWRST = 0;   // end reset
>
>   IE2_bit.UTXIE1  = 0; // disable tx interrupt for now
>   IE2_bit.URXIE1  = 0; // disable rx interrupt for now
> }
>
> void fFlash_Reset(void)
> {
>   // ASSUMES 8MHz MCLK for 10 microsec delay
>   // (more than 2.5 millisec if 32 kHz)
>   // reset pulse (at least 10 microsec)
>
>   P5OUT &= ~P5OUT_5; //set low
>   for (volatile int i=0; i<20; i++) {};
>
>   P5OUT |=  P5OUT_5; //set high
>   for (volatile int i=0; i<20; i++) {};
> }
>
> unsigned char fFlash_RStatus_Once(void)
> {
>   // Reads status register from flash
>
>   fFlash_CSHi();
>   fFlash_CSLo();
>
>   fFlash_W(kFlash_Cmnd_ReadStatus);  // kFlash_Cmnd_ReadStatus = 0xB7
>
>   return fFlash_RW(0x00);
> }
>
> inline void fFlash_CSHi(void)
> {
>   //programmed io , assume tx register empty
>
>   P5OUT |= 0x10; // /CS high
>
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   return;
> }
>
> inline void fFlash_CSLo(void)
> {
>   //programmed io , assume tx register empty
>
>   P5OUT &= ~(0x10); // /CS high
>
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   __no_operation(); // minimum CS high time%0 nsec (about 2 MCLK)
>   return;
> }
>
> inline void fFlash_W(unsigned char outbyte)
> {
>   // Writes a byte if TX register empty.
>   // Does not wait for received byte.
>   // Programmed IO, assume TX register empty.
>
>   while (!(IFG2_bit.UTXIFG1)){};      // wait for txreg to empty
>   U1TXBUF=outbyte;                    // write byte
> }
>
> inline unsigned char fFlash_RW(unsigned char outbyte)
> {
>   // Programmed IO, assume TX register empty
>
>   unsigned char res;
>   while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for last
data
>
>   res = U1RXBUF;    // get byte
>   U1TXBUF = outbyte;       // write byte
>   return res;
> }


Hi Matt,

> Perhaps you should modify your fFlash_RW function
to read as follows:
>
>    inline unsigned char fFlash_RW(unsigned char outbyte)
>    {
>      // Programmed IO, assume TX register empty
>
>      unsigned char res;
>      while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for last
> data
>      U1TXBUF = outbyte;       // write byte
>
>      while( !(IFG2 & URXIFG1)) {}; //wait for rx data
>      res = U1RXBUF;    // get byte
>
>      return res;
>    }
>
> The response from the DataFlash comes through on the empty ( 0x00 ) byte
> being transmitted, so you want to read after it has been sent.


Thank you very much for the hint. I will try and get back as soon as possible.

Regards,
Onur Yildirim

Hi,

It was just wrongly configured SPI situation. After correcting
configuration settings it seems to work well now.

Thanks anyway.
Onur

> > Perhaps you should modify your fFlash_RW
function to read as follows:
> >
> >    inline unsigned char fFlash_RW(unsigned char outbyte)
> >    {
> >      // Programmed IO, assume TX register empty
> >
> >      unsigned char res;
> >      while (!(U1TCTL_bit.TXEPT)){}; // wait for txshift empty wait for
last
> > data
> >      U1TXBUF = outbyte;       // write byte
> >
> >      while( !(IFG2 & URXIFG1)) {}; //wait for rx data
> >      res = U1RXBUF;    // get byte
> >
> >      return res;
> >    }
> >
> > The response from the DataFlash comes through on the empty ( 0x00 )
byte
> > being transmitted, so you want to read after it has been sent.


Memfault Beyond the Launch