lpcware

LPC1788 emWin Crash in GUI_Init()

Discussion created by lpcware Employee on Jun 15, 2016
Content originally posted in LPCWare by rmoss on Thu Jan 31 07:36:07 MST 2013
I have an external Static RAM chip connected to the LPC1788 and when I move the GUI RAM from GUIConf.c to external static RAM, emWin crashes in GUI_Init().  Here is my linker file and GUIConf / LCDConf settings.  The same behavior occurs whether I use Muliple Buffering or single buffering.

Linker icf
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0007FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x10000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x1000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__   = 0x200;
/**** End of ICF editor section. ###ICF###*/

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define symbol _AHB_RAM_start__  = 0x20080000;
define symbol _AHB_RAM_end__    = 0x200BFFFF;
define region AHB_RAM_region = mem:[from _AHB_RAM_start__ to _AHB_RAM_end__];

define symbol _EXT_RAM_start__  = 0x90000000;
define symbol _EXT_RAM_end__    = 0x903FFFFF;

define region EXT_RAM_region = mem:[from _EXT_RAM_start__ to _EXT_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy with packing = zeros { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { section .intvec };
place at address mem:0x2FC { section CRPKEY };
place in ROM_region     { readonly };
place in RAM_region     { readwrite,
                          block CSTACK, block HEAP };
place in EXT_RAM_region { section VRAM, section GUI_RAM };


GUIConf.c
//
// Define the available number of bytes available for the GUI
//
#define GUI_NUMBYTES  (1024 * 1024) * 32  // x MByte

//
// Define the average block size
//
#define GUI_BLOCKSIZE 0x80

//
// 32 bit aligned memory area
//
#ifdef __ICCARM__
  #pragma location="GUI_RAM"
  static __no_init U32 _aMemory[GUI_NUMBYTES / 4];
#endif
#ifdef __CC_ARM
  U32 static _aMemory[GUI_NUMBYTES / 4] __attribute__ ((section ("GUI_RAM"), zero_init));
#endif
#ifdef __GNUC__
  U32 static _aMemory[GUI_NUMBYTES / 4] __attribute__ ((section(".GUI_RAM"))) = { 0 };
#endif
#ifdef _WINDOWS
  static U32 _aMemory[GUI_NUMBYTES / 4];
#endif

/*********************************************************************
*
*       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_SetAvBlockSize(GUI_BLOCKSIZE);
}

LCDConf.c
/*********************************************************************
*                SEGGER Microcontroller GmbH & Co. KG                *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2012  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V5.16 - 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 Energy Micro AS whose registered office
is situated at  Sandakerveien 118, N-0484 Oslo, NORWAY solely
for  the  purposes  of  creating  libraries  for Energy Micros ARM Cortex-M3, M4F
processor-based  devices,  sublicensed  and distributed  under the terms and
conditions  of  the   End  User  License Agreement supplied by Energy Micro AS.
Full source code is available at: www.segger.com

We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : LCDConf.c
Purpose     : Display controller configuration (single layer)
---------------------------END-OF-HEADER------------------------------
*/

#include "GUI.h"
#include <string.h>
#include "GUIDRV_Lin.h"
#include "LPC177x_8x.h"
#include "system_LPC177x_8x.h"
#include "HWConf.h"

#include "bsp.h"
#include "lcdconf.h"

/*********************************************************************
*
*       Layer configuration (to be modified)
*
**********************************************************************
*/
//
// Physical display size
//
#define XSIZE_PHYS 320
#define YSIZE_PHYS 240
#define FRAME_BUFFER_SIZE (XSIZE_PHYS * YSIZE_PHYS * 2)
#define BITSPERPIXEL    2
//
// Color conversion
//
#define COLOR_CONVERSION GUICC_565

//
// Display driver
//
#define DISPLAY_DRIVER GUIDRV_LIN_16

#ifndef   USE_MULTIBUF
  #define USE_MULTIBUF  1
#endif
//
// Buffers / VScreens
//
#define NUM_BUFFERS  2 // Number of multiple buffers to be used


//
//  VSYNC Interrupt Register Mask
//
#define VCompIC_MASK (1<<3)

/*********************************************************************
*
*       Configuration checking
*
**********************************************************************
*/
#pragma data_alignment=8  // 8 byte align frame buffer
#pragma location="VRAM"
static __no_init U32 _aVRAM[FB_XSIZE * FB_YSIZE / (4 / PIXEL_WIDTH)];

#define VRAM_ADDR  (U32)&_aVRAM[0]

#ifndef   VRAM_ADDR
  #define VRAM_ADDR 0x90000000
#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   COLOR_CONVERSION
  #error Color conversion not defined!
#endif
#ifndef   DISPLAY_DRIVER
  #error No display driver defined!
#endif

static void _SetVRAMAddr(void * pVRAM);
static void _SetOrg(int xPos, int yPos) ;

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

uint32_t VRAM_pointer = 0;
static int orgx, orgy;
volatile int pendingFrameIndex = -1;
LCD_X_SHOWBUFFER_INFO * pBufferData;



/*********************************************************************
*
*       _InitController
*
* Purpose:
*   Should initialize the display controller
*/
static void _InitController(void) {
  orgx = orgy = 0;
  _SetVRAMAddr((void *)(VRAM_ADDR));
  _SetOrg(orgx, orgy);
  LPC_LCD->UPBASE = (uint32_t)VRAM_ADDR;
}

/*********************************************************************
*
*       _SetVRAMAddr
*
* Purpose:
*   Should set the frame buffer base address
*/
static void _SetVRAMAddr(void * pVRAM)
{
    LPC_LCD->UPBASE = (uint32_t)pVRAM;
}

/*********************************************************************
*
*       _SetOrg
*
* Purpose:
*   Should set the origin of the display typically by modifying the
*   frame buffer base address register
*/
static void _SetOrg(int xPos, int yPos) {
    orgx = xPos;
    orgy = yPos;
    //LPC_LCD->UPBASE = (uint32_t)(VRAM_ADDR);
    LPC_LCD->UPBASE = (uint32_t)(VRAM_ADDR + (y * YSIZE_PHYS * PIXEL_WIDTH));  // Needs to be set, before LCDC is enabled   
}


/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/* Initialize LCD in Direct mode and touch panel */
void LCD_InitializeLCD(void)
{
  _SetVRAMAddr((void *)(VRAM_ADDR));
  _SetOrg(orgx, orgy); 
}

/*********************************************************************
*
*       LCD_InitializeDriver
*
* Purpose:
*   Set Vram address and org
*
*/
void LCD_InitializeDriver(void)
{
  _SetVRAMAddr((void *)(VRAM_ADDR));
  _SetOrg(orgx, orgy);
}

/*********************************************************************
*
*       LCD_IRQHandler
*
* Purpose:
*   VSYNC Interrupt Service Routine
*
*/
void LCD_IRQHandler(void)
{
  uint32_t flags;
  uint32_t Addr, BufferSize;
  flags = LPC_LCD->INTSTAT;
  LPC_LCD->INTCLR |= VCompIC_MASK;
  if ( flags & VCompIC_MASK )
  {
    if(pendingFrameIndex >= 0)
    {
      //
      // Calculate address of the given buffer
      //
      BufferSize = (XSIZE_PHYS * YSIZE_PHYS * BITSPERPIXEL);
      Addr = VRAM_ADDR + BufferSize * pBufferData->Index;
      //
      // Make the given buffer visible
      //
      LPC_LCD->UPBASE = Addr;
      //
      // Send a confirmation that the buffer is visible now
      //
      GUI_MULTIBUF_Confirm(pendingFrameIndex);
      pendingFrameIndex = -1;
    }
  }
}

/*********************************************************************
*
*       EnableVsyncInterrupt
*
* Purpose:
*   Setup VSYNC Interrupt
*
*/
void EnableVsyncInterrupt(void)
{
  /* Clear interrupts */
  LPC_LCD->INTCLR |= VCompIC_MASK;

  /* Enable VSYNC interrupt */
  LPC_LCD->INTMSK = VCompIC_MASK;

  /* Enable EBI interrupts in core */
  NVIC_ClearPendingIRQ(LCD_IRQn);
  NVIC_EnableIRQ(LCD_IRQn); 
}

/*********************************************************************
*
*       LCD_X_Config
*
* Purpose:
*   Called during the initialization process in order to set up the
*   display driver configuration.
*
*/
void LCD_X_Config(void) {
#if MULTIBUFF
  GUI_MULTIBUF_Config(NUM_BUFFERS);
#endif
  //
  // Set display driver and color conversion for 1st layer
  //
  GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);
  //
  // Display driver configuration, required for Lin-driver
  //
  if (LCD_GetSwapXY()) {
    LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);
    //LCD_SetVSizeEx(0, YSIZE_PHYS, XSIZE_PHYS);
  } else {
    LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
    //LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);
  }
  LCD_SetVRAMAddrEx(0, (void *)VRAM_ADDR);
}

/*********************************************************************
*
*       LCD_X_DisplayDriver
*
* Purpose:
*   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 r;

  (void)LayerIndex;                   /* Unused parameter */

  switch (Cmd) {
  //
  // Required
  //
  case LCD_X_INITCONTROLLER: {
    //
    // Called during the initialization process in order to set up the
    // display controller and put it into operation. If the display
    // controller is not initialized by any external routine this needs
    // to be adapted by the customer...
    //
    _InitController();
    EnableVsyncInterrupt();
    return 0;
  }
  case LCD_X_SETVRAMADDR: {
    //
    // Required for setting the address of the video RAM for drivers
    // with memory mapped video RAM which is passed in the 'pVRAM' element of p
    //
    LCD_X_SETVRAMADDR_INFO * p;
    p = (LCD_X_SETVRAMADDR_INFO *)pData;
    _SetVRAMAddr(p->pVRAM);
    return 0;
  }
  case LCD_X_SETORG: {
    //
    // Required for setting the display origin which is passed in the 'xPos' and 'yPos' element of p
    //
    LCD_X_SETORG_INFO * p;
    p = (LCD_X_SETORG_INFO *)pData;
    _SetOrg(p->xPos, p->yPos);
    return 0;
  }

  case LCD_X_ON: {
    //
    // Required if the display controller should support switching on and off
    //
    return 0;
  }
  case LCD_X_OFF: {
    //
    // Required if the display controller should support switching on and off
    //
    // ...
    return 0;
  }
  case LCD_X_SHOWBUFFER:
    {
      pBufferData = (LCD_X_SHOWBUFFER_INFO *)pData;
      //
      // Remember buffer index to be used by ISR
      //
      pendingFrameIndex = pBufferData->Index;
    }
    break;

  default:
    r = -1;
  }
  return r;
}

/*************************** End of file ****************************/

Thanks,
RMoss

Outcomes