AnsweredAssumed Answered

STM32F417 SPI1 Start Bit Detection

Question asked by wormsley.jeff on Dec 15, 2015
Latest reply on Dec 15, 2015 by wormsley.jeff
I am trying to implement an SDCard interface using SPI on an STM32F417 based board.  I have to use SPI, because pins needed for SDIO are in use by other peripherals on my board.

I have three devices on my SPI bus, an SPI flash device, an EEPROM/MAC chip, and the SDCard, all with their own chip select lines.  The flash device and EEPROM/MAC device both work perfectly.  However, I am having trouble with the SDCard interface.

The initialization process on the SDCard involves sending a CMD0 command, followed by a CMD8 command.  The CMD0 command should return an R1 response format.  For all SDCard SPI responses, the first bit should be a 0, which is a Start Bit, and the final bit is a 1, which is the Stop Bit.  The R1 response has both the Start Bit and Stop Bit in one byte.

When I send the CMD0 I get the expected R1 response of binary 00000001.  

Next I send CMD8.  This command nominally sets the operating voltage, but it primarily used to determine if the card is a newer high capacity SDCard, or an older one.  The older cards do not implement the CMD8 command, and should respond to CMD8 with an R1 response of binary 00000101.  Looking at this on my scope, I see that this is indeed the case.

However, when I read the response in my code, I get two bytes, an 0xC1 and an 0x7F.  Looking at the bit patterns:

0xC1 = 11000001
0x7F = 01111111

Put these together and you see:

1100000101111111

Notice that if you start at the first 0, and look at 8 bits, you have:

00000101

This is precisely the R1 response I should have gotten. 

My question is, why is this offset by two bits, and what can I do about it?

Here is my SPI1 port initialization:

  // Disable the selected SPI peripheral
  SPI1->CR1 &= ~SPI_CR1_SPE;
 
//  SPI1->CR1 = (SPI_MODE_MASTER | SPI_DIRECTION_2LINES | SPI_DATASIZE_8BIT |
//               SPI_POLARITY_LOW | SPI_PHASE_1EDGE | (SPI_NSS_SOFT & SPI_CR1_SSM) |
//               SPI_BAUDRATEPRESCALER_4 | SPI_FIRSTBIT_MSB  | SPI_CRCCALCULATION_DISABLED);
  SPI1->CR1 = (SPI_MODE_MASTER | SPI_DIRECTION_2LINES | SPI_DATASIZE_8BIT |
               SPI_POLARITY_HIGH | SPI_PHASE_2EDGE | (SPI_NSS_SOFT & SPI_CR1_SSM) |
               SPI_BAUDRATEPRESCALER_4 | SPI_FIRSTBIT_MSB  | SPI_CRCCALCULATION_DISABLED);
 
  // Configure : NSS management
  SPI1->CR2 = (((SPI_NSS_SOFT >> 16) & SPI_CR2_SSOE) | SPI_TIMODE_DISABLED);
 
  // ---------------------------- SPIx CRCPOLY Configuration ------------------
  // Configure : CRC Polynomial
  SPI1->CRCPR = 7;
 
  /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
  SPI1->I2SCFGR &= (uint32_t)(~SPI_I2SCFGR_I2SMOD);

Initialization is done at the slowest speed possible, set using a routine to change the speed:

void spiSetSpeed(uint32_t Prescaler)
{
  u32 tmp;
 
  tmp = SPI1->CR1;    // Read current configuration
  tmp &= 0xFFFFFFC7;  // Preserve all but prescaler bits, set those to 0's
  tmp |= Prescaler;   // Add new prescaler bits
  SPI1->CR1 = tmp;    // Write back to register
}

Called with:

spiSetSpeed(SPI_BAUDRATEPRESCALER_256);

Has anyone else seen anything like this?  I've checked the CPU errata and can't find anything.

Thanks,
  Jeff.

Outcomes