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.

NAND Flash Read/Write Problems

Other Parts Discussed in Thread: MSP430F5638

Hello Everyone,

I am working with an MSP430F5638 and trying to interface with a 2G Micron NAND Flash chip. I am able to successfully read the device ID and the parameters, however, I am not able to successfully write to the flash chip. I am also able to read from the flash chip, I know this because when I read from the chip I get 0xFF, which is the default state for this NAND flash chip. I think there are two reasons for this, the first is I am confused on the address structure. I have looked at various application notes and I think I have an idea, but it is very confusing. The first byte out of five transmitted is the LSB of the address, which corresponds to the LSB of the Byte address in the Page. Then comes more of the byte-in-page, then page address with two bits of the block address and the remaining bytes/bits are the actual block/plane (I hope that makes sense). I suspect my second issue is some problem with my code, but I am not sure what. I have looked at all of the pins on an oscilliscope, and everything seems to be lining up.

I have posted my header file, driver code and main code below. I would appreciate any help you guys can give me on why I can't seem to write to the flash!

//----------------------------------------------------------------------------//
// FUNCTION NAME: NAND_ProgData
//
// INPUTS: col1, col2 - Column address bytes
// row1 - row3 - Row address bytes
// Size - Length in bytes to be written to flash
// dataIn - Array of data to be written to flash
//
// OUTPUTS: None
//
// FUNCTIONALITY: Send data in dataIn array to flash at given memory address
//----------------------------------------------------------------------------//
unsigned char NAND_ProgData(unsigned char col1,unsigned char col2,unsigned char
row1,unsigned char row2,unsigned char row3,uint16_t
Size,unsigned char *dataIn)
{
uint16_t i;
unsigned char status[1];

NAND_WriteCommand(0x80,false);
NAND_WriteAddress(col1,col2,row1,row2,row3);
__delay_cycles(2);
for(i=0;i<Size;i++)
{
NAND_WriteByte(dataIn[i]);
}
NAND_WriteCommand(0x00,false);
while((P1IN&RB) == 0){}
NAND_WriteCommand(0x70,false);
NAND_ReadBytes(1,status);
CE_ON;
return(status[0]);
}

**********************************Relevant Main Function********************************************

for(i=0;i<255;i++)
{
flashOut[i] = 0xAA;
}
flashOut[255] = 0x2C;

NAND_ProgEnable();
temp = NAND_ProgData(0x00,0x00,0x00,0x00,0x00,256,flashOut);
NAND_ReadData(0x00,0x00,0x00,0x00,0x00,256,flashIn);


while(1)
{

}

  • Everyone,

    I edited the original post to cut down on the large amount of code. The code I left shows the error. In the for-loop I write:

    David Engineer said:
    for(i=0;i<Size;i++)
    {
    NAND_WriteByte(dataIn[i]);
    }

    But this will not work, I'm not sure why, but I edited it to:

    for(i=0;i<Size;i++)
    {
    outVar = dataIn[i];
    NAND_WriteByte(outVar);
    }

    This change made the code work! Could someone please explain why this is?

  • Hello David!

    David Engineer said:
    But this will not work, I'm not sure why, but I edited it to:

    Do you mean: "It was compiled successfully but it didn't work properly"?

    I'm not sure but it's possible this extra line works in your application like a "nop" ("no operation") making flash ready for the next operation.

    You can try this:

    for(i=0;i<Size;i++)
    {
      asm("nop");

      NAND_WriteByte(dataIn[i]);
    }

    Best regards,

    Mikolaj

  • Mikolaj,

    I meant that it compiles successfully, however it does not operate as intended. No data is transmitted.

    I also discovered that I had sent the wrong terminating command, I sent 0x00 instead of 0x10.

    David

  • Hello again,

    I can also recommend looking at time timing diagrams in datasheet if you didn't do that.

    Best regards,

    Mikolaj

  • David Engineer said:
    This change made the code work! Could someone please explain why this is?

    Are you using large code model. Or even large data model?

    It seems there are some still undiscovered bugs with the use of indexed addressing modes (which are used for array access).
    If the MOVA or CALLA instruction is used in indexed addressing mode, and the array base address is above 0x8000, this leads to a wrong address to be created (0xFF8000+x instead of 0x008000+x).
    Splitting the access into two instructions seems to circumvent the problem.
    This only applies if dataIn[] happens to be a constant array (which is placed in flash and not ram and placed above 0x8000). And for large memory/data model on MSPs with MSP430X core (20 bit address range).

  • Jens-Michael,

    I am not familiar with the terms "large code model" or "even large data model", could you explain what they are? Thanks for the explanation of 3 byte vs. 2 byte issue, that will save me a lot of time in the future!

    Also, I found a second problem in the code, which was I sent the wrong termination code of 0x00 instead of 0x10. After making the two changes, I was able to get the communication working. 

    -David

  • David Engineer said:
    "large code model" or "even large data model", could you explain what they are?

    Normal MSP addressign range is 16 bit (64k). This is small code/data model. All code is reachable by a 16 bit address, all dat ais addressable by a 16 bit pointer.

    However, newer MSPs with MSP430X core can have more than 64k flash (up to 256k). The CPU core has been extended to support 20 bit registers/instructions.
    For example, the usual "CALL function" instruction got a brother 'CALLA function' which puts a 20 (actually 32) bit return address on the stack and jumps to a 20 bit destination address. Same for RET and RETA.
    Large code model compiles all funcitons to use CALLA and RETA instructions, and puts function pointers in 32 bit variables. It allows code (except for ISRs, since the interrupt vectors are still 16 bit) to be beyond 64k border.

    Large data model goes a step further. data (constants, as beyond 64k there is no ram) can be accessed using new 20 bit instructions too. However, access to data that is beyond 64k border, the index registers need to hold a 20 bit value rahtehr than the usualy 16 bit. All MSP registers are 20 bit wide (well, except the status register and the constant generator). So any function needs to preserve registers by saving a 20 (32) bit register value to the stack, which requires a different push/pop instruction (and takes an additional clock cycle and 2 more byte son stack). Same for ISRs.
    This makes the code slower and bigger, but if you need large tables or much code...

**Attention** This is a public forum