2024-10-11 09:39 AM
I'm working on a custom board with a STM32H723ZG. I'm also using external sd ram part IS42S16400J-6TL found here (https://www.digikey.com/en/products/detail/issi-integrated-silicon-solution-inc/IS42S16400J-6TL/2708625). I've followed the excellent sd ram tutorial here: https://community.st.com/t5/stm32-mcus/how-to-set-up-the-fmc-peripheral-to-interface-with-the-sdram/ta-p/49457 which was how I was able to determine the values in the stm32 cube IDE. The FMC init generated function runs without error (MX_FMC_Init which calls HAL_SDRAM_Init). I have posted the cube IDE set up below.
This is a new board design, so it is possible that something about the layout isn't working, but I've confirmed that all the lines are connected correctly to the chip. The address and data lines are also length matched.
My FMC clock input is using HCLK3 at 275Mhz, but the sd ram common clock is 3 HCLK cycles, so this should put the sd ram clock at 91.66 mhz. I believe this is below the 110 mhz limit for my voltage range (3.3V).
I understand that there a lot of reasons why this "isn't working", but as a first step, I am attempting to use an oscilloscope to see the clock waveform. There is no waveform, it is always low.
I also have tried to upload the same firmware to a discovery board with the same chip (NUCLEO-H723ZG) and am not seeing the clk signal (even though there is no sd ram on this board) .
I'm looking for advice on other threads I can pull to discover what is wrong. Im not getting any errors until I attempt to read memory at 0xC0000000 (which is a hard fault for reading memory which is inaccessible, pretty generic).
DataSheet Symbol | Datasheet value | CubeMx name | CubeMX value | |
Tmrd | 2 cycles | Load Mode Register to Active Delay | ||
TXSR | 66 ns | exit self refresh delay | 7 | |
tRAS | 42 ns (min) | self refresh time | 4 | |
trc | 60 ns | sdram common row cycle delay | 6 | |
tDPL | 2 * clk (nanoseconds) | Write Recovery time | 3 | twr - tcd (5 -2) =3 |
tRP | 15 ns | common row precharge delay | 2 | |
tRCD | 15 ns | row to col delay | 2 |
Thank you.
Solved! Go to Solution.
2024-10-16 01:18 PM
I've solved the problem. When you generate fmc related files in cubemx, they can be different if your target is a ST board, vs just the chip. The following defines and sd ram commands were present in the discovery board, but were not being generated when I built for our custom board. Adding these in allowed me to see the clock signal (FMC_CLK) and then I was able to read sd ram
/* USER CODE BEGIN 0 */
#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)
/* USER CODE END 0 */
// More generated code ....
/* USER CODE BEGIN FMC_Init 2 */
/* Step 1: Configure a clock configuration enable command */
static FMC_SDRAM_CommandTypeDef command;
command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &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_BANK1;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
/* Step 4: Configure an Auto Refresh command */
command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
command.AutoRefreshNumber = 8;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
uint32_t 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(&hsdram1, &command, SDRAM_TIMEOUT);
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, 1292);
/* USER CODE END FMC_Init 2 */
2024-10-16 01:18 PM
I've solved the problem. When you generate fmc related files in cubemx, they can be different if your target is a ST board, vs just the chip. The following defines and sd ram commands were present in the discovery board, but were not being generated when I built for our custom board. Adding these in allowed me to see the clock signal (FMC_CLK) and then I was able to read sd ram
/* USER CODE BEGIN 0 */
#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)
/* USER CODE END 0 */
// More generated code ....
/* USER CODE BEGIN FMC_Init 2 */
/* Step 1: Configure a clock configuration enable command */
static FMC_SDRAM_CommandTypeDef command;
command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &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_BANK1;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
/* Step 4: Configure an Auto Refresh command */
command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
command.AutoRefreshNumber = 8;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &command, SDRAM_TIMEOUT);
uint32_t 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(&hsdram1, &command, SDRAM_TIMEOUT);
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, 1292);
/* USER CODE END FMC_Init 2 */