Writing to FSMC is extremely slow

armclcdstm32

I have an ARM Cortex M3 STMF32F103VE http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00191185.pdf, and I'm using an LCD with ILI9320 controller http://www.densitron.com/uploadedFiles/Displays/Support/ILI9320AN_V0.92.pdf

I'm using controlling the LCD using the FSMC, and I'm trying to write for example 240*100*16bit bytes and it takes about 0.1Seconds for that operation and the clock is 72Mhz.

for(i=0;i<240*100;i++)
    {
      *(__IO uint16_t *) (Bank1_LCD_D) = frameBuffer[i];
    }

The code for initializing the FSMC is copied and paste from the STMF32 application note for using an LCD TFT with FSMC:

#define Bank1_LCD_D    ((uint32_t)0x60020000)    //disp Data ADDR
#define Bank1_LCD_C    ((uint32_t)0x60000000)    //disp Reg ADDR

/**
  * @brief  Configures the FSMC and GPIOs to interface with the SRAM memory.
  *         This function must be called before any write/read operation
  *         on the SRAM.
  * @param  None 
  * @retval : None
  */
void FSMC_LCD_Init(void)
{
  FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  p;
  //GPIO_InitTypeDef GPIO_InitStructure; 



  p.FSMC_AddressSetupTime = 0x02;
  p.FSMC_AddressHoldTime = 0x00;
  p.FSMC_DataSetupTime = 0x05;
  p.FSMC_BusTurnAroundDuration = 0x00;
  p.FSMC_CLKDivision = 0x00;
  p.FSMC_DataLatency = 0x00;
  p.FSMC_AccessMode = FSMC_AccessMode_B;

  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;      





  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 

  /* Enable FSMC Bank1_SRAM Bank */
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);  
}

and in main init code:

just a call to SystemInit(); and RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

Best Answer

How are you transferring the data into the FSMC address space? Are you manually copying it from RAM? Constructing it on the fly and writing it to the address space?

To transfer it in the minimum possible time and without CPU intervention, I would:

  1. Reserve the 48kB of RAM necessary to store a complete LCD frame (a "frame buffer").
  2. Use DMA in a continuous loop to transfer the frame buffer into the FSMC address space.
  3. Manually update the contents of the frame buffer as needed; DMA/CPU contention will sort itself out.

The biggest problem with this approach is that you may not have 48kB of RAM spare, given that the STM32F1 has at most 64kB of RAM.