Occasional Data Corruption in the external SDRAM in STM32F429
Hi,
I run an application with stm32f429zg using freertos. An external 8Mb SDRAM from winbond (W9864G6KH-6) is used with fmc protocol.
I set timing settings in stm32cubemx based on the sdram datasheet.
The common clock of sdram is 72Mhz. All other settings can be seen below:
The sdram initialization code can also be seen below:
static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
__IO uint32_t tmpmrd =0;
/* Step 3: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 4: Insert 100 ms delay */
HAL_Delay(100);
/* Step 5: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 6 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 4;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 7: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_2 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, 0x1000);
/* Step 8: Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
}I define a uint8_t array (about 50kbytes) in sdram and use it in dma spi receive. This buffer that contains samples of a 50 Hz sinusoidal waveform is written by dma about every 125us. After the completion of dma data receive, it is processed by another task.
One problem I have is that sometimes data stored in the sdram become corrupted. For example, I see some unusual and invalid surge in the waveform. It means that some bytes of buffer in the external sdram are corrupted. When I define this buffer in the internal MCU ram all things go well and there is no corruption.
When I change some config like sdram timing or refresh rate or CAS latency, the corruption rate is also changed, but I couldn’t have a complete valid samples yet.
I think this problem may be aroused from one of the below reasons:
1. There are some mistakes in PCB layout design.
2. Timing config may not set correctly.
3. Self-Refresh or auto-refresh rate is not chosen properly
4. The selected burst length is not compatible with this sdram.
5. …..
Which of the above (or other unmentioned) reasons do you consider more probable? How can I a find the main reason?
Thanks
