Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F429 - FMC с дисплеем и SDRAM
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
VHEMaster
Доброго времени суток! На STM32F429 пытаюсь запустить LCD дисплей на ILI9325 через FMC вместе с SDRAM - IS42S16400-7TL на 64 Мбита.
Данные с внутреннего буфера контроллера пересылаются в дисплей через DMA, и одновременно с этим происходят операции с SDRAM. Проблема в том, если в этот момент происходит запись в SDRAM, то на дисплее появляются артефакты, и при чтении данных с SDRAM получаются совсем не те данные, которые были записаны. Если отключить дисплей программно, то всё работает отлично. Никаких ошибок нет. Вообще, моя цель такова. Переместить видеобуфер в SDRAM, и оттуда перебрасывать данные в дисплей с помощью DMA. Возможно ли это оформить без артефактов?

Код инициализации дисплея:
CODE

GPIO_InitTypeDef GPIO_InitStruct;
__GPIOE_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
__FMC_CLK_ENABLE();

GPIO_InitStruct.Pin = 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;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);


GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


FMC_NORSRAM_TimingTypeDef Timing;

hsram1.Instance = FMC_NORSRAM_DEVICE;
hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/* hsram1.Init */
hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WrapMode = FMC_WRAP_MODE_DISABLE;
hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
/* Timing */
Timing.AddressSetupTime = 10;
Timing.DataSetupTime = 20;
Timing.AddressHoldTime = 0;
Timing.BusTurnAroundDuration = 0;
Timing.CLKDivision = 0;
Timing.DataLatency = 0;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/* ExtTiming */

HAL_SRAM_Init(&hsram1, &Timing, NULL);


HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET);
DelayMs(1);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET);
DelayMs(10);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET);
DelayMs(50);

//************* Start Initial Sequence **********//
graph_command(0x00E3, 0x3008); // Set internal timing
graph_command(0x00E7, 0x0012); // Set internal timing
graph_command(0x00EF, 0x1231); // Set internal timing
graph_command(0x0001, 0x0100); // set SS and SM bit
graph_command(0x0002, 0x0700); // set 1 line inversion
//graph_command(0x0003, 0x1030); // ВЕР ОРИЕН, >
graph_command(0x0003, 0x1018); // ГОР ОРИЕН, >
graph_command(0x0004, 0x0000); // Resize register
graph_command(0x0008, 0x0207); // set the back porch and front porch
graph_command(0x0009, 0x0000); // set non-display area refresh cycle ISC[3:0]
graph_command(0x000A, 0x0000); // FMARK function
graph_command(0x000C, 0x0000); // RGB interface setting
graph_command(0x000D, 0x0000); // Frame marker Position
graph_command(0x000F, 0x0000); // RGB interface polarity
//*************Power On sequence ****************//
graph_command(0x0010, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB
graph_command(0x0011, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0]
graph_command(0x0012, 0x0000); // VREG1OUT voltage
graph_command(0x0013, 0x0000); // VDV[4:0] for VCOM amplitude
DelayMs(200); // Dis-charge capacitor power voltage
graph_command(0x0010, 0x1490); // SAP, BT[3:0], AP, DSTB, SLP, STB
graph_command(0x0011, 0x0227); // DC1[2:0], DC0[2:0], VC[2:0]
DelayMs(50); // Delay 50ms
graph_command(0x0012, 0x001C); // Internal reference voltage= Vci;
DelayMs(50); // Delay 50ms
graph_command(0x0013, 0x1A00); // Set VDV[4:0] for VCOM amplitude
graph_command(0x0029, 0x0025); // Set VCM[5:0] for VCOMH
graph_command(0x002B, 0x000E); // Set Frame Rate
DelayMs(50); // Delay 50ms
graph_command(0x0020, 0x0000); // GRAM horizontal Address
graph_command(0x0021, 0x0000); // GRAM Vertical Address
// ----------- Adjust the Gamma Curve ----------//
graph_command(0x0030, 0x0000);
graph_command(0x0031, 0x0506);
graph_command(0x0032, 0x0104);
graph_command(0x0035, 0x0207);
graph_command(0x0036, 0x000F);
graph_command(0x0037, 0x0306);
graph_command(0x0038, 0x0102);
graph_command(0x0039, 0x0707);
graph_command(0x003C, 0x0702);
graph_command(0x003D, 0x1604);
//------------------ Set GRAM area ---------------//
graph_command(0x0050, 0x0000); // Horizontal GRAM Start Address
graph_command(0x0051, 0x00EF); // Horizontal GRAM End Address
graph_command(0x0052, 0x0000); // Vertical GRAM Start Address
graph_command(0x0053, 0x013F); // Vertical GRAM Start Address
graph_command(0x0060, 0xA700); // Gate Scan Line
graph_command(0x0061, 0x0001); // NDL,VLE, REV
graph_command(0x006A, 0x0000); // set scrolling line
//-------------- Partial Display Control ---------//
graph_command(0x0080, 0x0000);
graph_command(0x0081, 0x0000);
graph_command(0x0082, 0x0000);
graph_command(0x0083, 0x0000);
graph_command(0x0084, 0x0000);
graph_command(0x0085, 0x0000);
//-------------- Panel Control -------------------//
graph_command(0x0090, 0x0010);
graph_command(0x0092, 0x0600);

graph_command(0x0007, 0x0133); // 262K color and display ON


DelayMs(50); // Delay 50ms
graph_command(32, 0);
graph_command(33, 0);
graph_command(34, 0);

//for (i = 0; i < 153280; i++)
// graph_data(0);

uint32_t i,j;


for(i=0;i<Y_SIZE;i++)
for(j=0;j<X_SIZE;j++)
LCD_GRAM[i][j] = 0;

LCD_DAT = (volatile uint16_t*)LCD_GRAM;


__DMA2_CLK_ENABLE();
hdma_memtomem_dma2_stream0.Instance = DMA2_Stream0;
hdma_memtomem_dma2_stream0.Init.Channel = DMA_CHANNEL_0;
hdma_memtomem_dma2_stream0.Init.Direction = DMA_MEMORY_TO_MEMORY;
hdma_memtomem_dma2_stream0.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_memtomem_dma2_stream0.Init.MemInc = DMA_MINC_DISABLE;
hdma_memtomem_dma2_stream0.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_memtomem_dma2_stream0.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_memtomem_dma2_stream0.Init.Mode = DMA_NORMAL;
hdma_memtomem_dma2_stream0.Init.Priority = DMA_PRIORITY_LOW;
hdma_memtomem_dma2_stream0.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_memtomem_dma2_stream0.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_memtomem_dma2_stream0.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_memtomem_dma2_stream0.Init.PeriphBurst = DMA_MBURST_SINGLE;
HAL_DMA_Init(&hdma_memtomem_dma2_stream0);

HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

dma_pool = 1;
ILI_TIME = Delay_Tick;
tp_step = 0;
HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)LCD_DAT+640, 0x60020000, 38080);



Код инициализации SDRAM
CODE

GPIO_InitTypeDef GPIO_InitStruct;


GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12
|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5
|GPIO_PIN_8|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

GPIO_InitStruct.Pin = 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|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

__FMC_CLK_ENABLE();


FMC_SDRAM_TimingTypeDef SdramTiming;
FMC_SDRAM_CommandTypeDef SdramCommand;

/** Perform the SDRAM1 memory initialization sequence
*/
hsdram1.Instance = FMC_SDRAM_DEVICE;
/* hsdram1.Init */
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_3;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_2;
/* SdramTiming */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 7;
SdramTiming.SelfRefreshTime = 4;
SdramTiming.RowCycleDelay = 7;
SdramTiming.WriteRecoveryTime = 2;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;

HAL_SDRAM_Init(&hsdram1, &SdramTiming);


SdramCommand.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
SdramCommand.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
SdramCommand.AutoRefreshNumber = 1;
SdramCommand.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &SdramCommand,1000);

SdramCommand.CommandMode = FMC_SDRAM_CMD_PALL;
SdramCommand.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
SdramCommand.AutoRefreshNumber = 1;
SdramCommand.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &SdramCommand,1000);

SdramCommand.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
SdramCommand.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
SdramCommand.AutoRefreshNumber = 8;
SdramCommand.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &SdramCommand,1000);

SdramCommand.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
SdramCommand.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
SdramCommand.AutoRefreshNumber = 1;
SdramCommand.ModeRegisterDefinition = (uint32_t)0x0230;
HAL_SDRAM_SendCommand(&hsdram1, &SdramCommand,1000);

SDRAM_8 = (volatile uint8_t *)((uint32_t)0xC0000000);
SDRAM_16 = (volatile uint16_t *)((uint32_t)0xC0000000);
SDRAM_32 = (volatile uint32_t *)((uint32_t)0xC0000000);


Обработчик прерывания DMA дисплея:
CODE

HAL_DMA_IRQHandler(&hdma_memtomem_dma2_stream0);
hdma_memtomem_dma2_stream0_state = HAL_DMA_GetState(&hdma_memtomem_dma2_stream0);
if(hdma_memtomem_dma2_stream0_state == HAL_DMA_STATE_READY_MEM0)
{
if(dma_pool == 0)
{
graph_fps = Delay_Tick-ILI_TIME;
ILI_TIME = Delay_Tick;

if(tp_step == 4) { TP_Get(); tp_step = 0; }
else tp_step++;

graph_command(32, 0);
graph_command(33, 0);
*(volatile uint16_t *)((uint32_t)0x60000000) = 34;
HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)LCD_DAT+638, 0x60020000, 38081);
dma_pool = 1;

}
else if(dma_pool == 1)
{
//HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)LCD_DAT+76800, 0x60020000, 38400);
HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)LCD_DAT, 0x60020000, 38400);
dma_pool = 2;
}
else if(dma_pool == 2)
{
HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)LCD_DAT, 0x60020000, 319);
dma_pool = 0;
}
}
scifi
Еррату на этот МК читали? Там много фееричного про SDRAM написано.
VHEMaster
Цитата(scifi @ Dec 14 2015, 09:13) *
Еррату на этот МК читали? Там много фееричного про SDRAM написано.


Там нашëл следующее:
Цитата
2.9.7 FMC dynamic and static bank switching Description The dynamic and static banks cannot be accessed concurrently. Workaround Do not use dynamic and static banks at the same time. The SDRAM device must be in selfrefresh before switching to the static memory mapped on the NOR/PSRAM or NAND/PCCard controller. Before switching from static memory to SDRAM, issue a Normal command to wake-up the device from self-refresh mode. This limitation is fixed in silicon revision “3”.

Если не ошибаюсь, у меня ревизия Y. Т.е. возле логотипа ST написана буква Y. Это означает, что я не смогу использовать SDRAM и дисплей одновременно?(
scifi
Цитата(VHEMaster @ Dec 14 2015, 22:06) *
Это означает, что я не смогу использовать SDRAM и дисплей одновременно?(

Почему же? Можно построить программу так, чтобы обойти это ограничение. Некий программный арбитр доступа к внешней шине.
VHEMaster
Цитата(scifi @ Dec 14 2015, 22:05) *
Почему же? Можно построить программу так, чтобы обойти это ограничение. Некий программный арбитр доступа к внешней шине.

Я хочу подбрасывать данные с SDRAM в дисплей через DMA... Или предлагаете сначала переписать некоторую часть видеобуфера в ОЗУ МК, затем из него в дисплей и так далее? А если нужно ещё дополнительно поюзать SDRAM, хотя-бы для того чтобы заполнить видеобуфер?...
scifi
Цитата(VHEMaster @ Dec 14 2015, 23:36) *
Или предлагаете сначала переписать некоторую часть видеобуфера в ОЗУ МК, затем из него в дисплей и так далее?

Получается так.

Цитата(VHEMaster @ Dec 14 2015, 23:36) *
А если нужно ещё дополнительно поюзать SDRAM, хотя-бы для того чтобы заполнить видеобуфер?...

Разделять по времени дисплей и SDRAM. Арбитр, как и сказано выше.
Геморрой, да. А что делать, кому сейчас легко? laughing.gif
Rash
или заменить контролер на ревизию Z судя по эррате или STM32F469 поставить, сам не пользовался, но думаю должны исправить в новых контроллерах.
VHEMaster
Короче, так и не получилось нифига адекватно разделить по времени эти два девайса.. В конечном итоге решил взять VGA монитор bb-offtopic.gif
SpyBot
А почему вы выбрали вариант подключения дисплея через FMC?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.