Jump to content

    
Sign in to follow this  
kostya-m

STM32F745 FMC + LCD 16-bit i8080 mode

Recommended Posts

Условия:

Плата с STM32F745VET (100 pin)

Схема спроектирована с помощью CubeMX и им же сделан базовый код.

 

Проблема:

Не работает дисплей

 

Анализ:

Исследования с помощью многоканального осциллоскопа показало белиберду в управляющих сигналах.

 

Безуспешные попытки:

Пробовал изменять режимы работы FMC, тайминги, настройки. Ничего принципиально не помогает. Если код исполнять пошагово, то работает, если непрерывно - не работает. Промежуточным решением оказалось вставить после каждого обращения к LCD задержку на 400-500 нс. Но скорость записи сильно страдает.

 

Решение:

Похоже, в FMC, в отличие от FSMC есть логика кеширования. Запись в дисплей ведется по двум адресам ((__IO uint16_t*)0x60000000) и ((__IO uint16_t*)0x60020000). Данные потоком пишутся по второму адресу и FMC начинает пропускать циклы записи, оставляя последний. Отключение FIFO не помогает. Решением оказалось инкрементирование адреса в рамках до A16, которым проводится разделение команда-данные.

 void LCD_CMD( uint16_t cmd ) 
{
  static volatile uint16_t *Cmd = ((__IO uint16_t*)0x60000000);
  *(Cmd++) = cmd;
  if( Cmd >= ((__IO uint16_t*)0x6000FFF) ) Cmd = ((__IO uint16_t*)0x60000000);
}
void LCD_DATA( uint16_t data ) 
{
  static volatile uint16_t *Data = ((__IO uint16_t*)0x60020000);
  *(Data++) = data;
  if( Data >= ((__IO uint16_t*)0x6002FFFF)) Data = ((__IO uint16_t*)0x60020000);
}

Так все заработало

Share this post


Link to post
Share on other sites
Условия:

Плата с STM32F745VET (100 pin)

Схема спроектирована с помощью CubeMX и им же сделан базовый код.

 

Проблема:

Не работает дисплей

 

Анализ:

Исследования с помощью многоканального осциллоскопа показало белиберду в управляющих сигналах.

 

Безуспешные попытки:

Пробовал изменять режимы работы FMC, тайминги, настройки. Ничего принципиально не помогает. Если код исполнять пошагово, то работает, если непрерывно - не работает. Промежуточным решением оказалось вставить после каждого обращения к LCD задержку на 400-500 нс. Но скорость записи сильно страдает.

 

Всё прям как у меня :)

 

После инита FMC сделать:

HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);

 

и обращаться к дисплею по адресам 0xC0000000 и 0xC0020000.

 

 

 

Share this post


Link to post
Share on other sites

О, снова знакомая тема вылезла.

Где-то ранее я уже с этми же бился и даже победил.

 

И ровно та же ситуация. Ремаппинг памяти и ВСЕ проблемы сразу же ушли.

Edited by AlanDrakes

Share this post


Link to post
Share on other sites

Вот и вопрос к STM, почему бы в очередной редакции мануала не давать контекстно ссылки на пункты errata и appnotes-заплаты.

Хотя их консультанты, очевидно, получают премии за кол-во запросов-ответов по e-mail.

:)

 

Share this post


Link to post
Share on other sites
Вот и вопрос к STM, почему бы в очередной редакции мануала не давать контекстно ссылки на пункты errata и appnotes-заплаты.

Хотя их консультанты, очевидно, получают премии за кол-во запросов-ответов по e-mail.

:)

 

Сейчас набегут гуру ядра ARM-а и закидают шапками, что мол надо спецификации на Cortex-M7 ядро почитать, так как эта фишка (разграничение регионов адресов на "Device" и "Memory") заложена в самом ядре и К ЭТОМУ НАДО БЫЛО УЖЕ БЫТЬ ГОТОВЫМ! Так что это не глюк, а просто дефолтная установка.

 

Попробую MPU настроить чтобы всё-же классический адрес 0x60000000 работал как "Device" (отключить кеширование этой области, возможно отключить буферизацию и включить shareable).

 

А вот в AT91RM9200 был полноценный MMU - с поддержкой виртуальных адресов. А в STM32H7 нет, и это меня огорчает. Свершилась бы мечта идиота программиста - фрагментированную на куски SRAM сделать одним непрерывным большим массивом данных :) А так прийдётся писать нечто вроде:

 

u16 VideoBuffer[n] __attribute__((at(0x20000000)));
u8 SoundBuffer[n] __attribute__((at(0x24000000)));

:)

Share this post


Link to post
Share on other sites
А вот в AT91RM9200 был полноценный MMU - с поддержкой виртуальных адресов. А в STM32H7 нет, и это меня огорчает.

Если бы у бабушки был @#$, то она была бы дедушкой © наше всё

Может в M8 и станет, а? :rolleyes:

Share this post


Link to post
Share on other sites
Если бы у бабушки был @#$, то она была бы дедушкой © наше всё

Может в M8 и станет, а? :rolleyes:

А я и не жду :) ждать - это вообще очень дорогое для меня удовольствие... Потому что время. Поэтому стараемся использовать всё что есть и выкручиваться.

 

А вот в -A7, -A8 лучше не лезть. Пускай они для линуксоидов, андроидов, питонов и прочей нечисти:)

Share this post


Link to post
Share on other sites
Почему?

1) нет внятных доков по его программированию. Хотя бы на уровне reference manual-ов как у STM

 

2) нет практических примеров использования (на уровне микроконтроллеров)

 

3) Application-ориентирование, а не Microcontroller. Это значит - Only for Linux, Only for Android, under Linux, Under Android.

 

4) Слишком сложное внутреннее устройство (без 1) -реверс черного ящика). В Linux BSP освещены не все моменты. Хотя бы банально - работы с TCON0 через i8080 bus я не нашёл. В частности, как расставлять времянки по сигналам D, A, CS, WR, RD, WAIT.

 

Попробую MPU настроить чтобы всё-же классический адрес 0x60000000 работал как "Device" (отключить кеширование этой области, возможно отключить буферизацию и включить shareable).

 

Всё мощно! :rolleyes:

 

Получилось работать с FMC + LCD и через адреса с 0x60000000. С помощью MPU запрещаем кеширование данного адресного региона и работаем:

static void MPU_Conf(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
HAL_MPU_Disable();
MPU_InitStruct.Enable=MPU_REGION_ENABLE;

MPU_InitStruct.BaseAddress = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256KB; //256KB если линия A16 и 16-битная шина данных. 128KB если линия A16 и 8-битная шина данных

MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;

MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
MPU_InitStruct.IsCacheable=MPU_ACCESS_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_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

int main(void)
{
MPU_Conf();

SCB_EnableICache();
SCB_EnableDCache();

HAL_Init();
..................

 

Убрать HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM); , если оно было.

И использовать:

#define LCD_COM16 (*(volatile unsigned short int*) 0x60000000)
#define LCD_DAT16 (*(volatile unsigned short int*) 0x60020000)

 

У меня работает через DMA и через CPU.

 

Единственно, остался невыясненным момент в этих вещах:

 MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_SHAREABLE;

 

Какие бы не ставил значения - все 4 комбинации работают. И прироста/замедления в скорости не заметил.

Играют ли они роль в контексте LCD по FMC или нет?

 

Ещё по DMA бурстам вопрос.

hdma_memtomem_dma1_stream0.Init.MemBurst = DMA_MBURST_SINGLE; //DMA_MBURST_INC4;

hdma_memtomem_dma1_stream0.Init.PeriphBurst = DMA_PBURST_SINGLE; //DMA_PBURST_INC4;

 

SINGLE и INC4 работает DMA + FMC LCD. С бурстами INC8, INC16 - нет. Почему?

Edited by __inline__

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this