About MCF51EM256 SPI

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

About MCF51EM256 SPI

802 Views
sinanmuratkeşen
Contributor I

Hi,

I am currently using MCF51EM256 Cold Fire1. I am working on SPI communication with SPI flash ( 25P80 ). I am using SPI3 for SPI communication. SPI3 have open-drain pins, PTE4, PTE5 and PTE6. I have connected these pins with pull-up resistors to VDD (3V3) and I have configured SPI. Configuration codes are below:

 

 

SPI3C1 = 0x00;

SPI3C2 = 0x00;                                     

SPI3BR = 0x78;                                     

(void)(SPI3S == 0);

 

CONFIGURE_SPI3_SS_PIN_OUTPUT();

CONFIGURE_SPI3_MISO_PIN_INPUT();

SPI3C1 = 0x12;                                     

SPI3C2 = 0x12;

PTEPE_PTEPE3 = 1;

PTEPF1 = 0X56; 

PTEPF2 = 0X83;

CONFIGURE_SPI3_CONTROLE_REG1(SPI_SYS_ENABLED);

 

 

When I had tried to communicate to spi flash,  I didn't communicate properly. I have written another spi softwares for another device as a slave then when I had recieved a character in slave device, spi receiver interrupt had occured then I have sent this character to SCI. When I had monitored this SCI communication via serial port terminal I realised the character which I sent to slave device was right but I didn't write to spi flash.. When I had tried to read any character in the spi flash I received 0 'zero'.

 

 

Do you any suggestion about this subject? Are My spi configuration codes right or my hardware configurations right? I am using 10K for the pull-up resistor.

 

 

Best Regards.

 

Labels (1)
0 Kudos
8 Replies

605 Views
Monica
Senior Contributor III

Hello!

How is the project going sinanmuratkeşen?

Keep us posted! :smileyhappy:

0 Kudos

605 Views
sinanmuratkeşen
Contributor I

Hello,

Actually my project isn't going on. I am still working on the same problem  :smileysad: and I haven't solved this problem yet. I tried everything bu it didn't work. If I have any result I will post it.

Sinan..

0 Kudos

605 Views
JimDon
Senior Contributor III

We need more information.

To write to a Serial Flash, you first need to erase, and then write - to do this you typically need to send a series of commands to set the address and the operation desired. You also have to wait for these operations to complete.

For this device you need may to send the command followed by 3 address bytes (see the spec sheet).

What are you actually sending to the device?

0 Kudos

605 Views
sinanmuratkeşen
Contributor I

Hi,

I have already done these things which you told me. I am following these instructions:

1) I have sent to the flash write enable command

stData.m_pucCmd[0] = 0x06; // write enable command is 0x06

clear_cs();                              // I selected the flash.

SPI3D =  stData.m_pucCmd[0]; // I sent to flash write enable command.

set_cs(); // disable flash, disable chip select pin..

2) I have erased the target adress which I wanted to write:

stData.m_pucCmd[0] = 0xD8: // sector erase command is 0xD8

stData.m_pucCmd[1] = 0x00;

stData.m_pucCmd[2] = 0x00;

stData.m_pucCmd[3] = 0x00;

First byte is command and the others are target address.

stData.m_pucCmdLen = 4; // one byte command and three bytess adress.

stat_cSPITxStatus= COMMAND;

g_ucSPITimeOutCount= _20_MS;

3) I have called my transmit function. These function is like:

UINT8 ucIntFlag = CLEAR;

    ucIntFlag = SPI3S;

    /* Check transmit flag and SPI time out */

if((CLEAR == g_ucSPITimeOutCount) && (ucIntFlag & TRANSMIT_FLAG))

    {

        {

        /* check SPI status and load the SPI data buffer with the data to be

        * write in the sequence command,address and data to be written

        */

        switch(stat_cSPITxStatus)

        {

                case COMMAND:

        /* load the address of the NV memory to the SPI data

        * buffer

        */

        stat_unSPIIndex++;

        if(stat_unSPIIndex >= stData.m_ucCmdLen)

        {

           stData.m_ucCmdLen = CLEAR;

        stat_unSPIIndex = CLEAR;

        /* After address transmission change SPI tx status to data

        * in order to send the data bytes

        */

        if(CLEAR != stData.m_unDataLen)

        {

           SPI3D = stData.m_pucData[stat_unSPIIndex];

                            /* Initialize a SPI timer to count 1 byte transmission */

                            g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

           stat_cSPITxStatus = DATA;

        }

        else

        {

                            /* Initialize a SPI timer to count 1 byte transmission */

                            g_ucSPITimeOutCount = THREE;

        stat_cSPIStatus = SUCCESS;

        }

        }

        else

        {

        SPI3D = stData.m_pucCmd[stat_unSPIIndex];

                while(ERR_RXEMPTY==SPI_RecvChar(&temp));

                        /* Initialize a SPI timer to count 1 byte transmission */

                        g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

        }

        break;

        case DATA:   

    stat_unSPIIndex++ ;

    /* Return success after transferring all data bytes */

    if(stat_unSPIIndex >= stData.m_unDataLen)

    {

                        /* Initialize a SPI timer to count 1 byte transmission */

                        g_ucSPITimeOutCount = THREE;

    /* Clear buffer index */

    stat_unSPIIndex = CLEAR;

    stat_cSPIStatus = SUCCESS;

    stat_cSPITxStatus = COMMAND;

                    stData.m_pucData = NULL;

                    stData.m_unDataLen = ZERO_0;

}

    else

    {

       SPI3D = stData.m_pucData[stat_unSPIIndex];

                while(ERR_RXEMPTY==SPI_RecvChar(&temp));

                        /* Initialize a SPI timer to count 1 byte transmission */

                        g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

    }   

           break;

      

        default:

        break;

        }

        }

    }

4-) I am calling my read function:

void SPIReadData(UINT32 ulnAddress, UINT8 *pucData, UINT32 unNoOfBytes)

{

    UINT8 ucIntFlag = CLEAR, temp;

        /*

         * Select prescaler value 1 and divider value 128 to achieve the 156.25khz

         * clock rate

         */

    CONFIGURE_SPI3_BAUD_RATE(BUSCLK_PRESCALER_8|BAUD_RATE_DIVIDER_512) ;

    CONFIGURE_SPI3_CONTROLE_REG1(SPI_SYS_ENABLED);

    /* Read flag register to clear the transmit flag */

    ucIntFlag = SPI3S;

  /* select NV memory as slave */

    CLEAR_CS();

    /* NV memory Read command */

    SPIUpdateCmd(READ_DATA_CMD);

  /*  Command length including address length */

  stData.m_ucCmdLen = COMMAND_LENGTH + ADDRESS_LENGTH;

  /* Address of the NV memory */

    SPIUpdateAddr(ulnAddress);

  /*  buffer store data read from NV memory */

  stData.m_pucData = pucData;

  /*  Number of bytes of data to be read */

  stData.m_unDataLen = unNoOfBytes;

  /*  Operation mode */

  stData.m_ucMode = SPI_READ;

  stat_unSPIIndex = CLEAR;

  /* load read command to Tx buffer */

  SPI3D = stData.m_pucCmd[COMMAND_INDEX];

    /* Set the SPI status as command */

    stat_cSPITxStatus = COMMAND;

    /* Return the SPI status to NV driver as, read in progress */

    stat_cSPIStatus = RD_INPROGRESS;

    /* Initialize a SPI timer to count 1 byte transmission */

    g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

    /*  Enable the SPI transmit interrupt */

    SPI_TX_EN();

}

my ISR funciton is :

interrupt VectorNumber_Vspi3 void SPIISR(void)

{

    UINT8 ucIntFlag = CLEAR;

    /* Initialize a SPI timer to count 20msec */

    g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

    /* Read flag register to clear the transmit flag */

    ucIntFlag = SPI3S;

    /* check transmit buffer is empty */

    if( ( ucIntFlag & TRANSMIT_FLAG ) )

    {

  /* check SPI status and load the SPI data buffer with the data to be

  * write in the sequence command,address and data to be written

  */

  switch(stat_cSPITxStatus)

  {

            case COMMAND:

  /* load the address of the NV memory to the SPI data

  * buffer

  */

  stat_unSPIIndex++;

  if(stat_unSPIIndex >= stData.m_ucCmdLen)

  {

     stData.m_ucCmdLen = CLEAR;

  stat_unSPIIndex = CLEAR;

    /* After address transmission change SPI tx status to data

    * in order to send the data bytes

    */

  if(CLEAR != stData.m_unDataLen)

  {

      /* write dummy data to SPI transmit buffer in order

       * to receive data

    */

        SPI3D = DUMMY_DATA;

        //        g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

     stat_cSPITxStatus = DATA;

  }

  }

  else

  {

         SPI3D = stData.m_pucCmd[stat_unSPIIndex];

  //        g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

  }                                             

  break;

  case DATA:

    /* write dummy data to SPI transmit buffer in order

     * to receive data

  */

          if((SPI_READ == stData.m_ucMode) &&

             (CLEAR == stData.m_ucCmdLen))

        {

      

                    switch(stat_cSPITxStatus)

                    {

                        case DATA:

                            /* read the data from the SPI data buffer */

                            if(stat_unSPIIndex > CLEAR)

                            {  

                                stData.m_pucData[stat_unSPIIndex - ONE] = SPI3D ;

                            }

                            else

                            {

                                ucIntFlag = SPI3D;

                            }

                            stat_unSPIIndex++ ;

                            if(stat_unSPIIndex > stData.m_unDataLen)

                    {

                                    /* Disable the slave select pin  */

                                SET_CS();

                                    SPI_SYSTEM_DISABLE();

                                        /* Disable the SPI transmit interrupt */

                                        SPI3_TX_DIS();

                       /* Clear buffer index */

                    stat_unSPIIndex = CLEAR;

                    stat_cSPIStatus = SUCCESS;

                    stat_cSPITxStatus = COMMAND;

                                    stData.m_pucData = NULL;

                                    stData.m_unDataLen = ZERO_0;

                    /* Disable the slave select pin after completing

                    * read operation

                    */

                    }

                        else

                        {

                        SPI3D = DUMMY_DATA;

            //           g_ucSPITimeOutCount = SPI_TIME_OUT_20MS;

                        }

                        break;

                        default:

                        break;

                    }

        }

        else

        {

           /* Read flag register to clear the transmit flag */

                    ucIntFlag = SPI3S;

           ucIntFlag =  SPI3D; 

        }

  break;

  default:

  break;

  }

    }

}

0 Kudos

605 Views
TomE
Specialist II

Try to get it working with simpler code than you're using.

Or start with someone else's working code.

I don't know why the code is full of different timeouts as that should be unnecessary. I don't know why you're reinitialising the baud rate on every read call. I have no idea why you'd need the constant "THREE". That's usually the punch line of a joke where someone has redefined THREE to be "7" or something.

I hope this is a summary and you're not really doing the following:

> clear_cs();                              // I selected the flash.

> SPI3D =  stData.m_pucCmd[0]; // I sent to flash write enable command.

> set_cs(); // disable flash, disable chip select pin..


You have to monitor SPI3S and wait for the transmission to complete before you disable the chip select.


You are also setting the baud rate in SPIReadData(), but NOT setting the baud rate before your sending of the "flash write enable command". Your code should have one SPI Initialisation routine that sets up the hardware, and then it shouldn't need to be changed from then on.

Using interrupts on SPI adds complexity, and sometimes isn't worthwhile. it is easier to wait for the byte to be sent/received rather than schedule and handle an interrupt. In your case the CPU runs at a maximum speed of 50.33MHz. The SPI can run at 25MHz. That means it can send and receive a byte in the time it takes for the CPU to run 16 instructions. Since it takes longer than that to respond to an interrupt you're a lot better off just polling for completion and clocking as fast as you can.

As long as the M25P80 can run at that speed. It can run at 75MHz, except that Reads can only run at 33MHz. Except that the Data Sheet also says it has a Maximum speed of 25MHz and 20MHz for Read. That seems to imply there are two different speed grades of the part, but there's nothing mentioned about this in  the Data Sheet. You might have to run at 12.5MHz to meet the 20MHz spec. Good luck.

Anyway, it isn't worth using interrupts with this combination.

Tom


0 Kudos

605 Views
sinanmuratkeşen
Contributor I

Hi Tom,

Thank you for reply. I have already monitored SPI signal with oscilloscope and the signals was right. TEK0000.BMP

The purple one is data.

The yellow one is clock pulse.

The blue one is chip select.

Also I had monitored SPI signals via RS-485 port of slave device and I realised the signals was right.

Sinan.

0 Kudos

605 Views
TomE
Specialist II

You have captured one data signal. To see what is happening you need to monitor the input and output data pins. Then send the command sequence that should be trying to program a FLASH location and compare that with the data sheet for that FLASH device. Then perform the read operation and compare with the data sheet.

Remember that with SPI that you send a command in one cycle and read the results of that command back in the NEXT cycle. All the reads happen one cycle later than you'd expect with a parallel bus.

Tom

0 Kudos

605 Views
TomE
Specialist II

Examine the SPI signals with an oscilloscope and decode them. That's always the easiest way to find what's going wrong.


Tom

0 Kudos