Problem with SPI in MC9S12NE64

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

Problem with SPI in MC9S12NE64

Jump to solution
3,250 Views
ace_avm
Contributor II

Hi,

 

We are using the MC9S12NE64 chip in master mode to access an M25P128-VMF6P SPI flash chip from STMicroelectronics. We are not able to access the flash (even the device ID read is not happening).

 

Upon detailed analysis, the following issues were seen.

1. The data transfer was initiated with a read of the SPISR with the SPTEF bit set and then moving the data into the SPIDR. Still, the SPTEF bit is staying as set and not getting cleared.

 

2. Even with the data in the SPIDR, the SS signal line is staying at a high level itself. 

 

Can anyone help me to sort out this issues?

 

Thanks and regards,

ace_avm

Labels (1)
0 Kudos
1 Solution
1,112 Views
ace_avm
Contributor II

Hi all,

 

 

The issue is resolved. There were two errors from our part.

Initially, we had enabled the SS signal (SSOE = 1) but were facing issues with the signal not coming properly from the chip. Thanks to Mac for suggesting the use of the pin as GPIO with the same functionality instead of using it as SS signal.

 

Also, we had enabled the Interrupts (SPIE = 1) but didn't put any interrupt handlers. (Thanks to kef for pointing it out):smileyhappy:

 

Finally, when these two errors were corrected, we observed that the local variable "val" which we used in our function was not showing the proper values when a read from SPISR or SPIDR is executed due to which the code was looping infinitely at the

        

          val = SPISR;
          if(val && SPIF)
                break;

 

section.

 

We had to change the scope of the variable to global to make this work properly (I am still not sure why it is like this:smileysurprised:, though getting the code to work is more of an achievement. :smileyhappy:)

 

Kudos to you both, Mac and kef for all your help in finding a solution for the problem.

 

 

Thanks and Regards,

ace_avm

 

View solution in original post

0 Kudos
10 Replies
1,112 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

I can surmise that there are two probable issues with your approach, although I cannot be certain without seeing your SPI module code.

 

Firstly, after writing a value to SPIDR, to commence a master transfer (in both directions), you must then wait until the SPIF flag is set, to indicate that the transfer is complete.  This flag must then be cleared by reading SPIDR (even if you have no interest in the return value), to avoid an over-run condition.

 

The SPTEF flag  must be  set  prior  to  each  write to  SPIDR, but this will usually be so if handling a single byte at a time.

 

To communicate with the flash device, you will not be able to use the automatic SS output mode.  You will need to configure this pin as a general purpose output, and explicitly control its state within your code.  The reason for this is that the signal is required to remain active low during the whole command sequence to the flash device.  With automatic SS output, the signal would be raised after each byte.

 

Regards,

Mac

 

0 Kudos
1,112 Views
ace_avm
Contributor II

Hi Mac,

 

I am pasting a copy of the function which we are using to write as well as read data from SPI.

 

// spi transmit byte function
char SPI_TX (char sendval)
{
   SPICR1 = 0xD2;
   SPICR2 = 0x10;
   SPIBR   = 0x43;

   char val=0;
   while (1)
   {
       val = SPISR;
       if(val == SPTEF)
             break;
   }
   SPIDR = sendval;
   while (1)
   {
          val = SPISR;
          if(val == SPIF)
                break;
   }
   val = SPIDR;
   return (val);
}

 

While debugging with codewarrior, we are seeing that SPTEF flag always remains set, no matter, whether we write a data byte into the SPIDR or not.  But after 1 data byte is written to the SPIDR, SPIF flag is also getting set. And we are seeing that when the second "val = SPISR" statement is executed, the SPIF bit is getting cleared automatically. Is the behaviour which we are observing correct or not.

 

 

Thanks and regards,

ace_avm 

0 Kudos
1,112 Views
kef
Specialist I

What a nasty habit of encoding something into constant and not leaving any comment about what this constant means. You are lazy to write comments, I will be lazy to help you next time, ok? I mean this:

 

   SPICR1 = 0xD2;

 

Do you think everyone remembers the name and position of each SPICR1 bit???

 

Decrypting your SPICR1 setting means SPIE=1, SPE=1, MSTR=1, SSOE=1.

You enabled SPI interrupts (SPIE), but where's your interrupt handler?

 

As Bigmac said, automatic SS function should be disabled, SS pin should be set and cleared manually. So SSOE should be 0.

 

 

   SPICR2 = 0x10;

 

MODFEN bit should be also off.

 

 

       val = SPISR;
       if(val == SPTEF)

           break;

 

SPISR may have more than one bits set, not just SPTEF. BTW how is SPTEF defined, is it constant 0x20? If so then red line should be changed to  if(val & SPTEF)

 

 

 

         val = SPISR;
          if(val == SPIF)
                break;

 

Same here, if(val & SPIF)

0 Kudos
1,112 Views
ace_avm
Contributor II

Hi kef,

 

 

Sorry for not having included the comments. Seemed to miss it somewhere in between... :smileysurprised:

 

Also, I forgot to include the definitions of SPIF and SPTEF.

#define SPIF 0x20

#define SPTEF 0xA0

 

We did try disabling the SS function and have made it to act as a GPIO. So, right now, SSOE and MODFEN are both zero. With this configuration, we see that upon the first SPISR read, SPISR has only SPTEF bit set. After SPIDR is written with data, both SPIF and SPTEF bits get set. On the second SPISR read, SPIF flag is cleared.

0 Kudos
1,112 Views
kef
Specialist I

   #define SPIF 0x20

 

It should be 0x80

 

  

 

   #define SPTEF 0xA0

 

It should be 0x20

 

 

    After SPIDR is written with data, both SPIF and SPTEF bits get set.

 

SPIF and SPTEF get set not immediately after write to SPIDR. SPTEF after reset to 0, almost immediately can revert to 1, indicating that SPI buffer is empty (that data was transferred from TX buffer SPI shift register). And SPIF reverts to 1 after transfer is complete. This happens too quick to see it using debugger.

0 Kudos
1,112 Views
ace_avm
Contributor II

Ok, I have changed the definitions to

 

#define SPTEF 0x20

#define SPIF   0x80

 

 

>>SPIF and SPTEF get set not immediately after write to SPIDR. SPTEF after reset to 0, almost immediately can revert to 1, indicating that SPI buffer is empty (that data was transferred from TX buffer SPI shift register). And SPIF reverts to 1 after transfer is complete. This happens too quick to see it using debugger

 

So does this mean that the write is happening properly? We are not seeing any waveform on MOSI as well as SCLK pins even after this is happening.

0 Kudos
1,112 Views
kef
Specialist I

I don't know why it may not work. Most often I'm something like this

 

 

void SPIInit(void)
{
char tmp;

   tmp=SPI1SR; /* read SR */

   SPI0BR = 0;


   SPI0CR1 =    SPICR1_SPE_MASK
                  | SPICR1_MSTR_MASK
                  | SPICR1_CPHA_MASK * 0
// CPHA = 0
                  | SPICR1_CPOL_MASK * 0
// CPOL = 0
               ;
}

char SPIIO(char c)
{
   SPI0DR = c;
    while( !(SPI0SR & SPISR_SPIF_MASK) )
      ;
    return SPI0DR;
}

0 Kudos
1,113 Views
ace_avm
Contributor II

Hi all,

 

 

The issue is resolved. There were two errors from our part.

Initially, we had enabled the SS signal (SSOE = 1) but were facing issues with the signal not coming properly from the chip. Thanks to Mac for suggesting the use of the pin as GPIO with the same functionality instead of using it as SS signal.

 

Also, we had enabled the Interrupts (SPIE = 1) but didn't put any interrupt handlers. (Thanks to kef for pointing it out):smileyhappy:

 

Finally, when these two errors were corrected, we observed that the local variable "val" which we used in our function was not showing the proper values when a read from SPISR or SPIDR is executed due to which the code was looping infinitely at the

        

          val = SPISR;
          if(val && SPIF)
                break;

 

section.

 

We had to change the scope of the variable to global to make this work properly (I am still not sure why it is like this:smileysurprised:, though getting the code to work is more of an achievement. :smileyhappy:)

 

Kudos to you both, Mac and kef for all your help in finding a solution for the problem.

 

 

Thanks and Regards,

ace_avm

 

0 Kudos
1,112 Views
Lundin
Senior Contributor IV
As a side note, ST chips implementing SPI tend be be notoriously non-standard. I have had similar problems with various MEMS IC from ST where they added strange timing requirements on the chip select, it sounds like the same problem as the original poster is having.

So if you must use ST chips with SPI, hold on tight to your oscilloscope. How wonderful it would be if SPI was an ISO standard...

0 Kudos
1,112 Views
ace_avm
Contributor II
There's one more behaviour which we are observing. The SPI clock signal also is not coming when probed.
0 Kudos