|
HardFault при записи/чтении в SDRAM на Core429i, программа при записи/чтении в SDRAM на Core429i вылетает в HardFault |
|
|
|
Oct 1 2016, 13:31
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Пытаюсь запустить SDRAM на Core429i в TrueStudio с помощью CubeMX. Цепи FMC настроил согласно схеме, но программа при записи/чтении в SDRAM вылетает в HardFault. Уже и PD6 подтянул к питанию... Ничего не помогает... Прерываний, ОСРВ и т.п. вещей, который могли бы влиять на роботу с SDRAM, нет. Код Код: if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) { Error_Handler(); } - выполняется без входа в Error_Handler. Ревизия МК - 3, т.е. проблем с FMC быть не должно. Может в кубе (прикрепляю файл проекта) что-то не так указал? Что еще можно проверить?
Сообщение отредактировал IgorKossak - Oct 1 2016, 17:30
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Oct 1 2016, 15:55
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(amiller @ Oct 1 2016, 18:17)  . Судя по коду, который генерирует куб, он все это делает. Кроме тестирования чтения/записи, которое пытаюсь выполнить я.
Сообщение отредактировал IgorKossak - Oct 1 2016, 17:32
Причина редактирования: бездумное цитирование
|
|
|
|
|
Oct 1 2016, 16:38
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(x893 @ Oct 1 2016, 19:06)  Наверно придется использовать их (хотя код куба сравнивал как раз с этими примерами - не один в один, но очень похоже получается...). Я думал, что куб позволит быстро проверить работоспособность озушки, т.к. прикручивать примеры у меня не быстро получается... Очень похоже, что при настройке FMC для SDRAM я что-то упустил, т.к. отдельно SDIO (+fatfs), FMC для LCD работают без проблем. В прикрепленном проекте (в первом сообщении) только FMC для SDRAM, т.е. ничего на него влиять не должно.
Сообщение отредактировал IgorKossak - Oct 1 2016, 17:32
Причина редактирования: бездумное цитирование
|
|
|
|
|
Oct 1 2016, 18:49
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(scifi @ Oct 1 2016, 20:58)  Зачем сразу так? Куб - он же как раз для того, чтобы талмуд не листать. А если сразу не срослось - что ж, бывает... Поддерживаю. Кто-нибудь смотрел файл проекта куба, прикрепленный к первому сообщению? Предполагаю, что именно там какая-то мелочь не дает работать с sdram...
|
|
|
|
|
Oct 1 2016, 19:23
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(x893 @ Oct 1 2016, 21:59)  Никак не могу заставить разбираться в килотоннах букв. Всегда проще пройти отладчиком и не заставлять людей мучиться. К тому же (в случае с Cube) правильнее публиковать ioc файл, а не килостроки им сгенерированные. Именно ioc и прикреплен, т.е. только один файл (я, наверно, некорректно его назвал в предыдущих сообщениях). Отладчиком, естественно проходился - в hardfault стабильно входит на операции чтения/записи.
|
|
|
|
|
Oct 1 2016, 20:41
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(Sharf @ Oct 1 2016, 20:31)  Что еще можно проверить? Например адреса чтения/записи - у вас кстати второй банк 0xD0000000 ++. Соответствие выставленных таймингов с тактовой и временем из доки на память. В доке большая часть параметров привязана к времени а не к тактовой. А у вас тактовая памяти получается 80мгц !!! - ниже некуда. Первый PLL не может корректно умножать пограничные частоты в 1мгц и в 2мгц - середина умножается корректно и гладко, 1,5мгц - идеально. Кубик игнорирует установку подтяжки на используемые ноги, а делать это ручным способом весьма утомительно. Дата в землю, адрес без подтяжки, управление: sdclk, nbl0, nbl1 - в землю, - остальное в плюс. После чего становится доступным спящий режим. Забыл: ноги нужно лочить, чтоб не слетали при дальнейшем неаккуратном инсталле. Ну и наверное главное, хотя уже упомянули создание раздела в линковщике - забыли напомнить про копирование инициализированных переменных из флеша. Сделать эту операцию корректно из С кода - весьма проблематично. А в случае применения хала - практически не реально. Так-шта в выигрыше старый добрый SystemInit запускаемый до копирования в sdram кучи переменных, с таким расчётом чтоб майн запустить на всём готовом.
Сообщение отредактировал AVI-crak - Oct 1 2016, 20:47
|
|
|
|
|
Oct 2 2016, 09:59
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(AVI-crak @ Oct 1 2016, 23:41)  Например адреса чтения/записи - у вас кстати второй банк 0xD0000000 ++. Соответствие выставленных таймингов с тактовой и временем из доки на память. В доке большая часть параметров привязана к времени а не к тактовой. А у вас тактовая памяти получается 80мгц !!! - ниже некуда. Первый PLL не может корректно умножать пограничные частоты в 1мгц и в 2мгц - середина умножается корректно и гладко, 1,5мгц - идеально. Кубик игнорирует установку подтяжки на используемые ноги, а делать это ручным способом весьма утомительно. Дата в землю, адрес без подтяжки, управление: sdclk, nbl0, nbl1 - в землю, - остальное в плюс. После чего становится доступным спящий режим. Забыл: ноги нужно лочить, чтоб не слетали при дальнейшем неаккуратном инсталле.
Ну и наверное главное, хотя уже упомянули создание раздела в линковщике - забыли напомнить про копирование инициализированных переменных из флеша. Сделать эту операцию корректно из С кода - весьма проблематично. А в случае применения хала - практически не реально. Так-шта в выигрыше старый добрый SystemInit запускаемый до копирования в sdram кучи переменных, с таким расчётом чтоб майн запустить на всём готовом. //Например адреса чтения/записи - у вас кстати второй банк 0xD0000000 ++. да, именно такой адрес у SDRAM_BASE. Уходит в hardfault внутри: status = HAL_SDRAM_Read_16b(&hsdram1, (uint32_t*)SDRAM_BASE, buf, SDRAM_SIZE); на строчке *pDstBuffer = *(__IO uint16_t *)pSdramAddress; дизассемблер: ldrh.w r4, [r1], #2 при этом pDstBuffer = 0x2002fff0 (т.е. буфер из внутреннего ОЗУ МК), pSdramAddress = 0xd0000000 SDRAM_SIZE = 4 (чисто для проверки) //Соответствие выставленных таймингов с тактовой и временем из доки на память - это еще смотрю //Дата в землю, адрес без подтяжки, управление: sdclk, nbl0, nbl1 - в землю, - остальное в плюс. После чего становится доступным спящий режим. сделал, не помогает //Забыл: ноги нужно лочить, чтоб не слетали при дальнейшем неаккуратном инсталле. - это есть в ioc //Ну и наверное главное, хотя уже упомянули создание раздела в линковщике - забыли напомнить про копирование инициализированных переменных из флеша. //Сделать эту операцию корректно из С кода - весьма проблематично. А в случае применения хала - практически не реально. //Так-шта в выигрыше старый добрый SystemInit запускаемый до копирования в sdram кучи переменных, с таким расчётом чтоб майн запустить на всём готовом. Можно тут подробнее? Пока во внешнем ОЗУ я ничего не храню и не планирую хранить.
|
|
|
|
|
Oct 3 2016, 00:21
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Код инстала для stm32f439, с небольшими исправлениями кочует из проекта в проект. CODE ///Install SDRAM stm32f439 FMC_Bank5_6 -> SDCR[0] = FMC_SDCR1_NC_9bits |FMC_SDCR1_NR_13bits |FMC_SDCR1_MWID_16bits |FMC_SDCR1_NB_4banks |FMC_SDCR1_CAS_2cycle //|FMC_SDCR1_SDCLK_3x |FMC_SDCR1_SDCLK_2x |FMC_SDCR2_RBURST |FMC_SDCR1_WP |FMC_SDCR1_RPIPE_1delay; //FMC_SDCR1_RPIPE_1delay FMC_SDCR1_RPIPE_3delay
FMC_Bank5_6->SDTR[0] = (0x00000001) /// TMRD время между записью в MODE-REGISTER и ACTIVATE/1 /2 |(0x00000005 << 4) /// TXSR время между SELF-REFRESHING и ACTIVATE (exit self-refresh mode)/5 /7 |(0x00000002 << 8) /// TRAS минимальное время между SELF-REFRESH/2 /4 |(0x00000006 << 12) /// TRC время между двумя командами REFRESH/5 /7 |(0x00000003 << 16) /// TWR задержка между командой WRITE и вызовом PRECHARGE/1 /2 |(0x00000001 << 20) /// TRP время между командой PRECHARGE и любой другой командой/1 /1 |(0x00000002 << 24); /// TRCD время между подачей команды ACTIVATE и появлением данных на шинеС/1 /2 ///TWR >= TRAS - TRCD and TWR >= TRC - TRCD - TRP FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB1 | FMC_SDCMR_MODE_Config_Enable; tmp = FMC_Bank5_6->SDSR & 0x00000020; timeout = 0xFFFF; while((tmp != 0) && (timeout-- > 0)) { tmp = FMC_Bank5_6->SDSR & 0x00000020; }
delay(10000); /// PALL command FMC_Bank5_6->SDCMR = FMC_SDCMR_CTB1 | FMC_SDCMR_MODE_PALL; timeout = 0xFFFF; tmp = 10; while((tmp != 0) && (timeout-- > 0)) { tmp = FMC_Bank5_6->SDSR & 0x00000020; } /// Auto refresh command FMC_Bank5_6->SDCMR = (0x00000003 << 5) | FMC_SDCMR_CTB1 | FMC_SDCMR_MODE_Self_refresh; /// Количество рефлеш минимум 2 timeout = 0xFFFF; tmp = 10; while((tmp != 0) && (timeout-- > 0)) { tmp = FMC_Bank5_6->SDSR & 0x00000020; } // MRD register program tmp = (((((HSE_gz / (((RCC->PLLCFGR)<<26)>>26))*(((RCC->PLLCFGR)<<17)>>23))/(((((RCC->PLLCFGR)<<14)>>30)<<1)+2))/2000)*64)/8192; FMC_Bank5_6->SDCMR = (tmp << 9) | FMC_SDCMR_CTB1 | FMC_SDCMR_MODE_Load_Mode; /// 64mc/(размер блока Row Addresses(8192)) * (тактовая частота чипа) timeout = 0xFFFF; tmp = 10; while((tmp != 0) && (timeout-- > 0)) { tmp = FMC_Bank5_6->SDSR & 0x00000020; } tmp = (((((((HSE_gz / (((RCC->PLLCFGR)<<26)>>26))*(((RCC->PLLCFGR)<<17)>>23))/(((((RCC->PLLCFGR)<<14)>>30)<<1)+2))/2000)*64)/8192)<<1) | FMC_Bank5_6->SDRTR; FMC_Bank5_6->SDRTR = (tmp | (0x000002C5<<1)) | 1<<14; // время регена + вкл регена /// Refresh rate = (COUNT) * SDRAM clock frequency /// SDRAM refresh period = 64 mc /// COUNT = (SDRAM refresh period / Number of rows ) /// Refresh rate = 0.064 / (8192rows + 4) ) * 84000000 , ~ 656 ( 0x290 )
FMC_Bank5_6->SDCR[0] &= (~FMC_SDCR1_WP);// снятие защиты от записи // timeout =0; for(tmp = 0xc0000000; tmp < 0xC1FFFFFC; tmp += 4) ///32Mb 0.873 ms { *((volatile uint32_t *)tmp) = 0x00000000;// timeout; } Для файла линкера нечто подобное (у меня иначе, возможны ошибки) CODE MEMORY { ROM (rx) : ORIGIN = 0x08000000, LENGTH = 2048K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K SRAM (rwx) : ORIGIN = 0xD0000000, LENGTH = 64K CCRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K SDRAM (rwx) : ORIGIN = 0xC0000000, LENGTH = 16384K BKRAM (rw) : ORIGIN = 0x40024000, LENGTH = 4K }
-------------- /* размещение констант в SDRAM */ _sicsdram = LOADADDR(.csdram); .csdram : { . = ALIGN(4); _scsdram = .; /* глобальный символ начала SDRAM */ *(.csdram) *(.csdram*) . = ALIGN(4); _ecsdram = .; /* глобальный символ конца SDRAM */ } > SDRAM AT> FLASH
--------------- *.s файл
bl SystemInit
ldr r0, =_scsdram ldr r1, =_sicsdram ldr r2, =_ecsdram LoopCopySdram: cmp r0, r2 ittt ne ldrne r3, [r1], #4 strne r3, [r0], #4 bne LoopCopySdram bl main ---------
макрос #define SDram __attribute__((section(".csdram"))) ---------- глобальные переменные SDram const uint16_t Font[размер] ={дата}; Таким образом можно объявить функции и даже часть данных что не могут физически уместиться во внутреннюю флеш чипа. В этом случае из асмы *.s вызывается функция чтения внешней флешки, например 25q64, и есно запись в sdram. Сделать это необходимо до входа в майн. Естественно размещение дампа на внешней памяти - отдельный разговор, он станет актуальным после получения бинарного файла прошивки размером за 2 гигабайта. Исправляется ситуация весьма оригинально, но это потом.
Сообщение отредактировал IgorKossak - Oct 3 2016, 07:31
Причина редактирования: [codebox] для длинного кода. [code]-для короткого!!!
|
|
|
|
|
Oct 5 2016, 07:48
|
Участник

Группа: Участник
Сообщений: 67
Регистрация: 25-01-06
Пользователь №: 13 571

|
Цитата(AVI-crak @ Oct 3 2016, 03:21)  Код инстала для stm32f439, с небольшими исправлениями кочует из проекта в проект.
...
Таким образом можно объявить функции и даже часть данных что не могут физически уместиться во внутреннюю флеш чипа. В этом случае из асмы *.s вызывается функция чтения внешней флешки, например 25q64, и есно запись в sdram. Сделать это необходимо до входа в майн. Естественно размещение дампа на внешней памяти - отдельный разговор, он станет актуальным после получения бинарного файла прошивки размером за 2 гигабайта. Исправляется ситуация весьма оригинально, но это потом. Спасибо большое за информацию! Проблема решилась - была ошибка при инициализации памяти (банальность - при копипасте тактирование не включилось  ) Не подскажете, для чего waveshare два раза посылает одну и ту же команду: Код /* Wait until the SDRAM controller is ready */ while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET) { } /* Send the first command */ FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); /* Wait until the SDRAM controller is ready */ while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET) { } /* Send the second command */ FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure); Также Вы писали: А у вас тактовая памяти получается 80мгц !!! - ниже некуда. Почему ниже некуда? В описании на SDRAM ограничения максимальные частоты/тайминги указаны. Т.е. теоретически можно работать и на более низких частотах
Сообщение отредактировал IgorKossak - Oct 5 2016, 07:49
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|