Перейти к содержанию

    

STM32F745 FMC + LCD 16-bit i8080 mode

Условия:

Плата с 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);
}

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Условия:

Плата с STM32F745VET (100 pin)

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

 

Проблема:

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

 

Анализ:

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

 

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

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

 

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

 

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

HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);

 

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

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Изменено пользователем AlanDrakes

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо про ремапинг. Но вот и еще один вариант :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

:)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Вот и вопрос к 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)));

:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
А вот в AT91RM9200 был полноценный MMU - с поддержкой виртуальных адресов. А в STM32H7 нет, и это меня огорчает.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Если бы у бабушки был @#$, то она была бы дедушкой © наше всё

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

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

 

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

Поделиться сообщением


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

Почему?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Почему?

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 - нет. Почему?

Изменено пользователем __inline__

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация