STM32F4 SPI code only works in debug mode
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-07 05:18 AM
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-07 09:57 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-07 11:07 PM
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.
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-08 02:02 AM
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-06-08 07:11 AM
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.