AnsweredAssumed Answered

Problem getting STemWin to work with RA8875-Based LCD...

Question asked by Zaher on Oct 11, 2015
Latest reply on Oct 11, 2015 by Zaher
Hello Everybody! 

It's been more than 4 months since I got my hands on the STemWin. I spent quite a considerable time on getting familiar with the API itself, as you know, emWin has a huge API and a steep learning curve. Finally, I got where I want with STemWin with my STM32F429-Disco Board. I have read most of Segger's notes and their manual for configuration and driver support, and because my LCD Driver is already supported, or supposed to be, out of the box by the GUIDRV_FlexColor, I thought I wouldn't face any trouble porting STemWin to my new 7" RA8875-based LCD. Unfortunately, this soon proved to be the opposite. 

First of all, my LCD is connected to the STM32F429ZIT by FMC. The driver implemented works flawlessly and I can write and draw any shape directly on the LCD. Here's my FMC configuration, in case something is not configured appropriately for STemWin:

void FMC_LCD_Init(void)
{
  FMC_NORSRAMInitTypeDef  FMC_NORSRAMInitStructure;
  FMC_NORSRAMTimingInitTypeDef  p;
 
  //GPIO_InitTypeDef GPIO_InitStructure;
   
  /* Enable the FMC Clock */
  //RCC_AHB3PeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
  //RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE); /* Enabled Earlier in GPIO_Configuration()  */
 
  p.FMC_AddressSetupTime = 2;
  p.FMC_AddressHoldTime = 2;
  p.FMC_DataSetupTime = 4;
  p.FMC_BusTurnAroundDuration = 1;
  p.FMC_CLKDivision = 0x00;
  p.FMC_DataLatency = 0x00;
  p.FMC_AccessMode = FMC_AccessMode_A;
 
  FMC_NORSRAMInitStructure.FMC_Bank = FMC_Bank1_NORSRAM1;
  FMC_NORSRAMInitStructure.FMC_DataAddressMux = FMC_DataAddressMux_Disable;
  FMC_NORSRAMInitStructure.FMC_MemoryType = FMC_MemoryType_SRAM;
  FMC_NORSRAMInitStructure.FMC_AsynchronousWait = FMC_AsynchronousWait_Disable;
  FMC_NORSRAMInitStructure.FMC_MemoryDataWidth = FMC_NORSRAM_MemoryDataWidth_16b;
  FMC_NORSRAMInitStructure.FMC_BurstAccessMode = FMC_BurstAccessMode_Disable;
  FMC_NORSRAMInitStructure.FMC_WaitSignalPolarity = FMC_WaitSignalPolarity_Low;
  FMC_NORSRAMInitStructure.FMC_WrapMode = FMC_WrapMode_Disable;
  FMC_NORSRAMInitStructure.FMC_WaitSignalActive = FMC_WaitSignalActive_BeforeWaitState;
  FMC_NORSRAMInitStructure.FMC_WriteOperation = FMC_WriteOperation_Enable;
  FMC_NORSRAMInitStructure.FMC_WaitSignal = FMC_WaitSignal_Disable;
  FMC_NORSRAMInitStructure.FMC_ExtendedMode = FMC_ExtendedMode_Disable;
  FMC_NORSRAMInitStructure.FMC_WriteBurst = FMC_WriteBurst_Disable;
  FMC_NORSRAMInitStructure.FMC_ReadWriteTimingStruct = &p;
  FMC_NORSRAMInitStructure.FMC_WriteTimingStruct = &p;
 
  
 
  
 
  FMC_NORSRAMInit(&FMC_NORSRAMInitStructure);
 
  /* Enable FSMC Bank1_SRAM Bank */
  FMC_NORSRAMCmd(FMC_Bank1_NORSRAM1, ENABLE);
 
}


And here is the contents of my GUIConf.h file:

#include "GUI.h"
/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
//
// Define the available number of bytes available for the GUI
//
#define GUI_NUMBYTES  160000 // x KByte
//
// Define the average block size
//
//#define GUI_BLOCKSIZE 0x80
/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
// 32 bit aligned memory area
//U32 _aMemory[GUI_NUMBYTES / 4] __attribute__((aligned (4)));
//U32 HeapMem[1024 * 1024] __attribute__((section(".HeapMemSection")));
U32 HeapMem[GUI_NUMBYTES /4] __attribute__((section(".HeapMemSection")));
//U32 extMem[GUI_NUMBYTES / 4] __attribute__((at(0xD0000000)));
/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       GUI_X_Config
*
* Purpose:
*   Called during the initialization process in order to set up the
*   available memory for the GUI.
*/
 
void GUI_X_Config(void) {
 
  // Assign memory to emWin
  //GUI_ALLOC_AssignMemory(_aMemory, GUI_NUMBYTES);
  GUI_ALLOC_AssignMemory(HeapMem, GUI_NUMBYTES);
  //GUI_ALLOC_AssignMemory(extMem, GUI_NUMBYTES);
  //GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
 
}

And here is the contents of the most important file, LCDConf.c:

/*********************************************************************
*          Portions COPYRIGHT 2013 STMicroelectronics                *
*          Portions SEGGER Microcontroller GmbH & Co. KG             *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2013  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************
 
** emWin V5.20 - Graphical user interface for embedded applications **
All  Intellectual Property rights  in the Software belongs to  SEGGER.
emWin is protected by  international copyright laws.  Knowledge of the
source code may not be used to write a similar product.  This file may
only be used in accordance with the following terms:
 
The  software has  been licensed  to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: www.segger.com
 
We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : LCDConf.c
Purpose     : Display controller configuration
 
---------------------------END-OF-HEADER------------------------------
*/
 
/**
  ******************************************************************************
  * @file    LCDConf.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    22-July-2013
  * @brief   Template driver, should be used as starting point for new display drivers
  ******************************************************************************
  * @attention
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */
 
 
#include "stm32f4xx.h"
#include "GUI.h"
#include "GUIDRV_FlexColor.h"
//#include "GUIDRV_Template.h"
#include "RA8875_subroutine.h"
#include "LCDConf.h"
#include "lcd.h"
#include "Global.h"
 
//
// Physical display size
//
#define XSIZE_PHYS  800
#define YSIZE_PHYS  480
//#define VXSIZE_PHYS         800
//#define VYSIZE_PHYS         480
//
// Color conversion
//
#define COLOR_CONVERSION GUICC_565
//
// Display driver
//
#define DISPLAY_DRIVER GUIDRV_FLEXCOLOR
//
// Buffers / VScreens
//
//#define NUM_BUFFERS   1
//#define NUM_VSCREENS  1
//#define LCD_LAYER0_FRAME_BUFFER  ((uint32_t)0xD0200000)
//#define LCD_LAYER1_FRAME_BUFFER  ((uint32_t)0xD0400000)
#ifndef   VXSIZE_PHYS
  #define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef   VYSIZE_PHYS
  #define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef   LCD_XSIZE
  #define LCD_XSIZE XSIZE_PHYS
#endif
#ifndef   LCD_YSIZE
  #define LCD_YSIZE YSIZE_PHYS
#endif
 
#ifndef   XSIZE_PHYS
  #error Physical X size of display is not defined!
#endif
#ifndef   YSIZE_PHYS
  #error Physical Y size of display is not defined!
#endif
#ifndef   DISPLAY_DRIVER
  #error No display driver defined!
#endif
#ifndef   DISPLAY_ORIENTATION
  #define DISPLAY_ORIENTATION 0
#endif
 
/*********************************************************************
*       Defines for Macros used in LCD Control
**********************************************************************/
#define  LCD_BASE_Addr               ((U32)(0x60000000|0x00000000))
#define  LCD_BASE_Data               ((U32)(0x60000000|0x00100000))
#define  LCD_CMD                     (*(U16 *)(LCD_BASE_Addr))
#define  LCD_Data                    (*(U16 *)(LCD_BASE_Data))
 
/********************************************************************
*
*       LcdWriteReg
*
* Function description:
*   Sets display register
*/
static void LcdWriteReg(U16 Data)
{
    LCD_CMD = Data;
}
/********************************************************************
*
*       LcdWriteData
*
* Function description:
*   Writes a value to a display register
*/
static void LcdWriteData(U16 Data)
{
    LCD_Read_Write_RAM_Prepare();
    LCD_Data = Data;
}
/********************************************************************
*
*       LcdWriteDataMultiple
*
* Function description:
*   Writes multiple values to a display register.
*/
static void LcdWriteDataMultiple(U16 * pData, int NumItems)
{
    LCD_Read_Write_RAM_Prepare();
    while (NumItems--)
    {
        LCD_Data = *pData++;
    }
}
/********************************************************************
*
*       LcdReadDataMultiple
*
* Function description:
*   Reads multiple values from a display register.
*/
static void LcdReadDataMultiple(U16 * pData, int NumItems)
{
    LCD_Read_Write_RAM_Prepare();
    while (NumItems--)
    {
        *pData++ = LCD_Data;
    }
}
 
 
/*********************************************************************
*
*       LCD_X_Config
*
* Function description:
*   Called during the initialization process in order to set up the
*   display driver configuration.
*
*/
void LCD_X_Config(void) {
  GUI_DEVICE * pDevice;
  CONFIG_FLEXCOLOR Config = {0};
  GUI_PORT_API PortAPI = {0};
  //
  // Set display driver and color conversion
  //
  pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);
  //
  // Display driver configuration, required for Lin-driver
  //
  LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
  LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
  //
  // Orientation
  //
  //Config.Orientation = GUI_MIRROR_X;
  Config.NumDummyReads = 1;
  //Config.RegEntryMode = 0x6830; // **************** TRY TO MODIFY HERE!
  GUIDRV_FlexColor_Config(pDevice, &Config);
  //
  // Set controller and operation mode
  //
  PortAPI.pfWrite16_A0  = LcdWriteReg;
  PortAPI.pfWrite16_A1  = LcdWriteData;
  PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;
  PortAPI.pfReadM16_A1  = LcdReadDataMultiple;
  GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66708, GUIDRV_FLEXCOLOR_M16C0B16);
}
 
/*********************************************************************
*
*       LCD_X_DisplayDriver
*
* Function description:
*   This function is called by the display driver for several purposes.
*   To support the according task the routine needs to be adapted to
*   the display controller. Please note that the commands marked with
*   'optional' are not cogently required and should only be adapted if
*   the display controller supports these features.
*
* Parameter:
*   LayerIndex - Index of layer to be configured
*   Cmd        - Please refer to the details in the switch statement below
*   pData      - Pointer to a LCD_X_DATA structure
*
* Return Value:
*   < -1 - Error
*     -1 - Command not handled
*      0 - Ok
*/
int LCD_X_DisplayDriver ( unsigned LayerIndex, unsigned Cmd, void *pData )
{
  int retCode = 0;
  GUI_USE_PARA(LayerIndex);
  GUI_USE_PARA(pData);
 
  switch (Cmd)
  {
      case LCD_X_INITCONTROLLER: {
          // Initialize The Display Driver RA8875 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
          //RA8875_Init();
          return 0;
      }
 
      default:
        retCode = -1;
  } // switch
 
  return retCode;
} //  LCD_X_DisplayDriver
/*************************** End of file ****************************/

I have disabled the initialize of LCD in LCD_X_DisplayDriver, as the LCD is already initialized in the main function before branching to GUI_Init(). 

While the driver that is supposed to talk with RA8875 is GUIDRV_FLEXCOLOR_F66721, I had to select GUIDRV_FLEXCOLOR_F66708 because when the former is being selected, the program goes into an infinite loop after calling GUI_Init() and GUI_Init is never called/executed. I will send bt output from debugger later if that helps.

CRC Clock is already enabled in main function, and right after GPIO, FMC, and RA8875_Init functions. 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);

From my previous experience with STemWin with the default demo shipped with the STM32F429-FW package, the LCD goes black after calling GUI_Init() from within the program, which, as far as I know, indicates a working setup. Now, the same applies when I call GUI_Init() and the screen goes black immediately, however, as I follow it with any write command (e.g., GUI_DispString() ), all I got is a small strip of color appears on top of the LCD. 

It's the fifth week for me now, and I just can't figure it out what's wrong with my setup. Unfortunately, Segger is very allergic to any sort of question when it comes to the pre-built emWin that they licensed for ST. Just like if they are implicitly regretting that agreement with ST. So, Mr. Clive, and anyone who could help over here, please do not direct me to Segger because simple it won't work! 

Thank you in advance! 

Zaher

Outcomes