Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32H743. Тайминги FMC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
__inline__
Обнаружил интересную проблему и способ её решения.

Отладочная плата Nucleo-H743. Процессор STM32H743. Частота ядра 400 МГц. Частота шины FMC выставлена 200 МГц (максимум). Тактирование заведено от HCLK3.
На FMC висит дисплей с настроенными времянками. Инит дисплея проходит успешно, его ID производителя успешно определяется.
Далее в дисплей начинаю сыпать, сыпать, сыпать данные.... Через DMA. Только данные. Ножка A16 всегда =1 при этом.

Возникает проблема: дисплей перестаёт отображать данные. Либо он "зависает" (картинка не обновляется), либо он уходит в стэндбай - и весь экран становится белым.
При этом процессор и остальная периферия работают.
И с каждым сбросом CPU проблема повторяется.

Но стоило выбрать другой источник тактирования FMC - PLL1Q, а частоту тактирования FMC сделать в 2 раза ниже: 100 МГц, дисплей работает как часы и передача данных не срывается. Времянки при этом перерасчитаны (тоесть в масштабах времени они одинаковы, меняется число клоков) - использую Mode A - там только Address Setup и Data Setup.

Пробовал сильно укорачивать времянки - всёравно работает. Картинка не перекручивается - пиксели не пропускаются, и нужного цвета.
Но стоит поднять частоту FMC чуть выше 100 МГц, то проблема снова появляется, даже если времянки поставить очень длинные.

Я вот о чем подумал - в Mode A у FMC есть "хвостик" после Data Setup - его длина ВСЕГДА ФИКСИРОВАНА и равна 1 такту шины FMC. Картинка ниже.

Вопрос вот в чём, насколько существенна длительность этого "хвоста" для работы с периферией на FMC?

Ведь по сути нет никаких способов влиять программно на этот "хвост", кроме как занижать частоту FMC. А значит стабильную работу с данным LCD можно получить только, выставив минимально допустимую длину "хвоста", понизив частоту FMC и выставив остальные параметры времянок.

Пробовал другие дисплеи(модели другие!) подключать, таких проблем не было. Только один конкретный дисплей так ведёт себя.

В чем может быть ещё проблема? Дисплеи на "макаронах" до 10 см., это не критично для обмена на частоте данных 20-30 МГц.

Нажмите для просмотра прикрепленного файла
__inline__
Привожу времянки на проблемный дисплей. Из рисунка видно, что данные защёлкиваются по фронту сигнала !WR. И что важно после этого выдержать tAH=15ns, tDHW=15ns:

Нажмите для просмотра прикрепленного файла

А теперь в референс-мануале смотрим главу FMC и находим времянки. Времянка номер 1 - Mode A, цикл записи:

Нажмите для просмотра прикрепленного файла

И видим - всего 1 CLK FMC на tAH, tDHW ! crying.gif Что при тактовой FMC 200 MHZ даст всего 5 нс. Глянул времянки других дисплеев: у них tAH варьируется от 2 до 7 нс, поэтому с ними проблем не возникало (хотя работают на пределе своих возможностей).

В том же референс-мануале - другая времянка - Mode D, цикл записи:

Нажмите для просмотра прикрепленного файла

Тут зачем-то Address Hold задвинули перед DATA Setup, а должно быть ПОСЛЕ. Значит, тоже не годится.

Из всего резюмирую: для "длинно-хвостной" периферии для выдерживания tAH, tDHW прийдётся снижать тактовую частоту FMC - как единственный путь для получения tAH= 1 CLK FMC. Потому что другого способа не вижу как управлять длительностью холда.

Забавно, что после снижения тактовой FMC, резистор в 2 кОм на Chip Select дисплея можно исключить - вместе с ёмкостью вывода он создавал затянутый фронт до- и после- CS, тем самым внося задержку, которой так не хватало. О резисторе писал ранее здесь: https://electronix.ru/forum/index.php?showt...147646&st=0

Планирую попробовать подключить дисплей к NAND контроллеру. У него можно регулировать "хвост" после DATASETUP (HOLD):

Нажмите для просмотра прикрепленного файла

О результатах напишу.

А вообще конечно, STM-овцы облажались с FMC. biggrin.gif Даже на вшивых AVR-ках у XMEM была возможность регулировать tAH:

Нажмите для просмотра прикрепленного файла
__inline__
Успешно запустил контроллер NAND Flash и прикрутил к нему проблемный дисплей.
Получил ещё одно подтверждение того, что дисплей хочет длинный HOLD.

Частота FMC=200 МГц. 1 CLK = 5 нс.

Первым делом, настроил MPU, для отключения кеширования диапазона адресов: 0x80000000...0x8FFFFFFF (256 МБ). Позже объясню, зачем так много.
Код
static void MPU_Conf(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;

HAL_MPU_Disable();

MPU_InitStruct.Enable=MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = 0x80000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256MB; //0x80000000..0x8FFFFFFF

MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;

MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;

MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE; //NOT CACHEABLE
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_SHAREABLE;

MPU_InitStruct.Number=MPU_REGION_NUMBER0;
MPU_InitStruct.SubRegionDisable=0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}


Затем проинитил FMC , NAND. Здесь разные времянки для PMEM и PATT - использую первую для записи, вторую для чтения в регистры LCD (времянки на чтение всегда более длинные):
Код
static void MX_FMC_Init(void)
{
  FMC_NAND_PCC_TimingTypeDef ComSpaceTiming;
  FMC_NAND_PCC_TimingTypeDef AttSpaceTiming;

  /** Perform the NAND1 memory initialization sequence
  */
  hnand1.Instance = FMC_NAND_DEVICE;
  /* hnand1.Init */
  hnand1.Init.NandBank = FMC_NAND_BANK3;
  hnand1.Init.Waitfeature = FMC_NAND_WAIT_FEATURE_DISABLE;
  hnand1.Init.MemoryDataWidth = FMC_NAND_MEM_BUS_WIDTH_8;
  hnand1.Init.EccComputation = FMC_NAND_ECC_DISABLE;
  hnand1.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_256BYTE;
  hnand1.Init.TCLRSetupTime = 0;
  hnand1.Init.TARSetupTime = 0;
  /* hnand1.Config */
  hnand1.Config.PageSize      = 262144; //256kB >= 320x240x2
  hnand1.Config.SpareAreaSize = 262144; //256kB >= 320x240x2
  hnand1.Config.BlockSize = 1;
  hnand1.Config.BlockNbr = 1;
  hnand1.Config.PlaneNbr = 1;
  hnand1.Config.PlaneSize = 1;
  hnand1.Config.ExtraCommandEnable = ENABLE;

//Адреса для записи:
  /* ComSpaceTiming: 0x80000000..0x83FFFFFF */
  ComSpaceTiming.SetupTime     = 0; //+1 1CLK =  5ns             >=  4ns
  ComSpaceTiming.WaitSetupTime = 3; //+1 4CLK = 20ns             >= 18ns 1CLK уже мало
  ComSpaceTiming.HoldSetupTime = 3; //+0 3CLK = 15ns             >= 15ns 1CLK уже мало
  ComSpaceTiming.HiZSetupTime  = 1; //+0 1CLK =  5ns (tSET=tHIZ) >=  4ns 0CLK работает (0CLK: данные появятся сразу после падения NCE, 1CLK: после падения NWE, >1CLK: ещё позже)

//Адреса для чтения:
  /* AttSpaceTiming: 0x88000000..0x8BFFFFFF */
  AttSpaceTiming.SetupTime     = 254; //+1
  AttSpaceTiming.WaitSetupTime = 254; //+1
  AttSpaceTiming.HoldSetupTime = 254; //WR:+0 RD:+1
  AttSpaceTiming.HiZSetupTime  = 254; //+0

  if (HAL_NAND_Init(&hnand1, &ComSpaceTiming, &AttSpaceTiming) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}


Почитал референс-мануал на H743, внимательно расставил параметры времянок с учётом того, что к некоторым добавляется +1 CLK.

Код
  ComSpaceTiming.SetupTime     = 0; //+1 1CLK =  5ns             >=  4ns
  ComSpaceTiming.WaitSetupTime = 3; //+1 4CLK = 20ns             >= 18ns 1CLK уже мало
  ComSpaceTiming.HoldSetupTime = 3; //+0 3CLK = 15ns             >= 15ns 1CLK уже мало
  ComSpaceTiming.HiZSetupTime  = 1; //+0 1CLK =  5ns (tSET=tHIZ) >=  4ns 0CLK работает (0CLK: данные появятся сразу после падения NCE, 1CLK: после падения NWE, >1CLK: ещё позже)


Всё согласно времянкам проблемного дисплея:

Нажмите для просмотра прикрепленного файла

Уточнения:

1)
tHIZ выбрано равным tSETUP. Чтобы данные выкидывались на шину сразу же после падения строба записи NWE.
Можно сделать вообще tHIZ=0, тогда данные будут выдаваться сразу же после падения NCE - проверил: тоже работает!

2)
Если tWAIT меньше 2, то кадр в дисплее начинает перекручиваться и периодически переставлять байты цвета (идут пропуски байтов)

3)
Если tHOLD меньше 2, то дисплей повисает. Как раз тот случай, что с NOR/PSRAM контроллером - tHOLD там всегда 1 CLK !

4)
Если tWAIT=2 и tHOLD=2, то дисплей работает, но очень редко зависает (времянка не соответствует приведённой в даташите на LCD).

Код что выше, обеспечивает необходимую времянку. Дисплей проработал 1.5 часа без сбоя. Дальше не тестировал.

Порты для записи в LCD:
Код
#define LCD_WR_COM16 (*(volatile unsigned short int*) 0x80000000)
#define LCD_WR_DAT16 (*(volatile unsigned short int*) 0x80010000)


Для чтения:
Код
#define LCD_RD_COM16 (*(volatile unsigned short int*) 0x88000000)
#define LCD_RD_DAT16 (*(volatile unsigned short int*) 0x88010000)


Итоговая скорость записи в дисплей: 200MHz/(1+4+3)=25 MHz

Соединение дисплея с FMC:
Цитата
D0..D7 - LCD D0..D7
NWAIT - не используется
NOE - LCD !RD
NWE - LCD !WE
NCE - LCD !CS
A16 - CLE - LCD !RS
A17 - ALE - не используется
mantech
Цитата(__inline__ @ Jul 21 2018, 16:42) *
Отладочная плата Nucleo-H743. Процессор STM32H743. Частота ядра 400 МГц. Частота шины FMC выставлена 200 МГц (максимум). Тактирование заведено от HCLK3.
На FMC висит дисплей с настроенными времянками. Инит дисплея проходит успешно, его ID производителя успешно определяется.


Сорри за оффтоп, с оллвиннером уже наигрались, раз на стм перешли? Что не понравилось?
__inline__
Цитата(mantech @ Jul 23 2018, 11:18) *
Сорри за оффтоп, с оллвиннером уже наигрались, раз на стм перешли? Что не понравилось?

Олвиннер пока отложил временно, не успеваю. Но один момент успел не понравиться. Я раскопал это в Linux BSP. Работа с TCON в режиме i8080:
Код
s32 tcon0_cpu_wr_24b_data(u32 sel, u32 data)
{
    u32 count = 0;
    while((tcon0_cpu_busy(sel)) && (count < 50)) {
        count ++;
        disp_delay_us(100);
    }
    lcd_dev[sel]->tcon0_cpu_ctl.bits.ca = 1;        //tcon0_cpu_if_reg_t
    lcd_dev[sel]->tcon0_cpu_wr.bits.data_wr = data; //tcon0_cpu_wr_reg_t
    return 0;
}


Видите костыль? Вот он:
Цитата
u32 count = 0;
while((tcon0_cpu_busy(sel)) && (count < 50)) {
count ++;
disp_delay_us(100);


Меня как аппаратчика, разочаровывают эти строки.

Пока временно отложил. Ну и в связи с последними событиями - появление STM на 400 МГц занялся пока изучением Cortex-M7.
mantech
Цитата(__inline__ @ Jul 23 2018, 14:04) *
Пока временно отложил. Ну и в связи с последними событиями - появление STM на 400 МГц занялся пока изучением Cortex-M7.


Понятно, жаль, думал, может УСБшку вскладчину подняли бы, одному как-то тяжко с ней sad.gif

Меня б 400МГц тоже устроили бы, но СДРАМ и только внешняя - это уже прошлый век, для дисплейчиков 320х240 или чуть выше может оно и нормально, но для хороших разрешений совсем не айс laughing.gif

Цитата(__inline__ @ Jul 23 2018, 14:04) *
Но один момент успел не понравиться. Я раскопал это в Linux BSP. Работа с TCON в режиме i8080:


Дак это можно понять - этот режим у них очень опциональный и скорее всего никто его не использовал...
__inline__
Цитата(mantech @ Jul 23 2018, 12:31) *
Понятно, жаль, думал, может УСБшку вскладчину подняли бы, одному как-то тяжко с ней sad.gif

Скажу по секрету, с USB на микроконтроллерах никогда не работал. Только на компе и только через FT232/245. biggrin.gif

Цитата(mantech @ Jul 23 2018, 12:31) *
Меня б 400МГц тоже устроили бы, но СДРАМ и только внешняя - это уже прошлый век, для дисплейчиков 320х240 или чуть выше может оно и нормально, но для хороших разрешений совсем не айс laughing.gif

C v3s вопрос о памяти снимается автоматически - 64 biultin sm.gif А на отладках с A13 что есть там уже напаяна DDR. (Olinuxino и SOM)

Цитата(mantech @ Jul 23 2018, 12:31) *
Дак это можно понять - этот режим у них очень опциональный и скорее всего никто его не использовал...

На счёт дисплеев. Пересмотрел все даташиты все LCD, которые использовал и оказалось, что у них всех HOLD после DATA SETUP от 0 до 7 нс.
Становится понятным, почему ранее при подключении их к FMC проблем не было.

Попался дисплей с обалденно хорошим качеством картинки с SE K800i оригинал (контроллер Toshiba). Но у него HOLD от 15 нс, что нереализуемо на частотах FMC выше 66 Мгц.
Пришлось FMC в режим NAND загонять, чтобы выставить нужный HOLD без снижения тактовой частоты FMC (иначе остальные времянки прийдётся загрублять в большую сторону).

Но до того как это понял и докопаться до сути - понаставил костыли:

1) Резистор около 2 кОм на !CS
2) Постоянно посыл команды Write Data , перед отправкой фреймбуфера
3) Костыль в алгоритме инициализации

Теперь все костыли ушли в небытиё! Дисплей стабильно работает и рисует непрерывно кадр через DMA бе опорных команд (позиция по X,Y; write data) и ничего не съезжает.
FMC в режиме NAND рулит! rolleyes.gif

Правда, на смежном форуме меня пытались убедить, что через NAND мол, можно к дисплею обращаться как к массиву. Но в STM32 адрес NAND Flash задаётся через запись в регистр, также как и данные. Так что смещения относительно базового адреса NAND не вышло. А было бы очень изящно: все регистры дисплея - элементы массива(или структуры), вместо раздельных посылок: адреса и данных.
AVI-crak
Цитата(__inline__ @ Jul 23 2018, 20:12) *
Правда, на смежном форуме меня пытались убедить, что через NAND мол, можно к дисплею обращаться как к массиву.

Я и здесь могу это повторить - можно и нужно. Более того - код будет более простым и нативным по сравнению с явным указанием адреса команд и данных.
Обращаться к области памяти как к массиву, да почти так. Без адреса, через имя структуры, и линейно от начала до конца окна. Дело в том что у всех дисплеев счётчик адреса данных щёлкает автоматически с каждым чтением/записи данных. А для новых дисплеев это свойство распространяется на всю периферию (наверное забыли отключить).
__inline__
Цитата(AVI-crak @ Jul 23 2018, 17:16) *
Я и здесь могу это повторить - можно и нужно. Более того - код будет более простым и нативным по сравнению с явным указанием адреса команд и данных.
Обращаться к области памяти как к массиву, да почти так. Без адреса, через имя структуры, и линейно от начала до конца окна. Дело в том что у всех дисплеев счётчик адреса данных щёлкает автоматически с каждым чтением/записи данных. А для новых дисплеев это свойство распространяется на всю периферию (наверное забыли отключить).


Ой, да ладно! rolleyes.gif biggrin.gif Мечтать оно не вредно, но реалии намного скромнее.

В HAL идёт обращение к NAND как к регистрам: выставляем байты адреса(Addr section), байт команды(Cmd section), затем только читем/пишем(Data section).
Нет тут обращения как к массиву даже и близко:
Код
HAL_NAND_Read_Page_8b(...)
{
//........

//Записывается адрес в несколько байт
        *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = 0x00; __DSB();
        *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandAddress);    __DSB();
        *(__IO uint8_t *)((uint32_t)(deviceAddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandAddress);  __DSB();

//далее ждем.......

//Read Page CMD
      *(__IO uint8_t *)((uint32_t)(deviceAddress | CMD_AREA)) = ((uint8_t)0x00U);      __DSB();

//Читаем данные
for(; index < size; index++)
    {
      *(uint8_t *)pBuffer++ = *(uint8_t *)deviceAddress;
    }

//..............
}


У меня делается обращение к дисплею всего 2 записями (CMD_AREA - это A16. =0 - регистр, =1 - данные.):

Код
*(__IO uint16_t *)((uint32_t)(deviceAddress )) = ((uint16_t)LCD_REGISTER_N);
*(__IO uint16_t *)((uint32_t)(deviceAddress| CMD_AREA )) = ((uint16_t)LCD_DATA);


Принцип тот же.

А вы предлагаете сделать так (полагая, что если записать смещение в адрес, то оно упадёт на шину):

Код
*(__IO uint16_t *)((uint32_t)(deviceAddress | ADDR_AREA | LCD_REGISTER_N)) = ((uint16_t)LCD_DATA);


Но этого не будет. Потому что либо товарищ AVI-crak никогда не работал с FMC в режиме NAND, либо он - циничный тролль и издевается надо мной.

В мануале на H743 чётко прописан алгоритм взаимодействия FMC c NAND-flash. Что адрес выставляется записью значения в регистр, а не идёт в смещение относительно базы:

Нажмите для просмотра прикрепленного файла

AVI-crak, Вы бы Бога побоялись что-ли... Ну нельзя ж так издеваться! 05.gif

И перестаньте вводить в заблуждение! wink.gif
__inline__
Оказывается, эта проблема существует уже много лет : https://community.st.com/s/question/0D50X00...-of-stm32f407ig
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.