cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot get FMC SDRAM driver to work on stm32f429 discovery board

MLiva
Associate III

Using CubeMX configuration specific to stm32f429 discovery board which configures FMC to support SDRAM board. Have a memory test program that tests the 8Mb memory available at 0xD0000000. This program fails to run by triggering a hardware fault exception. The same program works fine with example FMC configuration which is not using CubeMX. I checked the pin configuration between the two and they seem same. Is there anything I am missing, I was expecting the CubeMX driver to work out of the box.

10 REPLIES 10
DavidAlfa
Senior II

Thanks!! I was having a painful time trying to correctly init it.

I tried my stm32f429 discovery years ago, back then the libraries and documentation were a mess, and as I only program as a hobbie I abandoned it.

Now due the covid and the lockdown I returned to it.

The HAL library is a little better, and the CUBEMX makes the initial configuration a breeze, although still lacks a lot of documentation and there're plenty of bugs.

There's a small problem in your code, as it doesn't check for Busy flag, and at the end doesn't wait for the refresh command to finish.

This resulted in my STM hanging every time, also freezing the stlink, because I erased the LCD buffer area just after initializing the SDRAM.

Adding Busy flag checks made it work perfectly,

/* Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
//#define REFRESH_COUNT      ((uint32_t)1386)  /* SDRAM refresh counter from forum*/
#define REFRESH_COUNT      ((uint32_t)683)  /* SDRAM refresh counter old setting */
#define SDRAM_TIMEOUT      ((uint32_t)0xFFFF)
/**
 * @brief FMC SDRAM Mode definition register defines
 */
#define SDRAM_MODEREG_BURST_LENGTH_1       ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2       ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4       ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8       ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED   ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2       ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3       ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD  ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE   ((uint16_t)0x0200)
 
void SDRAM_InitSequence(void) {
 
	FMC_SDRAM_CommandTypeDef FMC_SDRAMCommandStructure;
	uint32_t tmpr = 0;
 
	/* Step 1 --------------------------------------------------------------------*/
	/* Configure a clock configuration enable command */
	FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
	FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
	FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
	FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before sending command
	HAL_SDRAM_SendCommand(&hsdram1, &FMC_SDRAMCommandStructure, SDRAM_TIMEOUT);
 
	/* Step 2 --------------------------------------------------------------------*/
	/* Configure a PALL (precharge all) command */
	FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_PALL;
	FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
	FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
	FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before sending command
	HAL_SDRAM_SendCommand(&hsdram1, &FMC_SDRAMCommandStructure, SDRAM_TIMEOUT);
 
	/* Step 3 --------------------------------------------------------------------*/
	/* Configure a Auto-Refresh command */
	FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
	FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
	FMC_SDRAMCommandStructure.AutoRefreshNumber = 4;
	FMC_SDRAMCommandStructure.ModeRegisterDefinition = 0;
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before sending command
	HAL_SDRAM_SendCommand(&hsdram1, &FMC_SDRAMCommandStructure, SDRAM_TIMEOUT);
 
	/* Step 4 --------------------------------------------------------------------*/
	/* Program the external memory mode register */
	tmpr = (uint32_t)	SDRAM_MODEREG_BURST_LENGTH_1     |
					SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL  |
					SDRAM_MODEREG_CAS_LATENCY_3      |
					SDRAM_MODEREG_OPERATING_MODE_STANDARD |
					SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
 
	/* Step 5 --------------------------------------------------------------------*/
	/* Configure a load Mode register command*/
	FMC_SDRAMCommandStructure.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
	FMC_SDRAMCommandStructure.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
	FMC_SDRAMCommandStructure.AutoRefreshNumber = 1;
	FMC_SDRAMCommandStructure.ModeRegisterDefinition = tmpr;
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before sending command
	HAL_SDRAM_SendCommand(&hsdram1, &FMC_SDRAMCommandStructure, SDRAM_TIMEOUT);
 
	/* Step 6 --------------------------------------------------------------------*/
	/* Set the refresh rate counter */
	/* (7.81 us x Freq) - 20 */
	/* Set the device refresh counter */
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before sending command
	HAL_SDRAM_ProgramRefreshRate(&hsdram1, REFRESH_COUNT); // local
	
	while( (HAL_SDRAM_GetState(&hsdram1) & HAL_SDRAM_STATE_BUSY) );	// Check Busy Flag before returning
}