MPC5748GRM SPI write EEPROM problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MPC5748GRM SPI write EEPROM problem

8,925 Views
haibinwang
Contributor II

Hi all,

 

I am Wang Haibin from faladay future company. I have question on use spi to write EEPROM driver.

 

Now I am develop an spi driver to write EEPROM(M9501M-A125) on chip MPC5748GRM,   MPC5748GRM spi3 is master, EEPROM is slave.

 

the attachment is the EEPROM M9501M-125 specification

 

 

 

but when I try to write a byte to eeprom, there is no any feedback from the port MISO.

 

my port configuration is :

 

void init_spi3_ports(){

 

  /* Master - SPI_3 to configure to write eeprom */

SIUL2.MSCR[116].B.SSS = 2;                  /* Pad PH4: Source signal is SPI_3 SOUT  */

SIUL2.MSCR[116].B.OBE = 1u;                 /* Pad PH4: OBE=1. */

SIUL2.MSCR[116].B.SRC = 3;      /* Pad PH4: Full strength slew rate */

 

SIUL2.MSCR[117].B.IBE = 1;                 /* Pad PH5: Enable pad for input SPI_3 SIN */

SIUL2.IMCR[309].B.SSS = 1;    /* Pad PH5: Set as peripheral SPI3, MISO (SIN_3) - 821-512 */

 

SIUL2.MSCR[118].B.SSS = 2;                  /* Pad PH6: Source signal is SPI_3 SCK  */

SIUL2.MSCR[118].B.OBE = 1u;                 /* Pad PH6: OBE=1. */

SIUL2.MSCR[118].B.SRC = 3;                  /* Pad PH6: Full strength slew rate */

 

SIUL2.MSCR[119].B.SSS = 4;                  /* Pad PH7: Source signal is SPI_3 CS0_3  */

SIUL2.MSCR[119].B.OBE = 1u;                 /* Pad PH7: OBE=1. */

SIUL2.MSCR[119].B.SRC = 3;                  /* Pad PH7: Full strength slew rate */

}

 

Register configuration is:

 

void init_SPI_3(void) {

    SPI_3.MCR.R = 0x80010001;                 /* Configure SPI_3 as master,  SPI */

    SPI_3.MODE.CTAR[0].R = 0x38065522;   /1.25 MHz, 1 byte every frame size/

    SPI_3.MCR.B.HALT = 0x0;                   /* Exit HALT mode: go from STOPPED to RUNNING state*/

}

 

/function to write a byte/

 

static uint8_t Write_Byte(uint8_t cmd)

{

 

    uint16_t    response    = 0x0000;

    SPI_3.PUSHR.PUSHR.R = (uint32_t)((((uint32_t)cmd) & 0x000000FF) + 0x00010000);

 

    while (SPI_3.SR.B.RFDF != 1){}  /* Wait for Receive FIFO Drain Flag = 1 */

    response = (uint8_t)SPI_3.POPR.R;   /* Read data received by master SPI */

    SPI_3.SR.R = 0x80020000;

 

    return((uint8_t)((0x02 & response) >> 1));

}

 

/the function to write a byte to eeprom/

 

void EEPROMWriteByte(uint8_t Data, uint32_t Address)

{

SPI_Status_t spi3_status = 0;

    uint8_t* spi3_rx_byte = 0;

    uint8_t write_response;

 

 

    SPI_3.MCR.B.HALT = 0x0; /spi enable/

    write_response = Write_Byte(EEPROM_CMD_WREN); /eeprom write enable command/

    write_response = Write_Byte(EEPROM_CMD_WRITE); /eeprom write command/

    write_response = Write_Byte(Hi(Address)); /eeprom high address/

    write_response = Write_Byte(Mid(Address)); /eeprom middle address/

    write_response = Write_Byte(Lo(Address)); /eeprom low address/

    write_response = Write_Byte(Data); /a byte prepare to write to eeprom/

    while(EEPROMReadStatus().Bits.WIP); /read back the eeprom status/

    write_response = Write_Byte(EEPROM_CMD_WRDI); /eeprom rom write disable command/

    SPI_3.MCR.B.HALT = 0x1; /spi disable/

}

 

/the function of EEPROMWriteByte() is called in 10ms task/

 

10ms_task()

 

{

 

EEPROMWriteByte(0x5A, 0x010011);

 

}

 

 

 

the debugger RxData register always is 0. the PORT MISO is alway in low voltage level.

 

it is my first to develop spi driver, maybe my question is too simple but it is realy puzzled me over 2 days, my question is follows:

 

1. whether  the enable port rise to high voltage is necessary after send one byte successfully?

 

2. How to differ the command, address, and data from the data transfer?

 

3. how to solve the promblem that MISO port is alway no any change, keep in low level voltage?

 

 

 

Do you mind to help me to solve the problem?

 

the following diagram show my puzzle:

 

 

 

channel 1 and channel 5 is HOLD and W protect pin in eeprom, already pulll up to battery.

 

Great thanks!

 

Wang Haibin

Labels (1)
18 Replies

7,361 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

Your SPI module and pin configuration looks correct. However the command sequence is wrong. Read the EEPROM datasheet carefully, especially chapters 4.3 to 4.6. All commands except of WREN and WRDI require continuous chip selection during all bytes (command+address/data) transmission. You need to use Continuous Selection Format in your SPI master, see chapter 40.5.6.5 of the MPC5748G RM.

The “Q” output of the EEPROM memory is in high impedance state for all write commands and only driven after read command is received into EEPROM and chip select continues to be driven low.

BR, Petr

7,361 Views
haibinwang
Contributor II

hi Petr,

Thanks for your suggestion, I make some progress in my task of writing EEPROM with spi.

my present work statue as the following:

figure 1

but the datasheet requirement as follows:

figure 2

in order to meet the requirement I have to setting as the chapter 40.5.6.6 Fast Continuous Selection Format discription, that means masking Tasc and Tcsc is needed in my SPI configuration .

but it is likely that I could not understand the masking rules right, I try many cases but cann't reach the figure 2 shows in past 3 days.

I only can setting as the figure 3 shows:

figure 3

That mean write enable byte 6 and data 5 could not be send out via MOSI.

Do you mind help me to correct my fast continues setting?

the follow is my setting:

I think the question should happend on the function Write_Byte(), but I really puzzled the description in chapter 40.5.6.6 Fast Continuous Selection Format.

Besides, I am not sure if the Tasc and Tcsc in register CTAR0 setting would affect the final output?

The controller present fp should be 40MHz.

******************************************************************************

static uint8_t Write_Byte(uint8_t cmd)

{

uint16_t response = 0x0000;

SPI_3.PUSHR.PUSHR.R = (uint32_t)((((uint32_t)cmd) & 0x000000FF) + 0x0B000000);

while (SPI_3.SR.B.RFDF != 1){} /* Wait for Receive FIFO Drain Flag = 1 */

response = (uint8_t)SPI_3.POPR.R; /* Read data received by master SPI */

SPI_3.SR.R = 0x90020000;

return((uint8_t)((0x02 & response) >> 1));

}

/**************************************************************************

    • Private Functions

**************************************************************************/

static uint8_t Write_FirstByte(uint8_t cmd)

{

uint16_t response = 0x0000;

SPI_3.PUSHR.PUSHR.R = (uint32_t)((((uint32_t)cmd) & 0x000000FF) + 0x08010000); /**/

while (SPI_3.SR.B.RFDF != 1){} /* Wait for Receive FIFO Drain Flag = 1 */

response = (uint8_t)SPI_3.POPR.R; /* Read data received by master SPI */

SPI_3.SR.R = 0x90020000;

return((uint8_t)((0x02 & response) >> 1));

}

/**************************************************************************

    • Private Functions

**************************************************************************/

void EEPROMWriteByte(uint8_t* Data, uint32_t DataSize, uint32_t Address)

{

SPI_Status_t spi3_status = 0;

uint8_t* spi3_rx_byte = 0;

uint8_t write_response,i;

uint8_t* data;

data = Data;

SPI_3.MCR.B.HALT = 0x1;

SPI_3.MCR.R = 0x80010001;

SPI_3.MODE.CTAR[0].R = 0x38020002; /1.25 MHz/

SPI_3.MCR.B.HALT = 0x0;

write_response = Write_FirstByte(EEPROM_CMD_WREN);

/fast continues send setting, MCR bit29 is set/

SPI_3.MCR.B.HALT = 0x1;

SPI_3.MCR.R = 0x80000005;

SPI_3.MODE.CTAR[0].R = 0x38020002; /1.25 MHz SUCCESS/

SPI_3.MCR.B.HALT = 0x0;

write_response = Write_Byte(EEPROM_CMD_WRITE); /*command write */

write_response = Write_Byte(Hi(Address)); /high address byte/

write_response = Write_Byte(Mid(Address)); /Middle address byte/

write_response = Write_Byte(Lo(Address)); /low address byte/

for (i = 0; i < (DataSize); i++) /* Datasize equal 5, plan to send 1, 2, 3, 4, 5 to EEPROM via MOSI*/

{

write_response = Write_Byte(i+1);

}

/*wait for completion of previous continues frame and begin to read status register */

SPI_3.MCR.B.HALT = 0x1;

SPI_3.MCR.R = 0x80010001;

SPI_3.MODE.CTAR[0].R = 0x38020002; /1.25 MHz/

SPI_3.MCR.B.HALT = 0x0;

/read register status EEPROM_CMD_RDSR equal 5/

write_response = Write_FirstByte(EEPROM_CMD_RDSR);

/write disable command EEPROM_CMD_WRDI equal 4/

write_response = Write_FirstByte(EEPROM_CMD_WRDI);

SPI_3.MCR.B.HALT = 0x1;

}

EEPROMWriteByte() function is call in 10ms task.

Great thanks for your help!

Wang Haibin

0 Kudos

7,361 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

Why there is a need to use a Fast Continuous Selection Format?

Here is a result I got with normal one and modified code. You can test.

I used DSPI3, which is running from 80Mhz, you should recalculate CTAR for your 40Mhz. I set tcsc,tasc, tdt to half of bit rate.

 

void init_DSPI_3(void)

{

   DSPI_3.MCR.R = 0x80010001;                /* Configure DSPI as master */

   DSPI_3.MODE.CTAR[0].R =  0x38004445;       /* Configure CTAR0 , baudrate = 1.25MHz */

   DSPI_3.MCR.B.HALT = 0x0;                  /* Exit HALT mode: go from STOPPED to RUNNING state*/

}

 

static uint8_t Write_Byte(uint16_t cmd, uint16_t data)

{

    uint16_t    response    = 0x0000;

 

    DSPI_3.PUSHR.PUSHR.R = (uint32_t)((uint32_t)(cmd<<16) + data); /**/

    while (DSPI_3.SR.B.RFDF != 1){}  /* Wait for Receive FIFO Drain Flag = 1 */

    response = (uint8_t)DSPI_3.POPR.R;   /* Read data received by master SPI */

 

    DSPI_3.SR.R = 0x90020000;

 

    return((uint8_t)((0x02 & response) >> 1));

 

}

 

void EEPROMWriteByte(void)

{

 

  #define EEPROM_CMD_WREN 6

  #define EEPROM_CMD_WRDI 4

  #define EEPROM_CMD_WRITE 2

  #define EEPROM_CMD_RDSR 5

 

  uint8_t write_response,i, DataSize=5;

 

  write_response = Write_Byte(0x0001,EEPROM_CMD_WREN);

  write_response = Write_Byte(0x8001,EEPROM_CMD_WRITE); /*command write */

  write_response = Write_Byte(0x8001,0); //high address byte/

  write_response = Write_Byte(0x8001,1); //Middle address byte/

  write_response = Write_Byte(0x8001,0); //low address byte/

  for (i = 0; i < (DataSize-1); i++) /* Datasize equal 5, plan to send 1, 2, 3, 4, 5 to EEPROM via MOSI*/

  {

     write_response = Write_Byte(0x8001,i+1);

  }

  write_response = Write_Byte(0x0001,i+1);        // write last data byte

 

  //read register status EEPROM_CMD_RDSR equal 5

  write_response = Write_Byte(0x8001,EEPROM_CMD_RDSR);

  write_response = Write_Byte(0x0001,0);           // dummy byte to read status

 

  write_response = Write_Byte(0x0001,EEPROM_CMD_WRDI);

 

}

pastedImage_1.png

If needed I can test "fast" mode too, but believe this is not needed.

BR, Petr

7,361 Views
xushengyu
Contributor II

hello, Petr Stancik! I look at the sequence you shown above. I do not know why the output is 255, it means there is no data readback. 

Am i right? Can you send the resource code to me? Thank you very much!

0 Kudos

7,360 Views
haibinwang
Contributor II

Hi,

I have realize how to readback the data written by the function EEPROMWriteByte().

Great thanks for your help!

Wang Haibin

0 Kudos

7,360 Views
ramanjineyuluth
Contributor II

Hi,

I am also working on SPI with EEPROM but i am unable to write data to EEPROM.

Please see the below code and let me know any modifications is needed.

int8_t SpiEepWritePage(const EEP_FUNC_ADDR func_addr, const uint8_t * const content)

{

uint16_t phy_addr;

uint32_t i;

phy_addr = SpiEepConvert2PhyAddr(func_addr);

ASSERT_WR_ENABLE();

SpiEepSelectSlave(SIG_ASSERTED);//CS=0

SPIIfTransferByte(Eep_Spi_Chanl_No, EEP_INSTRUCT_WRITE);

SPIIfTransferByte(Eep_Spi_Chanl_No, ADDR_HIGH(phy_addr));

SPIIfTransferByte(Eep_Spi_Chanl_No, ADDR_LOW(phy_addr));

for (i = 0; i < EEP_PAGE_SIZE; i++)//128Bytes

{

SPIIfTransferByte(Eep_Spi_Chanl_No, (uint8_t)(*(uint8_t *)(content + i)));

}

SpiEepSelectSlave(SIG_NEGATED);//CS=1

/* Wait for completion of previous write cycle */

while (((EEP_STAT_REG)(SpiEepReadStatReg())).B.WIP);

ASSERT_WR_DISABLE();

return 1;

}

In the above code we are transferring data to DSPI2.

In your code I could not understand the below line.

Write_Byte(0x8001, Hi(Address));

Can you please tell me 0x8001(cmd) how you taken this command and which address you giving.

If possible can you please send your code, It is very helpful to me.

Thanks in advance.

Thanks & Regards,

Ramanjineyulu.

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi,

Thanks for your reply.

uint8_t EEPROMReadByte(uint32_t Address, uint8_t *pReadData, uint8_t DataSize)

Please let me know in the above function which Address you are passing.

In my source code the below while loop function is not coming out of the loop.

Please see the below code and let me know any modifications is needed.

Thanks in advance.

Thanks & Regards,

Relationships.

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi,

Sorry I forgot the below line.

while (((EEP_STAT_REG)(SpiEepReadStatReg())).B.WIP);

Please tell me above condition is write or wrong.

Thanks,

Relationships.

0 Kudos

7,361 Views
haibinwang
Contributor II

hi,

yes, you are right, WIP means the writting is in progress, but more important thing is that you have to insure you could read back the eeprom status.

infact in you could use sizeof(array) as the condition to determine if it has reached the last byte you want to chansfer.

hope it helpful to you!

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi,

Thanks a lot for your support.

I saw your code, I want to know the how you get the Address.

EEPROMWriteByte(0x5A, 0x010011);//DATA , ADDRESS.

Can you please tell me how you taken above ADDRESS.

EEPROMreadByte function we have to pass the ADDRESS, so Please tell me how you taken the ADDRESS.

We can take any ADDRESS or any specific address we have to give.

It is very help full.

Thanks,

Ramanjineyulu.

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi Wang,

I am struggling a lot last 1 week onwards but receiving data is always 0xFF.

Could you please send your tested code it is very helpful to me.

Thanks & Regards,

Ramanjineyulu.

0 Kudos

7,360 Views
haibinwang
Contributor II

hi,

Most of the source codes are already mentioned in the email list, you could find them in the following emails.

you could test the source code and add your own function to them.

I hope it would helpful to your work!

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi Wang,

Thanks a lot for your support.

I have tested the hardware the CS0 is always high.

By writing CS0 high and low but it always high.

Please see the below code and let me know your comments.

void SUIL2_Init(void)
{

    SIUL2.MSCR[3].R = 0x32870002; // A[3] pin as SPI_0 CS0 output
    SIUL2.MSCR[0].R = 0x32840002; // A[0] pin as SPI_0 SCK output
    SIUL2.MSCR[1].R = 0x32840002; // A[1] pin as SPI_0 SOUT output

    SIUL2.MSCR[2].B.IBE = 1;    // A[2]: Enable pad for input - SPI_0 SIN
    SIUL2.IMCR[47].B.SSS = 2;   // SPI_0 SIN: connected to pad C[7]
}   

while(1)
    {
     SetPadLow(92);
     SetPadLow(3);

     timeout = 100000000uL;
     while ((--timeout) != 0uL);

     SetPadHigh(92);
     SetPadHigh(3);

     timeout = 100000000uL;
     while ((--timeout) != 0uL);
    }

Could you please check the hardware schematic also whether it is correct or not.

164900_164900.jpgHardware.jpg

Thanks & Regards,

Ramanjineyulu.

0 Kudos

7,361 Views
haibinwang
Contributor II

I have to say sorry for you!

I am really not good at hardware configuration.

even for myself spi driver, the hardware engineer help me to finish the hardware pin configuration.

so I could not provide you any help on port configuration.

0 Kudos

7,361 Views
ramanjineyuluth
Contributor II

Hi Wang,

Thank you very much for your support.

SPI with EEPROM code is working fine now.

The issue is with hardware, we have to connect /HOLD pin to VCC with 10K.

The issue is resolved.

Thanks & Regards,

Ramanjineyulu.

0 Kudos

7,360 Views
haibinwang
Contributor II

hi,

My chip is MPC5xxxx, different chip maybe little differrence.

The cmd value 0x8001 is the setting for register PUSHR, the 0x8001 in binary is 0b1000000000000001, so you could find CONT bit and PCS0 bit are set to 1.

I hope my answer could help you!

Wang Haibin

0 Kudos

7,360 Views
haibinwang
Contributor II

hi,

you code seems work, I could read back the write status change as the follow figure 1:

figure 1

according the EEPROM datasheet define in figure 2

figure 2

status register status be 3, bit1 and bit0 be set 1, illustrate the write process is on going.

and at the next 10ms reread the status register state be 0x00.

but I think the best way to verify the code is to readback the data writen via the function EEPROMWriteByte(void).

but when I try to read the data I write from start address 0b000100, it is failed. show in figure 3

figure 3

the related code function to read back the writen data as follows:

********************************************************************

uint8_t EEPROMReadByte(uint32_t Address)

{

uint8_t write_response;

write_response = Write_Byte(0x0801, EEPROM_CMD_READ);

write_response = Write_Byte(0x0801, Hi(Address));

write_response = Write_Byte(0x0801, Mid(Address));

write_response = Write_Byte(0x0801, Lo(Address));

write_response = Write_Byte(0x0001,0); // dummy byte to read data

return write_response;

}

********************************************************************

the other part is fllow your code.

is it the right code? or I am something wrong?

Do you mind to help me to corrent the code?

Wang Haibin

0 Kudos

7,360 Views
PetrS
NXP TechSupport
NXP TechSupport

You need to use continuous chip selection for all bytes to be read.  In your code you are using EOQ bit instead of CONT.

Also from the datasheet ... the instruction is not accepted, and is not executed, if a Write cycle is currently in progress.

So I think you should first read the Status register and if memory is ready, execute read sequence.

It could be done in following way, just generally…

 

uint8_t EEPROMReadByte(uint32_t Address, uint8_t *pReadData, uint8_t DataSize)

{

    uint8_t response,i;

 

    //read register status EEPROM_CMD_RDSR equal 5

    response = Write_Byte(0x8001,EEPROM_CMD_RDSR);

    response = Write_Byte(0x0001,0);       // dummy byte to read status

 

    if((response&1)==0) // if memory is ready

    {         

                response = Write_Byte(0x8001, EEPROM_CMD_READ);

 

                response = Write_Byte(0x8001, Hi(Address));

                response = Write_Byte(0x8001, Mid(Address));

                response = Write_Byte(0x8001, Lo(Address));

 

                for (i = 0; i < (DataSize-1); i++) /* read “DataSize” bytes*/

                {

                    *pReadData++ = Write_Byte(0x8001,0); // dummy byte to read data

                }

                *pReadData = Write_Byte(0x0001,0);     // dummy write for last last data read

 

                return 0; // read successful

    }

    return 1; // memory is busy still

}