cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F417 SPI1 Start Bit Detection

jwormsley
Associate III
Posted on December 15, 2015 at 00:28

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 00000 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 00000 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. #stm32f417-spi-spi1
3 REPLIES 3
Posted on December 15, 2015 at 06:52

Try to clear SPE while changing the baudrate or anything else in SPI_CR1.

JW
jwormsley
Associate III
Posted on December 15, 2015 at 19:28

That didn't help (there were no changes during communications anyway).

Using the ST HAL code from MXCube didn't help either.

A different card works, although this card works in my PC (probably SDIO mode) and in another STM32F103 board in SPI mode.

I've seen mention on a PIC forum about some cards showing this behavior, but that was because the CRC/End Byte was being sent as 0x00, where it should have had bit0 (LSBit) set, and in my code that is 0x01 (and I tried 0xFF) as well, so that's not the issue.

For now, I'm going to set this card aside and continue with a card that isn't showing this issue.

Thanks,

  Jeff.
jwormsley
Associate III
Posted on December 15, 2015 at 23:47

I believe I have this resolved.  Apparently these cards work as simple state machines, and some cards but not other require a few more clocks to complete their internal state transitions to be ready to accept a new command (but only on certain commands, ones issued early in initialization cannot tolerate the extra clocks).  

The solution is, on commands outside of early initialization, to issue reads on the SPI port until the read data is 0xFF.  This is usually, but not always, just one read.  Then when reading the R1 response, read until the MSB is zero, usually only two reads.  This lets both of the cards I was using operate properly.

Thanks,

  Jeff.