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

FSMC: можно ли (и как) обойти ограничение

Сходу не вспомню, как сделать максимально устойчивую конфигурацию. Сам пользовался FSMC лет пять назад, приходилось разрисовывать всё на бумажке, чтобы состыковать даташит от ST с даташитом производителя RAM. С тех пор забылось всё...

 

Дурацкий вопрос, кстати: вы проверяли (методом записи и последующего чтения) как именно данные портятся? Всегда одинаково?

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


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

4 часа назад, mihlit1 сказал:

У меня вопрос может к FSMC нельзя подключать 16-битную память и 8-битный дисплей? RM0090 молчит по этому поводу (или я невнимательно смотрел).

Как вы себе это представляете? Например, нужно записать 32х битное число, оно контроллером разбивается на 2 16и битных и пишется в память. Потом вы его же пишете в дисплей, контроллер что должен делать, он "думает", что дисплей тоже 16и битный, правда? А на самом деле как? Куда он будет закидывать то, что должен поместить в битах 8-15? Может, конечно, там можно делать ШД разной ширины для разных регионов адресов, но что-то я сомневаюсь в этом...

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

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


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

//-----------------------
uint16_t sram_read(uint32_t addr)
{
    uint32_t ret_wert = 0;
    __IO uint32_t address = 0;
    address = SRAM_ADR + (addr*2);
    // Read 16-bits data from the memory
    ret_wert = *(uint32_t*) address;

    return ret_wert >> 16;
}
//-----------------------
void sram_write(uint32_t addr, uint16_t wert)
{
    __IO uint32_t address = 0;
    address = SRAM_ADR + (addr*2);
    *(uint16_t *) address = wert;
}
//-----------------------

Это чтение/запись в RAM. Код с просторов тырнета.

Запись в память цвета RED (0xF800). Мой код:

	for(i=0; i<FULL; i++)
	{
		sram_write(i,RED);
	}
	TFT_SetAdrWindow(0,0,479,319);
	Write_Com(0x2C);

	for(i=0; i<FULL; i++)
	{
		buf = sram_read(i);
		Write_Dat(buf & 0xFF);
		Write_Dat(buf > 8);
	}

Читается16-битное слово, побайтно отправляетя в дисплей. Уже в памяти вместо  0xF800 вижу 0xF83А. 

1 час назад, esaulenka сказал:

как именно данные портятся? Всегда одинаково?

Да мл. байт вместо 00 всегда 3F. Смотрю память в Кейле 5.23.

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


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

15 minutes ago, mihlit1 said:

вместо  0xF800 вижу 0xF83А

 

16 minutes ago, mihlit1 said:

вместо 00 всегда 3F

Показания расходятся.

 

 

Такое подозрение, что дисплей не отпускает шину. Было б неплохо узнать, что именно за дисплей.

Например, у ILI9481 есть chip select, и когда к нему нет обращений, этот чипселект должен быть в единице.

 

1 hour ago, mantech said:

он "думает", что дисплей тоже 16и битный, правда?

Неправда. Он думает ровно то, что настроено в соответствующем банке памяти.

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


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

37 минут назад, esaulenka сказал:

вижу 0xF83А

переключался между раскдадками, ошибся, конечно 3F.

 

37 минут назад, esaulenka сказал:

Он думает ровно то, что настроено в соответствующем банке памяти.

// board STM32F407ZET6	
void SRAM_Config(void)
{
	FSMC_NORSRAMInitTypeDef fsmc_sram_ini;
	FSMC_NORSRAMTimingInitTypeDef sram_Timing;
	GPIO_InitTypeDef GPIO_Init_fsmc;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|
						RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);

	GPIO_Init_fsmc.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|
						GPIO_Pin_5|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;	//10
	GPIO_Init_fsmc.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init_fsmc.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init_fsmc.GPIO_OType = GPIO_OType_PP;
	GPIO_Init_fsmc.GPIO_PuPd = GPIO_PuPd_NOPULL;

	GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_FSMC);		//A0
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_FSMC);		//A1
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_FSMC);		//A2
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_FSMC);		//A3
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_FSMC);		//A4
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_FSMC);		//A5
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_FSMC);	//A6
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_FSMC);	//A7
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_FSMC);	//A8
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_FSMC);	//A9

	GPIO_Init(GPIOF, &GPIO_Init_fsmc);

	GPIO_Init_fsmc.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_10;	//7
	GPIO_Init_fsmc.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init_fsmc.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init_fsmc.GPIO_OType = GPIO_OType_PP;
	GPIO_Init_fsmc.GPIO_PuPd = GPIO_PuPd_NOPULL;

	GPIO_PinAFConfig(GPIOG, GPIO_PinSource0, GPIO_AF_FSMC);		//A10
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource1, GPIO_AF_FSMC);		//A11
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource2, GPIO_AF_FSMC);		//A12
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource3, GPIO_AF_FSMC);		//A13
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource4, GPIO_AF_FSMC);		//A14
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource5, GPIO_AF_FSMC);		//A15
	GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_FSMC);	//NE3, CS3

	GPIO_Init(GPIOG, &GPIO_Init_fsmc);

	GPIO_Init_fsmc.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9|
						GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;	//13 GPIO_Pin_7
	GPIO_Init_fsmc.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init_fsmc.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init_fsmc.GPIO_OType = GPIO_OType_PP;
	GPIO_Init_fsmc.GPIO_PuPd = GPIO_PuPd_NOPULL;

	GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC);	//A16
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_FSMC);	//A17
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC);	//A18
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);	//D0
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);	//D1
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);		//D2
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);		//D3
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);		//D13
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);		//D14
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);	//D15
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);		//NOE, RD, OE
	GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);		//NWE, WR

	GPIO_Init(GPIOD, &GPIO_Init_fsmc);

	GPIO_Init_fsmc.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_7|GPIO_Pin_8|
						GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;	//12 GPIO_Pin_3|GPIO_Pin_4 A19, A20
	GPIO_Init_fsmc.GPIO_Mode = GPIO_Mode_AF;
	GPIO_Init_fsmc.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init_fsmc.GPIO_OType = GPIO_OType_PP;
	GPIO_Init_fsmc.GPIO_PuPd = GPIO_PuPd_NOPULL;

	GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_FSMC);		//NBL0
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_FSMC);		//NBL1
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC);		//D4
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC);		//D5
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC);		//D6
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC);	//D7
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC);	//D8
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC);	//D9
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC);	//D10
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC);	//D11
	GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC);	//D12

	GPIO_Init(GPIOE, &GPIO_Init_fsmc);

	RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

	sram_Timing.FSMC_AddressHoldTime = 15;	//
	sram_Timing.FSMC_AddressSetupTime = 15;	//
	sram_Timing.FSMC_BusTurnAroundDuration = 15;	//
	sram_Timing.FSMC_CLKDivision = 16;	//
	sram_Timing.FSMC_DataLatency = 17;	//
	sram_Timing.FSMC_DataSetupTime = 255;	//
	sram_Timing.FSMC_AccessMode = FSMC_AccessMode_A;	//

	fsmc_sram_ini.FSMC_Bank = FSMC_Bank1_NORSRAM3;	//
	fsmc_sram_ini.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;	//
	fsmc_sram_ini.FSMC_MemoryType = FSMC_MemoryType_SRAM;	//
	fsmc_sram_ini.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;	//
	fsmc_sram_ini.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;	//
	fsmc_sram_ini.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;	//
	fsmc_sram_ini.FSMC_WrapMode = FSMC_WrapMode_Disable;	//
	fsmc_sram_ini.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;	//
	fsmc_sram_ini.FSMC_WriteOperation = FSMC_WriteOperation_Enable;	//
	fsmc_sram_ini.FSMC_WaitSignal = FSMC_WaitSignal_Disable;	//
	fsmc_sram_ini.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;	//
	fsmc_sram_ini.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;	//
	fsmc_sram_ini.FSMC_WriteBurst = FSMC_WriteBurst_Disable;	//
	fsmc_sram_ini.FSMC_ReadWriteTimingStruct = &sram_Timing;	//
	fsmc_sram_ini.FSMC_WriteTimingStruct = &sram_Timing;	//

	FSMC_NORSRAMInit(&fsmc_sram_ini);
	FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}
//-----------------------

При  мах задержках тайминга (15, 255) вместо 3F иногда 1F

42 минуты назад, esaulenka сказал:

Было б неплохо узнать, что именно за дисплей.

Так мне тоже интересно. Какой там чип мне неизвестно. Откликнулся на инит ili9486, я и решил для себя, что чип 9486. Спасибо за подсказку, пойду искать различия между 9481 и 9486.

Посмотрел даташиты, оказывается еще есть 9488 и все 320х480. Теперь есть что смотреть, еще раз спасибо.

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

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


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

7 hours ago, mihlit1 said:

Так мне тоже интересно. Какой там чип мне неизвестно. Откликнулся на инит ili9486, я и решил для себя, что чип 9486. Спасибо за подсказку, пойду искать различия между 9481 и 9486.

Посмотрел даташиты, оказывается еще есть 9488 и все 320х480. Теперь есть что смотреть, еще раз спасибо.

Чтобы узнать тип чипа- прочитайте его ID. Например, в 9481 это команда "Device Code Read (BFh)". И пока не поймете что за контроллер, дальше не идите.

Ну и там куча регистров и перемычек может быть, но начинать нужно с типа контроллера.

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


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

21 hours ago, mihlit1 said:

void SRAM_Config(void)

Очень неохота перечитывать мануал на FSMC, а по памяти в этой портянке я ничего не скажу.

 

Параллельный интерфейс у 9481 и 9486 одинаковый, насколько я вижу в даташите.

Вы вот лучше скажите: CS на вашем дисплее есть? Он корректно дёргается?

Если оторвать RD от дисплея (раз уж всё равно проводами всё) память перестаёт портиться?

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


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

Приветствую!

 

Вопрос не совсем по теме ТС, но...

Теоретически (а лучше практически) возможно ли подцепить WG12864B по FSMC?

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

В целом, имеет ли смысл как-то завести сигналы экрана на выводы FSMC или нет?

Ногодрыгом, если что, в любом случае подыграю. Интересно все-таки по FSMC.

 

Гляжу, в режиме SRAM/NOR Flash особых ограничений нет, разве что по длительности CS. Но, вроде, эти времянки задаются в каких-то пределах.

Соединять думаю так

  LCD   <--->   MCU

D7...D0 <---- D7...D0
  CS1   <---- NBL0
  CS2   <---- NBL1
  RST   <---- пост. подтяжка к 1
  R/W   <---- пост. подтяжка к 0
  D/I   <---- A16
   E    <---- NWE

 

У него основная засада - два раздельных контроллера со своими CS.

Планирую подцепить их на линии выбора байтов при обращении к внешней памяти.

Ну, то есть пишем байт - пишется один контроллер, пишем полуслово - пишутся оба контролера параллельно.

Пишем в адрес с A16 равным 0 - пишутся команды, 1 - данные. E цепляю на NWE (разрешение записи).

 

Взлетит? Глянул на времянку записи в экран

Спойлер

write.GIF

 

и на работу FSMC

Спойлер

Картинки по запросу "fsmc stm32 lcd"

 

и все вроде норм. Кроме 1HCLK времени удержания NWE. Экран просит хотя бы 1мкс, но это можно задрать общий цикл доступа к памяти побольше и он растянется.

 

P.S. Доселе доводилось по FSMC только с памятью работать, с экранами нет.

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


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

19 часов назад, esaulenka сказал:

Вы вот лучше скажите: CS на вашем дисплее есть? Он корректно дёргается?

Если оторвать RD от дисплея (раз уж всё равно проводами всё) память перестаёт портиться?

Не то чтобы совсем на проводках - на макетке распаяны разъемы, а между ними МГТФ. Счас попробую. Вчера пол-дня искал ардуину проверить дисплей. Короче, дисплей определяется как "99". Знающие подсказали, что можно каким то образом затереть ID, получается какой-то левый от друзей китайцев получил. 16 битный строго определяется как 9341.

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


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

Отпаял RD - память перестала портиться. Вот он гад и попался. 

12 минут назад, mihlit1 сказал:

Вы вот лучше скажите: CS на вашем дисплее есть? Он корректно дёргается?

Я уже писАл ранее, что дисплей работает - экран заливается, палочки-кружочки разноцветные рисует, картинку с микроSD выводит. Получается, он не желает делить FSMC еще с кем-то. Тогда что - оторвать его от FSMC и устроить ему ногодрыг, либо тогда с другим дисплеем работать. Как то так.

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


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

Была история, правда с LPC29xx

Контроллер внешней пямяти настраивается с нужными таймингами, всё ОК. Паузы после CS выдерживаются... Но только в пределах доступа одного банка. Если после операции с одним банком тут же обратиться в другой, всё идёт вразнос, предыдущее устройство продолжает держать шину данных не в HI-Z. Приходилось ручками добавлять NOP в каком-то количестве

Возможно, здесь что-то похожее

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


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

3 hours ago, mihlit1 said:

Я уже писАл ранее, что дисплей работает

Это всё здорово, но палочки-кружочки могут рисоваться в т.ч. и при всегда активном CSX (во всяком случае, в описании 9341 есть такая сноска).

У вас там при записи в RAM никакие артефакты на дисплее не лезут?

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


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

Я смотрел ЛА - на каждый байт в дисплей  устанавливается CS, т.е. не пост-но он активный. 

29 минут назад, esaulenka сказал:

У вас там при записи в RAM никакие артефакты на дисплее не лезут?

 Запись в память по времени где то 1,5 мсек, есс-но ничего не видно, если пошагово - никаких артефактов.

1 час назад, toweroff сказал:

Приходилось ручками добавлять NOP в каком-то количестве

//передать данные
void Write_Dat(uint8_t dt)
{
	ADDR_DATA = dt;
	__ASM("nop");
	__ASM("nop");
}

Вы про эти? Это запись в дисплей. А для RAM счас вставлю, посмотрю, что получится.

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


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

2 minutes ago, mihlit1 said:

 Запись в память по времени где то 1,5 мсек, есс-но ничего не видно, если пошагово - никаких артефактов.

Нет, я к тому, что по какой-то причине у дисплея CS всегда активен, он не только будет выставлять данные по RD, как мы наблюдаем, но и сохранять (куда-то) данные, записываемые в ОЗУ.

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


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

Понял - запись ЛА по CS RAM и включить канал регистрации CS дисплея. Сейчас попробую.

Вспомнил, что у данного дисплея матрица тачскрина выведена на какие то ножки, а сейчас роюсь и не могу найти на какие. И кажется на управляющие ноги. Гугл тоже не помогает. Может у Вас инфа где то есть по 3,5 inch TFT LCD mcufriend.com

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


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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...