cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 SPI code only works in debug mode

LLOLO.1
Associate II

Hi I am trying to read ID of an external FLASH.

The code which reads it is shown below.

uint16_t FLASH_ReadID(void)
{
	uint16_t tempData = 0x0000;
 
	//Read ID
	GPIOB->BSRR |= GPIO_BSRR_BR2; //Reset FLASH CS
	while(!(SPI1->SR & SPI_SR_TXE));
	SPI1->DR = 0x9E;
 
	while(!(SPI1->SR & SPI_SR_TXE));
	SPI1->DR = 0xFF;
	while((SPI1->SR & SPI_SR_BSY));
	tempData = (SPI1->DR << 8);
 
	while(!(SPI1->SR & SPI_SR_TXE));
	SPI1->DR = 0xFF;
	while((SPI1->SR & SPI_SR_BSY));
	tempData |= SPI1->DR;
 
	GPIOB->BSRR |= GPIO_BSRR_BS2; //Set FLASH CS
 
	return tempData;
}

After reading 2byte ID (0x20, 0xBA)I am transmitting the ID information to PC through USART. I use a serial terminal program which called Hterm. Problem is when I run the code, the FLASH ID returns as 0x00, 0x20. I set SPI baudrate as 42Mbps. When I set the baudrate to lower speeds output becomes 0x00, 0x00. After getting 0x00, 0x00 if I call the function one more time I get 0x80, 0x80.

The most interesting part is when I debug the code it seems to return correct value of 0x20, 0xBA.

Why does the code work properly when in debug mode step by step?

4 REPLIES 4
TDK
Guru

From the reference manual:

Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the

TXE and RXNE flags instead.

If you feel a post has answered your question, please click "Accept as Solution".

I updated the code as below.

uint16_t FLASH_ReadID(void)
{
	uint16_t tempData = 0x0000;
 
	//Read ID
	GPIOB->BSRR |= GPIO_BSRR_BR2; //Reset FLASH CS
 
	SPI1->DR = 0x9E;
	while(!(SPI1->SR & SPI_SR_TXE));
	SPI1->DR = 0xFF;
	while(!(SPI1->SR & SPI_SR_RXNE));
	tempData = (SPI1->DR << 8);
	while(!(SPI1->SR & SPI_SR_TXE));
	SPI1->DR = 0xFF;
	while(!(SPI1->SR & SPI_SR_RXNE));
	tempData |= SPI1->DR;
	while((SPI1->SR & SPI_SR_BSY));
 
	GPIOB->BSRR |= GPIO_BSRR_BS2; //Set FLASH CS
 
	return tempData;
}

And I scoped the SPI line. The screenshot shown below.

0693W00000BaM4GQAV.jpg 

In scope everything seems to be fine but when I try to read the registers first I read 0x00, 0x20 and when I recall the function again I read 0xBA, 0x00 and if I recall the function again I read 0x20, 0x00. From this point whenever I call the function I read only 0x20,0x00. I am confused

Instead of polling RXNE and TX I decided to use RXNE interrupt for receiving data. It seems to work correct but I wonder why polling does not work?

TDK
Guru

For every byte you send, you need to read a byte, even if you don't care about it, in order to keep the RXNE flag in sync. Your code sends 3 bytes but only reads 2.

If you feel a post has answered your question, please click "Accept as Solution".