cserp
cserp

Reputation: 29

STM32 SDRAM Write or Read Operation Is Not Executing Properly

I am using STM32F469BIT6 on a custom PCB with IS42S16400J-7TLI external 8Mb SDRAM. On my previous board, I was using STM32F429ZIT6 with the same SDRAM (these MCU and SDRAM were selected because they were used in STM32F429-DISCO) I was able to write/read data to/from SDRAM with these settings:

sdram config

When I try the same settings with the new MCU (STM32F469BIT6) on the new PCB, I can write to / read from SDRAM but data is corrupted. Here's the code that I use to test my SDRAM:

/* USER CODE BEGIN PV */
volatile uint8_t *externalRAM = (uint8_t*) 0xC0000000;
const uint32_t size = 8 * 1024 * 1024; //8MB
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
//write external RAM
for (uint32_t i = 0; i < size; i++) {
    externalRAM[i] = i % 256;
}

//read external RAM
for (uint32_t i = 0; i < size; i++) {
    if (externalRAM[i] != i % 256) {
        asm("nop");
        // insert error handling logic here
    }
}
/* USER CODE END 2 */

Here's my SDRAM configuration code:

    /* USER CODE BEGIN FMC_Init 2 */
    FMC_SDRAM_CommandTypeDef Command;
    /* Step 1 and Step 2 already done in HAL_SDRAM_Init() */
    /* Step 3: Configure a clock configuration enable command */
    Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; /* Set MODE bits to "001" */
    Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; /* configure the Target Bank bits */
    Command.AutoRefreshNumber = 1;
    Command.ModeRegisterDefinition = 0;
    HAL_SDRAM_SendCommand(&hsdram2, &Command, 0xfff);
    HAL_Delay(1); /* Step 4: Insert 100 us minimum delay - Min HAL Delay is 1ms */
    /* Step 5: Configure a PALL (precharge all) command */
    Command.CommandMode = FMC_SDRAM_CMD_PALL; /* Set MODE bits to "010" */
    HAL_SDRAM_SendCommand(&hsdram2, &Command, 0xfff);
    /* Step 6: Configure an Auto Refresh command */
    Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; /* Set MODE bits to "011" */
    Command.AutoRefreshNumber = 2;
    HAL_SDRAM_SendCommand(&hsdram2, &Command, 0xfff);
    /* Step 7: Program the external memory mode register */
    Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;/*set the MODE bits to "100" */
    Command.ModeRegisterDefinition = (uint32_t) 0 | 0 << 3 | 2 << 4 | 0 << 7
            | 1 << 9;
    HAL_SDRAM_SendCommand(&hsdram2, &Command, 0xfff);
    /* Step 8: Set the refresh rate counter - refer to section SDRAM refresh timer register in RM0455 */
    /* Set the device refresh rate
     * COUNT = [(SDRAM self refresh time / number of row) x  SDRAM CLK] – 20
     = [(64ms/4096) * 100MHz] - 20 = 1562.5 - 20 ~ 1542 */
    HAL_SDRAM_ProgramRefreshRate(&hsdram2, 1292); // 84MHZ
    /* USER CODE END FMC_Init 2 */

I can see clock generated on the oscilloscope:

oscilloscope

So, the problem is this:

volatile uint8_t *externalRAM = (uint8_t *) 0xC0000000;
const uint32_t size = (8 * 1024 * 1024); // 8MB

When I try to write uint8_t values, if the value is odd (address being even or odd does not change anything), it seems like all the data in SDRAM is set to that value. If the value is even, all even addresses are set to that value. This can happen because of write or read issues in SDRAM. I could not pin point if I am writing correct but reading wrong, writing wrong reading correct or both.

one byte write memory view 1

one byte write memory view 2

volatile uint16_t *externalRAM = (uint16_t *) 0xC0000000;
const uint32_t size = (8 * 1024 * 1024) / 2; // 8MB

When I try to write uint16_t values, no matter the value/address, only even addresses change and their values are all the same.

two bytes write memory view

volatile uint32_t *externalRAM = (uint32_t *) 0xC0000000;
const uint32_t size = (8 * 1024 * 1024) / 4; // 8MB

When I try to write uint32_t values, no matter the value/address, I don't see any change in memory viewer.

three bytes write memory view

I tried with different clock frequencies and SDRAM configurations but the problem is not fixed. For example I tried:

@30MHz (MCU CLK 60MHz)

Setting Value
Load mode register to active delay (tMRD / tRSC) 2
Exit self-refresh delay (tXSR) 3
Self-refresh time (tRAS) 2
SDRAM common row cycle delay (tRC) 2
Write recovery time (tWR) 2
SDRAM common row precharge delay (tRP) 1
Row to column delay (tRCD) 1
Refresh Rate 448

@90MHz (MCU CLK 180MHz MAX)

Setting Value
Load mode register to active delay (tMRD / tRSC) 2
Exit self-refresh delay (tXSR) 7
Self-refresh time (tRAS) 4
SDRAM common row cycle delay (tRC) 6
Write recovery time (tWR) 2
SDRAM common row precharge delay (tRP) 2
Row to column delay (tRCD) 2
Refresh Rate 1386

So what might be the issue here? Any help would be much appreciated! If we can't figure out what is the problem, I can connect all SDRAM pins to logic analyzer and share the results.

Upvotes: 0

Views: 71

Answers (1)

cserp
cserp

Reputation: 29

I saw that in the initialization code I got from STM32 was incorrcet. I just copied and pasted the code. Only change I did was the refresh rate, but I did not see that it's initializing BANK2. My SDRAM bank is 1, so I wrote:

    Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; /* Set MODE bits to "001" */
    Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; /* configure the Target Bank bits */
    Command.AutoRefreshNumber = 1;
    Command.ModeRegisterDefinition = 0;
    HAL_SDRAM_SendCommand(&hsdram2, &Command, 0xfff);

and problem is solved.

Upvotes: 2

Related Questions