Skip to main content
Tamas Novak
Associate III
December 29, 2015
Question

SDRAM write/read order problem

  • December 29, 2015
  • 5 replies
  • 1625 views
Posted on December 29, 2014 at 15:09

My project contains a STM32F429 and a AS4C4M16S SDRAM (own designed PCB)

I have tested writing-reading by the next function:

void    SDRAM_TEST(void) {

int i;

int err=0;

int ok=0;

HAL_StatusTypeDef ret;

#define TEST_ARRAY_SIZE_WORD   10000

uint16_t x1[TEST_ARRAY_SIZE_WORD];

uint16_t x2[TEST_ARRAY_SIZE_WORD];

for (i=0; i<TEST_ARRAY_SIZE_WORD; i++) {    //random data into the buffer

    x1[i]= rand();

    }   

ret= HAL_SDRAM_Write_16b(&hsdram, SDRAM0, x1, TEST_ARRAY_SIZE_WORD);    //write to SDRAM

ret= HAL_SDRAM_Read_16b(&hsdram, SDRAM0, x2,  TEST_ARRAY_SIZE_WORD);    //reading SDRAM back into other buffer

for (i=0; i<TEST_ARRAY_SIZE_WORD; i++) {

    if (x1[i] != x2[i])      err++; else     ok++;    //check if fits

    }   

 }

Surprisingly the ''err'' and ''ok'' values came out as 5000-5000!

The debug values of x1 and x2 arrays are

0   f42d   a01d

1   8ccf    8ccf

2   f646    f42d

3   3129   3129

4   5b04   f646

5   5db4   5db4

6   7f78    5b04

7   59d8   59d8

...

So even words are fine, odd words are shifted.

It seems to be a word-order problem.

Internally two 16-bit words are probably linked into one 32bit word, and

the problem must be there somewhere...

full code for FMC init is

void MX_FMC_Init(void) {    //**********************************************

int i;

HAL_StatusTypeDef  ret;  

FMC_SDRAM_TimingTypeDef  timing;

hsdram.Instance = FMC_SDRAM_DEVICE;    //Perform the SDRAM1 memory initialization sequence

hsdram.Init.SDBank = FMC_SDRAM_BANK1;

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_2;

hsdram.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;

hsdram.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_3;  

hsdram.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;

hsdram.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;    //1??

//168MHz, tcycle= 11.9nsec

timing.LoadToActiveDelay= 2;    // TMRD: 2 Clock cycles

timing.ExitSelfRefreshDelay= 7;    //TXSR: min=65ns (6x11.9ns)   

timing.SelfRefreshTime= 5;            //TRAS: min=49ns (5x11.90ns)

timing.RowCycleDelay= 7;            //TRC:  min=63 nsec (6x11.90ns)

timing.WriteRecoveryTime= 2;    //TWR:  2 Clock cycles

timing.RPDelay= 2;                        //TRP:  min=21nsec  (2x11.90ns)

timing.RCDDelay= 2;                    //TRCD: min=21nsec (2x11.90ns )

ret= HAL_SDRAM_Init(&hsdram, &timing);        //Initialize the SDRAM controller

if(ret != HAL_OK)   {

    i= 99;   //bp here debug

    }

SDRAM_Initialization_Sequence(&hsdram);   //Program the SDRAM external device

}

void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram) {    //***********************************************

//static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Cmd) {    //***********************************************

FMC_SDRAM_CommandTypeDef Cmd;

__IO uint32_t tmpmrd =0;

Cmd.CommandMode= FMC_SDRAM_CMD_CLK_ENABLE;    //Step 3:  Configure a clock configuration enable command

Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

Cmd.AutoRefreshNumber= 1;

Cmd.ModeRegisterDefinition= 0;

HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);    //Send the command

HAL_Delay(100);    //Step 4: Insert 100 ms delay

Cmd.CommandMode= FMC_SDRAM_CMD_PALL;    //Step 5: Configure a PALL (precharge all) command

Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

Cmd.AutoRefreshNumber= 1;

Cmd.ModeRegisterDefinition= 0;

HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

Cmd.CommandMode= FMC_SDRAM_CMD_AUTOREFRESH_MODE;    //Step 6 : Configure a Auto-Refresh command

Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

Cmd.AutoRefreshNumber= 4;

Cmd.ModeRegisterDefinition= 0;

HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2          |        //Step 7: Program the external memory mode register

                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |

                     SDRAM_MODEREG_CAS_LATENCY_3           |

                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |

                     SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

Cmd.CommandMode= FMC_SDRAM_CMD_LOAD_MODE;

Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

Cmd.AutoRefreshNumber= 1;

Cmd.ModeRegisterDefinition= tmpmrd;

HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

    /* Step 8: Set the refresh rate counter

64msec / 4096 fresh = 15.62 us

refresh count= 15.62usec * 84MHz  - 20 =  1292 */

HAL_SDRAM_ProgramRefreshRate(hsdram, 1292);     //refresh count

}

    This topic has been closed for replies.

    5 replies

    bmh
    Associate II
    November 22, 2015
    Posted on November 22, 2015 at 18:55

    Hi, I'm facing a similar problem with same SDRAM. Can you publish the configuration that worked for you?

    Thanks,

    Tamas Novak
    Associate III
    February 3, 2017
    Posted on February 03, 2017 at 16:44

    I'm a bit late, but here is the working source:

    void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram) { //***********************************************

    //static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Cmd) { //***********************************************

    FMC_SDRAM_CommandTypeDef Cmd;

    __IO uint32_t tmpmrd =0;

    Cmd.CommandMode= FMC_SDRAM_CMD_CLK_ENABLE; //Step 3: Configure a clock configuration enable command

    Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

    Cmd.AutoRefreshNumber= 1;

    Cmd.ModeRegisterDefinition= 0;

    HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000); //Send the command

    HAL_Delay(100); //Step 4: Insert 100 ms delay

    Cmd.CommandMode= FMC_SDRAM_CMD_PALL; //Step 5: Configure a PALL (precharge all) command

    Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

    Cmd.AutoRefreshNumber= 1;

    Cmd.ModeRegisterDefinition= 0;

    HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

    Cmd.CommandMode= FMC_SDRAM_CMD_AUTOREFRESH_MODE; //Step 6 : Configure a Auto-Refresh command

    Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

    Cmd.AutoRefreshNumber= 4;

    Cmd.ModeRegisterDefinition= 0;

    HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

    tmpmrd = (uint32_t) //Step 7: Program the external memory mode register

          0x0200 | //bit9: write burst length 1=single bit

          0x0000 | //bit 8..7: test mode=0 normal mode

          0x0020 | //bit 6..4: cas latency= 2

          0x0000 | //bit 3: burst type=1 sequential

          0x0000; //bit 2..0: burst length= 1 word

    Cmd.CommandMode= FMC_SDRAM_CMD_LOAD_MODE;

    Cmd.CommandTarget= FMC_SDRAM_CMD_TARGET_BANK1;

    Cmd.AutoRefreshNumber= 1;

    Cmd.ModeRegisterDefinition= tmpmrd;

    HAL_SDRAM_SendCommand(hsdram, &Cmd, 0x1000);

    /* Step 8: Set the refresh rate counter

    64msec / 4096 fresh = 15.62 us

    refresh count= 15.62usec * 84MHz - 20 = 1292 */

    HAL_SDRAM_ProgramRefreshRate(hsdram, 1292); //refresh count

    }
    waclawek.jan
    Super User
    December 29, 2015
    Posted on December 29, 2014 at 15:45

    > So even words are fine, odd words are shifted.

    You mean, odd halfwords are fine, even are shifted.

    What is the result of direct reading, after the above test, e.g. if you add

    somevariable = *(uint16_t *)SDRAM0;

    someothervariable = *(uint32_t *)SDRAM0;

    after the above test, what are the x1[]/x2[]/somevariable/someothervariable?

    JW

    Tamas Novak
    Associate III
    December 30, 2015
    Posted on December 30, 2014 at 20:47

    Thanks, Jan,

    the FMC_SDRAM_CMD_LOAD_MODE   command in SDRAM_Initialization_Sequence() was bad.  I have simply copied the Mode parameters from some example code, which was for a different type of SDRAM...it was a miracle that even half of bytes fitted:)))

    I couldn't clearly understand how that happened...

    but now it's 10k/10k good!!!

    thanks,

     Tamas

    Mootaz Amr
    Associate II
    February 13, 2017
    Posted on February 13, 2017 at 16:49

    Hi Thomas Novak

    Ihave a custom made board around an STM32F429IIT6 connected to an external SDRAM AS4C4M16SA, I followed initialization steps embedded in the STM32F429 Reference Manual

    /external-link.jspa?url=http%3A%2F%2Fwww.st.com%2Fcontent%2Fccc%2Fresource%2Ftechnical%2Fdocument%2Freference_manual%2F3d%2F6d%2F5a%2F66%2Fb4%2F99%2F40%2Fd4%2FDM00031pdf%2Ffiles%2FDM00031pdf%2Fjcr%3Acontent%2Ftranslations%2Fen.DM00031pdf

    page 1663, and the Power Up sequence described in Note 11 of the AS4C4M16SA

    /external-link.jspa?url=http%3A%2F%2Fwww.alliancememory.com%2Fpdf%2Fdram%2F64M-AS4C4M16SA.pdf

    page

    I configured also the same settings and initialization stepsthat you usedbutit fails for me.

    Iused previously the MT48LC4M16 chip and it works fine, but the PCB design has changed and the old code doesn't fit the new AS4C4M16SA, the pins of the 2 chips are the same, and connections with the microcontroller are then the same.

    Iuploaded my configuration files, my test functions, my serial_debug results and my schematic related to the memory power and pins.

    Is there any difference inmy and your schematics ? Is there any problem with my code ?

    I don't think that the problem is from a difference in the used libraries,CMSIS (for my case) and HAL

    (for yours)arealmost the same especially for the SDRAM controller, and migrating toHAL library isn't a solution since I will be forcedto rewrite the wholeproject.

    Thanks

    ________________

    Attachments :

    Schematic and config Files.rar : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hyvn&d=%2Fa%2F0X0000000bE6%2FF0LAei5EkL4yZ8xgOI73RcJmHvXpUXtT7uosBBWwCbU&asPdf=false