2023-04-03 06:22 AM
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
2023-04-22 08:14 AM - edited 2023-11-20 09:02 AM
hi, I found the same problem. I capture GPIO data triggered by TIM8_CH1 to buffer in DMA mode. When I locate the buffer in internal ram, all data are correct. But when I locate the buffer in SDRAM, occasional Data Corruption will occur randomly.
2023-04-23 03:39 AM
What revision is your chip? Have you checked the errata?
Years ago, I think with the first revision of stm32f433, there was a problem where an interrupt could spoil writing through the FMC. ST soon spotted the problem and came out with a fixed revision but any chips of the original revision are unusable as far as I am concerned.
It might be, given the recent chip shortages, that some of the first revision have come on the market.