Question
SDRAM write/read order problem
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 }