Skip to main content
GGowi.1
Associate II
July 23, 2020
Solved

External RAM on STM32H743IIT6

  • July 23, 2020
  • 6 replies
  • 4204 views

I am trying to set up FMC to work with external RAM. The code compiles and works with KEIL, but I am trying to make it work with STM32CubeIDE. The code compiles and runs, but the RAM is not initialized. I copied all of the code, including the .ioc file, and used it but it won't enable the RAM.

I have a temporary license for KEIL and I have confirmed that the memory and the code work by compiling and debugging in KEIL and accessing the RAM in the code and in the debugger.

Any thoughts or ideas? I need this external ram so I can continue to port TouchGFX to my board for a research project.

Thanks

This topic has been closed for replies.
Best answer by PMath.4

Setup FMC and SDRAM

void RAMSETUP(void){
	 /*##-1- Configure the SDRAM device #########################################*/
	 /* SDRAM device configuration */
	 hsdram.Instance = FMC_SDRAM_DEVICE;
 
	 /* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
	 SDRAM_Timing.LoadToActiveDelay = 2;
	 SDRAM_Timing.ExitSelfRefreshDelay = 7;
	 SDRAM_Timing.SelfRefreshTime = 4;
	 SDRAM_Timing.RowCycleDelay = 7;
	 SDRAM_Timing.WriteRecoveryTime = 2;
	 SDRAM_Timing.RPDelay = 2;
	 SDRAM_Timing.RCDDelay = 2;
 
	 hsdram.Init.SDBank = FMC_SDRAM_BANK2;
	 hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
	 hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
	 hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
	 hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
	 hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
	 hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
	 hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
	 hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
	 hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
 
	 /* Initialize the SDRAM controller */
	 if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
	 {
	 /* Initialization Error */
	 SystemError=1;Error_Handler();
	 }
 
	 /* Program the SDRAM external device */
	 SDRAM_Initialization_Sequence(&hsdram, &command);
 
}

6 replies

Tesla DeLorean
Guru
July 24, 2020

"the RAM is not initialized."

Hard Faults, because the hardware/pins don't come up, or some static initialization is not copied over there?

The latter means you have to add code in startup.s to copy over the statics, which Keil would have done if the memory was properly setup in SystemInit()

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
GGowi.1
GGowi.1Author
Associate II
July 24, 2020

Thanks. I'll look into it. I'm new to STM bare-metal programming. I'll see what differences I can find.

I tried copying the original code from the KEIL project but it wouldn't work, so something is obviously missing. Thanks.

Tesla DeLorean
Guru
July 24, 2020

Probably the Keil library code that unpacks the Load Region properly.

Didn't really answer the question as to whether the memory was accessible..​

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
PMath.4
Senior III
July 25, 2020

I'm using the Waveshare board with STM32CubeIDE. I'll attach the various bits of relevant code. Willl take more than 1 post due to size limits on the forum

IN main.c start the clocks including the FMC clock

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
 
 /** Supply configuration update enable 
 */
 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
 /** Configure the main internal regulator output voltage 
 */
 if(HAL_GetREVID()==0x1003)__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 else __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
 
 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
 /** Configure LSE Drive Capability 
 */
 __HAL_RCC_BKPRAM_CLK_ENABLE();
 HAL_PWREx_EnableBkUpReg();
 HAL_PWR_EnableBkUpAccess();
 /** Macro to configure the PLL clock source 
 */
 __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI
 |RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON ;
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = 1;
 RCC_OscInitStruct.PLL.PLLN = (MAINCLOCKSPEED>>2);
 RCC_OscInitStruct.PLL.PLLP = 2;
 RCC_OscInitStruct.PLL.PLLQ = 20;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
 RCC_OscInitStruct.PLL.PLLFRACN = 0;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 SystemError=1;Error_Handler();
 }
 /** Initializes the CPU, AHB and APB busses clocks 
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, (HAL_GetREVID()==0x1003 ? FLASH_LATENCY_2:FLASH_LATENCY_4)) != HAL_OK)
 {
 SystemError=1;Error_Handler();
 }
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_LTDC
 |RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_UART4
 |RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_RNG
 |RCC_PERIPHCLK_SPI3|RCC_PERIPHCLK_SPI1
 |RCC_PERIPHCLK_SPI2|RCC_PERIPHCLK_I2C2
 |RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_I2C1
 |RCC_PERIPHCLK_I2C4|RCC_PERIPHCLK_USB
 |RCC_PERIPHCLK_FMC;
 PeriphClkInitStruct.PLL2.PLL2M = 1;
 if(HAL_GetREVID()==0x1003){
	 PeriphClkInitStruct.PLL2.PLL2N = 100;
	 PeriphClkInitStruct.PLL2.PLL2P = 16;
	 PeriphClkInitStruct.PLL2.PLL2Q = 16;
	 PeriphClkInitStruct.PLL2.PLL2R = 4;
 } else {
	 PeriphClkInitStruct.PLL2.PLL2N = 120;
	 PeriphClkInitStruct.PLL2.PLL2P = 20;
	 PeriphClkInitStruct.PLL2.PLL2Q = 20;
	 PeriphClkInitStruct.PLL2.PLL2R = 5;
 }
 PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
 PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
 PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
 PeriphClkInitStruct.PLL3.PLL3M = 1;
 if(HAL_GetREVID()==0x1003){
	 PeriphClkInitStruct.PLL3.PLL3N = 100;
	 PeriphClkInitStruct.PLL3.PLL3P = 20;
	 PeriphClkInitStruct.PLL3.PLL3Q = 20;
	 PeriphClkInitStruct.PLL3.PLL3R = 20;
 } else {
	 PeriphClkInitStruct.PLL3.PLL3N = 120;
	 PeriphClkInitStruct.PLL3.PLL3P = 24;
	 PeriphClkInitStruct.PLL3.PLL3Q = 24;
	 PeriphClkInitStruct.PLL3.PLL3R = 24;
 }
 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_3;
 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
 PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_PLL2;
 PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
 PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_PLL2;
 PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_PLL2;
 PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48;
 PeriphClkInitStruct.I2c123ClockSelection = RCC_I2C123CLKSOURCE_HSI;
 PeriphClkInitStruct.UsbClockSelection = (HAL_GetREVID()==0x1003 ? RCC_USBCLKSOURCE_HSI48:RCC_USBCLKSOURCE_PLL);
 PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_HSI;
 PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
 {
 SystemError=1;Error_Handler();
 }
 HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1);
 /** Enable USB Voltage detector 
 */
 HAL_PWREx_EnableUSBVoltageDetector();
}

GGowi.1
GGowi.1Author
Associate II
July 25, 2020

Can you attach your .ioc file? It looks like most of this code is autogenerated by CubeMX. I'm trying to figure out which settings to change so I don't have to go in and change the files manually each time.

PMath.4
PMath.4Best answer
Senior III
July 25, 2020

Setup FMC and SDRAM

void RAMSETUP(void){
	 /*##-1- Configure the SDRAM device #########################################*/
	 /* SDRAM device configuration */
	 hsdram.Instance = FMC_SDRAM_DEVICE;
 
	 /* Timing configuration for 100Mhz as SDRAM clock frequency (System clock is up to 200Mhz) */
	 SDRAM_Timing.LoadToActiveDelay = 2;
	 SDRAM_Timing.ExitSelfRefreshDelay = 7;
	 SDRAM_Timing.SelfRefreshTime = 4;
	 SDRAM_Timing.RowCycleDelay = 7;
	 SDRAM_Timing.WriteRecoveryTime = 2;
	 SDRAM_Timing.RPDelay = 2;
	 SDRAM_Timing.RCDDelay = 2;
 
	 hsdram.Init.SDBank = FMC_SDRAM_BANK2;
	 hsdram.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
	 hsdram.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
	 hsdram.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
	 hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
	 hsdram.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
	 hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
	 hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
	 hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
	 hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
 
	 /* Initialize the SDRAM controller */
	 if(HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK)
	 {
	 /* Initialization Error */
	 SystemError=1;Error_Handler();
	 }
 
	 /* Program the SDRAM external device */
	 SDRAM_Initialization_Sequence(&hsdram, &command);
 
}

GGowi.1
GGowi.1Author
Associate II
July 25, 2020

Where are you getting the variable command?

PMath.4
Senior III
July 25, 2020

Configure the pins

static uint32_t FMC_Initialized = 0;
 
static void HAL_FMC_MspInit(void){
 /* USER CODE BEGIN FMC_MspInit 0 */
 
 /* USER CODE END FMC_MspInit 0 */
 GPIO_InitTypeDef GPIO_InitStruct ={0};
 if (FMC_Initialized) {
 return;
 }
 FMC_Initialized = 1;
 
 /* Peripheral clock enable */
 __HAL_RCC_FMC_CLK_ENABLE();
 
 /** FMC GPIO Configuration 
 PF0 ------> FMC_A0
 PF1 ------> FMC_A1
 PF2 ------> FMC_A2
 PF3 ------> FMC_A3
 PF4 ------> FMC_A4
 PF5 ------> FMC_A5
 PH5 ------> FMC_SDNWE
 PF11 ------> FMC_SDNRAS
 PF12 ------> FMC_A6
 PF13 ------> FMC_A7
 PF14 ------> FMC_A8
 PF15 ------> FMC_A9
 PG0 ------> FMC_A10
 PG1 ------> FMC_A11
 PE7 ------> FMC_D4
 PE8 ------> FMC_D5
 PE9 ------> FMC_D6
 PE10 ------> FMC_D7
 PE11 ------> FMC_D8
 PE12 ------> FMC_D9
 PE13 ------> FMC_D10
 PE14 ------> FMC_D11
 PE15 ------> FMC_D12
 PH6 ------> FMC_SDNE1
 PH7 ------> FMC_SDCKE1
 PD8 ------> FMC_D13
 PD9 ------> FMC_D14
 PD10 ------> FMC_D15
 PD14 ------> FMC_D0
 PD15 ------> FMC_D1
 PG4 ------> FMC_BA0
 PG5 ------> FMC_BA1
 PG8 ------> FMC_SDCLK
 PD0 ------> FMC_D2
 PD1 ------> FMC_D3
 PG15 ------> FMC_SDNCAS
 PE0 ------> FMC_NBL0
 PE1 ------> FMC_NBL1
 */
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
 |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12 
 |GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5 
 |GPIO_PIN_8|GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10 
 |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 
 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14 
 |GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
 /* USER CODE BEGIN FMC_MspInit 1 */
 
 /* USER CODE END FMC_MspInit 1 */
}
 
void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram){
 /* USER CODE BEGIN SDRAM_MspInit 0 */
 
 /* USER CODE END SDRAM_MspInit 0 */
 HAL_FMC_MspInit();
 /* USER CODE BEGIN SDRAM_MspInit 1 */
 
 /* USER CODE END SDRAM_MspInit 1 */
}
 

PMath.4
Senior III
July 25, 2020

Main code startup

 SystemClock_Config();
RAMSETUP();
FMC_Bank1_R->BTCR[1] = 0x000030D2;
HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAMB2);

PMath.4
Senior III
July 25, 2020

Set up refresh

static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
 __IO uint32_t tmpmrd =0;
 /* Step 1: Configure a clock configuration enable command */
 Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
 Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;;
 Command->AutoRefreshNumber = 1;
 Command->ModeRegisterDefinition = 0;
 
 /* Send the command */
 HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
 
 /* Step 2: Insert 100 us minimum delay */
 /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
 HAL_Delay(1);
 
 /* Step 3: Configure a PALL (precharge all) command */
 Command->CommandMode = FMC_SDRAM_CMD_PALL;
 Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
 Command->AutoRefreshNumber = 1;
 Command->ModeRegisterDefinition = 0;
 
 /* Send the command */
 HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
 
 /* Step 4 : Configure a Auto-Refresh command */
 Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
 Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
 Command->AutoRefreshNumber = 8;
 Command->ModeRegisterDefinition = 0;
 
 /* Send the command */
 HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
 
 /* Step 5: Program the external memory mode register */
 tmpmrd = (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;
 
 Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
 Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
 Command->AutoRefreshNumber = 1;
 Command->ModeRegisterDefinition = tmpmrd;
 
 /* Send the command */
 HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
 
 /* Step 6: Set the refresh rate counter */
 /* Set the device refresh rate */
 HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
 
}