[ST_MICRO]/STM32H72018. 12. 1. 04:54

STM32H7 FMC - TFT LCD 출력하기 (STM32F7 FMC와 다른점)

STM32H7 FMC - TFT LCD 출력하기 (STM32F7 FMC와 다른점)




STM32H7 EVM 보드에는 FMC를 이용하여 기존에 제작 해 두었던 TFT LCD 모듈을 연결할 수 있도록 구성하였다. STM32H7에서 FMC로 TFC LCD 테스트를 진행 해 볼 수 있다.







STM32H7 의 FMC는  Data(16), WR, RD, CS, A16 핀을 할당 할 수 있다.

메모리 맵핑은 기존 STM32 시리즈와 동일하게 0x6000 0000 에 가능하다.






STM32CubeMX에서 FMC 설정을 LCD Interface 타입으로 설정하여 코드 생성 한다.








STM32H7 FMC 기본 동작 테스트

FMC 제어를 위해 STM32CubeMx의 HAL 라이브러리가 제공된다.


uint8_t BSP_SRAM_WriteData(uint32_t uwStartAddress, uint16_t *pData, uint32_t uwDataSize)
{
  if(HAL_SRAM_Write_16b(&hsram1, (uint32_t *)uwStartAddress, pData, uwDataSize) != HAL_OK)
  {
    return SRAM_ERROR;
  }
  else
  {
    return SRAM_OK;
  }

}



스코프 확인식 신호가 정상 적으로 출력 되는것을 확이 할 수 있다.


  MX_FMC_Init();

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
         data ^= 0x55;
         addr ^= 1;
         if(addr)
         {
                //BSP_SRAM_WriteData(LCD_BANK_ADDR, &data, 1);
                _LCD_DATA(0) ^= data ;
         }
         else
         {
                //BSP_SRAM_WriteData(LCD_BANK_ADDR+(1<<16), &data, 1);
                _LCD_DATA((1<<16)) ^= data ;
         }
      
        GPIOD->ODR ^= GPIO_PIN_13;
        HAL_Delay(100);

  }





이제 실제 TFT LCD모듈을 연결하여 테스트 해 보자





TFT LCD가 정상 동작을 하지 않는다.


스코프 확인 해 보니 Address, Data Write 구간에 CS핀이 4번 정도 High가 되는 현상이 있다.





너무 고속이라 그런가?

STM32H7에서 FMC에서 달라진 점은 속도 이다. 최대 180Mhz 까지 가능하다.





열심히 구글링 결과  STM32H7 vs STM32F7 GPIO 속도 테스트2 와 같이 STM32H7의 버스 메트릭스 구조가 달라져서 그1사이클에 4번의 전환이 발생 한다고 한다. H7으로 코드 전환이 쉽지가 않네...


Memory Type을 바꾸어 보니 그런 현상이 없어 졌다.

 hsram1.Init.MemoryType = FMC_MEMORY_TYPE_NOR;




/* FMC initialization function */
static void MX_FMC_Init(void)
{
  /* USER CODE BEGIN FMC_Init 0 */
  /* USER CODE END FMC_Init 0 */
  FMC_NORSRAM_TimingTypeDef Timing = {0};
  /* USER CODE BEGIN FMC_Init 1 */
  /* USER CODE END FMC_Init 1 */
  /** Perform the SRAM1 memory initialization sequence
  */
  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.MemoryType = FMC_MEMORY_TYPE_NOR;
  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.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;
  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 30;
  Timing.AddressHoldTime = 30;
  Timing.DataSetupTime = 25;
  Timing.BusTurnAroundDuration =50;
  Timing.CLKDivision = 0;
  Timing.DataLatency = 0;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */
  if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  {
    Error_Handler( );
  }
  /* USER CODE BEGIN FMC_Init 2 */
  /* USER CODE END FMC_Init 2 */

}





SD카드 연결하고 BMP 이미지 출력하니 TFT LCD에 BMP이미지가 정상적으로 출력된다.

















Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32F72018. 5. 15. 04:34

STM32F7 EVM FMC 테스트 - TFT LCD 제어 (STM32F7 에서 FMC출력 문제발생)

STM32F7 EVM FMC 테스트 - TFT LCD 제어 (STM32F7 에서 FMC출력 문제발생)




STM32F7 EVM 보드는 100핀 페키지의 STM32F767이 실장되어 있다. 100핀 페키지에서는 FMC Data/Address 16, RD, WR, NE 을 사용할 수 있어 버스 방식의 LCD 제어에 적합하다.

기존에 제작한 LCD 모듈중 버스제어 방식의 LCD모듈을 표준 핀맵으로 제작해 두었기 때문에 이 모듈로 STM32F7의 FMC를 이용한 TFT LCD를 테스트 해 보았다.




STM32F7 EVM보드의 TFT LCD는 CS -> NE1, RS->A16에 연결에 되어 있다.









STM32F7 FMC 테스트 코드 작성

STM32CubeMX 에서 FMC를 아래와 같이 핀맵에 맞게 설정 하면 된다.





STM32CubeMX에서 코드 생성을 하면 아래와 같이 기본 초기화 코드가 생성된다.



static void MX_FMC_Init(void)
{
  /* USER CODE BEGIN FMC_Init 0 */
  /* USER CODE END FMC_Init 0 */
  FMC_NORSRAM_TimingTypeDef Timing = {0};
  /* USER CODE BEGIN FMC_Init 1 */
  /* USER CODE END FMC_Init 1 */
  /** Perform the SRAM1 memory initialization sequence
  */
  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.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;
  hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
  hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
  /* Timing */
  Timing.AddressSetupTime = 25;
  Timing.AddressHoldTime = 15;
  Timing.DataSetupTime = 50;//50;//255;
  Timing.BusTurnAroundDuration = 1;//2;//15;
  Timing.CLKDivision = 2;
  Timing.DataLatency = 2;
  Timing.AccessMode = FMC_ACCESS_MODE_A;
  /* ExtTiming */
  if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
  {
    Error_Handler( );
  }
  /* USER CODE BEGIN FMC_Init 2 */
  /* USER CODE END FMC_Init 2 */
}





기존 STM32F439 FMC테스트 예제와 동일한 코드를 구동 시켰는데...

동작을 하지 않는다.


뭔가 이상하다. STM32F7에서 뭐가 달라졌나?



일단 LCD기본 테스트 코드로 파형이 정상적으로 출력이 되는지 확인 해 보자


CMD출력 할때 RS(A16)가 low가 되는것을 확인 할 수 있다.


       while(1)
       {
              Lcd_Cmd(0x0200);Lcd_Data(0x0000);        //Horizontal Address Set
              Lcd_Cmd(0x0201);Lcd_Data(0x0000);        //Vertical Address Set
              Delay(delay_time);
       }



하지만 4번의 출력이 있어야 하는 WR신호가 2번 밖에 출력되지 않는다.




타이밍 이슈 인가? 하지만 타이밍을 짧게 해도 2번 밖에 출력이 되지 않는다.






FMC 출력 할 때 딜레이를 좀 주면 어떻게 될까?


#define _LCD_TIME_DELAY                                60
#define Lcd_Cmd(reg)                    _LCD_DATA(0x0000) = reg;Delay_ns(_LCD_TIME_DELAY);

#define Lcd_Data(dat)                   _LCD_DATA(0x10000) = dat;Delay_ns(_LCD_TIME_DELAY);



정상 동작은 하지만 속도가 STM32F4에 비해 4배 이상 느리다.

딜레이 타임을 줄이면 정상 동작을 하지 않는다.







STM32F7 FMC HAL 코드를 사용해 보면 어떨까?


void Lcd_Cmd(unsigned int reg)

{
       uint16_t buf = reg;
       HAL_SRAM_Write_16b(&hsram1, (uint32_t*)(LCD_BANK_ADDR+0), &buf, 1);
}

void Lcd_Data(unsigned int reg)
{
       uint16_t buf = reg;
       HAL_SRAM_Write_16b(&hsram1, (uint32_t*)(LCD_BANK_ADDR+0x20000), &buf, 1);

}




하지만 HAL코드를 이용하면 동작은 하지만 속도가 너무 느리다.

타이밍을 짧게 해도 1프래임 출력 시간이 44ms나 소요된다.



결론적으로 보면 출력 후 바로 출력 하는것에는 문제가 있는것 같다.

무시 해 버리는듯..


속도는 느리지만 SD카드의 BMP출력하면 STM32F7에서 TFT-LCD에 이미지 출력은 되고 있다. 

하지만 속도 문제는 해결해야 할것 같다.









Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32F42015. 6. 29. 14:14

[STM32F4_ZE_NET] FSMC 테스트 - TFT LCD 출력 테스트


[STM32F4_ZE_NET] FSMC 테스트 - TFT LCD 출력 테스트





STM32F4의 FSMC를 이용하면 TFT-LCD를 버스 방식으로 제어 가능하다.


STM32F4의 FSMC는 4개의 64MB로 할당 가능하다.






STM32F405 FSMC 블록도





STM32F405 FSMC 테스트 초기화 코드


초기화 코드

#define LCD_BANK_ADDR                   ((uint32_t)0x6C000000)
#define _LCD_CMD_OUT(Data)              (*(uint16_t *) (LCD_BANK_ADDR) = Data)
#define _LCD_DAT_OUT(Data)              (*(uint16_t *) (LCD_BANK_ADDR) = Data)
#define _LCD_DATA(p)                    (*(volatile uint16_t*) (LCD_BANK_ADDR + (p<<1)))

#define Lcd_Cmd(reg)                    _LCD_DATA(0x0000) = reg;

#define Lcd_Data(dat)                   _LCD_DATA(0x0002) = dat;




테스트 코로 테스트 해 보면 CMD출력 할때 RS(A1)가 low가 되는것을 확인 할 수 있다.

       while(1)
       {
              Lcd_Cmd(0x0200);Lcd_Data(0x0000);
              Lcd_Cmd(0x0201);Lcd_Data(0x0000);
              Delay(delay_time);
       }







/CS와 /WR 신호를 확인 해 보면 4개의 /CS,/RS가 출력 되는것을 확인 할 수 있다.

타이밍을 최적화 해 보면 300ns 내에 4개의 명령이 수행 되는것을 확인 할 수 있다.

  /* Timing */
  Timing.AddressSetupTime = 4;
  Timing.AddressHoldTime = 4;
  Timing.DataSetupTime = 8;
  Timing.BusTurnAroundDuration = 6;
  Timing.CLKDivision = 2;
  Timing.DataLatency = 2;




LCD에 이미지 한장 출력하는데 7.5ms 정도 소요된다.






TFT-LCD에 BMP 파일 출력 해보면 정상 적으로 잘 출력 되는것을 확인 할 수 있다.








Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32F43x2015. 3. 8. 21:30

STM32F439 EVM - FMC SRAM 방식의 FTF LCD 제어 테스트

STM32F439 EVM - FMC SRAM 방식의 FTF LCD 제어 테스트








STM32F4는 FSMC(Flexible static memory controller)를 지원하는데 STMF439에서는 SDRAM을 지원하기 위해 FMC (Flexible memory controller )로 변경되었다. 

기존 프로그램에서 FMC를 이용하여 메모리 방식으로 LCD제어 하기 위해서는 코드 수정이 필요하다.



STM32F439 FMC 블록도

NOR,SRAM, SDRAM 을 지원한다.

- NOR/PSRAM memory controller

- NAND/PC Card memory controller

- Synchronous DRAM (SDRAM/Mobile LPSDR SDRAM) controller










[STM32F439 EV] 보드에서는 메모리 방식의 TFT-LCD는 CN26을 통해 연결되어 있고 PG9->FMC_NE2/FMC_NCE3 에 CS를 할당하였다.


FMC 어드레스 할당 핀맵

(BANK1)CS1 -> PD7    : ((uint32_t)0x60000000) 

(BANK2)CS2 -> PG9    : ((uint32_t)0x64000000) 

(BANK3)CS3 -> PG10   : ((uint32_t)0x68000000)

(BANK4)CS4 -> PG12   : ((uint32_t)0x6C000000)








STM32F439 TFT LCD FMC초기화 코드


void InitFMC_TftLcd(void)

{

  GPIO_InitTypeDef GPIO_Init_Structure;

 

  dio_fmc.Instance  = FMC_NORSRAM_DEVICE;

  dio_fmc.Extended  = FMC_NORSRAM_EXTENDED_DEVICE;

  

 

  SRAM_Timing.AddressSetupTime       = 5;

  SRAM_Timing.AddressHoldTime        = 5;

  SRAM_Timing.DataSetupTime          = 5;

  SRAM_Timing.BusTurnAroundDuration  = 2;

  SRAM_Timing.CLKDivision            = 2;

  SRAM_Timing.DataLatency            = 2; 

 

  SRAM_Timing.AccessMode             = FMC_ACCESS_MODE_A;

  

//뱅크 선택 FMC_NORSRAM_BANK1~FMC_NORSRAM_BANK4

  dio_fmc.Init.NSBank             = FMC_NORSRAM_BANK2;

  dio_fmc.Init.DataAddressMux     = FMC_DATA_ADDRESS_MUX_DISABLE;//FMC_DATA_ADDRESS_MUX_ENABLE

  dio_fmc.Init.MemoryType         = FMC_MEMORY_TYPE_SRAM;

  dio_fmc.Init.MemoryDataWidth    = SRAM_MEMORY_WIDTH;

  dio_fmc.Init.BurstAccessMode    = FMC_BURST_ACCESS_MODE_DISABLE;

  dio_fmc.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;

  dio_fmc.Init.WrapMode           = FMC_WRAP_MODE_DISABLE;

  dio_fmc.Init.WaitSignalActive   = FMC_WAIT_TIMING_BEFORE_WS;

  dio_fmc.Init.WriteOperation     = FMC_WRITE_OPERATION_ENABLE;

  dio_fmc.Init.WaitSignal         = FMC_WAIT_SIGNAL_DISABLE;

  dio_fmc.Init.ExtendedMode       = FMC_EXTENDED_MODE_DISABLE;

  dio_fmc.Init.AsynchronousWait   = FMC_ASYNCHRONOUS_WAIT_DISABLE;

  dio_fmc.Init.WriteBurst         = FMC_WRITE_BURST_DISABLE;

  dio_fmc.Init.ContinuousClock    = SRAM_CONTINUOUS_CLOCK;

  

  /* Initialize the SRAM controller */

  if(HAL_SRAM_Init(&dio_fmc, &SRAM_Timing, &SRAM_Timing) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler(); 

  }

      

}




이미지 한장 출력하는데 10m가 소요되고 있다. (STM32F405 에서는 7ms 정도 소요 된다.)

왜 STM32F439가 더 느리지? STM32F4에서 TFT-LCD 테스트와 동일한 클럭 속도 인데...



가장 기본 적인 LCD출력으로 파형을 관찰 해 볼까?


       while(1)
       {
              Lcd_Cmd(0x0200);Lcd_Data(0x0000);        //Horizontal Address Set
              Lcd_Cmd(0x0201);Lcd_Data(0x0000);        //Vertical Address Set
              Delay(delay_time);

       }



300ns 보다 약간 시간이 더 걸린다.
특이한점은 CS한번에 WR신호가 4번 출력 된다.







STM32F439 FMC 이용 LCD출력 테스트 결과

Posted by nexp

댓글을 달아 주세요

[FreeScale]/KINETIS2013. 11. 10. 23:30

K20 EVM - Kinetis Cortex-M4 TFT LCD 테스트

K20 EVM - Kinetis Cortex-M4 TFT LCD 테스트



Cortex-M4 코어를 가진 K20 EVM보를 이용하여 TFT-LCD 출력 테스트를 했다.

50Mhz에서 400x320 픽셀의 TFT LCD에 1프레임 출력하는데 18ms정도 소요된다.



[NET-EVB SM] 확장 테스트 보드를 이용하여 SD Card의 BMP이미지를 출력하도록 했다.









K20 EVM TFT LCD 출력 테스트 동영상




K20 TFT LCD 드라이버 소스코드정리
//-----------------------------------------------------------------------------
#define _SPI0_IO_INIT() PORTD_PCR0 = PORT_PCR_MUX(0x2);\
PORTD_PCR1 = PORT_PCR_MUX(0x2);\
PORTD_PCR2 = PORT_PCR_MUX(0x2);\
PORTD_PCR3 = PORT_PCR_MUX(0x2);
                                        
                                        
                                        

#define TFT_DRV_HD66791                 0
#define TFT_DRV_COM44                   1

#define LCD_LAT_BIT BIT16
#define LCD_LAT_PORT GPIOB
#define LCD_LAT_ON() sbi(LCD_LAT_PORT, LCD_LAT_BIT) 
#define LCD_LAT_OFF() cbi(LCD_LAT_PORT, LCD_LAT_BIT) 
#define LCD_DATA_LATCH() LCD_LAT_ON();LCD_LAT_OFF();

#define LCD_EN_BIT BIT17
#define LCD_EN_PORT GPIOB
#define LCD_ENABLE() cbi(LCD_EN_PORT, LCD_EN_BIT) 
#define LCD_DISABLE() sbi(LCD_EN_PORT, LCD_EN_BIT) 

#define LCD_RST_BIT //BIT8
#define LCD_RST_PORT //PORTB
#define LCD_RST_ON() //Sbi(LCD_RST_PORT, LCD_RST_BIT) 
#define LCD_RST_OFF() //Cbi(LCD_RST_PORT, LCD_RST_BIT) 

#define LCD_RS_BIT BIT0
#define LCD_RS_PORT GPIOA
#define LCD_RS_OFF() cbi(LCD_RS_PORT, LCD_RS_BIT) 
#define LCD_RS_ON() sbi(LCD_RS_PORT, LCD_RS_BIT)

#define LCD_WR_BIT BIT3
#define LCD_WR_PORT GPIOA
#define LCD_WR_OFF() cbi(LCD_WR_PORT, LCD_WR_BIT) 
#define LCD_WR_ON() sbi(LCD_WR_PORT, LCD_WR_BIT)

#define LCD_RD_BIT ///BIT9
#define LCD_RD_PORT //PORTB
#define LCD_RD_OFF() //Cbi(LCD_RD_PORT, LCD_RD_BIT) 
#define LCD_RD_ON() //Sbi(LCD_RD_PORT, LCD_RD_BIT)

#define LCD_BL_BIT BIT3
#define LCD_BL_PORT GPIOC
#define LCD_BL_OFF() cbi(LCD_BL_PORT, LCD_BL_BIT) 
#define LCD_BL_ON() sbi(LCD_BL_PORT, LCD_BL_BIT)

#define _LCD_DAT_OUT(Data) PORTD = (Data>>8);\
                                    LCD_DATA_LATCH();\
                                    PORTD = (Data&0xFF);

#define TFTGpioInit() SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;\
                                        SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;\
                                        SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;\
                                        SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;\
                                        PORTA_PCR0 = PORT_PCR_MUX(1);\
                                        PORTA_PCR3 = PORT_PCR_MUX(1);\
PORTB_PCR16 = PORT_PCR_MUX(1);\
                                        PORTB_PCR17 = PORT_PCR_MUX(1);\
                                        PORTC_PCR3 = PORT_PCR_MUX(1);\
                                        PORTD_PCR0 = PORT_PCR_MUX(1);\
                                        PORTD_PCR1 = PORT_PCR_MUX(1);\
                                        PORTD_PCR2 = PORT_PCR_MUX(1);\
                                        PORTD_PCR3 = PORT_PCR_MUX(1);\
                                        PORTD_PCR4 = PORT_PCR_MUX(1);\
                                        PORTD_PCR5 = PORT_PCR_MUX(1);\
                                        PORTD_PCR6 = PORT_PCR_MUX(1);\
                                        PORTD_PCR7 = PORT_PCR_MUX(1);\
                                        Sbi(GPIOA_PDDR, (BIT0|BIT3));\
                                        Sbi(GPIOB_PDDR, (BIT16|BIT17));\
                                        Sbi(GPIOD_PDDR, 0xFF);



Posted by nexp

댓글을 달아 주세요