|
SDRAM MT48LC16M16 + STM32F429 + FMC |
|
|
|
Oct 20 2016, 05:30
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Добрый день! Пытаюсь завести SDRAM MT48LC16M16 на моем STM32F429. Схему проверил уже несколько раз и не только я - все верно. Грешу уже только на инициализацию, уже просто не знаю куда смотреть. Тайминги уже несколько раз перепроверил. Если не затруднит, может кто посмотрит, может я просто что-то проглядел, по-причине "замыленности" глаза. Код:CODE /** * @brief Executes the SDRAM memory initialization sequence. * @param None. * @retval None. */ void SDRAM_InitSequence(void) { FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure; uint32_t tmpr = 0; uint32_t timeout = SDRAM_TIMEOUT;
// Step 3 -------------------------------------------------------------------- // Configure a clock configuration enable command FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled; // 0x00000001 FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2; // 0x00000010 FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0; //
// Wait until the SDRAM controller is ready while ( ( FMC_GetFlagStatus ( FMC_Bank2_SDRAM, FMC_FLAG_Busy ) != RESET ) && (timeout > 0) ) { timeout--; } // Send the command // SDCMR = 0x00000011 = xx 0001 0001 // MRD = 0 // NRFS = 0 - Clock Configuration Enable // CTB1 = 1 - Command issued to SDRAM Bank 1 // CTB2 = 0 - Command not issued to SDRAM Bank 2 // MODE = 001 - Clock Configuration Enable FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
// Step 4 -------------------------------------------------------------------- // Insert 100 ms delay timeout = SDRAM_TIMEOUT; while (timeout--); //_delay_ms ( 100 );
// Step 5 -------------------------------------------------------------------- // Configure a PALL (precharge all) command FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL; FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2; FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
// Wait until the SDRAM controller is ready timeout = SDRAM_TIMEOUT; while ( ( FMC_GetFlagStatus ( FMC_Bank2_SDRAM, FMC_FLAG_Busy ) != RESET ) && (timeout > 0) ) { timeout--; } // Send the command // SDCMR = 0x00000012 = xxx 0001 0010 // MRD = 0 // NRFS = 0 - Clock Configuration Enable // CTB1 = 1 - Command issued to SDRAM Bank 1 // CTB2 = 0 - Command not issued to SDRAM Bank 2 // MODE = 010 - Clock Configuration Enable FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
// Step 6 -------------------------------------------------------------------- // Configure a Auto-Refresh command FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh; FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2; FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8; FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
// Wait until the SDRAM controller is ready timeout = SDRAM_TIMEOUT; while ( ( FMC_GetFlagStatus ( FMC_Bank2_SDRAM, FMC_FLAG_Busy ) != RESET ) && (timeout > 0) ) { timeout--; } // Send the command // SDCMR = 0x00000013 = xxx 0001 0011 // MRD = 0 // NRFS = 7 - 7 Auto refresh cycles // CTB1 = 1 - Command issued to SDRAM Bank 1 // CTB2 = 0 - Command not issued to SDRAM Bank 2 // MODE = 011 - Auto-refresh command FMC_SDRAMCmdConfig ( &FMC_SDRAMCommandStructure );
// Step 7 -------------------------------------------------------------------- // Program the external memory mode register // 12 bits tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | // 0x0000 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | // 0x0000 SDRAM_MODEREG_CAS_LATENCY_3 | // 0x0030 SDRAM_MODEREG_OPERATING_MODE_STANDARD | // 0x0000 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; // 0x0200
// Configure a load Mode register command FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode; // 0x00000004 FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2; // 0x00000010 FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1; // 0 -> NRFS FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr; // 0x0230 << 9
// Wait until the SDRAM controller is ready timeout = SDRAM_TIMEOUT; while ( ( FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET ) && ( timeout > 0 ) ) { timeout--; }
// Send the command // MRD = 0x230 // NRFS = 0 - 0 Auto refresh cycles // CTB1 = 1 - Command issued to SDRAM Bank 1 // CTB2 = 0 - Command not issued to SDRAM Bank 2 // MODE = 100 - Load Mode Register FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
// Step 8 -------------------------------------------------------------------- /* Set the refresh rate counter */ /* (15.62 us x Freq) - 20 */ /* Set the device refresh counter */ FMC_SetRefreshCount ( 1385 );
// Wait until the SDRAM controller is ready timeout = SDRAM_TIMEOUT; while ( (FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0) ) { timeout--; } }
void initSdram (void) { FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure; FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
// Enable FMC clock RCC_AHB3PeriphClockCmd ( RCC_AHB3Periph_FMC, ENABLE );
SDRAM_GPIOConfig();
// FMC Configuration --------------------------------------------------------- // FMC SDRAM Bank configuration // Timing configuration for 90 Mhz of SD clock frequency (180Mhz/2) // TMRD: 2 Clock cycles FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2; // TXSR: min=70ns (7x11.11ns) FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7; // TRAS: min=42ns (4x11.11ns) max=120k (ns) FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4; // TRC: min=70 (7x11.11ns) FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7; // TWR: min=1+ 7ns (1+1x11.11ns) FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2; // TRP: 20ns => 2x11.11ns FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2; // TRCD: 20ns => 2x11.11ns FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
// ОТладка: SDTR = 0x01116361
// FMC SDRAM control configuration FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank2_SDRAM; // 0 // Col addressing: [8:0] - 9 bits FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_9b; // 0x00000001 // Row addressing: [12:0] - 13 bits FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_13b; // 0x00000008 FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b; // 0x00000010 FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4; // 0x00000040 // CL: Cas Latency = 3 clock cycles FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3; // 0x00000180 FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable; // 0x00000000 FMC_SDRAMInitStructure.FMC_SDClockPeriod = FMC_SDClock_Period_2; // 0x00000800 FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable; // 0x00001000 FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1; // 0x00002000 FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
// FMC SDRAM bank initialization // SDCR := 0x000039D9 - xx x011 1001 1101 1001 // RPIPE = 01; - one HCLK clock cycle delay // RBURST = 1; - single read requests are always managed as bursts // SDCLK = 10; - SDCLK period = 2 x HCLK periods // WP = 0; - write accesses allowed // CAS = 11; - CAS Latency - 3 cycles // NB = 1; - 4 internal Banks // MWID = 01; - memory data bus width - 16 bits // NR = 10; - number of row address bits - 13 bits // NC = 01; - number of column address bits - 9 bits FMC_SDRAMInit ( &FMC_SDRAMInitStructure );
SDRAM_InitSequence(); }
Проверяю работоспособность так: CODE #define SDRAM_ADR 0xD0000000
void sdramWriteTest(void) { u32 * p; p = SDRAM_ADR; printf("\tWriting to sdram\r\n"); for (u32 i = 0; i < 8000000; i++) p[i] = i; }
void sdramReadTest (void) { u32 * y; y = SDRAM_ADR; for (u32 i = 0; i < 8000000; i++) { if ( y[i] != i ) { printf("\t\tsomething wrong in sdram %d - %x \r\n", i, y[i]); break; } } printf("\tSdram test end\r\n"); }
При чтении уже на втором слове обнаруживается несовпадение между записанным и считанным.
|
|
|
|
|
Oct 20 2016, 11:45
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Начал проверять Вашу догадку, изменил код следующим образом: CODE #define SDRAM_ADR 0xD0000000 #define TEST_LEN 0x800000
void testSdram (void) { u32 * p; p = SDRAM_ADR; printf("\tWriting to sdram\r\n"); for (u32 i = 0; i < TEST_LEN; i++) p[i] = i; }
void testEnding (void) { u32 * y; y = SDRAM_ADR; for (u32 i = 0; i < TEST_LEN; i++) { if ( y[i] != i ) { printf("\t\twrong value on adr %d - %x \r\n", i, y[i]); } } printf("\tSdram test end\r\n"); }
То есть теперь тест не оставливается на первом несовпадении. В результате вижу следующее: Код Writing to sdram
Startint reading... wrong value on adr 2 - 61745309 wrong value on adr 3 - 20676e6f wrong value on adr 4 - 756c6176 wrong value on adr 5 - 6e6f2065 wrong value on adr 6 - 72646120 wrong value on adr 7 - 2d203620 wrong value on adr 8 - 32643220 wrong value on adr 9 - 32323334 wrong value on adr 10 - a0d2034 Sdram test end То есть значения не совпадают со второго по десятый адреса, далее все нормально. Что это может быть???
|
|
|
|
|
Oct 21 2016, 04:49
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Цитата(skripach @ Oct 20 2016, 19:28)  Схему подключения памяти покажите. На скорую руку выкинул из схемы все, что не касается SDRAM. Так много чего лишнего было, так что там нагромождено...
Цитата(x893 @ Oct 20 2016, 21:27)  Изменить код - так что бы понятно с первого взгляда. эээ... Ну может так понятнее: CODE
#define SDRAM_ADR 0xD0000000 #define TEST_LEN 0x800000
void writeToSdram (void) { u32 * p; p = SDRAM_ADR; /**< Присваиваю указателю адрес начала SDRAM */ printf("\tWriting to sdram\r\n", exampleStr); /** Пишу по этому указателю пишу четырехбайтными словами 0x800000 раз (то есть забиваю все 32 мегабайта) */ for (u32 i = 0; i < TEST_LEN; i++) p[i] = i; /**< Пишу значение счетчика итераций */ }
void readFromSdram (void) { u32 * y; y = SDRAM_ADR; /**< Присваиваю указателю адрес начала SDRAM */ for (u32 i = 0; i < TEST_LEN; i++) { /** Сравниваю значение в SDRAM со счетчиком итераций, так как при записи я записывал это самый счетчик. * Если значение не совпадает, значит по этому адресу не то значение, которое я записываю. * Данные об этих несовпадениях я вывожу в консоль */ if ( y[i] != i ) printf("\t\twrong value on adr %d - %x \r\n", i, y[i]); } printf("\tSdram test end\r\n"); }
int main (void) { initSdram(); /**< эта моя инииализация SDRAM, которую я показал в первом посте */ writeToSdram(); /**< Записываю в SDRAM */ readFromSdram(); /**< Читаю из SDRAM и сравниваю */
while (1) {}; }
Цитата(AVI-crak @ Oct 20 2016, 22:54)  Время рефлеша "1385" - ? это для какой тактовой? Здесь таковая не есть частота ядра, а лишь то что прилетает на сам чип памяти. Тактовая частота ядра 180MHz на SDRAM приходит 90 MHz. Я что-то не совсем понял, а как тогда рассчитать это значение?
|
|
|
|
|
Oct 21 2016, 05:07
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(yanvasiij @ Oct 21 2016, 11:49)  Тактовая частота ядра 180MHz на SDRAM приходит 90 MHz. Я что-то не совсем понял, а как тогда рассчитать это значение? Примерно так. Refresh rate = ( 64 ms ⁄ ( 8196rows ) ) * 90000000 = 702 Кстати, в случае когда настройка sdram начинает кочевать из проекта в проект - проще один раз написать макрос вычисления этого числа, и забыть о проблеме.
|
|
|
|
|
Oct 21 2016, 12:53
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Прикольно чип на части разбит, я-то монстров рисую в натуральную величину... Кстати, а это случайно не кеш барахлит? И ещё один вариант - полностью убрать хал: https://electronix.ru/forum/index.php?s=&am...t&p=1453129
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|