2015-10-12 01:30 AM
Hi,
I want to control a TFT (with a ILI9341) display via the 16 bit FSMC interface of a STM32F205VET6. Therefore I am using the emWin library v5.30 provided by Keil. I got the application working and all the display content is drawn properly on the TFT. But now I want to use the blinking cursor functionality of the EDIT widget and therefore the emWin library performs a multiple read operation (µC reads from display GRAM). Here I get into trouble. It seems like I have some timing problems. If the code writes data to the TFT I immediately read back the written data but the read data differs from the written data in approx. 30% of the write attempts. I already played around with the FSMC timings but without any changes. I calculated the timings according to AN2790 DATAST = 355ns and ADDSET = 67ns. Which makes DATAST = 22 and ADDSET = 4 @ fFSMC = 60MHz.Hope that anybody can help me.
Here is my initialization code.
void LCD_X_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct; FSMC_NORSRAMInitTypeDef hsram1; FSMC_NORSRAMTimingInitTypeDef Timing; /* GPIO Ports Clock Enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); /** FSMC GPIO Configuration PE7 ------> FSMC_D4 PE8 ------> FSMC_D5 PE9 ------> FSMC_D6 PE10 ------> FSMC_D7 PE11 ------> FSMC_D8 PE12 ------> FSMC_D9 PE13 ------> FSMC_D10 PE14 ------> FSMC_D11 PE15 ------> FSMC_D12 PD8 ------> FSMC_D13 PD9 ------> FSMC_D14 PD10 ------> FSMC_D15 PD11 ------> FSMC_A16 PD14 ------> FSMC_D0 PD15 ------> FSMC_D1 PD0 ------> FSMC_D2 PD1 ------> FSMC_D3 PD4 ------> FSMC_NOE PD5 ------> FSMC_NWE PD7 ------> FSMC_NE1 */ /* GPIOE configuration */ GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC); GPIO_InitStruct.GPIO_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.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOE, &GPIO_InitStruct); /* GPIOD configuration */ GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5| \ GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10| \ GPIO_Pin_11|GPIO_Pin_14|GPIO_Pin_15; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOD, &GPIO_InitStruct); /* Configuration of the reset pin */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz; GPIO_Init(GPIOD, &GPIO_InitStruct); GPIO_WriteBit(GPIOD, GPIO_Pin_13, Bit_RESET); /* Enable FSMC peripheral clock */ RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); /* SRAM1 memory initialization */ hsram1.FSMC_Bank = FSMC_Bank1_NORSRAM1; hsram1.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; hsram1.FSMC_MemoryType = FSMC_MemoryType_SRAM; hsram1.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; hsram1.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; hsram1.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; hsram1.FSMC_WrapMode = FSMC_WrapMode_Disable; hsram1.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; hsram1.FSMC_WriteOperation = FSMC_WriteOperation_Enable; hsram1.FSMC_WaitSignal = FSMC_WaitSignal_Disable; hsram1.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; hsram1.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; hsram1.FSMC_WriteBurst = FSMC_WriteBurst_Disable;/* @todo: Check timing */ Timing.FSMC_AddressSetupTime = 1; Timing.FSMC_AddressHoldTime = 4; Timing.FSMC_DataSetupTime = 22; Timing.FSMC_BusTurnAroundDuration = 0; Timing.FSMC_CLKDivision = 0; Timing.FSMC_DataLatency = 0; Timing.FSMC_AccessMode = FSMC_AccessMode_A; hsram1.FSMC_ReadWriteTimingStruct = &Timing; hsram1.FSMC_WriteTimingStruct = &Timing; FSMC_NORSRAMInit(&hsram1); /* Enable FSMC_Bank1_NORSRAM1 */ FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); /* Turn LCD Backlight On, release display from reset */ GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET); GPIO_WriteBit(GPIOD, GPIO_Pin_13, Bit_SET);}regards Thomas
2015-10-12 11:03 AM
I don't exactly know what's your problem, but you might want to read the FSMC_BTR.BUSTURN field's description in the RM.
JW2015-10-12 10:20 PM
Hi.
thank you for your response.My problem is that I am not able to reliably read data back from the ILI9341.So I guessed that maybe one of the forum users can provide a FSMC configuration which works with the ILI9341.regards Thomas2015-10-13 05:03 AM
According to the ILI9341 datasheet the trcfm cycle time for a memory read is 450ns, about 3x as long as a register read. The cycle time between reads is set by the trdh read pulse hi duration, 90ns. What do you have set for access time in the FSMC, and do you guarantee 90ns between reads?
Jack Peacock2015-10-13 05:59 AM
Hi Jack,
in the meantime I changed the FSMC configuration as follow:/* SRAM1 memory initialization */
hsram1.FSMC_Bank = FSMC_Bank1_NORSRAM1; hsram1.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; hsram1.FSMC_MemoryType = FSMC_MemoryType_SRAM; hsram1.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; hsram1.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; hsram1.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; hsram1.FSMC_WrapMode = FSMC_WrapMode_Disable; hsram1.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; hsram1.FSMC_WriteOperation = FSMC_WriteOperation_Enable; hsram1.FSMC_WaitSignal = FSMC_WaitSignal_Disable; hsram1.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; hsram1.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; hsram1.FSMC_WriteBurst = FSMC_WriteBurst_Disable;/* FSMC read timing */
ReadTiming.FSMC_AddressSetupTime = 4; ReadTiming.FSMC_AddressHoldTime = 0; ReadTiming.FSMC_DataSetupTime = 60; ReadTiming.FSMC_BusTurnAroundDuration = 12; ReadTiming.FSMC_CLKDivision = 0; ReadTiming.FSMC_DataLatency = 0; ReadTiming.FSMC_AccessMode = FSMC_AccessMode_A; hsram1.FSMC_ReadWriteTimingStruct = &ReadTiming; /* FSMC write timing */ WriteTiming.FSMC_AddressSetupTime = 2; WriteTiming.FSMC_AddressHoldTime = 0; WriteTiming.FSMC_DataSetupTime = 5; WriteTiming.FSMC_BusTurnAroundDuration = 2; WriteTiming.FSMC_CLKDivision = 0; WriteTiming.FSMC_DataLatency = 0; WriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; hsram1.FSMC_WriteTimingStruct = &WriteTiming;Now I am able to read from the ILI9341. I also realized that I must perform two read operations if I want to get a valid register value. Therefore a dummy read is necessary. Writing to and reading from the ILI9341 via the FSMC works great now. regards Thomas