реклама на сайте
подробности

 
 
> HardFault при записи/чтении в SDRAM на Core429i, программа при записи/чтении в SDRAM на Core429i вылетает в HardFault
Sharf
сообщение Oct 1 2016, 13:31
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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] - для короткого!

Прикрепленные файлы
Прикрепленный файл  Core429i.zip ( 3.55 килобайт ) Кол-во скачиваний: 21
 
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AVI-crak
сообщение Oct 1 2016, 20:41
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Sharf
сообщение Oct 2 2016, 09:59
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 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 кучи переменных, с таким расчётом чтоб майн запустить на всём готовом.

Можно тут подробнее? Пока во внешнем ОЗУ я ничего не храню и не планирую хранить.

Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Oct 3 2016, 00:21
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 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]-для короткого!!!
Go to the top of the page
 
+Quote Post
Sharf
сообщение Oct 5 2016, 07:48
Сообщение #5


Участник
*

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



Цитата(AVI-crak @ Oct 3 2016, 03:21) *
Код инстала для stm32f439, с небольшими исправлениями кочует из проекта в проект.

...

Таким образом можно объявить функции и даже часть данных что не могут физически уместиться во внутреннюю флеш чипа. В этом случае из асмы *.s вызывается функция чтения внешней флешки, например 25q64, и есно запись в sdram. Сделать это необходимо до входа в майн.
Естественно размещение дампа на внешней памяти - отдельный разговор, он станет актуальным после получения бинарного файла прошивки размером за 2 гигабайта.
Исправляется ситуация весьма оригинально, но это потом.


Спасибо большое за информацию! Проблема решилась - была ошибка при инициализации памяти (банальность - при копипасте тактирование не включилось sm.gif )

Не подскажете, для чего 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
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Oct 5 2016, 13:59
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894



SDRAM необходимо регенерировать каждые 64мс независимо от частоты клока. Выше частота - быстрее получается регенерация, остаётся больше времени на рабочее состояние.

Зачем в конструкциях хала одинаково повторяющиеся команды? а фиг его знает. После десятого рекурсивного дифлайна на хале - у меня теряется терпение. Да и зачем, если с прямым обращением в регистры - код получается намного проще и понятнее.
Go to the top of the page
 
+Quote Post
Sharf
сообщение Oct 6 2016, 17:43
Сообщение #7


Участник
*

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



Цитата(AVI-crak @ Oct 5 2016, 16:59) *
SDRAM необходимо регенерировать каждые 64мс независимо от частоты клока. Выше частота - быстрее получается регенерация, остаётся больше времени на рабочее состояние.

Зачем в конструкциях хала одинаково повторяющиеся команды? а фиг его знает. После десятого рекурсивного дифлайна на хале - у меня теряется терпение. Да и зачем, если с прямым обращением в регистры - код получается намного проще и понятнее.


Спасибо большое за всю Вашу информацию! Она была очень полезна!
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Sharf   HardFault при записи/чтении в SDRAM на Core429i   Oct 1 2016, 13:31
- - amiller   1. Прочитать документацию на семейство контроллеро...   Oct 1 2016, 15:17
|- - Sharf   Цитата(amiller @ Oct 1 2016, 18:17) . Су...   Oct 1 2016, 15:55
|- - jcxz   Цитата(Sharf @ Oct 1 2016, 21:55) Судя по...   Oct 1 2016, 16:53
|- - scifi   Цитата(jcxz @ Oct 1 2016, 19:53) Он и док...   Oct 1 2016, 17:58
|- - Sharf   Цитата(scifi @ Oct 1 2016, 20:58) Зачем с...   Oct 1 2016, 18:49
- - x893   И даже примеры от waveshare не работают ? http://...   Oct 1 2016, 16:06
|- - Sharf   Цитата(x893 @ Oct 1 2016, 19:06) Наверн...   Oct 1 2016, 16:38
- - x893   Никак не могу заставить разбираться в килотоннах б...   Oct 1 2016, 18:59
|- - Sharf   Цитата(x893 @ Oct 1 2016, 21:59) Никак не...   Oct 1 2016, 19:23


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01424 секунд с 7
ELECTRONIX ©2004-2016